Hi! I've been playing around with Nim, and to get my head around core concepts I've rewritten my existing Telegram bot in Nim. I've used [Telebot](https://github.com/ba0f3/telebot.nim) for this. The core update handler loop looks somewhat like this (abridged version): import regex import unicode import httpclient import telebot, asyncdispatch, logging, options import timezones import times import json import options const OH_PATTERN = re(r"(?i)(\b[oо]+|\b[аa]+|\b[ы]+|\b[еe]+|\b[уy]+|\b[э]+)[xх]+\b") const API_KEY = getEnv("BOT_TOKEN") proc fromJson*(json: JsonNode): DateTime {.gcsafe.} = let timezone = tz"Asia/Yekaterinburg" let response = to(json, seq[ApiResponse]) let responseDate: DateTime = parse("1970-01-01", "yyyy-MM-dd") for item in response: if item.category.isSome() and item.date.isSome(): case item.category.get(): of "holiday": date = parseDateTime(item.date.get(), timezone) // ...some other cases... else: discard return responseDate proc updateHandler(b: Telebot, u: Update): Future[bool] {.async.} = if not u.message.isSome: return true var response = u.message.get if not response.text.isSome: return true let text = response.text.get var m: RegexMatch if text.find(OH_PATTERN, m): let vowel = m.groupFirstCapture(0, text) discard await b.sendMessage(response.chat.id, generateOh(vowel)) elif text.toLower().contains("some request"): let client = newHttpClient() let content = client.getContent("https://example.com/some_api") let jsonNode = parseJson(content) let response = fromJson(jsonNode["items"]) discard await b.sendMessage(response.chat.id, $response) // ...some other cases... let bot = newTeleBot(API_KEY) bot.onUpdate(updateHandler) bot.poll(timeout=300) Run
So my main problem with this is the fact that `updateHandler` has to be gc-safe, which leads to some awkward coding for me, but I'm hoping that there's a better way to do things (which is why I'm here). Here are my questions: 1. Coming from other languages like Java/C#/Python/Go I'm used to the fact that httpclient is usually created once and then it's reused without any gimmicks, as it's threadsafe. So the first thing I did here was `let content = client.getContent("https://example.com/some_api")` just outside of `updateHandler`. But then it complains that `updateHandler` is not gc-safe anymore and I can't compile this. So for now I create a new client with every request, but how do I do this properly? I've heard about `threadvar` but not sure if it's applicable here? 2. You may have noticed that I'm using `regex` and not `re` from stdlib. And the reason is exactly the same: it's my understanding that to use compiled regex patterns inside of `updateHandler` they either have to be constants (which you can't do with `re`), or they have to be created inside of `updateHandler`. But there's no reason to compile the same patterns over and over with each request, so the question is the same: can I use standard `re` _and_ create it just once outside of `updateHandler`? 3. The final question is about timezones. Again, coming from languages like Java and Python I was very surprised to find that there's basically no tzdata support in the language. So I've found [timezones](https://github.com/GULPF/timezones) and [chrono](https://github.com/treeform/chrono). `Chrono` seems to bring with it a whole lot of things for manipulating dates which I don't really need, so I didn't want to use that. `Timezones` works, but it also inflates the binary size: I was honestly expecting something <1MB in size, originally but with `-d:ssl` and imported `unicode` and `regex` package it's already at 1.5MB even with `-d:release` and `--opt:size`. So when I add timezones it results in 4MB binary. It's not critical for me by any means, but I was just wondering: what's the usual approach here? All I need is data for one specific timezone for the next few years, but I also want the code to be readable and the ability to easily change the timezone if I need (I saw `newTimeZone` in `times` and that doesn't look very supportable nor readable) I would be glad if someone could clarify these things for me and show what's the idiomatic way to solve these problems. Thanks!