Get Unique ID for Receipient / Current Chat in Telegram Bot Inline Query? - telegram

I am working on a Telegram Bot in Python that should work inline and the answer to an inline query with different results, depending on what chat you are in.
But at the moment, i can only get my own ID. I need to somehow get either a Chat-ID or a receipient User-ID, or Groupchat-ID for Groups.
I have already tried checking out the data that comes with the inline-query, but besides Identifiers for my own User, it doesn't seem to have any information to create a unique identifier for the current chat.
I also tried interacting with the bot from both sides to see if that would change anything, but same result from both sides, all the info in the query can only identify the sender but not the recipient or chat-ID
Is there a way to get this info from a inline request? ´
Or any ideas for a workaround?
For context, I want to create a To-Do-List on a per-Chat basis, so for example my brother and I see the same To-Do-List when we are in our Chat. Same with groups.
Thanks in Advance

Is there a way to get this info from a inline request?
No. You have already answered that question here:
I have already tried checking out the data that comes with the inline-query, but besides Identifiers for my own User, it doesn't seem to have any information to create a unique identifier for the current chat.
The InlineQuery not containing information about the chat that the query is made in also makes sense, because the bot doesn't even need to be a member of that chat.

Related

How to get a list of all the telegram groups I have joined?

I want to get the list of telegram groups(name) which I am a part of. Like a text file or something else. How can I do that?
I had the same question here, so I started searching and found no proper answer. Then I came over this question and since it had no answers, it triggered me to search more and write an answer.
According to what Telegram document says here and here:
messages.getAllChats
Get all chats, channels and supergroup
apparently getAllChats gives you all ChatIds. You can pass chatIds to another API to get chat name and more info.
Also, if you want to get the list of chats you administrate, use the following API:
channels.getAdminedPublicChannels
Get channels/supergroups/geogroups we're admin in. Usually called when
the user exceeds the limit for owned public
channels/supergroups/geogroups, and the user is given the choice to
remove one of his channels/supergroups/geogroups.
I just don't like (or maybe understand) the way they documented their APIs. I wish it was something more familiar, more HTTP-like.
Another way - use web-version of the telegram and parse HTML. Here are steps:
create folder with only groups;
go to web-version, open this folder;
run code copy($$(".dialog-title .peer-title").map(function(e){return e.textContent})) in console, it will copy title of groups on screen into clipboard;
if you have a lot groups on several screens, list groups below and make previous step again;
join all the groups into one big list;
profit!

Reading list with Dialoglfow fulfillment from Real-Time Database

I am creating a chatbot using Dialogflow and Dialogflow's Inline Editor (for Cloud functions and Firebase database "Real-Time Database"). I will integrate this chatbot with Google Assistant.
I have to read a list from the database, wherein the list has several children, few of them have sub-children, and few of sub-children have sub-sub-children. Because the output is a list and consists long-text, it will take too long to speak all data at once. So I would like to output one child from the list and ask the user for permission (Yes/No) as "Do you want to read the next?". If the user says "Yes", I will continue reading likewise until the end. And if the user says "No", I will trigger an event. Asking for the permission from the user is true before reading a child, even sub-child, and even sub-sub-child.
The approach that I have taken involves creating a separate DB record for each user when they first request the list, to keep track of where they are in the list. When the user says yes, get user’s current item id from the database, get the next item in the list (return it to the user via agent.add) and then update the user’s DB record to the next item’s id and so on until the user reaches the end of the list. After agent.add(), ask for the permission from the user by agent.setFollowupEvent(). If the user says no, just reset/delete the DB record for that user.
Few questions I would like to ask:
How will I identify each user as an individual: by some id, session, or something else?
When I run the below code in return cloud function, agent.add is overridden by agent.setFollowupEvent. How do I stop this?
agent.add('I will print the list here!');
agent.setFollowupEvent('SOME_EVENT'); //invoking an intent to ask for the permission.
You have a few issues you're trying to raise here, in addition to the one you're dealing with. Looking at each:
How can I stop setFollowupEvent() from overriding the message I've set?
You don't. The entire point of setFollowupEvent() is to switch to a different Intent instead of the one that is currently being processed.
Most of the time you think you want setFollowupEvent(), you probably don't. Don't use it.
So how can I add the question at the end of what I'm saying?
Just ask it.
Really, it is that easy.
You can either include it in the string you're sending to agent.add(), or (depending on the details), you can do a second add() with the prompt.
But don't I need to trigger an Intent to get the answer?
No. That isn't what an Intent is for.
Intents capture what the user is saying, not what you are asking or what your agent is doing. Your fulfillment does something based on both the Intent that is triggered as well as the rest of the state that you know about the conversation. But the Intent is just one bit of that information.
You mentioned user state. How can I keep track of the user state during the conversation?
Since it looks like you're using the dialogflow-fulfillment library, the easiest way is to store your state in the parameters in a Context with a very long lifespan (or that you keep renewing).
So the first time your fulfillment is triggered, you can check the Context. If the Context or ID aren't there, then you would generate a random user ID and store it in the Context. Subsequently, you would use this ID to look up the user's information in the real time database.
If I'm doing this work, do I need the database?
Nope! If you are just storing a little bit of information about the user, and the information will just last the lifespan of the conversation, you can store all of it in Context parameters directly. You do need to make sure that these parameter names don't conflict with any parameters that your Intents have, but otherwise these will last las long as the Context does.
If you need to store information about this person in between conversations, then you will need to look into other methods. There is a User ID available for Actions, but this is deprecated and scheduled to be removed. There are also session storage and user storage fields that the Assistant makes available, but these are a little tricker to use using the dialogflow-fulfillment library if you don't need them.

