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

10
Cargo.lock generated
View File

@@ -1389,6 +1389,15 @@ version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "linkify"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1986921c3c13e81df623c66a298d4b130c061bcb98a01f5b2d3ac402b1649a7f"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.3.4" version = "0.3.4"
@@ -2490,6 +2499,7 @@ dependencies = [
"impl_ops", "impl_ops",
"lazy_static", "lazy_static",
"lettre", "lettre",
"linkify",
"log", "log",
"many-to-many", "many-to-many",
"md5", "md5",

View File

@@ -17,6 +17,7 @@ ulid = "0.4.1"
rand = "0.7.3" rand = "0.7.3"
time = "0.2.16" time = "0.2.16"
base64 = "0.13.0" base64 = "0.13.0"
linkify = "0.6.0"
dotenv = "0.15.0" dotenv = "0.15.0"
futures = "0.3.8" futures = "0.3.8"
chrono = "0.4.15" chrono = "0.4.15"

View File

@@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
export version=0.4.1-alpha.7-patch.2 export version=0.4.1-alpha.8
echo "pub const VERSION: &str = \"${version}\";" > src/version.rs echo "pub const VERSION: &str = \"${version}\";" > src/version.rs

View File

@@ -94,9 +94,7 @@ impl Channel {
let channel_id = self.id().to_string(); let channel_id = self.id().to_string();
ClientboundNotification::ChannelCreate(self) ClientboundNotification::ChannelCreate(self)
.publish(channel_id) .publish(channel_id);
.await
.ok();
Ok(()) Ok(())
} }
@@ -108,9 +106,7 @@ impl Channel {
data, data,
clear: None clear: None
} }
.publish(id) .publish(id);
.await
.ok();
Ok(()) Ok(())
} }
@@ -193,9 +189,7 @@ impl Channel {
})?; })?;
ClientboundNotification::ChannelDelete { id: id.to_string() } ClientboundNotification::ChannelDelete { id: id.to_string() }
.publish(id.to_string()) .publish(id.to_string());
.await
.ok();
if let Channel::Group { icon, .. } = self { if let Channel::Group { icon, .. } = self {
if let Some(attachment) = icon { 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, ContentEncoding, SubscriptionInfo, VapidSignatureBuilder, WebPushClient, WebPushMessageBuilder,
}; };
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum MessageEmbed {
Dummy,
}
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum SystemMessage { pub enum SystemMessage {
@@ -60,7 +54,7 @@ pub struct Message {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub edited: Option<DateTime>, pub edited: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub embeds: Option<MessageEmbed>, pub embeds: Option<Vec<Embed>>,
} }
impl Message { impl Message {
@@ -138,11 +132,12 @@ impl Message {
_ => {} _ => {}
} }
self.process_embed();
let enc = serde_json::to_string(&self).unwrap(); let enc = serde_json::to_string(&self).unwrap();
ClientboundNotification::Message(self) ClientboundNotification::Message(self)
.publish(channel.id().to_string()) .publish(channel.id().to_string());
.await
.unwrap();
/* /*
Web Push Test Code Web Push Test Code
@@ -162,6 +157,7 @@ impl Message {
_ => {} _ => {}
} }
async_std::task::spawn(async move {
// Fetch their corresponding sessions. // Fetch their corresponding sessions.
if let Ok(mut cursor) = get_collection("accounts") if let Ok(mut cursor) = get_collection("accounts")
.find( .find(
@@ -217,23 +213,58 @@ impl Message {
} }
} }
} }
});
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(); let channel = self.channel.clone();
ClientboundNotification::MessageUpdate { ClientboundNotification::MessageUpdate {
id: self.id.clone(), id: self.id.clone(),
data, data,
} }
.publish(channel) .publish(channel);
.await self.process_embed();
.ok();
Ok(()) 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<()> { pub async fn delete(&self) -> Result<()> {
if let Some(attachment) = &self.attachment { if let Some(attachment) = &self.attachment {
attachment.delete().await?; attachment.delete().await?;
@@ -256,9 +287,7 @@ impl Message {
ClientboundNotification::MessageDelete { ClientboundNotification::MessageDelete {
id: self.id.clone(), id: self.id.clone(),
} }
.publish(channel) .publish(channel);
.await
.ok();
if let Some(attachment) = &self.attachment { if let Some(attachment) = &self.attachment {
get_collection("attachments") get_collection("attachments")

View File

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

View File

@@ -107,9 +107,11 @@ pub enum ClientboundNotification {
} }
impl ClientboundNotification { impl ClientboundNotification {
pub async fn publish(self, topic: String) -> Result<(), String> { pub fn publish(self, topic: String) {
async_std::task::spawn(async move {
prehandle_hook(&self); // ! TODO: this should be moved to pubsub prehandle_hook(&self); // ! TODO: this should be moved to pubsub
hive_pubsub::backend::mongo::publish(get_hive(), &topic, self).await hive_pubsub::backend::mongo::publish(get_hive(), &topic, self).await.ok();
});
} }
} }

View File

@@ -133,9 +133,7 @@ async fn accept(stream: TcpStream) {
id: id.clone(), id: id.clone(),
online: true, online: true,
} }
.publish(id) .publish(id);
.await
.ok();
} }
} }
Err(_) => { Err(_) => {
@@ -173,9 +171,7 @@ async fn accept(stream: TcpStream) {
id: channel.clone(), id: channel.clone(),
user, user,
} }
.publish(channel) .publish(channel);
.await
.ok();
} else { } else {
send(ClientboundNotification::Error( send(ClientboundNotification::Error(
WebSocketError::AlreadyAuthenticated, WebSocketError::AlreadyAuthenticated,
@@ -196,9 +192,7 @@ async fn accept(stream: TcpStream) {
id: channel.clone(), id: channel.clone(),
user, user,
} }
.publish(channel) .publish(channel);
.await
.ok();
} else { } else {
send(ClientboundNotification::Error( send(ClientboundNotification::Error(
WebSocketError::AlreadyAuthenticated, WebSocketError::AlreadyAuthenticated,
@@ -238,9 +232,7 @@ async fn accept(stream: TcpStream) {
id: id.clone(), id: id.clone(),
online: false, online: false,
} }
.publish(id) .publish(id);
.await
.ok();
} }
} }

View File

@@ -95,9 +95,7 @@ pub async fn req(user: User, target: Ref) -> Result<()> {
id: id.clone(), id: id.clone(),
user: user.id.clone(), user: user.id.clone(),
} }
.publish(id.clone()) .publish(id.clone());
.await
.ok();
Message::create( Message::create(
"00000000000000000000000000".to_string(), "00000000000000000000000000".to_string(),

View File

@@ -101,9 +101,7 @@ pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<()> {
data: json!(set), data: json!(set),
clear: data.remove clear: data.remove
} }
.publish(id.clone()) .publish(id.clone());
.await
.ok();
if let Some(name) = data.name { if let Some(name) = data.name {
Message::create( Message::create(

View File

@@ -52,9 +52,7 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
id: id.clone(), id: id.clone(),
user: member.id.clone(), user: member.id.clone(),
} }
.publish(id.clone()) .publish(id.clone());
.await
.ok();
Message::create( Message::create(
"00000000000000000000000000".to_string(), "00000000000000000000000000".to_string(),

View File

@@ -49,9 +49,7 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
id: id.clone(), id: id.clone(),
user: member.id.clone(), user: member.id.clone(),
} }
.publish(id.clone()) .publish(id.clone());
.await
.ok();
Message::create( Message::create(
"00000000000000000000000000".to_string(), "00000000000000000000000000".to_string(),

View File

@@ -74,21 +74,19 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> {
.from_override(&target_user, RelationshipStatus::Friend) .from_override(&target_user, RelationshipStatus::Friend)
.await?; .await?;
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target_user, user: target_user,
status: RelationshipStatus::Friend status: RelationshipStatus::Friend
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.to_string(), id: target_id.to_string(),
user, user,
status: RelationshipStatus::Friend status: RelationshipStatus::Friend
} }
.publish(target_id.to_string()) .publish(target_id.to_string());
)
.ok();
Ok(json!({ "status": "Friend" })) Ok(json!({ "status": "Friend" }))
} }
@@ -136,21 +134,20 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> {
let user = user let user = user
.from_override(&target_user, RelationshipStatus::Incoming) .from_override(&target_user, RelationshipStatus::Incoming)
.await?; .await?;
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target_user, user: target_user,
status: RelationshipStatus::Outgoing status: RelationshipStatus::Outgoing
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.to_string(), id: target_id.to_string(),
user, user,
status: RelationshipStatus::Incoming status: RelationshipStatus::Incoming
} }
.publish(target_id.to_string()) .publish(target_id.to_string());
)
.ok();
Ok(json!({ "status": "Outgoing" })) Ok(json!({ "status": "Outgoing" }))
} }

View File

@@ -38,9 +38,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
user: target, user: target,
status: RelationshipStatus::Blocked, status: RelationshipStatus::Blocked,
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }
@@ -84,21 +82,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target, user: target,
status: RelationshipStatus::Blocked status: RelationshipStatus::Blocked
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::BlockedOther status: RelationshipStatus::BlockedOther
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }
@@ -146,21 +142,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target, user: target,
status: RelationshipStatus::Blocked status: RelationshipStatus::Blocked
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::BlockedOther status: RelationshipStatus::BlockedOther
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "Blocked" })) Ok(json!({ "status": "Blocked" }))
} }

View File

@@ -60,9 +60,7 @@ pub async fn req(
data: json!(data.0), data: json!(data.0),
clear: None clear: None
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
Ok(()) Ok(())
} }

View File

@@ -135,9 +135,7 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
data: json!({ "status": status }), data: json!({ "status": status }),
clear: None clear: None
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
} }
if let Some(avatar) = attachment { if let Some(avatar) = attachment {
@@ -146,9 +144,7 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
data: json!({ "avatar": avatar }), data: json!({ "avatar": avatar }),
clear: None clear: None
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
} }
if let Some(clear) = data.remove { if let Some(clear) = data.remove {
@@ -157,9 +153,7 @@ pub async fn req(user: User, data: Json<Data>, _ignore_id: String) -> Result<()>
data: json!({}), data: json!({}),
clear: Some(clear) clear: Some(clear)
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
} }
if remove_avatar { if remove_avatar {

View File

@@ -53,21 +53,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target, user: target,
status: RelationshipStatus::None status: RelationshipStatus::None
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user, user,
status: RelationshipStatus::None status: RelationshipStatus::None
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "None" })) Ok(json!({ "status": "None" }))
} }

View File

@@ -40,9 +40,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
user: target, user: target,
status: RelationshipStatus::BlockedOther, status: RelationshipStatus::BlockedOther,
} }
.publish(user.id.clone()) .publish(user.id.clone());
.await
.ok();
Ok(json!({ "status": "BlockedOther" })) Ok(json!({ "status": "BlockedOther" }))
} }
@@ -84,21 +82,19 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
.await?; .await?;
let target_id = target.id.clone(); let target_id = target.id.clone();
try_join!(
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: user.id.clone(), id: user.id.clone(),
user: target, user: target,
status: RelationshipStatus::None status: RelationshipStatus::None
} }
.publish(user.id.clone()), .publish(user.id.clone());
ClientboundNotification::UserRelationship { ClientboundNotification::UserRelationship {
id: target_id.clone(), id: target_id.clone(),
user: user, user: user,
status: RelationshipStatus::None status: RelationshipStatus::None
} }
.publish(target_id) .publish(target_id);
)
.ok();
Ok(json!({ "status": "None" })) Ok(json!({ "status": "None" }))
} }

View File

@@ -18,6 +18,8 @@ lazy_static! {
pub static ref AUTUMN_URL: String = pub static ref AUTUMN_URL: String =
env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref JANUARY_URL: String =
env::var("JANUARY_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref VOSO_URL: String = pub static ref VOSO_URL: String =
env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref VOSO_WS_HOST: String = pub static ref VOSO_WS_HOST: String =