Code Monkey home page Code Monkey logo

iahr's Introduction

About

Telegram chat command execution framework based on telethon library

Quick simple demo

Basically 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.

You can call a commands predefined in your files with . operator:

image

But it is much more than that! This projects provides:

  • Built-in access permitions. Yes, you may allow/ban other users to call your commands. Just like in Linux.
  • Built-in help on commands.
  • Allows you to access any of Telegram API via Telethon library. Like invoke a command once someone edits a message. Or change image in your profile whenever someone else does this.
  • Grants solid support for logging.
  • Graceful and in-chat handling of errors.
  • Serialization and deserialization of state on exit.
  • Localization to popular languages.
  • You may customize nearly EVERYTHING(yes, even syntax) via config.

Warning

Be careful, do not violate Telegram's Terms of service.

If you use the Telegram API for flooding, spamming, faking subscriber and view counters of channels, you will be banned forever. 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.

Contents

What is it

How to start

Docker

cp .env_exmpl .env

# fulfill .env with your data
# ...
# run exmpl(as a daemon)

docker-compose up iahr_exmpl

# run tests(optional)

docker-compose up iahr_tests

P. S. try adding sudo if something is faulty

Basic concepts

Routines

Routine is your python function with some metadata that can be accessed from telegram

There are two type of routines:

  • Commands - text-based routines, call it by typing it's name in message.
  • Handlers - reactions to some events(e.g. onedit)

Senders

Senders decorators are used to register your routine. Currently there are three senders:

  • VoidSender - your function returns nothing
  • TextSender - it returns str
  • MediaSender - return file-like object

You can import it from iahr.reg. And easily create new senders(more on it later, below).

Events

Every function, if not specified otherwise, takes event object from telethon as first parameter. This helps to provide custom behavior and enables more freedom in terms of an API.

How it works

You 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.

For example:

.upper word ~> WORD

.lower wORd ~> word

and the most epic one(attention!):

.lower .upper word ~> word

- WOW, isn't it?

- It is!

And this is just text examples, you can use any data format to pass in/out of commands.

Adding new commands

I'm feeling lonely and bored, so i want to be able to play my favorite game marcopolo with myself in any chat.

Just add new function, like you would do it in python.

def marco():
    return 'polo'

And that's wrong!. Stop, not so fast. It lacks three more things:

  1. Iahr doesn't know anything about your code. So it should be registered.
  2. Use async def because it's faster
  3. You need more info to reply to a message, just an additional parameter: event

So now:

@VoidSender()
async def marco(event):
	await event.message.reply('polo')

That's it. It automatically adds your command to the list of commands on .commands. But there is more than one way to do it right:

from telethon.events import NewMessage as newmsg

@TextSender(
	name='marco', # how you will call it in chat
    about='An ancient game in modern messenger', # description on `.help marco`
    take_event=False, # whether it takes event, default - True
    multiret=False, # whether it returns one value, or multiple, default - False
    on_event=newmsg, # what event it should be called on, default - events.NewMessage
    tags={'games'}) # tags facility to quickly search for commands
async def marco():
    return 'polo'

NB: don't forget multiret=True when you want to return list of values instead of one value: list.


Well 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:

@TextSender(take_event=False, about="""
	An ancient game in modern messenger
""")
async def marco():
    return 'polo'

# or

@TextSender(about='An ancient game in modern messenger')
async def marco(_):
    return 'polo'

Adding new handlers

I want to trigger if someone edits a message. Let's do this.

By the way, there are 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.

from telthon import events

@TextSender(take_event=False, about="""
	Reply, when someone edits the message
""", on_event=events.MessageEdited)
async def isaw():
    return 'I saw what you did here! You bastard!'

Built-in commands

To 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).

  • help
    Info to start with
  • synhelp
    Info about syntax rules and some usage examples
  • acceshelp
	Get help about access rights actions
  • commands
    Get the list of all commands or info about command

        Commands list:

        `.commands`

        Info about command:

        `.commands commands`
  • handlers
    Get the info about handlers.
    Handler is a reaction to some event:

        Handlers list(divided by event types):

        `.handlers`

        Handlers on specific event type:

        `.handlers onedit`

        Info about handlers(specify event type):

        `.handlers onedit [hndl1 hndl2]`
  • tags
    Get the list of all tags or list of commands tagged,

        Tags list:

        `.tags`

        Commands tagged with `default`:

        `.tags default`
  • {allow|ban|allowed}{usr|chat}
    You can customize access level 
    to all your routines anytime.
    ------------------------------------

    1. First you need to decide which 
    command to use, start typing '.'
    2. Then select the access action 
    write one of three: 'ban', 'allow' or
    'allowed'(to find out the rights)
    3. Then continue and select one 
    of two: 'chat' or 'usr' entities

    For example: .allowedusr
    Continue typing, tell what you need...
    ------------------------------------

    Whatever command you've chosen in
    the previous paragraph, the interface 
    to it is all the same.

    It depends on type of routine,
    some examples:

    .allowchat commands [chat1 chat2] [synhelp help]

    Or deduce entity from context,
    by using $ wildcard.
    USR: usr you are replying to, or you
    CHAT: current chat

    .allowedusr handlers $ onedit somehandler

    Apply to all commands, handlers, tags:

    .banusr commands $
    .allowedchat handlers onedit $
    .banchat tags $

    Use tags to access whole categories
    of commands/handlers:

    .allowchat tags $ r[default admin]r
  • errignore
    Ignore a chat when processing commands from
    banned users. Reduces spam level

        by chatname or id all commands:
        
        `.errignore chatname`
        
        all chats:
        
        `.errignore *`
        
        the chat that you are writing this in:
        
        `.errignore`
  • errverbose
    Enable chat when processing commands from
    banned users. Increases spam level, but
    also increases clarity

        by chatname or id all commands:
        
        `.errverbose chatname`
        
        all chats:
        
        `.errverbose *`
        
        the chat that you are writing this in:
        
        `.errverbose`

