diff --git a/app/blueprints/api/tasks/tasks.py b/app/blueprints/api/tasks/tasks.py index de533b1..0c74350 100644 --- a/app/blueprints/api/tasks/tasks.py +++ b/app/blueprints/api/tasks/tasks.py @@ -20,9 +20,44 @@ async def sending_message(session, task, task_self): async with PaperParser(session.name) as parser: await parser.send_messages(task.collection.users, task.message, task.file, task_self) -async def parse_users(session, task): +async def parse_users(session, task, db, collection): async with PaperParser(session.name) as parser: - return await parser.get_participants(task.url) + users = await parser.get_participants(task.url) + + filtered_users = filter(filter_users, users) + + for user in filtered_users: + if not User.exist(user.username, collection): + full = await parser.get_full_info() + bio = full.full_user.about if full.full_user else None + + db.session.add( + User( + first_name=user.first_name, + last_name=user.last_name, + username=user.username, + phone=user.phone, + description=bio, + collection=collection, + ) + ) + + db.session.commit() + +def filter_users(user): + if not user.username or user.bot: + return False + + is_active = False + if isinstance(user.status, UserStatusOffline): + was_online = user.status.was_online.replace(tzinfo=datetime.timezone.utc) + today = datetime.datetime.today().replace(tzinfo=datetime.timezone.utc) + is_active = was_online + datetime.timedelta(days=5) >= today + + if isinstance(user.status, UserStatusOnline) or isinstance(user.status, UserStatusRecently): + is_active = True + + return is_active @shared_task(bind=True) def add_to_group_task(self, task_id: int): @@ -31,8 +66,6 @@ def add_to_group_task(self, task_id: int): run_state(self.request.id, task_id) session = task.session - - time.sleep(10) asyncio.run( add_to_group(session, task, self) @@ -45,44 +78,27 @@ def add_to_group_task(self, task_id: int): else: success_state(task_id) + @shared_task(bind=True) def parse_users_task(self, task_id: int): - task: Task = Task.query.get_or_404(task_id) - session = task.session - collection = task.collection + try: + task: Task = Task.query.get_or_404(task_id) + session = task.session + collection = task.collection - users = asyncio.run( - parse_users(session, task) - ) + run_state(self.request.id, task_id) + + asyncio.run( + parse_users(session, task, db, collection) + ) - for user in users: - if not user.username or user.bot: - continue - - is_active = False - if isinstance(user.status, UserStatusOffline): - was_online = user.status.was_online.replace(tzinfo=datetime.timezone.utc) - today = datetime.datetime.today().replace(tzinfo=datetime.timezone.utc) - is_active = was_online + datetime.timedelta(days=5) >= today - - if isinstance(user.status, UserStatusOnline) or isinstance(user.status, UserStatusRecently): - is_active = True - - if not is_active: - continue - - if not User.exist(user.username, collection): - db.session.add( - User( - first_name=user.first_name, - last_name=user.last_name, - username=user.username, - phone=user.phone, - collection=collection, - ) - ) + except Exception as e: + logger.exception(e) + failure_state(task_id, e) - db.session.commit() + else: + success_state(task_id) + @shared_task(bind=True) def send_messages_task(self, task_id: int): diff --git a/app/blueprints/frontend/templates/base.j2 b/app/blueprints/frontend/templates/base.j2 index 2cdb15b..8df9b36 100644 --- a/app/blueprints/frontend/templates/base.j2 +++ b/app/blueprints/frontend/templates/base.j2 @@ -63,4 +63,4 @@ {% block scripts %} {% endblock %} - \ No newline at end of file + diff --git a/app/models/user.py b/app/models/user.py index 85acfb9..6184564 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -14,7 +14,8 @@ class User(db.Model): phone: Mapped[str] = mapped_column(nullable=True) username: Mapped[str] = mapped_column(nullable=True) - + description: Mapped[str] = mapped_column(nullable=True) + delete: Mapped[bool] = mapped_column(default="false") collection_id = Column(Integer, ForeignKey("collection.id")) @@ -30,4 +31,5 @@ class User(db.Model): 'last_name': self.last_name, 'phone': self.phone, 'username': self.username, + 'description': self.description } \ No newline at end of file diff --git a/migrations/versions/d4a19a758c83_added_desc_field_to_user.py b/migrations/versions/d4a19a758c83_added_desc_field_to_user.py new file mode 100644 index 0000000..5e884f8 --- /dev/null +++ b/migrations/versions/d4a19a758c83_added_desc_field_to_user.py @@ -0,0 +1,32 @@ +"""Added desc field to user + +Revision ID: d4a19a758c83 +Revises: 65ccd5b1039b +Create Date: 2024-04-12 16:53:20.758855 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd4a19a758c83' +down_revision = '65ccd5b1039b' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('user', schema=None) as batch_op: + batch_op.add_column(sa.Column('description', sa.String(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('user', schema=None) as batch_op: + batch_op.drop_column('description') + + # ### end Alembic commands ### diff --git a/paper/client.py b/paper/client.py index a171ff8..0b4a4a7 100644 --- a/paper/client.py +++ b/paper/client.py @@ -5,6 +5,7 @@ from opentele.api import API from telethon.tl.functions.channels import InviteToChannelRequest, JoinChannelRequest from telethon.tl.functions.messages import AddChatUserRequest +from telethon.tl.functions.users import GetFullUserRequest # Types from telethon.hints import (Entity, EntityLike, MessageLike) @@ -105,3 +106,6 @@ class PaperClient(TelegramClient): return entity # type: ignore except UsernameInvalidError as e: raise IgnoreException(e) + + async def get_full_info(self, user): + return await self(GetFullUserRequest(user)) \ No newline at end of file diff --git a/paper/parser.py b/paper/parser.py index bc8b106..def584e 100644 --- a/paper/parser.py +++ b/paper/parser.py @@ -67,6 +67,10 @@ class PaperParser: await self.client.invite_self(group) return await self.client.get_participants(group) + + async def get_full_info(self, user): + return await self.client.get_full_info(user) + async def sign_in(self, phone: str, password: str | None = None, code: str | None = None, phone_hash: str | None = None, **kwargs): if not await self.client.is_user_authorized():