Closed robinwersich closed 4 years ago
The problem with the bot using a reply independent answer endpoint is that the server can not handle invalid replies or loop messages anymore. Currently the server has logic to decide what to do with a current reply. Changing the endpoint to be independent of the reply would pose the need of making [...]/answers
stateful, which is a terrible solution.
However, this seems to be a mistake in the bot as well.
The bot should have a /start
-command handler, that differs from the behavior of the normal text handler by not calling a reply dependent endpoint. It should instead just try to register the user and get answers in return.
I think this is part of a bigger problem on the server side actually. Does the server set a new story point when ansers?reply=reply
is sent?
There should be separate endpoints like
user/<id>/story/replies
user/<id>/story/answers
user/<id>/story/proceed?reply=reply
which are used to access/debug/edit the story only and are not access by the bot!
There should be endpoints for the bot to react to /start
and all other text.
This could look like this (I think we should keep telegram
out of the endpoints to emphasize that we could use any bot enabled chat program)
users/registerBot?handle=<handle>&token=<token>
user/<id>/bot/answers?reply=<reply>
user/<id>/bot/replyOptions
This way the server exposes an interface to the bot (4 to 6) that does not necessarily influence the story progression. That would be handled by the logic behind those endpoints on the server side. This logic then could call actual story endpoints (1 to 3) that cause the user state to change.
I numbered the endpoints to easier talk about them.
This is actually close to what I meant (more elaborated of course)
I mostly agree with what you said :)
However, I'm not sure what you mean with .../answers
would be stateful. If any, it's less stateful (it's equivalent to 2. with the difference that I would let the bot access it)
So: I like the interface you proposed, and would like to make the addition, that reply
is optional in 5., so that if it's omitted the story is not progressed. This could be used when handeling the /start
command, because there is no (real) user reply (this would mean the story state starts with the start_point
instead of null
which makes more sense imo anyway - the "user not yet registered"-state is still modelles by the telegram handle being null
)
btw, answers
and replies
are synonyms and should not be used to differentiate between bot and user ^^
botMessages
and userReplies
would be more appropriate
also, REST suggests not using camelCase but hyphens (thus bot-messages
)
we might consider doing so
Lets do that
A write up of the discussion above
/users/<id>/story
endpointThere should be endpoints regarding the story independent of the bots interface. Needed endpoints would include:
users/<id>/story/user-replies
- Returns strings the user can currently choose fromusers/<id>/story/description
- Returns the current storypoint descriptionusers/<id>/story/proceed?reply=<reply>
- Proceeds the user in the story dependent on <reply>
/users/<id>/bot
endpointThe bot should access the users via the userID
and not via a second primary key (the handle
).
/start
the bot should call /users/register?bot_handle=<telegram_handle>&firstname=<firstname>&token=<start_token>
and then ask users/<id>/bot/initial-message
to receive the first contact message to react to the /start
command/users/<id>/bot/bot-answers?reply=<reply>
to receive text to answer and /users/<id>/bot/user-replies
to receive the next options for the user to choose from.telegram_handle
:user_id
association, because telegram_handle
wont be implemented as secondary key anymore. Therefore he needs to lookup unkown user_id
s by using /users?bot_handle=<telegram_handle
and parse the user_id
out of the answer./user/byTelegramHandle
/users/<id>/bot/initial-message
, which returns the personalized message of the initial storypoint/user/replyOptionsForUser
becomes /users/<id>/bot/user-replies
/user/answersForUserAndReply?telegramUser=<telegram_handle>&reply=<reply>
becomes /users/<id>/bot/bot-answers?reply=<reply>
Furthermore the endpoint /users?bot_handle=<telegram_handle>
is needed to be implemented for this. See #33
description
is not a fitting name in my opinion. Also we should merge /story
and /bot
and have an endpoint for the bot that takes a reply and returns bot messages and user replies. I propose the following:
users/<id>/story/bot-messages
- the current messages from the botusers/<id>/story/user-replies
- the currently valid user repliesusers/<id>/story/proceed?reply=<reply>
continue to the next story point (empty return)users/<id>/story/next-messages-and-replies?reply=<reply>
proceed the story and return the new bot messages and user replies/users?bot_handle=<telegram_handle>
should be renamed. Bot handle sounds like the bots handle, so I would only call it handle
/start
as the only path.Despite this post beeing German and therefore completly unreadable, I still agree with its main points.
I dont think that the start command should be coded into story.json
as we then would have a static beginning that would always include a unnecessary start point, whose only purpose is to house the /start
reply and the next story point.
Instead we could leave story.josn
as is and code the artificial "start command storypoint" into the storycontroller.py
, so the user does not see engine specific things in the story file.
This would be really easy todo, as we just need to add said storypoint into the loaded dictionary and add a path {start, initialStorypoint}, where initialStorypoint is just the start point from story.json
Is users/<id>/story/next-messages-and-replies?reply=<reply>
even needed?
The bot could just call users/<id>/story/proceed?reply=<reply>
, which could contain the logic for proceeding based on the reply.
A debug interface to proceed is not good, as it would actually break the bot
I though that YOU discouraged the idea and I saw reasons for that (the already mentioned race conditions). But we could drop the proceed endpoint
Nope. At least I hope. I was against a bot-answer endpoint independent of reply used by the bot.
You can try if there are problems with the race conditions. But I still think there might be
Could you go more into detail about those race conditions? Where did you describe them?
If the bot sends proceed
, and shortly after bot-messages
, the server might not have processed the old requests and send the old messages. However, we could probably fix this with a delay
This can not happen, as neither the bot nor the server works async in the context of a single user.
The bot waits for the response to proceed
and the server does not trigger async function in order to respond to proceed
Therefore bot-messages
can not be the old messages.
(If there would be multiple bot instances this would be a problem. But this is not the case)
oh, of course - then let's drop the endpoint in question :)
After another discussion, we decided, that we should replace bot-messages
(which also provided error messages on incompleted taskswith
/current-story-point/description(which does only provide the description but not error messages). In return, the
proceed` endpoint should return the new bot messages
resolved by #46
Problem
After the
/start
command the bot asks the server for new answers. The users answer (/start <token>
is then checked for validity, but doesn't appear in any answer options and is thus neglected.Suggestion
with the new route, the bot could ask for the current answers for a given user, without needing to provide a reply. This could be used after the user sends the
start
command