hyperboria/nexus/hub/services/base.py

148 lines
4.9 KiB
Python

import asyncio
from aiobaseclient.exceptions import BadRequestError
from library.aiogrpctools.base import BaseService
from library.telegram.common import close_button
from nexus.views.telegram.common import vote_button
from telethon.errors import rpcerrorlist
from telethon.tl.types import DocumentAttributeFilename
from tenacity import (
retry,
retry_if_exception_type,
stop_after_attempt,
)
def is_group_or_channel(chat_id: int):
return chat_id < 0
class ProcessedDocument:
def __init__(self, processed_document):
self.processed_document = processed_document
@staticmethod
async def setup(file_data, grobid_client, request_context):
try:
processed_document = await grobid_client.process_fulltext_document(pdf_file=file_data)
except BadRequestError as e:
request_context.statbox(action='unparsable_document')
request_context.error_log(e)
processed_document = {}
return ProcessedDocument(processed_document)
@property
def doi(self):
return self.processed_document.get('doi')
@property
def title(self):
return self.processed_document.get('title')
@property
def abstract(self):
return self.processed_document.get('abstract')
@property
def body(self):
return self.processed_document.get('body')
class BaseHubService(BaseService):
async def found_item(self, bot_name, doi):
if mutual_aid_service := self.application.mutual_aid_services.get(bot_name):
await mutual_aid_service.delete_request(doi)
await self.application.idm_client.reschedule_subscriptions(
subscriptions_ids=dict(
subscription_query=f'doi:{doi}',
),
new_schedule={'schedule': '*/1 * * * *'},
)
async def get_ipfs_hashes(self, file):
return list(map(
lambda x: x['Hash'],
await asyncio.gather(
self.application.ipfs_client.add_bytes(file, cid_version=1, hash='blake2b-256', only_hash=True),
self.application.ipfs_client.add_bytes(file, cid_version=0, hash='sha2-256', only_hash=True),
self.application.ipfs_client.add_bytes(file, cid_version=1, hash='blake3', only_hash=True),
)
))
def set_fields_from_processed(self, document_pb, processed_document: ProcessedDocument):
new_fields = []
if processed_document.abstract and not document_pb.abstract:
document_pb.abstract = processed_document.abstract
new_fields.append('abstract')
if processed_document.body and not document_pb.content:
document_pb.content = processed_document.body
new_fields.append('content')
return new_fields
@retry(
reraise=True,
stop=stop_after_attempt(3),
retry=retry_if_exception_type((rpcerrorlist.TimeoutError, ValueError)),
)
async def send_file(
self,
document_holder,
file,
request_context,
session_id,
document_id=None,
voting=True,
close=False,
progress_callback=None,
chat_id=None,
reply_to=None,
):
if document_id is None:
document_id = document_holder.id
buttons = []
if voting:
buttons += [
vote_button(
case='broken',
index_alias=document_holder.index_alias,
document_id=document_id,
language=request_context.chat.language,
session_id=session_id,
),
vote_button(
case='ok',
index_alias=document_holder.index_alias,
document_id=document_id,
language=request_context.chat.language,
session_id=session_id,
),
]
if close:
buttons += [
close_button(session_id=session_id)
]
if not buttons:
buttons = None
short_description = (
document_holder.view_builder(request_context.chat.language)
.add_short_description().add_doi_link(label=True, on_newline=True).build()
)
caption = (
f"{short_description}\n"
f"@{self.application.config['telegram']['related_channel']}"
)
message = await self.application.telegram_clients[request_context.bot_name].send_file(
attributes=[DocumentAttributeFilename(document_holder.get_filename())],
buttons=buttons,
caption=caption,
entity=chat_id or request_context.chat.chat_id,
file=file,
progress_callback=progress_callback,
reply_to=reply_to,
)
request_context.statbox(
action='sent',
voting=voting,
)
return message