refactor: switch from fcm to fcm_v1 crate

This commit is contained in:
Paul Makles
2024-08-29 20:17:52 +01:00
parent ae2194cce8
commit 1fb4032d9e
4 changed files with 76 additions and 26 deletions

View File

@@ -47,8 +47,18 @@ private_key = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUJSUWpyTWxLR
public_key = "BGcvgR-i2z4IQ5Mw841vJvkLjt8wY-FjmWrw83jOLCY52qcGZS0OF7nfLzuYbjsQISwVO2HXrmf18gLWVX3Kwfw=" public_key = "BGcvgR-i2z4IQ5Mw841vJvkLjt8wY-FjmWrw83jOLCY52qcGZS0OF7nfLzuYbjsQISwVO2HXrmf18gLWVX3Kwfw="
[api.fcm] [api.fcm]
# Google Firebase Cloud Messaging API key for sending notifications # Google Firebase Cloud Messaging Service Account Key
api_key = "" # Obtained from the cloud messaging console
key_type = ""
project_id = ""
private_key_id = ""
private_key = ""
client_email = ""
client_id = ""
auth_uri = ""
token_uri = ""
auth_provider_x509_cert_url = ""
client_x509_cert_url = ""
[api.apn] [api.apn]
# Apple Push Notifications keys for sending notifications # Apple Push Notifications keys for sending notifications

View File

@@ -74,7 +74,16 @@ pub struct ApiVapid {
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct ApiFcm { pub struct ApiFcm {
pub api_key: String, pub key_type: String,
pub project_id: String,
pub private_key_id: String,
pub private_key: String,
pub client_email: String,
pub client_id: String,
pub auth_uri: String,
pub token_uri: String,
pub auth_provider_x509_cert_url: String,
pub client_x509_cert_url: String,
} }
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]

View File

@@ -85,11 +85,9 @@ revolt_okapi = { version = "0.9.1", optional = true }
revolt_rocket_okapi = { version = "0.9.1", optional = true } revolt_rocket_okapi = { version = "0.9.1", optional = true }
# Notifications # Notifications
fcm = "0.9.2" fcm_v1 = "0.3.0"
web-push = "0.10.0" web-push = "0.10.0"
revolt_a2 = { version = "0.10", default-features = false, features = [ revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] }
"ring",
] }
# Authifier # Authifier
authifier = { version = "1.0.8" } authifier = { version = "1.0.8" }

View File

@@ -1,4 +1,7 @@
use std::collections::HashSet; use std::{
collections::{HashMap, HashSet},
time::Duration,
};
use authifier::Database; use authifier::Database;
use base64::{ use base64::{
@@ -6,6 +9,7 @@ use base64::{
Engine as _, Engine as _,
}; };
use deadqueue::limited::Queue; use deadqueue::limited::Queue;
use fcm_v1::auth::{Authenticator, ServiceAccountKey};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use revolt_config::config; use revolt_config::config;
use revolt_models::v0::PushNotification; use revolt_models::v0::PushNotification;
@@ -54,10 +58,28 @@ pub async fn worker(db: Database) {
let config = config().await; let config = config().await;
let web_push_client = IsahcWebPushClient::new().unwrap(); let web_push_client = IsahcWebPushClient::new().unwrap();
let fcm_client = if config.api.fcm.api_key.is_empty() { let fcm_client = if config.api.fcm.key_type.is_empty() {
None None
} else { } else {
Some(fcm::Client::new()) Some(fcm_v1::Client::new(
Authenticator::service_account::<&str>(ServiceAccountKey {
key_type: Some(config.api.fcm.key_type),
project_id: Some(config.api.fcm.project_id.clone()),
private_key_id: Some(config.api.fcm.private_key_id),
private_key: config.api.fcm.private_key,
client_email: config.api.fcm.client_email,
client_id: Some(config.api.fcm.client_id),
auth_uri: Some(config.api.fcm.auth_uri),
token_uri: config.api.fcm.token_uri,
auth_provider_x509_cert_url: Some(config.api.fcm.auth_provider_x509_cert_url),
client_x509_cert_url: Some(config.api.fcm.client_x509_cert_url),
})
.await
.unwrap(),
config.api.fcm.project_id,
false,
Duration::from_secs(5),
))
}; };
let web_push_private_key = engine::general_purpose::URL_SAFE_NO_PAD let web_push_private_key = engine::general_purpose::URL_SAFE_NO_PAD
@@ -76,27 +98,38 @@ pub async fn worker(db: Database) {
let PushNotification { let PushNotification {
author, author,
icon, icon,
image: _, image,
body, body,
tag, tag: _,
timestamp: _, timestamp,
url: _, url: _,
message: _, message,
} = &task.payload; } = &task.payload;
let mut notification = fcm::NotificationBuilder::new(); let message = fcm_v1::message::Message {
notification.title(author); token: Some(sub.auth),
notification.icon(icon); data: Some(HashMap::from([
notification.body(body); (
notification.tag(tag); "author".to_owned(),
// TODO: expand support for fields serde_json::Value::String(author.clone()),
let notification = notification.finalize(); ),
("icon".to_owned(), serde_json::Value::String(icon.clone())),
(
"image".to_owned(),
if let Some(image) = image {
serde_json::Value::String(image.clone())
} else {
serde_json::Value::Null
},
),
("body".to_owned(), serde_json::Value::String(body.clone())),
("timestamp".to_owned(), json!(timestamp)),
("message".to_owned(), json!(&message)),
])),
..Default::default()
};
let mut message_builder = if let Err(err) = client.send(&message).await {
fcm::MessageBuilder::new(&config.api.fcm.api_key, &sub.auth);
message_builder.notification(notification);
if let Err(err) = client.send(message_builder.finalize()).await {
error!("Failed to send FCM notification! {:?}", err); error!("Failed to send FCM notification! {:?}", err);
} else { } else {
info!("Sent FCM notification to {:?}.", session.id); info!("Sent FCM notification to {:?}.", session.id);