mirror of
https://github.com/MrSedan/neuro-reply-bot-reworked.git
synced 2026-01-14 13:39:42 +03:00
@@ -1 +0,0 @@
|
|||||||
Generic single-database configuration.
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import os
|
|
||||||
from logging.config import fileConfig
|
|
||||||
from os import getenv
|
|
||||||
from os.path import dirname, join
|
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
|
|
||||||
from alembic import context
|
|
||||||
from db.data import Base
|
|
||||||
|
|
||||||
# this is the Alembic Config object, which provides
|
|
||||||
# access to the values within the .ini file in use.
|
|
||||||
config = context.config
|
|
||||||
|
|
||||||
# Interpret the config file for Python logging.
|
|
||||||
# This line sets up loggers basically.
|
|
||||||
if config.config_file_name is not None:
|
|
||||||
fileConfig(config.config_file_name)
|
|
||||||
|
|
||||||
# add your model's MetaData object here
|
|
||||||
# for 'autogenerate' support
|
|
||||||
# from myapp import mymodel
|
|
||||||
# target_metadata = mymodel.Base.metadata
|
|
||||||
target_metadata = Base.metadata
|
|
||||||
|
|
||||||
# other values from the config, defined by the needs of env.py,
|
|
||||||
# can be acquired:
|
|
||||||
# my_important_option = config.get_main_option("my_important_option")
|
|
||||||
# ... etc.
|
|
||||||
|
|
||||||
load_dotenv(join(dirname(__file__), '..', '.env'))
|
|
||||||
DATABASE_PASSWORD=os.getenv('DATABASE_PASSWORD')
|
|
||||||
DATABASE_NAME=os.getenv('DATABASE_NAME')
|
|
||||||
DATABASE_USER=os.getenv('DATABASE_USER')
|
|
||||||
DATABASE_PORT=os.getenv('DATABASE_PORT')
|
|
||||||
DATABASE_HOST=os.getenv('DATABASE_HOST')
|
|
||||||
URL=f"postgresql+psycopg2://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}"
|
|
||||||
def run_migrations_offline() -> None:
|
|
||||||
"""Run migrations in 'offline' mode.
|
|
||||||
|
|
||||||
This configures the context with just a URL
|
|
||||||
and not an Engine, though an Engine is acceptable
|
|
||||||
here as well. By skipping the Engine creation
|
|
||||||
we don't even need a DBAPI to be available.
|
|
||||||
|
|
||||||
Calls to context.execute() here emit the given string to the
|
|
||||||
script output.
|
|
||||||
|
|
||||||
"""
|
|
||||||
url = URL
|
|
||||||
context.configure(
|
|
||||||
url=url,
|
|
||||||
target_metadata=target_metadata,
|
|
||||||
literal_binds=True,
|
|
||||||
dialect_opts={"paramstyle": "named"},
|
|
||||||
)
|
|
||||||
|
|
||||||
with context.begin_transaction():
|
|
||||||
context.run_migrations()
|
|
||||||
|
|
||||||
|
|
||||||
def run_migrations_online() -> None:
|
|
||||||
"""Run migrations in 'online' mode.
|
|
||||||
|
|
||||||
In this scenario we need to create an Engine
|
|
||||||
and associate a connection with the context.
|
|
||||||
|
|
||||||
"""
|
|
||||||
connectable = create_engine(URL)
|
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
|
||||||
context.configure(
|
|
||||||
connection=connection, target_metadata=target_metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
with context.begin_transaction():
|
|
||||||
context.run_migrations()
|
|
||||||
|
|
||||||
|
|
||||||
if context.is_offline_mode():
|
|
||||||
run_migrations_offline()
|
|
||||||
else:
|
|
||||||
run_migrations_online()
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
"""${message}
|
|
||||||
|
|
||||||
Revision ID: ${up_revision}
|
|
||||||
Revises: ${down_revision | comma,n}
|
|
||||||
Create Date: ${create_date}
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
${imports if imports else ""}
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = ${repr(up_revision)}
|
|
||||||
down_revision: Union[str, None] = ${repr(down_revision)}
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
||||||
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
${upgrades if upgrades else "pass"}
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
${downgrades if downgrades else "pass"}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
"""Added file_id to image table
|
|
||||||
|
|
||||||
Revision ID: 1d040fbb74ce
|
|
||||||
Revises: 8c2a92134271
|
|
||||||
Create Date: 2023-11-04 03:35:28.011123
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '1d040fbb74ce'
|
|
||||||
down_revision: Union[str, None] = '8c2a92134271'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('photo', sa.Column('file_id', sa.String(), nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('photo', 'file_id')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
"""Moved media group from image to post
|
|
||||||
|
|
||||||
Revision ID: 278f7650482f
|
|
||||||
Revises: ca01506184b5
|
|
||||||
Create Date: 2023-11-04 02:32:22.398760
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '278f7650482f'
|
|
||||||
down_revision: Union[str, None] = 'ca01506184b5'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('photo', 'media_group_id')
|
|
||||||
op.add_column('post', sa.Column('media_group_id', sa.Integer(), nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('post', 'media_group_id')
|
|
||||||
op.add_column('photo', sa.Column('media_group_id', sa.INTEGER(), autoincrement=False, nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
"""Added timestamp and posted
|
|
||||||
|
|
||||||
Revision ID: 2af6a0df717b
|
|
||||||
Revises: 1d040fbb74ce
|
|
||||||
Create Date: 2023-11-04 04:09:12.689628
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '2af6a0df717b'
|
|
||||||
down_revision: Union[str, None] = '1d040fbb74ce'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('post', sa.Column('timestamp', sa.DateTime(), nullable=True))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('post', 'timestamp')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
"""Change to str mediag_group_id
|
|
||||||
|
|
||||||
Revision ID: 8c2a92134271
|
|
||||||
Revises: 278f7650482f
|
|
||||||
Create Date: 2023-11-04 03:06:58.339894
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '8c2a92134271'
|
|
||||||
down_revision: Union[str, None] = '278f7650482f'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.alter_column('post', 'media_group_id',
|
|
||||||
existing_type=sa.INTEGER(),
|
|
||||||
type_=sa.String(),
|
|
||||||
existing_nullable=False)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.alter_column('post', 'media_group_id',
|
|
||||||
existing_type=sa.String(),
|
|
||||||
type_=sa.INTEGER(),
|
|
||||||
existing_nullable=False)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
"""Initial migration
|
|
||||||
|
|
||||||
Revision ID: 9de2db27ca6e
|
|
||||||
Revises:
|
|
||||||
Create Date: 2023-10-29 01:23:30.890347
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '9de2db27ca6e'
|
|
||||||
down_revision: Union[str, None] = None
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
pass
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
pass
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
"""Added spoiler to photo
|
|
||||||
|
|
||||||
Revision ID: c9872bd4d4b5
|
|
||||||
Revises: f0ed48a3ded3
|
|
||||||
Create Date: 2023-11-15 23:38:03.886970
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = 'c9872bd4d4b5'
|
|
||||||
down_revision: Union[str, None] = 'f0ed48a3ded3'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('photo', sa.Column('has_spoiler', sa.Boolean(), nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('photo', 'has_spoiler')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
"""Added image table
|
|
||||||
|
|
||||||
Revision ID: ca01506184b5
|
|
||||||
Revises: 9de2db27ca6e
|
|
||||||
Create Date: 2023-11-04 02:21:28.077631
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = 'ca01506184b5'
|
|
||||||
down_revision: Union[str, None] = '9de2db27ca6e'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_table('photo',
|
|
||||||
sa.Column('message_id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('media_group_id', sa.Integer(), nullable=False),
|
|
||||||
sa.Column('post_id', sa.Uuid(), nullable=False),
|
|
||||||
sa.ForeignKeyConstraint(['post_id'], ['post.uuid'], ),
|
|
||||||
sa.PrimaryKeyConstraint('message_id')
|
|
||||||
)
|
|
||||||
op.drop_column('post', 'images')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('post', sa.Column('images', sa.VARCHAR(), autoincrement=False, nullable=False))
|
|
||||||
op.drop_table('photo')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
"""Added posted
|
|
||||||
|
|
||||||
Revision ID: f0ed48a3ded3
|
|
||||||
Revises: 2af6a0df717b
|
|
||||||
Create Date: 2023-11-04 04:12:46.479474
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = 'f0ed48a3ded3'
|
|
||||||
down_revision: Union[str, None] = '2af6a0df717b'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('post', sa.Column('posted', sa.Boolean(), nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('post', 'posted')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
78
db/data.py
78
db/data.py
@@ -1,78 +0,0 @@
|
|||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from os.path import dirname, join
|
|
||||||
from typing import List, Optional
|
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from sqlalchemy import Column, DateTime, ForeignKey, create_engine
|
|
||||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
|
||||||
|
|
||||||
load_dotenv(join(dirname(__file__), '..', '.env'))
|
|
||||||
DATABASE_PASSWORD = os.getenv('DATABASE_PASSWORD')
|
|
||||||
DATABASE_NAME = os.getenv('DATABASE_NAME')
|
|
||||||
DATABASE_USER = os.getenv('DATABASE_USER')
|
|
||||||
DATABASE_PORT = os.getenv('DATABASE_PORT')
|
|
||||||
DATABASE_HOST = os.getenv('DATABASE_HOST')
|
|
||||||
engine = create_engine(
|
|
||||||
f"postgresql+psycopg2://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}", echo=True)
|
|
||||||
|
|
||||||
|
|
||||||
class Base(DeclarativeBase):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
|
||||||
__tablename__ = 'user'
|
|
||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True)
|
|
||||||
user_name: Mapped[Optional[str]]
|
|
||||||
|
|
||||||
admin: Mapped['Admin'] = relationship(
|
|
||||||
back_populates='user', cascade='all, delete-orphan')
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f'User(id={self.id!r}, user_name={self.user_name!r})'
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f'User(id={self.id!r}, user_name={self.user_name!r})'
|
|
||||||
|
|
||||||
|
|
||||||
class Admin(Base):
|
|
||||||
__tablename__ = 'admin'
|
|
||||||
|
|
||||||
user_id: Mapped[int] = mapped_column(
|
|
||||||
ForeignKey('user.id'), primary_key=True)
|
|
||||||
user: Mapped['User'] = relationship(back_populates='admin')
|
|
||||||
posts: Mapped[List['Post']] = relationship(
|
|
||||||
back_populates='user', cascade='all, delete')
|
|
||||||
|
|
||||||
|
|
||||||
class Post(Base):
|
|
||||||
__tablename__ = 'post'
|
|
||||||
|
|
||||||
uuid: Mapped[UUID] = mapped_column(primary_key=True)
|
|
||||||
posted: Mapped[bool] = mapped_column(default=False)
|
|
||||||
from_user_id: Mapped[int] = mapped_column(ForeignKey('admin.user_id'))
|
|
||||||
user: Mapped['Admin'] = relationship(back_populates='posts')
|
|
||||||
text: Mapped[str]
|
|
||||||
media_group_id: Mapped[str]
|
|
||||||
images: Mapped[List['Image']] = relationship(
|
|
||||||
back_populates='post', cascade='all, delete')
|
|
||||||
timestamp = Column(DateTime, default=datetime.utcnow)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f"UUID: {self.uuid}. From_user_id: {self.from_user_id}. media group id: {self.media_group_id}. Text: {self.text}"
|
|
||||||
|
|
||||||
|
|
||||||
class Image(Base):
|
|
||||||
__tablename__ = 'photo'
|
|
||||||
message_id: Mapped[int] = mapped_column(primary_key=True)
|
|
||||||
post: Mapped['Post'] = relationship(back_populates='images')
|
|
||||||
post_id: Mapped[int] = mapped_column(ForeignKey('post.uuid'))
|
|
||||||
file_id: Mapped[str]
|
|
||||||
has_spoiler: Mapped[bool]
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
Base.metadata.create_all(engine)
|
|
||||||
@@ -1,24 +1,22 @@
|
|||||||
from datetime import datetime
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from uuid import uuid4
|
|
||||||
|
|
||||||
from aiogram import Bot, F, Router, types
|
from aiogram import Bot, F, Router, types
|
||||||
from aiogram.filters import Command
|
from aiogram.filters import Command
|
||||||
from aiogram.fsm.context import FSMContext
|
from aiogram.fsm.context import FSMContext
|
||||||
from aiogram.utils.media_group import MediaGroupBuilder
|
from aiogram.utils.media_group import MediaGroupBuilder
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
from db.data import Admin, Image, Post, User, engine
|
|
||||||
from handlers.filters.new_post import (ChangePosts, NewPostFilter,
|
from handlers.filters.new_post import (ChangePosts, NewPostFilter,
|
||||||
NewSoloPostFilter)
|
NewSoloPostFilter)
|
||||||
|
from handlers.filters.reply_to_user import ReplyToUser
|
||||||
from handlers.middlewares.user import AdminMiddleware
|
from handlers.middlewares.user import AdminMiddleware
|
||||||
from handlers.states.change_post import ChangePost
|
from handlers.states.change_post import ChangePost
|
||||||
|
from neuroapi import neuroapi
|
||||||
|
|
||||||
|
|
||||||
def get_post_info(post: Post, post_id: int) -> str:
|
def get_post_info(post: dict, post_id: int) -> str:
|
||||||
text = post.text
|
text = post["text"]
|
||||||
time = post.timestamp
|
time = post["timestamp"]
|
||||||
from_user = post.from_user_id
|
from_user = post["from_user_id"]
|
||||||
s = f"""Индекс: {post_id}\nТекст: {text}\nВремя отправки: {time}\nОт: [id{from_user}](tg://user?id={from_user})""".replace('#', '\#').replace(
|
s = f"""Индекс: {post_id}\nТекст: {text}\nВремя отправки: {time}\nОт: [id{from_user}](tg://user?id={from_user})""".replace('#', '\#').replace(
|
||||||
"_", "\_").replace('.', '\.').replace(',', '\,').replace('!', '\!').replace('-', '\-').replace(':', '\:')
|
"_", "\_").replace('.', '\.').replace(',', '\,').replace('!', '\!').replace('-', '\-').replace(':', '\:')
|
||||||
return s
|
return s
|
||||||
@@ -33,43 +31,26 @@ class Admin_commands:
|
|||||||
self.router = Router()
|
self.router = Router()
|
||||||
self.router.message.middleware(AdminMiddleware())
|
self.router.message.middleware(AdminMiddleware())
|
||||||
|
|
||||||
@self.router.message(Command('test'))
|
|
||||||
async def test_command(message: types.Message):
|
|
||||||
with Session(engine) as session:
|
|
||||||
user = session.get(User, message.from_user.id)
|
|
||||||
await message.answer(str(user))
|
|
||||||
|
|
||||||
@self.router.message(NewPostFilter())
|
@self.router.message(NewPostFilter())
|
||||||
async def new_post(message: types.Message):
|
async def new_post(message: types.Message):
|
||||||
with Session(engine) as session:
|
post = await neuroapi.post.get_by_media_group_id(message.media_group_id)
|
||||||
post = session.query(Post).filter(
|
await neuroapi.image.add(post['uuid'], message.photo[-1].file_id, message.has_media_spoiler, message.message_id)
|
||||||
Post.media_group_id == message.media_group_id).first()
|
|
||||||
if post:
|
|
||||||
photo = Image(message_id=message.message_id,
|
|
||||||
post=post, file_id=message.photo[-1].file_id, has_spoiler=bool(message.has_media_spoiler))
|
|
||||||
session.add(photo)
|
|
||||||
session.commit()
|
|
||||||
else:
|
|
||||||
print('No posts anymore ;-(')
|
|
||||||
|
|
||||||
@self.router.message(Command('info'))
|
@self.router.message(Command('info'))
|
||||||
async def info_command(message: types.Message):
|
async def info_command(message: types.Message):
|
||||||
with Session(engine) as session:
|
posts = await neuroapi.post.get_will_post()
|
||||||
posts = session.query(Post).filter(Post.posted == False).all()
|
|
||||||
admins = session.query(Admin).all()
|
|
||||||
post_c = {}
|
post_c = {}
|
||||||
for admin in admins:
|
|
||||||
post_c[str(admin.user_id)] = 0
|
|
||||||
for post in posts:
|
for post in posts:
|
||||||
post_c[str(post.from_user_id)] += 1
|
if post['from_user_id'] not in post_c:
|
||||||
|
post_c[post['from_user_id']] = 1
|
||||||
|
else:
|
||||||
|
post_c[post['from_user_id']] += 1
|
||||||
await message.answer(str(post_c))
|
await message.answer(str(post_c))
|
||||||
|
|
||||||
@self.router.message(ChangePosts())
|
@self.router.message(ChangePosts())
|
||||||
async def change_post(message: types.Message, state: FSMContext):
|
async def change_post(message: types.Message, state: FSMContext):
|
||||||
with Session(engine) as session:
|
posts = await neuroapi.post.get_will_post()
|
||||||
posts = session.query(Post).filter(
|
if (posts):
|
||||||
Post.posted == False).order_by(Post.timestamp.asc()).all()
|
|
||||||
if len(posts):
|
|
||||||
await state.update_data(posts=posts, id=0)
|
await state.update_data(posts=posts, id=0)
|
||||||
select_btns = []
|
select_btns = []
|
||||||
if len(posts) > 1:
|
if len(posts) > 1:
|
||||||
@@ -83,15 +64,15 @@ class Admin_commands:
|
|||||||
text='Отмена', callback_data='cancel')]
|
text='Отмена', callback_data='cancel')]
|
||||||
]
|
]
|
||||||
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
||||||
|
post = await neuroapi.post.get(posts[0]['uuid'])
|
||||||
images = MediaGroupBuilder(
|
images = MediaGroupBuilder(
|
||||||
caption=get_post_info(posts[0], 1))
|
caption=get_post_info(post, 1))
|
||||||
for image in posts[0].images:
|
for image in sorted(post['images'], key=lambda x: x['message_id']):
|
||||||
images.add_photo(
|
images.add_photo(image['file_id'],
|
||||||
image.file_id, parse_mode='markdownv2')
|
has_spoiler=image['has_spoiler'], parse_mode='markdownv2')
|
||||||
mes = await message.answer_media_group(media=images.build())
|
mes = await message.answer_media_group(images.build())
|
||||||
await state.update_data(edit_msg=mes[0].message_id)
|
await state.update_data(edit_msg=mes[0].message_id)
|
||||||
await message.answer('Действия', reply_markup=keyboard)
|
await message.answer('Действия', reply_markup=keyboard)
|
||||||
# await message.answer(get_post_info(posts[0]), reply_markup=keyboard, parse_mode='markdownv2')
|
|
||||||
else:
|
else:
|
||||||
await message.answer('Нет постов')
|
await message.answer('Нет постов')
|
||||||
|
|
||||||
@@ -119,7 +100,8 @@ class Admin_commands:
|
|||||||
]
|
]
|
||||||
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
||||||
await state.update_data(id=post_id)
|
await state.update_data(id=post_id)
|
||||||
await bot.edit_message_caption(caption=get_post_info(posts[post_id], post_id+1), chat_id=callback.message.chat.id, message_id=data['edit_msg'], parse_mode='markdownv2')
|
post = await neuroapi.post.get(posts[post_id]['uuid'])
|
||||||
|
await bot.edit_message_caption(caption=get_post_info(post, post_id+1), chat_id=callback.message.chat.id, message_id=data['edit_msg'], parse_mode='markdownv2')
|
||||||
await callback.message.edit_reply_markup(reply_markup=keyboard)
|
await callback.message.edit_reply_markup(reply_markup=keyboard)
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
@@ -149,13 +131,13 @@ class Admin_commands:
|
|||||||
return
|
return
|
||||||
posts = data['posts']
|
posts = data['posts']
|
||||||
post_id = data['id']
|
post_id = data['id']
|
||||||
post: Post = posts[post_id]
|
post_uuid = posts[post_id]['uuid']
|
||||||
with Session(engine) as session:
|
try:
|
||||||
p = session.get(Post, post.uuid)
|
await neuroapi.post.edit_text(post_uuid, message.text)
|
||||||
p.text = message.text
|
|
||||||
session.commit()
|
|
||||||
await state.clear()
|
|
||||||
await message.answer(f'Текст поста изменен на: {message.text}')
|
await message.answer(f'Текст поста изменен на: {message.text}')
|
||||||
|
except:
|
||||||
|
await message.answer('Ошибка')
|
||||||
|
await state.clear()
|
||||||
|
|
||||||
@self.router.callback_query(F.data == 'prev_post')
|
@self.router.callback_query(F.data == 'prev_post')
|
||||||
async def prev_post_changing(callback: types.CallbackQuery, state: FSMContext):
|
async def prev_post_changing(callback: types.CallbackQuery, state: FSMContext):
|
||||||
@@ -181,7 +163,8 @@ class Admin_commands:
|
|||||||
]
|
]
|
||||||
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
keyboard = types.InlineKeyboardMarkup(inline_keyboard=kb)
|
||||||
await state.update_data(id=post_id)
|
await state.update_data(id=post_id)
|
||||||
await bot.edit_message_caption(caption=get_post_info(posts[post_id], post_id), chat_id=callback.message.chat.id, message_id=data['edit_msg'], parse_mode='markdownv2')
|
post = await neuroapi.post.get(posts[post_id]['uuid'])
|
||||||
|
await bot.edit_message_caption(caption=get_post_info(post, post_id), chat_id=callback.message.chat.id, message_id=data['edit_msg'], parse_mode='markdownv2')
|
||||||
await callback.message.edit_reply_markup(reply_markup=keyboard)
|
await callback.message.edit_reply_markup(reply_markup=keyboard)
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
@@ -196,34 +179,34 @@ class Admin_commands:
|
|||||||
|
|
||||||
@self.router.message(Command('post'))
|
@self.router.message(Command('post'))
|
||||||
async def post(message: types.Message):
|
async def post(message: types.Message):
|
||||||
with Session(engine) as session:
|
posts = await neuroapi.post.get_will_post()
|
||||||
post = session.query(Post).filter(
|
if (posts):
|
||||||
Post.posted == False).order_by(Post.timestamp.asc()).first()
|
post = await neuroapi.post.get(posts[0]['uuid'])
|
||||||
if post:
|
images = MediaGroupBuilder(caption=post['text'])
|
||||||
images = MediaGroupBuilder(caption=post.text)
|
for image in sorted(post['images'], key=lambda x: x['message_id']):
|
||||||
for image in post.images[::-1]:
|
images.add_photo(image['file_id'],
|
||||||
images.add_photo(
|
has_spoiler=image['has_spoiler'])
|
||||||
image.file_id, has_spoiler=image.has_spoiler)
|
|
||||||
await message.answer_media_group(images.build())
|
await message.answer_media_group(images.build())
|
||||||
post.posted = True
|
|
||||||
session.commit()
|
|
||||||
else:
|
else:
|
||||||
await message.answer('Постов немаэ')
|
await message.answer('Нет постов')
|
||||||
|
|
||||||
@self.router.message(NewSoloPostFilter())
|
@self.router.message(NewSoloPostFilter())
|
||||||
async def post_solo(message: types.Message):
|
async def post_solo(message: types.Message):
|
||||||
with Session(engine) as session:
|
post = await neuroapi.post.new(message.caption.replace('/newpost ', ''), message.from_user.id)
|
||||||
post = Post(uuid=uuid4(), text=message.caption.replace(
|
await neuroapi.image.add(post['uuid'], message.photo[-1].file_id, message.has_media_spoiler, message.message_id)
|
||||||
'/newpost ', ''), media_group_id='')
|
|
||||||
post_user = session.get(Admin, message.from_user.id)
|
|
||||||
post.user = post_user
|
|
||||||
photo = Image(message_id=message.message_id,
|
|
||||||
post=post, file_id=message.photo[-1].file_id, has_spoiler=bool(message.has_media_spoiler))
|
|
||||||
session.add(photo)
|
|
||||||
session.add(post)
|
|
||||||
session.commit()
|
|
||||||
await message.answer('Пост успешно добавлен!')
|
await message.answer('Пост успешно добавлен!')
|
||||||
|
|
||||||
|
@self.router.message(ReplyToUser())
|
||||||
|
async def reply_user(message: types.Message):
|
||||||
|
if message.reply_to_message.forward_from is None:
|
||||||
|
await message.reply('Пользователь стесняшка и не разрешает отвечать на его сообщения...')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await bot.send_message(message.reply_to_message.forward_from.id, f'Вам ответил админ:\n{message.text}')
|
||||||
|
await message.reply('Ваше сообщение было отправлено!')
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def __call__(self, *args: Any, **kwds: Any) -> Router:
|
def __call__(self, *args: Any, **kwds: Any) -> Router:
|
||||||
return self.router
|
return self.router
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,28 @@
|
|||||||
from asyncio import create_task
|
|
||||||
from time import sleep
|
|
||||||
from typing import Any
|
|
||||||
from uuid import uuid4
|
|
||||||
|
|
||||||
from aiogram import types
|
from aiogram import types
|
||||||
from aiogram.filters import Filter
|
from aiogram.filters import Filter
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
from db.data import Admin, Image, Post, User, engine
|
from neuroapi import neuroapi
|
||||||
|
|
||||||
|
|
||||||
class NewPostFilter(Filter):
|
class NewPostFilter(Filter):
|
||||||
async def __call__(self, message: types.Message) -> bool:
|
async def __call__(self, message: types.Message) -> bool:
|
||||||
if message.media_group_id is None or message.content_type != 'photo':
|
if message.media_group_id is None or message.content_type != 'photo':
|
||||||
return False
|
return False
|
||||||
with Session(engine) as session:
|
try:
|
||||||
post = session.query(Post).filter(
|
await neuroapi.post.get_by_media_group_id(message.media_group_id)
|
||||||
Post.media_group_id == message.media_group_id).first()
|
except:
|
||||||
if post is None:
|
|
||||||
if not (message.caption.startswith('/newpost ') if message.caption else False):
|
if not (message.caption.startswith('/newpost ') if message.caption else False):
|
||||||
return False
|
return False
|
||||||
new_post = Post(uuid=uuid4(), text=message.caption.replace(
|
await neuroapi.post.new(message.caption.replace(
|
||||||
'/newpost ', ''), media_group_id=message.media_group_id)
|
'/newpost ', ''), str(message.from_user.id), str(message.media_group_id))
|
||||||
post_user = session.get(Admin, message.from_user.id)
|
|
||||||
new_post.user = post_user
|
|
||||||
session.add(new_post)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
await message.answer('Пост успешно добавлен!')
|
await message.answer('Пост успешно добавлен!')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class NewSoloPostFilter(Filter):
|
class NewSoloPostFilter(Filter):
|
||||||
async def __call__(self, message: types.Message) -> bool:
|
async def __call__(self, message: types.Message) -> bool:
|
||||||
return message.media_group_id is None and message.content_type == 'photo' and message.caption.startswith('/newpost ')
|
return message.media_group_id is None and message.content_type == 'photo' and message.caption and message.caption.startswith('/newpost ')
|
||||||
|
|
||||||
|
|
||||||
class ChangePosts(Filter):
|
class ChangePosts(Filter):
|
||||||
async def __call__(self, message: types.Message) -> bool:
|
async def __call__(self, message: types.Message) -> bool:
|
||||||
|
|||||||
9
handlers/filters/reply_to_user.py
Normal file
9
handlers/filters/reply_to_user.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from aiogram import types
|
||||||
|
from aiogram.filters import Filter
|
||||||
|
|
||||||
|
|
||||||
|
class ReplyToUser(Filter):
|
||||||
|
async def __call__(self, message: types.Message) -> bool:
|
||||||
|
if message.reply_to_message is None or message.chat.type != 'private':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
@@ -2,9 +2,8 @@ from typing import Any, Awaitable, Callable, Dict
|
|||||||
|
|
||||||
from aiogram import BaseMiddleware
|
from aiogram import BaseMiddleware
|
||||||
from aiogram.types import Message
|
from aiogram.types import Message
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
from db.data import Admin, User, engine
|
from neuroapi import neuroapi
|
||||||
|
|
||||||
|
|
||||||
class AdminMiddleware(BaseMiddleware):
|
class AdminMiddleware(BaseMiddleware):
|
||||||
@@ -12,12 +11,8 @@ class AdminMiddleware(BaseMiddleware):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
|
async def __call__(self, handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]], event: Message, data: Dict[str, Any]) -> Any:
|
||||||
with Session(engine) as session:
|
await neuroapi.user.get(str(event.from_user.id), event.from_user.username)
|
||||||
if not session.get(User, event.from_user.id):
|
isAdmin = await neuroapi.admin.is_admin(str(event.from_user.id))
|
||||||
user = User(id=event.from_user.id, user_name=event.from_user.username)
|
|
||||||
session.add(user)
|
|
||||||
session.commit()
|
|
||||||
isAdmin = session.get(Admin, event.from_user.id)
|
|
||||||
if not isAdmin:
|
if not isAdmin:
|
||||||
await event.answer('Команда только для админов!')
|
await event.answer('Команда только для админов!')
|
||||||
return None
|
return None
|
||||||
|
|||||||
33
handlers/user_commands.py
Normal file
33
handlers/user_commands.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from aiogram import Bot, F, Router, types
|
||||||
|
|
||||||
|
from neuroapi import neuroapi
|
||||||
|
|
||||||
|
|
||||||
|
class User_commands:
|
||||||
|
bot: Bot
|
||||||
|
router: Router
|
||||||
|
|
||||||
|
def __init__(self, bot: Bot) -> None:
|
||||||
|
self.bot = bot
|
||||||
|
self.router = Router()
|
||||||
|
|
||||||
|
@self.router.message(F.chat.type == 'private')
|
||||||
|
async def forward_post(message: types.Message):
|
||||||
|
admins = await neuroapi.admin.get()
|
||||||
|
canReply = True
|
||||||
|
for a in admins:
|
||||||
|
await bot.send_message(a['user_id'], f'Вам новое сообщение от пользователя {message.from_user.full_name}. ' +
|
||||||
|
(f'\nНик: @{message.from_user.username}' if message.from_user.username else f'ID: {message.from_user.id}'))
|
||||||
|
forwarded_message = await bot.forward_message(a['user_id'], message.chat.id, message.message_id)
|
||||||
|
if forwarded_message.forward_from is None:
|
||||||
|
canReply = False
|
||||||
|
await message.reply('Ваше сообщение было отправлено администраторам'+('' if canReply else '\nНо они не смогут вам ответить из-за ваших настроек конфиденциальности.'))
|
||||||
|
|
||||||
|
def __call__(self, *args: Any, **kwds: Any) -> Router:
|
||||||
|
return self.router
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot: Bot) -> Router:
|
||||||
|
return User_commands(bot)()
|
||||||
17
neuroapi/__init__.py
Normal file
17
neuroapi/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from .post import Post
|
||||||
|
from .admin import Admin
|
||||||
|
from .user import User
|
||||||
|
from .image import Image
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
from os.path import join, dirname
|
||||||
|
|
||||||
|
|
||||||
|
load_dotenv(join(dirname(__file__), "..", '.env'))
|
||||||
|
|
||||||
|
|
||||||
|
class neuroapi:
|
||||||
|
post = Post(os.environ.get('API_URL'))
|
||||||
|
admin = Admin(os.environ.get('API_URL'))
|
||||||
|
user = User(os.environ.get('API_URL'))
|
||||||
|
image = Image(os.environ.get('API_URL'))
|
||||||
18
neuroapi/admin.py
Normal file
18
neuroapi/admin.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from aiohttp import ClientSession
|
||||||
|
|
||||||
|
from .api_method import ApiMethod
|
||||||
|
|
||||||
|
|
||||||
|
class Admin(ApiMethod):
|
||||||
|
|
||||||
|
async def get(self):
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.get(self.api_url+'/admin/get')
|
||||||
|
return await response.json()
|
||||||
|
|
||||||
|
async def is_admin(self, id: str):
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.get(self.api_url+f'/admin/is-admin/{id}')
|
||||||
|
if await response.text() == 'false':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
5
neuroapi/api_method.py
Normal file
5
neuroapi/api_method.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class ApiMethod:
|
||||||
|
api_url: str
|
||||||
|
|
||||||
|
def __init__(self, api_url: str) -> None:
|
||||||
|
self.api_url = api_url
|
||||||
1
neuroapi/enums/__init__.py
Normal file
1
neuroapi/enums/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .get_all import EGetAll
|
||||||
7
neuroapi/enums/get_all.py
Normal file
7
neuroapi/enums/get_all.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class EGetAll(Enum):
|
||||||
|
all = 'all'
|
||||||
|
will_post = 'will-post'
|
||||||
|
posted = 'posted'
|
||||||
20
neuroapi/image.py
Normal file
20
neuroapi/image.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from aiohttp import ClientSession
|
||||||
|
|
||||||
|
from .api_method import ApiMethod
|
||||||
|
|
||||||
|
|
||||||
|
class Image(ApiMethod):
|
||||||
|
async def add(self, post_id: str, file_id: str, has_spoiler: bool | None, message_id: int):
|
||||||
|
payload = {'post_id': post_id, 'file_id': file_id,
|
||||||
|
'has_spoiler': has_spoiler, 'message_id': message_id}
|
||||||
|
if has_spoiler is None:
|
||||||
|
payload.pop('has_spoiler')
|
||||||
|
payload = json.dumps(payload)
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.post(
|
||||||
|
self.api_url+'/image/add', data=payload, headers={'Content-Type': 'application/json'})
|
||||||
|
data = await response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
57
neuroapi/post.py
Normal file
57
neuroapi/post.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import requests
|
||||||
|
from aiohttp import ClientSession
|
||||||
|
|
||||||
|
from .api_method import ApiMethod
|
||||||
|
from .enums import EGetAll
|
||||||
|
|
||||||
|
|
||||||
|
class Post(ApiMethod):
|
||||||
|
|
||||||
|
async def new(self, text: str, from_user_id: str, media_group_id: str = "None"):
|
||||||
|
payload = {'text': text, 'from_user_id': from_user_id}
|
||||||
|
if media_group_id != 'None':
|
||||||
|
payload['media_group_id'] = media_group_id
|
||||||
|
response = requests.post(self.api_url+'/post/new', data=payload)
|
||||||
|
data = response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def __get_all(self, status: EGetAll):
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.get(self.api_url+f'/post/get-all/{status.value}')
|
||||||
|
return response
|
||||||
|
|
||||||
|
async def get_all(self):
|
||||||
|
result = await self.__get_all(EGetAll.all)
|
||||||
|
return await result.json()
|
||||||
|
|
||||||
|
async def get_will_post(self):
|
||||||
|
result = await self.__get_all(EGetAll.will_post)
|
||||||
|
return await result.json()
|
||||||
|
|
||||||
|
async def get_posted(self):
|
||||||
|
result = await self.__get_all(EGetAll.posted)
|
||||||
|
return await result.json()
|
||||||
|
|
||||||
|
async def get(self, post_id: str):
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.get(self.api_url+f'/post/get/{post_id}')
|
||||||
|
data = await response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def get_by_media_group_id(self, media_group_id: str):
|
||||||
|
response = requests.get(self.api_url+f'/post/get-by-media-group-id/{media_group_id}')
|
||||||
|
data = response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def edit_text(self, post_id: str, text: str):
|
||||||
|
response = requests.post(self.api_url+f"/post/edit/{post_id}", data={"text": text})
|
||||||
|
data = response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
|
return data
|
||||||
13
neuroapi/user.py
Normal file
13
neuroapi/user.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from aiohttp import ClientSession
|
||||||
|
from .api_method import ApiMethod
|
||||||
|
|
||||||
|
|
||||||
|
class User(ApiMethod):
|
||||||
|
async def get(self, id: str, username: str):
|
||||||
|
payload = {'id': id, 'username': username}
|
||||||
|
async with ClientSession() as session:
|
||||||
|
response = await session.post(
|
||||||
|
self.api_url+'/user/get', data=payload)
|
||||||
|
data = await response.json()
|
||||||
|
if 'statusCode' in data:
|
||||||
|
raise Exception(data['message'])
|
||||||
Reference in New Issue
Block a user