{"id":18303082,"url":"https://github.com/b1z0n/iahr","last_synced_at":"2025-07-25T05:32:24.963Z","repository":{"id":43186355,"uuid":"261727069","full_name":"B1Z0N/iahr","owner":"B1Z0N","description":"Telegram userbot creation platform framework.","archived":false,"fork":false,"pushed_at":"2024-01-29T23:43:12.000Z","size":869,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T06:33:21.754Z","etag":null,"topics":["framework","telegram","telegram-userbot","telethon","userbot","userbot-for-telegram","userbot-telegram"],"latest_commit_sha":null,"homepage":"https://b1z0n.github.io/iahr/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/B1Z0N.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-05-06T10:35:10.000Z","updated_at":"2023-04-04T20:09:19.000Z","dependencies_parsed_at":"2023-01-25T13:45:58.931Z","dependency_job_id":"a25f56e5-23d9-4ab7-9fd0-fa12f45cc932","html_url":"https://github.com/B1Z0N/iahr","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/B1Z0N%2Fiahr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/B1Z0N%2Fiahr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/B1Z0N%2Fiahr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/B1Z0N%2Fiahr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/B1Z0N","download_url":"https://codeload.github.com/B1Z0N/iahr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247352661,"owners_count":20925309,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","telegram","telegram-userbot","telethon","userbot","userbot-for-telegram","userbot-telegram"],"created_at":"2024-11-05T15:24:04.049Z","updated_at":"2025-04-05T14:31:46.010Z","avatar_url":"https://github.com/B1Z0N.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\nTelegram chat command execution framework based on telethon library\n\n## Quick simple demo\n\nBasically this allows you to turn any(or all of them) telegram chat into REPL where you call a command and this app from under your account responds to you with the result. \n\nYou can call a commands predefined in your files with `.` operator:\n\n\u003cimg width=\"1121\" alt=\"image\" src=\"https://github.com/B1Z0N/iahr/assets/32279961/1e5b9453-71dd-4f4f-b6ab-8cdad4ccef57\"\u003e\n\nBut it is much more than that! This projects provides:\n\n- Built-in access permitions. Yes, you may allow/ban other users to call your commands. Just like in Linux.\n- Built-in help on commands.\n- Allows you to access any of Telegram API via [Telethon library](https://docs.telethon.dev/en/stable/). Like invoke a command once someone edits a message. Or change image in your profile whenever someone else does this.\n- Grants solid support for logging.\n- Graceful and in-chat handling of errors.\n- Serialization and deserialization of state on exit.\n- Localization to popular languages.\n- You may customize nearly EVERYTHING(yes, even syntax) via config.\n\n## Warning\n\nBe careful, do not violate Telegram's [Terms of service](https://core.telegram.org/api/terms).\n\u003e If you use the Telegram API for flooding, spamming, faking subscriber and view counters of channels, you will be banned forever.\n\u003e Due to excessive abuse of the Telegram API, all accounts that sign up or log in using unofficial Telegram API clients are automatically put under observation to avoid violations of the Terms of Service.\n\n# Contents\n\n- [About](#about)\n  * [Warning](#warning)\n  * [Quick simple demo](#quick-simple-demo)\n- [Contents](#contents)\n- [How to start](#how-to-start)\n  * [Docker](#docker)\n  * [Basic concepts](#basic-concepts)\n    + [Routines](#routines)\n    + [Senders](#senders)\n    + [Events](#events)\n  * [How it works](#how-it-works)\n    + [Adding new commands](#adding-new-commands)\n    + [Adding new handlers](#adding-new-handlers)\n    + [Built-in commands](#built-in-commands)\n    + [Useful custom commands](#useful-custom-commands)\n- [How to customize](#how-to-customize)\n  * [Env](#env)\n  * [Config](#config)\n  * [Session file](#session-file)\n- [How to extend](#how-to-extend)\n  * [Creating senders as functions](#creating-senders-as-functions)\n  * [Creating senders as classes](#creating-senders-as-classes)\n  * [Other ways](#other-ways)\n- [How to contribute](#how-to-contribute)\n  * [Guidelines](#guidelines)\n    + [Coding style](#coding-style)\n    + [Templates](#templates)\n  * [Error refactoring](#error-refactoring)\n  * [New commands](#new-commands)\n  * [Localization](#localization)\n  * [Tests](#tests)\n  * [Ideas](#ideas)\n    + [Build and deployment related](#build-and-deployment-related)\n    + [Command ideas](#command-ideas)\n    + [Core features](#core-features)\n    + [Documentation](#documentation)\n- [Naming](#naming)\n- [Thanks](#thanks)\n\n# What is it\n\n# How to start\n\n## Docker\n\n```\ncp .env_exmpl .env\n\n# fulfill .env with your data\n# ...\n# run exmpl(as a daemon)\n\ndocker-compose up iahr_exmpl\n\n# run tests(optional)\n\ndocker-compose up iahr_tests\n```\n\nP. S. try adding sudo if something is faulty\n\n## Basic concepts\n\n### Routines\n\nRoutine is your python function with some metadata \nthat can be accessed from telegram\n\nThere are two type of routines:\n\n* **Commands** - text-based routines, call it by typing it's name in message.\n* **Handlers** - reactions to some events(e.g. `onedit`)\n\n### Senders\n\nSenders decorators are used to register your routine.\nCurrently there are three senders:\n\n* `VoidSender` - your function returns nothing\n* `TextSender` - it returns `str`\n* `MediaSender` - return file-like object\n\nYou can import it from `iahr.reg`. \nAnd easily create new senders(more on it later, below).\n\n### Events\n\nEvery function, if not specified otherwise, takes event object\nfrom telethon as first parameter. This helps to  provide custom\nbehavior and enables more freedom in terms of an API.\n\n## How it works\n\nYou could easily add new commands, `Iahr` was designed for it. And moreover you could easily compose them(like plain old functions in any modern PL), as long as one commands return type corresponds to other parameter's type.\n\nFor example:\n\n`.upper word` ~\u003e `WORD`\n\n`.lower wORd` ~\u003e `word`\n\nand the most epic one(attention!):\n\n`.lower .upper word` ~\u003e `word`\n\n\u003e  \\- WOW, isn't it?\n\u003e\n\u003e \\- It is!\n\nAnd this is just text examples, you can use any data format to pass in/out of  commands.\n\n### Adding new commands\n\nI'm feeling lonely and bored, so i want to be able to play my favorite game marcopolo with myself in any chat.\n\nJust add new function, like you would do it in python. \n\n```python\ndef marco():\n    return 'polo'\n```\n\nAnd that's wrong!. Stop, not so fast. It lacks three more things:\n\n1. `Iahr` doesn't know anything about your code. So it should be registered.\n2. Use `async def` because it's faster\n3. You need more info to reply to a message, just an additional parameter: `event`\n\nSo now:\n\n```python\n@VoidSender()\nasync def marco(event):\n\tawait event.message.reply('polo')\n```\n\nThat's it. It automatically adds your command to the list of commands on `.commands`. \nBut there is more than one way to do it right: \n\n```python\nfrom telethon.events import NewMessage as newmsg\n\n@TextSender(\n\tname='marco', # how you will call it in chat\n    about='An ancient game in modern messenger', # description on `.help marco`\n    take_event=False, # whether it takes event, default - True\n    multiret=False, # whether it returns one value, or multiple, default - False\n    on_event=newmsg, # what event it should be called on, default - events.NewMessage\n    tags={'games'}) # tags facility to quickly search for commands\nasync def marco():\n    return 'polo'\n```\n\n**NB**: don't forget `multiret=True` when you want to return list of values instead of one value: list. \n\n-------------------------\n\nWell that's now a lot more, it's just an overview of an API and you don't need to use it whole. Personally I would stop on something like this:\n\n```python\n@TextSender(take_event=False, about=\"\"\"\n\tAn ancient game in modern messenger\n\"\"\")\nasync def marco():\n    return 'polo'\n\n# or\n\n@TextSender(about='An ancient game in modern messenger')\nasync def marco(_):\n    return 'polo'\n```\n\n### Adding new handlers\n\nI want to trigger if someone edits a message. Let's do this.\n\nBy the way, there [are](https://docs.telethon.dev/en/latest/quick-references/events-reference.html) other types of events. So here is an example of how you could use it, currently only `onedit` is supported. But it is implemented with extension in future.\n\n```python\nfrom telthon import events\n\n@TextSender(take_event=False, about=\"\"\"\n\tReply, when someone edits the message\n\"\"\", on_event=events.MessageEdited)\nasync def isaw():\n    return 'I saw what you did here! You bastard!'\n```\n\n### Built-in commands\n\nTo run a command both user and chat need to be allowed to run this command(except if it's you(admin) who is running the command).\n\n* `help`\n```\n    Info to start with\n```\n* `synhelp`\n```\n    Info about syntax rules and some usage examples\n```\n* `acceshelp`\n\n```\n\tGet help about access rights actions\n```\n\n* `commands`\n```\n    Get the list of all commands or info about command\n\n        Commands list:\n\n        `.commands`\n\n        Info about command:\n\n        `.commands commands`\n```\n\n* `handlers`\n```\n    Get the info about handlers.\n    Handler is a reaction to some event:\n\n        Handlers list(divided by event types):\n\n        `.handlers`\n\n        Handlers on specific event type:\n\n        `.handlers onedit`\n\n        Info about handlers(specify event type):\n\n        `.handlers onedit [hndl1 hndl2]`\n```\n* `tags`\n```\n    Get the list of all tags or list of commands tagged,\n\n        Tags list:\n\n        `.tags`\n\n        Commands tagged with `default`:\n\n        `.tags default`\n```\n* `{allow|ban|allowed}{usr|chat}`\n```\n    You can customize access level \n    to all your routines anytime.\n    ------------------------------------\n\n    1. First you need to decide which \n    command to use, start typing '.'\n    2. Then select the access action \n    write one of three: 'ban', 'allow' or\n    'allowed'(to find out the rights)\n    3. Then continue and select one \n    of two: 'chat' or 'usr' entities\n\n    For example: .allowedusr\n    Continue typing, tell what you need...\n    ------------------------------------\n\n    Whatever command you've chosen in\n    the previous paragraph, the interface \n    to it is all the same.\n\n    It depends on type of routine,\n    some examples:\n\n    .allowchat commands [chat1 chat2] [synhelp help]\n\n    Or deduce entity from context,\n    by using $ wildcard.\n    USR: usr you are replying to, or you\n    CHAT: current chat\n\n    .allowedusr handlers $ onedit somehandler\n\n    Apply to all commands, handlers, tags:\n\n    .banusr commands $\n    .allowedchat handlers onedit $\n    .banchat tags $\n\n    Use tags to access whole categories\n    of commands/handlers:\n\n    .allowchat tags $ r[default admin]r\n```\n* `errignore`\n```\n    Ignore a chat when processing commands from\n    banned users. Reduces spam level\n\n        by chatname or id all commands:\n        \n        `.errignore chatname`\n        \n        all chats:\n        \n        `.errignore *`\n        \n        the chat that you are writing this in:\n        \n        `.errignore`\n```\n* `errverbose`\n```\n    Enable chat when processing commands from\n    banned users. Increases spam level, but\n    also increases clarity\n\n        by chatname or id all commands:\n        \n        `.errverbose chatname`\n        \n        all chats:\n        \n        `.errverbose *`\n        \n        the chat that you are writing this in:\n        \n        `.errverbose`\n```\n\n### Useful custom commands\n\n* `tagall`\n\n```\n    Tag all participants in a chat\n```\n\n* `openonline`\n\n```\n\tOpen the file in online service\n\n    (Google Docs, Sheets and Slides currently supported)\n```\n\n* `audiocrop`\n\n```\n\tCrop an  audio track.\n\n    Example:\n\n    .audiocrop 2s 5s\n        \n    the same\n\n    .audiocrop 2000 5000\n```\n\n*  `audioreverse`\n\n```    Reverse an audio track\n\tReverse an audio track\n```\n\n*  `audiodistort`\n\n```\n\tDistort an audio track\n```\n\n# How to customize\n\n## Env\n\nChange `.env` file to fit your needs.\n\n**NB**: `TG_SESSION_PATH` and `IAHR_DATA_FOLDER` are relative to the working directory(`exmpl` or `tests`).\n\n## Config\n\nTo configure use `config.json` file relative to `IAHR_DATA_FOLDER` env var.\n(see example [here](exmpl/etc/config.json))\nOr a function `config` from `iahr.config`. The first variant is preferable,\nbecause it initializes program before it's execution.\n\n## Session file\n\nGo to the session file and modify it's json manually to get what you want.\nIt's path is `${IAHR_DATA_FOLDER}/iahr.session`.\n\n# How to extend\n\n## Creating senders as functions\n\nNo words, just action. For example, here are how `MediaSender` defined.\n\n```python\nfrom iahr.reg import create_sender, any_send, MultiArgs\n\n# self.res - result of a function: MultiArgs object\n# self.event - original event object\nasync def __media_send(self):\n    # MultiArgs contains only `args` - list of args \n    res = self.res.args[0]\n    await any_send(self.event, file=res)\n    \nMediaSender = create_sender('MediaSender', __media_send)\n```\n\nAnd that's it. You could register new functions with `@MediaSender`.\n\n**Note**: args and kwargs you pass to `any_send` after event are all that you pass to [event.message.reply](https://docs.telethon.dev/en/latest/modules/events.html?highlight=reply#telethon.events.chataction.ChatAction.Event.reply). \n\n## Creating senders as classes\n\nTake a look on the [AudioSender](https://github.com/B1Z0N/iahr/blob/77cedfe264ffb9e9121bcf61bd95242859239df8/iahr/commands/audio/utils.py#L57) class.\n\n## Other ways\n\nIf you have more demanding wishes. We are glad to satisfy them. Here is how to initialize it all manually:\n\n```python\nfrom iahr import init\nfrom iahr.run import Manager\nfrom iahr.reg import Register\nfrom iahr.config import IahrConfig\n\n# ...\n# init telethons `client` variable\n# ...\n\napp = Manager()\nregister = Register(client, app)\nIahrConfig.init(app, register)\n```\n\nThat's how `iahr.init` works. But what if you want to create custom Manager and custom Register? We have something for you just overload `ABCManager` and `ABCRegister`. But i'll leave you on your own here. Go check how it works by example in [Manager](iahr/run/manager.py) and [Register](iahr/reg/register.py). \n\n# How to contribute\n\n## Guidelines\n\n### Coding style\n\nUse [yapf](https://github.com/google/yapf) with default settings([pep8](https://www.python.org/dev/peps/pep-0008/)). Be sure to run `yapf -ri *` before pushing. Or use an [online demo](https://yapf.now.sh/).\n\n**Note**: there are errors regarding new [walrus operator](https://medium.com/better-programming/what-is-the-walrus-operator-in-python-5846eaeb9d95) and [f-strings](https://realpython.com/python-f-strings/), just remove them manually and then add it back after formatting.\n\n### Templates\n\nThere are templates for issues and pull requests in here. Use them.\n\n## Error refactoring\n\nThere are much more to learn in the wisdom of python's success. It is much easier to write code(commands in chat) when you have a lot of useful errors appearing when you do something wrong. So it's a major issue to work on. Some ideas on what errors we'd like to provide:\n\n* Incompatible commands error\n\n  When there are more or less args than command can take, we'll print \n  ```\n  {command} takes more/less args, please check your query\n  ```\n\n## New commands\n\nThere is such a small directory as [commands](iahr/commands). And you can fulfill it with whole bunch of other modules containing commands for different topics, like text, photos audiofiles, jokes and pranks, videos and many others, just use your imagination. That's the point!\n\n## Localization\n\nRight now `Iahr` supports english and russian languages.\nYou can provide localization to your own language.\nFor this you need to alter:\n\n* `Iahr` internal messages:\n    create file {yourlang}.py in [iahr/localization](iahr/localization).\n* default commands messages:\n    create according dictionary in [iahr/commands/default/localization.py](iahr/commands/default/localization.py).\n\n## Tests\n\nRight now there are lots of unit tests. Endpoint is a full test coverage. We need to add tests to check if all is working as expected at telegram level. So here how integration testing could be done:\n\n1. [Mock](https://docs.python.org/3/library/unittest.mock.html)\n2. Create two clients and/or use [test servers](https://docs.telethon.dev/en/latest/developing/test-servers.html)\n\n## Ideas\n\n### Build and deployment related\n\n* Script to generate `README.md` from code\n* Generate [docs](https://b1z0n.github.io/iahr/) on commit\n* Reformat code on commit\n* Enable to easily run docker from vscode\n* Add site that allows users to easily \n  * configure and create `iahr` telegram client from web gui\n  * manage commands(for example access rights) from gui\n  * share command sets and include it to their own clients\n* Rerun after code changes script\n\n### Command ideas\n\n* Command that allows to execute regex\n* Typing in chat for specific time\n* Change `tagall` to create multiple messages so that it works\n* Simplify access rights commands interface\n* Add commands to get access rights user and chat lists for specific command\n* Command that lets you define global constants(text, media, people)\n* Remove messages after specific time passed\n* Text to voice\n* Sticker quotes and it's search\n* Overlay two audios\n* Get user location on premise\n\n### Core features\n\n* Dynamic command creation(see branch [alias](https://github.com/B1Z0N/iahr/tree/alias))\n\n  something like `.alias r[oneword x: .concat .split $1]r`  and then `.oneword [nice nice day] =\u003e niceniceday`\n* Autocompletion like in shell with help of some special character(e.g. '-')\n* Does tags enough? If no, you can always implement modules.\n* Save data in telegram, like a permanent storage(implement a db interface?)\n* Formalization of parsing algorithm with lex/yacc\n\n### Documentation\n\n* Document all config.json\n\n### Tests\n\n* Mock telegram api integration tests\n\n# Naming\n\n`Iah` is [egyptian god](https://en.wikipedia.org/wiki/Iah) of the new moon. And in russian language \"echo\" and \"moon\" are homophones. The words that pronounce the same, but have different meaning. So \"echo\" is a prefect synonym to functionality of this framework. It replies to you with your request results. \n\nBut I thought it'll sound more epic with \"r\" at the end. So here is why ^^\n\n# Thanks\n\n* To [Vsevolod Ambros](https://github.com/kraftwerk28), the man the idea of `Iahr` was [stolen](https://github.com/kraftwerk28/tgai28) from.\n\n* To my university/employer, that will drop me out for doing this and not studying/working\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb1z0n%2Fiahr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb1z0n%2Fiahr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb1z0n%2Fiahr/lists"}