Useful custom commands

  • tagall
    Tag all participants in a chat
  • openonline
	Open the file in online service

    (Google Docs, Sheets and Slides currently supported)
  • audiocrop
	Crop an  audio track.

    Example:

    .audiocrop 2s 5s
        
    the same

    .audiocrop 2000 5000
  • audioreverse
	Reverse an audio track
  • audiodistort
	Distort an audio track

How to customize

Env

Change .env file to fit your needs.

NB: TG_SESSION_PATH and IAHR_DATA_FOLDER are relative to the working directory(exmpl or tests).

Config

To configure use config.json file relative to IAHR_DATA_FOLDER env var. (see example here) Or a function config from iahr.config. The first variant is preferable, because it initializes program before it's execution.

Session file

Go to the session file and modify it's json manually to get what you want. It's path is ${IAHR_DATA_FOLDER}/iahr.session.

How to extend

Creating senders as functions

No words, just action. For example, here are how MediaSender defined.

from iahr.reg import create_sender, any_send, MultiArgs

# self.res - result of a function: MultiArgs object
# self.event - original event object
async def __media_send(self):
    # MultiArgs contains only `args` - list of args 
    res = self.res.args[0]
    await any_send(self.event, file=res)
    
MediaSender = create_sender('MediaSender', __media_send)

And that's it. You could register new functions with @MediaSender.

Note: args and kwargs you pass to any_send after event are all that you pass to event.message.reply.

Creating senders as classes

Take a look on the AudioSender class.

Other ways

If you have more demanding wishes. We are glad to satisfy them. Here is how to initialize it all manually:

from iahr import init
from iahr.run import Manager
from iahr.reg import Register
from iahr.config import IahrConfig

# ...
# init telethons `client` variable
# ...

app = Manager()
register = Register(client, app)
IahrConfig.init(app, register)

That'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 and Register.

How to contribute

Guidelines

Coding style

Use yapf with default settings(pep8). Be sure to run yapf -ri * before pushing. Or use an online demo.

Note: there are errors regarding new walrus operator and f-strings, just remove them manually and then add it back after formatting.

Templates

There are templates for issues and pull requests in here. Use them.

Error refactoring

There 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:

  • Incompatible commands error

    When there are more or less args than command can take, we'll print

    {command} takes more/less args, please check your query
    

New commands

There is such a small directory as 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!

Localization

Right now Iahr supports english and russian languages. You can provide localization to your own language. For this you need to alter:

Tests

Right 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:

  1. Mock
  2. Create two clients and/or use test servers

Ideas

Build and deployment related

  • Script to generate README.md from code
  • Generate docs on commit
  • Reformat code on commit
  • Enable to easily run docker from vscode
  • Add site that allows users to easily
    • configure and create iahr telegram client from web gui
    • manage commands(for example access rights) from gui
    • share command sets and include it to their own clients
  • Rerun after code changes script

Command ideas

  • Command that allows to execute regex
  • Typing in chat for specific time
  • Change tagall to create multiple messages so that it works
  • Simplify access rights commands interface
  • Add commands to get access rights user and chat lists for specific command
  • Command that lets you define global constants(text, media, people)
  • Remove messages after specific time passed
  • Text to voice
  • Sticker quotes and it's search
  • Overlay two audios
  • Get user location on premise

Core features

  • Dynamic command creation(see branch alias)

    something like .alias r[oneword x: .concat .split $1]r and then .oneword [nice nice day] => niceniceday

  • Autocompletion like in shell with help of some special character(e.g. '-')

  • Does tags enough? If no, you can always implement modules.

  • Save data in telegram, like a permanent storage(implement a db interface?)

  • Formalization of parsing algorithm with lex/yacc

Documentation

  • Document all config.json

Tests

  • Mock telegram api integration tests

Naming

Iah is egyptian god 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.

But I thought it'll sound more epic with "r" at the end. So here is why ^^

Thanks

  • To Vsevolod Ambros, the man the idea of Iahr was stolen from.

  • To my university/employer, that will drop me out for doing this and not studying/working

iahr's People

Contributors

b1z0n avatar dependabot[bot] avatar kraftwerk28 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.