from typing import List import strawberry from sqlalchemy import and_ from orm.author import Author from services.auth import login_required from services.db import local_session @strawberry.type class NotificationSeen: notification: int # notification id viewer: int # author id @strawberry.type class Notification: id: int action: str # create update delete join follow etc. entity: str # REACTION SHOUT created_at: int seen: list[NotificationSeen] data: str # JSON data occurrences: int @strawberry.type class NotificationsQueryResult: notifications: list[Notification] unread: int total: int @strawberry.type class NotificationSeenResult: error: str @strawberry.type class NotificationsResult: notifications: List[Notification] unread: int def notification_seen_by_viewer(viewer_id, notification_id, session): seen = ( session.query(NotificationSeen) .filter(NotificationSeen.viewer == viewer_id, NotificationSeen.notification == notification_id) .first() ) return seen is not None @strawberry.type class Query: @strawberry.field @login_required async def load_notifications(self, info, limit: int = 50, offset: int = 0) -> NotificationsResult: user_id = info.context["user_id"] with local_session() as session: author = session.query(Author).filter(Author.user == user_id).first() query = ( session.query(Notification) .outerjoin( NotificationSeen, and_(NotificationSeen.viewer == author.id, NotificationSeen.notification == Notification.id), ) .limit(limit) .offset(offset) ) nslist = query.all() total = query.group_by(Notification.id).count() unread = sum(1 for n in nslist if not n.seen_by_viewer) return NotificationsResult(notifications=nslist, unread=unread, total=total) @strawberry.type class Mutation: @strawberry.mutation @login_required async def mark_notification_as_read(self, info, notification_id: int) -> NotificationSeenResult: user_id = info.context["user_id"] try: with local_session() as session: author = session.query(Author).filter(Author.user == user_id).first() ns = NotificationSeen({"notification": notification_id, "viewer": author.id}) session.add(ns) session.commit() except Exception as e: session.rollback() print(f"[mark_notification_as_read] error: {str(e)}") return NotificationSeenResult(error="cant mark as read") return NotificationSeenResult() @strawberry.mutation @login_required async def mark_all_notifications_as_read(self, info) -> NotificationSeenResult: user_id = info.context["user_id"] with local_session() as session: try: author = session.query(Author).filter(Author.user == user_id).first() _nslist = session.quuery(NotificationSeen).filter(NotificationSeen.viewer == author.id).all() except Exception as e: session.rollback() print(f"[mark_all_notifications_as_read] error: {str(e)}") return NotificationSeenResult(error="cant mark as read") return NotificationSeenResult() schema = strawberry.Schema(query=Query, mutation=Mutation)