PureTelegram (framework for using the Telegram API)

Share your advanced PureBasic knowledge/code with the community.
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

The framework is now too big to fit in a forum post so I have uploaded it to Mediafire. (Link in OP.) I have also given it the name PureTelegram - after all, why not?

Other changes:
Added: PostVenue()
Added: PostLocation()
Added: PostContact()
Renamed: CreatePoll() to PostPoll()
Changed: PostAlbum() now returns a 1-based array of "message ID" integers

Added: GetStickerSet()
Added: UploadStickerFile()
Added: CreateNewStickerSet()
Added: AddStickerToSet()
Added: SetStickerPositionInSet()
Added: DeleteStickerFromSet()
Added: SetStickerSetThumb()

Added: SetChatStickerSet()
Added: DeleteChatStickerSet()

Added: a system for handling updates
First, a note about Telegram's unusual ways for referring to users:
  • user_id
    An integer identifier which is unique and never changes. As such, this is the sensible way to refer to the user throughout your code, and the only way they can be referred to in API calls.
  • username (possibly blank)
    A string which the user can change whenever they want, and might choose to keep blank. If it is non-blank, then their Telegram profile has a URL which can be used on the Internet, for example https://t.me/username. Also, they can be linked to within Telegram like this: "Please welcome @username to the group."
  • first_name
    A string which the user can change whenever they want
  • last_name (possibly blank)
    A string which the user can change whenever they want, and might choose to keep blank.
Telegram combines first_name and last_name to create the person's display name. PureTelegram does the same thing with the Telegram_UserDisplayName() procedure.

Now, handling updates...

Some things you need to understand about Telegram's API.
  • An "update" describes a single event (a message has been posted, a message has been edited, etc.). Each time you ask the API for updates, it will deliver a maximum of 100. You can make multiple calls until the API runs out of updates to give you. All of this is wrapped into a single procedure in PureTelegram, which makes multiple calls to the server and then delivers all new available updates, in a structured list.
  • The Telegram API endpoint is called GetUpdates, but the PureTelegram procedure is called GetNewUpdates(). Here's why. The API might only deliver a particular update once, then immediately "forget" it and never pass it to you again. It is impossible to know how long an update will persist after being sent, so I've written this framework to assume that any updates sent have already been "forgotten" by the API and to only request updates newer than the last one sent. To clarify the situation, I have named the procedure GetNewUpdates().
  • An update will be one of eleven different types, depending on the type of event it is describing.
Now some things about PureTelegram:
  • PureTelegram uses two txt files in order to keep up with things. The first file is a bot-independent ledger of Telegram users and their names, so that you can work with that data outside of these GetNewUpdates() calls. Set this file using Telegram_InstantiateLedger(). The second file enables PureTelegram to "remember" the number of the last update it received from each bot. Set this file using Telegram_InstantiateBot(). You will need to call these two procedures once, before calling GetNewUpdates().
  • Telegram's API delivers all structured data as JSON, which results in very unwieldly structuring, with pointlessly repeated fields all over the place. It is NOT elegant. PureTelegram creates a few generic custom variables in an attempt to make the data handling a bit easier. For each update, regardless of the type, it will automatically fill in the following additional top-level fields:
    • id.i
    • type.s
    • group_or_channel.s (if the update relates to one)
    • user.i (if the update relates to a particular user) - this will be their unique, unchanging ID number, as described above
    With this info known, you can then proceed to deal with the update as you see fit. Learn what info is supplied for each type of update.
With all of that said, here is the full code for a program which gets updates from a bot every 30 seconds, then goes through the updates and reports to you if anyone has used the word "purebasic" in a message:

Code: Select all

