Add january support.

This commit is contained in:
Paul
2021-05-07 18:00:21 +01:00
parent cf7bb832da
commit 7293abfc53
20 changed files with 280 additions and 208 deletions

View File

@@ -94,9 +94,7 @@ impl Channel {
let channel_id = self.id().to_string();
ClientboundNotification::ChannelCreate(self)
.publish(channel_id)
.await
.ok();
.publish(channel_id);
Ok(())
}
@@ -108,9 +106,7 @@ impl Channel {
data,
clear: None
}
.publish(id)
.await
.ok();
.publish(id);
Ok(())
}
@@ -193,9 +189,7 @@ impl Channel {
})?;
ClientboundNotification::ChannelDelete { id: id.to_string() }
.publish(id.to_string())
.await
.ok();
.publish(id.to_string());
if let Channel::Group { icon, .. } = self {
if let Some(attachment) = icon {

View File

@@ -0,0 +1,71 @@
use serde::{Serialize, Deserialize};
use linkify::{LinkFinder, LinkKind};
use crate::util::{result::{Error, Result}, variables::JANUARY_URL};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum MediaSize {
Large,
Preview,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Media {
pub url: String,
pub width: isize,
pub height: isize,
pub size: MediaSize,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Metadata {
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
image: Option<Media>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum Embed {
Website(Metadata),
Image(Media),
None,
}
impl Embed {
pub async fn generate(content: String) -> Result<Vec<Embed>> {
// FIXME: allow multiple links
let mut finder = LinkFinder::new();
finder.kinds(&[LinkKind::Url]);
let links: Vec<_> = finder.links(&content).collect();
if links.len() == 0 {
return Err(Error::LabelMe);
}
let link = &links[0];
let client = reqwest::Client::new();
let result = client
.get(&format!("{}/embed", *JANUARY_URL))
.query(&[("url", link.as_str())])
.send()
.await;
match result {
Err(_) => return Err(Error::LabelMe),
Ok(result) => match result.status() {
reqwest::StatusCode::OK => {
let res: Embed = result.json()
.await
.map_err(|_| Error::InvalidOperation)?;
Ok(vec![ res ])
},
_ => return Err(Error::LabelMe),
},
}
}
}

View File

@@ -17,12 +17,6 @@ use web_push::{
ContentEncoding, SubscriptionInfo, VapidSignatureBuilder, WebPushClient, WebPushMessageBuilder,
};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum MessageEmbed {
Dummy,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum SystemMessage {
@@ -60,7 +54,7 @@ pub struct Message {
#[serde(skip_serializing_if = "Option::is_none")]
pub edited: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embeds: Option<MessageEmbed>,
pub embeds: Option<Vec<Embed>>,
}
impl Message {
@@ -138,11 +132,12 @@ impl Message {
_ => {}
}
self.process_embed();
let enc = serde_json::to_string(&self).unwrap();
ClientboundNotification::Message(self)
.publish(channel.id().to_string())
.await
.unwrap();
.publish(channel.id().to_string());
/*
Web Push Test Code
@@ -162,78 +157,114 @@ impl Message {
_ => {}
}
// Fetch their corresponding sessions.
if let Ok(mut cursor) = get_collection("accounts")
.find(
doc! {
"_id": {
"$in": target_ids
async_std::task::spawn(async move {
// Fetch their corresponding sessions.
if let Ok(mut cursor) = get_collection("accounts")
.find(
doc! {
"_id": {
"$in": target_ids
},
"sessions.subscription": {
"$exists": true
}
},
"sessions.subscription": {
"$exists": true
}
},
FindOptions::builder()
.projection(doc! { "sessions": 1 })
.build(),
)
.await
{
let mut subscriptions = vec![];
while let Some(result) = cursor.next().await {
if let Ok(doc) = result {
if let Ok(sessions) = doc.get_array("sessions") {
for session in sessions {
if let Some(doc) = session.as_document() {
if let Ok(sub) = doc.get_document("subscription") {
let endpoint = sub.get_str("endpoint").unwrap().to_string();
let p256dh = sub.get_str("p256dh").unwrap().to_string();
let auth = sub.get_str("auth").unwrap().to_string();
FindOptions::builder()
.projection(doc! { "sessions": 1 })
.build(),
)
.await
{
let mut subscriptions = vec![];
while let Some(result) = cursor.next().await {
if let Ok(doc) = result {
if let Ok(sessions) = doc.get_array("sessions") {
for session in sessions {
if let Some(doc) = session.as_document() {
if let Ok(sub) = doc.get_document("subscription") {
let endpoint = sub.get_str("endpoint").unwrap().to_string();
let p256dh = sub.get_str("p256dh").unwrap().to_string();
let auth = sub.get_str("auth").unwrap().to_string();
subscriptions
.push(SubscriptionInfo::new(endpoint, p256dh, auth));
subscriptions
.push(SubscriptionInfo::new(endpoint, p256dh, auth));
}
}
}
}
}
}
}
if subscriptions.len() > 0 {
let client = WebPushClient::new();
let key =
base64::decode_config(VAPID_PRIVATE_KEY.clone(), base64::URL_SAFE).unwrap();
if subscriptions.len() > 0 {
let client = WebPushClient::new();
let key =
base64::decode_config(VAPID_PRIVATE_KEY.clone(), base64::URL_SAFE).unwrap();
for subscription in subscriptions {
let mut builder = WebPushMessageBuilder::new(&subscription).unwrap();
let sig_builder =
VapidSignatureBuilder::from_pem(std::io::Cursor::new(&key), &subscription)
.unwrap();
let signature = sig_builder.build().unwrap();
builder.set_vapid_signature(signature);
builder.set_payload(ContentEncoding::AesGcm, enc.as_bytes());
let m = builder.build().unwrap();
client.send(m).await.ok();
for subscription in subscriptions {
let mut builder = WebPushMessageBuilder::new(&subscription).unwrap();
let sig_builder =
VapidSignatureBuilder::from_pem(std::io::Cursor::new(&key), &subscription)
.unwrap();
let signature = sig_builder.build().unwrap();
builder.set_vapid_signature(signature);
builder.set_payload(ContentEncoding::AesGcm, enc.as_bytes());
let m = builder.build().unwrap();
client.send(m).await.ok();
}
}
}
}
});
Ok(())
}
pub async fn publish_update(&self, data: JsonValue) -> Result<()> {
pub async fn publish_update(self, data: JsonValue) -> Result<()> {
let channel = self.channel.clone();
ClientboundNotification::MessageUpdate {
id: self.id.clone(),
data,
}
.publish(channel)
.await
.ok();
.publish(channel);
self.process_embed();
Ok(())
}
pub fn process_embed(&self) {
if let Content::Text(text) = &self.content {
let id = self.id.clone();
let content = text.clone();
let channel = self.channel.clone();
async_std::task::spawn(async move {
if let Ok(embeds) = Embed::generate(content).await {
if let Ok(bson) = to_bson(&embeds) {
if let Ok(_) = get_collection("messages")
.update_one(
doc! {
"_id": &id
},
doc! {
"$set": {
"embeds": bson
}
},
None,
)
.await {
ClientboundNotification::MessageUpdate {
id,
data: json!({
"embeds": embeds
}),
}
.publish(channel);
}
}
}
});
}
}
pub async fn delete(&self) -> Result<()> {
if let Some(attachment) = &self.attachment {
attachment.delete().await?;
@@ -256,9 +287,7 @@ impl Message {
ClientboundNotification::MessageDelete {
id: self.id.clone(),
}
.publish(channel)
.await
.ok();
.publish(channel);
if let Some(attachment) = &self.attachment {
get_collection("attachments")

View File

@@ -1,9 +1,11 @@
mod autumn;
mod channel;
mod guild;
mod autumn;
mod january;
mod channel;
mod message;
mod user;
pub use january::*;
pub use autumn::*;
pub use channel::*;
pub use guild::*;