From 88d33da92c5503bf9645c187765f512ec0c44bef Mon Sep 17 00:00:00 2001 From: octospacc Date: Sat, 18 Nov 2023 01:27:42 +0100 Subject: [PATCH] Add separate text/markdown reply mode, add help, fix some commands --- .gitignore | 1 - .gitlab-ci.yml | 0 LICENSE.md | 0 LibWinDog/Config.py | 38 +++++++++++++++++++++++---- Locale/en.json | 0 Locale/it.json | 0 ModWinDog/Mods.py | 59 +++++++++++++++++++++++++---------------- StartWinDog | 7 ----- StartWinDog.sh | 3 +++ WinDog.py | 64 ++++++++++++++++----------------------------- requirements.txt | 2 +- 11 files changed, 95 insertions(+), 79 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .gitlab-ci.yml mode change 100644 => 100755 LICENSE.md mode change 100644 => 100755 LibWinDog/Config.py mode change 100644 => 100755 Locale/en.json mode change 100644 => 100755 Locale/it.json mode change 100644 => 100755 ModWinDog/Mods.py delete mode 100755 StartWinDog create mode 100755 StartWinDog.sh mode change 100644 => 100755 requirements.txt diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 7dad927..a82b62e --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -StartWinDog Database.json Dump.txt /Config.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml old mode 100644 new mode 100755 diff --git a/LICENSE.md b/LICENSE.md old mode 100644 new mode 100755 diff --git a/LibWinDog/Config.py b/LibWinDog/Config.py old mode 100644 new mode 100755 index ee9a0ec..2d13e94 --- a/LibWinDog/Config.py +++ b/LibWinDog/Config.py @@ -6,11 +6,11 @@ MastodonUrl = '' MastodonToken = '' -TGID = 1637713483 -TGToken = '' -TGAdmins = [ 123456789, ] -TGWhitelist = [ 123456789, ] -TGRestrict = False +TelegramId = 1637713483 +TelegramToken = '' +TelegramAdmins = [ 123456789, ] +TelegramWhitelist = [ 123456789, ] +TelegramRestrict = False DefaultLang = 'en' Debug = False @@ -19,3 +19,31 @@ CmdPrefixes = '.!/' # False: ASCII output; True: ANSI Output (must be escaped) ExecAllowed = {'date': False, 'fortune': False, 'neofetch': True, 'uptime': False} WebUserAgent = f'WinDog v.Staging' + +Endpoints = { + "start": cStart, + "help": cHelp, + #"config": cConfig, + "source": cSource, + "ping": cPing, + "echo": cEcho, + #"repeat": cRepeat, + "wish": percenter, + "level": percenter, + #"hug": multifun, + #"pat": multifun, + #"poke": multifun, + #"cuddle": multifun, + #"floor": multifun, + #"hands": multifun, + #"sessocto": multifun, + "hash": cHash, + "eval": cEval, + "exec": cExec, + #"format": cFormat, + #"frame": cFrame, + "web": cWeb, + "translate": cTranslate, + "unsplash": cUnsplash, + "safebooru": cSafebooru, +} diff --git a/Locale/en.json b/Locale/en.json old mode 100644 new mode 100755 diff --git a/Locale/it.json b/Locale/it.json old mode 100644 new mode 100755 diff --git a/ModWinDog/Mods.py b/ModWinDog/Mods.py old mode 100644 new mode 100755 index cc3066f..4d945fb --- a/ModWinDog/Mods.py +++ b/ModWinDog/Mods.py @@ -21,7 +21,7 @@ def multifun(update:Update, context:CallbackContext) -> None: ReplyToMsg = update.message.message_id if update.message.reply_to_message: ReplyFromUID = update.message.reply_to_message.from_user.id - if ReplyFromUID == TGID and 'bot' in Locale.__(Key): + if ReplyFromUID == TelegramId and 'bot' in Locale.__(Key): Text = CharEscape(choice(Locale.__(f'{Key}.bot')), 'MARKDOWN_SPEECH') elif ReplyFromUID == update.message.from_user.id and 'self' in Locale.__(Key): FromUName = CharEscape(update.message.from_user.first_name, 'MARKDOWN') @@ -54,12 +54,16 @@ def cStart(Context, Data=None) -> None: # Module: Help # ... def cHelp(Context, Data=None) -> None: - SendMsg(Context, {"Text": choice(Locale.__('help'))}) + #SendMsg(Context, {"Text": choice(Locale.__('help'))}) + Commands = '' + for Cmd in Endpoints.keys(): + Commands += f'* /{Cmd}\n' + SendMsg(Context, {"TextPlain": f'Available Endpoints (WIP):\n{Commands}'}) # Module: Source # Provides a copy of the bot source codes and/or instructions on how to get it. def cSource(Context, Data=None) -> None: - pass + SendMsg(Context, {"TextPlain": "{https://gitlab.com/octospacc/WinDog}"}) # Module: Config # ... @@ -93,7 +97,11 @@ def cEcho(Context, Data=None) -> None: def cHash(Context, Data=None) -> None: if len(Data.Tokens) >= 3 and Data.Tokens[1] in hashlib.algorithms_available: Alg = Data.Tokens[1] - SendMsg(Context, {"Text": hashlib.new(Alg, Alg.join(Data.Body.split(Alg)[1:]).strip().encode()).hexdigest()}) + Hash = hashlib.new(Alg, Alg.join(Data.Body.split(Alg)[1:]).strip().encode()).hexdigest() + SendMsg(Context, { + "TextPlain": Hash, + "TextMarkdown": MarkdownCode(Hash, True), + }) else: SendMsg(Context, {"Text": choice(Locale.__('hash.usage')).format(Data.Tokens[0], hashlib.algorithms_available)}) @@ -104,20 +112,18 @@ def cEval(Context, Data=None) -> None: # Module: Exec # Execute a system command and return stdout/stderr. -def cExec(update:Update, context:CallbackContext) -> None: - Cmd = HandleCmd(update) - if not Cmd: return - Toks = Cmd.Tokens - if len(Cmd.Tokens) >= 2 and Cmd.Tokens[1].lower() in ExecAllowed: - Cmd = Toks[1].lower() +def cExec(Context, Data=None) -> None: + if len(Data.Tokens) >= 2 and Data.Tokens[1].lower() in ExecAllowed: + Cmd = Data.Tokens[1].lower() Out = subprocess.run(('sh', '-c', f'export PATH=$PATH:/usr/games; {Cmd}'), stdout=subprocess.PIPE).stdout.decode() # - Caption = (re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])').sub('', Out)) #if ExecAllowed[Cmd] else Out) - update.message.reply_markdown_v2(MarkdownCode(Caption, True), reply_to_message_id=update.message.message_id) + Caption = (re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])').sub('', Out)) + SendMsg(Context, { + "TextPlain": Caption, + "TextMarkdown": MarkdownCode(Caption, True), + }) else: - update.message.reply_markdown_v2( - CharEscape(choice(Locale.__('eval')), 'MARKDOWN_SPEECH'), - reply_to_message_id=update.message.message_id) + SendMsg(Context, {"Text": choice(Locale.__('eval'))}) # Module: Format # Reformat text using an handful of rules @@ -131,22 +137,20 @@ def cFrame(Context, Data=None) -> None: # Module: Web # Provides results of a DuckDuckGo search. -# This is now broken with the new infer escape system... def cWeb(Context, Data=None) -> None: if Data.Body: try: QueryUrl = UrlParse.quote(Data.Body) Req = HttpGet(f'https://html.duckduckgo.com/html?q={QueryUrl}') - Caption = f'🦆🔎 "*{Data.Body}*": https://duckduckgo.com/?q={QueryUrl}\n\n' + Caption = f'🦆🔎 "{Data.Body}": https://duckduckgo.com/?q={QueryUrl}\n\n' Index = 0 for Line in Req.read().decode().replace('\t', ' ').splitlines(): if ' class="result__a" ' in Line and ' href="//duckduckgo.com/l/?uddg=' in Line: Index += 1 Link = UrlParse.unquote(Line.split(' href="//duckduckgo.com/l/?uddg=')[1].split('&rut=')[0]) Title = HtmlUnescape(Line.split('')[0].split('')[-1].split('>')[1]) - Domain = Link.split('://')[1].split('/')[0] - Caption += f'{Index}. *{HtmlEscapeFull(Title)}*: {Link} [`{Domain}`]\n\n' - SendMsg(Context, {"Text": f'{Caption}...'}) + Caption += f'[{Index}] {Title} : {{{Link}}}\n\n' + SendMsg(Context, {"TextPlain": f'{Caption}...'}) except Exception: raise else: @@ -160,7 +164,7 @@ def cTranslate(Context, Data=None) -> None: Lang = Data.Tokens[1] # TODO: Use many different public Lingva instances in rotation to avoid overloading a specific one Result = json.loads(HttpGet(f'https://lingva.ml/api/v1/auto/{Lang}/{UrlParse.quote(Lang.join(Data.Body.split(Lang)[1:]))}').read())["translation"] - SendMsg(Context, {"Text": Result}) + SendMsg(Context, {"TextPlain": Result}) except Exception: raise else: @@ -171,7 +175,12 @@ def cTranslate(Context, Data=None) -> None: def cUnsplash(Context, Data=None) -> None: try: Req = HttpGet(f'https://source.unsplash.com/random/?{UrlParse.quote(Data.Body)}') - SendMsg(Context, {"Text": MarkdownCode(Req.geturl().split('?')[0], True), "Media": Req.read()}) + ImgUrl = Req.geturl().split('?')[0] + SendMsg(Context, { + "TextPlain": f'{{{ImgUrl}}}', + "TextMarkdown": MarkdownCode(ImgUrl, True), + "Media": Req.read(), + }) except Exception: raise @@ -198,7 +207,11 @@ def cSafebooru(Context, Data=None) -> None: ImgId = ImgUrl.split('?')[-1] break if ImgUrl: - SendMsg(Context, {"Text": (f'`{ImgId}`\n' + MarkdownCode(ImgUrl, True)), "Media": HttpGet(ImgUrl).read()}) + SendMsg(Context, { + "TextPlain": f'[{ImgId}]\n{{{ImgUrl}}}', + "TextMarkdown": f'\\[`{ImgId}`\\]\n{MarkdownCode(ImgUrl, True)}', + "Media": HttpGet(ImgUrl).read(), + }) else: pass except Exception: diff --git a/StartWinDog b/StartWinDog deleted file mode 100755 index 28c1e09..0000000 --- a/StartWinDog +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -ScriptPath=$(realpath $0) -ScriptDir=$(dirname $ScriptPath) -cd $ScriptDir - -python3 WinDog.py diff --git a/StartWinDog.sh b/StartWinDog.sh new file mode 100755 index 0000000..34251d5 --- /dev/null +++ b/StartWinDog.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cd "$( dirname "$( realpath "$0" )" )" +python3 ./WinDog.py diff --git a/WinDog.py b/WinDog.py index f7cbe66..596a56e 100755 --- a/WinDog.py +++ b/WinDog.py @@ -28,40 +28,13 @@ MdEscapes = '\\`*_{}[]()<>#+-.!|=' Db = {"Chats": {}} Locale = {"Fallback": {}} -for Dir in ('Lib', 'Mod'): +for Dir in ('Mod', 'Lib'): for File in listdir(f'./{Dir}WinDog'): File = f'./{Dir}WinDog/{File}' if isfile(File): with open(File, 'r') as File: exec(File.read()) -Endpoints = { - "start": cStart, - "help": cHelp, - #"config": cConfig, - "source": cSource, - "ping": cPing, - "echo": cEcho, - "wish": percenter, - "level": percenter, - #"hug": multifun, - #"pat": multifun, - #"poke": multifun, - #"cuddle": multifun, - #"floor": multifun, - #"hands": multifun, - #"sessocto": multifun, - "hash": cHash, - "eval": cEval, - #"exec": cExec, - "format": cFormat, - "frame": cFrame, - "web": cWeb, - "translate": cTranslate, - "unsplash": cUnsplash, - "safebooru": cSafebooru, -} - def SetupLocale() -> None: global Locale for File in listdir('./Locale'): @@ -142,11 +115,11 @@ def HtmlEscapeFull(Raw:str) -> str: return New def CmdAllowed(update) -> bool: - if not TGRestrict: + if not TelegramRestrict: return True else: - if TGRestrict.lower() == 'whitelist': - if update.message.chat.id in TGWhitelist: + if TelegramRestrict.lower() == 'whitelist': + if update.message.chat.id in TelegramWhitelist: return True return False @@ -234,15 +207,23 @@ def SendMsg(Context, Data): Manager = Context['Manager'] if 'Manager' in Context else None else: [Event, Manager] = [Context, Context] - if InDict(Data, 'Text'): + + if InDict(Data, 'TextPlain') or InDict(Data, 'TextMarkdown'): + TextPlain = InDict(Data, 'TextPlain') + TextMarkdown = InDict(Data, 'TextMarkdown') + if not TextPlain: + TextPlain = TextMarkdown + elif InDict(Data, 'Text'): + # our old system attemps to always receive Markdown and retransform when needed TextPlain = MdToTxt(Data['Text']) TextMarkdown = CharEscape(HtmlUnescape(Data['Text']), InferMdEscape(HtmlUnescape(Data['Text']), TextPlain)) + if isinstance(Manager, mastodon.Mastodon): if InDict(Data, 'Media'): Media = Manager.media_post(Data['Media'], Magic(mime=True).from_buffer(Data['Media'])) while Media['url'] == 'null': Media = Manager.media(Media) - if InDict(Data, 'Text'): + if TextPlain: Manager.status_post( status=(TextPlain + '\n\n@' + Event['account']['acct']), media_ids=(Media if InDict(Data, 'Media') else None), @@ -253,15 +234,14 @@ def SendMsg(Context, Data): if InDict(Data, 'Media'): Event.message.reply_photo( Data['Media'], - caption=(TextMarkdown if InDict(Data, 'Text') else None), - parse_mode='MarkdownV2', - reply_to_message_id=Event.message.message_id, - ) - elif InDict(Data, 'Text'): - Event.message.reply_markdown_v2( - TextMarkdown, + caption=(TextMarkdown if TextMarkdown else TextPlain if TextPlain else None), + parse_mode=('MarkdownV2' if TextMarkdown else None), reply_to_message_id=Event.message.message_id, ) + elif TextMarkdown: + Event.message.reply_markdown_v2(TextMarkdown, reply_to_message_id=Event.message.message_id) + elif TextPlain: + Event.message.reply_text(TextPlain,reply_to_message_id=Event.message.message_id) def Main() -> None: SetupDb() @@ -269,12 +249,12 @@ def Main() -> None: #Private['Chats'].update({update.message.chat.id:{}}) - updater = Updater(TGToken) + updater = Updater(TelegramToken) dispatcher = updater.dispatcher dispatcher.add_handler(CommandHandler('config', cConfig)) #dispatcher.add_handler(CommandHandler('time', cTime)) - dispatcher.add_handler(CommandHandler('exec', cExec)) + #dispatcher.add_handler(CommandHandler('repeat', cRepeat)) for Cmd in ('hug', 'pat', 'poke', 'cuddle', 'floor', 'hands', 'sessocto'): dispatcher.add_handler(CommandHandler(Cmd, multifun)) diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 index 6e53a85..53d9e9c --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,4 @@ beautifulsoup4 Markdown # Telegram support -python-telegram-bot +python-telegram-bot==13.4.1