#BotAPIToken = ""
Telegram_InstantiateLedger("D:\tg_user_ledger.txt")
Telegram_InstantiateBot(@MyTG.TG_BotInstance,#BotAPIToken,"D:\tgbot_update_counter.txt")

Repeat
  Telegram_GetNewUpdates(@MyTG)
  ForEach MyTG\update()
    With MyTG\update()
      If \type = #TU_Type_MessagePosted
        ss.s = "purebasic"
        If FindString(\message\text+" "+\message\caption,ss,#PB_String_NoCase)
          txt.s = Telegram_UserDisplayName(\user)+" said "+Chr(34)+ss+Chr(34)+"."+Chr(13)+Chr(10)+Telegram_MessageURLFromStructure(@\message)
          MessageRequester("Telegram Report",txt)
        EndIf
      EndIf
    EndWith
  Next
  Delay(30000) ; wait 30 seconds
ForEver
Another way to use it is to call GetNewUpdates() with a maximum wait time, in which case it will "long poll" Telegram and get updated as soon as an event occurs. Obviously, long polling is something you only want to do in a threaded program.

Code: Select all

Telegram_GetNewUpdates(@MyTG,60) ; wait a maximum of 1 minute for Telegram to send updates
Note that you could interact with multiple bots in the same program:

Code: Select all

Telegram_InstantiateLedger("D:\tg_user_ledger.txt")
Telegram_InstantiateBot(@MyBot1.TG_BotInstance,#Bot1APIToken,"D:\bot1_update_counter.txt")
Telegram_InstantiateBot(@MyBot2.TG_BotInstance,#Bot2APIToken,"D:\bot2_update_counter.txt")
Telegram_InstantiateBot(@MyBot3.TG_BotInstance,#Bot3APIToken,"D:\bot3_update_counter.txt")
This will probably be the final version of this framework, unless Telegram expand their API with more functions that I want to use. I haven't coded for everything that is already in the API, just what I personally felt like doing. If anyone who uses PureTelegram feels that something important is missing, let me know and I'll see about adding it. Likewise, if you write any generic components that could be useful, please post them here and I will add them to the PBI.

Anyway, this little project has been a pleasure to work on, and I hope that the framework gives people ideas for new ways they could interact with what seems to be very much an up-and-coming messaging platform.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
User avatar
Caronte3D
Addict
Addict
Posts: 1014
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: PureTelegram (framework for using the Telegram API)

Post by Caronte3D »

Very useful, I'll use it for my next project for sure :D
Thank you very much, Seymour Clufley!
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

Thank you, Caronte3D.

A new version is linked in the OP. I have fixed a bug that affected ForwardMessage() and CopyMessage(). Also, some more "data-tidying" now takes place in the GetNewUpdates() procedure, splitting system notification messages out of the update type "message posted" into a set of new custom update types:
#TU_Type_LeftChatMember
#TU_Type_NewChatMember
#TU_Type_GroupCreated
#TU_Type_SupergroupCreated
#TU_Type_ChannelCreated
#TU_Type_ChatPhotoDeleted
#TU_Type_ChatTitleChanged
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

A few changes:
Added: PostOnlineImage()
Changed: PostText() now passes the text as a multi-part data field, rather than as a URL parameter. This prevents failures due to special characters in the text, etc.
Changed: PostItem(), PostItemWithThumbnail() and PostPBImage() - as above, re. the caption
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: PureTelegram (framework for using the Telegram API)

Post by vwidmer »

Seymour Clufley wrote:The framework is now too big to fit in a forum post so I have uploaded it to Mediafire. (Link in OP.) I have also given it the name PureTelegram - after all, why not?
Why not put it on github or other git server? that way as well people can submit any changes fixes etc?

Just idea.
Thanks for the great code though.
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
morosh
Enthusiast
Enthusiast
Posts: 291
Joined: Wed Aug 03, 2011 4:52 am
Location: Beirut, Lebanon

Re: PureTelegram (framework for using the Telegram API)

Post by morosh »

Thank you very much for sharing!!
I like to command a esp8266 from my phone. Using telegram no problem: I created a bot and there I type /led_on or /led_off to turn the led on and off. the esp8266 is already programmed for that.

My question: is it possible to command the led by httpRequest()? I like to create an application with SpiderBasic and move it to phone for that, what httpRequest() is sent after type /led_on from the bot?

Can this be done?

Thanks in advance
PureBasic: Surprisingly simple, diabolically powerful
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

Morosh... unfortunately I have never used SpiderBasic so I don't know what can/can't be done with it. I'm sorry I can't help you.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
ruslanx
User
User
Posts: 46
Joined: Mon Jun 06, 2011 8:28 am

Re: PureTelegram (framework for using the Telegram API)

Post by ruslanx »

"The chat_id passed can be username or integer ID " - how to use integer ID ? or only comment "PrepareChatID"

Code: Select all

Telegram_PostText("token", "chatID", "text")
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

Just pass the integer ID as a string - eg. Str(my_integer_id.i)
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
ruslanx
User
User
Posts: 46
Joined: Mon Jun 06, 2011 8:28 am

Re: PureTelegram (framework for using the Telegram API)

Post by ruslanx »

not work ... only if I remove PrepareChatID ... it add "@" in front of ID..
or this code is old from first post ?


my ID is without "-" sign ... like 614331292

Code: Select all

Macro PrepareChatID
  EnsureThisNotStart(chat_id,"@")
;   If Left(chat_id,1)<>"-"
;     chat_id = "@"+chat_id
;   EndIf
EndMacro
u must check for number or ...

Code: Select all

chat_id.s = "614331292"
;chat_id.s = "username"


Macro EnsureThisNotStart(t,start)
  If Left(t,Len(start)) = start
    t = Mid(t,Len(start)+1,Len(t))
  EndIf
EndMacro

Macro PrepareChatID
  EnsureThisNotStart(chat_id,"@")
  If Val(chat_id) = 0
    chat_id = "@"+chat_id
  EndIf
EndMacro


PrepareChatID

Debug chat_id

How can I receive mess from Telegram Bot .. example ?
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

ruslanx wrote:my ID is without "-" sign ... like 614331292
That is your own personal profile ID, not a chat ID (eg. for a group or channel). All of these procedures require a chat ID, not a personal profile ID.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
ruslanx
User
User
Posts: 46
Joined: Mon Jun 06, 2011 8:28 am

Re: PureTelegram (framework for using the Telegram API)

Post by ruslanx »

is chat ID
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
zikitrake
Addict
Addict
Posts: 833
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Re: PureTelegram (framework for using the Telegram API)

Post by zikitrake »

:D Autosolved
#TelegramTargetID must be "channel Name" not "chat ID"

Hello,
I'm trying to use it but I'm getting "Bad Request: chat not found" error.

The channel is public, and I created the bot with @Botfather.
I take the id from the url that Telegram web gives me (in the image I have deleted the last 2 digits, but it matches in the program and in the original url).

Have you changed anything or am I missing something?

Thanks for your labour.... and for your time!

Image

PS: I Just added mi User Bot to administrators of the channel without luck :oops:
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

Re: PureTelegram (framework for using the Telegram API)

Post by Seymour Clufley »

Somebody has asked for a demo of using the API function GetChatMember.

In order for this code to work, you have to:
  • create a Telegram group
  • create a Telegram bot
  • add that bot as an admin to your group
  • either know the ID number for your group, or have its @username (either of these will do for the chat_id string variable)
  • know the unique ID number for the member of your group whose details you want. This is the difficult bit. You will either obtain someone's ID number manually, or programmatically by harvesting messages using GetUpdates

Code: Select all

#BotAPIToken = "716306084:AAGUrvMNGzddZ2CkN_MbCLBv7ra3RORJ-cF"
chat_id.s = Str(-1001212492478)
;chat_id.s = "@mygroupusername"
user_id.i = 808415027
Debug Telegram_GetChatMember(#BotAPIToken,chat_id,user_id,@cp.TG_ChatMemberStructure)
Debug cp\user\first_name+" "+cp\user\last_name
All of the user's details are now in the TG_ChatMemberStructure structure, specifically in its "user" field, which is of type TG_UserStructure.
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."
Post Reply