v1.1
This commit is contained in:
parent
26f511535a
commit
c5e0c91828
@ -1,4 +1,9 @@
|
||||
**1.1**
|
||||
-
|
||||
- Replaced `Message` with `MessageContext`. Now API and database should will accessed by context.
|
||||
-
|
||||
|
||||
|
||||
**1.0**
|
||||
-
|
||||
---
|
||||
Initial release
|
@ -1,6 +1,6 @@
|
||||
**Kuro Core**
|
||||
-
|
||||
Требуется Python 3.6-3.11
|
||||
Требуется Python 3.6-3.12
|
||||
|
||||
|
||||
Ниже возможно работает.
|
||||
|
@ -1,8 +1,5 @@
|
||||
from .config import Config
|
||||
from .bot import Bot
|
||||
from .logger import BotLogger, RequestLogger, ClientLogger
|
||||
|
||||
from main.plugins import Plugin, MethodWithPriority
|
||||
|
||||
from main.event import ChatEvent, Event
|
||||
from main.message import Message, MessageArgs
|
||||
from .database import Database
|
||||
from .main import Plugin, MethodWithPriority, ChatEvent, Event, MessageContext, Message, Attachment
|
||||
|
@ -1,24 +1,27 @@
|
||||
import sys
|
||||
from asyncio import WindowsSelectorEventLoopPolicy, set_event_loop_policy
|
||||
from asyncio import set_event_loop_policy
|
||||
from platform import system
|
||||
|
||||
from .logger import BotLogger, RequestLogger, ClientLogger
|
||||
from .main.handler import Handler
|
||||
from kurocore.database import Database
|
||||
|
||||
|
||||
class Bot:
|
||||
__slots__ = ('config', 'is_running', 'middlewares', 'tasks')
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, load_db=False):
|
||||
BotLogger(config)
|
||||
RequestLogger(config)
|
||||
ClientLogger(config)
|
||||
self.config = config
|
||||
# Database(self.config)
|
||||
if load_db:
|
||||
Database(self.config)
|
||||
self.is_running = False
|
||||
self.middlewares = []
|
||||
self.tasks = []
|
||||
if sys.version_info >= (3, 8) and sys.platform.lower().startswith("win"):
|
||||
from asyncio import WindowsSelectorEventLoopPolicy
|
||||
set_event_loop_policy(WindowsSelectorEventLoopPolicy())
|
||||
|
||||
def add_plugin(self, plugin):
|
||||
@ -55,5 +58,5 @@ class Bot:
|
||||
handler.run()
|
||||
except KeyboardInterrupt:
|
||||
handler.shutdown()
|
||||
# if Database.db and not Database.db.is_closed():
|
||||
# Database.db.close()
|
||||
if Database.db and not Database.db.is_closed():
|
||||
Database.db.close()
|
||||
|
@ -0,0 +1,3 @@
|
||||
from .plugins import Plugin, MethodWithPriority
|
||||
from .message import Message, MessageContext, Attachment
|
||||
from .event import Event, ChatEvent
|
@ -1,11 +1,10 @@
|
||||
from kurocore.utils.vk_utils import generate_random_id
|
||||
from kurocore.vk.utils import generate_random_id
|
||||
|
||||
|
||||
class ChatEvent:
|
||||
__slots__ = ('session', 'api', 'raw', 'type', 'member_id', 'text', 'photo')
|
||||
|
||||
def __init__(self, session, api, raw: dict):
|
||||
self.session = session
|
||||
def __init__(self, api, raw: dict):
|
||||
self.api = api
|
||||
self.raw: dict = raw
|
||||
|
||||
@ -18,8 +17,7 @@ class ChatEvent:
|
||||
class Event:
|
||||
__slots__ = ('session', 'api', 'raw', 'type')
|
||||
|
||||
def __init__(self, session, api, raw: dict):
|
||||
self.session = session
|
||||
def __init__(self, api, raw: dict):
|
||||
self.api = api
|
||||
|
||||
self.raw: dict = raw['object']
|
||||
@ -35,7 +33,7 @@ class Event:
|
||||
if text:
|
||||
data.update({'message': text})
|
||||
if attachments:
|
||||
if type(attachments) == str:
|
||||
if type(attachments) is str:
|
||||
data.update({'attachment': attachments})
|
||||
else:
|
||||
data.update({'attachment': ','.join(attachments)})
|
||||
|
@ -4,11 +4,11 @@ import traceback
|
||||
from aiohttp.web import run_app
|
||||
from sentry_sdk import init as sentry_init, capture_exception, set_user
|
||||
|
||||
from kurocore.logger import BotLogger
|
||||
from kurocore.vk import VK, VKLongPoll, VkBotEventType
|
||||
from .event import ChatEvent, Event
|
||||
from kurocore.utils.database.database import Database
|
||||
from kurocore.utils.vk.longpoll import VKLongPoll, VkBotEventType
|
||||
from kurocore.utils.vk.vk import VK
|
||||
from ..logger import BotLogger
|
||||
from .message import MessageContext, Message
|
||||
from kurocore.database import Database
|
||||
|
||||
|
||||
class Handler:
|
||||
@ -145,7 +145,10 @@ class Handler:
|
||||
for before_process in p.before_process_methods:
|
||||
before_process.call()
|
||||
|
||||
await p._process_command(command, msg, args)
|
||||
ctx = MessageContext(self.api, msg, None)
|
||||
if Database.db:
|
||||
ctx.db = Database
|
||||
await p._process_command(command, ctx, args)
|
||||
return
|
||||
except Exception as e:
|
||||
if self.config.debug:
|
||||
@ -175,9 +178,9 @@ class Handler:
|
||||
if not await self.check_payload(msg):
|
||||
await self.check_command(msg)
|
||||
|
||||
# if db:
|
||||
# db.close()
|
||||
# BotLogger.log.debug('Connection closed!')
|
||||
if db:
|
||||
db.close()
|
||||
BotLogger.log.debug('Connection closed!')
|
||||
|
||||
async def check_event(self, event: (ChatEvent, Event), msg):
|
||||
event_type = event.type
|
||||
@ -220,23 +223,22 @@ class Handler:
|
||||
# self.shutdown()
|
||||
|
||||
async def handle_event(self, event):
|
||||
from kurocore import Message
|
||||
if ((event.type == VkBotEventType.MESSAGE_NEW and 'action' not in event.obj)
|
||||
or event.type == VkBotEventType.MESSAGE_EVENT):
|
||||
msg = Message(self.session, self.api, event.obj)
|
||||
msg = Message(self.api, event.obj)
|
||||
if msg.user_id > 0:
|
||||
set_user({'id': msg.user_id})
|
||||
await self.check(msg)
|
||||
|
||||
elif event.type == VkBotEventType.MESSAGE_NEW and 'action' in event.obj:
|
||||
e = ChatEvent(self.session, self.api, event.obj['action'])
|
||||
msg = Message(self.session, self.api, event.obj)
|
||||
e = ChatEvent(self.api, event.obj['action'])
|
||||
msg = Message(self.api, event.obj)
|
||||
if msg.user_id > 0:
|
||||
set_user({'id': msg.user_id})
|
||||
await self.check_event(e, msg)
|
||||
|
||||
else:
|
||||
e = Event(self.session, self.api, event.raw)
|
||||
e = Event(self.api, event.raw)
|
||||
await self.check_event(e, None)
|
||||
|
||||
async def _run(self):
|
||||
|
@ -2,9 +2,9 @@ import json
|
||||
from enum import Enum
|
||||
from typing import Union, Type, Tuple
|
||||
|
||||
from kurocore.utils.vk.keyboard import VkKeyboard
|
||||
from kurocore.utils.vk.vk import VKApiException
|
||||
from kurocore.utils.vk_utils import generate_random_id
|
||||
from kurocore.database import Database
|
||||
from kurocore.vk import VkKeyboard, VKApiException, VK
|
||||
from kurocore.vk.utils import generate_random_id
|
||||
|
||||
|
||||
class MessageArgs(dict):
|
||||
@ -137,41 +137,6 @@ class Document(VkObject):
|
||||
Attachment = Type[Photo], Type[Document], Type[Sticker]
|
||||
|
||||
|
||||
def load_attachments(raw: list[dict]) -> list[Attachment]:
|
||||
attachments = []
|
||||
for attachment in raw:
|
||||
match attachment['type']:
|
||||
case 'photo':
|
||||
attachments.append(Photo(attachment))
|
||||
case 'doc':
|
||||
attachments.append(Document(attachment))
|
||||
case 'sticker':
|
||||
attachments.append(Sticker(attachment))
|
||||
case _:
|
||||
attachments.append(VkObject(attachment))
|
||||
return attachments
|
||||
|
||||
|
||||
def dump_attachments(raw_attachments: list[Attachment]) -> str:
|
||||
return ','.join(map(repr, raw_attachments))
|
||||
|
||||
|
||||
class EventActions:
|
||||
SHOW_SNACKBAR = 'show_snackbar'
|
||||
OPEN_LINK = 'open_link'
|
||||
OPEN_APP = 'open_app'
|
||||
|
||||
|
||||
class MessageID:
|
||||
def __init__(self, body):
|
||||
if type(body) is dict:
|
||||
self.message_id = body.get('message_id', 0)
|
||||
self.cmid = body.get('cmid', 0)
|
||||
else:
|
||||
self.message_id = body
|
||||
self.cmid = body
|
||||
|
||||
|
||||
class Message(VkObject):
|
||||
__slots__ = (
|
||||
'vk', 'api', 'raw', 'id', 'conversation_message_id', 'cmid',
|
||||
@ -181,10 +146,9 @@ class Message(VkObject):
|
||||
'meta'
|
||||
)
|
||||
|
||||
def __init__(self, vk, api, raw):
|
||||
def __init__(self, api, raw):
|
||||
super().__init__(raw)
|
||||
|
||||
self.vk = vk
|
||||
self.api = api
|
||||
|
||||
if type(raw) is Message:
|
||||
@ -218,8 +182,7 @@ class Message(VkObject):
|
||||
self.event_id: str = self.raw.get('event_id', '')
|
||||
|
||||
self.forwarded_messages: list = self.raw.get('fwd_messages', [])
|
||||
self.reply_message = Message(self.vk, self.api, self.raw['reply_message']) \
|
||||
if 'reply_message' in self.raw else None
|
||||
self.reply_message = Message(self.api, self.raw['reply_message']) if 'reply_message' in self.raw else None
|
||||
|
||||
self.meta: dict = {}
|
||||
|
||||
@ -325,7 +288,56 @@ class Message(VkObject):
|
||||
'conversation_message_ids': [cmid]
|
||||
}
|
||||
res = await self.api.messages.getByConversationMessageId(**data)
|
||||
return Message(self.vk, self.api, res['items'][0])
|
||||
return Message(self.api, res['items'][0])
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.raw)
|
||||
|
||||
|
||||
class MessageContext:
|
||||
__slots__ = ('api', 'msg', 'db', 'args', 'meta')
|
||||
|
||||
def __init__(self, api, msg, db):
|
||||
self.api: VK = api
|
||||
self.msg: Message = msg
|
||||
self.db: Database = db
|
||||
self.args = None
|
||||
self.meta = {}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<MessageContext{self.msg}({self.args})>'
|
||||
|
||||
|
||||
def load_attachments(raw: list[dict]) -> list[Attachment]:
|
||||
attachments = []
|
||||
for attachment in raw:
|
||||
match attachment['type']:
|
||||
case 'photo':
|
||||
attachments.append(Photo(attachment))
|
||||
case 'doc':
|
||||
attachments.append(Document(attachment))
|
||||
case 'sticker':
|
||||
attachments.append(Sticker(attachment))
|
||||
case _:
|
||||
attachments.append(VkObject(attachment))
|
||||
return attachments
|
||||
|
||||
|
||||
def dump_attachments(raw_attachments: list[Attachment]) -> str:
|
||||
return ','.join(map(repr, raw_attachments))
|
||||
|
||||
|
||||
class EventActions:
|
||||
SHOW_SNACKBAR = 'show_snackbar'
|
||||
OPEN_LINK = 'open_link'
|
||||
OPEN_APP = 'open_app'
|
||||
|
||||
|
||||
class MessageID:
|
||||
def __init__(self, body):
|
||||
if type(body) is dict:
|
||||
self.message_id = body.get('message_id', 0)
|
||||
self.cmid = body.get('cmid', 0)
|
||||
else:
|
||||
self.message_id = body
|
||||
self.cmid = body
|
||||
|
@ -1,6 +1,7 @@
|
||||
import inspect
|
||||
import re
|
||||
|
||||
from kurocore.main.message import MessageArgs
|
||||
|
||||
|
||||
class MethodWithPriority:
|
||||
__slots__ = ('priority', 'method')
|
||||
@ -160,12 +161,10 @@ class Plugin:
|
||||
self.tasks.append(f)
|
||||
return f
|
||||
|
||||
async def _process_command(self, command: str, msg, args):
|
||||
sig = inspect.signature(self.commands[command])
|
||||
if len(sig.parameters) == 1:
|
||||
await self.commands[command](msg)
|
||||
elif len(sig.parameters) == 2:
|
||||
await self.commands[command](msg, args)
|
||||
async def _process_command(self, command: str, ctx, args):
|
||||
# sig = inspect.signature(self.commands[command])
|
||||
ctx.args = args
|
||||
await self.commands[command](ctx)
|
||||
|
||||
async def _process_payload(self, payload: str, msg):
|
||||
await self.payloads[payload](msg)
|
||||
@ -180,7 +179,6 @@ class Plugin:
|
||||
return command in self.admin_commands
|
||||
|
||||
async def _validate_command_args(self, command: str, cmd_args: tuple):
|
||||
from kurocore import MessageArgs
|
||||
commands_args = self.commands_args
|
||||
if command not in commands_args:
|
||||
return True, MessageArgs({})
|
||||
@ -215,7 +213,6 @@ class Plugin:
|
||||
return True, MessageArgs(args)
|
||||
|
||||
async def _validate_payload_args(self, payload: str, msg_args: dict):
|
||||
from kurocore import MessageArgs
|
||||
payloads_args = self.payloads_args
|
||||
if payload not in payloads_args:
|
||||
return True, None
|
||||
|
@ -1,173 +0,0 @@
|
||||
from peewee import Model, IntegerField, BigIntegerField, DecimalField, TextField, ForeignKeyField, DateTimeField, \
|
||||
BooleanField, CompositeKey, CharField, AutoField
|
||||
|
||||
# from plugins import models
|
||||
from utils.database.database import Database
|
||||
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = Database.db
|
||||
|
||||
|
||||
class Groups(BaseModel):
|
||||
id = IntegerField(null=False)
|
||||
name = TextField(default='')
|
||||
is_vip = BooleanField(default=False)
|
||||
is_admin = BooleanField(default=False)
|
||||
is_tester = BooleanField(default=False)
|
||||
multiplier = DecimalField(default=1)
|
||||
sale = DecimalField(default=1)
|
||||
max_multigen = IntegerField(default=3)
|
||||
|
||||
|
||||
class Works(BaseModel):
|
||||
id = IntegerField(null=False)
|
||||
name = TextField(default='')
|
||||
required_lvl = IntegerField(default=1)
|
||||
money_income = DecimalField(default=0)
|
||||
min_exp = IntegerField(default=0)
|
||||
max_exp = IntegerField(default=0)
|
||||
|
||||
|
||||
class Fractions(BaseModel):
|
||||
id = IntegerField()
|
||||
name = TextField(default='Без названия', null=False)
|
||||
owner_id = IntegerField(null=False)
|
||||
money = DecimalField()
|
||||
exp = IntegerField()
|
||||
level = IntegerField()
|
||||
|
||||
|
||||
class Auto(BaseModel):
|
||||
id = IntegerField()
|
||||
name = TextField()
|
||||
price = DecimalField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'shop_auto'
|
||||
|
||||
|
||||
class Business(BaseModel):
|
||||
id = IntegerField()
|
||||
name = TextField()
|
||||
price = DecimalField()
|
||||
income = DecimalField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'shop_business'
|
||||
|
||||
|
||||
class Maid(BaseModel):
|
||||
id = IntegerField()
|
||||
name = TextField()
|
||||
price = DecimalField()
|
||||
income = DecimalField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'shop_maid'
|
||||
|
||||
|
||||
class Miner(BaseModel):
|
||||
id = IntegerField()
|
||||
name = TextField()
|
||||
price = DecimalField()
|
||||
income = DecimalField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'shop_miner'
|
||||
|
||||
|
||||
class Users(BaseModel):
|
||||
id = IntegerField()
|
||||
user_id = BigIntegerField()
|
||||
|
||||
name = TextField()
|
||||
greeting = TextField()
|
||||
pair = IntegerField()
|
||||
donat = IntegerField()
|
||||
|
||||
balance = DecimalField(default=10000, max_digits=20)
|
||||
invested = DecimalField(default=0, max_digits=20)
|
||||
btc = DecimalField(default=0, max_digits=20, decimal_places=6)
|
||||
level = IntegerField()
|
||||
exp = DecimalField(default=0)
|
||||
|
||||
group_id = IntegerField()
|
||||
group = ForeignKeyField(Groups)
|
||||
fraction = ForeignKeyField(Fractions, null=True, lazy_load=True)
|
||||
|
||||
work = ForeignKeyField(Works)
|
||||
work_time = DateTimeField()
|
||||
|
||||
income_time = DateTimeField()
|
||||
|
||||
auto = ForeignKeyField(Auto)
|
||||
business = ForeignKeyField(Business)
|
||||
maid = ForeignKeyField(Maid)
|
||||
miner = ForeignKeyField(Miner)
|
||||
|
||||
subscribed = BooleanField()
|
||||
|
||||
|
||||
class Reports(BaseModel):
|
||||
id = IntegerField(unique=True, null=False, primary_key=True)
|
||||
text = TextField(null=False)
|
||||
admin_answer = TextField(null=True)
|
||||
from_id = BigIntegerField(null=False)
|
||||
date = DateTimeField()
|
||||
status = CharField(null=False)
|
||||
attachments = TextField(null=True)
|
||||
|
||||
|
||||
class FractionMember(BaseModel):
|
||||
fraction = ForeignKeyField(Fractions)
|
||||
user = ForeignKeyField(Users)
|
||||
is_moderator = BooleanField()
|
||||
is_admin = BooleanField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'fraction_member'
|
||||
primary_key = CompositeKey('fraction', 'user')
|
||||
|
||||
|
||||
# WD
|
||||
class WDModels(BaseModel):
|
||||
model_id = IntegerField(null=False)
|
||||
name = TextField(null=False)
|
||||
image = TextField(null=False)
|
||||
description = TextField(null=False)
|
||||
|
||||
class Meta:
|
||||
table_name = 'wd_models'
|
||||
|
||||
|
||||
class WDUsers(BaseModel):
|
||||
user_id = IntegerField(null=False)
|
||||
model = ForeignKeyField(WDModels)
|
||||
model_id = IntegerField(null=False, default=1)
|
||||
orientation = TextField(null=False, default='PORTRAIT')
|
||||
|
||||
class Meta:
|
||||
table_name = 'wd_users'
|
||||
primary_key = CompositeKey('user_id', 'model_id')
|
||||
|
||||
|
||||
class WDLoras(BaseModel):
|
||||
id = IntegerField(null=False)
|
||||
name = TextField(null=False, default='NOT SET')
|
||||
trigger_prompt = TextField(null=False, default='')
|
||||
prompt_mixin = TextField(null=False, default='')
|
||||
|
||||
class Meta:
|
||||
table_name = 'wd_loras'
|
||||
primary_key = CompositeKey('id', 'trigger_prompt')
|
||||
|
||||
|
||||
class WDPrompts(BaseModel):
|
||||
id = AutoField(null=False)
|
||||
user_id = IntegerField(null=False)
|
||||
prompt = TextField(null=False)
|
||||
|
||||
class Meta:
|
||||
table_name = 'wd_prompts'
|
@ -1,42 +0,0 @@
|
||||
import re
|
||||
|
||||
|
||||
def chunk_array(array, chunk_number) -> list:
|
||||
if len(array) <= chunk_number:
|
||||
return [array]
|
||||
out, tmp, index = [], [], 0
|
||||
for el in array:
|
||||
tmp.append(el)
|
||||
index += 1
|
||||
if index == chunk_number:
|
||||
out.append(tmp)
|
||||
tmp = []
|
||||
index = 0
|
||||
out.append(tmp)
|
||||
return out
|
||||
|
||||
|
||||
def parse_attachments(attachments) -> tuple:
|
||||
out = []
|
||||
for attach in attachments:
|
||||
t = attach['type']
|
||||
if t == 'wall':
|
||||
out.append(f'{t}{attach[t]["from_id"]}_{attach[t]["id"]}')
|
||||
else:
|
||||
out.append(f'{t}{attach[t]["owner_id"]}_{attach[t]["id"]}')
|
||||
return tuple(out)
|
||||
|
||||
|
||||
def parse_mention(mention: (str, None)) -> int:
|
||||
if not mention:
|
||||
return 0
|
||||
reg = r'\[id(\d+)\|.+\]'
|
||||
match = re.match(reg, mention)
|
||||
if not match:
|
||||
return 0
|
||||
return int(match.group(1))
|
||||
|
||||
|
||||
async def get_user_sex(user_id, api):
|
||||
query = await api.users.get(user_ids=user_id, fields='sex')
|
||||
return query[0]['sex'] if len(query) > 0 else 2
|
@ -1,6 +0,0 @@
|
||||
from json import JSONEncoder
|
||||
|
||||
|
||||
class EnumEncoder(JSONEncoder):
|
||||
def default(self, obj):
|
||||
return obj.value
|
3
kurocore/vk/__init__.py
Normal file
3
kurocore/vk/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from .vk import VK, VKApiException
|
||||
from .longpoll import VKLongPoll, VkBotEventType
|
||||
from .keyboard import VkKeyboard
|
@ -1,9 +1,8 @@
|
||||
from enum import Enum
|
||||
from logging import Logger
|
||||
|
||||
from kurocore import Config
|
||||
from kurocore.logger import RequestLogger
|
||||
from kurocore.utils.vk.vk import VK
|
||||
from kurocore.logger import RequestLogger, BotLogger
|
||||
from kurocore.vk.vk import VK
|
||||
|
||||
|
||||
class DotDict(dict):
|
||||
@ -54,7 +53,7 @@ class VKLongPoll:
|
||||
async def listen(self):
|
||||
while True:
|
||||
async for event in self.check():
|
||||
Logger.log.debug(f'new event: {event.raw}')
|
||||
BotLogger.log.debug(f'new event: {event.raw}')
|
||||
yield event
|
||||
|
||||
|
@ -2,9 +2,9 @@ import json
|
||||
|
||||
from aiohttp import FormData
|
||||
|
||||
from handler.message import load_attachments
|
||||
from kurocore import LoggingClientSession
|
||||
from utils.vk.vk import VK, VkApiMethod
|
||||
from kurocore.logger import LoggingClientSession
|
||||
from kurocore.main.message import load_attachments
|
||||
from kurocore.vk.vk import VK, VkApiMethod
|
||||
|
||||
|
||||
class JsonParser:
|
@ -1,9 +1,15 @@
|
||||
from json import JSONEncoder
|
||||
import io
|
||||
from random import randint
|
||||
|
||||
from aiohttp import ClientSession
|
||||
|
||||
|
||||
class EnumEncoder(JSONEncoder):
|
||||
def default(self, obj):
|
||||
return obj.value
|
||||
|
||||
|
||||
def get_self_id(api):
|
||||
return api.groups.getById()[0]['id']
|
||||
|
||||
@ -12,11 +18,22 @@ def generate_random_id():
|
||||
return randint(-9 ** 99, 9 ** 99)
|
||||
|
||||
|
||||
async def get_user_name(id, api, name_case='nom'):
|
||||
user = (await api.users.get(user_ids=id, name_case=name_case))[0]
|
||||
async def get_user_name(user_id, api, name_case='nom'):
|
||||
user = (await api.users.get(user_ids=user_id, name_case=name_case))[0]
|
||||
return f'{user["first_name"]} {user["last_name"]}'
|
||||
|
||||
|
||||
def parse_attachments(attachments) -> tuple:
|
||||
out = []
|
||||
for attach in attachments:
|
||||
t = attach['type']
|
||||
if t == 'wall':
|
||||
out.append(f'{t}{attach[t]["from_id"]}_{attach[t]["id"]}')
|
||||
else:
|
||||
out.append(f'{t}{attach[t]["owner_id"]}_{attach[t]["id"]}')
|
||||
return tuple(out)
|
||||
|
||||
|
||||
async def reupload_attachments(attachments, upload):
|
||||
new_attachments = []
|
||||
for a in attachments:
|
@ -1,10 +1,10 @@
|
||||
[project]
|
||||
name = "kurocore"
|
||||
version = "1.0"
|
||||
version = "1.1"
|
||||
authors = [
|
||||
{ name="ScuroNeko", email="author@example.com" },
|
||||
{ name="ScuroNeko" },
|
||||
]
|
||||
description = "A small example package"
|
||||
description = "A basic library for VK bot"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.6"
|
||||
classifiers = [
|
||||
|
@ -1,9 +1,4 @@
|
||||
asyncio
|
||||
aiohttp
|
||||
aiopg
|
||||
psycopg2-binary
|
||||
peewee
|
||||
peewee-async
|
||||
sentry-sdk
|
||||
|
||||
py-aiovk
|
||||
peewee-async
|
Loading…
Reference in New Issue
Block a user