Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Announcement parsing #90

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion Sources/Server/Controllers/AnnouncementController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct AnnouncementController<DecoderType>: RouteCollection where DecoderType: C
.first()
guard let announcement else {
throw Abort(.notFound)
}
} //testing
return announcement
}

Expand Down
22 changes: 21 additions & 1 deletion Sources/Server/Controllers/AnnouncementsController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,29 @@ struct AnnouncementsController<DecoderType>: RouteCollection where DecoderType:

private func create(_ request: Request) async throws -> Announcement {
let announcement = try request.content.decode(Announcement.self, using: self.decoder)
guard let data = (announcement.subject + announcement.body).data(using: .utf8) else {

// Check if the announcement start date is at least an hour in the future
let now = Date()
let timeUntilStart = announcement.start.timeIntervalSince(now)
if timeUntilStart > 3600 { // More than an hour ahead
// Schedule the notification job here
let job = SendAnnouncementNotificationJob(announcementID: announcement.id)
// Calculate the delay for the job based on the announcement's start date
let delay = DispatchTimeInterval.seconds(Int(timeUntilStart))
application.queues.dispatch(job, after: delay)
} else {

}


// new changes 2/13

// ** announcement json string **
guard let data = ("\(announcement.id) || \(announcement.subject) || \(announcement.start) || \(announcement.end) ||
\(announcement.scheduleType) || \(announcement.body) || \(announcement.interruptionLevel)").data(using: .utf8) else {
throw Abort(.internalServerError)
}

if try CryptographyUtilities.verify(signature: announcement.signature, of: data) {
try await announcement.save(on: request.db(.psql))

Expand Down
66 changes: 66 additions & 0 deletions Sources/Server/Jobs/AnnouncementJobs.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import Vapor
import Fluent
import FluentPostgresDriver // or whichever Fluent driver you're using
import APNS

// Define a job for sending announcement notifications
struct SendAnnouncementNotificationJob: Job {
// Define properties needed for the job
let announcementID: UUID

// Implement the job execution logic
func dequeue(_ context: QueueContext, _ task: Task) async throws {
// Fetch the announcement from the database using the provided announcementID
guard let announcement = try await Announcement.find(announcementID, on: context.application.db(.psql)).get() else {
// Handle the case where the announcement could not be found
context.logger.error("Announcement with ID \(announcementID) not found.")
return
}

// Prepare the APNS notification payload and other settings based on the announcement details
let interruptionLevel: APNSAlertNotificationInterruptionLevel
switch announcement.interruptionLevel {
case .passive:
interruptionLevel = .passive
case .active:
interruptionLevel = .active
case .timeSensitive:
interruptionLevel = .timeSensitive
case .critical:
interruptionLevel = .critical
}

let payload = ... // Construct your notification payload here

// Fetch all APNS devices from the database
let devices = try await APNSDevice.query(on: context.application.db(.psql)).all()

// Send the notification to each device
for device in devices {
let deviceToken = device.token
do {
try await context.application.apns.client.sendAlertNotification(
APNSAlertNotification(
alert: APNSAlertNotificationContent(
title: .raw("Announcement"),
subtitle: .raw(announcement.subject),
body: .raw(announcement.body),
launchImage: nil
),
expiration: announcement.end, // Adjust the expiration based on the announcement's end date
priority: .immediately,
topic: Constants.apnsTopic,
payload: payload,
sound: .default,
mutableContent: 1,
interruptionLevel: interruptionLevel,
apnsID: announcement.id
),
deviceToken: deviceToken
)
} catch {
context.logger.error("Failed to send APNS notification: \(error)")
}
}
}
}