diff --git a/LibWinDog/Config.py b/LibWinDog/Config.py index 6b16662..89df73c 100755 --- a/LibWinDog/Config.py +++ b/LibWinDog/Config.py @@ -41,10 +41,12 @@ Endpoints = { #"hands": multifun, #"sessocto": multifun, "hash": cHash, + #"time": cTime, "eval": cEval, "exec": cExec, #"format": cFormat, #"frame": cFrame, + "embedded": cEmbedded, "web": cWeb, "translate": cTranslate, "unsplash": cUnsplash, diff --git a/ModWinDog/Mods.py b/ModWinDog/Mods.py index 0749474..f29a3bf 100755 --- a/ModWinDog/Mods.py +++ b/ModWinDog/Mods.py @@ -1,7 +1,9 @@ -# ================================== # -# WinDog multi-purpose chatbot # -# Licensed under AGPLv3 by OctoSpacc # -# ================================== # +# ==================================== # +# WinDog multi-purpose chatbot # +# Licensed under AGPLv3 by OctoSpacc # +# ==================================== # + +from urlextract import URLExtract # Module: Percenter # Provides fun trough percentage-based toys. @@ -38,23 +40,13 @@ def multifun(update:Update, context:CallbackContext) -> None: update.message.reply_markdown_v2(Text, reply_to_message_id=ReplyToMsg) # Module: Start -# ... +# Salutes the user, for now no other purpose except giving a feel that the bot is working. def cStart(Context, Data=None) -> None: - SendMsg(Context, {"Text": choice(Locale.__('start')).format('stupid')}) - -#def cStart(update:Update, context:CallbackContext) -> None: -# Cmd = HandleCmd(update) -# if not Cmd: return -# user = update.effective_user -# update.message.reply_markdown_v2(#'Hi\!', -# #CharEscape(choice(Locale.__('start')).format(CharEscape(user.mention_markdown_v2(), 'MARKDOWN')), 'MARKDOWN'), -# CharEscape(choice(Locale.__('start')), '.!').format(user.mention_markdown_v2()), -# reply_to_message_id=update.message.message_id) + SendMsg(Context, {"Text": choice(Locale.__('start')).format(Data.User['Name'])}) # Module: Help -# ... +# Provides help for the bot. For now, it just lists the commands. def cHelp(Context, Data=None) -> None: - #SendMsg(Context, {"Text": choice(Locale.__('help'))}) Commands = '' for Cmd in Endpoints.keys(): Commands += f'* /{Cmd}\n' @@ -117,12 +109,12 @@ def cHash(Context, Data=None) -> None: SendMsg(Context, {"Text": choice(Locale.__('hash.usage')).format(Data.Tokens[0], hashlib.algorithms_available)}) # Module: Eval -# Execute a Python command (or safe literal operation) in the current context. +# Execute a Python command (or safe literal operation) in the current context. Currently not implemented. def cEval(Context, Data=None) -> None: SendMsg(Context, {"Text": choice(Locale.__('eval'))}) # Module: Exec -# Execute a system command and return stdout/stderr. +# Execute a system command from the allowed ones and return stdout/stderr. def cExec(Context, Data=None) -> None: if len(Data.Tokens) >= 2 and Data.Tokens[1].lower() in ExecAllowed: Cmd = Data.Tokens[1].lower() @@ -137,15 +129,46 @@ def cExec(Context, Data=None) -> None: SendMsg(Context, {"Text": choice(Locale.__('eval'))}) # Module: Format -# Reformat text using an handful of rules +# Reformat text using an handful of rules. Currently not implemented. def cFormat(Context, Data=None) -> None: pass # Module: Frame -# Frame someone's message into a platform-styled image. +# Frame someone's message into a platform-styled image. Currently not implemented. def cFrame(Context, Data=None) -> None: pass +# Module: Embedded +# Rewrite a link trying to make sure we have an embed view. +def cEmbedded(Context, Data=None) -> None: + if len(Data.Tokens) >= 2: + # Find links in command body + Text = Data.Body + elif Data.Quoted and Data.Quoted['Body']: + # Find links in quoted message + Text = Data.Quoted['Body'] + else: + # Error + return + pass + Urls = URLExtract().find_urls(Text) + if len(Urls) > 0: + Proto = 'https://' + Url = Urls[0] + UrlLow = Url.lower() + if UrlLow.startswith('http://') or UrlLow.startswith('https://'): + Proto = Url.split('://')[0] + '://' + Url = '://'.join(Url.split('://')[1:]) + UrlLow = '://'.join(UrlLow.split('://')[1:]) + if UrlLow.startswith('facebook.com/') or UrlLow.startswith('www.facebook.com/') or UrlLow.startswith('m.facebook.com/') or UrlLow.startswith('mbasic.facebook.com/'): + Url = 'https://hlb0.octt.eu.org/cors-main.php/https://' + Url + Proto = '' + elif UrlLow.startswith('instagram.com/'): + Url = 'ddinstagram.com/' + Url[len('instagram.com/'):] + elif UrlLow.startswith('twitter.com/'): + Url = 'fxtwitter.com/' + Url[len('twitter.com/'):] + SendMsg(Context, {"TextPlain": Proto+Url}) + # Module: Web # Provides results of a DuckDuckGo search. def cWeb(Context, Data=None) -> None: diff --git a/WinDog.py b/WinDog.py index 8cb5536..b76e14d 100755 --- a/WinDog.py +++ b/WinDog.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -# ================================== # -# WinDog multi-purpose chatbot # -# Licensed under AGPLv3 by OctoSpacc # -# ================================== # +# ==================================== # +# WinDog multi-purpose chatbot # +# Licensed under AGPLv3 by OctoSpacc # +# ==================================== # import json, hashlib, re, time, subprocess from binascii import hexlify @@ -25,8 +25,8 @@ from urllib.request import urlopen, Request # MdEscapes = '\\`*_{}[]()<>#+-.!|=' -Db = {"Chats": {}} -Locale = {"Fallback": {}} +Db = { "Rooms": {}, "Users": {}, } +Locale = { "Fallback": {}, } for Dir in ('Mod', 'Lib'): for File in listdir(f'./{Dir}WinDog'): @@ -140,17 +140,28 @@ def ParseCmd(Msg) -> dict: "Name": Name, "Body": Name.join(Msg.split(Name)[1:]).strip(), "Tokens": GetRawTokens(Msg), - "User": {}, - "Tagged": {}, + "User": None, + "Quoted": None, }) def TelegramQueryHandle(update:Update, context:CallbackContext=None) -> None: if update and update.message: Cmd = ParseCmd(update.message.text) if Cmd and Cmd.Tokens[0][0] in CmdPrefixes and Cmd.Name in Endpoints: - Cmd.User['Name'] = 'null' - Cmd.User['Tag'] = 'null' - Cmd.User['Id'] = f'{update.message.from_user.id}@telegram' + Cmd.User = { + "Name": update.message.from_user.first_name, + "Tag": update.message.from_user.username, + "Id": f'{update.message.from_user.id}@telegram', + } + if update.message.reply_to_message: + Cmd.Quoted = { + "Body": update.message.reply_to_message.text, + "User": { + "Name": update.message.reply_to_message.from_user.first_name, + "Tag": update.message.reply_to_message.from_user.username, + "Id": f'{update.message.reply_to_message.from_user.id}@telegram', + }, + } Endpoints[Cmd.Name]({ "Event": update, "Manager": context }, Cmd) if Debug and Dumper: Text = update.message.text @@ -168,16 +179,6 @@ def TelegramQueryHandle(update:Update, context:CallbackContext=None) -> None: reply_to_message_id=update.message.message_id) ''' -def setfilter(update:Update, context:CallbackContext) -> None: - pass - ''' - if CmdAllowed(update): - ChatID = update.message.chat.id - if ChatID not in Private['Chats'] or 'Filters' not in Private['Chats'][ChatID]: - Private['Chats'][ChatID] = {'Filters':{}} - Private['Chats'][ChatID]['Filters'][update.message.text] = {'Text':0} - ''' - def RandPercent() -> int: Num = randint(0,100) if Num == 100: @@ -192,21 +193,10 @@ def RandHexStr(Len:int) -> str: Hex += choice('0123456789abcdef') return Hex -#def CmdArgs(Msg:str, Cfg:tuple=None): -# Args = [] -# Msg = Msg.strip().replace('\t', ' ') -# if Cfg: -# for i in Cfg: -# Args += [Msg.replace(' ', ' ').replace(' ', ' ').split(' ')[:i]] -# Msg = Msg -# else: -# return Msg.replace(' ', ' ').replace(' ', ' ').split(' ') - def HttpGet(Url:str): return urlopen(Request(Url, headers={"User-Agent": WebUserAgent})) def SendMsg(Context, Data, Destination=None) -> None: - #Data: Text, Media, Files if type(Context) == dict: Event = Context['Event'] if 'Event' in Context else None Manager = Context['Manager'] if 'Manager' in Context else None @@ -255,23 +245,14 @@ def Main() -> None: SetupDb() SetupLocale() - #Private['Chats'].update({update.message.chat.id:{}}) - - updater = Updater(TelegramToken) - dispatcher = updater.dispatcher - - dispatcher.add_handler(CommandHandler('config', cConfig)) - #dispatcher.add_handler(CommandHandler('time', cTime)) - #dispatcher.add_handler(CommandHandler('repeat', cRepeat)) - - for Cmd in ('hug', 'pat', 'poke', 'cuddle', 'floor', 'hands', 'sessocto'): - dispatcher.add_handler(CommandHandler(Cmd, multifun)) - - #dispatcher.add_handler(CommandHandler('setfilter', setfilter)) - dispatcher.add_handler(MessageHandler(Filters.text | Filters.command, TelegramQueryHandle)) - - print('Starting WinDog...') - updater.start_polling() + if TelegramToken: + updater = Updater(TelegramToken) + dispatcher = updater.dispatcher + dispatcher.add_handler(CommandHandler('config', cConfig)) + for Cmd in ('hug', 'pat', 'poke', 'cuddle', 'floor', 'hands', 'sessocto'): + dispatcher.add_handler(CommandHandler(Cmd, multifun)) + dispatcher.add_handler(MessageHandler(Filters.text | Filters.command, TelegramQueryHandle)) + updater.start_polling() if MastodonUrl and MastodonToken: Mastodon = mastodon.Mastodon(api_base_url=MastodonUrl, access_token=MastodonToken) @@ -296,5 +277,6 @@ if __name__ == '__main__': except Exception: pass + print('Starting WinDog...') Main() print('Closing WinDog...') diff --git a/requirements.txt b/requirements.txt index 53d9e9c..21bb3ff 100755 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ # Required by some bot modules urllib3 +urlextract # Mastodon support Mastodon.py