Giter Club home page Giter Club logo

userbot's Introduction

userbot

wakatime Crowdin

Commit activity Latest commit Total LoC Code size License Python version black code style Imports: isort

Build status Code quality check Deployment status

The userbot I use with some specific features written in Pyrogram.

Features

Commands

Commands work only when sent by the user who runs userbot. Default command prefix is , unless overriden in config.

Click to expand full command list
List of userbot commands available:

About:
• about — Shows information about this userbot.
• help [command] — Sends help for all commands or for a specific one.
• stats ['bot'|'short'|'full'] — Shows some statistics about this userbot.

Chat administration:
• chatban|chatrestrict <'reply'|user_id|username|user_group> ['0'|'forever'|timespec] ['*'|perms] [reason...] — Restricts or bans a user in a chat.
• chatcleardel — Kicks Deleted Accounts from the chat.
• chatinvite <user_id|username|user_group> ['verify'] — Invites users to the current chat.
• chatunban <'reply'|user_id|username|user_group> — Unbans a user in a chat.
• <in reply> no_react2ban|noreact2ban — Stops react2ban on the message.
• <in reply> pin ['silent'] — Pins the message.
• <in reply> promote <admin_title...> — Promotes a user to an admin without any rights but with title.
• react2ban — Bans a user whoever reacted to the message.
• <in reply> s_pin ['silent'] — Pins the message silently (without returning the result).

Chat info:
• rndinfo ['photo'|'title'] — Sets random chat photo and/or title.
• rndmsg — Sends a random message from the chat.

Colors:
• color <color_spec> — Sends a specified color sample.
• usercolor [user_id|username|user_group] — Sends a color sample of user's color as shown in clients.

Content converters:
• toaudio — Extracts audio from video.
• togif — Converts a video to a mpeg4 gif.
• tosticker ['png'|'webp'] — Converts a photo to a sticker-ready png or webp.
• <in reply> totext — Transcribes speech in voice and video messages to text.

Dice:
• roll|dice <dice_spec> — Rolls dice according to `d20.roll` syntax.

Download:
• download|dl ['single'|'all'] [filename]... — Downloads a file or files.

Hooks:
• hooklist|hook_list — Lists all available hooks.
• hookshere|hooks_here — Lists enabled hooks in the chat.

Language:
• lang [language_code] — Gets or changes the language of the bot for the current chat.

Messages:
• <in reply> copyhere|cphere|cph — Copies replied message to current chat.
• <in reply> delete|delet|del — Deletes replied message for everyone.
• dump [jq_query...] — Dumps entire message or its attribute specified with `jq` syntax.
• userfirstmsg — Looks for the user's very first message in the chat.

Notes:
• get|note|n <key...> — Sends saved note.
• note_del|ndel <key...> — Deletes saved note.
• notes|ns — Shows all saved notes.
• <in reply> save|note_add|nadd <key...> — Saves replied message as note for later use.

Reactions:
• <in reply> r [emoji] — Reacts to a message with a specified emoji or removes any reaction.
• <in reply> rr — Reacts to a message with a random available emoji.
• <in reply> rs — Gets message reactions with users who reacted to it.

Reminders:
• remind <time> [message...] — Sets a reminder in the chat.
• remindme <time> [message...] — Sets a reminder for myself.
• sremind <time> [message...] — Sets a silent reminder in the chat (no confirmation about scheduled message).
• sremindme <time> [message...] — Sets a silent reminder for myself (no confirmation about scheduled message).

Stickers:
• longcat — Sends random longcat.
• rnds <pack_shortlink|pack_alias|emoji> — Sends random sticker from specified pack or one matching specified emoji.

Text converters:
• <in reply> caps — Toggles capslock on the message.
• <in reply> s <args...> — sed-like replacement.
• <in reply> tr ['en'|'ru'] — Swaps keyboard layout from en to ru or vice versa.

Tools:
• cal [month] [year] — Sends a calendar for a specified month and year.
• calc|eval <python_expr...> — Evaluates Python expression.
• exec <python_code...> — Executes Python code.
• <in reply> id — Sends replied user's ID as link.
• ugping <user_group> [text...] — Pings a user group with optional text.

User groups:
• usergroupadd|ugadd <group_name> [user_id|username|user_group]... — Adds a user to the user group for later use with user resolving.
• usergroupdel|ugdel <group_name> [user_id|username|user_group]... — Removes a user from the user group.
• usergrouplist|uglist <group_name> ['resolve'] — Lists the users in the user group.
• usergroups|ugs — Lists all user groups.

Wakatime:
• wakatime|waka — Gets your Wakatime stats for today and the last 7 days.

Hooks (triggers)

Triggers can be enabled by .<hookname>here and disabled by .no<hookname>here. They are disabled everywhere by default. To check if a hook is enabled or disabled, use .hookshere.

  • emojis:
    • Sends a duck emoji (🦆) when someone writes "дак" (pronounced as "duck") or "кря" (pronounces as "krya", English equivalent is "quack")
    • Sends a pancake emoji (🥞) when someone writes "блин" (English equivalent is "pancake", also that's how Russian equivalent to the English "f*ck" may be "censored")
  • tap: Sends a sticker with a finger touching a seal when someone writes "тык" or sends that sticker itself (link to the pack)
  • mibib: Sends a sticker (with 20% chance) with an animated pixelated bear when someone sends that sticker itself (link to the pack)
  • bra: Sends a picture from this Reddit post when someone sends "бра" or "bra"
  • uwu: Sends a picture when someone sends "uwu", "owo", "уву" or "ово"
  • auto_transcribe: Automatically transcribes speech in voice and video messages to text whenever it is sent in the chat

Shortcuts

Shortcuts work only when sent by the user who runs userbot.

Click to expand full shortcut list
  • yt:<id> — Sends a YouTube video with the specified ID
  • @:<id> — Mentions a user with the specified ID
    • @:<id>:<name>@ — Mentions a user with the specified ID with a custom name
  • github:<username> or gh:<username> — Sends a GitHub link to the specified user's profile
    • github:<username>/<repo> — ... to the specified repo, <repo> can be "@" which means "same as <username>"
    • github:<username>/<repo>:/<path> — ... to the specified path on the default branch
    • github:<username>/<repo>:/<path>#<line1> — ... to the specified line in file
    • github:<username>/<repo>:/<path>#<line1>-<line2> — ... to the specified lines in file
    • github:<username>/<repo>@<branch-or-commit> — ... to the specified branch or commit of the repo
    • github:<username>/<repo>@<branch-or-commit>:/<path> — ... to the specified path on the branch or commit
    • github:<username>/<repo>@<branch-or-commit>:/<path>#<line1> — ... to the specified line in file
    • github:<username>/<repo>@<branch-or-commit>:/<path>#<line1>-<line2> — ... to the specified lines in file
    • github:<username>/<repo>#<issue-or-pr> — ... to the specified issue or pull request
  • :uwu: — Sends a 🥺👉👈 emoji
    • :uwu<number>: — Sends a 👉👈 emoji with the specified number of finger pairs
  • google://<query>/ — Sends a link to a Google search for the specified query
  • :shrug: — Sends a shrug kaomoji ¯\_(ツ)_/¯
  • n://<key>/ — Sends a saved note with the specified key
  • xkcd:<number> — Sends a link to XKCD comic with the specified number
  • pypi://<package>/ or pip://<package>/ — Sends a link to PyPI page of the specified package
  • tg:<username>/<message-id> or tg:<username>#<message-id> — Sends a link to the specified message in the specified chat

Installation and running

  1. Copy .env.example file to .env and modify for yourself.
  2. Make sure docker is installed, then run docker-compose build.
  3. Go through interactive authentication (needed only once as /data is mounted as docker volume) by running docker-compose run --rm main python -m userbot.
  4. Stop the script by pressing Ctrl+C as soon as you see Bot started message in console.
  5. Run docker-compose up -d to run the userbot in the background.
  6. To run migrations, run docker-compose run --rm --entrypoint /usr/bin/env main python3.11 -m userbot.migrations. Userbot must be stopped before running any migrations to prevent conflicts.

Contributing

TODO

userbot's People

Contributors

dependabot[bot] avatar evgfilim1 avatar krau5 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

userbot's Issues

Integrate mypy

Start here

diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index 833fcde..77cf54c 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -45,6 +45,7 @@ jobs:
         run: |
           isort --check --diff userbot
           black --check --diff userbot
+          mypy userbot
 
       - name: Check message catalog template is up-to-date
         run: python potctl.py --diff
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 390cec5..41f7d7e 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,3 +1,5 @@
 Babel~=2.10.3
 black~=22.10.0
 isort~=5.10.1
+mypy~=0.982
+types-aiofiles~=22.1.0
diff --git a/pyproject.toml b/pyproject.toml
index bcb9333..e1c88f9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,3 +7,52 @@ line_length = 100
 py_version = '310'  # (2022-10-28) isort 5.10.1 doesn't support 3.11
 profile = 'black'
 known_first_party = ['userbot']
+
+[tool.mypy]
+# Config file
+warn_unused_configs = true
+
+# Import discovery
+namespace_packages = true
+
+# Platform configuration
+python_version = "3.11"
+
+# Disallow dynamic typing
+#disallow_any_explicit = true
+disallow_any_generics = true
+disallow_subclassing_any = true
+
+# Untyped definitions and calls
+disallow_untyped_calls = true
+disallow_untyped_defs = true
+disallow_incomplete_defs = true
+check_untyped_defs = true
+disallow_untyped_decorators = true
+
+# None and Optional handling
+no_implicit_optional = true
+
+# Configuring warnings
+warn_redundant_casts = true
+warn_unused_ignores = true
+warn_return_any = true
+warn_unreachable = true
+
+# Miscellaneous strictness flags
+local_partial_types = true
+# Pyrogram doesn't explicitly export some attributes, so this has to be disabled
+no_implicit_reexport = false
+strict_equality = true
+strict = true
+
+# Configuring error messages
+show_error_context = true
+show_column_numbers = true
+show_error_codes = true
+pretty = true
+
+# Advanced options
+plugins = [
+]
+warn_incomplete_stub = true

Allow running commands from drafts

This will require wrapping the original message class from Pyrogram into something that will behave almost the same but will support drafts.

Handling requires registering RawUpdateHandler like this:

client.add_handler(
RawUpdateHandler(partial(react2ban_raw_reaction_handler, storage=storage)),
group=1,
)

Usage:
async def react2ban_raw_reaction_handler(
client: Client,
update: base.Update,
users: dict[int, types.User],
_: dict[int, types.Chat | types.Channel],
*,
storage: Storage,
) -> None:
if not isinstance(update, types.UpdateMessageReactions):
raise ContinuePropagation() # don't consume an update here, it's not for this handler

UpdateDraftMessage will be received when something is saved as a draft:
https://docs.pyrogram.org/telegram/types/update-draft-message#pyrogram.raw.types.UpdateDraftMessage

Implementing this may open new abilities like silent execution without having to edit sources, looped execution, etc.

`prefix` isn't honored in some places

  • When looking for .help command:
    if args := command.args:
    for h in self._handlers:
    for cmd in h.commands:
    match cmd:
    case re.Pattern() as pattern:
    matches = pattern.fullmatch(args) is not None
    case str():
    matches = cmd == args
    case _:
    raise AssertionError(f"Unexpected command type: {type(cmd)}")
    if matches:
    usage = h.format_usage(full=True)
    return _("<b>Help for {args}:</b>\n{usage}").format(
    args=html.escape(args),
    usage=html.escape(usage),
    )
  • When checking command conflicts while registering:
    for handler in self._handlers:
    for cmd in handler.commands:
    if cmd in commands:
    raise ValueError(f"Duplicate command: {cmd}")

Search docs

.pydoc <query> — Search Python documentation

.tbapidoc <query> — Search Telegram Bot API documentation

Runtime hooks (triggers)

.rhadd <reply> <key> <text...> — adds a runtime trigger <key> on <text> that sends <reply>

.rhs — list all runtime triggers

.rhdel <key> — removes a runtime trigger

Message edits may be skipped by clients

Some clients have a bug when they for some reason don't update a message edited by userbot. Adding a small (~0.1–0.25s) delay would help, I guess.

Chat:
Not edited message
Admin log:
Admin log with edit event

Bot stats

.stats — show some stats for the bot and the user

Example output:

⚙ Uptime: 1h2m3s
⭐️ Doesn't have premium
💬 Total chats: 1000
💬 Unread: 2
📥 Archived chats: 50
👤 Private chats: 400
👥 Groups: 400
📢 Channels: 200
🎞 Saved GIFs: 300
📑 Saved stickers: 200
🕒 Archived stickers: 300
...

Take appropriate icons from https://t.me/addemoji/IconsInTg for premium users
image

Ban until specific date

Same behavior as in .remind and .remindme

userbot/userbot/utils.py

Lines 109 to 117 in 4bfb02f

def parse_timespec(now: datetime, timespec: str) -> datetime:
"""Parse a time specification and return target datetime.
The time specification is a string of the form:
– HH:MM
– YYYY-MM-DD_HH:MM
– N[smhdwy]
– N[smhdwy]N[smhdwy]...
"""

Clear service messages for a period

.clearsvcs [period] — Clear service messages for a period.

period can be a timedelta (e.g. "1d3h") or a time string (e.g. "12:30" or "2022-12-31_23:59").
If period is not specified, assume "1d"

userbot/userbot/utils.py

Lines 109 to 117 in 4bfb02f

def parse_timespec(now: datetime, timespec: str) -> datetime:
"""Parse a time specification and return target datetime.
The time specification is a string of the form:
– HH:MM
– YYYY-MM-DD_HH:MM
– N[smhdwy]
– N[smhdwy]N[smhdwy]...
"""

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.