from my_helpers.ConvexDbBase import ConvexDbBase from my_modules.app.logger import logger from convex import ConvexError, ConvexExecutionError from datetime import datetime class ConvexDB(ConvexDbBase): service_namespace = 'nanoshare' def __init__(self, dsn:str): super().__init__(dsn=dsn, service=ConvexDB.service_namespace) # File Quary Functions async def get_file(self, file_id:str): data = await self.run_query_with_reconnection( self.client.query, f"{self.service_namespace}/files:getByFileId", args={ 'file_id': file_id } ) return data async def get_files(self, user_id:str): data = await self.run_query_with_reconnection( self.client.query, f"{self.service_namespace}/files:getAllNotExpired", args={ 'user_id': user_id } ) return [ { "file_id": x['file_id'], "file_name": x['file_name'], "file_size": x['file_size'], "note": x['note'], "expires_at": int(x['expires_at']) if x.get('expires_at', None) else '', "uploaded_at": int(x['uploaded_at']), } for x in data ] async def add_file(self, file_name:str, file_size:str, note:str, content_type:str, expires_at:datetime, storage_id:str, user_id:str): args = { 'file_name': file_name, 'file_size': file_size, 'content_type': content_type, 'note': note, 'file_storage_id': storage_id, 'user_id': user_id } if expires_at: args['expires_at'] = expires_at.isoformat() data = await self.run_query_with_reconnection( self.client.mutation, f"{self.service_namespace}/files:addNewFile", args=args, ) return data async def update_file(self, file_id:str, file_name:str, note:str, expires_at:datetime, user_id:str): await self.run_query_with_reconnection( self.client.mutation, f"{self.service_namespace}/files:updateFile", args={ 'file_id': file_id, 'file_name': file_name, 'note': note, 'expires_at': expires_at.isoformat(), 'user_id': user_id } ) async def delete_file(self, file_id:str, user_id:str): await self.run_query_with_reconnection( self.client.mutation, f"{self.service_namespace}/files:deleteFile", args={ 'file_id': file_id, 'user_id': user_id } ) async def get_file_informations(self, file_id:str): pass # File Access Quary Functions async def add_file_access(self, file_id: str, ip_address:str, status:str, user_agent:str): data = await self.run_query_with_reconnection( self.client.mutation, f"{self.service_namespace}/access:addNewAccess", args={ 'file_id': file_id, 'ip_address': ip_address, 'user_agent': str(user_agent), 'status': status } ) return data async def get_all_access(self, user_id:str): data = await self.run_query_with_reconnection( self.client.query, """ select files { file_id, file_name, note, accesses: { at, status, ip: { value }, user_agent: { value } } order by .at desc } filter .user_id = $user_id """, user_id=user_id ) return sorted([{ "file_id": file.file_id, "file_name": file.file_name, "file_note": file.note, "status": access.status, "ip": access.ip.value, "user_agent": access.user_agent.value, "accessed_at": access.at, } for file in data for access in file.accesses], key=lambda x: x["accessed_at"], reverse=True) async def get_file_access(self, file_id: str): data = await self.run_query_with_reconnection( self.client.query_single, """ SELECT files { accesses: { status, ip: { value }, user_agent: { value }, at } } FILTER .file_id = $file_id LIMIT 1 """, file_id=file_id, ) if data: return [{ "status": str(access.status), "ip": access.ip.value if access.ip else None, "user_agent": access.user_agent.value if access.user_agent else None, "accessed_at": access.at, } for access in data.accesses] return None