A Russian developer and a student at Innopolis University.
Coming soon! one day.
A Telegram helpline chat-bot. Enables pairs of people to have anonymous conversations
License: MIT License
Currently, the whole sent_invitations
table is locked during the whole process of sending out a group of invitations (either all invitations to a client or all invitations for an operator). For example,
helpline_telegraph/helpline_telegraph/core/invitations.py
Lines 118 to 121 in d791607
We could introduce "pending invitations": invitations that have already been inserted into the database (for example, with invitation_message_id
set to NULL
) but haven't yet been actually sent. In this case, threads can first INSERT
the invitations they are about to send, without explicit locking at all (PostgreSQL will automatically create row-level locks on the inserted rows, and the inserting transaction will acquire them, not lock the whole table), and after all the rows are inserted, the thread, which has made the insertions, actually sends out the invitations, updates the row and commits the transaction. Thus, other threads, trying to insert an invitation, which is being sent by another thread, will be paused just as they are now (because of the row-level locks) and will then fail to duplicate the invitation if the first transaction commits successfully. But unlike the current behavior, with the pending invitations the table doesn't get locked completely, that's why if there are invitations being sent for non-intersecting sets of users, transactions won't block each other
The database schema is invalid because PostgreSQL does not support CHECK
constraints that reference data that is not in the row being inserted or updated (docs). The current scheme does have these invalid CHECK
s, but it seems like we actually only need them when creating a new conversation (i. e. INSERT
ing into conversations
), so, I guess, we could ensure the data being inserted is valid in the INSERT
query
A bool is_operator
field should be in the users
table instead of a field type
of the enum
type. It will simplify the schema by removing a user-defined type and allow operators to interact with the bot as if they were clients
The current version of the bot has the following issue. All the invitation messages' ids are stored in the runtime variables instead of the database. That's why whenever the bot is restarted (for example, because of an update or because of an unhandled internal error) the invitation messages become undeletable. They aren't invalidated and operators still can join the conversations, but because the bot doesn't have the messages' ids, it is unable to delete them, so all the operators are likely to try to join the conversation.
I see two ways of solving this problem: either trying to handle the moment when the bot stops and removing the invitations at that moment (with warnings sent to users that something goes wrong and they'll have to request a conversation again), or moving the information about the invitation messages to the database. The second way, of course, provides a better user experience, however, it may be hard to implement, so the first solution can be used as a hotfix/workaround
I don't like the bot creates a new connection to the database each time it needs something from there. I guess, we should use a connection pool instead. Should search for tips from psycopg developers or look how others do this
The ideal way is to copy all the entities from the original message to the copied one. It will be easy to implement this with the Telegram Bots API 5.0 (with the copyMessage
method), however, currently, there is no telebot
release, supporting this API version.
For now, users should at least warned, that their formatting is lost and messages are forwarded as a plain text
The piece of code
https://github.com/kolayne/anonymous_helpline_chatbot/blob/a2c20f78738bc1dff082d506a74714a7c60872b4/main.py#L44-L46
must be under the with conversation_starter_lock
block:
https://github.com/kolayne/anonymous_helpline_chatbot/blob/a2c20f78738bc1dff082d506a74714a7c60872b4/main.py#L54-L72
because otherwise, the set of free operators could change between these code fragments, so the bot will send invitations to busy operators
If a conversation has finished, don't allow users to keep sending messages to each other
Forgot to implement this part!
Exceptions should be raised instead to indicate errors instead of using error code integers
Move everything containing SQL queries to the core
package
The simplest solution I've found is to insert new rows such that interlocutor1_chat_id
is always less than interlocutor2_chat_id
. This way we always know, what the order of the arguments in a query should be.
It's the second option from https://stackoverflow.com/a/15144061/11248508
When a client reports feeling himself worse after a conversation with an operator, administrators receive the corresponding notification with the operator mentioned. The client number should be mentioned there too (however, administrators must not be able to determine who the client actually is)
Admins should have an interface for adding new operators
Indicate if the user I am chatting to is typing / has read my messages. Built-in Telegram typing event should be used to notify about typing
Add support for various kinds of messages, at least photos and videos, probably also voice messages and stickers
When a user (either a client or an operator) edits a message, the reflected message should be updated too. Same for messages deletions (probably with a reservation that when a client deletes a message, it doesn't disappear for the operator, but is marked as deleted somehow)
Give operators ability to use the /end_conversation
command
Add a readme, telling about usage and authors, add some comments to the scheme, explaining the unobvious meanings of tables/fields there
Do not select operators randomly. Perhaps decide which operators to choose based on:
There is now a handler for an invalid callback (which will be triggered if the given callback data can't be json-decoded to a dictionary containing the 'type'
key). However, I would also like to have the callbacks with present but unknown types to be handled. This should be a simple handler after all the others which should just tell the callback had an incorrect type
I like the solution provided here
The invitations messages system doesn't currently work well when there are multiple clients and multiple operators in different states. For example, the following situations:
Report about start/end of conversation with operator designation to admin. Maybe should include rating of session (how?)
Rate may be:
An operator shouldn't be able to talk with two users at the same time
There are now many places for potential race conditions and deadlocks. It'd be nice to have tests for that part of the back-end
SQL tables shouldn't be locked in the SHARE
mode if they are to be modified, they are to be locked in the SHARE ROW EXCLUSIVE
mode instead
Use the telegram id as a primary identifier and use local id only when anonymity is required (when telling operators "User #N says the following"). Because all (or almost all) the requests sent to the database are using the telegram id, so an additional SELECT
from the users
table happens all the time
It should be possible to distinguish between a message from bot and a message from a user you're in a conversation with
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.