···5858 ll.Info("starting scheduler")
5959 go notella.StartScheduler()
60606161+ ll.Log("Connecting", "cyan", "to Churros database at [bold]%s[reset]", config.ChurrosDatabaseURL)
6262+ err = notella.ConnectToDababase()
6363+ if err != nil {
6464+ ll.ErrorDisplay("could not connect to database", err)
6565+ }
6666+6167 ll.Log("Connecting", "cyan", "to NATS server at [bold]%s[reset]", nats.DefaultURL)
6268 nc, err := nats.Connect(nats.DefaultURL)
6369 if err != nil {
···131137132138 // Process each message
133139 for _, msg := range msgs {
134134- notella.NatsReceiver(msg)
140140+ err = notella.NatsReceiver(msg)
141141+ if err != nil {
142142+ ll.ErrorDisplay("Could not process message", err)
143143+ }
135144 msg.Ack() // Acknowledge the message
136145 }
137146 }
+45-45
types.d.ts
···11export interface Message {
22- /**
33- * URL to go to when the action button is clicked
44- */
55- action: string;
66- /**
77- * Additional action buttons
88- */
99- actions: Action[];
1010- /**
1111- * Notification body
1212- */
1313- body: string;
1414- /**
1515- * Type of event that triggered the notification
1616- */
1717- event: Event;
1818- /**
1919- * Unique ID for the notification scheduling request.
2020- */
2121- id: string;
2222- /**
2323- * URL to an image to display in the notification
2424- */
2525- image: string;
2626- /**
2727- * Churros ID of the ressource (the ticket, the post, the comment, etc)
2828- * Used to determine to whom the notification should be sent
2929- * For godchild_request, this is not a user id, but a godparent request id.
3030- */
3131- object_id: string;
3232- /**
3333- * When to push the notification
3434- */
3535- send_at: Date;
3636- /**
3737- * Notification title
3838- */
3939- title: string;
22+ /**
33+ * URL to go to when the action button is clicked
44+ */
55+ action: string;
66+ /**
77+ * Additional action buttons
88+ */
99+ actions: Action[];
1010+ /**
1111+ * Notification body
1212+ */
1313+ body: string;
1414+ /**
1515+ * Type of event that triggered the notification
1616+ */
1717+ event: Event;
1818+ /**
1919+ * Unique ID for the notification scheduling request.
2020+ */
2121+ id: string;
2222+ /**
2323+ * URL to an image to display in the notification
2424+ */
2525+ image: string;
2626+ /**
2727+ * Churros ID of the ressource (the ticket, the post, the comment, etc)
2828+ * Used to determine to whom the notification should be sent
2929+ * For godchild_request, this is not a user id, but a godparent request id.
3030+ */
3131+ object_id: string;
3232+ /**
3333+ * When to push the notification
3434+ */
3535+ send_at: Date;
3636+ /**
3737+ * Notification title
3838+ */
3939+ title: string;
4040}
41414242export interface Action {
4343- action: string;
4444- label: string;
4343+ action: string;
4444+ label: string;
4545}
46464747/**
4848 * Type of event that triggered the notification
4949 */
5050export enum Event {
5151- CommentReply = 'comment_reply',
5252- GodchildRequest = 'godchild_request',
5353- NewComment = 'new_comment',
5454- NewPost = 'new_post',
5555- NewTicket = 'new_ticket',
5151+ CommentReply = "comment_reply",
5252+ GodchildRequest = "godchild_request",
5353+ NewComment = "new_comment",
5454+ NewPost = "new_post",
5555+ NewTicket = "new_ticket",
5656}
+84
users.go
···11+package notella
22+33+import (
44+ "context"
55+ "fmt"
66+77+ "git.inpt.fr/churros/notella/db"
88+)
99+1010+// AllUsers returns all the users in the database that have at least one notification subscription
1111+func AllUsers() ([]string, error) {
1212+ users, err := prisma.User.FindMany(
1313+ db.User.NotificationSubscriptions.Some(),
1414+ ).Select(
1515+ db.User.ID.Field(),
1616+ ).Exec(context.Background())
1717+1818+ if err != nil {
1919+ return []string{}, fmt.Errorf("while getting all users: %w", err)
2020+ }
2121+2222+ ids := make([]string, len(users))
2323+ for i, user := range users {
2424+ ids[i] = user.ID
2525+ }
2626+2727+ return ids, nil
2828+}
2929+3030+// Receivers determines which users to send the notification to
3131+func Receivers(message Message) ([]string, error) {
3232+ switch message.Event {
3333+ case EventNewPost:
3434+ return receiversForPost(message)
3535+ }
3636+3737+ return []string{}, nil
3838+}
3939+4040+func receiversForPost(message Message) (userIds []string, err error) {
4141+ post, err := prisma.Article.FindUnique(
4242+ db.Article.ID.Equals(message.ChurrosObjectId),
4343+ ).With(
4444+ db.Article.Group.Fetch().With(
4545+ db.Group.Members.Fetch().Select(
4646+ db.GroupMember.MemberID.Field(),
4747+ ),
4848+ db.Group.StudentAssociation.Fetch().With(
4949+ db.StudentAssociation.School.Fetch().With(
5050+ db.School.Majors.Fetch().With(
5151+ db.Major.Students.Fetch().Select(
5252+ db.User.ID.Field(),
5353+ ),
5454+ ),
5555+ ),
5656+ ),
5757+ ),
5858+ ).Exec(context.Background())
5959+6060+ if err != nil {
6161+ return []string{}, fmt.Errorf("while getting the post %q: %w", message.Id, err)
6262+ }
6363+6464+ switch post.Visibility {
6565+ case db.VisibilityPrivate:
6666+ case db.VisibilityUnlisted:
6767+ return []string{}, nil
6868+ case db.VisibilityPublic:
6969+ return AllUsers()
7070+ case db.VisibilitySchoolRestricted:
7171+ for _, major := range post.Group().StudentAssociation().School().Majors() {
7272+ for _, student := range major.Students() {
7373+ userIds = append(userIds, student.ID)
7474+ }
7575+ }
7676+ return
7777+ case db.VisibilityGroupRestricted:
7878+ for _, member := range post.Group().Members() {
7979+ userIds = append(userIds, member.MemberID)
8080+ }
8181+ }
8282+8383+ return userIds, fmt.Errorf("unknown post visibility %q", post.Visibility)
8484+}