import html import googletrans import octobot import octobot.localization translator = googletrans.Translator() inf = octobot.PluginInfo(octobot.localizable("Google Translate")) TRANSLATION_TEMPLATE = octobot.localizable( "From <i>{source_language}</i> to <i>{target_language}</i>\n<code>{text}</code>" ) @octobot.CommandHandler( ["tl", "translate"], description=octobot.localizable("Translates text using Google Translate")) def gtl(bot: octobot.OctoBot, context: octobot.Context): if context.update.message is not None and context.update.message.reply_to_message is not None: reply = context.update.message.reply_to_message if reply.caption is not None: text = reply.caption else: text = reply.text text_type = "reply" else: text = str(context.query) text_type = "args" source_language = None
import octobot import telegram inf = octobot.PluginInfo(name=octobot.localizable("Admin cache utils")) @octobot.CommandHandler( ["cache_check", "cache_chk"], description=octobot.localizable("Check group admins cache")) @octobot.permissions(is_admin=True) @octobot.supergroup_only def cache_chk(bot, context): cache_msg = [] cache_msg.append( context.localize("Cache database availability: {}").format( octobot.Database.redis is not None)) if octobot.Database.redis is not None: cache_msg.append( context.localize("Time until current cache death: {}").format( octobot.Database.redis.ttl(octobot._perm_db_entry( context.chat)))) cache_msg.append( context.localize("To reset cache use /cache_reset command")) context.reply("\n".join(cache_msg)) @octobot.CommandHandler("cache_reset", "Resets cache") @octobot.permissions(is_admin=True) @octobot.supergroup_only def cache_reset(bot, context): octobot.reset_cache(context.chat)
# OR OTHER DEALINGS IN THE SOFTWARE. import logging import re import requests from babel.numbers import format_currency, format_decimal, get_currency_name from settings import Settings import octobot plugin = octobot.PluginInfo(name="Currency Converter") CURR_TEMPLATE = octobot.localizable(""" %(in)s = %(out)s <a href="http://free.currencyconverterapi.com/">Powered by Currency convert API</a> """) LOGGER = plugin.logger if Settings.currency_converter_apikey == "": plugin.state = octobot.PluginStates.disabled plugin.state_description = "API Key is not set. Get it @ https://free.currencyconverterapi.com/" def get_currency_data(): r = octobot.Database.get_cache( "https://free.currconv.com/api/v7/currencies", params={"apiKey": Settings.currency_converter_apikey}) if not r.ok: LOGGER.warning( "Failed to get currency list, conversion using symbols won't work")
import octobot from settings import Settings plugin = octobot.PluginInfo("Spamwatch") def kick(bot: octobot.OctoBot, chat: telegram.Chat, user: telegram.User): bot.unban_chat_member(chat.id, user.id) def ban(bot: octobot.OctoBot, chat: telegram.Chat, user: telegram.User): bot.kick_chat_member(chat.id, user.id) VALID_ACTIONS = { "kick": (octobot.localizable( "Users will be kicked from this chat if they are banned in SpamWatch"), kick), "ban": (octobot.localizable( "Users will be banned from this chat if they are banned in SpamWatch"), ban), "nothing": (octobot.localizable("SpamWatch plugin is disabled in this chat."), ...) } if Settings.spamwatch.default_action not in VALID_ACTIONS: plugin.state = octobot.PluginStates.disabled plugin.state_description = f"Invalid default action set ({Settings.spamwatch.default_action})" if Settings.spamwatch.token != "not set": SW_CLIENT = spamwatch.Client(Settings.spamwatch.token, host=Settings.spamwatch.api_host) plugin.logger.debug("Created spamwatch class OK")
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE # OR OTHER DEALINGS IN THE SOFTWARE. import logging from io import BytesIO from PIL import Image from telegram.error import BadRequest, TimedOut import octobot LOGGER = logging.getLogger("Sticker Optimizer") PLUGINVERSION = 2 maxwidth, maxheight = 512, 512 # Always name this variable as `plugin` # If you dont, module loader will fail to load the plugin! inf = octobot.PluginInfo(name=octobot.localizable("Stickers"), reply_kwargs={"editable": False}) class NoImageProvided(ValueError): pass def resize_sticker(image: Image): resz_rt = min(maxwidth / image.width, maxheight / image.height) sticker_size = [int(image.width * resz_rt), int(image.height * resz_rt)] if sticker_size[0] > sticker_size[1]: sticker_size[0] = 512 else: sticker_size[1] = 512 image = image.resize(sticker_size, Image.ANTIALIAS)
import datetime import pytz from octobot import CommandHandler, Context, OctoBot, PluginInfo, localizable plugin_info = PluginInfo(localizable("User ID")) @CommandHandler(command="id", description=localizable("Check the user/group/message/inline_query IDs")) def ping(bot: OctoBot, ctx: Context): user_id = ctx.user.id if ctx.update.message: chat_id = ctx.update.message.chat.id chat_type = ctx.update.message.chat.type elif ctx.update.inline_query: chat_id = "None" chat_type = "Inline Query" else: return ctx.reply("Cant understand what is going on in that update of yours") message = [ctx.localize("{} ID:<code>{}</code>").format(ctx.user.mention_html(ctx.localize("Your")), user_id), ctx.localize("Chat ID:<code>{}</code>").format(chat_id), ctx.localize("Chat type is <code>{}</code>").format(chat_type)] if ctx.update.message: msg = ctx.update.message message.append(ctx.localize("ID of your message: <code>{}</code>").format(ctx.update.message.message_id)) if msg.reply_to_message: reply = msg.reply_to_message message.append(ctx.localize("ID of replied message: <code>{}</code>").format(reply.message_id)) if reply.from_user.id:
# copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE # OR OTHER DEALINGS IN THE SOFTWARE. import datetime import pytz from octobot import CommandHandler, Context, OctoBot, PluginInfo, localizable plugin_info = PluginInfo(localizable("Ping")) @CommandHandler(command="ping", description=localizable( "Make sure bot is alive and get message delivery latency")) def ping(bot: OctoBot, ctx: Context): time = (datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) - ctx.update.message.date).total_seconds() ctx.reply(ctx.localize("🏓 Pong! Reply latency: %.2fs") % time)
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE # OR OTHER DEALINGS IN THE SOFTWARE. import base64 import html from dataclasses import dataclass from urllib.parse import urlparse import bs4 import requests import telegram import octobot from octobot import CatalogPhoto, CatalogKeyArticle, Catalog, CatalogNotFound, OctoBot, Context, \ localizable, PluginInfo, CatalogCantGoBackwards, CatalogKeyPhoto from octobot.catalogs import CatalogHandler MSG_TEMPLATE = localizable("""<b>Rating:</b> {rating} <b>Tags:</b> {tags_str}""") HEADERS = {"User-Agent": "OctoBot/1.0"} MAX_RESULTS = 25 plugin = PluginInfo("Safebooru") @dataclass class SafebooruPost: id: int rating: int tags: [str] tags_str: str source: str
import html import telegram import octobot import typing inf = octobot.PluginInfo(name=octobot.localizable("Admin commands"), reply_kwargs={"editable": False}) def lookup_username(target): if octobot.database.redis is None: return False, 0 uname_key = generate_uname_key(target) if octobot.Database.redis.exists(uname_key): return True, int(octobot.Database.redis.get(uname_key)) return False, 0 def execute_cancel(bot: octobot.OctoBot, context: octobot.Context, func: typing.Callable, reply_text: str): tgt_id, chat_id = context.text.split(":")[1:] perm_check, missing_perms = octobot.check_permissions( chat=chat_id, user=context.user.id, bot=bot, permissions_to_check={"can_restrict_members"}) if perm_check: if tgt_id.isdigit(): func(chat_id=chat_id, user_id=tgt_id)
"lifeline": "💊", "pathfinder": "🧗♂️", "wraith": "🌀", "bangalore": "🚀", "caustic": "☣️", "mirage": "🏃♂️", "octane": "💉", "wattson": "⚡️", "crypto": "🕵️♂️", "revenant": "⚰️", "loba": "💰", "rampart": "🔫", "horizon": "🚀" } inf = octobot.PluginInfo(octobot.localizable("Apex Legends player stats")) API_BASEURL = "https://api.mozambiquehe.re/bridge" PREFERRED_FIELDS = { "kills": octobot.localizable("Kills"), "damage": octobot.localizable("Damage"), "revives": octobot.localizable("Revives"), "games_played": octobot.localizable("Games player"), "kd": octobot.localizable("Kill/Death ratio") } def good_username(strg, search=re.compile(r'[^a-zA-Z\-_0-9 ]').search): return not bool(search(strg))
def handler(bot, context): if len(context.args) > 0: return get_apex_stats(platform, context.query, context) else: context.reply(octobot.localizable("Specify username to lookup"))
# furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE # OR OTHER DEALINGS IN THE SOFTWARE. import octobot import telegram plugin = octobot.PluginInfo("About bot") @octobot.CommandHandler(command="about", description=octobot.localizable("About bot"), hidden=False, service=True) def about(bot, context): about_string = context.localize("OctoBot4 based on commit <code>{ob_version}</code>\n" + \ "Python-Telegram-Bot version: <code>{ptb_version}</code>\n" + \ '<a href="https://github.com/octo-tg-bot/">GitHub page</a>\n').format( ob_version=octobot.__version__, ptb_version=telegram.__version__ ) + (context.localize("🐳Running inside Docker") if octobot.is_docker else context.localize("🖥️Running on normal system")) context.reply(text=about_string, parse_mode="HTML")
import base64 import html import octobot from octobot import catalogs import telegram from settings import Settings import logging logger = logging.getLogger("StartHelp") info = octobot.PluginInfo(octobot.localizable("Usual bot commands")) @octobot.CommandHandler("start", description="Bot generic description and stuff", inline_support=False) def start(bot: octobot.OctoBot, ctx: octobot.Context): if ctx.query == "": kbd = telegram.InlineKeyboardMarkup( [[ telegram.InlineKeyboardButton( ctx.localize("Command list"), url=f"https://t.me/{bot.me.username}?start=help") ], [ telegram.InlineKeyboardButton(ctx.localize("Support chat"), url=Settings.support_url) ]]) ctx.reply(ctx.localize( "Hi! I am {bot.me.first_name}, a Telegram bot with features and bugs and blah blah, noone reads /start anyway."
""" Adds <b></b> tags to words that are changed https://stackoverflow.com/a/10775310 """ l1 = s1.split(' ') l2 = s2.split(' ') dif = list(Differ().compare(l1, l2)) return " ".join([ '<b>' + i[2:] + '</b>' if i[:1] == '+' else i[2:] for i in dif if not i[:1] in '-?' ]) # Always name this variable as `plugin` # If you dont, module loader will fail to load the plugin! plugin = octobot.PluginInfo(name=octobot.localizable("Word Swapper")) @octobot.CommandHandler( command=["s/", "/s/"], description=octobot.localizable("Swaps word(s) in message"), prefix="", inline_support=False) def wordsw(bot, context): try: msg = context.update.message txt = msg.text if msg.reply_to_message is not None: if not msg.reply_to_message.from_user.id == bot.getMe().id: offset = (1 if txt.startswith("/") else 0) groups = [
import html import telegram import octobot from settings import Settings plugin = octobot.PluginInfo("Imgur") if Settings.imgur_clientid == "": plugin.state = octobot.PluginStates.disabled plugin.state_description = "Imgur client ID is not set" logger = plugin.logger @octobot.catalogs.CatalogHandler( "imgur", description=octobot.localizable("Search for image on Imgur")) def imgur_search(query, index, max_count, bot: octobot.OctoBot, context: octobot.Context): index = int(index) page = index // 60 start_pos = index % 60 logger.debug("page %s, start pos %s", page, start_pos) if index < 0: raise octobot.catalogs.CatalogCantGoDeeper r = octobot.Database.get_cache( f"https://api.imgur.com/3/gallery/search/time/all/{page}", params={ "q": query }, headers={ "Authorization": f"Client-ID {Settings.imgur_clientid}" }).json()
import html import octobot import telegram inf = octobot.PluginInfo(name="Sticker block") def create_redis_set_name(chat: telegram.Chat): return f"stickerban:{chat.id}" @octobot.CommandHandler( ["toggle_pack", "ban_sticker"], description=octobot.localizable("Bans stickerpack in chat")) @octobot.supergroup_only @octobot.permissions(can_delete_messages=True) @octobot.my_permissions(can_delete_messages=True) def toggle_pack_command(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable no_pack_msg = context.localize( "Reply to sticker from stickerpack which you want to ban or pass the pack name as argument" ) if context.update.message.reply_to_message is not None: if context.update.message.reply_to_message.sticker is not None: target_pack = str( context.update.message.reply_to_message.sticker.set_name) else: return context.reply(no_pack_msg) elif len(context.args) > 0:
import html import requests import telegram import octobot from octobot import catalogs import textwrap import re apiurl = "http://api.urbandictionary.com/v0/define" DEF_BASELINE = octobot.localizable("Definition for <b>{word}</b> by <i>{author}</i>:\n" + \ "\n{definition}\n" + \ "\nExample(s):\n" + \ "{example}" ) def add_links(text: str, bot: octobot.OctoBot) -> str: matches = re.findall(r"\[.*?\]", text) for match in matches: query = match[1:-1] text = text.replace( match, f'<a href="{bot.generate_startlink("/ud " + query)}">{query}</a>') return text @catalogs.CatalogHandler(["urban", "ud"], description="Urban dictionary search") def urban_query(query, index, max_amount, bot: octobot.OctoBot,
english } siteUrl } } siteUrl } } } """ HEADERS = {"User-Agent": "OctoBot/1.0"} MEDIA_TEMPLATE_STR = localizable("""<b>{title}</b> <i>{metadata}</i> <a href="{siteUrl}">on anilist</a> {description} <i>{genres}</i> """) CHARACTER_TEMPLATE_STR = localizable("""<b>{full_name}</b> <i>{alternative_names}</i><a href="{siteUrl}">on anilist</a> {description} <i>Present in:</i> {present_in} """) ANIME_MEDIA_STATUSES_STR = { "FINISHED": localizable("finished"),