change apns to use sandbox, and (somewhat) provide a custom payload

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
IAmTomahawkx
2024-07-05 20:43:08 -07:00
parent f9d9059e73
commit 27f15f7b02
3 changed files with 54 additions and 4 deletions

View File

@@ -30,6 +30,7 @@ public_key = "BGcvgR-i2z4IQ5Mw841vJvkLjt8wY-FjmWrw83jOLCY52qcGZS0OF7nfLzuYbjsQIS
api_key = ""
[api.apn]
sandbox = false
pkcs8 = ""
key_id = ""
team_id = ""

View File

@@ -79,6 +79,7 @@ pub struct ApiFcm {
#[derive(Deserialize, Debug, Clone)]
pub struct ApiApn {
pub sandbox: bool,
pub pkcs8: String,
pub key_id: String,
pub team_id: String,

View File

@@ -6,13 +6,23 @@ use base64::{
};
use deadqueue::limited::Queue;
use once_cell::sync::Lazy;
use revolt_a2::{Client, ClientConfig, DefaultNotificationBuilder};
use revolt_a2::{Client, ClientConfig, DefaultNotificationBuilder, Endpoint};
use revolt_a2::{Error, ErrorBody, ErrorReason, NotificationBuilder, Response};
use revolt_config::config;
use revolt_models::v0::PushNotification;
use revolt_models::v0::{Message, PushNotification};
use crate::Database;
/// Payload information
#[derive(Debug)]
pub struct ApnCustomPayload {
message: Message,
serverId: String,
authorAvatar: String,
authorDisplayName: String,
channelName: String,
}
/// Task information
#[derive(Debug)]
pub struct ApnTask {
@@ -30,9 +40,24 @@ pub struct ApnTask {
/// Thread Id
thread_id: String,
/// Category (informs the client what kind of notification is being sent.)
category: String,
/// Payload used by the iOS client to modify the notification
payload: ApnCustomPayload,
}
impl ApnTask {
fn format_title(notification: &PushNotification) -> String {
// ideally this changes depending on context
// in a server, it would look like "Sendername, #channelname in servername"
// in a group, it would look like "Sendername in groupname"
// in a dm it should just be "Sendername".
// not sure how feasible all those are given the PushNotification object as it currently stands.
todo!();
}
pub fn from_notification(
session_id: String,
device_token: String,
@@ -41,9 +66,17 @@ impl ApnTask {
ApnTask {
session_id,
device_token,
title: notification.author.to_string(),
title: ApnTask::format_title(notification),
body: notification.body.to_string(),
thread_id: notification.tag.to_string(),
category: "ALERT_MESSAGE".to_string(),
payload: ApnCustomPayload {
message: (),
serverId: (),
authorAvatar: notification.icon.to_string(),
authorDisplayName: notification.author.to_string(),
channelName: (),
},
}
}
}
@@ -67,15 +100,24 @@ pub async fn worker(db: Database) {
return;
}
let endpoint = if config.api.apn.sandbox {
Endpoint::Sandbox
} else {
Endpoint::Production
};
let pkcs8 = engine::general_purpose::STANDARD
.decode(config.api.apn.pkcs8)
.expect("valid `pcks8`");
let client_config = ClientConfig::default();
client_config.endpoint = endpoint;
let client = Client::token(
&mut Cursor::new(pkcs8),
config.api.apn.key_id,
config.api.apn.team_id,
ClientConfig::default(),
client_config,
)
.expect("could not create APN client");
@@ -85,8 +127,14 @@ pub async fn worker(db: Database) {
.set_title(&task.title)
.set_body(&task.body)
.set_thread_id(&task.thread_id)
.set_category(&task.category)
.set_mutable_content() // allows the service extension to execute
.build(&task.device_token, Default::default());
payload.data = &task.payload; // this looks like a job for someone more rust-inclined than me. -tom
println!("sending APNS payload: {:?}", payload.data);
if let Err(err) = client.send(payload).await {
match err {
Error::ResponseError(Response {