Compare commits
3 Commits
main
...
telethon-v
Author | SHA1 | Date |
---|---|---|
Chris W | c0c16338e7 | |
Chris W | ad8a496d7a | |
Chris W | 1a9ed07a02 |
|
@ -1,3 +1,9 @@
|
||||||
APP_ID=
|
APP_ID=
|
||||||
APP_HASH=
|
APP_HASH=
|
||||||
TG_PHONE=+15555555555
|
TG_PHONE=+15555555555
|
||||||
|
|
||||||
|
DB_HOST=
|
||||||
|
DB_USER=
|
||||||
|
DB_PASS=
|
||||||
|
DB_PORT=27017
|
||||||
|
DB_NAME=fenneko
|
|
@ -1,22 +1,40 @@
|
||||||
import os
|
import os
|
||||||
from telethon import TelegramClient
|
import jsonpickle
|
||||||
from telethon.sessions import SQLiteSession
|
from mongoengine import connect
|
||||||
|
from telemongo import MongoSession
|
||||||
|
from telethon import Client as TelegramClient
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from cyber_fenneko.bot import Bot
|
from cyber_fenneko.bot import Bot
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
jsonpickle.set_encoder_options('json', ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
# Remember to use your own values from my.telegram.org!
|
# Remember to use your own values from my.telegram.org!
|
||||||
api_id = os.environ.get('APP_ID')
|
api_id = os.environ.get('APP_ID')
|
||||||
api_hash = os.environ.get('APP_HASH')
|
api_hash = os.environ.get('APP_HASH')
|
||||||
phone_number = os.environ.get('TG_PHONE')
|
phone_number = os.environ.get('TG_PHONE')
|
||||||
|
|
||||||
session = SQLiteSession('fenneko-' + phone_number)
|
db_host = os.environ.setdefault('DB_HOST', 'localhost')
|
||||||
client = TelegramClient(session, api_id, api_hash)
|
db_port = os.environ.setdefault('DB_PORT', 27017)
|
||||||
|
db_user = os.environ.get('DB_USER')
|
||||||
|
db_pass = os.environ.get('DB_PASS')
|
||||||
|
db_name = os.environ.get('DB_NAME')
|
||||||
|
|
||||||
|
connect(db=db_name, host=db_host, port=int(db_port), username=db_user, password=db_pass)
|
||||||
|
session = MongoSession()
|
||||||
|
|
||||||
|
client = TelegramClient(session, int(api_id), api_hash)
|
||||||
bot = Bot(client)
|
bot = Bot(client)
|
||||||
|
|
||||||
|
# Import all middlewares from the middleware directory
|
||||||
|
# We just need the files to be imported, nothing else
|
||||||
|
# This is a bit hacky, but it works
|
||||||
|
for filename in os.listdir('cyber_fenneko/middleware'):
|
||||||
|
if filename.endswith('.py'):
|
||||||
|
__import__('cyber_fenneko.middleware.' + filename[:-3])
|
||||||
|
|
||||||
# Import all commands from the commands directory
|
# Import all commands from the commands directory
|
||||||
# We just need the files to be imported, nothing else
|
# We just need the files to be imported, nothing else
|
||||||
# This is a bit hacky, but it works
|
# This is a bit hacky, but it works
|
||||||
|
|
|
@ -1,12 +1,30 @@
|
||||||
from telethon.events import NewMessage
|
import asyncio
|
||||||
|
from datetime import datetime
|
||||||
|
from telethon.events import NewMessage, Event
|
||||||
|
|
||||||
|
from cyber_fenneko.models.chat import Chat, ChatType
|
||||||
from . import client, bot, phone_number
|
from . import client, bot, phone_number
|
||||||
|
|
||||||
async def new_message_handler(event: NewMessage):
|
client.add_event_handler(bot._on_raw, Event)
|
||||||
print(event)
|
# client.add_event_handler(bot._on_new_message, NewMessage)
|
||||||
|
|
||||||
client.add_event_handler(bot.on_new_message, NewMessage)
|
async def main():
|
||||||
# client.add_event_handler(new_message_handler, NewMessage)
|
async with client:
|
||||||
|
me = await client.interactive_login(phone_number)
|
||||||
|
Chat.objects(id=me.id).update_one(
|
||||||
|
set__id=me.id,
|
||||||
|
set__name=me.first_name,
|
||||||
|
set__username=me.username,
|
||||||
|
set__chat_type=ChatType.USER,
|
||||||
|
set__phone=me.phone,
|
||||||
|
set__packed=me.pack().__bytes__(),
|
||||||
|
set__updated_at=datetime.utcnow(),
|
||||||
|
upsert=True
|
||||||
|
)
|
||||||
|
|
||||||
with client:
|
client.add_event_handler(bot._on_raw, Event)
|
||||||
client.start(phone_number)
|
client.add_event_handler(bot._on_new_message, NewMessage)
|
||||||
client.run_until_disconnected()
|
|
||||||
|
await client.run_until_disconnected()
|
||||||
|
|
||||||
|
asyncio.run(main())
|
|
@ -1,15 +1,28 @@
|
||||||
import logging
|
import logging
|
||||||
from telethon import TelegramClient
|
from pprint import pprint
|
||||||
from telethon.tl.custom.message import Message
|
from typing import Dict
|
||||||
|
from telethon import Client as TelegramClient
|
||||||
|
from telethon._impl.client.types import Message
|
||||||
|
from telethon._impl.tl.abcs import Update
|
||||||
|
from telethon._impl.client.events import NewMessage, Event
|
||||||
from cyber_fenneko.internal.constants import GLOBAL_ARGS
|
from cyber_fenneko.internal.constants import GLOBAL_ARGS
|
||||||
from cyber_fenneko.internal.command import Command
|
from cyber_fenneko.internal.command import Command
|
||||||
from cyber_fenneko.internal.command_context import CommandContext
|
from cyber_fenneko.internal.command_context import CommandContext
|
||||||
from cyber_fenneko.internal.arg_parser import parse_args
|
from cyber_fenneko.internal.arg_parser import parse_args
|
||||||
|
from cyber_fenneko.utils import to_dict
|
||||||
|
|
||||||
class Bot:
|
class Bot:
|
||||||
|
commands: Dict[str, Command]
|
||||||
|
command_aliases: Dict[str, str]
|
||||||
|
update_handlers: Dict[Update, list]
|
||||||
|
client: TelegramClient
|
||||||
|
logger: logging.Logger
|
||||||
|
default_prefix: str
|
||||||
|
|
||||||
def __init__(self, client: TelegramClient):
|
def __init__(self, client: TelegramClient):
|
||||||
self.commands = {}
|
self.commands = {}
|
||||||
self.command_aliases = {}
|
self.command_aliases = {}
|
||||||
|
self.update_handlers = {}
|
||||||
self.client = client
|
self.client = client
|
||||||
self.logger = logging.getLogger('cyber_fenneko.bot')
|
self.logger = logging.getLogger('cyber_fenneko.bot')
|
||||||
self.default_prefix = '.'
|
self.default_prefix = '.'
|
||||||
|
@ -17,13 +30,22 @@ class Bot:
|
||||||
def set_default_prefix(self, prefix: str):
|
def set_default_prefix(self, prefix: str):
|
||||||
self.default_prefix = prefix
|
self.default_prefix = prefix
|
||||||
|
|
||||||
|
def on(self, *events: Event):
|
||||||
|
def decorator(func):
|
||||||
|
for event in events:
|
||||||
|
if event not in self.update_handlers:
|
||||||
|
self.update_handlers[event] = []
|
||||||
|
self.update_handlers[event].append(func)
|
||||||
|
return func
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def command(self, cmd: str, **kwargs: dict):
|
def command(self, cmd: str, **kwargs: dict):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
# Set some defaults
|
# Set some defaults
|
||||||
kwargs.setdefault('prefix', self.default_prefix)
|
kwargs.setdefault('prefix', self.default_prefix)
|
||||||
|
|
||||||
command = Command(func, cmd, **kwargs)
|
command = Command(func, cmd, **kwargs)
|
||||||
command.args = GLOBAL_ARGS + command.args
|
|
||||||
|
|
||||||
# Check if a command with the same name already exists
|
# Check if a command with the same name already exists
|
||||||
if command.command in self.commands:
|
if command.command in self.commands:
|
||||||
|
@ -42,8 +64,17 @@ class Bot:
|
||||||
return func # we still want the function to be normally accessible
|
return func # we still want the function to be normally accessible
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
async def on_new_message(self, event: Message):
|
async def _on_raw(self, event: Update):
|
||||||
message_text = event.message.message.strip()
|
pass
|
||||||
|
# if event.__class__ not in self.update_handlers:
|
||||||
|
# return
|
||||||
|
|
||||||
|
# for handler in self.update_handlers[event.__class__]:
|
||||||
|
# await handler(self, event)
|
||||||
|
|
||||||
|
async def _on_new_message(self, event: NewMessage):
|
||||||
|
# pprint(to_dict(event))
|
||||||
|
message_text = event.text.strip()
|
||||||
if not message_text:
|
if not message_text:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -56,28 +87,27 @@ class Bot:
|
||||||
if cmd.prefix != prefix:
|
if cmd.prefix != prefix:
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.out and not cmd.outgoing:
|
if event._raw.out and not cmd.outgoing:
|
||||||
return
|
return
|
||||||
elif not event.out and not cmd.incoming:
|
elif not event._raw.out and not cmd.incoming:
|
||||||
return
|
return
|
||||||
|
|
||||||
text = message_text[len(command_text) + 1:].strip()
|
text = message_text[len(command_text) + 1:].strip()
|
||||||
try:
|
try:
|
||||||
args, text = parse_args(text, cmd.args)
|
args, text = parse_args(self.client, text, cmd.args)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
await event.respond(f'Error: {e}')
|
await event.respond(f'Error: {e}')
|
||||||
return
|
return
|
||||||
|
|
||||||
reply_message = await event.message.get_reply_message()
|
reply_message = await event.get_replied_message()
|
||||||
|
|
||||||
# create the command context
|
# create the command context
|
||||||
ctx = CommandContext(
|
ctx = CommandContext(
|
||||||
client=self.client,
|
|
||||||
bot=self,
|
bot=self,
|
||||||
|
client=event.client,
|
||||||
raw_text=message_text,
|
raw_text=message_text,
|
||||||
text=text,
|
text=text,
|
||||||
event=event,
|
event=event,
|
||||||
message=event.message,
|
|
||||||
reply_to=reply_message,
|
reply_to=reply_message,
|
||||||
args=args
|
args=args
|
||||||
)
|
)
|
||||||
|
@ -87,4 +117,4 @@ class Bot:
|
||||||
|
|
||||||
# if the command is marked as 'delete', delete the message that triggered it
|
# if the command is marked as 'delete', delete the message that triggered it
|
||||||
if ctx.args['delete']:
|
if ctx.args['delete']:
|
||||||
await event.message.delete()
|
await event.delete()
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
import openai
|
||||||
|
|
||||||
|
from cyber_fenneko.internal.constants import OPENAI_API_KEY
|
||||||
|
from .. import bot
|
||||||
|
from ..internal.command_context import CommandContext
|
||||||
|
from ..internal.arg_parser import Arg, ArgType
|
||||||
|
|
||||||
|
MODELS = {
|
||||||
|
'3.5': 'gpt-3.5-turbo',
|
||||||
|
'4': 'gpt-4',
|
||||||
|
}
|
||||||
|
|
||||||
|
@bot.command(
|
||||||
|
'ask',
|
||||||
|
args=[
|
||||||
|
Arg('model', type=ArgType.enum, aliases=['m'], description='The model to use', enum_values=list(MODELS.keys()), default='3.5'),
|
||||||
|
Arg('max-tokens', type=ArgType.int, aliases=['t'], description='The maximum number of tokens to generate', default=750),
|
||||||
|
Arg('temperature', type=ArgType.int, aliases=['temp'], description='The temperature to use', default=1),
|
||||||
|
Arg('top-p', type=ArgType.int, aliases=['top'], description='The top-p value to use', default=1),
|
||||||
|
Arg('presence-penalty', type=ArgType.int, aliases=['pp'], description='The presence penalty to use', default=0),
|
||||||
|
Arg('frequency-penalty', type=ArgType.int, aliases=['fp'], description='The frequency penalty to use', default=0),
|
||||||
|
],
|
||||||
|
description='Ask a question using ChatGPT',
|
||||||
|
)
|
||||||
|
async def ask(bot, ctx: CommandContext):
|
||||||
|
if not OPENAI_API_KEY:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the message. If this command was sent in response to a message, use that message.
|
||||||
|
# Otherwise, use the message that invoked the command.
|
||||||
|
message = ctx.reply_to or ctx.event
|
||||||
|
|
||||||
|
# Get the prompt
|
||||||
|
prompt = ctx.reply_to.text.strip() if ctx.reply_to else ctx.text.strip()
|
||||||
|
|
||||||
|
# If this message was sent in response to another message, delete the sent message
|
||||||
|
if ctx.reply_to:
|
||||||
|
await ctx.event.delete()
|
||||||
|
|
||||||
|
# Get the arguments to be passed to the API
|
||||||
|
model = MODELS[ctx.args['model']]
|
||||||
|
max_tokens = ctx.args['max-tokens']
|
||||||
|
temperature = ctx.args['temperature']
|
||||||
|
top_p = ctx.args['top-p']
|
||||||
|
presence_penalty = ctx.args['presence-penalty']
|
||||||
|
frequency_penalty = ctx.args['frequency-penalty']
|
||||||
|
|
||||||
|
# Set the scene
|
||||||
|
messages = [{
|
||||||
|
"role": "system",
|
||||||
|
"content": """You are a chatbot within Telegram masquerading as a real person.
|
||||||
|
Your name is watzon, and you should act and respond like watzon would.
|
||||||
|
Watzon is a web developer of 13 years, father of 2, and husband of 1.
|
||||||
|
You are having a conversation with other humans in a Telegram group chat. Assume you have been a part of the chat for a while. No need for greetings or introductions.
|
||||||
|
The person you're responding to is either asking a question, or making a statement.
|
||||||
|
You should respond to the human in a way that makes sense.
|
||||||
|
The human is not trying to trick you. You are responding as a user, so act natural. Use slang if necessary, acronyms, etc.
|
||||||
|
Do not be too formal, and keep responses short unless the question requires a larger response.
|
||||||
|
You may use markdown formatting in your responses.
|
||||||
|
Markdown code blocks should not include the language, and should be delimited by triple backticks.
|
||||||
|
"""
|
||||||
|
}, {
|
||||||
|
"role": "user",
|
||||||
|
"content": prompt
|
||||||
|
}]
|
||||||
|
|
||||||
|
# Generate the completion
|
||||||
|
openai.api_key = OPENAI_API_KEY
|
||||||
|
completion = openai.chat.completions.create(
|
||||||
|
messages=messages,
|
||||||
|
model=model,
|
||||||
|
top_p=top_p,
|
||||||
|
temperature=temperature,
|
||||||
|
max_tokens=max_tokens,
|
||||||
|
presence_penalty=presence_penalty,
|
||||||
|
frequency_penalty=frequency_penalty,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send the response
|
||||||
|
await message.reply(markdown=completion.choices[0].message.content, link_preview=False)
|
|
@ -0,0 +1,24 @@
|
||||||
|
import time
|
||||||
|
from telethon._impl.tl.types import ChatParticipant, ChatParticipantCreator, ChatParticipantAdmin
|
||||||
|
from cyber_fenneko.utils import format_time, to_dict
|
||||||
|
from .. import bot, Bot
|
||||||
|
from ..internal.command_context import CommandContext
|
||||||
|
|
||||||
|
@bot.command(
|
||||||
|
'cache',
|
||||||
|
description='Cache as many users in the current chat as possible',
|
||||||
|
)
|
||||||
|
async def cache(bot: Bot, ctx: CommandContext):
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
msg = await ctx.event.respond('Caching...')
|
||||||
|
users = []
|
||||||
|
async for participant in ctx.client.get_participants(ctx.event.chat):
|
||||||
|
id = participant._raw.user_id
|
||||||
|
user = participant._chat_map[id]
|
||||||
|
users.append(user)
|
||||||
|
|
||||||
|
print(users)
|
||||||
|
|
||||||
|
end = time.time()
|
||||||
|
await msg.edit(f'Cached {len(users)} users in {format_time(end - start)}')
|
|
@ -9,7 +9,7 @@ async def help(bot, ctx: CommandContext):
|
||||||
cmd = ctx.text
|
cmd = ctx.text
|
||||||
if cmd:
|
if cmd:
|
||||||
if cmd in bot.commands:
|
if cmd in bot.commands:
|
||||||
await ctx.respond(bot.commands[cmd].long_help(), parse_mode='Markdown')
|
await ctx.respond(markdown=bot.commands[cmd].long_help())
|
||||||
else:
|
else:
|
||||||
await ctx.respond(f'Command `{cmd}` not found')
|
await ctx.respond(f'Command `{cmd}` not found')
|
||||||
else:
|
else:
|
||||||
|
@ -19,4 +19,4 @@ async def help(bot, ctx: CommandContext):
|
||||||
continue
|
continue
|
||||||
commands.append(command.help())
|
commands.append(command.help())
|
||||||
commands.sort()
|
commands.sort()
|
||||||
await ctx.respond('\n'.join(commands), parse_mode='Markdown')
|
await ctx.respond(markdown='\n'.join(commands))
|
|
@ -1,9 +1,11 @@
|
||||||
import time
|
|
||||||
import httpx
|
import httpx
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from telethon.tl.types import TypeMessageEntity, MessageEntityPre
|
from telethon._impl.tl.types import MessageEntityPre
|
||||||
|
|
||||||
|
from cyber_fenneko.models.settings import Settings, HighlightSettings
|
||||||
from .. import bot
|
from .. import bot
|
||||||
from ..internal.command_context import CommandContext
|
from ..internal.command_context import CommandContext
|
||||||
from ..internal.arg_parser import Arg, ArgType
|
from ..internal.arg_parser import Arg, ArgType
|
||||||
|
@ -20,9 +22,9 @@ ENDPOINT_URL = 'https://inkify.0x45.st'
|
||||||
Arg('shadow_color', type=ArgType.str, description='The color of the shadow'),
|
Arg('shadow_color', type=ArgType.str, description='The color of the shadow'),
|
||||||
Arg('background', type=ArgType.str, description='The background color'),
|
Arg('background', type=ArgType.str, description='The background color'),
|
||||||
Arg('tab_width', type=ArgType.int, description='The tab width'),
|
Arg('tab_width', type=ArgType.int, description='The tab width'),
|
||||||
Arg('line_pad', type=ArgType.int, description='The line padding'),
|
Arg('line_pad', type=ArgType.int, aliases=['pad'], description='The line padding'),
|
||||||
Arg('line_offset', type=ArgType.int, description='The line offset'),
|
Arg('line_offset', type=ArgType.int, aliases=['offset'], description='The line offset'),
|
||||||
Arg('window_title', type=ArgType.str, description='The window title'),
|
Arg('window_title', type=ArgType.str, aliases=['title'], description='The window title'),
|
||||||
Arg('no_line_number', type=ArgType.bool, description='Whether to hide the line numbers'),
|
Arg('no_line_number', type=ArgType.bool, description='Whether to hide the line numbers'),
|
||||||
Arg('no_round_corner', type=ArgType.bool, description='Whether to round the corners'),
|
Arg('no_round_corner', type=ArgType.bool, description='Whether to round the corners'),
|
||||||
Arg('no_window_controls', type=ArgType.bool, description='Whether to hide the window controls'),
|
Arg('no_window_controls', type=ArgType.bool, description='Whether to hide the window controls'),
|
||||||
|
@ -44,17 +46,17 @@ async def highlight(bot, ctx: CommandContext):
|
||||||
# Check if the user wants to list available themes
|
# Check if the user wants to list available themes
|
||||||
if ctx.args['themes']:
|
if ctx.args['themes']:
|
||||||
themes = httpx.get(f'{ENDPOINT_URL}/themes').json()
|
themes = httpx.get(f'{ENDPOINT_URL}/themes').json()
|
||||||
themes_list = ', '.join(themes)
|
themes_list = [f'- `{theme}`' for theme in themes]
|
||||||
message = f'Available themes ({len(themes)}):\n{themes_list}'
|
message = f'Available themes ({len(themes)}):\n' + '\n'.join(themes_list)
|
||||||
await ctx.event.respond(message)
|
await ctx.event.respond(markdown=message)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if the user wants to list available fonts
|
# Check if the user wants to list available fonts
|
||||||
if ctx.args['fonts']:
|
if ctx.args['fonts']:
|
||||||
fonts = httpx.get(f'{ENDPOINT_URL}/fonts').json()
|
fonts = httpx.get(f'{ENDPOINT_URL}/fonts').json()
|
||||||
fonts_list = ', '.join(fonts)
|
fonts_list = [f'- `{font}`' for font in fonts]
|
||||||
message = f'Available fonts ({len(fonts)}):\n{fonts_list}'
|
message = f'Available fonts ({len(fonts)}):\n' + '\n'.join(fonts_list)
|
||||||
await ctx.event.respond(message)
|
await ctx.event.respond(markdown=message)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if the user wants to list available languages
|
# Check if the user wants to list available languages
|
||||||
|
@ -67,63 +69,82 @@ async def highlight(bot, ctx: CommandContext):
|
||||||
|
|
||||||
# Get the message that triggered this command
|
# Get the message that triggered this command
|
||||||
message = ctx.reply_to
|
message = ctx.reply_to
|
||||||
if not message or not message.message:
|
if not message:
|
||||||
await ctx.event.respond('Reply to a message to highlight it')
|
await ctx.event.respond('Reply to a message to highlight it')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if there is a code block in the message
|
language = ctx.args['language']
|
||||||
if not message.entities:
|
code = None
|
||||||
await ctx.event.respond('No code block found')
|
|
||||||
return
|
|
||||||
|
|
||||||
# Filter through entities in the message to find the code block
|
|
||||||
code_blocks = []
|
|
||||||
for entity in message.entities:
|
|
||||||
if isinstance(entity, MessageEntityPre):
|
|
||||||
code_blocks.append(message.message[entity.offset:entity.offset + entity.length])
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
code_blocks.append(ctx.text)
|
|
||||||
|
|
||||||
for code_block in code_blocks:
|
# First check if the message contains a file
|
||||||
# Inkify returns an image, we just need to build the URL
|
if message.file:
|
||||||
query = OrderedDict(
|
mime = message.file._mime
|
||||||
code=code_block,
|
if mime and (mime.startswith('text/') or mime.startswith('application/')):
|
||||||
language=ctx.args['language'],
|
with NamedTemporaryFile(mode='wb', suffix=message.file.ext) as file:
|
||||||
theme=ctx.args['theme'],
|
await message.file.download(file)
|
||||||
font=ctx.args['font'],
|
file.seek(0)
|
||||||
shadow_color=ctx.args['shadow_color'],
|
code = file.read().decode('utf-8')
|
||||||
background=ctx.args['background'],
|
language = language or message.file.ext[1:]
|
||||||
tab_width=ctx.args['tab_width'],
|
|
||||||
line_pad=ctx.args['line_pad'],
|
|
||||||
line_offset=ctx.args['line_offset'],
|
|
||||||
window_title=ctx.args['window_title'],
|
|
||||||
no_line_number=ctx.args['no_line_number'],
|
|
||||||
no_round_corner=ctx.args['no_round_corner'],
|
|
||||||
no_window_controls=ctx.args['no_window_controls'],
|
|
||||||
shadow_blur_radius=ctx.args['shadow_blur_radius'],
|
|
||||||
shadow_offset_x=ctx.args['shadow_offset_x'],
|
|
||||||
shadow_offset_y=ctx.args['shadow_offset_y'],
|
|
||||||
pad_horiz=ctx.args['pad_horiz'],
|
|
||||||
pad_vert=ctx.args['pad_vert'],
|
|
||||||
highlight_lines=ctx.args['highlight_lines'],
|
|
||||||
background_image=ctx.args['background_image'],
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove any arguments that are None, and transform booleans into lowercase strings
|
# Next check if the message contains any code blocks
|
||||||
query = {k: v for k, v in query.items() if v is not None}
|
if not code and message._raw.entities:
|
||||||
query = {k: str(v).lower() if isinstance(v, bool) else v for k, v in query.items()}
|
for entity in message._raw.entities:
|
||||||
|
if isinstance(entity, MessageEntityPre):
|
||||||
|
code = message.text[entity.offset:entity.offset + entity.length]
|
||||||
|
language = language or entity.language
|
||||||
|
break
|
||||||
|
|
||||||
# Get the image from the URL
|
# If there are no code blocks (or more than one), we'll just use the entire message
|
||||||
url = f'{ENDPOINT_URL}/generate?{urlencode(query)}'
|
if not code:
|
||||||
print(url)
|
code = message.text
|
||||||
res = httpx.get(url)
|
|
||||||
|
|
||||||
if res.status_code != 200:
|
|
||||||
await ctx.event.respond(f'Error: {res.status_code}')
|
|
||||||
return
|
|
||||||
|
|
||||||
img = BytesIO(res.content)
|
|
||||||
|
|
||||||
# Send the image
|
settings = Settings.objects.first()
|
||||||
await ctx.event.respond(file=img)
|
if settings.highlight is None:
|
||||||
|
settings.highlight = HighlightSettings()
|
||||||
|
settings.save()
|
||||||
|
|
||||||
|
# Inkify returns an image, we just need to build the URL
|
||||||
|
query = OrderedDict(
|
||||||
|
code=code,
|
||||||
|
language=language,
|
||||||
|
theme=ctx.args['theme'] or settings.highlight.theme,
|
||||||
|
font=ctx.args['font'] or settings.highlight.font,
|
||||||
|
shadow_color=ctx.args['shadow_color'] or settings.highlight.shadow_color,
|
||||||
|
background=ctx.args['background'] or settings.highlight.background,
|
||||||
|
tab_width=ctx.args['tab_width'] or settings.highlight.tab_width,
|
||||||
|
line_pad=ctx.args['line_pad'] or settings.highlight.line_pad,
|
||||||
|
line_offset=ctx.args['line_offset'] or settings.highlight.line_offset,
|
||||||
|
window_title=ctx.args['window_title'] or settings.highlight.window_title,
|
||||||
|
no_line_number=ctx.args['no_line_number'] or settings.highlight.no_line_number,
|
||||||
|
no_round_corner=ctx.args['no_round_corner'] or settings.highlight.no_round_corner,
|
||||||
|
no_window_controls=ctx.args['no_window_controls'] or settings.highlight.no_window_controls,
|
||||||
|
shadow_blur_radius=ctx.args['shadow_blur_radius'] or settings.highlight.shadow_blur_radius,
|
||||||
|
shadow_offset_x=ctx.args['shadow_offset_x'] or settings.highlight.shadow_offset_x,
|
||||||
|
shadow_offset_y=ctx.args['shadow_offset_y'] or settings.highlight.shadow_offset_y,
|
||||||
|
pad_horiz=ctx.args['pad_horiz'] or settings.highlight.pad_horiz,
|
||||||
|
pad_vert=ctx.args['pad_vert'] or settings.highlight.pad_vert,
|
||||||
|
highlight_lines=ctx.args['highlight_lines'] or settings.highlight.highlight_lines,
|
||||||
|
background_image=ctx.args['background_image'] or settings.highlight.background_image,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Remove any arguments that are None, and transform booleans into lowercase strings
|
||||||
|
query = {k: v for k, v in query.items() if v is not None}
|
||||||
|
query = {k: str(v).lower() if isinstance(v, bool) else v for k, v in query.items()}
|
||||||
|
|
||||||
|
url = f'{ENDPOINT_URL}/generate?{urlencode(query)}'
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(url)
|
||||||
|
file = BytesIO(response.content)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await ctx.client.send_photo(
|
||||||
|
ctx.event.chat,
|
||||||
|
file=file,
|
||||||
|
size=int(response.headers['content-length']),
|
||||||
|
compress=True,
|
||||||
|
name='highlight.png',
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
await ctx.event.respond(f'Failed to highlight code: {e}')
|
||||||
|
return
|
|
@ -1,5 +1,5 @@
|
||||||
import time
|
import jsonpickle
|
||||||
import json
|
from cyber_fenneko.utils import to_dict
|
||||||
from .. import bot
|
from .. import bot
|
||||||
from ..internal.command_context import CommandContext
|
from ..internal.command_context import CommandContext
|
||||||
from ..internal.arg_parser import Arg, ArgType
|
from ..internal.arg_parser import Arg, ArgType
|
||||||
|
@ -16,10 +16,10 @@ from ..utils.paste import paste as paste_util
|
||||||
async def jsondump(bot, ctx: CommandContext):
|
async def jsondump(bot, ctx: CommandContext):
|
||||||
# Get the message to paste
|
# Get the message to paste
|
||||||
message = ctx.reply_to or ctx.message
|
message = ctx.reply_to or ctx.message
|
||||||
dict = message.to_dict()
|
dict = to_dict(message)
|
||||||
|
|
||||||
# Prettify the JSON
|
# Prettify the JSON
|
||||||
raw = json.dumps(dict, indent=4, sort_keys=True, default=str)
|
raw = jsonpickle.encode(dict, unpicklable=False, indent=4)
|
||||||
|
|
||||||
# Check if the JSON is too long
|
# Check if the JSON is too long
|
||||||
if len(raw) > 4000 or ctx.args['paste']:
|
if len(raw) > 4000 or ctx.args['paste']:
|
||||||
|
@ -28,4 +28,5 @@ async def jsondump(bot, ctx: CommandContext):
|
||||||
await ctx.event.respond(f'Created paste: {url}', link_preview=False)
|
await ctx.event.respond(f'Created paste: {url}', link_preview=False)
|
||||||
else:
|
else:
|
||||||
# Respond with the JSON
|
# Respond with the JSON
|
||||||
await ctx.event.respond(f'```\n{raw}\n```', link_preview=False)
|
response = f'<pre><code class="language-json">{raw}</code></pre>'
|
||||||
|
await ctx.event.respond(html=response)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
import re
|
||||||
|
from io import BytesIO
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
import time
|
import time
|
||||||
import httpx
|
import httpx
|
||||||
from telethon.tl.types import MessageEntityPre
|
from telethon._impl.tl.types import MessageEntityPre
|
||||||
from telethon.tl.custom.message import Message
|
|
||||||
|
from cyber_fenneko.models.paste import Paste
|
||||||
from .. import bot
|
from .. import bot
|
||||||
from ..internal.command_context import CommandContext
|
from ..internal.command_context import CommandContext
|
||||||
from ..internal.arg_parser import Arg, ArgType
|
from ..internal.arg_parser import Arg, ArgType
|
||||||
|
@ -9,44 +13,53 @@ from ..utils.paste import paste as paste_util
|
||||||
|
|
||||||
ENDPOINT = 'https://0x45.st/api/pastes'
|
ENDPOINT = 'https://0x45.st/api/pastes'
|
||||||
|
|
||||||
|
|
||||||
@bot.command(
|
@bot.command(
|
||||||
'paste',
|
'paste',
|
||||||
description='Send the contents of the replied to message to a pastebin',
|
description='Send the contents of the replied to message to a pastebin',
|
||||||
args=[
|
args=[
|
||||||
Arg('language', type=ArgType.str, aliases=['lang'], default='txt', description='The language to use for syntax highlighting'),
|
Arg('delete', default=True),
|
||||||
|
Arg('list', type=ArgType.bool, default=False, aliases=[
|
||||||
|
'l'], description='List all pastes made by the bot'),
|
||||||
|
Arg('raw', type=ArgType.bool, default=True,
|
||||||
|
description='Paste the raw markdown instead of the rendered text'),
|
||||||
|
Arg('language', type=ArgType.str, aliases=[
|
||||||
|
'lang'], default=None, description='The language to use for syntax highlighting'),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
async def paste(bot, ctx: CommandContext):
|
async def paste(bot, ctx: CommandContext):
|
||||||
# Get the message to paste
|
# Get the message to paste
|
||||||
message: Message = ctx.reply_to
|
message = ctx.reply_to
|
||||||
if message is None:
|
if message is None:
|
||||||
await ctx.event.respond('You must reply to a message to use this command')
|
await ctx.event.respond('You must reply to a message to use this command')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get the message text
|
|
||||||
text = message.text
|
|
||||||
if text is None:
|
|
||||||
await ctx.event.respond('You must reply to a text message to use this command')
|
|
||||||
return
|
|
||||||
|
|
||||||
# Get the language
|
|
||||||
language = ctx.args['language']
|
language = ctx.args['language']
|
||||||
|
code = None
|
||||||
|
|
||||||
contents = ''
|
# First check if the message contains a file
|
||||||
|
if message.file:
|
||||||
|
mime = message.file._mime
|
||||||
|
if mime and (mime.startswith('text/') or mime.startswith('application/')):
|
||||||
|
buff = BytesIO()
|
||||||
|
await message.file.download(buff)
|
||||||
|
code = buff.getvalue().decode('utf-8')
|
||||||
|
language = language or message.file.ext[1:]
|
||||||
|
|
||||||
# Check if the message has entities; any pre entities will be used as the contents
|
# Next check if the message contains any code blocks
|
||||||
if message.entities is not None:
|
if not code and message._raw.entities:
|
||||||
for entity in message.entities:
|
for entity in message._raw.entities:
|
||||||
if isinstance(entity, MessageEntityPre):
|
if isinstance(entity, MessageEntityPre):
|
||||||
contents += text[entity.offset:entity.offset + entity.length]
|
code = message.text[entity.offset:entity.offset + entity.length]
|
||||||
contents += '\n\n'
|
language = language or entity.language
|
||||||
break
|
break
|
||||||
|
|
||||||
if not contents:
|
|
||||||
contents = text
|
|
||||||
|
|
||||||
json = paste_util(contents, language)
|
# If there are no code blocks (or more than one), we'll just use the entire message
|
||||||
|
if not code:
|
||||||
|
code = message.text_markdown if ctx.args['raw'] else message.text
|
||||||
|
|
||||||
|
json = paste_util(code, language)
|
||||||
url = json['url']
|
url = json['url']
|
||||||
|
|
||||||
# Respond with the paste URL
|
# Respond with the paste URL
|
||||||
await ctx.event.respond(f'Created paste: {url}', link_preview=False)
|
await ctx.event.respond(f'Created new paste at:\n{url}', link_preview=False)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import time
|
import time
|
||||||
from .. import bot
|
from .. import bot
|
||||||
from ..internal.command_context import CommandContext
|
from ..internal.command_context import CommandContext
|
||||||
from ..internal.arg_parser import Arg, ArgType
|
|
||||||
|
|
||||||
@bot.command(
|
@bot.command(
|
||||||
'ping',
|
'ping',
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
from urllib import parse
|
||||||
|
from cyber_fenneko.internal.arg_parser import Arg, ArgType
|
||||||
|
from .. import bot
|
||||||
|
from ..internal.command_context import CommandContext
|
||||||
|
from cyber_fenneko.models.settings import Settings
|
||||||
|
|
||||||
|
engine_map = {
|
||||||
|
'google': 'https://www.google.com/search?q=%s',
|
||||||
|
'bing': 'https://www.bing.com/search?q=%s',
|
||||||
|
'duckduckgo': 'https://duckduckgo.com/?q=%s',
|
||||||
|
'qwant': 'https://www.qwant.com/?q=%s',
|
||||||
|
'ecosia': 'https://www.ecosia.org/search?q=%s',
|
||||||
|
'kagi': 'https://kagi.com/search?q=%s',
|
||||||
|
}
|
||||||
|
|
||||||
|
@bot.command(
|
||||||
|
'search',
|
||||||
|
aliases=['google', 'lmgtfy'],
|
||||||
|
args=[
|
||||||
|
# Arg('delete', type=ArgType.bool, default=True),
|
||||||
|
Arg('google', type=ArgType.bool, default=False, description='Use Google as the search engine'),
|
||||||
|
Arg('bing', type=ArgType.bool, default=False, description='Use Bing as the search engine'),
|
||||||
|
Arg('duckduckgo', type=ArgType.bool, aliases=['ddg'], default=False, description='Use DuckDuckGo as the search engine'),
|
||||||
|
Arg('qwant', type=ArgType.bool, default=False, description='Use Qwant as the search engine'),
|
||||||
|
Arg('ecosia', type=ArgType.bool, default=False, description='Use Ecosia as the search engine'),
|
||||||
|
Arg('kagi', type=ArgType.bool, default=False, description='Use Kagi as the search engine'),
|
||||||
|
],
|
||||||
|
description='"Help people out by posting a link to a search query for their question"',
|
||||||
|
)
|
||||||
|
async def search(bot, ctx: CommandContext):
|
||||||
|
print(ctx)
|
||||||
|
# Get the search query from the reply message or the sent message
|
||||||
|
query = ctx.reply_to.text if ctx.reply_to else ctx.text
|
||||||
|
if not query:
|
||||||
|
await ctx.event.respond('You must specify a search query')
|
||||||
|
return
|
||||||
|
|
||||||
|
settings = Settings.objects.first()
|
||||||
|
|
||||||
|
# Get the search engine
|
||||||
|
search_engine = None
|
||||||
|
for engine in engine_map:
|
||||||
|
if ctx.args[engine]:
|
||||||
|
search_engine = engine
|
||||||
|
|
||||||
|
search_engine = search_engine or settings.search_engine or 'google'
|
||||||
|
url = engine_map[search_engine] % parse.quote_plus(query)
|
||||||
|
|
||||||
|
# Send the search query
|
||||||
|
await ctx.event.respond(html=f'<a href="{url}">{query}</a>', link_preview=False)
|
|
@ -0,0 +1,64 @@
|
||||||
|
import time
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from mongoengine import EmbeddedDocumentField, StringField, IntField, BooleanField, EnumField
|
||||||
|
from cyber_fenneko.internal.arg_parser import Arg, ArgType
|
||||||
|
from cyber_fenneko.models.settings import Settings
|
||||||
|
from .. import bot
|
||||||
|
from ..internal.command_context import CommandContext
|
||||||
|
|
||||||
|
def mongo_field_to_arg_type(field):
|
||||||
|
if isinstance(field, StringField):
|
||||||
|
return ArgType.str
|
||||||
|
elif isinstance(field, IntField):
|
||||||
|
return ArgType.int
|
||||||
|
elif isinstance(field, BooleanField):
|
||||||
|
return ArgType.bool
|
||||||
|
elif isinstance(field, EnumField):
|
||||||
|
return ArgType.enum
|
||||||
|
else:
|
||||||
|
return ArgType.str
|
||||||
|
|
||||||
|
# Build the args object for the settings command using the fields from the Settings model.
|
||||||
|
# Keys are the field names, values are the field types. With EmbeddedDocuments, the key
|
||||||
|
# is the Settings object property name and the embedded document's field name,
|
||||||
|
# concaternated with a period. Ex. 'highlight.theme'.
|
||||||
|
setings_args: List[Arg] = []
|
||||||
|
for field in Settings._fields:
|
||||||
|
if isinstance(Settings._fields[field], EmbeddedDocumentField):
|
||||||
|
for embedded_field in Settings._fields[field].document_type._fields:
|
||||||
|
if embedded_field == 'id':
|
||||||
|
continue
|
||||||
|
name = f'{field}.{embedded_field}'
|
||||||
|
kind = mongo_field_to_arg_type(Settings._fields[field].document_type._fields[embedded_field])
|
||||||
|
setings_args.append(Arg(name, type=kind))
|
||||||
|
else:
|
||||||
|
if field == 'id':
|
||||||
|
continue
|
||||||
|
kind = mongo_field_to_arg_type(Settings._fields[field])
|
||||||
|
setings_args.append(Arg(field, type=kind))
|
||||||
|
|
||||||
|
@bot.command(
|
||||||
|
'settings',
|
||||||
|
aliases=['s', 'set'],
|
||||||
|
args=setings_args,
|
||||||
|
description='Change the bot\'s settings',
|
||||||
|
)
|
||||||
|
async def settings(bot, ctx: CommandContext):
|
||||||
|
"""Change the bot's settings"""
|
||||||
|
# Get the settings object
|
||||||
|
settings = Settings.objects.first()
|
||||||
|
|
||||||
|
# Find all args that have a value, and set them on the settings object
|
||||||
|
for arg in ctx.args:
|
||||||
|
if ctx.args[arg] is not None:
|
||||||
|
if '.' in arg:
|
||||||
|
parts = arg.split('.')
|
||||||
|
setattr(getattr(settings, parts[0]), parts[1], ctx.args[arg])
|
||||||
|
else:
|
||||||
|
setattr(settings, arg, ctx.args[arg])
|
||||||
|
|
||||||
|
# Save the settings object
|
||||||
|
settings.save()
|
||||||
|
|
||||||
|
await ctx.reply('Settings updated')
|
|
@ -0,0 +1,116 @@
|
||||||
|
# import time
|
||||||
|
|
||||||
|
# from telethon._impl.tl.types import User
|
||||||
|
# from telethon._impl.tl.functions import messages
|
||||||
|
|
||||||
|
# from cyber_fenneko.internal.arg_parser import Arg, ArgType
|
||||||
|
# from cyber_fenneko.models.chat import Chat
|
||||||
|
# from cyber_fenneko.utils import format_bool, format_user_status
|
||||||
|
# from cyber_fenneko.bot import Bot
|
||||||
|
|
||||||
|
# from .. import bot
|
||||||
|
# from ..internal.command_context import CommandContext
|
||||||
|
|
||||||
|
# @bot.command(
|
||||||
|
# 'user',
|
||||||
|
# aliases=['u'],
|
||||||
|
# args = [
|
||||||
|
# Arg('user', type=ArgType.peer, aliases=['u'], description='The user to get information about'),
|
||||||
|
# Arg('id', type=ArgType.bool, aliases=['i'], default=True, description='Return only the user ID'),
|
||||||
|
# Arg('mention', type=ArgType.bool, aliases=['m'], default=False, description='Whether to mention the user in the response'),
|
||||||
|
# Arg('check_forward', type=ArgType.bool, aliases=['fwd'], default=True, description='Whether to check the forward from the reply message'),
|
||||||
|
|
||||||
|
# Arg('full', type=ArgType.bool, aliases=['f'], default=False, description='Whether to get full information about the user'),
|
||||||
|
# Arg('general', type=ArgType.bool, aliases=['g'], default=False, description='Whether to show general information about the user'),
|
||||||
|
# Arg('common_chats', type=ArgType.bool, aliases=['chats'], default=False, description='Whether to get the user\'s common chats'),
|
||||||
|
# Arg('meta', type=ArgType.bool, default=False, description='Extra infomation about the user that didn\'t fit in the other categories'),
|
||||||
|
# ],
|
||||||
|
# description='Gather and return information about the given user',
|
||||||
|
# )
|
||||||
|
# async def user(bot: Bot, ctx: CommandContext):
|
||||||
|
# peer: Chat = ctx.args['user']
|
||||||
|
# user: User = peer._to_input_peer()
|
||||||
|
|
||||||
|
# if not user:
|
||||||
|
# # Attempt to get the user from the reply message
|
||||||
|
# message = await ctx.event.get_replied_message()
|
||||||
|
# if message:
|
||||||
|
# try:
|
||||||
|
# if ctx.args['check_forward'] and message._raw.fwd_from:
|
||||||
|
# # user = message.forward_info
|
||||||
|
# # TODO: Forwarded messages
|
||||||
|
# raise NotImplementedError('Forwarded messages are not supported yet')
|
||||||
|
# else:
|
||||||
|
# user = message.sender
|
||||||
|
# except:
|
||||||
|
# await ctx.event.respond('Failed to get user from reply message')
|
||||||
|
# return
|
||||||
|
|
||||||
|
# if not user:
|
||||||
|
# await ctx.event.respond('You must specify a user to get information about')
|
||||||
|
# return
|
||||||
|
|
||||||
|
# mention = ctx.args['mention']
|
||||||
|
# show_full = ctx.args['full']
|
||||||
|
# id = ctx.args['id']
|
||||||
|
# show_general = show_full or ctx.args['general']
|
||||||
|
# show_meta = show_full or ctx.args['meta']
|
||||||
|
# show_common_chats = show_full or ctx.args['common_chats']
|
||||||
|
|
||||||
|
# if show_general or show_meta or show_common_chats:
|
||||||
|
# id = False
|
||||||
|
|
||||||
|
# # Screen name (first name + last name if available)
|
||||||
|
# screen_name = user.first_name
|
||||||
|
# if user.last_name:
|
||||||
|
# screen_name += f' {user.last_name}'
|
||||||
|
|
||||||
|
# # Start building a response
|
||||||
|
# response = ''
|
||||||
|
# if id:
|
||||||
|
# if mention:
|
||||||
|
# response += f'[{screen_name}](tg://user?id={user.id}) (`{user.id}`)'
|
||||||
|
# else:
|
||||||
|
# response += f'**{screen_name}**: {user.id}'
|
||||||
|
# else:
|
||||||
|
# if mention:
|
||||||
|
# response += f'[{screen_name}](tg://user?id={user.id}) (`{user.id}`):\n'
|
||||||
|
# else:
|
||||||
|
# response += f'**{screen_name}** ({user.id})\n'
|
||||||
|
|
||||||
|
# # General
|
||||||
|
# if show_general:
|
||||||
|
# response += f'**general**\n'
|
||||||
|
# response += f' username: `{user.username}`\n'
|
||||||
|
# response += f' phone: `{user.phone}`\n'
|
||||||
|
# response += f' bot: {format_bool(user.bot)}\n'
|
||||||
|
# response += f' verified: {format_bool(user.verified)}\n'
|
||||||
|
# response += f' restricted: {format_bool(user.restricted)}\n'
|
||||||
|
# response += f' support: {format_bool(user.support)}\n'
|
||||||
|
# response += f' scam: {format_bool(user.scam)}\n'
|
||||||
|
# response += f' fake: {format_bool(user.fake)}\n'
|
||||||
|
|
||||||
|
# # Common chats
|
||||||
|
# if show_common_chats:
|
||||||
|
# response += f'**common chats**\n'
|
||||||
|
# common_chats = await bot.client(messages.get_common_chats(user.id, 0, 200))
|
||||||
|
# for chat in common_chats.chats:
|
||||||
|
# response += f' {chat.title} ({chat.id})\n'
|
||||||
|
|
||||||
|
# # Meta
|
||||||
|
# if show_meta:
|
||||||
|
# response += f'**meta**\n'
|
||||||
|
# response += f' access_hash: `{user.access_hash}`\n'
|
||||||
|
# response += f' bot_chat_history: {format_bool(user.bot_chat_history)}\n'
|
||||||
|
# response += f' bot_nochats: {format_bool(user.bot_nochats)}\n'
|
||||||
|
# response += f' bot_inline_geo: {format_bool(user.bot_inline_geo)}\n'
|
||||||
|
# response += f' min: {format_bool(user.min)}\n'
|
||||||
|
# response += f' bot_inline_placeholder: {format_bool(user.bot_inline_placeholder)}\n'
|
||||||
|
# response += f' lang_code: `{user.lang_code}`\n'
|
||||||
|
# response += f' status: `{format_user_status(user.status)}`\n'
|
||||||
|
# response += f' bot_info_version: `{user.bot_info_version}`\n'
|
||||||
|
# response += f' restriction_reason: `{user.restriction_reason}`\n'
|
||||||
|
# response += f' bot_inline_geo: {format_bool(user.bot_inline_geo)}\n'
|
||||||
|
|
||||||
|
# # Send the response
|
||||||
|
# await ctx.reply(markdown=response, link_preview=False)
|
|
@ -2,8 +2,12 @@ import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Dict, List, Union
|
from typing import Dict, List, Union
|
||||||
|
|
||||||
|
from telethon import Client as TelegramClient
|
||||||
|
|
||||||
ArgType = Enum('ArgType', ['str', 'int', 'bool', 'peer_id'])
|
from cyber_fenneko.utils import get_chat_by_id, get_chat_by_username
|
||||||
|
|
||||||
|
|
||||||
|
ArgType = Enum('ArgType', ['str', 'int', 'bool', 'enum', 'peer'])
|
||||||
|
|
||||||
logger = logging.getLogger('cyber_fenneko.internal.arg_parser')
|
logger = logging.getLogger('cyber_fenneko.internal.arg_parser')
|
||||||
|
|
||||||
|
@ -29,6 +33,9 @@ class Arg:
|
||||||
|
|
||||||
# Special designation for global args
|
# Special designation for global args
|
||||||
global_arg: bool = False,
|
global_arg: bool = False,
|
||||||
|
|
||||||
|
# If the type is enum, this is the list of valid values
|
||||||
|
enum_values: List[str] = None,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
|
@ -37,8 +44,25 @@ class Arg:
|
||||||
self.default = default
|
self.default = default
|
||||||
self.description = description
|
self.description = description
|
||||||
self.global_arg = global_arg
|
self.global_arg = global_arg
|
||||||
|
self.enum_values = enum_values
|
||||||
|
|
||||||
def parse_args(text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str):
|
def merge(self, other: 'Arg'):
|
||||||
|
"""
|
||||||
|
Merge the values of another arg into this one.
|
||||||
|
"""
|
||||||
|
self.name = self.name if self.name is not None else other.name
|
||||||
|
self.type = self.type if self.type is not None else other.type
|
||||||
|
self.aliases = self.aliases if self.aliases is not None else other.aliases
|
||||||
|
self.required = self.required if self.required is not None else other.required
|
||||||
|
self.default = self.default if self.default is not None else other.default
|
||||||
|
self.description = self.description if self.description is not None else other.description
|
||||||
|
self.global_arg = self.global_arg if self.global_arg is not None else other.global_arg
|
||||||
|
self.enum_values = self.enum_values if self.enum_values is not None else other.enum_values
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'Arg({self.name}, type={self.type}, aliases={self.aliases}, required={self.required}, default={self.default}, description={self.description}, global_arg={self.global_arg}, enum_values={self.enum_values})'
|
||||||
|
|
||||||
|
def parse_args(client: TelegramClient, text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str):
|
||||||
"""
|
"""
|
||||||
Take an incoming string and parse args from it.
|
Take an incoming string and parse args from it.
|
||||||
Args are defined one of three ways:
|
Args are defined one of three ways:
|
||||||
|
@ -96,6 +120,31 @@ def parse_args(text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str):
|
||||||
raise ValueError(f'Unterminated string for arg "{arg.name}"')
|
raise ValueError(f'Unterminated string for arg "{arg.name}"')
|
||||||
arg_value = arg_value[1:-1]
|
arg_value = arg_value[1:-1]
|
||||||
parsed_args[arg.name] = arg_value
|
parsed_args[arg.name] = arg_value
|
||||||
|
elif arg.type == ArgType.enum:
|
||||||
|
# if the arg is an enum, we need to check if the value is valid
|
||||||
|
if arg_value in arg.enum_values:
|
||||||
|
parsed_args[arg.name] = arg_value
|
||||||
|
else:
|
||||||
|
raise ValueError(f'Invalid enum value {arg_value} for arg "{arg.name}"')
|
||||||
|
elif arg.type == ArgType.peer:
|
||||||
|
# peer is a special type that can be a username, user id, or chat id.
|
||||||
|
# we need to fetch the user or chat that the id belongs to.
|
||||||
|
|
||||||
|
chat = None
|
||||||
|
try:
|
||||||
|
int_value = int(arg_value)
|
||||||
|
chat = get_chat_by_id(int_value)
|
||||||
|
except ValueError:
|
||||||
|
chat = get_chat_by_username(arg_value)
|
||||||
|
|
||||||
|
if chat is None:
|
||||||
|
raise ValueError(f'Invalid peer value {arg_value} for arg "{arg.name}"')
|
||||||
|
|
||||||
|
peer = chat.unpack()
|
||||||
|
if peer is None:
|
||||||
|
raise ValueError(f'Invalid peer value {arg_value} for arg "{arg.name}"')
|
||||||
|
|
||||||
|
parsed_args[arg.name] = peer
|
||||||
elif arg.type == ArgType.bool:
|
elif arg.type == ArgType.bool:
|
||||||
# if the arg is a boolean, we need to check if the value is true or false
|
# if the arg is a boolean, we need to check if the value is true or false
|
||||||
if arg_value.lower() == 'true':
|
if arg_value.lower() == 'true':
|
||||||
|
@ -118,6 +167,7 @@ def parse_args(text: str, cmd_args: List[Arg]) -> (Dict[str, Arg], str):
|
||||||
|
|
||||||
# If we get here, we've encountered a non-arg token
|
# If we get here, we've encountered a non-arg token
|
||||||
# so we stop parsing
|
# so we stop parsing
|
||||||
|
tokens.insert(0, token)
|
||||||
break
|
break
|
||||||
|
|
||||||
# Check if any required args are missing
|
# Check if any required args are missing
|
||||||
|
|
|
@ -51,6 +51,14 @@ class Command:
|
||||||
self.description = description
|
self.description = description
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
|
for arg in GLOBAL_ARGS:
|
||||||
|
if arg.name not in [a.name for a in self.args]:
|
||||||
|
self.args.append(arg)
|
||||||
|
else:
|
||||||
|
for a in self.args:
|
||||||
|
if a.name == arg.name:
|
||||||
|
a.merge(arg)
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return self.func(*args, **kwargs)
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -85,14 +93,27 @@ class Command:
|
||||||
help_string += f'`{arg.name}'
|
help_string += f'`{arg.name}'
|
||||||
if arg.aliases:
|
if arg.aliases:
|
||||||
help_string += f' ({", ".join(arg.aliases)})'
|
help_string += f' ({", ".join(arg.aliases)})'
|
||||||
help_string += f': {arg.type.name}`\n {arg.description}\n'
|
help_string += f': {arg.type.name}'
|
||||||
|
if arg.default is not None:
|
||||||
|
help_string += f' = {arg.default}'
|
||||||
|
help_string += '`\n'
|
||||||
|
if arg.description:
|
||||||
|
help_string += f' {arg.description}\n'
|
||||||
help_string += '\n'
|
help_string += '\n'
|
||||||
|
|
||||||
for arg in args:
|
for arg in command_args:
|
||||||
help_string += f'`{arg.name}'
|
help_string += f'`{arg.name}'
|
||||||
if arg.aliases:
|
if arg.aliases:
|
||||||
help_string += f' ({", ".join(arg.aliases)})'
|
help_string += f' ({", ".join(arg.aliases)})'
|
||||||
help_string += f': {arg.type.name}`\n {arg.description}\n'
|
help_string += f': {arg.type.name}'
|
||||||
|
if arg.default is not None:
|
||||||
|
help_string += f' = {arg.default}'
|
||||||
|
help_string += '`\n'
|
||||||
|
if arg.description:
|
||||||
|
help_string += f' {arg.description}\n'
|
||||||
|
|
||||||
help_string += '\n'
|
help_string += '\n'
|
||||||
return help_string
|
return help_string
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'Command({self.command}, prefix={self.prefix}, incoming={self.incoming}, outgoing={self.outgoing}, aliases={self.aliases}, silent={self.silent}, hidden={self.hidden}, usage={self.usage}, description={self.description}, args={self.args})'
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import Dict, Union
|
from typing import Dict, Union
|
||||||
from telethon import TelegramClient
|
from telethon import Client as TelegramClient
|
||||||
from telethon.events import NewMessage
|
from telethon.events import NewMessage
|
||||||
from telethon.tl.custom.message import Message
|
from telethon._impl.client.types import Message
|
||||||
|
|
||||||
from .. import bot
|
from .. import bot
|
||||||
from .arg_parser import Arg
|
from .arg_parser import Arg
|
||||||
|
@ -26,9 +26,6 @@ class CommandContext:
|
||||||
# The event that triggered this command
|
# The event that triggered this command
|
||||||
event: NewMessage,
|
event: NewMessage,
|
||||||
|
|
||||||
# The message from the event
|
|
||||||
message: Message,
|
|
||||||
|
|
||||||
# The message that was replied to
|
# The message that was replied to
|
||||||
reply_to: Union[Message, None],
|
reply_to: Union[Message, None],
|
||||||
|
|
||||||
|
@ -40,7 +37,6 @@ class CommandContext:
|
||||||
self.raw_text = raw_text
|
self.raw_text = raw_text
|
||||||
self.text = text
|
self.text = text
|
||||||
self.event = event
|
self.event = event
|
||||||
self.message = message
|
|
||||||
self.reply_to = reply_to
|
self.reply_to = reply_to
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
|
@ -49,8 +45,11 @@ class CommandContext:
|
||||||
|
|
||||||
async def respond(self, *args, **kwargs):
|
async def respond(self, *args, **kwargs):
|
||||||
"""Respond to the message that triggered this command."""
|
"""Respond to the message that triggered this command."""
|
||||||
await self.message.respond(*args, **kwargs)
|
await self.event.respond(*args, **kwargs)
|
||||||
|
|
||||||
async def reply(self, *args, **kwargs):
|
async def reply(self, *args, **kwargs):
|
||||||
"""Reply to the message that triggered this command."""
|
"""Reply to the message that triggered this command."""
|
||||||
await self.message.reply(*args, **kwargs)
|
await self.event.reply(*args, **kwargs)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'CommandContext(raw_text={self.raw_text}, text={self.text}, args={self.args})'
|
|
@ -1,5 +1,8 @@
|
||||||
|
import os
|
||||||
from .arg_parser import Arg, ArgType
|
from .arg_parser import Arg, ArgType
|
||||||
|
|
||||||
|
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
|
||||||
|
|
||||||
# Args that exist on every command
|
# Args that exist on every command
|
||||||
GLOBAL_ARGS = [
|
GLOBAL_ARGS = [
|
||||||
Arg("delete", type=ArgType.bool, aliases=['d', 'del'], default=False, description="Delete the message that triggered this command", global_arg=True)
|
Arg("delete", type=ArgType.bool, aliases=['d', 'del'], default=False, description="Delete the message that triggered this command", global_arg=True)
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from telethon import events
|
||||||
|
from telethon._impl.tl.types import User, Chat, Channel
|
||||||
|
|
||||||
|
from .. import bot
|
||||||
|
from cyber_fenneko.models.chat import Chat as Entity, ChatType
|
||||||
|
|
||||||
|
def is_incoming(event):
|
||||||
|
return not event._raw.out
|
||||||
|
|
||||||
|
@bot.client.on(events.NewMessage, filter=is_incoming)
|
||||||
|
async def caching(event: events.NewMessage):
|
||||||
|
chat = event.sender
|
||||||
|
if chat is not None:
|
||||||
|
ent = Entity.objects(id=chat.id).first() or Entity()
|
||||||
|
ent.id = chat.id
|
||||||
|
ent.name = chat.name
|
||||||
|
ent.username = chat.username
|
||||||
|
|
||||||
|
if isinstance(chat, User):
|
||||||
|
ent.phone = chat.phone
|
||||||
|
ent.chat_type = ChatType.USER
|
||||||
|
elif isinstance(chat, Chat):
|
||||||
|
ent.chat_type = ChatType.GROUP
|
||||||
|
elif isinstance(chat, Channel):
|
||||||
|
ent.chat_type = ChatType.CHANNEL
|
||||||
|
|
||||||
|
if not ent.packed:
|
||||||
|
ent.packed = chat.pack().__bytes__()
|
||||||
|
|
||||||
|
ent.updated_at = datetime.utcnow()
|
||||||
|
ent.save()
|
||||||
|
|
||||||
|
channel = event.chat
|
||||||
|
if channel is not None:
|
||||||
|
ent = Entity.objects(id=channel.id).first() or Entity()
|
||||||
|
ent.id = channel.id
|
||||||
|
ent.name = channel.name
|
||||||
|
ent.username = channel.username
|
||||||
|
|
||||||
|
if isinstance(chat, User):
|
||||||
|
ent.phone = chat.phone
|
||||||
|
ent.chat_type = ChatType.USER
|
||||||
|
elif isinstance(chat, Chat):
|
||||||
|
ent.chat_type = ChatType.GROUP
|
||||||
|
elif isinstance(chat, Channel):
|
||||||
|
ent.chat_type = ChatType.CHANNEL
|
||||||
|
|
||||||
|
if not ent.packed:
|
||||||
|
ent.packed = channel.pack().__bytes__()
|
||||||
|
|
||||||
|
ent.updated_at = datetime.utcnow()
|
||||||
|
ent.save()
|
|
@ -0,0 +1,30 @@
|
||||||
|
from enum import Enum
|
||||||
|
from mongoengine import Document, IntField, StringField, DateTimeField, BinaryField, EnumField
|
||||||
|
from telethon._impl.session import PackedChat
|
||||||
|
|
||||||
|
class ChatType(Enum):
|
||||||
|
USER = 1
|
||||||
|
GROUP = 2
|
||||||
|
CHANNEL = 3
|
||||||
|
|
||||||
|
class Chat(Document):
|
||||||
|
id = IntField(primary_key=True)
|
||||||
|
name = StringField()
|
||||||
|
username = StringField()
|
||||||
|
phone = StringField()
|
||||||
|
name = StringField()
|
||||||
|
packed = BinaryField()
|
||||||
|
chat_type = EnumField(ChatType)
|
||||||
|
created_at = DateTimeField()
|
||||||
|
updated_at = DateTimeField(required=True)
|
||||||
|
meta = {
|
||||||
|
'collection': 'entities',
|
||||||
|
'indexes': [
|
||||||
|
'username',
|
||||||
|
'phone',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def unpack(self):
|
||||||
|
if self.packed:
|
||||||
|
return PackedChat.from_bytes(self.packed)
|
|
@ -0,0 +1,12 @@
|
||||||
|
from .chat import Chat
|
||||||
|
from mongoengine import Document, StringField, DateTimeField, IntField, BooleanField
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class Paste(Document):
|
||||||
|
"""Contains a record of a paste creation on Paste69"""
|
||||||
|
url = StringField(required=True)
|
||||||
|
language = StringField(required=True)
|
||||||
|
chat = Chat()
|
||||||
|
author = Chat()
|
||||||
|
message_id = IntField()
|
||||||
|
created_at = DateTimeField(default=datetime.utcnow)
|
|
@ -0,0 +1,32 @@
|
||||||
|
from mongoengine import Document, StringField, IntField, BooleanField, EmbeddedDocument, EmbeddedDocumentField
|
||||||
|
|
||||||
|
class HighlightSettings(EmbeddedDocument):
|
||||||
|
"""Stores settings for the highlight command"""
|
||||||
|
theme = StringField()
|
||||||
|
font = StringField()
|
||||||
|
shadow_color = StringField()
|
||||||
|
background = StringField()
|
||||||
|
tab_width = IntField()
|
||||||
|
line_pad = IntField()
|
||||||
|
line_offset = IntField()
|
||||||
|
window_title = StringField()
|
||||||
|
no_line_number = BooleanField()
|
||||||
|
no_round_corner = BooleanField()
|
||||||
|
no_window_controls = BooleanField()
|
||||||
|
shadow_blur_radius = IntField()
|
||||||
|
shadow_offset_x = IntField()
|
||||||
|
shadow_offset_y = IntField()
|
||||||
|
pad_horiz = IntField()
|
||||||
|
pad_vert = IntField()
|
||||||
|
highlight_lines = StringField()
|
||||||
|
background_image = StringField()
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(Document):
|
||||||
|
"""Stores configuration settings for the bot"""
|
||||||
|
highlight = EmbeddedDocumentField(HighlightSettings)
|
||||||
|
search_engine = StringField(default='google')
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
'collection': 'settings'
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
import jsonpickle
|
||||||
|
from typing import Optional
|
||||||
|
from telethon._impl.tl.abcs import UserStatus
|
||||||
|
from telethon._impl.tl.core import Serializable
|
||||||
|
from telethon._impl.tl.types import UserStatusRecently, UserStatusOnline, UserStatusOffline, UserStatusLastWeek, UserStatusLastMonth, UserStatusEmpty
|
||||||
|
|
||||||
|
from cyber_fenneko.models.chat import Chat
|
||||||
|
|
||||||
|
# Format time (in ms) to a human readable format.
|
||||||
|
def format_time(ms: float) -> str:
|
||||||
|
time = str('%.2f', ms)
|
||||||
|
unit = 'millis'
|
||||||
|
|
||||||
|
if time > 1000000:
|
||||||
|
mins = time / 60000
|
||||||
|
secs = time % 60000
|
||||||
|
time = '%d.%.2f' % (mins, secs)
|
||||||
|
unit = 'mins'
|
||||||
|
if time > 1000:
|
||||||
|
secs = time / 1000
|
||||||
|
millis = time % 1000
|
||||||
|
time = '%d.%.2f' % (secs, millis)
|
||||||
|
unit = 'secs'
|
||||||
|
|
||||||
|
return f'{time} {unit}'
|
||||||
|
|
||||||
|
# Format a boolean as a simple yes/no string.
|
||||||
|
def format_bool(value: bool) -> str:
|
||||||
|
return 'Yes' if value else 'No'
|
||||||
|
|
||||||
|
# Convert a TypeUserStatus to a string.
|
||||||
|
def format_user_status(status: UserStatus) -> str:
|
||||||
|
if isinstance(status, UserStatusRecently):
|
||||||
|
return 'Recently'
|
||||||
|
elif isinstance(status, UserStatusOnline):
|
||||||
|
return 'Online'
|
||||||
|
elif isinstance(status, UserStatusOffline):
|
||||||
|
return 'Offline'
|
||||||
|
elif isinstance(status, UserStatusLastWeek):
|
||||||
|
return 'Last week'
|
||||||
|
elif isinstance(status, UserStatusLastMonth):
|
||||||
|
return 'Last month'
|
||||||
|
elif isinstance(status, UserStatusEmpty):
|
||||||
|
return 'Empty'
|
||||||
|
else:
|
||||||
|
return 'Unknown'
|
||||||
|
|
||||||
|
def to_dict(obj: object) -> dict:
|
||||||
|
if obj is None or isinstance(obj, (bool, int, bytes, str)): return obj
|
||||||
|
if isinstance(obj, (list, tuple)): return [to_dict(v) for v in obj]
|
||||||
|
if isinstance(obj, dict): return {k: to_dict(v) for k, v in obj.items()}
|
||||||
|
if hasattr(obj, '_from_raw') or isinstance(obj, Serializable):
|
||||||
|
props = dir(obj)
|
||||||
|
return {k: to_dict(getattr(obj, k)) for k in props if not k.startswith('_') and not callable(getattr(obj, k))}
|
||||||
|
return obj.__repr__()
|
||||||
|
|
||||||
|
def get_chat_by_id(id: int) -> Optional[Chat]:
|
||||||
|
return Chat.objects(id=id).first()
|
||||||
|
|
||||||
|
def get_chat_by_username(username: str) -> Optional[Chat]:
|
||||||
|
username = username.lstrip('@')
|
||||||
|
return Chat.objects(username=username).first()
|
||||||
|
|
||||||
|
def get_chat_by_phone(phone: str) -> Optional[Chat]:
|
||||||
|
return Chat.objects(phone=phone).first()
|
|
@ -9,6 +9,7 @@ def paste(text: str, language: str = 'txt', password = None, burn = False) -> st
|
||||||
'contents': text,
|
'contents': text,
|
||||||
'password': password,
|
'password': password,
|
||||||
'burnAfterReading': burn,
|
'burnAfterReading': burn,
|
||||||
|
'raw': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
response = httpx.post(ENDPOINT, json=data)
|
response = httpx.post(ENDPOINT, json=data)
|
||||||
|
|
|
@ -1,14 +1,25 @@
|
||||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyio"
|
name = "annotated-types"
|
||||||
version = "4.0.0"
|
version = "0.6.0"
|
||||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
description = "Reusable constraint types to use with typing.Annotated"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"},
|
{file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
|
||||||
{file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"},
|
{file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyio"
|
||||||
|
version = "3.7.1"
|
||||||
|
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
|
||||||
|
{file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -16,9 +27,9 @@ idna = ">=2.8"
|
||||||
sniffio = ">=1.1"
|
sniffio = ">=1.1"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"]
|
doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
|
||||||
test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
|
test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
|
||||||
trio = ["trio (>=0.22)"]
|
trio = ["trio (<0.22)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
|
@ -31,6 +42,47 @@ files = [
|
||||||
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
|
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
description = "Cross-platform colored terminal text."
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "distro"
|
||||||
|
version = "1.8.0"
|
||||||
|
description = "Distro - an OS platform information API"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "distro-1.8.0-py3-none-any.whl", hash = "sha256:99522ca3e365cac527b44bde033f64c6945d90eb9f769703caaec52b09bbd3ff"},
|
||||||
|
{file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dnspython"
|
||||||
|
version = "2.4.2"
|
||||||
|
description = "DNS toolkit"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8,<4.0"
|
||||||
|
files = [
|
||||||
|
{file = "dnspython-2.4.2-py3-none-any.whl", hash = "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8"},
|
||||||
|
{file = "dnspython-2.4.2.tar.gz", hash = "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dnssec = ["cryptography (>=2.6,<42.0)"]
|
||||||
|
doh = ["h2 (>=4.1.0)", "httpcore (>=0.17.3)", "httpx (>=0.24.1)"]
|
||||||
|
doq = ["aioquic (>=0.9.20)"]
|
||||||
|
idna = ["idna (>=2.1,<4.0)"]
|
||||||
|
trio = ["trio (>=0.14,<0.23)"]
|
||||||
|
wmi = ["wmi (>=1.5.1,<2.0.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h11"
|
name = "h11"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
@ -44,39 +96,40 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpcore"
|
name = "httpcore"
|
||||||
version = "0.18.0"
|
version = "1.0.1"
|
||||||
description = "A minimal low-level HTTP client."
|
description = "A minimal low-level HTTP client."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"},
|
{file = "httpcore-1.0.1-py3-none-any.whl", hash = "sha256:c5e97ef177dca2023d0b9aad98e49507ef5423e9f1d94ffe2cfe250aa28e63b0"},
|
||||||
{file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"},
|
{file = "httpcore-1.0.1.tar.gz", hash = "sha256:fce1ddf9b606cfb98132ab58865c3728c52c8e4c3c46e2aabb3674464a186e92"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
anyio = ">=3.0,<5.0"
|
|
||||||
certifi = "*"
|
certifi = "*"
|
||||||
h11 = ">=0.13,<0.15"
|
h11 = ">=0.13,<0.15"
|
||||||
sniffio = "==1.*"
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
asyncio = ["anyio (>=4.0,<5.0)"]
|
||||||
http2 = ["h2 (>=3,<5)"]
|
http2 = ["h2 (>=3,<5)"]
|
||||||
socks = ["socksio (==1.*)"]
|
socks = ["socksio (==1.*)"]
|
||||||
|
trio = ["trio (>=0.22.0,<0.23.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httpx"
|
name = "httpx"
|
||||||
version = "0.25.0"
|
version = "0.25.1"
|
||||||
description = "The next generation HTTP client."
|
description = "The next generation HTTP client."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"},
|
{file = "httpx-0.25.1-py3-none-any.whl", hash = "sha256:fec7d6cc5c27c578a391f7e87b9aa7d3d8fbcd034f6399f9f79b45bcc12a866a"},
|
||||||
{file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"},
|
{file = "httpx-0.25.1.tar.gz", hash = "sha256:ffd96d5cf901e63863d9f1b4b6807861dbea4d301613415d9e6e57ead15fc5d0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
anyio = "*"
|
||||||
certifi = "*"
|
certifi = "*"
|
||||||
httpcore = ">=0.18.0,<0.19.0"
|
httpcore = "*"
|
||||||
idna = "*"
|
idna = "*"
|
||||||
sniffio = "*"
|
sniffio = "*"
|
||||||
|
|
||||||
|
@ -97,6 +150,93 @@ files = [
|
||||||
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonpickle"
|
||||||
|
version = "3.0.2"
|
||||||
|
description = "Python library for serializing any arbitrary object graph into JSON"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "jsonpickle-3.0.2-py3-none-any.whl", hash = "sha256:4a8442d97ca3f77978afa58068768dba7bff2dbabe79a9647bc3cdafd4ef019f"},
|
||||||
|
{file = "jsonpickle-3.0.2.tar.gz", hash = "sha256:e37abba4bfb3ca4a4647d28bb9f4706436f7b46c8a8333b4a718abafa8e46b37"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["jaraco.packaging (>=3.2)", "rst.linker (>=1.9)", "sphinx"]
|
||||||
|
testing = ["ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-black-multipy", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-flake8 (>=1.1.1)", "scikit-learn", "sqlalchemy"]
|
||||||
|
testing-libs = ["simplejson", "ujson"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "3.0.0"
|
||||||
|
description = "Python port of markdown-it. Markdown parsing, done right!"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
|
||||||
|
{file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mdurl = ">=0.1,<1.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
|
||||||
|
code-style = ["pre-commit (>=3.0,<4.0)"]
|
||||||
|
compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
|
||||||
|
linkify = ["linkify-it-py (>=1,<3)"]
|
||||||
|
plugins = ["mdit-py-plugins"]
|
||||||
|
profiling = ["gprof2dot"]
|
||||||
|
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
||||||
|
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
description = "Markdown URL utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
|
||||||
|
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mongoengine"
|
||||||
|
version = "0.27.0"
|
||||||
|
description = "MongoEngine is a Python Object-Document Mapper for working with MongoDB."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "mongoengine-0.27.0-py3-none-any.whl", hash = "sha256:c3523b8f886052f3deb200b3218bcc13e4b781661e3bea38587cc936c80ea358"},
|
||||||
|
{file = "mongoengine-0.27.0.tar.gz", hash = "sha256:8f38df7834dc4b192d89f2668dcf3091748d12f74d55648ce77b919167a4a49b"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pymongo = ">=3.4,<5.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openai"
|
||||||
|
version = "1.1.1"
|
||||||
|
description = "Client library for the openai API"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.1"
|
||||||
|
files = [
|
||||||
|
{file = "openai-1.1.1-py3-none-any.whl", hash = "sha256:1496418b132c88352bcfffa8c24e83a69f0e01b1484cbb7bb48f722aad8fd6e1"},
|
||||||
|
{file = "openai-1.1.1.tar.gz", hash = "sha256:80e49cb21d8445f6d51339b8af7376fc83302c78ab78578b78133ef89634869d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
anyio = ">=3.5.0,<4"
|
||||||
|
distro = ">=1.7.0,<2"
|
||||||
|
httpx = ">=0.23.0,<1"
|
||||||
|
pydantic = ">=1.9.0,<3"
|
||||||
|
tqdm = ">4"
|
||||||
|
typing-extensions = ">=4.5,<5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyaes"
|
name = "pyaes"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
@ -118,6 +258,245 @@ files = [
|
||||||
{file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"},
|
{file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.4.2"
|
||||||
|
description = "Data validation using Python type hints"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"},
|
||||||
|
{file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
annotated-types = ">=0.4.0"
|
||||||
|
pydantic-core = "2.10.1"
|
||||||
|
typing-extensions = ">=4.6.1"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
email = ["email-validator (>=2.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-core"
|
||||||
|
version = "2.10.1"
|
||||||
|
description = ""
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"},
|
||||||
|
{file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"},
|
||||||
|
{file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"},
|
||||||
|
{file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pymongo"
|
||||||
|
version = "4.6.0"
|
||||||
|
description = "Python driver for MongoDB <http://www.mongodb.org>"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c011bd5ad03cc096f99ffcfdd18a1817354132c1331bed7a837a25226659845f"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux1_i686.whl", hash = "sha256:5e63146dbdb1eac207464f6e0cfcdb640c9c5ff0f57b754fa96fe252314a1dc6"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:2972dd1f1285866aba027eff2f4a2bbf8aa98563c2ced14cb34ee5602b36afdf"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux2014_i686.whl", hash = "sha256:a0be99b599da95b7a90a918dd927b20c434bea5e1c9b3efc6a3c6cd67c23f813"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux2014_ppc64le.whl", hash = "sha256:9b0f98481ad5dc4cb430a60bbb8869f05505283b9ae1c62bdb65eb5e020ee8e3"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux2014_s390x.whl", hash = "sha256:256c503a75bd71cf7fb9ebf889e7e222d49c6036a48aad5a619f98a0adf0e0d7"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:b4ad70d7cac4ca0c7b31444a0148bd3af01a2662fa12b1ad6f57cd4a04e21766"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5717a308a703dda2886a5796a07489c698b442f5e409cf7dc2ac93de8d61d764"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f7f9feecae53fa18d6a3ea7c75f9e9a1d4d20e5c3f9ce3fba83f07bcc4eee2"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128b1485753106c54af481789cdfea12b90a228afca0b11fb3828309a907e10e"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3077a31633beef77d057c6523f5de7271ddef7bde5e019285b00c0cc9cac1e3"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebf02c32afa6b67e5861a27183dd98ed88419a94a2ab843cc145fb0bafcc5b28"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-win32.whl", hash = "sha256:b14dd73f595199f4275bed4fb509277470d9b9059310537e3b3daba12b30c157"},
|
||||||
|
{file = "pymongo-4.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:8adf014f2779992eba3b513e060d06f075f0ab2fb3ad956f413a102312f65cdf"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba51129fcc510824b6ca6e2ce1c27e3e4d048b6e35d3ae6f7e517bed1b8b25ce"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2973f113e079fb98515722cd728e1820282721ec9fd52830e4b73cabdbf1eb28"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af425f323fce1b07755edd783581e7283557296946212f5b1a934441718e7528"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ec71ac633b126c0775ed4604ca8f56c3540f5c21a1220639f299e7a544b55f9"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ec6c20385c5a58e16b1ea60c5e4993ea060540671d7d12664f385f2fb32fe79"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:85f2cdc400ee87f5952ebf2a117488f2525a3fb2e23863a8efe3e4ee9e54e4d1"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-win32.whl", hash = "sha256:7fc2bb8a74dcfcdd32f89528e38dcbf70a3a6594963d60dc9595e3b35b66e414"},
|
||||||
|
{file = "pymongo-4.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6695d7136a435c1305b261a9ddb9b3ecec9863e05aab3935b96038145fd3a977"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d603edea1ff7408638b2504905c032193b7dcee7af269802dbb35bc8c3310ed5"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79f41576b3022c2fe9780ae3e44202b2438128a25284a8ddfa038f0785d87019"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f2af6cf82509b15093ce3569229e0d53c90ad8ae2eef940652d4cf1f81e045"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecd9e1fa97aa11bf67472220285775fa15e896da108f425e55d23d7540a712ce"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d2be5c9c3488fa8a70f83ed925940f488eac2837a996708d98a0e54a861f212"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab6bcc8e424e07c1d4ba6df96f7fb963bcb48f590b9456de9ebd03b88084fe8"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-win32.whl", hash = "sha256:47aa128be2e66abd9d1a9b0437c62499d812d291f17b55185cb4aa33a5f710a4"},
|
||||||
|
{file = "pymongo-4.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:014e7049dd019a6663747ca7dae328943e14f7261f7c1381045dfc26a04fa330"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:288c21ab9531b037f7efa4e467b33176bc73a0c27223c141b822ab4a0e66ff2a"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:747c84f4e690fbe6999c90ac97246c95d31460d890510e4a3fa61b7d2b87aa34"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:055f5c266e2767a88bb585d01137d9c7f778b0195d3dbf4a487ef0638be9b651"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:82e620842e12e8cb4050d2643a81c8149361cd82c0a920fa5a15dc4ca8a4000f"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:6b18276f14b4b6d92e707ab6db19b938e112bd2f1dc3f9f1a628df58e4fd3f0d"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:680fa0fc719e1a3dcb81130858368f51d83667d431924d0bcf249644bce8f303"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:3919708594b86d0f5cdc713eb6fccd3f9b9532af09ea7a5d843c933825ef56c4"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db082f728160369d9a6ed2e722438291558fc15ce06d0a7d696a8dad735c236b"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e4ed21029d80c4f62605ab16398fe1ce093fff4b5f22d114055e7d9fbc4adb0"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bea9138b0fc6e2218147e9c6ce1ff76ff8e29dc00bb1b64842bd1ca107aee9f"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a0269811661ba93c472c8a60ea82640e838c2eb148d252720a09b5123f2c2fe"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d6a1b1361f118e7fefa17ae3114e77f10ee1b228b20d50c47c9f351346180c8"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e3b0127b260d4abae7b62203c4c7ef0874c901b55155692353db19de4b18bc4"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a49aca4d961823b2846b739380c847e8964ff7ae0f0a683992b9d926054f0d6d"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-win32.whl", hash = "sha256:09c7de516b08c57647176b9fc21d929d628e35bcebc7422220c89ae40b62126a"},
|
||||||
|
{file = "pymongo-4.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:81dd1308bd5630d2bb5980f00aa163b986b133f1e9ed66c66ce2a5bc3572e891"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:2f8c04277d879146eacda920476e93d520eff8bec6c022ac108cfa6280d84348"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5802acc012bbb4bce4dff92973dff76482f30ef35dd4cb8ab5b0e06aa8f08c80"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ccd785fafa1c931deff6a7116e9a0d402d59fabe51644b0d0c268295ff847b25"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fe03bf25fae4b95d8afe40004a321df644400fdcba4c8e5e1a19c1085b740888"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:2ca0ba501898b2ec31e6c3acf90c31910944f01d454ad8e489213a156ccf1bda"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:10a379fb60f1b2406ae57b8899bacfe20567918c8e9d2d545e1b93628fcf2050"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:a4dc1319d0c162919ee7f4ee6face076becae2abbd351cc14f1fe70af5fb20d9"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ddef295aaf80cefb0c1606f1995899efcb17edc6b327eb6589e234e614b87756"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:518c90bdd6e842c446d01a766b9136fec5ec6cc94f3b8c3f8b4a332786ee6b64"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b80a4ee19b3442c57c38afa978adca546521a8822d663310b63ae2a7d7b13f3a"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb438a8bf6b695bf50d57e6a059ff09652a07968b2041178b3744ea785fcef9b"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3db7d833a7c38c317dc95b54e27f1d27012e031b45a7c24e360b53197d5f6e7"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3729b8db02063da50eeb3db88a27670d85953afb9a7f14c213ac9e3dca93034b"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:39a1cd5d383b37285641d5a7a86be85274466ae336a61b51117155936529f9b3"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7b0e6361754ac596cd16bfc6ed49f69ffcd9b60b7bc4bcd3ea65c6a83475e4ff"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-win32.whl", hash = "sha256:806e094e9e85d8badc978af8c95b69c556077f11844655cb8cd2d1758769e521"},
|
||||||
|
{file = "pymongo-4.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1394c4737b325166a65ae7c145af1ebdb9fb153ebedd37cf91d676313e4a67b8"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a8273e1abbcff1d7d29cbbb1ea7e57d38be72f1af3c597c854168508b91516c2"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:e16ade71c93f6814d095d25cd6d28a90d63511ea396bd96e9ffcb886b278baaa"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:325701ae7b56daa5b0692305b7cb505ca50f80a1288abb32ff420a8a209b01ca"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:cc94f9fea17a5af8cf1a343597711a26b0117c0b812550d99934acb89d526ed2"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:21812453354b151200034750cd30b0140e82ec2a01fd4357390f67714a1bfbde"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:0634994b026336195778e5693583c060418d4ab453eff21530422690a97e1ee8"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:ad4f66fbb893b55f96f03020e67dcab49ffde0177c6565ccf9dec4fdf974eb61"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:2703a9f8f5767986b4f51c259ff452cc837c5a83c8ed5f5361f6e49933743b2f"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bafea6061d63059d8bc2ffc545e2f049221c8a4457d236c5cd6a66678673eab"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f28ae33dc5a0b9cee06e95fd420e42155d83271ab75964baf747ce959cac5f52"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16a534da0e39785687b7295e2fcf9a339f4a20689024983d11afaa4657f8507"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef67fedd863ffffd4adfd46d9d992b0f929c7f61a8307366d664d93517f2c78e"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05c30fd35cc97f14f354916b45feea535d59060ef867446b5c3c7f9b609dd5dc"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c63e3a2e8fb815c4b1f738c284a4579897e37c3cfd95fdb199229a1ccfb638a"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e5e193f89f4f8c1fe273f9a6e6df915092c9f2af6db2d1afb8bd53855025c11f"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-win32.whl", hash = "sha256:a09bfb51953930e7e838972ddf646c5d5f984992a66d79da6ba7f6a8d8a890cd"},
|
||||||
|
{file = "pymongo-4.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:107a234dc55affc5802acb3b6d83cbb8c87355b38a9457fcd8806bdeb8bce161"},
|
||||||
|
{file = "pymongo-4.6.0.tar.gz", hash = "sha256:fb1c56d891f9e34303c451998ef62ba52659648bb0d75b03c5e4ac223a3342c2"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
dnspython = ">=1.16.0,<3.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
aws = ["pymongo-auth-aws (<2.0.0)"]
|
||||||
|
encryption = ["certifi", "pymongo[aws]", "pymongocrypt (>=1.6.0,<2.0.0)"]
|
||||||
|
gssapi = ["pykerberos", "winkerberos (>=0.5.0)"]
|
||||||
|
ocsp = ["certifi", "cryptography (>=2.5)", "pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"]
|
||||||
|
snappy = ["python-snappy"]
|
||||||
|
test = ["pytest (>=7)"]
|
||||||
|
zstd = ["zstandard"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dotenv"
|
name = "python-dotenv"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -158,23 +537,80 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "telethon"
|
name = "telemongo"
|
||||||
version = "1.30.3"
|
version = "0.2.2"
|
||||||
description = "Full-featured Telegram client library for Python 3"
|
description = "MongoDB backend for Telethon session storage"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = "^3.9"
|
||||||
|
files = []
|
||||||
|
develop = true
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mongoengine = "^0.27.0"
|
||||||
|
telethon = {git = "https://github.com/LonamiWebs/Telethon", rev = "v2", subdirectory = "client"}
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "directory"
|
||||||
|
url = "../telethon-session-mongo"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "Telethon"
|
||||||
|
version = "2.0.0a0"
|
||||||
|
description = "Full-featured Telegram client library"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = []
|
||||||
|
develop = false
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
markdown-it-py = ">=3.0,<4.0"
|
||||||
|
pyaes = ">=1.6,<2.0"
|
||||||
|
rsa = ">=4.9,<5.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
cryptg = ["cryptg (>=0.4,<1.0)"]
|
||||||
|
dev = ["black (>=23.3.0,<23.4.0)", "isort (>=5.12,<6.0)", "mypy (>=1.3,<2.0)", "pytest (>=7.3,<8.0)", "pytest-asyncio (>=0.21,<1.0)", "ruff (>=0.0.292,<0.1.0)"]
|
||||||
|
doc = ["sphinx_rtd_theme (>=1.2,<2.0)", "types-docutils (>=0.20,<1.0)"]
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "git"
|
||||||
|
url = "https://github.com/LonamiWebs/Telethon"
|
||||||
|
reference = "v2"
|
||||||
|
resolved_reference = "ae44426a78d553cd1a3ea9f536c0f2c90751d657"
|
||||||
|
subdirectory = "client"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tqdm"
|
||||||
|
version = "4.66.1"
|
||||||
|
description = "Fast, Extensible Progress Meter"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "Telethon-1.30.3.tar.gz", hash = "sha256:313e40fa06667b19ced13b379d9988167a8319bc0eb90bf39347cff46919a351"},
|
{file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"},
|
||||||
|
{file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyaes = "*"
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
rsa = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
cryptg = ["cryptg"]
|
dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"]
|
||||||
|
notebook = ["ipywidgets (>=6)"]
|
||||||
|
slack = ["slack-sdk"]
|
||||||
|
telegram = ["requests"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.8.0"
|
||||||
|
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
|
||||||
|
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
|
||||||
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "9ef099a5cfddbb3a84d27506f528e2edca10562fad5dabeb22bd64d49d9c1b04"
|
content-hash = "4dcc24786204463583f6e954cb90106d79ec504ffa7f3f9ad321444e55cc5e9a"
|
||||||
|
|
|
@ -10,10 +10,14 @@ fenneko = "cyber_fenneko.__main__:main"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.11"
|
python = "^3.11"
|
||||||
telethon = "^1.30.3"
|
# telethon = "^1.30.3"
|
||||||
python-dotenv = "^1.0.0"
|
python-dotenv = "^1.0.0"
|
||||||
httpx = "^0.25.0"
|
httpx = "^0.25.0"
|
||||||
|
openai = {version = "^1.0.0b3", allow-prereleases = true}
|
||||||
|
telemongo = {path = "../telethon-session-mongo", develop=true}
|
||||||
|
mongoengine = "^0.27.0"
|
||||||
|
telethon = {git = "https://github.com/LonamiWebs/Telethon", rev = "v2", subdirectory = "client"}
|
||||||
|
jsonpickle = "^3.0.2"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|
|
@ -4,6 +4,9 @@ anyio==4.0.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
certifi==2023.7.22 ; python_version >= "3.11" and python_version < "4.0" \
|
certifi==2023.7.22 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \
|
--hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \
|
||||||
--hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9
|
--hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9
|
||||||
|
dnspython==2.4.2 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
|
--hash=sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8 \
|
||||||
|
--hash=sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984
|
||||||
h11==0.14.0 ; python_version >= "3.11" and python_version < "4.0" \
|
h11==0.14.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||||
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
|
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
|
||||||
|
@ -16,11 +19,96 @@ httpx==0.25.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
idna==3.4 ; python_version >= "3.11" and python_version < "4.0" \
|
idna==3.4 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
|
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
|
||||||
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
|
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
|
||||||
|
mongoengine==0.27.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
|
--hash=sha256:8f38df7834dc4b192d89f2668dcf3091748d12f74d55648ce77b919167a4a49b \
|
||||||
|
--hash=sha256:c3523b8f886052f3deb200b3218bcc13e4b781661e3bea38587cc936c80ea358
|
||||||
pyaes==1.6.1 ; python_version >= "3.11" and python_version < "4.0" \
|
pyaes==1.6.1 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f
|
--hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f
|
||||||
pyasn1==0.5.0 ; python_version >= "3.11" and python_version < "4" \
|
pyasn1==0.5.0 ; python_version >= "3.11" and python_version < "4" \
|
||||||
--hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \
|
--hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \
|
||||||
--hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde
|
--hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde
|
||||||
|
pymongo==4.5.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
|
--hash=sha256:076afa0a4a96ca9f77fec0e4a0d241200b3b3a1766f8d7be9a905ecf59a7416b \
|
||||||
|
--hash=sha256:08819da7864f9b8d4a95729b2bea5fffed08b63d3b9c15b4fea47de655766cf5 \
|
||||||
|
--hash=sha256:0a1f26bc1f5ce774d99725773901820dfdfd24e875028da4a0252a5b48dcab5c \
|
||||||
|
--hash=sha256:0f4b125b46fe377984fbaecf2af40ed48b05a4b7676a2ff98999f2016d66b3ec \
|
||||||
|
--hash=sha256:1240edc1a448d4ada4bf1a0e55550b6292420915292408e59159fd8bbdaf8f63 \
|
||||||
|
--hash=sha256:152259f0f1a60f560323aacf463a3642a65a25557683f49cfa08c8f1ecb2395a \
|
||||||
|
--hash=sha256:168172ef7856e20ec024fe2a746bfa895c88b32720138e6438fd765ebd2b62dd \
|
||||||
|
--hash=sha256:1b1d7d9aabd8629a31d63cd106d56cca0e6420f38e50563278b520f385c0d86e \
|
||||||
|
--hash=sha256:1d40ad09d9f5e719bc6f729cc6b17f31c0b055029719406bd31dde2f72fca7e7 \
|
||||||
|
--hash=sha256:21b953da14549ff62ea4ae20889c71564328958cbdf880c64a92a48dda4c9c53 \
|
||||||
|
--hash=sha256:23cc6d7eb009c688d70da186b8f362d61d5dd1a2c14a45b890bd1e91e9c451f2 \
|
||||||
|
--hash=sha256:2988ef5e6b360b3ff1c6d55c53515499de5f48df31afd9f785d788cdacfbe2d3 \
|
||||||
|
--hash=sha256:2a0aade2b11dc0c326ccd429ee4134d2d47459ff68d449c6d7e01e74651bd255 \
|
||||||
|
--hash=sha256:2b0176f9233a5927084c79ff80b51bd70bfd57e4f3d564f50f80238e797f0c8a \
|
||||||
|
--hash=sha256:2d4fa1b01fa7e5b7bb8d312e3542e211b320eb7a4e3d8dc884327039d93cb9e0 \
|
||||||
|
--hash=sha256:3236cf89d69679eaeb9119c840f5c7eb388a2110b57af6bb6baf01a1da387c18 \
|
||||||
|
--hash=sha256:33faa786cc907de63f745f587e9879429b46033d7d97a7b84b37f4f8f47b9b32 \
|
||||||
|
--hash=sha256:37df8f6006286a5896d1cbc3efb8471ced42e3568d38e6cb00857277047b0d63 \
|
||||||
|
--hash=sha256:3a7166d57dc74d679caa7743b8ecf7dc3a1235a9fd178654dddb2b2a627ae229 \
|
||||||
|
--hash=sha256:3d79ae3bb1ff041c0db56f138c88ce1dfb0209f3546d8d6e7c3f74944ecd2439 \
|
||||||
|
--hash=sha256:3e33064f1984db412b34d51496f4ea785a9cff621c67de58e09fb28da6468a52 \
|
||||||
|
--hash=sha256:3fa3648e4f1e63ddfe53563ee111079ea3ab35c3b09cd25bc22dadc8269a495f \
|
||||||
|
--hash=sha256:40d5f6e853ece9bfc01e9129b228df446f49316a4252bb1fbfae5c3c9dedebad \
|
||||||
|
--hash=sha256:41771b22dd2822540f79a877c391283d4e6368125999a5ec8beee1ce566f3f82 \
|
||||||
|
--hash=sha256:435228d3c16a375274ac8ab9c4f9aef40c5e57ddb8296e20ecec9e2461da1017 \
|
||||||
|
--hash=sha256:44ee985194c426ddf781fa784f31ffa29cb59657b2dba09250a4245431847d73 \
|
||||||
|
--hash=sha256:465fd5b040206f8bce7016b01d7e7f79d2fcd7c2b8e41791be9632a9df1b4999 \
|
||||||
|
--hash=sha256:496c9cbcb4951183d4503a9d7d2c1e3694aab1304262f831d5e1917e60386036 \
|
||||||
|
--hash=sha256:49dce6957598975d8b8d506329d2a3a6c4aee911fa4bbcf5e52ffc6897122950 \
|
||||||
|
--hash=sha256:4c42748ccc451dfcd9cef6c5447a7ab727351fd9747ad431db5ebb18a9b78a4d \
|
||||||
|
--hash=sha256:505f8519c4c782a61d94a17b0da50be639ec462128fbd10ab0a34889218fdee3 \
|
||||||
|
--hash=sha256:53f2dda54d76a98b43a410498bd12f6034b2a14b6844ca08513733b2b20b7ad8 \
|
||||||
|
--hash=sha256:56320c401f544d762fc35766936178fbceb1d9261cd7b24fbfbc8fb6f67aa8a5 \
|
||||||
|
--hash=sha256:58a63a26a1e3dc481dd3a18d6d9f8bd1d576cd1ffe0d479ba7dd38b0aeb20066 \
|
||||||
|
--hash=sha256:5caee7bd08c3d36ec54617832b44985bd70c4cbd77c5b313de6f7fce0bb34f93 \
|
||||||
|
--hash=sha256:631492573a1bef2f74f9ac0f9d84e0ce422c251644cd81207530af4aa2ee1980 \
|
||||||
|
--hash=sha256:63d8019eee119df308a075b8a7bdb06d4720bf791e2b73d5ab0e7473c115d79c \
|
||||||
|
--hash=sha256:6422b6763b016f2ef2beedded0e546d6aa6ba87910f9244d86e0ac7690f75c96 \
|
||||||
|
--hash=sha256:681f252e43b3ef054ca9161635f81b730f4d8cadd28b3f2b2004f5a72f853982 \
|
||||||
|
--hash=sha256:6d64878d1659d2a5bdfd0f0a4d79bafe68653c573681495e424ab40d7b6d6d41 \
|
||||||
|
--hash=sha256:74c0da07c04d0781490b2915e7514b1adb265ef22af039a947988c331ee7455b \
|
||||||
|
--hash=sha256:7591a3beea6a9a4fa3080d27d193b41f631130e3ffa76b88c9ccea123f26dc59 \
|
||||||
|
--hash=sha256:76a262c41c1a7cbb84a3b11976578a7eb8e788c4b7bfbd15c005fb6ca88e6e50 \
|
||||||
|
--hash=sha256:77cfff95c1fafd09e940b3fdcb7b65f11442662fad611d0e69b4dd5d17a81c60 \
|
||||||
|
--hash=sha256:8027c9063579083746147cf401a7072a9fb6829678076cd3deff28bb0e0f50c8 \
|
||||||
|
--hash=sha256:80a167081c75cf66b32f30e2f1eaee9365af935a86dbd76788169911bed9b5d5 \
|
||||||
|
--hash=sha256:840eaf30ccac122df260b6005f9dfae4ac287c498ee91e3e90c56781614ca238 \
|
||||||
|
--hash=sha256:8543253adfaa0b802bfa88386db1009c6ebb7d5684d093ee4edc725007553d21 \
|
||||||
|
--hash=sha256:89b3f2da57a27913d15d2a07d58482f33d0a5b28abd20b8e643ab4d625e36257 \
|
||||||
|
--hash=sha256:8e559116e4128630ad3b7e788e2e5da81cbc2344dee246af44471fa650486a70 \
|
||||||
|
--hash=sha256:9aff6279e405dc953eeb540ab061e72c03cf38119613fce183a8e94f31be608f \
|
||||||
|
--hash=sha256:9c04b9560872fa9a91251030c488e0a73bce9321a70f991f830c72b3f8115d0d \
|
||||||
|
--hash=sha256:9d2346b00af524757576cc2406414562cced1d4349c92166a0ee377a2a483a80 \
|
||||||
|
--hash=sha256:a253b765b7cbc4209f1d8ee16c7287c4268d3243070bf72d7eec5aa9dfe2a2c2 \
|
||||||
|
--hash=sha256:a8127437ebc196a6f5e8fddd746bd0903a400dc6b5ae35df672dd1ccc7170a2a \
|
||||||
|
--hash=sha256:b25f7bea162b3dbec6d33c522097ef81df7c19a9300722fa6853f5b495aecb77 \
|
||||||
|
--hash=sha256:b33c17d9e694b66d7e96977e9e56df19d662031483efe121a24772a44ccbbc7e \
|
||||||
|
--hash=sha256:b4fe46b58010115514b842c669a0ed9b6a342017b15905653a5b1724ab80917f \
|
||||||
|
--hash=sha256:b520aafc6cb148bac09ccf532f52cbd31d83acf4d3e5070d84efe3c019a1adbf \
|
||||||
|
--hash=sha256:b5bbb87fa0511bd313d9a2c90294c88db837667c2bda2ea3fa7a35b59fd93b1f \
|
||||||
|
--hash=sha256:b6d2a56fc2354bb6378f3634402eec788a8f3facf0b3e7d468db5f2b5a78d763 \
|
||||||
|
--hash=sha256:bbd705d5f3c3d1ff2d169e418bb789ff07ab3c70d567cc6ba6b72b04b9143481 \
|
||||||
|
--hash=sha256:bc5d8c3647b8ae28e4312f1492b8f29deebd31479cd3abaa989090fb1d66db83 \
|
||||||
|
--hash=sha256:c3c3525ea8658ee1192cdddf5faf99b07ebe1eeaa61bf32821126df6d1b8072b \
|
||||||
|
--hash=sha256:c9a9a39b7cac81dca79fca8c2a6479ef4c7b1aab95fad7544cc0e8fd943595a2 \
|
||||||
|
--hash=sha256:cd4c8d6aa91d3e35016847cbe8d73106e3d1c9a4e6578d38e2c346bfe8edb3ca \
|
||||||
|
--hash=sha256:cf62da7a4cdec9a4b2981fcbd5e08053edffccf20e845c0b6ec1e77eb7fab61d \
|
||||||
|
--hash=sha256:d67225f05f6ea27c8dc57f3fa6397c96d09c42af69d46629f71e82e66d33fa4f \
|
||||||
|
--hash=sha256:dfcd2b9f510411de615ccedd47462dae80e82fdc09fe9ab0f0f32f11cf57eeb5 \
|
||||||
|
--hash=sha256:e1f61355c821e870fb4c17cdb318669cfbcf245a291ce5053b41140870c3e5cc \
|
||||||
|
--hash=sha256:e249190b018d63c901678053b4a43e797ca78b93fb6d17633e3567d4b3ec6107 \
|
||||||
|
--hash=sha256:e2654d1278384cff75952682d17c718ecc1ad1d6227bb0068fd826ba47d426a5 \
|
||||||
|
--hash=sha256:e57d859b972c75ee44ea2ef4758f12821243e99de814030f69a3decb2aa86807 \
|
||||||
|
--hash=sha256:e5a27f348909235a106a3903fc8e70f573d89b41d723a500869c6569a391cff7 \
|
||||||
|
--hash=sha256:ead4f19d0257a756b21ac2e0e85a37a7245ddec36d3b6008d5bfe416525967dc \
|
||||||
|
--hash=sha256:f076b779aa3dc179aa3ed861be063a313ed4e48ae9f6a8370a9b1295d4502111 \
|
||||||
|
--hash=sha256:f1bb3a62395ffe835dbef3a1cbff48fbcce709c78bd1f52e896aee990928432b \
|
||||||
|
--hash=sha256:f2227a08b091bd41df5aadee0a5037673f691e2aa000e1968b1ea2342afc6880 \
|
||||||
|
--hash=sha256:f3754acbd7efc7f1b529039fcffc092a15e1cf045e31f22f6c9c5950c613ec4d \
|
||||||
|
--hash=sha256:fe48f50fb6348511a3268a893bfd4ab5f263f5ac220782449d03cd05964d1ae7 \
|
||||||
|
--hash=sha256:fff7d17d30b2cd45afd654b3fc117755c5d84506ed25fda386494e4e0a3416e1
|
||||||
python-dotenv==1.0.0 ; python_version >= "3.11" and python_version < "4.0" \
|
python-dotenv==1.0.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
|
--hash=sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba \
|
||||||
--hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
|
--hash=sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a
|
||||||
|
@ -30,5 +118,8 @@ rsa==4.9 ; python_version >= "3.11" and python_version < "4" \
|
||||||
sniffio==1.3.0 ; python_version >= "3.11" and python_version < "4.0" \
|
sniffio==1.3.0 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||||
telethon==1.30.3 ; python_version >= "3.11" and python_version < "4.0" \
|
telemongo==0.2.2 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
--hash=sha256:313e40fa06667b19ced13b379d9988167a8319bc0eb90bf39347cff46919a351
|
--hash=sha256:02dce5c4918a305f6b75766107382fd2af4a477d05ddb512e617eacac8130a48 \
|
||||||
|
--hash=sha256:ef4a383b8c25c62a3b3f640fe4cd9a4d3c1fa0ab0b22d51e047f9f6c924c6795
|
||||||
|
telethon==1.31.1 ; python_version >= "3.11" and python_version < "4.0" \
|
||||||
|
--hash=sha256:299567c307818e0ecd1ecb208c2f4269be4ea84fdea49b5061c36362dc92abbd
|
||||||
|
|
Loading…
Reference in New Issue