hyperboria/nexus/bot/handlers/profile.py

128 lines
4.6 KiB
Python

import asyncio
import re
import time
from library.telegram.base import RequestContext
from nexus.bot.widgets.profile_widget import ProfileWidget
from nexus.views.telegram.base_holder import BaseHolder
from nexus.views.telegram.document_list_widget import DocumentListWidget
from telethon import events
from telethon.tl.types import PeerChannel
from .base import BaseHandler
class ProfileHandler(BaseHandler):
filter = events.NewMessage(incoming=True, pattern=re.compile('^/profile'))
is_group_handler = True
should_reset_last_widget = False
stop_propagation = True
async def handler(self, event, request_context: RequestContext):
request_context.add_default_fields(mode='profile')
profile_user_id = None
profile_reply_message = None
target_events = []
if request_context.is_personal_mode():
profile_user_id = request_context.chat.chat_id
target_events.append(event.delete())
else:
reply_message = await event.get_reply_message()
if reply_message:
target_events.append(event.delete())
if not isinstance(reply_message.from_id, PeerChannel):
profile_user_id = reply_message.from_id.user_id
profile_reply_message = reply_message
else:
if not isinstance(event.from_id, PeerChannel):
profile_user_id = event.from_id.user_id
profile_reply_message = event
else:
target_events.append(event.delete())
if profile_user_id is None:
return await asyncio.gather(*target_events)
request_context.statbox(
action='show',
profile_user_id=profile_user_id,
)
profile = await self.application.idm_client.get_profile(chat_id=profile_user_id, last_n_documents=300)
profile_widget = ProfileWidget(
application=self.application,
request_context=request_context,
profile=profile,
)
rendered_widget, buttons = await profile_widget.render()
if profile_reply_message:
target_events.append(profile_reply_message.reply(rendered_widget, buttons=buttons, link_preview=False))
else:
target_events.append(event.reply(rendered_widget, buttons=buttons, link_preview=False))
return await asyncio.gather(*target_events)
class DigestHandler(BaseHandler):
filter = events.CallbackQuery(pattern=re.compile('^/digest$'))
should_reset_last_widget = False
async def handler(self, event, request_context: RequestContext):
bot_name = self.application.config['telegram']['bot_name']
session_id = self.generate_session_id()
request_context.add_default_fields(mode='digest', session_id=session_id)
profile = await self.application.idm_client.get_profile(
request_context.chat.chat_id,
last_n_documents=100,
)
query = []
for series in profile.most_popular_series:
for issn in series.issns:
query.append(f'issn:{issn}')
for tag in profile.most_popular_tags:
query.append(f'tag:"{tag}"')
query.append(f'+issued_at:[{int(time.time() - 3600 * 24 * 7)} TO {int(time.time())}]')
for document in profile.downloaded_documents:
query.append(f'-id:{document.id}')
query = ' '.join(query)
request_context.statbox(
action='query',
query=query,
)
search_response = await self.application.meta_api_client.meta_search(
index_aliases=['scimag'],
query=query,
collectors=[{'top_docs': {'limit': 5}}],
user_id=str(request_context.chat.chat_id),
query_tags=['digest'],
session_id=session_id,
request_id=request_context.request_id,
)
document_holders = [
BaseHolder.create_from_document(scored_document)
for scored_document in search_response.collector_outputs[0].top_docs.scored_documents
]
chat = await self.application.idm_client.get_chat(chat_id=request_context.chat.chat_id)
document_list_widget = DocumentListWidget(
chat=chat,
document_holders=document_holders,
bot_name=bot_name,
header='✨ Nexus Discovery ✨',
promotioner=self.application.promotioner,
)
view, buttons = await document_list_widget.render()
await event.reply(
view,
buttons=buttons,
link_preview=False,
)