Hacker News new | past | comments | ask | show | jobs | submit login
Botlib: C Telegram bot framework (github.com/antirez)
230 points by rgbrgb 12 months ago | hide | past | favorite | 86 comments



Author here, thank you for having this project on the front page! I want to explain why this bot is in C, while, for instance, another project of mine that implements a LoRa driver/protocol for the ESP32 (a much lower level project, in theory) is in Python!

This code started as the Telegram bot Stonky, it's on Github, and you'll see the bot does a lot of financial analysis things, including Montecarlo simulations. I really needed the speed. Later my daughter was diagnosed with scoliosis, and requires to wear a corset. To take track of the time she wears it was a pita, so I wrote another bot (not released so far) and put it in our family channel.

Then... I needed another bot. And I finally extracted the common parts from the two. So:

1. For Stonky, speed was essential, but not for my next bot.

2. Once I needed to write the new bot for the corset I tried the Python lib. And... I started to have the first code compatibility issues (accross versions) of the modern software stack (context here: https://twitter.com/antirez/status/1726305869032570992).

3. Meanwhile Stocky was no longer able to work because I did the unescapable error of basing it on the Yahoo Finance API, now retired :( So I told myself, I don't want to relay on a software stack that will make this bot unable to work or obsolete in 2/3 years because all the libraries will change fast (and, if you check, you will see there was a lot of work that went into Stonky back in the couple of weeks when I worked at it constantly).

On top of that, with Stonky I decided to serve each request with a thread, and not in multiplexing. In the specific case of a Telegram bot this is basically able to simplify many things: many bot requests are long living, because you want to call an LLM API, or Whisper to transcribe, or do a Montecarlo simulation on a stock history, (btw the Whisper thing will be one of the official examples of this library) and so forth. Now in Stonky this approach worked so well because it's written in C, so each thread consumes only minimaul resources associated with the OS thread creation.

Finally: With SDS lib, my JSON and Sqlite3 wrapper (the wrappers are the interesting part of the project IMHO) it is not so different than writing Python code. So, I said, why not?

P.S. this library is just a work in progress, hacked while I'm doing many other stuff. I hope it will improve in the next weeks. I use Telegram for more than 10 years now, with all my friends and family. So it is very likely I'll require to write more bots in the future :D


Unrelated: I just want to say thank you for all of your amazing work over the years. You’re a software hero of mine. I’m 100% certain your code and work has saved me time, money, and maybe even my job at one point! Also, sorry to hear about your daughter. I’m going to pray for you and your family! (If my memory serves me right, you don’t believe in God, but I hope you don’t mind.)


Thank you Jay! It's a great thing to read in the morning :) Appreciated. I don't believe in God, but in a very "soft" way, that is, I'm happy other people enjoy their religious life.


I am gonna try to generate Nim for this with https://github.com/nimterop/nimterop.


I must have missed something: why do you feel the need to explain why you used the C language?


Because certain hn users will dogpile on that when they have nothing to add to the discussion. Cue the same person trolling why not c++, same person saying how it would be done in D, and cue various people talking about rust and unsafe.


Amazing project, and sorry to hear about your daughter. I wore a back brace from age 4 until ~10, when my scoliosis curvature took a turn for the worse. They did surgery on me back then (27-28 years ago now) and put a stainless steel (or titanium im not sure) rod on my spine and fused it. I've been stuck at 5'1" since age 11, and have had to deal with some teasing about my height, but otherwise I've been able to have a good career in software and tech.

If you want to reach out and ask me any questions about life with scoliosis (or anything else for that matter), feel free to reach out to me:

https://www.evildojo.com

https://www.twitter.com/evildojo666

Your project is pretty cool...I can see myself integrating IRC support so I can bridge communications between telegram and IRC. I already do a lot of bot-like stuff using Sopel (Python) and notify (golang), but love working in C/C++.


Appreciate the words of support! Thanks. Very happy you managed regardless of scoliosis.


If, by bullet point 2, you are talking about python-telegram-bot, not only is it like that... the owners are also absolute shitheads about it - if you ask for help while using an older version of their library in their support chat, they threaten to ban you.


Yes, I have this vibe about many library authors in the Python/Ruby/Javascript ecosystem at this point. I don't want to be part of that, nor as a user, nor as a coder.


[flagged]


The Thompson story is very telling about C and how semantically powerful it is. KT tried to rewrite UNIX in B at some time, but he failed. Assembly allows you to do many interesting things because it is a low level language, and yet you can build abstractions, so it was a better language than B to write UNIX. But once B got structures, and was starting to become C, things changed. Structures with fields and pointers to other structures is the ha-ha moment of C. It is what really makes the whole language so special. With this simple building block you can start building abstractions that are able to abstract away low level details, while, at the same time, you have full control on low level details.


Do you see any features in modern, high-level programming languages (such as Python, Go, C#) that could guide the next evolutionary step for C, without sacrificing that low-level control?

Knowing KT worked on Go, I'd guess he'd say concurrency, but that's difficult to get right without sacrificing low-level control. What's your take?


Sure, C could be much better right now. In some incredible way people that are able to drive the future of C made all the worst choices, undermining the language instead of improving it, for most parts (with undefined behaviours).

C just needs:

1. A solid and modern standard library, with basic data structures, sane strings, higher level sockets, ...

2. A very simple object system. No inheritance, no advanced features at all, just the ability to call object->method(1,2,3) and getting a 'self' reference.

3. Ability to perform operations on function exit in order to clean-up locally allocated things. So as I allocate things or open files and alike, I can specify some cleanup code doing things like if (fp) fclose(fp); that is executed when the function returns in any case.


Just as an aside Odin (https://odin-lang.org) has all of these things and does not stray far from C otherwise. It's a delightful language.


I read a paper 'What If We Don’t Pop the Stack? The Return of 2nd-Class Values' where they discuss their research into delaying popping the stack to allow functions to return data allocated on the stack. As a small brained embedded primate that doesn't use malloc that sort of thing would make C vastly easier to use.

https://www.cs.purdue.edu/homes/rompf/papers/xhebraj-ecoop22...

Also would be super if C had first class types.


If C hadn't been standardized by ISO, I wonder if C implementors would have eventually added stuff like this just because they found it useful.

Or if C had been standardized, but C++ didn't exist, maybe they would have added features like this simply because contemporary languages like Object Pascal and Ada 95 supported object oriented programming better in practice.


There are other OOP paradigms, no need to force 'this' pointers on everyone like C++ does. Both 2 and 3 could be done with semantic-aware macros instead.


I believe the C++ way would be the right thing for C. Note that this does not mean in any way to inherit all the stuff from C++, nor even constructors and stuff like that. Simply a way to avoid doing this:

    list_add(&mylist,1);
But instead:

    mylist->add(1);
Note that doing this is not an option:

    mylist->class->add(&mylist,1);
It's not just ugly (even if often used), but also uses an additional pointer, which in some application (like Redis) is a no-go because of memory usage.


Perhaps, though I think one should be careful, as reproducing C++ in this fashion runs awfully close to reproducing what I see as C++'s largest sin...

Let me explain, I feel iteration speed is of utmost importance. So C++'s mistake of mixing interface and implementation (data layout specifically) leads to massive include bloat, and ultimately contributes significantly to the compilation time problem in C++. In contrast, in C, functions are almost entirely decoupled from structure data layout, and implementation, this promoting much more svelte headers and reduced compilation time for many projects.

So, IMO, it would be important to seperate object interface, from the layout, or risk a major, if not the most major, advantage of using C over C++


Maybe you would like UFCS: https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax

e.g. Nim has it, and it lets you do this:

  proc add(self: MyList, e: int) =
    # [insert append code here]

  mylist.add(1) # equivalent to
  add(mylist, 1)
Though I'm not sure how well it would work with C, considering it lacks function overloading.


> Structures with fields and pointers to other structures is the ha-ha moment of C. It is what really makes the whole language so special

How is it special at all?

> you have full control on low level details.

Yeah, if you add random attributes to the language and control the compiler. C still can’t properly do vector instructions, while even Java can, but so can C#, Rust, C++. It’s simply not a low-level language.


Did you check out the clang vector extensions? And before "but that's not standard C!": in the C world, the interesting stuff happens outside the standard in language extensions, the standard is mostly irrelevant for real world code. What counts is what specific compilers have to offer.


To the point that Linux, probably the most important C project in the world, was written in the GCC dialect for many many years. I think it's no longer the case.


AFAIK the only reason why Linux compiles on Clang now too is because Clang tries to emulate GCC behaviour as closely as possible? I doubt that the Linux kernel would compile out of the box with Microsoft's C compiler for instance ;)


All: can we please talk about something more interesting than how you don't like the language choice? If a project belongs on HN's front page, which I presume this one does, there must be more interesting things to talk about than that.


On what is a day off in the middle of a long weekend for many in the US, there's something comforting about returning to familiar traditions like eating leftover turkey, spending time with relatives, shopping, and arguing about programming languages.


Ffs… I thought you were just joking around until I scrolled down into piles of dead threads.


My guess is it got posted and noticed because "antirez did a thing" rather than a particular interest in Telegram bots.

antirez is a bright guy and worth paying attention to, but I think this is just him having some fun.

Edit: aha, here's what he's actually using it for.

https://twitter.com/antirez/status/1727969700783460734


Well, it’s sort of neat to me. I’ll probably build some bindings too. Know any good scripting languages?


You weren't kidding. Now I want to make a little bot too. In freestanding C with direct Linux system calls. :)


Given that there is probably less attention for good ol' C projects these days, its probably educational for the masses of readers using interpreted languages to see a simple-ish project using a classic, compiled language.

In terms of binary size, memory usage, you probably can't beat a slim C project.

Difficulty of clean code/memory leaks/security aside, I think everyone should read or write some C every once in a while. Fix that software that doesn't work quite right on wine. Learn the linux kernel enough to fix a bug for hardware you own. Start some project like this. You might learn something, or strengthen some old mental muscles.


> In terms of binary size, memory usage, you probably can't beat a slim C project

Zig can and do routinely beat it


To be fair, the Telegram bot API is amazing and speaks for itself, and this bot framework is such a thin wrapper around it that being written in C and the resulting idiosyncrasies are the points of interest.


FYI using non-bot APIs like WTelegram for gathering messages and sending them (even while sending thru a bot account!) gets you rid of the 50MB and similar limits.

Source: Run a bot that aggregates and translates several Russian channels for transparency reasons. ~100k msgs processed until now, including hour-long documentaries


First party bot support is one of the biggest reasons I stick with Telegram and Discord for communication.

Signal and WhatsApp (to a degree) have E2EE, but zero support for any kinds of bots, making them mostly useless for what I need chat applications for.


I'd be really interested if you could expand on what the point of these bots is? I genuinely don't see the point, why would I need a bit in a normal chat?

If I was managing a large chat group on a topic I could possibly see having a bit welcome new sign ups as beneficial ...

Either way I don't get the point so want to learn.


Discord bots are their own ecosystem, you can find bots for pretty much anything you can imagine https://discord.bots.gg

For example Midjourney is just a Discord bot you can invite to your own server and use it there.

I also ported an old IRC bot that had some specific functionality for a group to a basic Discord bot pretty much in one evening.

As for Telegram, I've get most of my server and software notifications via a single Telegram bot. A simple command just calls the API and sends the message to the bot

I also have an Octoprint bot on Telegram that I can use to monitor and control my 3D printer remotely.

Additionally we have a family channel in Telegram, and a home automation bot sits there. When someone forgets to close a door (front, fridge, freezer) the bot will complain in there. Same with temperature/humidity warnings and notifications. I'll add actual two-way controls when I get around to it, so that we could control the for example AC via the bot.


To everyone that got flagged before I could read their comments: I will keep writing code in C until I die, and I have just started.


The example mybot.c looks very clean and simple, nice project.

It's been a while since I played with telegram bots, but I remember thinking it is one of the best APIs I've used. So simple to register a bot directly through the chat interface with the not father, and a 5 second job to add message posting to a bash script etc.


That they offer long polling as one option for fetching updates makes it incredibly friendly for local development and one-offs.

I have had so much fun integrating with Telegram from Elixir. There is a lib (not in hex unfortunately) that makes it all quite straightforward.

I even gave a remote talk about it with an interactive demo: https://youtu.be/DFGHaER6_j4?si=sooEsiyVTmfXPqNs

Telegram is a mile simpler to get going with than the others.


By comparison I am currently doing some work with Google Chat of all things. If your bot is in a Space (channel/grouo) it only gets webhooks when someone @-mentions it. Which is really not ideal if you are trying to have an assistant bot participate organically in the convo..

I poked around with doing a Slack bot recently and the hoops for an app were many and confusing. Not Google credentials level but more than I cared for.


Seconded on the Telegram bot API.

I've used both Discord's bot API as well, and can say it was way more convoluted to get up and going. Telegram's API was a joy to build in. This was in Node.js.


Is there a simple API to read my chats programmatically? Not a bot, but on my own TG account? I was confused by this a while ago


You need to use the "Telegram API": https://core.telegram.org/api#telegram-api (not the "Bot API") to develop your client. It uses MTProto to communicate with the server, so I suggest you just use a library that supports it like Telethon if you want to program in Python.


Care to provide a concrete example of a difference? Curious.


was just looking at the official telegram bot api just last night! i'm going to give this a try, as a way to get more comfortable with C.

on a separate note, does anyone know of a stable telegram api (not bot api) in javascript that doesn't require polyfills?


I'm surprised no one has questioned why a bot made for one specific program and protocol has a generic name like 'botlib'.


can language evangelism strike forces just please go away?


[flagged]


After acheiving a certain level of expertise, most people tinker in the languages they're most fluent with (if they want to focus on the project) or the ones they're curious about (if they want to focus on the language).

It's a profound understatement to say that antirez has a certain level of expertise, and a certain fluency, in C.


I started writing C over 20 years ago. That doesn't mean that I'd ever pick it for this.


Why not, it's not like Telegram uses E2EE


Yes, he does. The next person who picks this up and does something with it might not, though.

IMO fun stuff like this is often a good excuse to learn something new and different that might be better in some way, like safety.


Agree in general, but as you can see this could’ve been done in other languages with less effort. In c you mostly need to reinvent the wheel


[flagged]


But then it's hard to imagine much better than the existing Telebot library, which is a very elegant and idiomatic Go.

https://github.com/tucnak/telebot


Are you aware of any similarly definitive library for the Telegram user (non-bot) API?


whoa, had no idea this existed - looks fantastic thanks for sharing


[flagged]


Modula had "import" in 1975, and C is only barely younger than it; the first version of C appeared in 1972, and the first version with structures appeared in 1973.

It's surprising to me that the creators of C++ didn't add modules in the 1980s, given it was literally called "C with classes" at first and was trying to be a better C. Modules seem like a lower-effort way to improve C than the addition of classes.


Conditional includes play a big role as a configuration mechanism in C. Likely the creators of C++ could not afford to get rid of that.


You don't have to get rid of #include and the preprocessor to add modules. The ISO C++ committee has added modules to the newer standard and they haven't gotten rid of headers and conditional inclusion. Modules would be nice just so that the build system doesn't have to rely on things like "gcc -MMD" generating header dependencies of object files for inclusion in Makefiles.


with C, i literally just do

    import "cJSON.h"


C doesn't have import. Perhaps you meant: #include "cJSON.h"


Ah, my bad.

    #define import #include
    import "cJSON.h"


Edit: It is with great sadness, and a heavy heart, that I report the following news: C doesn't let you do this. (Genuinely surprised, considering everything else it lets you do!)


In fact, I even made it into a reusable library!

    #include "import.h"
    import "cJSON.h"


even if that was valid syntax (its not), that is not the same thing at all. #include is just a "dumb" macro, that literally just dumps the file contents in that spot, so have fun figuring out where an identifier came from in the global scope!


>have fun figuring out where an identifier came from in the global scope!

grep?


grep where? First you need to find all include paths..


gcc -E


ah yes, who needs a proper module system when you have... grep. LOL sad.


[flagged]


>Whatever can be done in C in this case can be done with Python

This mindset is why, in a future not far away from now, we will have 20GHz 512-core IoT widgets with 8TB of RAM that still take 4 seconds to turn the lights on.


Isn't that just basic radio engineering? What does C have to do with radios?


Wait, do you even realise how much slower and more resource-intensive Python is than a compiled language like C?


Really? Oh wow, I did not know that. I thought all languages with recursion and loops were Turing complete. Are you saying there is some kind of difference between C and Python as far as what programs can be written in them or is this something else?


I can’t tell if you’re joking. Python uses tons of memory and is generally low performance. It can do everything c can but slower


This is good to know.


yea, it's certainly impossible and no one is capable of knowing what they're doing. eyeroll


I wouldn't say it's impossible but certainly much harder than Python.


[flagged]


Antirez sucks! You could easily do this with Redis as a data store ;)


How oblivious does one have to be to call antirez "people who can't code"


> user: swingingFlyFish > created: 63 days ago

HackerNews is flooded with clueless newcomers, it's not surprising that most of them don't know anything because they're also new to programming, the business and everything else, but usually try to join in on the conversation as if they weren't, because they have a set of opinions that they got from lifestyle YouTubers anyway.


Do elaborate! I thought antirez is a pretty well respected programmer.


?


[flagged]


I don't mind C and I don't think it's a security apocalypse, but if I were to use something more recent, with new ideas, I'd probably play with Crystal.

For my needs where a GC is not a show stopper, it's Go all the way down.


I love C.


[flagged]


[flagged]


"Don't feed egregious comments by replying; flag them instead."

a.k.a. please don't feed the trolls

https://news.ycombinator.com/newsguidelines.html


Certainly the first time I've heard this specific troll remark, good to know that their one joke is still alive and well.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: