Skip to content

Commit

Permalink
Merge pull request #66 from ksdfg/command_description
Browse files Browse the repository at this point in the history
Use class for storing commands descriptions
  • Loading branch information
ksdfg authored May 15, 2022
2 parents 02cc055 + c775c02 commit 0bbaf06
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 168 deletions.
39 changes: 22 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/ksdfg/neko-chan-telebot/graphs/commit-activity)
![GitHub contributors](https://img.shields.io/github/contributors/ksdfg/neko-chan-telebot)
![GitHub last commit](https://img.shields.io/github/last-commit/ksdfg/neko-chan-telebot)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
![GitHub pull requests](https://img.shields.io/github/issues-pr-raw/ksdfg/neko-chan-telebot)
![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed-raw/ksdfg/neko-chan-telebot)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
![GitHub pull requests](https://img.shields.io/github/issues-pr-raw/ksdfg/neko-chan-telebot)
![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed-raw/ksdfg/neko-chan-telebot)
![GitHub](https://img.shields.io/github/license/ksdfg/neko-chan-telebot)

Updated version of [SkittBot](https://github.com/skittles9823/SkittBot) with some features from
[skitt_bot](https://github.com/skittles9823/skitt_bot) to work with latest version of python-telegram-bot.
Updated version of [SkittBot](https://github.com/skittles9823/SkittBot) with some features from
[skitt_bot](https://github.com/skittles9823/skitt_bot) to work with the latest version of python-telegram-bot.
Now has quite a few original features as well.

## Config
Expand All @@ -18,14 +18,19 @@ You can set config variables in your environment, store them in a `.env` file in
commandline arguments while running the bot.

The config variables are as follows :-

- `ADMIN` : The user ID of the person managing the bot
- `TOKEN` : Telegram bot token
- `DATABASE_NAME` : The name of the database you are using
- `DATABASE_URL` : The MongoDB host URI (if not given, bot will try to connect to local MongoDB instance at default port)
- `DATABASE_URL` : The MongoDB host URI (if not given, bot will try to connect to local MongoDB instance at default
port)
- `WEBHOOK_URL` : The URL your webhook should connect to (Default value is `False`, which will disable webhook)
- `PORT` : Port to use for your webhooks (Default value is `80`)
- `LOAD` : Space separated list of modules (`.py` file name) you would like to load (Default value is `False`, which will just load all modules)
- `NO_LOAD` : Space separated list of modules (`.py` file name) you would like NOT to load (Default value is `False`, which will not skip any modules
- `LOAD` : Space separated list of modules (`.py` file name) you would like to load (Default value is `False`, which
will just load all modules)
- `NO_LOAD` : Space separated list of modules (`.py` file name) you would like NOT to load (Default value is `False`,
which will not skip any modules)
- `PREVIEW_COMMANDS` : Space separated list of commands you would like to preview in the bot's commands menu in TG
- `SUPERUSERS` : Space separated list of user IDs for which some exceptions won't work

## Installing Dependencies
Expand All @@ -50,15 +55,15 @@ set the `WEBHOOK_URL` to the heroku application URL (generally https://app_name.

## Note

For the first 70 commits or so, I didn't know that the concept of co-authorship existed.... so while the base logic is
the same as the above mentioned repositories with some changes that I thought were needed, the commit authorship for
those is shown as mine. Now there's a lot of stuff within those 70 commits that actually are my own idea (like the
`exceptions` and `nhentai` modules, as well as the mongodb schemas for everything) and it would honestly be a pain to go
through all 70 commits and figure out which to amend and change authorship of to add co-authorship to
For the first 70 commits or so, I didn't know that the concept of co-authorship existed.... so while the base logic is
the same as the above-mentioned repositories with some changes that I thought were needed, the commit authorship for
those are shown as mine. Now there's a lot of stuff within those 70 commits that actually are my own idea (like the
`exceptions` and `nhentai` modules, as well as the mongodb schemas for everything) and it would honestly be a pain to go
through all 70 commits and figure out which to amend and change authorship of to add co-authorship to
[Rhyse Simpson](https://github.com/skittles9823)

I got to talk to him on telegram and he said it was kinda OK to let the current history be and I can add him as
co-author on all future commits where I'm taking his code and either just updating it to work with latest version of
`python-telegram-bot` or editing it as I see fit. So please don't flame me too much for essentially kanging those
entire projects :P This bot was kinda meant more for me to have everything I want in a single place and on the way
I got to talk to him on telegram, and he said it was kinda OK to let the current history be and that I can add him as
co-author on all future commits where I'm taking his code and either just updating it to work with the latest version of
`python-telegram-bot` or editing it as I see fit. So please don't flame me too much for essentially kanging those
entire projects :P This bot was kinda meant more for me to have everything I want in a single place and on the way
somehow became about wanting to kick @NotAMemeBot from a group I'm on (yeah, I'm kinda irrational that way).
3 changes: 3 additions & 0 deletions telebot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def __init__(
port=False,
load=None,
no_load=None,
preview_commands=None,
superusers=None,
):
"""
Expand Down Expand Up @@ -42,6 +43,7 @@ def __init__(

self.LOAD = load
self.NO_LOAD = no_load
self.PREVIEW_COMMANDS = preview_commands

self.SUPERUSERS = superusers

Expand All @@ -57,6 +59,7 @@ def __init__(
port=config("PORT", default=80, cast=int),
load=config("LOAD", default=False, cast=lambda x: x.split(" ") if x else False),
no_load=config("NO_LOAD", default=False, cast=lambda x: x.split(" ") if x else False),
preview_commands=config("PREVIEW_COMMANDS", default=[], cast=lambda x: x.split(" ") if x else []),
superusers=config("SUPERUSERS", default=[], cast=lambda x: map(int, x.split(" "))),
)

Expand Down
31 changes: 4 additions & 27 deletions telebot/__main__.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,15 @@
from mongoengine import connect
from telegram import BotCommand

from telebot import updater, config
from telebot.modules import imported_mods
from telebot.modules import imported_mods, bot_commands

# log all imported modules
print("Imported modules :", ", ".join(sorted(mod.__mod_name__ for mod in imported_mods.values())))

# set bot commands
COMMANDS = []

# add commands from basics
if "Basics" in [mod.__mod_name__ for mod in imported_mods.values()]:
COMMANDS += [
BotCommand(command="talk", description="[<word>] : Say <word> (or meow, if not given) rendum number of times"),
BotCommand(command="modules", description="List all the active modules"),
BotCommand(
command="help", description="[<modules list>] : Display the help text to understand how to use this bot"
),
BotCommand(command="id", description="[<reply|username>] : Get details of chat and a user or yourself"),
]

# add commands from stickers
if "Stickers" in [mod.__mod_name__ for mod in imported_mods.values()]:
COMMANDS.append(
BotCommand(command="kang", description="<reply> [<emoji>] : Reply to a sticker to add it to your pack")
)

# add commands from delete
if "Delete" in [mod.__mod_name__ for mod in imported_mods.values()]:
COMMANDS.append(BotCommand(command="del", description="<reply> : delete the quoted message."))

if __name__ == "__main__":
updater.bot.set_my_commands(COMMANDS) # set bot commands to be displayed
# set bot commands to be displayed
print("Commands set :", *(cmd.command for cmd in bot_commands))
updater.bot.set_my_commands(bot_commands)

# connect to database
connect(config.DB_NAME, "default", host=config.DB_URI)
Expand Down
8 changes: 8 additions & 0 deletions telebot/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import importlib
from os.path import dirname, basename, isfile

from telegram import BotCommand

from telebot import config

# get names of all the module .py files currently in the repo
Expand All @@ -12,6 +14,7 @@

# Import all modules
imported_mods = {}
bot_commands: list[BotCommand] = []
for module_name in ALL_MODULES:
# check whether module is to be loaded or not
if (config.LOAD and module_name not in config.LOAD) or (config.NO_LOAD and module_name in config.NO_LOAD):
Expand All @@ -23,3 +26,8 @@
if not hasattr(imported_module, "__mod_name__"):
imported_module.__mod_name__ = imported_module.__name__.split(".")[-1]
imported_mods[imported_module.__mod_name__.lower()] = imported_module

# add bot commands
for cmd in imported_module.__commands__:
if cmd.command in config.PREVIEW_COMMANDS:
bot_commands.append(BotCommand(command=cmd.command, description=cmd.bot_command_description()))
72 changes: 53 additions & 19 deletions telebot/modules/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
get_user_from_message,
UserError,
UserRecordError,
CommandDescription,
)


Expand Down Expand Up @@ -573,27 +574,60 @@ def pin(update: Update, context: CallbackContext):
)


__help__ = """
- /pin `<reply> [silent|quiet]` : pin replied message in the chat.
***Admin only :***
- /promote `<reply|username> [<title>]` : promotes a user (whose username you've given as argument, or whose message you are quoting) to admin
- /demote `<reply|username>` : demotes an admin (whose username you've given as argument, or whose message you are quoting)
- /mute `<reply|username> [x<m|h|d>]` : mutes a user (whose username you've given as argument, or whose message you are quoting) for x time, or until they are un-muted. m = minutes, h = hours, d = days.
- /unmute `<reply|username>`: un-mutes a user (whose username you've given as argument, or whose message you are quoting)
- /ban `<reply|username> [x<m|h|d>]`: ban a user from the chat (whose username you've given as argument, or whose message you are quoting) for x time, or until they are added back. m = minutes, h = hours, d = days.
- /kick `<reply|username>` : kick a user from the chat (whose username you've given as argument, or whose message you are quoting)
__mod_name__ = "Admin"

If you add an exception to `admin`, I will allow admins to execute commands even if they don't have the individual permissions.
"""
__exception_desc__ = (
"If you add an exception to `admin`, I will allow admins to execute commands even if they don't have the "
"individual permissions."
)

__mod_name__ = "Admin"
__commands__ = [
CommandDescription(
command="pin", args="<reply> [silent|quiet]", description="pin replied message in the chat", is_admin=True
),
CommandDescription(
command="promote",
args="<reply|username> [<title>]",
description="promotes a user (whose username you've given as argument, or whose message you are quoting) to admin",
is_admin=True,
),
CommandDescription(
command="demote",
args="<reply|username>",
description="demotes an admin (whose username you've given as argument, or whose message you are quoting)",
is_admin=True,
),
CommandDescription(
command="mute",
args="<reply|username> [x<m|h|d>]",
description=(
"mutes a user (whose username you've given as argument, or whose message you are quoting) for x time, "
"or until they are un-muted. m = minutes, h = hours, d = days."
),
is_admin=True,
),
CommandDescription(
command="unmute",
args="<reply|username>",
description="un-mutes a user (whose username you've given as argument, or whose message you are quoting)",
is_admin=True,
),
CommandDescription(
command="ban",
args="<reply|username> [x<m|h|d>]",
description=(
"ban a user from the chat (whose username you've given as argument, or whose message you are quoting) "
"for x time, or until they are added back. m = minutes, h = hours, d = days."
),
is_admin=True,
),
CommandDescription(
command="kick",
args="<reply|username>",
description="kick a user from the chat (whose username you've given as argument, or whose message you are quoting)",
is_admin=True,
),
]

# create handlers
dispatcher.add_handler(CommandHandler("promote", promote, run_async=True))
Expand Down
70 changes: 44 additions & 26 deletions telebot/modules/basics.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import defaultdict
from random import choice

from emoji import emojize
Expand All @@ -7,15 +8,15 @@

from telebot import updater, dispatcher
from telebot.modules import imported_mods
from telebot.utils import bot_action, get_user_from_message, UserError, UserRecordError
from telebot.utils import bot_action, get_user_from_message, UserError, UserRecordError, CommandDescription

# default Start Text

START_TEXT = emojize(
f"""
NyaHello World! :cat:
I'm `{updater.bot.first_name}`, a cute little bot that does rendum shit rn.
I'm *{updater.bot.first_name}*, a cute little bot that does rendum shit.
""",
use_aliases=True,
)
Expand Down Expand Up @@ -52,28 +53,40 @@ def help(update: Update, context: CallbackContext):
:param update: object representing the incoming update.
:param context: object containing data about the command call.
"""
text_blob = START_TEXT + "\n_Use following commands to use me_ (*blush*):\n"
help_texts: dict[str, dict[str, list[CommandDescription] | str | None]] = defaultdict(lambda: {})

if not context.args:
# meme descriptions of basic commands
text_blob += """
- /help `[<modules list>]` : Recursion ftw
- /start : Turn me on
- /talk `[<word>]` : Make me meow... if you tell me what to meow then I'll do that too
- /modules : Let me tell you what all I can do to please you
"""
help_texts[""]["command_descriptions"] = [
CommandDescription(command="start", description="Start the bot! Gives a small welcome message"),
CommandDescription(command="help", args="[<modules list>]", description="Recursion ftw"),
CommandDescription(command="modules", description="List all the active modules"),
CommandDescription(
command="talk", args="[<word>]", description="Say <word> (or meow, if not given) rendum number of times"
),
]
else:
# add help strings of all imported modules too
for module in context.args:
try:
mod = imported_mods[module.lower()]
text_blob += f"\n`{mod.__mod_name__}`\n{mod.__help__}"
help_texts[mod.__mod_name__]["command_descriptions"] = [cd for cd in mod.__commands__]
if hasattr(mod, "__exception_desc__"):
help_texts[mod.__mod_name__]["exception_desc"] = mod.__exception_desc__
except KeyError:
continue

# initialize the text blob with start texts
text_blob = START_TEXT + "\n_Use following commands to use me_ (*blush*):"

# append help texts for all the modules
for mod_name, values in help_texts.items():
if mod_name:
text_blob += f"\n\n*{mod_name}*"
text_blob += "\n\n" + "\n\n".join(cd.help_text() for cd in values["command_descriptions"])
if values.get("exception_desc"):
text_blob += f"\n\n{values['exception_desc']}"

# Add informational footer
text_blob += (
"\n\nAll arguments that are mentioned as list are just space separated words.\n\n"
Expand Down Expand Up @@ -162,19 +175,24 @@ def info(update: Update, context: CallbackContext):

__mod_name__ = "Basics"

__help__ = """
- /help `[<modules list>]` : Display the help text to understand how to use this bot
- /start : Start the bot! Gives a small welcome message
- /talk `[<word>]` : Say <word> (or meow, if not given) rendum number of times
- /modules : List all the active modules
- /id `[<reply|username>]` : Get details of current chat and a user (by replying to their message or giving their username) or yourself
- /fileid `<reply>` : Get file ID of the file in the quoted message
"""
__commands__ = [
CommandDescription(
command="help", args="[<modules list>]", description="Display the help text to understand how to use this bot"
),
CommandDescription(command="start", description="Start the bot! Gives a small welcome message"),
CommandDescription(
command="talk", args="[<word>]", description="Say <word> (or meow, if not given) rendum number of times"
),
CommandDescription(command="modules", description="List all the active modules"),
CommandDescription(
command="id",
args="[<reply|username>]",
description="Get details of current chat and a user (by replying to their message or giving their username) or yourself",
),
CommandDescription(
command="fileid", args="<reply|username>", description="Get file ID of the file in the quoted message"
),
]

# create handlers
dispatcher.add_handler(CommandHandler("start", start, run_async=True))
Expand Down
15 changes: 13 additions & 2 deletions telebot/modules/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
from telegram.ext import CallbackContext, CommandHandler

from telebot import dispatcher
from telebot.modules.db.exceptions import get_command_exception_chats
from telebot.modules.db.users import add_user
from telebot.utils import (
check_user_admin,
check_bot_admin,
bot_action,
check_reply_to_message,
CommandDescription,
)
from telebot.modules.db.exceptions import get_command_exception_chats
from telebot.modules.db.users import add_user


def check_bot_can_delete(func: Callable):
Expand Down Expand Up @@ -140,6 +141,16 @@ def purge(update: Update, context: CallbackContext):

__mod_name__ = "Delete"

__exception_desc__ = (
"If you add an exception to `delete`, I will allow admins to execute commands even if they don't have the "
"permission to delete messages."
)

__commands__ = [
CommandDescription(command="del", args="<reply>", description="delete the quoted message"),
CommandDescription(command="purge", args="<reply> [silent|quiet]", description="delete the quoted message"),
]

# create handlers
dispatcher.add_handler(CommandHandler("del", delete, run_async=True))
dispatcher.add_handler(CommandHandler("delete", delete, run_async=True))
Expand Down
Loading

0 comments on commit 0bbaf06

Please sign in to comment.