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.
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:
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++.
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.
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.
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.
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++
> 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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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!)
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!
>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.
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?
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.
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.
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