From ebd352cf80841a449d013d0b6cd4e4f4a95b6a6d Mon Sep 17 00:00:00 2001 From: Chris W Date: Fri, 20 Oct 2023 22:58:08 -0600 Subject: [PATCH] fix things, add jsondump command --- cyber_fenneko/bot.py | 2 +- cyber_fenneko/commands/jsondump.py | 31 +++++++++++++++++++++++ cyber_fenneko/commands/paste.py | 14 ++-------- cyber_fenneko/internal/arg_parser.py | 11 +++++--- cyber_fenneko/internal/command_context.py | 4 +-- cyber_fenneko/utils/paste.py | 19 ++++++++++++++ 6 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 cyber_fenneko/commands/jsondump.py create mode 100644 cyber_fenneko/utils/paste.py diff --git a/cyber_fenneko/bot.py b/cyber_fenneko/bot.py index 921c343..0bd76e2 100644 --- a/cyber_fenneko/bot.py +++ b/cyber_fenneko/bot.py @@ -63,7 +63,7 @@ class Bot: text = message_text[len(command_text) + 1:].strip() try: - args, text = self.parse_args(text, cmd.args) + args, text = parse_args(text, cmd.args) except ValueError as e: await event.respond(f'Error: {e}') return diff --git a/cyber_fenneko/commands/jsondump.py b/cyber_fenneko/commands/jsondump.py new file mode 100644 index 0000000..12d542e --- /dev/null +++ b/cyber_fenneko/commands/jsondump.py @@ -0,0 +1,31 @@ +import time +import json +from .. import bot +from ..internal.command_context import CommandContext +from ..internal.arg_parser import Arg, ArgType +from ..utils.paste import paste as paste_util + +@bot.command( + 'jsondump', + aliases=['json', 'dump', 'jd'], + description='Dump the sent message or the replied to message as JSON', + args=[ + Arg('paste', type=ArgType.bool, aliases=['p'], default=False, description='Whether to paste the JSON (will paste anyway if the JSON is too long)'), + ] +) +async def jsondump(bot, ctx: CommandContext): + # Get the message to paste + message = ctx.reply_to or ctx.message + dict = message.to_dict() + + # Prettify the JSON + raw = json.dumps(dict, indent=4, sort_keys=True, default=str) + + # Check if the JSON is too long + if len(raw) > 4000 or ctx.args['paste']: + # Paste the JSON + url = paste_util(raw, 'json')['url'] + await ctx.event.respond(f'Created paste: {url}', link_preview=False) + else: + # Respond with the JSON + await ctx.event.respond(f'```\n{raw}\n```', link_preview=False) diff --git a/cyber_fenneko/commands/paste.py b/cyber_fenneko/commands/paste.py index f0da1c3..421cca7 100644 --- a/cyber_fenneko/commands/paste.py +++ b/cyber_fenneko/commands/paste.py @@ -5,6 +5,7 @@ from telethon.tl.custom.message import Message from .. import bot from ..internal.command_context import CommandContext from ..internal.arg_parser import Arg, ArgType +from ..utils.paste import paste as paste_util ENDPOINT = 'https://0x45.st/api/pastes' @@ -44,18 +45,7 @@ async def paste(bot, ctx: CommandContext): if not contents: contents = text - data = { - 'language': language, - 'contents': contents, - } - - response = httpx.post(ENDPOINT, json=data) - if response.status_code > 299: - await ctx.event.respond(f'Failed to create paste: {response.text}') - return - - # Get the paste URL - json = response.json() + json = paste_util(contents, language) url = json['url'] # Respond with the paste URL diff --git a/cyber_fenneko/internal/arg_parser.py b/cyber_fenneko/internal/arg_parser.py index 4c16bbd..d917c42 100644 --- a/cyber_fenneko/internal/arg_parser.py +++ b/cyber_fenneko/internal/arg_parser.py @@ -1,9 +1,12 @@ +import logging from enum import Enum from typing import Dict, List, Union ArgType = Enum('ArgType', ['str', 'int', 'bool', 'peer_id']) +logger = logging.getLogger('cyber_fenneko.internal.arg_parser') + class Arg: def __init__( self, @@ -35,7 +38,7 @@ class Arg: self.description = description self.global_arg = global_arg -def parse_args(self, text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str): +def parse_args(text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str): """ Take an incoming string and parse args from it. Args are defined one of three ways: @@ -64,7 +67,7 @@ def parse_args(self, text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str): else: raise ValueError(f'Arg "{arg.name}" is not a boolean, but a boolean was provided') else: - self.logger.warning(f'Unknown arg "{arg.name}"') + logger.warning(f'Unknown arg "{arg.name}"') continue elif token.startswith('!'): # shorthand for name:false @@ -75,7 +78,7 @@ def parse_args(self, text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str): else: raise ValueError(f'Arg "{arg.name}" is not a boolean, but a boolean was provided') else: - self.logger.warning(f'Unknown arg "{arg.name}"') + logger.warning(f'Unknown arg "{arg.name}"') continue elif ':' in token: # name:value @@ -110,7 +113,7 @@ def parse_args(self, text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str): else: raise ValueError(f'Invalid arg type {arg.type} for arg "{arg.name}"') else: - self.logger.warning(f'Unknown arg "{arg.name}"') + logger.warning(f'Unknown arg "{arg.name}"') continue # If we get here, we've encountered a non-arg token diff --git a/cyber_fenneko/internal/command_context.py b/cyber_fenneko/internal/command_context.py index 3ecc8e8..0f8643f 100644 --- a/cyber_fenneko/internal/command_context.py +++ b/cyber_fenneko/internal/command_context.py @@ -1,4 +1,4 @@ -from typing import Dict +from typing import Dict, Union from telethon import TelegramClient from telethon.events import NewMessage from telethon.tl.custom.message import Message @@ -30,7 +30,7 @@ class CommandContext: message: Message, # The message that was replied to - reply_to: Message, + reply_to: Union[Message, None], # The arguments that were passed to the command args: Dict[str, Arg] diff --git a/cyber_fenneko/utils/paste.py b/cyber_fenneko/utils/paste.py new file mode 100644 index 0000000..e0886b6 --- /dev/null +++ b/cyber_fenneko/utils/paste.py @@ -0,0 +1,19 @@ +import httpx + + +ENDPOINT = 'https://0x45.st/api/pastes' + +def paste(text: str, language: str = 'txt', password = None, burn = False) -> str: + data = { + 'language': language, + 'contents': text, + 'password': password, + 'burnAfterReading': burn, + } + + response = httpx.post(ENDPOINT, json=data) + if response.status_code > 299: + raise Exception(f'Failed to create paste: {response.text}') + + json = response.json() + return json \ No newline at end of file