add data to firebase realtime if not exists

coming from a SQL background I am still getting used to Firebase.
If I have a node for customers and I allow Firebase to create an id by using the "push" method, how do I take a customer and then only push if it doesn't already exist with the same email address and if it does, then update it?
I know set will create or update if I have a specific node (ie each node is identified by, say, the email address) but in this case I want to push if it doesn't exist and presumably set if it does. What's the neatest syntax for doing this?
thanks
Phil
First, Firestore is recommended for projects going forward. More features.
Note that firebase auth has this email duplication functionality baked in already. So, you might be spending effort on a feature that is already done for you. See auth/account-exists-with-different-credential
Finally to answer your specific question:
The way I do that is to chain the write after a read (.then). The read seeks to fetch the node. After the read if whatever field exists or === myString then you know it's already there.

Adding notifications to my web app

I'm creating a chrome extension that allows users to chat with one another. I've finished the basic implementation and want to add notifications that tell a user if they've received a new chat message since the last time they were connected. I have an idea of how I want to implement it but need input on whether it seems feasible and suitable.
Basically, my database is structured so that there is a list of users and chatrooms. Each user has a section called chats which lists all the names of the chatrooms they're in:
What I plan to do is the following: In every chat under each user's chats section, instead of setting its value to true, I set it to the last time they disconnected. Then in each chatroom, I add another field after user2 called timeLastMessageSent and always update it to the current time a new message is sent.
With that information, every time a user connects I'll loop through the chatroom's listed in their chats section and see if the value of timeLastMessageSent is higher than their last disconnect time, which means a message was sent while they were away and I can add some sort of notification that they have a new message.
I'm relatively new to firebase so if anyone with more experience can tell me what they think of my idea I'd really appreciate it. Is this idea feasible? Am I approaching the problem correctly? What sort of commands should I get familiar with to achieve this?

Get details of object from database - keep ID secure

I have a list of books obtained from the database. When a user selects a book, I'd like it to retrieve the information for that book and display it on screen. However, I'd like to keep the ID of the book hidden from the client-side, so what would be the best way to transfer the ID of the selected book? I think my brain has melted, so I'm probably missing something obvious. Sessions seem to be the only way to not have any ID information transferred, but I'm not sure how to implement a system where an item is selected (from whichever control type is most suited) and the ID of the item is somehow picked up by the server and the relevant information retrieved. (Using ASP.NET + SQL Server).
Thanks for any advice
Do you really want to hide the database id from the user, as in a scenario where the user has some alternate access to the database and you want him to search for the book the hard way?
Usually the requirement is not to keep the ID secret, but to prevent the user from figuring out IDs of other items (eg. to enforce a certain funnel of navigation to reach an item) or from sharing the ID with other users. So for example is ok to have an URL http://example.com/books/0867316672289 where the 0867316672289 will render the same book to the same visitor, but the user cannot poke around the value, so 0867316672288 or 0867316672290 will land 404s. It may also be required that another user entering 0867316672289 gets also a 404.
Keeping the ID truly 'secret' (ie. storing it in session and having the session state keep track of 'current book') adds little value over the scheme described above and only complicates things.
One solution is to encrypt the IDs using a site secret key. From a int ID you get a 16 bytes encrypted block (eg if AES block size is used) that can be reverted back by the site into the original ID on subsequent visits. Visitors cannot guess other IDs due to the sheer size of the solution space (16 bytes). If you want also to make the pseudo-ids sticky to an user you can make the encryption key user specific (eg. derived from user id) or add extra information into the pseudo-id (eg. encrypt also the user-id and check it in your request handler).
Is exposing the IDs a risk? (SO question)
How about using a "pseudo id" for each book? I am assuming you need something on the client side to tell the server which book the client chose.
Generate a Guid for each book to use as the web side "pseudo id", that should keep the real id fairly secure.
I am not sure I understand your question, because the answer seems too obvious: just don't send the entity's id to the client. Use it on the server side to compose the ASP.NET page, but don't include the id itself on the output page that is sent to the client.
Does this make sense? :-)

Resources