]> Untitled Git - lemmy.git/commitdiff
Move websocket code into workspace (#107)
authornutomic <nutomic@noreply.yerbamate.dev>
Thu, 24 Sep 2020 13:53:21 +0000 (13:53 +0000)
committerdessalines <dessalines@noreply.yerbamate.dev>
Thu, 24 Sep 2020 13:53:21 +0000 (13:53 +0000)
Adjust dockerfiles, fix cargo.toml and remove unused deps

Merge branch 'main' into move-websocket-to-workspace

Move api code into workspace

Move apub to separate workspace

Move websocket code into separate workspace

Some code cleanup

Remove websocket dependency on API

Co-authored-by: Felix Ableitner <me@nutomic.com>
Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/107

64 files changed:
Cargo.lock
Cargo.toml
docker/dev/Dockerfile
docker/prod/Dockerfile
docker/prod/deploy.sh
lemmy_api/Cargo.toml [new file with mode: 0644]
lemmy_api/src/claims.rs [moved from src/api/claims.rs with 100% similarity]
lemmy_api/src/comment.rs [moved from src/api/comment.rs with 98% similarity]
lemmy_api/src/community.rs [moved from src/api/community.rs with 98% similarity]
lemmy_api/src/lib.rs [new file with mode: 0644]
lemmy_api/src/post.rs [moved from src/api/post.rs with 98% similarity]
lemmy_api/src/site.rs [moved from src/api/site.rs with 98% similarity]
lemmy_api/src/user.rs [moved from src/api/user.rs with 99% similarity]
lemmy_api/src/version.rs [moved from src/version.rs with 100% similarity]
lemmy_apub/Cargo.toml [new file with mode: 0644]
lemmy_apub/src/activities.rs [moved from src/apub/activities.rs with 87% similarity]
lemmy_apub/src/activity_queue.rs [moved from src/apub/activity_queue.rs with 97% similarity]
lemmy_apub/src/comment.rs [moved from src/apub/comment.rs with 97% similarity]
lemmy_apub/src/community.rs [moved from src/apub/community.rs with 97% similarity]
lemmy_apub/src/extensions/group_extensions.rs [moved from src/apub/extensions/group_extensions.rs with 100% similarity]
lemmy_apub/src/extensions/mod.rs [moved from src/apub/extensions/mod.rs with 100% similarity]
lemmy_apub/src/extensions/page_extension.rs [moved from src/apub/extensions/page_extension.rs with 100% similarity]
lemmy_apub/src/extensions/signatures.rs [moved from src/apub/extensions/signatures.rs with 99% similarity]
lemmy_apub/src/fetcher.rs [moved from src/apub/fetcher.rs with 98% similarity]
lemmy_apub/src/inbox/activities/announce.rs [moved from src/apub/inbox/activities/announce.rs with 77% similarity]
lemmy_apub/src/inbox/activities/create.rs [moved from src/apub/inbox/activities/create.rs with 91% similarity]
lemmy_apub/src/inbox/activities/delete.rs [moved from src/apub/inbox/activities/delete.rs with 94% similarity]
lemmy_apub/src/inbox/activities/dislike.rs [moved from src/apub/inbox/activities/dislike.rs with 89% similarity]
lemmy_apub/src/inbox/activities/like.rs [moved from src/apub/inbox/activities/like.rs with 89% similarity]
lemmy_apub/src/inbox/activities/mod.rs [moved from src/apub/inbox/activities/mod.rs with 100% similarity]
lemmy_apub/src/inbox/activities/remove.rs [moved from src/apub/inbox/activities/remove.rs with 94% similarity]
lemmy_apub/src/inbox/activities/undo.rs [moved from src/apub/inbox/activities/undo.rs with 98% similarity]
lemmy_apub/src/inbox/activities/update.rs [moved from src/apub/inbox/activities/update.rs with 89% similarity]
lemmy_apub/src/inbox/community_inbox.rs [moved from src/apub/inbox/community_inbox.rs with 95% similarity]
lemmy_apub/src/inbox/mod.rs [moved from src/apub/inbox/mod.rs with 100% similarity]
lemmy_apub/src/inbox/shared_inbox.rs [moved from src/apub/inbox/shared_inbox.rs with 83% similarity]
lemmy_apub/src/inbox/user_inbox.rs [moved from src/apub/inbox/user_inbox.rs with 96% similarity]
lemmy_apub/src/lib.rs [moved from src/apub/mod.rs with 96% similarity]
lemmy_apub/src/post.rs [moved from src/apub/post.rs with 97% similarity]
lemmy_apub/src/private_message.rs [moved from src/apub/private_message.rs with 95% similarity]
lemmy_apub/src/user.rs [moved from src/apub/user.rs with 96% similarity]
lemmy_db/src/lib.rs
lemmy_rate_limit/src/lib.rs
lemmy_structs/Cargo.toml
lemmy_structs/src/lib.rs
lemmy_structs/src/websocket.rs
lemmy_utils/Cargo.toml
lemmy_utils/src/lib.rs
lemmy_utils/src/request.rs [moved from src/request.rs with 97% similarity]
lemmy_websocket/Cargo.toml [new file with mode: 0644]
lemmy_websocket/src/chat_server.rs [moved from src/websocket/chat_server.rs with 58% similarity]
lemmy_websocket/src/handlers.rs [moved from src/websocket/handlers.rs with 76% similarity]
lemmy_websocket/src/lib.rs [new file with mode: 0644]
lemmy_websocket/src/messages.rs [new file with mode: 0644]
src/api/mod.rs [deleted file]
src/lib.rs
src/main.rs
src/routes/api.rs
src/routes/federation.rs
src/routes/feeds.rs
src/routes/nodeinfo.rs
src/routes/webfinger.rs
src/routes/websocket.rs
src/websocket/mod.rs [deleted file]

index cefc4970580a957753aa58851c522de903fd9e5e..fe119382e5cc1e9d40f7d53985210cd86426f16b 100644 (file)
@@ -1113,12 +1113,6 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
 
-[[package]]
-name = "dotenv"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
-
 [[package]]
 name = "dtoa"
 version = "0.4.6"
@@ -1809,6 +1803,92 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
+[[package]]
+name = "lemmy_api"
+version = "0.1.0"
+dependencies = [
+ "actix",
+ "actix-rt",
+ "actix-web",
+ "anyhow",
+ "async-trait",
+ "awc",
+ "background-jobs",
+ "base64 0.12.3",
+ "bcrypt",
+ "captcha",
+ "chrono",
+ "diesel",
+ "futures",
+ "http",
+ "http-signature-normalization-actix",
+ "itertools",
+ "jsonwebtoken",
+ "lazy_static",
+ "lemmy_apub",
+ "lemmy_db",
+ "lemmy_rate_limit",
+ "lemmy_structs",
+ "lemmy_utils",
+ "lemmy_websocket",
+ "log",
+ "openssl",
+ "percent-encoding",
+ "rand 0.7.3",
+ "reqwest",
+ "serde 1.0.116",
+ "serde_json",
+ "sha2",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "tokio",
+ "url",
+ "uuid 0.8.1",
+]
+
+[[package]]
+name = "lemmy_apub"
+version = "0.1.0"
+dependencies = [
+ "activitystreams",
+ "activitystreams-ext",
+ "actix",
+ "actix-rt",
+ "actix-web",
+ "anyhow",
+ "async-trait",
+ "awc",
+ "background-jobs",
+ "base64 0.12.3",
+ "bcrypt",
+ "chrono",
+ "diesel",
+ "futures",
+ "http",
+ "http-signature-normalization-actix",
+ "itertools",
+ "lazy_static",
+ "lemmy_db",
+ "lemmy_structs",
+ "lemmy_utils",
+ "lemmy_websocket",
+ "log",
+ "openssl",
+ "percent-encoding",
+ "rand 0.7.3",
+ "reqwest",
+ "serde 1.0.116",
+ "serde_json",
+ "sha2",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "tokio",
+ "url",
+ "uuid 0.8.1",
+]
+
 [[package]]
 name = "lemmy_db"
 version = "0.1.0"
@@ -1844,58 +1924,41 @@ dependencies = [
 name = "lemmy_server"
 version = "0.0.1"
 dependencies = [
- "activitystreams",
- "activitystreams-ext",
  "actix",
  "actix-files",
- "actix-rt",
  "actix-web",
  "actix-web-actors",
  "anyhow",
- "async-trait",
  "awc",
- "background-jobs",
- "base64 0.12.3",
- "bcrypt",
- "captcha",
  "cargo-husky",
  "chrono",
  "diesel",
  "diesel_migrations",
- "dotenv",
  "env_logger",
- "futures",
- "http",
  "http-signature-normalization-actix",
- "itertools",
- "jsonwebtoken",
  "lazy_static",
+ "lemmy_api",
+ "lemmy_apub",
  "lemmy_db",
  "lemmy_rate_limit",
  "lemmy_structs",
  "lemmy_utils",
+ "lemmy_websocket",
  "log",
  "openssl",
- "percent-encoding",
- "rand 0.7.3",
  "reqwest",
  "rss",
  "serde 1.0.116",
- "serde_json",
  "sha2",
  "strum",
- "strum_macros",
- "thiserror",
  "tokio",
  "url",
- "uuid 0.8.1",
 ]
 
 [[package]]
 name = "lemmy_structs"
 version = "0.1.0"
 dependencies = [
- "actix",
  "actix-web",
  "chrono",
  "diesel",
@@ -1903,8 +1966,7 @@ dependencies = [
  "lemmy_utils",
  "log",
  "serde 1.0.116",
- "strum",
- "strum_macros",
+ "serde_json",
 ]
 
 [[package]]
@@ -1924,12 +1986,36 @@ dependencies = [
  "openssl",
  "rand 0.7.3",
  "regex",
+ "reqwest",
  "serde 1.0.116",
  "serde_json",
  "thiserror",
  "url",
 ]
 
+[[package]]
+name = "lemmy_websocket"
+version = "0.1.0"
+dependencies = [
+ "actix",
+ "anyhow",
+ "background-jobs",
+ "chrono",
+ "diesel",
+ "lemmy_db",
+ "lemmy_rate_limit",
+ "lemmy_structs",
+ "lemmy_utils",
+ "log",
+ "rand 0.7.3",
+ "reqwest",
+ "serde 1.0.116",
+ "serde_json",
+ "strum",
+ "strum_macros",
+ "tokio",
+]
+
 [[package]]
 name = "lettre"
 version = "0.9.3"
index 2545e268e9d0853e5695921f4541c651cde756a0..d8980157e2e6da203c1337a3132a15aa5ca5efef 100644 (file)
@@ -8,56 +8,43 @@ lto = true
 
 [workspace]
 members = [
+    "lemmy_api",
+    "lemmy_apub",
     "lemmy_utils",
     "lemmy_db",
     "lemmy_structs",
     "lemmy_rate_limit",
+    "lemmy_websocket",
 ]
 
 [dependencies]
+lemmy_api = { path = "./lemmy_api" }
+lemmy_apub = { path = "./lemmy_apub" }
 lemmy_utils = { path = "./lemmy_utils" }
 lemmy_db = { path = "./lemmy_db" }
 lemmy_structs = { path = "./lemmy_structs" }
 lemmy_rate_limit = { path = "./lemmy_rate_limit" }
+lemmy_websocket = { path = "./lemmy_websocket" }
 diesel = "1.4"
 diesel_migrations = "1.4"
-dotenv = "0.15"
-activitystreams = "0.7.0-alpha.4"
-activitystreams-ext = "0.1.0-alpha.2"
-bcrypt = "0.8"
 chrono = { version = "0.4", features = ["serde"] }
-serde_json = { version = "1.0", features = ["preserve_order"]}
 serde = { version = "1.0", features = ["derive"] }
 actix = "0.10"
 actix-web = { version = "3.0", default-features = false, features = ["rustls"] }
 actix-files = { version = "0.3", default-features = false }
 actix-web-actors = { version = "3.0", default-features = false }
-actix-rt = { version = "1.1", default-features = false }
 awc = { version = "2.0", default-features = false }
 log = "0.4"
 env_logger = "0.7"
-rand = "0.7"
 strum = "0.19"
-strum_macros = "0.19"
-jsonwebtoken = "7.0"
 lazy_static = "1.3"
 rss = "1.9"
 url = { version = "2.1", features = ["serde"] }
-percent-encoding = "2.1"
 openssl = "0.10"
-http = "0.2"
 http-signature-normalization-actix = { version = "0.4", default-features = false, features = ["sha-2"] }
-base64 = "0.12"
 tokio = "0.2"
-futures = "0.3"
-itertools = "0.9"
-uuid = { version = "0.8", features = ["serde", "v4"] }
 sha2 = "0.9"
-async-trait = "0.1"
-captcha = "0.0"
 anyhow = "1.0"
-thiserror = "1.0"
-background-jobs = " 0.8"
 reqwest = { version = "0.10", features = ["json"] }
 
 [dev-dependencies.cargo-husky]
index 17e58fda4602fb528c776d52e8790cc7bcc49f5b..a4341f3d031bf1d9624f528b56272d462fdccaa4 100644 (file)
@@ -12,6 +12,9 @@ RUN mkdir -p lemmy_db/src/ \
       lemmy_utils/src/ \
       lemmy_structs/src/ \
       lemmy_rate_limit/src/ \
+      lemmy_api/src/ \
+      lemmy_apub/src/ \
+      lemmy_websocket/src/ \
       lemmy
 
 # Copy the cargo tomls
@@ -20,6 +23,9 @@ COPY lemmy_db/Cargo.toml ./lemmy_db/
 COPY lemmy_utils/Cargo.toml ./lemmy_utils/
 COPY lemmy_structs/Cargo.toml ./lemmy_structs/
 COPY lemmy_rate_limit/Cargo.toml ./lemmy_rate_limit/
+COPY lemmy_api/Cargo.toml ./lemmy_api/
+COPY lemmy_apub/Cargo.toml ./lemmy_apub/
+COPY lemmy_websocket/Cargo.toml ./lemmy_websocket/
 
 # Cache the deps
 RUN cargo build-deps
@@ -30,6 +36,9 @@ COPY lemmy_db/src ./lemmy_db/src/
 COPY lemmy_utils/src/ ./lemmy_utils/src/
 COPY lemmy_structs/src/ ./lemmy_structs/src/
 COPY lemmy_rate_limit/src/ ./lemmy_rate_limit/src/
+COPY lemmy_api/src/ ./lemmy_api/src/
+COPY lemmy_apub/src/ ./lemmy_apub/src/
+COPY lemmy_websocket/src/ ./lemmy_websocket/src/
 COPY migrations ./migrations/
 
 # Build for debug
index 20e910a429f0ad9dfbf56be2599be020e44bbb1e..137adc4626c3f5fb67456ed761fa759abe8a311e 100644 (file)
@@ -15,6 +15,9 @@ COPY lemmy_db ./lemmy_db
 COPY lemmy_utils ./lemmy_utils
 COPY lemmy_structs ./lemmy_structs
 COPY lemmy_rate_limit ./lemmy_rate_limit
+COPY lemmy_api ./lemmy_api
+COPY lemmy_apub ./lemmy_apub
+COPY lemmy_websocket ./lemmy_websocket
 RUN mkdir -p ./src/bin \
    && echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
 RUN cargo build --release
index 94287126c60b97da34e3a8e8d53e4e5377c511d1..7d84738b213de52ae21875779df8ec6201baf3c6 100755 (executable)
@@ -9,8 +9,8 @@ third_semver=$(echo $new_tag | cut -d "." -f 3)
 # Setting the version on the front end
 cd ../../
 # Setting the version on the backend
-echo "pub const VERSION: &str = \"$new_tag\";" > "src/version.rs"
-git add "src/version.rs"
+echo "pub const VERSION: &str = \"$new_tag\";" > "lemmy_api/src/version.rs"
+git add "lemmy_api/src/version.rs"
 # Setting the version for Ansible
 echo $new_tag > "ansible/VERSION"
 git add "ansible/VERSION"
diff --git a/lemmy_api/Cargo.toml b/lemmy_api/Cargo.toml
new file mode 100644 (file)
index 0000000..b302854
--- /dev/null
@@ -0,0 +1,49 @@
+[package]
+name = "lemmy_api"
+version = "0.1.0"
+authors = ["Felix Ableitner <me@nutomic.com>"]
+edition = "2018"
+
+[lib]
+name = "lemmy_api"
+path = "src/lib.rs"
+
+[dependencies]
+lemmy_apub = { path = "../lemmy_apub" }
+lemmy_utils = { path = "../lemmy_utils" }
+lemmy_db = { path = "../lemmy_db" }
+lemmy_structs = { path = "../lemmy_structs" }
+lemmy_rate_limit = { path = "../lemmy_rate_limit" }
+lemmy_websocket = { path = "../lemmy_websocket" }
+diesel = "1.4"
+bcrypt = "0.8"
+chrono = { version = "0.4", features = ["serde"] }
+serde_json = { version = "1.0", features = ["preserve_order"]}
+serde = { version = "1.0", features = ["derive"] }
+actix = "0.10"
+actix-web = { version = "3.0", default-features = false }
+actix-rt = { version = "1.1", default-features = false }
+awc = { version = "2.0", default-features = false }
+log = "0.4"
+rand = "0.7"
+strum = "0.19"
+strum_macros = "0.19"
+jsonwebtoken = "7.0"
+lazy_static = "1.3"
+url = { version = "2.1", features = ["serde"] }
+percent-encoding = "2.1"
+openssl = "0.10"
+http = "0.2"
+http-signature-normalization-actix = { version = "0.4", default-features = false, features = ["sha-2"] }
+base64 = "0.12"
+tokio = "0.2"
+futures = "0.3"
+itertools = "0.9"
+uuid = { version = "0.8", features = ["serde", "v4"] }
+sha2 = "0.9"
+async-trait = "0.1"
+captcha = "0.0"
+anyhow = "1.0"
+thiserror = "1.0"
+background-jobs = " 0.8"
+reqwest = { version = "0.10", features = ["json"] }
similarity index 100%
rename from src/api/claims.rs
rename to lemmy_api/src/claims.rs
similarity index 98%
rename from src/api/comment.rs
rename to lemmy_api/src/comment.rs
index 69853c3e7e1bc37e4533b4b391599e47240e543b..5a78ba91404b16f8c7c06ee4805be0cff4cde1f9 100644 (file)
@@ -1,16 +1,13 @@
 use crate::{
-  api::{
-    check_community_ban,
-    get_post,
-    get_user_from_jwt,
-    get_user_from_jwt_opt,
-    is_mod_or_admin,
-    Perform,
-  },
-  apub::{ApubLikeableType, ApubObjectType},
-  LemmyContext,
+  check_community_ban,
+  get_post,
+  get_user_from_jwt,
+  get_user_from_jwt_opt,
+  is_mod_or_admin,
+  Perform,
 };
 use actix_web::web::Data;
+use lemmy_apub::{ApubLikeableType, ApubObjectType};
 use lemmy_db::{
   comment::*,
   comment_view::*,
@@ -24,12 +21,7 @@ use lemmy_db::{
   Saveable,
   SortType,
 };
-use lemmy_structs::{
-  blocking,
-  comment::*,
-  send_local_notifs,
-  websocket::{SendComment, UserOperation},
-};
+use lemmy_structs::{blocking, comment::*, send_local_notifs};
 use lemmy_utils::{
   apub::{make_apub_endpoint, EndpointType},
   utils::{remove_slurs, scrape_text_for_mentions},
@@ -37,6 +29,7 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
+use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
 use std::str::FromStr;
 
 #[async_trait::async_trait(?Send)]
similarity index 98%
rename from src/api/community.rs
rename to lemmy_api/src/community.rs
index c5199fe54b72ce32c26c71a81d9a84fc87baf6f4..1d3e63a9c780232d6e50daaccdc819ae3f97173b 100644 (file)
@@ -1,10 +1,7 @@
-use crate::{
-  api::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, is_mod_or_admin, Perform},
-  apub::ActorType,
-  LemmyContext,
-};
+use crate::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, is_mod_or_admin, Perform};
 use actix_web::web::Data;
 use anyhow::Context;
+use lemmy_apub::ActorType;
 use lemmy_db::{
   comment::Comment,
   comment_view::CommentQueryBuilder,
@@ -22,16 +19,7 @@ use lemmy_db::{
   Joinable,
   SortType,
 };
-use lemmy_structs::{
-  blocking,
-  community::*,
-  websocket::{
-    GetCommunityUsersOnline,
-    JoinCommunityRoom,
-    SendCommunityRoomMessage,
-    UserOperation,
-  },
-};
+use lemmy_structs::{blocking, community::*};
 use lemmy_utils::{
   apub::{generate_actor_keypair, make_apub_endpoint, EndpointType},
   location_info,
@@ -40,6 +28,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
+use lemmy_websocket::{
+  messages::{GetCommunityUsersOnline, JoinCommunityRoom, SendCommunityRoomMessage},
+  LemmyContext,
+  UserOperation,
+};
 use std::str::FromStr;
 
 #[async_trait::async_trait(?Send)]
diff --git a/lemmy_api/src/lib.rs b/lemmy_api/src/lib.rs
new file mode 100644 (file)
index 0000000..905075b
--- /dev/null
@@ -0,0 +1,509 @@
+use crate::claims::Claims;
+use actix_web::{web, web::Data};
+use anyhow::anyhow;
+use lemmy_db::{
+  community::Community,
+  community_view::CommunityUserBanView,
+  post::Post,
+  user::User_,
+  Crud,
+  DbPool,
+};
+use lemmy_structs::{blocking, comment::*, community::*, post::*, site::*, user::*};
+use lemmy_utils::{
+  apub::get_apub_protocol_string,
+  request::{retry, RecvError},
+  settings::Settings,
+  APIError,
+  ConnectionId,
+  LemmyError,
+};
+use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
+use log::error;
+use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
+use reqwest::Client;
+use serde::Deserialize;
+use std::process::Command;
+
+pub mod claims;
+pub mod comment;
+pub mod community;
+pub mod post;
+pub mod site;
+pub mod user;
+pub mod version;
+
+#[async_trait::async_trait(?Send)]
+pub trait Perform {
+  type Response: serde::ser::Serialize + Send;
+
+  async fn perform(
+    &self,
+    context: &Data<LemmyContext>,
+    websocket_id: Option<ConnectionId>,
+  ) -> Result<Self::Response, LemmyError>;
+}
+
+pub(in crate) async fn is_mod_or_admin(
+  pool: &DbPool,
+  user_id: i32,
+  community_id: i32,
+) -> Result<(), LemmyError> {
+  let is_mod_or_admin = blocking(pool, move |conn| {
+    Community::is_mod_or_admin(conn, user_id, community_id)
+  })
+  .await?;
+  if !is_mod_or_admin {
+    return Err(APIError::err("not_a_mod_or_admin").into());
+  }
+  Ok(())
+}
+pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> {
+  let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+  if !user.admin {
+    return Err(APIError::err("not_an_admin").into());
+  }
+  Ok(())
+}
+
+pub(in crate) async fn get_post(post_id: i32, pool: &DbPool) -> Result<Post, LemmyError> {
+  match blocking(pool, move |conn| Post::read(conn, post_id)).await? {
+    Ok(post) => Ok(post),
+    Err(_e) => Err(APIError::err("couldnt_find_post").into()),
+  }
+}
+
+pub(in crate) async fn get_user_from_jwt(jwt: &str, pool: &DbPool) -> Result<User_, LemmyError> {
+  let claims = match Claims::decode(&jwt) {
+    Ok(claims) => claims.claims,
+    Err(_e) => return Err(APIError::err("not_logged_in").into()),
+  };
+  let user_id = claims.id;
+  let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+  // Check for a site ban
+  if user.banned {
+    return Err(APIError::err("site_ban").into());
+  }
+  Ok(user)
+}
+
+pub(in crate) async fn get_user_from_jwt_opt(
+  jwt: &Option<String>,
+  pool: &DbPool,
+) -> Result<Option<User_>, LemmyError> {
+  match jwt {
+    Some(jwt) => Ok(Some(get_user_from_jwt(jwt, pool).await?)),
+    None => Ok(None),
+  }
+}
+
+pub(in crate) async fn check_community_ban(
+  user_id: i32,
+  community_id: i32,
+  pool: &DbPool,
+) -> Result<(), LemmyError> {
+  let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
+  if blocking(pool, is_banned).await? {
+    Err(APIError::err("community_ban").into())
+  } else {
+    Ok(())
+  }
+}
+
+pub async fn match_websocket_operation(
+  context: LemmyContext,
+  id: ConnectionId,
+  op: UserOperation,
+  data: &str,
+) -> Result<String, LemmyError> {
+  match op {
+    // User ops
+    UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await,
+    UserOperation::Register => do_websocket_operation::<Register>(context, id, op, data).await,
+    UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await,
+    UserOperation::GetUserDetails => {
+      do_websocket_operation::<GetUserDetails>(context, id, op, data).await
+    }
+    UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
+    UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
+    UserOperation::BanUser => do_websocket_operation::<BanUser>(context, id, op, data).await,
+    UserOperation::GetUserMentions => {
+      do_websocket_operation::<GetUserMentions>(context, id, op, data).await
+    }
+    UserOperation::MarkUserMentionAsRead => {
+      do_websocket_operation::<MarkUserMentionAsRead>(context, id, op, data).await
+    }
+    UserOperation::MarkAllAsRead => {
+      do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await
+    }
+    UserOperation::DeleteAccount => {
+      do_websocket_operation::<DeleteAccount>(context, id, op, data).await
+    }
+    UserOperation::PasswordReset => {
+      do_websocket_operation::<PasswordReset>(context, id, op, data).await
+    }
+    UserOperation::PasswordChange => {
+      do_websocket_operation::<PasswordChange>(context, id, op, data).await
+    }
+    UserOperation::UserJoin => do_websocket_operation::<UserJoin>(context, id, op, data).await,
+    UserOperation::PostJoin => do_websocket_operation::<PostJoin>(context, id, op, data).await,
+    UserOperation::CommunityJoin => {
+      do_websocket_operation::<CommunityJoin>(context, id, op, data).await
+    }
+    UserOperation::SaveUserSettings => {
+      do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
+    }
+
+    // Private Message ops
+    UserOperation::CreatePrivateMessage => {
+      do_websocket_operation::<CreatePrivateMessage>(context, id, op, data).await
+    }
+    UserOperation::EditPrivateMessage => {
+      do_websocket_operation::<EditPrivateMessage>(context, id, op, data).await
+    }
+    UserOperation::DeletePrivateMessage => {
+      do_websocket_operation::<DeletePrivateMessage>(context, id, op, data).await
+    }
+    UserOperation::MarkPrivateMessageAsRead => {
+      do_websocket_operation::<MarkPrivateMessageAsRead>(context, id, op, data).await
+    }
+    UserOperation::GetPrivateMessages => {
+      do_websocket_operation::<GetPrivateMessages>(context, id, op, data).await
+    }
+
+    // Site ops
+    UserOperation::GetModlog => do_websocket_operation::<GetModlog>(context, id, op, data).await,
+    UserOperation::CreateSite => do_websocket_operation::<CreateSite>(context, id, op, data).await,
+    UserOperation::EditSite => do_websocket_operation::<EditSite>(context, id, op, data).await,
+    UserOperation::GetSite => do_websocket_operation::<GetSite>(context, id, op, data).await,
+    UserOperation::GetSiteConfig => {
+      do_websocket_operation::<GetSiteConfig>(context, id, op, data).await
+    }
+    UserOperation::SaveSiteConfig => {
+      do_websocket_operation::<SaveSiteConfig>(context, id, op, data).await
+    }
+    UserOperation::Search => do_websocket_operation::<Search>(context, id, op, data).await,
+    UserOperation::TransferCommunity => {
+      do_websocket_operation::<TransferCommunity>(context, id, op, data).await
+    }
+    UserOperation::TransferSite => {
+      do_websocket_operation::<TransferSite>(context, id, op, data).await
+    }
+    UserOperation::ListCategories => {
+      do_websocket_operation::<ListCategories>(context, id, op, data).await
+    }
+
+    // Community ops
+    UserOperation::GetCommunity => {
+      do_websocket_operation::<GetCommunity>(context, id, op, data).await
+    }
+    UserOperation::ListCommunities => {
+      do_websocket_operation::<ListCommunities>(context, id, op, data).await
+    }
+    UserOperation::CreateCommunity => {
+      do_websocket_operation::<CreateCommunity>(context, id, op, data).await
+    }
+    UserOperation::EditCommunity => {
+      do_websocket_operation::<EditCommunity>(context, id, op, data).await
+    }
+    UserOperation::DeleteCommunity => {
+      do_websocket_operation::<DeleteCommunity>(context, id, op, data).await
+    }
+    UserOperation::RemoveCommunity => {
+      do_websocket_operation::<RemoveCommunity>(context, id, op, data).await
+    }
+    UserOperation::FollowCommunity => {
+      do_websocket_operation::<FollowCommunity>(context, id, op, data).await
+    }
+    UserOperation::GetFollowedCommunities => {
+      do_websocket_operation::<GetFollowedCommunities>(context, id, op, data).await
+    }
+    UserOperation::BanFromCommunity => {
+      do_websocket_operation::<BanFromCommunity>(context, id, op, data).await
+    }
+    UserOperation::AddModToCommunity => {
+      do_websocket_operation::<AddModToCommunity>(context, id, op, data).await
+    }
+
+    // Post ops
+    UserOperation::CreatePost => do_websocket_operation::<CreatePost>(context, id, op, data).await,
+    UserOperation::GetPost => do_websocket_operation::<GetPost>(context, id, op, data).await,
+    UserOperation::GetPosts => do_websocket_operation::<GetPosts>(context, id, op, data).await,
+    UserOperation::EditPost => do_websocket_operation::<EditPost>(context, id, op, data).await,
+    UserOperation::DeletePost => do_websocket_operation::<DeletePost>(context, id, op, data).await,
+    UserOperation::RemovePost => do_websocket_operation::<RemovePost>(context, id, op, data).await,
+    UserOperation::LockPost => do_websocket_operation::<LockPost>(context, id, op, data).await,
+    UserOperation::StickyPost => do_websocket_operation::<StickyPost>(context, id, op, data).await,
+    UserOperation::CreatePostLike => {
+      do_websocket_operation::<CreatePostLike>(context, id, op, data).await
+    }
+    UserOperation::SavePost => do_websocket_operation::<SavePost>(context, id, op, data).await,
+
+    // Comment ops
+    UserOperation::CreateComment => {
+      do_websocket_operation::<CreateComment>(context, id, op, data).await
+    }
+    UserOperation::EditComment => {
+      do_websocket_operation::<EditComment>(context, id, op, data).await
+    }
+    UserOperation::DeleteComment => {
+      do_websocket_operation::<DeleteComment>(context, id, op, data).await
+    }
+    UserOperation::RemoveComment => {
+      do_websocket_operation::<RemoveComment>(context, id, op, data).await
+    }
+    UserOperation::MarkCommentAsRead => {
+      do_websocket_operation::<MarkCommentAsRead>(context, id, op, data).await
+    }
+    UserOperation::SaveComment => {
+      do_websocket_operation::<SaveComment>(context, id, op, data).await
+    }
+    UserOperation::GetComments => {
+      do_websocket_operation::<GetComments>(context, id, op, data).await
+    }
+    UserOperation::CreateCommentLike => {
+      do_websocket_operation::<CreateCommentLike>(context, id, op, data).await
+    }
+  }
+}
+
+async fn do_websocket_operation<'a, 'b, Data>(
+  context: LemmyContext,
+  id: ConnectionId,
+  op: UserOperation,
+  data: &str,
+) -> Result<String, LemmyError>
+where
+  for<'de> Data: Deserialize<'de> + 'a,
+  Data: Perform,
+{
+  let parsed_data: Data = serde_json::from_str(&data)?;
+  let res = parsed_data
+    .perform(&web::Data::new(context), Some(id))
+    .await?;
+  serialize_websocket_message(&op, &res)
+}
+
+pub(crate) fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyError> {
+  let mut built_text = String::new();
+
+  // Building proper speech text for espeak
+  for mut c in captcha.chars() {
+    let new_str = if c.is_alphabetic() {
+      if c.is_lowercase() {
+        c.make_ascii_uppercase();
+        format!("lower case {} ... ", c)
+      } else {
+        c.make_ascii_uppercase();
+        format!("capital {} ... ", c)
+      }
+    } else {
+      format!("{} ...", c)
+    };
+
+    built_text.push_str(&new_str);
+  }
+
+  espeak_wav_base64(&built_text)
+}
+
+pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
+  // Make a temp file path
+  let uuid = uuid::Uuid::new_v4().to_string();
+  let file_path = format!("/tmp/lemmy_espeak_{}.wav", &uuid);
+
+  // Write the wav file
+  Command::new("espeak")
+    .arg("-w")
+    .arg(&file_path)
+    .arg(text)
+    .status()?;
+
+  // Read the wav file bytes
+  let bytes = std::fs::read(&file_path)?;
+
+  // Delete the file
+  std::fs::remove_file(file_path)?;
+
+  // Convert to base64
+  let base64 = base64::encode(bytes);
+
+  Ok(base64)
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct IframelyResponse {
+  title: Option<String>,
+  description: Option<String>,
+  thumbnail_url: Option<String>,
+  html: Option<String>,
+}
+
+pub(crate) async fn fetch_iframely(
+  client: &Client,
+  url: &str,
+) -> Result<IframelyResponse, LemmyError> {
+  let fetch_url = format!("http://iframely/oembed?url={}", url);
+
+  let response = retry(|| client.get(&fetch_url).send()).await?;
+
+  let res: IframelyResponse = response
+    .json()
+    .await
+    .map_err(|e| RecvError(e.to_string()))?;
+  Ok(res)
+}
+
+#[derive(Deserialize, Debug, Clone)]
+pub(crate) struct PictrsResponse {
+  files: Vec<PictrsFile>,
+  msg: String,
+}
+
+#[derive(Deserialize, Debug, Clone)]
+pub(crate) struct PictrsFile {
+  file: String,
+  delete_token: String,
+}
+
+pub(crate) async fn fetch_pictrs(
+  client: &Client,
+  image_url: &str,
+) -> Result<PictrsResponse, LemmyError> {
+  is_image_content_type(client, image_url).await?;
+
+  let fetch_url = format!(
+    "http://pictrs:8080/image/download?url={}",
+    utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed
+  );
+
+  let response = retry(|| client.get(&fetch_url).send()).await?;
+
+  let response: PictrsResponse = response
+    .json()
+    .await
+    .map_err(|e| RecvError(e.to_string()))?;
+
+  if response.msg == "ok" {
+    Ok(response)
+  } else {
+    Err(anyhow!("{}", &response.msg).into())
+  }
+}
+
+async fn fetch_iframely_and_pictrs_data(
+  client: &Client,
+  url: Option<String>,
+) -> (
+  Option<String>,
+  Option<String>,
+  Option<String>,
+  Option<String>,
+) {
+  match &url {
+    Some(url) => {
+      // Fetch iframely data
+      let (iframely_title, iframely_description, iframely_thumbnail_url, iframely_html) =
+        match fetch_iframely(client, url).await {
+          Ok(res) => (res.title, res.description, res.thumbnail_url, res.html),
+          Err(e) => {
+            error!("iframely err: {}", e);
+            (None, None, None, None)
+          }
+        };
+
+      // Fetch pictrs thumbnail
+      let pictrs_hash = match iframely_thumbnail_url {
+        Some(iframely_thumbnail_url) => match fetch_pictrs(client, &iframely_thumbnail_url).await {
+          Ok(res) => Some(res.files[0].file.to_owned()),
+          Err(e) => {
+            error!("pictrs err: {}", e);
+            None
+          }
+        },
+        // Try to generate a small thumbnail if iframely is not supported
+        None => match fetch_pictrs(client, &url).await {
+          Ok(res) => Some(res.files[0].file.to_owned()),
+          Err(e) => {
+            error!("pictrs err: {}", e);
+            None
+          }
+        },
+      };
+
+      // The full urls are necessary for federation
+      let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
+        Some(format!(
+          "{}://{}/pictrs/image/{}",
+          get_apub_protocol_string(),
+          Settings::get().hostname,
+          pictrs_hash
+        ))
+      } else {
+        None
+      };
+
+      (
+        iframely_title,
+        iframely_description,
+        iframely_html,
+        pictrs_thumbnail,
+      )
+    }
+    None => (None, None, None, None),
+  }
+}
+
+pub(crate) async fn is_image_content_type(client: &Client, test: &str) -> Result<(), LemmyError> {
+  let response = retry(|| client.get(test).send()).await?;
+
+  if response
+    .headers()
+    .get("Content-Type")
+    .ok_or_else(|| anyhow!("No Content-Type header"))?
+    .to_str()?
+    .starts_with("image/")
+  {
+    Ok(())
+  } else {
+    Err(anyhow!("Not an image type.").into())
+  }
+}
+
+#[cfg(test)]
+mod tests {
+  use crate::{captcha_espeak_wav_base64, is_image_content_type};
+
+  #[test]
+  fn test_image() {
+    actix_rt::System::new("tset_image").block_on(async move {
+      let client = reqwest::Client::default();
+      assert!(is_image_content_type(&client, "https://1734811051.rsc.cdn77.org/data/images/full/365645/as-virus-kills-navajos-in-their-homes-tribal-women-provide-lifeline.jpg?w=600?w=650").await.is_ok());
+      assert!(is_image_content_type(&client,
+                                    "https://twitter.com/BenjaminNorton/status/1259922424272957440?s=20"
+      )
+        .await.is_err()
+      );
+    });
+  }
+
+  #[test]
+  fn test_espeak() {
+    assert!(captcha_espeak_wav_base64("WxRt2l").is_ok())
+  }
+
+  // These helped with testing
+  // #[test]
+  // fn test_iframely() {
+  //   let res = fetch_iframely(client, "https://www.redspark.nu/?p=15341").await;
+  //   assert!(res.is_ok());
+  // }
+
+  // #[test]
+  // fn test_pictshare() {
+  //   let res = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpg");
+  //   assert!(res.is_ok());
+  //   let res_other = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpgaoeu");
+  //   assert!(res_other.is_err());
+  // }
+}
similarity index 98%
rename from src/api/post.rs
rename to lemmy_api/src/post.rs
index ef5409d1f604cf2fa903915f17f956f309c62834..e8fb9d984216b85d4c5a3926b0fb47ef0bd23ae3 100644 (file)
@@ -1,10 +1,13 @@
 use crate::{
-  api::{check_community_ban, get_user_from_jwt, get_user_from_jwt_opt, is_mod_or_admin, Perform},
-  apub::{ApubLikeableType, ApubObjectType},
+  check_community_ban,
   fetch_iframely_and_pictrs_data,
-  LemmyContext,
+  get_user_from_jwt,
+  get_user_from_jwt_opt,
+  is_mod_or_admin,
+  Perform,
 };
 use actix_web::web::Data;
+use lemmy_apub::{ApubLikeableType, ApubObjectType};
 use lemmy_db::{
   comment_view::*,
   community_view::*,
@@ -19,11 +22,7 @@ use lemmy_db::{
   Saveable,
   SortType,
 };
-use lemmy_structs::{
-  blocking,
-  post::*,
-  websocket::{GetPostUsersOnline, JoinPostRoom, SendPost, UserOperation},
-};
+use lemmy_structs::{blocking, post::*};
 use lemmy_utils::{
   apub::{make_apub_endpoint, EndpointType},
   utils::{check_slurs, check_slurs_opt, is_valid_post_title},
@@ -31,6 +30,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
+use lemmy_websocket::{
+  messages::{GetPostUsersOnline, JoinPostRoom, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 use std::str::FromStr;
 use url::Url;
 
similarity index 98%
rename from src/api/site.rs
rename to lemmy_api/src/site.rs
index 3ff1e49d0c3437436ec456edd637bccbce768d04..9db838ff106487ee98946c8e8afccf799ededbd5 100644 (file)
@@ -1,11 +1,7 @@
-use crate::{
-  api::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, Perform},
-  apub::fetcher::search_by_apub_id,
-  version,
-  LemmyContext,
-};
+use crate::{get_user_from_jwt, get_user_from_jwt_opt, is_admin, version, Perform};
 use actix_web::web::Data;
 use anyhow::Context;
+use lemmy_apub::fetcher::search_by_apub_id;
 use lemmy_db::{
   category::*,
   comment_view::*,
@@ -22,12 +18,7 @@ use lemmy_db::{
   SearchType,
   SortType,
 };
-use lemmy_structs::{
-  blocking,
-  site::*,
-  user::Register,
-  websocket::{GetUsersOnline, SendAllMessage, UserOperation},
-};
+use lemmy_structs::{blocking, site::*, user::Register};
 use lemmy_utils::{
   location_info,
   settings::Settings,
@@ -36,6 +27,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
+use lemmy_websocket::{
+  messages::{GetUsersOnline, SendAllMessage},
+  LemmyContext,
+  UserOperation,
+};
 use log::{debug, info};
 use std::str::FromStr;
 
similarity index 99%
rename from src/api/user.rs
rename to lemmy_api/src/user.rs
index 977250d34fdf2db8ff0847c7002b1601569dbb91..e2b73c53ed327ba9f8e48c72675dcfef1b26ea3e 100644 (file)
@@ -1,14 +1,17 @@
 use crate::{
-  api::{claims::Claims, get_user_from_jwt, get_user_from_jwt_opt, is_admin, Perform},
-  apub::ApubObjectType,
   captcha_espeak_wav_base64,
-  LemmyContext,
+  claims::Claims,
+  get_user_from_jwt,
+  get_user_from_jwt_opt,
+  is_admin,
+  Perform,
 };
 use actix_web::web::Data;
 use anyhow::Context;
 use bcrypt::verify;
 use captcha::{gen, Difficulty};
 use chrono::Duration;
+use lemmy_apub::ApubObjectType;
 use lemmy_db::{
   comment::*,
   comment_view::*,
@@ -34,18 +37,7 @@ use lemmy_db::{
   ListingType,
   SortType,
 };
-use lemmy_structs::{
-  blocking,
-  user::*,
-  websocket::{
-    CaptchaItem,
-    CheckCaptcha,
-    JoinUserRoom,
-    SendAllMessage,
-    SendUserRoomMessage,
-    UserOperation,
-  },
-};
+use lemmy_structs::{blocking, user::*};
 use lemmy_utils::{
   apub::{generate_actor_keypair, make_apub_endpoint, EndpointType},
   email::send_email,
@@ -63,6 +55,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
+use lemmy_websocket::{
+  messages::{CaptchaItem, CheckCaptcha, JoinUserRoom, SendAllMessage, SendUserRoomMessage},
+  LemmyContext,
+  UserOperation,
+};
 use log::error;
 use std::str::FromStr;
 
similarity index 100%
rename from src/version.rs
rename to lemmy_api/src/version.rs
diff --git a/lemmy_apub/Cargo.toml b/lemmy_apub/Cargo.toml
new file mode 100644 (file)
index 0000000..66dbbe4
--- /dev/null
@@ -0,0 +1,47 @@
+[package]
+name = "lemmy_apub"
+version = "0.1.0"
+authors = ["Felix Ableitner <me@nutomic.com>"]
+edition = "2018"
+
+[lib]
+name = "lemmy_apub"
+path = "src/lib.rs"
+
+[dependencies]
+lemmy_utils = { path = "../lemmy_utils" }
+lemmy_db = { path = "../lemmy_db" }
+lemmy_structs = { path = "../lemmy_structs" }
+lemmy_websocket = { path = "../lemmy_websocket" }
+diesel = "1.4"
+activitystreams = "0.7.0-alpha.4"
+activitystreams-ext = "0.1.0-alpha.2"
+bcrypt = "0.8"
+chrono = { version = "0.4", features = ["serde"] }
+serde_json = { version = "1.0", features = ["preserve_order"]}
+serde = { version = "1.0", features = ["derive"] }
+actix = "0.10"
+actix-web = { version = "3.0", default-features = false }
+actix-rt = { version = "1.1", default-features = false }
+awc = { version = "2.0", default-features = false }
+log = "0.4"
+rand = "0.7"
+strum = "0.19"
+strum_macros = "0.19"
+lazy_static = "1.3"
+url = { version = "2.1", features = ["serde"] }
+percent-encoding = "2.1"
+openssl = "0.10"
+http = "0.2"
+http-signature-normalization-actix = { version = "0.4", default-features = false, features = ["sha-2"] }
+base64 = "0.12"
+tokio = "0.2"
+futures = "0.3"
+itertools = "0.9"
+uuid = { version = "0.8", features = ["serde", "v4"] }
+sha2 = "0.9"
+async-trait = "0.1"
+anyhow = "1.0"
+thiserror = "1.0"
+background-jobs = " 0.8"
+reqwest = { version = "0.10", features = ["json"] }
\ No newline at end of file
similarity index 87%
rename from src/apub/activities.rs
rename to lemmy_apub/src/activities.rs
index dc18926937c33443156cb8d4e2e8399570b9e9fe..3b1b12ab3592c6c36cb47b5ea72ea76727359085 100644 (file)
@@ -1,13 +1,11 @@
-use crate::{
-  apub::{activity_queue::send_activity, community::do_announce, insert_activity},
-  LemmyContext,
-};
+use crate::{activity_queue::send_activity, community::do_announce, insert_activity};
 use activitystreams::{
   base::{Extends, ExtendsExt},
   object::AsObject,
 };
 use lemmy_db::{community::Community, user::User_};
 use lemmy_utils::{apub::get_apub_protocol_string, settings::Settings, LemmyError};
+use lemmy_websocket::LemmyContext;
 use serde::{export::fmt::Debug, Serialize};
 use url::{ParseError, Url};
 use uuid::Uuid;
@@ -37,7 +35,7 @@ where
   Ok(())
 }
 
-pub(in crate::apub) fn generate_activity_id<T>(kind: T) -> Result<Url, ParseError>
+pub(in crate) fn generate_activity_id<T>(kind: T) -> Result<Url, ParseError>
 where
   T: ToString,
 {
similarity index 97%
rename from src/apub/activity_queue.rs
rename to lemmy_apub/src/activity_queue.rs
index a48cf5bd2184abc2dc4a7695b6913fee4cc3a6fb..80c92c2f993de1e26adfa46da0ef3bfbef71efae 100644 (file)
@@ -1,4 +1,4 @@
-use crate::apub::{check_is_apub_id_valid, extensions::signatures::sign, ActorType};
+use crate::{check_is_apub_id_valid, extensions::signatures::sign, ActorType};
 use activitystreams::{
   base::{Extends, ExtendsExt},
   object::AsObject,
similarity index 97%
rename from src/apub/comment.rs
rename to lemmy_apub/src/comment.rs
index fc19ec334d697087ad677168fb88b9e0acabf9b4..4e5c173f892c8b3d4df55e1f9ba25c5f4881a574 100644 (file)
@@ -1,24 +1,20 @@
 use crate::{
-  apub::{
-    activities::{generate_activity_id, send_activity_to_community},
-    check_actor_domain,
-    create_apub_response,
-    create_apub_tombstone_response,
-    create_tombstone,
-    fetch_webfinger_url,
-    fetcher::{
-      get_or_fetch_and_insert_comment,
-      get_or_fetch_and_insert_post,
-      get_or_fetch_and_upsert_user,
-    },
-    ActorType,
-    ApubLikeableType,
-    ApubObjectType,
-    FromApub,
-    ToApub,
+  activities::{generate_activity_id, send_activity_to_community},
+  check_actor_domain,
+  create_apub_response,
+  create_apub_tombstone_response,
+  create_tombstone,
+  fetch_webfinger_url,
+  fetcher::{
+    get_or_fetch_and_insert_comment,
+    get_or_fetch_and_insert_post,
+    get_or_fetch_and_upsert_user,
   },
-  DbPool,
-  LemmyContext,
+  ActorType,
+  ApubLikeableType,
+  ApubObjectType,
+  FromApub,
+  ToApub,
 };
 use activitystreams::{
   activity::{
@@ -46,6 +42,7 @@ use lemmy_db::{
   post::Post,
   user::User_,
   Crud,
+  DbPool,
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{
@@ -53,6 +50,7 @@ use lemmy_utils::{
   utils::{convert_datetime, remove_slurs, scrape_text_for_mentions, MentionData},
   LemmyError,
 };
+use lemmy_websocket::LemmyContext;
 use log::debug;
 use serde::Deserialize;
 use serde_json::Error;
similarity index 97%
rename from src/apub/community.rs
rename to lemmy_apub/src/community.rs
index 54b2957ed1138281729643a37e0ffb5702131cad..8a41e88665e9dc9caf73ff442f9cadfe7a6509d1 100644 (file)
@@ -1,21 +1,17 @@
 use crate::{
-  apub::{
-    activities::generate_activity_id,
-    activity_queue::send_activity,
-    check_actor_domain,
-    create_apub_response,
-    create_apub_tombstone_response,
-    create_tombstone,
-    extensions::group_extensions::GroupExtension,
-    fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_user},
-    insert_activity,
-    ActorType,
-    FromApub,
-    GroupExt,
-    ToApub,
-  },
-  DbPool,
-  LemmyContext,
+  activities::generate_activity_id,
+  activity_queue::send_activity,
+  check_actor_domain,
+  create_apub_response,
+  create_apub_tombstone_response,
+  create_tombstone,
+  extensions::group_extensions::GroupExtension,
+  fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_user},
+  insert_activity,
+  ActorType,
+  FromApub,
+  GroupExt,
+  ToApub,
 };
 use activitystreams::{
   activity::{
@@ -44,6 +40,7 @@ use lemmy_db::{
   naive_now,
   post::Post,
   user::User_,
+  DbPool,
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{
@@ -52,6 +49,7 @@ use lemmy_utils::{
   utils::{check_slurs, check_slurs_opt, convert_datetime},
   LemmyError,
 };
+use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
 
similarity index 99%
rename from src/apub/extensions/signatures.rs
rename to lemmy_apub/src/extensions/signatures.rs
index 4a261c17e1335cbea63659e0d8f8ce5de7d982c7..5471e19e4a75490baac89f9d94e4d6c2d5b7f151 100644 (file)
@@ -1,4 +1,4 @@
-use crate::apub::ActorType;
+use crate::ActorType;
 use activitystreams::unparsed::UnparsedMutExt;
 use activitystreams_ext::UnparsedExtension;
 use actix_web::{client::ClientRequest, HttpRequest};
similarity index 98%
rename from src/apub/fetcher.rs
rename to lemmy_apub/src/fetcher.rs
index 5d772f062b66c271ce53b282d8b30d86c2911c9c..4ce4082cdcd4cf6c5bba57b5b919be8e506b77d4 100644 (file)
@@ -1,15 +1,11 @@
 use crate::{
-  apub::{
-    check_is_apub_id_valid,
-    ActorType,
-    FromApub,
-    GroupExt,
-    PageExt,
-    PersonExt,
-    APUB_JSON_CONTENT_TYPE,
-  },
-  request::{retry, RecvError},
-  LemmyContext,
+  check_is_apub_id_valid,
+  ActorType,
+  FromApub,
+  GroupExt,
+  PageExt,
+  PersonExt,
+  APUB_JSON_CONTENT_TYPE,
 };
 use activitystreams::{base::BaseExt, collection::OrderedCollection, object::Note, prelude::*};
 use anyhow::{anyhow, Context};
@@ -30,7 +26,13 @@ use lemmy_db::{
   SearchType,
 };
 use lemmy_structs::{blocking, site::SearchResponse};
-use lemmy_utils::{apub::get_apub_protocol_string, location_info, LemmyError};
+use lemmy_utils::{
+  apub::get_apub_protocol_string,
+  location_info,
+  request::{retry, RecvError},
+  LemmyError,
+};
+use lemmy_websocket::LemmyContext;
 use log::debug;
 use reqwest::Client;
 use serde::Deserialize;
similarity index 77%
rename from src/apub/inbox/activities/announce.rs
rename to lemmy_apub/src/inbox/activities/announce.rs
index 47607a05de078b71552c832122fc6474a2d90be9..d861e5f27231ca602fbf796e440612c78030abd3 100644 (file)
@@ -1,17 +1,14 @@
-use crate::{
-  apub::inbox::{
-    activities::{
-      create::receive_create,
-      delete::receive_delete,
-      dislike::receive_dislike,
-      like::receive_like,
-      remove::receive_remove,
-      undo::receive_undo,
-      update::receive_update,
-    },
-    shared_inbox::{get_community_id_from_activity, receive_unhandled_activity},
+use crate::inbox::{
+  activities::{
+    create::receive_create,
+    delete::receive_delete,
+    dislike::receive_dislike,
+    like::receive_like,
+    remove::receive_remove,
+    undo::receive_undo,
+    update::receive_update,
   },
-  LemmyContext,
+  shared_inbox::{get_community_id_from_activity, receive_unhandled_activity},
 };
 use activitystreams::{
   activity::*,
@@ -21,6 +18,7 @@ use activitystreams::{
 use actix_web::HttpResponse;
 use anyhow::Context;
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::LemmyContext;
 
 pub async fn receive_announce(
   activity: AnyBase,
similarity index 91%
rename from src/apub/inbox/activities/create.rs
rename to lemmy_apub/src/inbox/activities/create.rs
index 961991a651de9781a46b303219b41342f4cb364a..e25fdd979a28e8fbf00d8463251359df4aa7caee 100644 (file)
@@ -1,15 +1,12 @@
 use crate::{
-  apub::{
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    ActorType,
-    FromApub,
-    PageExt,
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  ActorType,
+  FromApub,
+  PageExt,
 };
 use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -20,14 +17,13 @@ use lemmy_db::{
   post::{Post, PostForm},
   post_view::PostView,
 };
-use lemmy_structs::{
-  blocking,
-  comment::CommentResponse,
-  post::PostResponse,
-  send_local_notifs,
-  websocket::{SendComment, SendPost, UserOperation},
-};
+use lemmy_structs::{blocking, comment::CommentResponse, post::PostResponse, send_local_notifs};
 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_create(
   activity: AnyBase,
similarity index 94%
rename from src/apub/inbox/activities/delete.rs
rename to lemmy_apub/src/inbox/activities/delete.rs
index 131588bace0d7ef2255d76300313b30aedad741a..2c3760e4280c8764c1f53869dfb80eb82024e688 100644 (file)
@@ -1,17 +1,14 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    ActorType,
-    FromApub,
-    GroupExt,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  ActorType,
+  FromApub,
+  GroupExt,
+  PageExt,
 };
 use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -31,9 +28,13 @@ use lemmy_structs::{
   comment::CommentResponse,
   community::CommunityResponse,
   post::PostResponse,
-  websocket::{SendComment, SendCommunityRoomMessage, SendPost, UserOperation},
 };
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendCommunityRoomMessage, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_delete(
   activity: AnyBase,
similarity index 89%
rename from src/apub/inbox/activities/dislike.rs
rename to lemmy_apub/src/inbox/activities/dislike.rs
index df9bd848663c9c81aca2f365b76193e9d148a1f4..dd63011d4df8383de82a0a67ea51412fe42cd2f2 100644 (file)
@@ -1,15 +1,12 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    FromApub,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  FromApub,
+  PageExt,
 };
 use activitystreams::{activity::Dislike, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -21,13 +18,13 @@ use lemmy_db::{
   post_view::PostView,
   Likeable,
 };
-use lemmy_structs::{
-  blocking,
-  comment::CommentResponse,
-  post::PostResponse,
-  websocket::{SendComment, SendPost, UserOperation},
-};
+use lemmy_structs::{blocking, comment::CommentResponse, post::PostResponse};
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_dislike(
   activity: AnyBase,
similarity index 89%
rename from src/apub/inbox/activities/like.rs
rename to lemmy_apub/src/inbox/activities/like.rs
index ce067c87990ae0271119abe923f6c3f544b47146..7b56867b4f0aa707c8f3cfda00d3a0e223feb911 100644 (file)
@@ -1,15 +1,12 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    FromApub,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  FromApub,
+  PageExt,
 };
 use activitystreams::{activity::Like, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -21,13 +18,13 @@ use lemmy_db::{
   post_view::PostView,
   Likeable,
 };
-use lemmy_structs::{
-  blocking,
-  comment::CommentResponse,
-  post::PostResponse,
-  websocket::{SendComment, SendPost, UserOperation},
-};
+use lemmy_structs::{blocking, comment::CommentResponse, post::PostResponse};
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_like(
   activity: AnyBase,
similarity index 94%
rename from src/apub/inbox/activities/remove.rs
rename to lemmy_apub/src/inbox/activities/remove.rs
index e91a65c038a84557c1b69847cf39ec5694d63cad..27a7775e6485bea5a851e69921450857f4c76e3c 100644 (file)
@@ -1,18 +1,15 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_community_id_from_activity,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    ActorType,
-    FromApub,
-    GroupExt,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_community_id_from_activity,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  ActorType,
+  FromApub,
+  GroupExt,
+  PageExt,
 };
 use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -32,9 +29,13 @@ use lemmy_structs::{
   comment::CommentResponse,
   community::CommunityResponse,
   post::PostResponse,
-  websocket::{SendComment, SendCommunityRoomMessage, SendPost, UserOperation},
 };
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendCommunityRoomMessage, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_remove(
   activity: AnyBase,
similarity index 98%
rename from src/apub/inbox/activities/undo.rs
rename to lemmy_apub/src/inbox/activities/undo.rs
index c8b4d35bf4bfd6a72fa9a0a9df27c46055325383..9a421ee69fade0ecba1b40025ac945deea24547e 100644 (file)
@@ -1,17 +1,14 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    ActorType,
-    FromApub,
-    GroupExt,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  ActorType,
+  FromApub,
+  GroupExt,
+  PageExt,
 };
 use activitystreams::{
   activity::*,
@@ -37,9 +34,13 @@ use lemmy_structs::{
   comment::CommentResponse,
   community::CommunityResponse,
   post::PostResponse,
-  websocket::{SendComment, SendCommunityRoomMessage, SendPost, UserOperation},
 };
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendCommunityRoomMessage, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_undo(
   activity: AnyBase,
similarity index 89%
rename from src/apub/inbox/activities/update.rs
rename to lemmy_apub/src/inbox/activities/update.rs
index ccf7534bcc481905553d2969b5ae687186fa925b..17d9d7084f7c14eb59053a2f5e1563dcbaf9c73a 100644 (file)
@@ -1,16 +1,13 @@
 use crate::{
-  apub::{
-    fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
-    inbox::shared_inbox::{
-      announce_if_community_is_local,
-      get_user_from_activity,
-      receive_unhandled_activity,
-    },
-    ActorType,
-    FromApub,
-    PageExt,
+  fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
+  inbox::shared_inbox::{
+    announce_if_community_is_local,
+    get_user_from_activity,
+    receive_unhandled_activity,
   },
-  LemmyContext,
+  ActorType,
+  FromApub,
+  PageExt,
 };
 use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*};
 use actix_web::HttpResponse;
@@ -22,14 +19,13 @@ use lemmy_db::{
   post_view::PostView,
   Crud,
 };
-use lemmy_structs::{
-  blocking,
-  comment::CommentResponse,
-  post::PostResponse,
-  send_local_notifs,
-  websocket::{SendComment, SendPost, UserOperation},
-};
+use lemmy_structs::{blocking, comment::CommentResponse, post::PostResponse, send_local_notifs};
 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
+use lemmy_websocket::{
+  messages::{SendComment, SendPost},
+  LemmyContext,
+  UserOperation,
+};
 
 pub async fn receive_update(
   activity: AnyBase,
similarity index 95%
rename from src/apub/inbox/community_inbox.rs
rename to lemmy_apub/src/inbox/community_inbox.rs
index 9dd010c3f09896e8286ff1b998b281ab0f5fa788..ee75fa005fa758cf75e3ed1e7f1a56dad2373054 100644 (file)
@@ -1,12 +1,9 @@
 use crate::{
-  apub::{
-    check_is_apub_id_valid,
-    extensions::signatures::verify,
-    fetcher::get_or_fetch_and_upsert_user,
-    insert_activity,
-    ActorType,
-  },
-  LemmyContext,
+  check_is_apub_id_valid,
+  extensions::signatures::verify,
+  fetcher::get_or_fetch_and_upsert_user,
+  insert_activity,
+  ActorType,
 };
 use activitystreams::{
   activity::{ActorAndObject, Follow, Undo},
@@ -22,6 +19,7 @@ use lemmy_db::{
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::LemmyContext;
 use log::debug;
 use serde::{Deserialize, Serialize};
 use std::fmt::Debug;
similarity index 83%
rename from src/apub/inbox/shared_inbox.rs
rename to lemmy_apub/src/inbox/shared_inbox.rs
index da79510823174c8b1b433e527d2b853a5b129267..b9077ebe9e688f785a6c931c902d2b3a59e56dba 100644 (file)
@@ -1,26 +1,23 @@
 use crate::{
-  apub::{
-    check_is_apub_id_valid,
-    community::do_announce,
-    extensions::signatures::verify,
-    fetcher::{
-      get_or_fetch_and_upsert_actor,
-      get_or_fetch_and_upsert_community,
-      get_or_fetch_and_upsert_user,
-    },
-    inbox::activities::{
-      announce::receive_announce,
-      create::receive_create,
-      delete::receive_delete,
-      dislike::receive_dislike,
-      like::receive_like,
-      remove::receive_remove,
-      undo::receive_undo,
-      update::receive_update,
-    },
-    insert_activity,
+  check_is_apub_id_valid,
+  community::do_announce,
+  extensions::signatures::verify,
+  fetcher::{
+    get_or_fetch_and_upsert_actor,
+    get_or_fetch_and_upsert_community,
+    get_or_fetch_and_upsert_user,
   },
-  LemmyContext,
+  inbox::activities::{
+    announce::receive_announce,
+    create::receive_create,
+    delete::receive_delete,
+    dislike::receive_dislike,
+    like::receive_like,
+    remove::receive_remove,
+    undo::receive_undo,
+    update::receive_update,
+  },
+  insert_activity,
 };
 use activitystreams::{
   activity::{ActorAndObject, ActorAndObjectRef},
@@ -32,6 +29,7 @@ use actix_web::{web, HttpRequest, HttpResponse};
 use anyhow::Context;
 use lemmy_db::user::User_;
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::LemmyContext;
 use log::debug;
 use serde::{Deserialize, Serialize};
 use std::fmt::Debug;
@@ -97,7 +95,7 @@ pub async fn shared_inbox(
   res
 }
 
-pub(in crate::apub::inbox) fn receive_unhandled_activity<A>(
+pub(in crate::inbox) fn receive_unhandled_activity<A>(
   activity: A,
 ) -> Result<HttpResponse, LemmyError>
 where
@@ -107,7 +105,7 @@ where
   Ok(HttpResponse::NotImplemented().finish())
 }
 
-pub(in crate::apub::inbox) async fn get_user_from_activity<T, A>(
+pub(in crate::inbox) async fn get_user_from_activity<T, A>(
   activity: &T,
   context: &LemmyContext,
 ) -> Result<User_, LemmyError>
@@ -119,7 +117,7 @@ where
   get_or_fetch_and_upsert_user(&user_uri, context).await
 }
 
-pub(in crate::apub::inbox) fn get_community_id_from_activity<T, A>(
+pub(in crate::inbox) fn get_community_id_from_activity<T, A>(
   activity: &T,
 ) -> Result<Url, LemmyError>
 where
@@ -136,7 +134,7 @@ where
   )
 }
 
-pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>(
+pub(in crate::inbox) async fn announce_if_community_is_local<T, Kind>(
   activity: T,
   user: &User_,
   context: &LemmyContext,
similarity index 96%
rename from src/apub/inbox/user_inbox.rs
rename to lemmy_apub/src/inbox/user_inbox.rs
index 5cbbedb6b9d88165b61d14f22a20e1638ab90c4c..a7050c45cc01fa8d46d7219fba6618e81dbe6dd6 100644 (file)
@@ -1,12 +1,9 @@
 use crate::{
-  apub::{
-    check_is_apub_id_valid,
-    extensions::signatures::verify,
-    fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
-    insert_activity,
-    FromApub,
-  },
-  LemmyContext,
+  check_is_apub_id_valid,
+  extensions::signatures::verify,
+  fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
+  insert_activity,
+  FromApub,
 };
 use activitystreams::{
   activity::{Accept, ActorAndObject, Create, Delete, Undo, Update},
@@ -25,12 +22,9 @@ use lemmy_db::{
   Crud,
   Followable,
 };
-use lemmy_structs::{
-  blocking,
-  user::PrivateMessageResponse,
-  websocket::{SendUserRoomMessage, UserOperation},
-};
+use lemmy_structs::{blocking, user::PrivateMessageResponse};
 use lemmy_utils::{location_info, LemmyError};
+use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
 use log::debug;
 use serde::{Deserialize, Serialize};
 use std::fmt::Debug;
similarity index 96%
rename from src/apub/mod.rs
rename to lemmy_apub/src/lib.rs
index 5fd5da36409426c37dfa8d1b523dd746f3fa35a3..22eb9fbe056548f9ec834ae330b4c50bf17f687e 100644 (file)
@@ -1,3 +1,6 @@
+#[macro_use]
+extern crate lazy_static;
+
 pub mod activities;
 pub mod activity_queue;
 pub mod comment;
@@ -9,16 +12,10 @@ pub mod post;
 pub mod private_message;
 pub mod user;
 
-use crate::{
-  apub::extensions::{
-    group_extensions::GroupExtension,
-    page_extension::PageExtension,
-    signatures::{PublicKey, PublicKeyExtension},
-  },
-  request::{retry, RecvError},
-  routes::webfinger::WebFingerResponse,
-  DbPool,
-  LemmyContext,
+use crate::extensions::{
+  group_extensions::GroupExtension,
+  page_extension::PageExtension,
+  signatures::{PublicKey, PublicKeyExtension},
 };
 use activitystreams::{
   activity::Follow,
@@ -32,15 +29,17 @@ use activitystreams_ext::{Ext1, Ext2};
 use actix_web::{body::Body, HttpResponse};
 use anyhow::{anyhow, Context};
 use chrono::NaiveDateTime;
-use lemmy_db::{activity::do_insert_activity, user::User_};
-use lemmy_structs::blocking;
+use lemmy_db::{activity::do_insert_activity, user::User_, DbPool};
+use lemmy_structs::{blocking, WebFingerResponse};
 use lemmy_utils::{
   apub::get_apub_protocol_string,
   location_info,
+  request::{retry, RecvError},
   settings::Settings,
   utils::{convert_datetime, MentionData},
   LemmyError,
 };
+use lemmy_websocket::LemmyContext;
 use log::debug;
 use reqwest::Client;
 use serde::Serialize;
@@ -191,7 +190,7 @@ pub trait ApubObjectType {
   async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
 }
 
-pub(in crate::apub) fn check_actor_domain<T, Kind>(
+pub(in crate) fn check_actor_domain<T, Kind>(
   apub: &T,
   expected_domain: Option<Url>,
 ) -> Result<String, LemmyError>
similarity index 97%
rename from src/apub/post.rs
rename to lemmy_apub/src/post.rs
index 85e00fb231c05538a4ae5f00f6a9a32bce99dfb5..07ecb8f703acfa4822aeb8b305bc51ff0df1553a 100644 (file)
@@ -1,21 +1,17 @@
 use crate::{
-  apub::{
-    activities::{generate_activity_id, send_activity_to_community},
-    check_actor_domain,
-    create_apub_response,
-    create_apub_tombstone_response,
-    create_tombstone,
-    extensions::page_extension::PageExtension,
-    fetcher::{get_or_fetch_and_upsert_community, get_or_fetch_and_upsert_user},
-    ActorType,
-    ApubLikeableType,
-    ApubObjectType,
-    FromApub,
-    PageExt,
-    ToApub,
-  },
-  DbPool,
-  LemmyContext,
+  activities::{generate_activity_id, send_activity_to_community},
+  check_actor_domain,
+  create_apub_response,
+  create_apub_tombstone_response,
+  create_tombstone,
+  extensions::page_extension::PageExtension,
+  fetcher::{get_or_fetch_and_upsert_community, get_or_fetch_and_upsert_user},
+  ActorType,
+  ApubLikeableType,
+  ApubObjectType,
+  FromApub,
+  PageExt,
+  ToApub,
 };
 use activitystreams::{
   activity::{
@@ -40,6 +36,7 @@ use lemmy_db::{
   post::{Post, PostForm},
   user::User_,
   Crud,
+  DbPool,
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{
@@ -47,6 +44,7 @@ use lemmy_utils::{
   utils::{check_slurs, convert_datetime, remove_slurs},
   LemmyError,
 };
+use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
 
similarity index 95%
rename from src/apub/private_message.rs
rename to lemmy_apub/src/private_message.rs
index 9e0549eeb43f840c45d3cfad512e7aab480f0de5..d61a7771ea07858587b38bc30aa0d6afd8a369a9 100644 (file)
@@ -1,19 +1,15 @@
 use crate::{
-  apub::{
-    activities::generate_activity_id,
-    activity_queue::send_activity,
-    check_actor_domain,
-    check_is_apub_id_valid,
-    create_tombstone,
-    fetcher::get_or_fetch_and_upsert_user,
-    insert_activity,
-    ActorType,
-    ApubObjectType,
-    FromApub,
-    ToApub,
-  },
-  DbPool,
-  LemmyContext,
+  activities::generate_activity_id,
+  activity_queue::send_activity,
+  check_actor_domain,
+  check_is_apub_id_valid,
+  create_tombstone,
+  fetcher::get_or_fetch_and_upsert_user,
+  insert_activity,
+  ActorType,
+  ApubObjectType,
+  FromApub,
+  ToApub,
 };
 use activitystreams::{
   activity::{
@@ -31,9 +27,11 @@ use lemmy_db::{
   private_message::{PrivateMessage, PrivateMessageForm},
   user::User_,
   Crud,
+  DbPool,
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
+use lemmy_websocket::LemmyContext;
 use url::Url;
 
 #[async_trait::async_trait(?Send)]
similarity index 96%
rename from src/apub/user.rs
rename to lemmy_apub/src/user.rs
index 47b6a58a71ade4f555c6973a527ddbf976996a49..950f59a18c32b16788b8c2b75ae90682d93ec6a8 100644 (file)
@@ -1,18 +1,14 @@
 use crate::{
-  apub::{
-    activities::generate_activity_id,
-    activity_queue::send_activity,
-    check_actor_domain,
-    create_apub_response,
-    fetcher::get_or_fetch_and_upsert_actor,
-    insert_activity,
-    ActorType,
-    FromApub,
-    PersonExt,
-    ToApub,
-  },
-  DbPool,
-  LemmyContext,
+  activities::generate_activity_id,
+  activity_queue::send_activity,
+  check_actor_domain,
+  create_apub_response,
+  fetcher::get_or_fetch_and_upsert_actor,
+  insert_activity,
+  ActorType,
+  FromApub,
+  PersonExt,
+  ToApub,
 };
 use activitystreams::{
   activity::{
@@ -30,6 +26,7 @@ use anyhow::Context;
 use lemmy_db::{
   naive_now,
   user::{UserForm, User_},
+  DbPool,
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{
@@ -37,6 +34,7 @@ use lemmy_utils::{
   utils::{check_slurs, check_slurs_opt, convert_datetime},
   LemmyError,
 };
+use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
 
index fc660208dcae8af3e73e5916ae738be9ccd4b534..40f6c3d26909cde8e57d1bc91a3e7b8594e14f2c 100644 (file)
@@ -4,14 +4,6 @@ extern crate diesel;
 extern crate strum_macros;
 #[macro_use]
 extern crate lazy_static;
-extern crate bcrypt;
-extern crate chrono;
-extern crate log;
-extern crate regex;
-extern crate serde;
-extern crate serde_json;
-extern crate sha2;
-extern crate strum;
 
 use chrono::NaiveDateTime;
 use diesel::{result::Error, *};
index 8f962bbe615454971e81e9f762602853de16fe04..ecb812af85cea24c459f79af7f174f7b8324a57c 100644 (file)
@@ -1,9 +1,5 @@
 #[macro_use]
 extern crate strum_macros;
-extern crate actix_web;
-extern crate futures;
-extern crate log;
-extern crate tokio;
 
 use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
 use futures::future::{ok, Ready};
index 58658b9240dbf9ddbbf26827942360a09b4549c2..8cf522c3962a4a7ee58dc96348f007e3ffe32b87 100644 (file)
@@ -14,8 +14,6 @@ lemmy_utils = { path = "../lemmy_utils" }
 serde = { version = "1.0", features = ["derive"] }
 log = "0.4"
 diesel = "1.4"
-actix = "0.10"
 actix-web = { version = "3.0" }
-strum = "0.19"
-strum_macros = "0.19"
 chrono = { version = "0.4", features = ["serde"] }
+serde_json = { version = "1.0", features = ["preserve_order"]}
index f7140205a284ce4478bd9b3ea8d79fbdf25568ac..3efe0beada50682b09b3d1b6e48b81c8b86cafd0 100644 (file)
@@ -1,12 +1,3 @@
-extern crate actix;
-extern crate actix_web;
-extern crate diesel;
-extern crate log;
-extern crate serde;
-#[macro_use]
-extern crate strum_macros;
-extern crate chrono;
-
 pub mod comment;
 pub mod community;
 pub mod post;
@@ -25,6 +16,24 @@ use lemmy_db::{
 };
 use lemmy_utils::{email::send_email, settings::Settings, utils::MentionData, LemmyError};
 use log::error;
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct WebFingerLink {
+  pub rel: Option<String>,
+  #[serde(rename(serialize = "type", deserialize = "type"))]
+  pub type_: Option<String>,
+  pub href: Option<String>,
+  #[serde(skip_serializing_if = "Option::is_none")]
+  pub template: Option<String>,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct WebFingerResponse {
+  pub subject: String,
+  pub aliases: Vec<String>,
+  pub links: Vec<WebFingerLink>,
+}
 
 pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
 where
index c5c6c5d607703daaed34cf6cd000089f09bf9b75..8b137891791fe96927ad78e64b0aad7bded08bdc 100644 (file)
@@ -1,195 +1 @@
-use crate::{comment::CommentResponse, post::PostResponse};
-use actix::{prelude::*, Recipient};
-use lemmy_utils::{CommunityId, ConnectionId, IPAddr, PostId, UserId};
-use serde::{Deserialize, Serialize};
 
-#[derive(EnumString, ToString, Debug, Clone)]
-pub enum UserOperation {
-  Login,
-  Register,
-  GetCaptcha,
-  CreateCommunity,
-  CreatePost,
-  ListCommunities,
-  ListCategories,
-  GetPost,
-  GetCommunity,
-  CreateComment,
-  EditComment,
-  DeleteComment,
-  RemoveComment,
-  MarkCommentAsRead,
-  SaveComment,
-  CreateCommentLike,
-  GetPosts,
-  CreatePostLike,
-  EditPost,
-  DeletePost,
-  RemovePost,
-  LockPost,
-  StickyPost,
-  SavePost,
-  EditCommunity,
-  DeleteCommunity,
-  RemoveCommunity,
-  FollowCommunity,
-  GetFollowedCommunities,
-  GetUserDetails,
-  GetReplies,
-  GetUserMentions,
-  MarkUserMentionAsRead,
-  GetModlog,
-  BanFromCommunity,
-  AddModToCommunity,
-  CreateSite,
-  EditSite,
-  GetSite,
-  AddAdmin,
-  BanUser,
-  Search,
-  MarkAllAsRead,
-  SaveUserSettings,
-  TransferCommunity,
-  TransferSite,
-  DeleteAccount,
-  PasswordReset,
-  PasswordChange,
-  CreatePrivateMessage,
-  EditPrivateMessage,
-  DeletePrivateMessage,
-  MarkPrivateMessageAsRead,
-  GetPrivateMessages,
-  UserJoin,
-  GetComments,
-  GetSiteConfig,
-  SaveSiteConfig,
-  PostJoin,
-  CommunityJoin,
-}
-
-/// Chat server sends this messages to session
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct WSMessage(pub String);
-
-/// Message for chat server communications
-
-/// New chat session is created
-#[derive(Message)]
-#[rtype(usize)]
-pub struct Connect {
-  pub addr: Recipient<WSMessage>,
-  pub ip: IPAddr,
-}
-
-/// Session is disconnected
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct Disconnect {
-  pub id: ConnectionId,
-  pub ip: IPAddr,
-}
-
-/// The messages sent to websocket clients
-#[derive(Serialize, Deserialize, Message)]
-#[rtype(result = "Result<String, std::convert::Infallible>")]
-pub struct StandardMessage {
-  /// Id of the client session
-  pub id: ConnectionId,
-  /// Peer message
-  pub msg: String,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendAllMessage<Response> {
-  pub op: UserOperation,
-  pub response: Response,
-  pub websocket_id: Option<ConnectionId>,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendUserRoomMessage<Response> {
-  pub op: UserOperation,
-  pub response: Response,
-  pub recipient_id: UserId,
-  pub websocket_id: Option<ConnectionId>,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendCommunityRoomMessage<Response> {
-  pub op: UserOperation,
-  pub response: Response,
-  pub community_id: CommunityId,
-  pub websocket_id: Option<ConnectionId>,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendPost {
-  pub op: UserOperation,
-  pub post: PostResponse,
-  pub websocket_id: Option<ConnectionId>,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendComment {
-  pub op: UserOperation,
-  pub comment: CommentResponse,
-  pub websocket_id: Option<ConnectionId>,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinUserRoom {
-  pub user_id: UserId,
-  pub id: ConnectionId,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinCommunityRoom {
-  pub community_id: CommunityId,
-  pub id: ConnectionId,
-}
-
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinPostRoom {
-  pub post_id: PostId,
-  pub id: ConnectionId,
-}
-
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetUsersOnline;
-
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetPostUsersOnline {
-  pub post_id: PostId,
-}
-
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetCommunityUsersOnline {
-  pub community_id: CommunityId,
-}
-
-#[derive(Message, Debug)]
-#[rtype(result = "()")]
-pub struct CaptchaItem {
-  pub uuid: String,
-  pub answer: String,
-  pub expires: chrono::NaiveDateTime,
-}
-
-#[derive(Message)]
-#[rtype(bool)]
-pub struct CheckCaptcha {
-  pub uuid: String,
-  pub answer: String,
-}
index 9ff9d7d3443545cabb54b107cd05c6888d24d143..a575bb18a20340476bf2da94762720dec3808376 100644 (file)
@@ -7,8 +7,6 @@ edition = "2018"
 name = "lemmy_utils"
 path = "src/lib.rs"
 
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
 [dependencies]
 regex = "1.3"
 config = { version = "0.10", default-features = false, features = ["hjson"] }
@@ -27,3 +25,4 @@ openssl = "0.10"
 url = { version = "2.1", features = ["serde"] }
 actix-web = { version = "3.0", default-features = false, features = ["rustls"] }
 anyhow = "1.0"
+reqwest = { version = "0.10", features = ["json"] }
index 247705e420e2807436b985307aade45fc027bf19..19e7bb8399d8d449af720702b84ae037af700f3b 100644 (file)
@@ -1,19 +1,9 @@
 #[macro_use]
 extern crate lazy_static;
-extern crate actix_web;
-extern crate anyhow;
-extern crate comrak;
-extern crate lettre;
-extern crate lettre_email;
-extern crate openssl;
-extern crate rand;
-extern crate regex;
-extern crate serde_json;
-extern crate thiserror;
-extern crate url;
 
 pub mod apub;
 pub mod email;
+pub mod request;
 pub mod settings;
 #[cfg(test)]
 mod test;
similarity index 97%
rename from src/request.rs
rename to lemmy_utils/src/request.rs
index 137848f2a695809eca9b162e6476817689bf099f..490609e7dc0be31954e5fd961e79e12579119f4e 100644 (file)
@@ -1,5 +1,5 @@
+use crate::LemmyError;
 use anyhow::anyhow;
-use lemmy_utils::LemmyError;
 use std::future::Future;
 use thiserror::Error;
 
diff --git a/lemmy_websocket/Cargo.toml b/lemmy_websocket/Cargo.toml
new file mode 100644 (file)
index 0000000..c61da42
--- /dev/null
@@ -0,0 +1,28 @@
+[package]
+name = "lemmy_websocket"
+version = "0.1.0"
+authors = ["Felix Ableitner <me@nutomic.com>"]
+edition = "2018"
+
+[lib]
+name = "lemmy_websocket"
+path = "src/lib.rs"
+
+[dependencies]
+lemmy_utils = { path = "../lemmy_utils" }
+lemmy_structs = { path = "../lemmy_structs" }
+lemmy_db = { path = "../lemmy_db" }
+lemmy_rate_limit = { path = "../lemmy_rate_limit" }
+reqwest = { version = "0.10", features = ["json"] }
+log = "0.4"
+rand = "0.7"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = { version = "1.0", features = ["preserve_order"]}
+actix = "0.10"
+anyhow = "1.0"
+diesel = "1.4"
+background-jobs = " 0.8"
+tokio = "0.2"
+strum = "0.19"
+strum_macros = "0.19"
+chrono = { version = "0.4", features = ["serde"] }
similarity index 58%
rename from src/websocket/chat_server.rs
rename to lemmy_websocket/src/chat_server.rs
index 611f44f9715ba6caa12e6b92e4c6d218787b8d7a..8346a32f60450ef8f727fe9e8bb9e65972dd2555 100644 (file)
@@ -1,7 +1,4 @@
-use crate::{
-  websocket::handlers::{do_user_operation, to_json_string, Args},
-  LemmyContext,
-};
+use crate::{messages::*, serialize_websocket_message, LemmyContext, UserOperation};
 use actix::prelude::*;
 use anyhow::Context as acontext;
 use background_jobs::QueueHandle;
@@ -10,7 +7,7 @@ use diesel::{
   PgConnection,
 };
 use lemmy_rate_limit::RateLimit;
-use lemmy_structs::{comment::*, community::*, post::*, site::*, user::*, websocket::*};
+use lemmy_structs::{comment::*, post::*};
 use lemmy_utils::{
   location_info,
   APIError,
@@ -29,6 +26,14 @@ use std::{
   collections::{HashMap, HashSet},
   str::FromStr,
 };
+use tokio::macros::support::Pin;
+
+type MessageHandlerType = fn(
+  context: LemmyContext,
+  id: ConnectionId,
+  op: UserOperation,
+  data: &str,
+) -> Pin<Box<dyn Future<Output = Result<String, LemmyError>> + '_>>;
 
 /// `ChatServer` manages chat rooms and responsible for coordinating chat
 /// session.
@@ -57,6 +62,8 @@ pub struct ChatServer {
   /// A list of the current captchas
   pub(super) captchas: Vec<CaptchaItem>,
 
+  message_handler: MessageHandlerType,
+
   /// An HTTP Client
   client: Client,
 
@@ -75,6 +82,7 @@ impl ChatServer {
   pub fn startup(
     pool: Pool<ConnectionManager<PgConnection>>,
     rate_limiter: RateLimit,
+    message_handler: MessageHandlerType,
     client: Client,
     activity_queue: QueueHandle,
   ) -> ChatServer {
@@ -87,6 +95,7 @@ impl ChatServer {
       pool,
       rate_limiter,
       captchas: Vec::new(),
+      message_handler,
       client,
       activity_queue,
     }
@@ -180,7 +189,7 @@ impl ChatServer {
   where
     Response: Serialize,
   {
-    let res_str = &to_json_string(op, response)?;
+    let res_str = &serialize_websocket_message(op, response)?;
     if let Some(sessions) = self.post_rooms.get(&post_id) {
       for id in sessions {
         if let Some(my_id) = websocket_id {
@@ -204,7 +213,7 @@ impl ChatServer {
   where
     Response: Serialize,
   {
-    let res_str = &to_json_string(op, response)?;
+    let res_str = &serialize_websocket_message(op, response)?;
     if let Some(sessions) = self.community_rooms.get(&community_id) {
       for id in sessions {
         if let Some(my_id) = websocket_id {
@@ -227,7 +236,7 @@ impl ChatServer {
   where
     Response: Serialize,
   {
-    let res_str = &to_json_string(op, response)?;
+    let res_str = &serialize_websocket_message(op, response)?;
     for id in self.sessions.keys() {
       if let Some(my_id) = websocket_id {
         if *id == my_id {
@@ -249,7 +258,7 @@ impl ChatServer {
   where
     Response: Serialize,
   {
-    let res_str = &to_json_string(op, response)?;
+    let res_str = &serialize_websocket_message(op, response)?;
     if let Some(sessions) = self.user_rooms.get(&recipient_id) {
       for id in sessions {
         if let Some(my_id) = websocket_id {
@@ -340,8 +349,6 @@ impl ChatServer {
     msg: StandardMessage,
     ctx: &mut Context<Self>,
   ) -> impl Future<Output = Result<String, LemmyError>> {
-    let addr = ctx.address();
-    let pool = self.pool.clone();
     let rate_limiter = self.rate_limiter.clone();
 
     let ip: IPAddr = match self.sessions.get(&msg.id) {
@@ -349,110 +356,27 @@ impl ChatServer {
       None => "blank_ip".to_string(),
     };
 
-    let client = self.client.clone();
-    let activity_queue = self.activity_queue.clone();
+    let context = LemmyContext {
+      pool: self.pool.clone(),
+      chat_server: ctx.address(),
+      client: self.client.to_owned(),
+      activity_queue: self.activity_queue.to_owned(),
+    };
+    let message_handler = self.message_handler;
     async move {
-      let msg = msg;
       let json: Value = serde_json::from_str(&msg.msg)?;
       let data = &json["data"].to_string();
       let op = &json["op"].as_str().ok_or(APIError {
         message: "Unknown op type".to_string(),
       })?;
 
-      let user_operation: UserOperation = UserOperation::from_str(&op)?;
-
-      let context = LemmyContext::new(pool, addr, client, activity_queue);
-      let args = Args {
-        context,
-        rate_limiter,
-        id: msg.id,
-        ip,
-        op: user_operation.clone(),
-        data,
-      };
-
+      let user_operation = UserOperation::from_str(&op)?;
+      let fut = (message_handler)(context, msg.id, user_operation.clone(), data);
       match user_operation {
-        // User ops
-        UserOperation::Login => do_user_operation::<Login>(args).await,
-        UserOperation::Register => do_user_operation::<Register>(args).await,
-        UserOperation::GetCaptcha => do_user_operation::<GetCaptcha>(args).await,
-        UserOperation::GetUserDetails => do_user_operation::<GetUserDetails>(args).await,
-        UserOperation::GetReplies => do_user_operation::<GetReplies>(args).await,
-        UserOperation::AddAdmin => do_user_operation::<AddAdmin>(args).await,
-        UserOperation::BanUser => do_user_operation::<BanUser>(args).await,
-        UserOperation::GetUserMentions => do_user_operation::<GetUserMentions>(args).await,
-        UserOperation::MarkUserMentionAsRead => {
-          do_user_operation::<MarkUserMentionAsRead>(args).await
-        }
-        UserOperation::MarkAllAsRead => do_user_operation::<MarkAllAsRead>(args).await,
-        UserOperation::DeleteAccount => do_user_operation::<DeleteAccount>(args).await,
-        UserOperation::PasswordReset => do_user_operation::<PasswordReset>(args).await,
-        UserOperation::PasswordChange => do_user_operation::<PasswordChange>(args).await,
-        UserOperation::UserJoin => do_user_operation::<UserJoin>(args).await,
-        UserOperation::PostJoin => do_user_operation::<PostJoin>(args).await,
-        UserOperation::CommunityJoin => do_user_operation::<CommunityJoin>(args).await,
-        UserOperation::SaveUserSettings => do_user_operation::<SaveUserSettings>(args).await,
-
-        // Private Message ops
-        UserOperation::CreatePrivateMessage => {
-          do_user_operation::<CreatePrivateMessage>(args).await
-        }
-        UserOperation::EditPrivateMessage => do_user_operation::<EditPrivateMessage>(args).await,
-        UserOperation::DeletePrivateMessage => {
-          do_user_operation::<DeletePrivateMessage>(args).await
-        }
-        UserOperation::MarkPrivateMessageAsRead => {
-          do_user_operation::<MarkPrivateMessageAsRead>(args).await
-        }
-        UserOperation::GetPrivateMessages => do_user_operation::<GetPrivateMessages>(args).await,
-
-        // Site ops
-        UserOperation::GetModlog => do_user_operation::<GetModlog>(args).await,
-        UserOperation::CreateSite => do_user_operation::<CreateSite>(args).await,
-        UserOperation::EditSite => do_user_operation::<EditSite>(args).await,
-        UserOperation::GetSite => do_user_operation::<GetSite>(args).await,
-        UserOperation::GetSiteConfig => do_user_operation::<GetSiteConfig>(args).await,
-        UserOperation::SaveSiteConfig => do_user_operation::<SaveSiteConfig>(args).await,
-        UserOperation::Search => do_user_operation::<Search>(args).await,
-        UserOperation::TransferCommunity => do_user_operation::<TransferCommunity>(args).await,
-        UserOperation::TransferSite => do_user_operation::<TransferSite>(args).await,
-        UserOperation::ListCategories => do_user_operation::<ListCategories>(args).await,
-
-        // Community ops
-        UserOperation::GetCommunity => do_user_operation::<GetCommunity>(args).await,
-        UserOperation::ListCommunities => do_user_operation::<ListCommunities>(args).await,
-        UserOperation::CreateCommunity => do_user_operation::<CreateCommunity>(args).await,
-        UserOperation::EditCommunity => do_user_operation::<EditCommunity>(args).await,
-        UserOperation::DeleteCommunity => do_user_operation::<DeleteCommunity>(args).await,
-        UserOperation::RemoveCommunity => do_user_operation::<RemoveCommunity>(args).await,
-        UserOperation::FollowCommunity => do_user_operation::<FollowCommunity>(args).await,
-        UserOperation::GetFollowedCommunities => {
-          do_user_operation::<GetFollowedCommunities>(args).await
-        }
-        UserOperation::BanFromCommunity => do_user_operation::<BanFromCommunity>(args).await,
-        UserOperation::AddModToCommunity => do_user_operation::<AddModToCommunity>(args).await,
-
-        // Post ops
-        UserOperation::CreatePost => do_user_operation::<CreatePost>(args).await,
-        UserOperation::GetPost => do_user_operation::<GetPost>(args).await,
-        UserOperation::GetPosts => do_user_operation::<GetPosts>(args).await,
-        UserOperation::EditPost => do_user_operation::<EditPost>(args).await,
-        UserOperation::DeletePost => do_user_operation::<DeletePost>(args).await,
-        UserOperation::RemovePost => do_user_operation::<RemovePost>(args).await,
-        UserOperation::LockPost => do_user_operation::<LockPost>(args).await,
-        UserOperation::StickyPost => do_user_operation::<StickyPost>(args).await,
-        UserOperation::CreatePostLike => do_user_operation::<CreatePostLike>(args).await,
-        UserOperation::SavePost => do_user_operation::<SavePost>(args).await,
-
-        // Comment ops
-        UserOperation::CreateComment => do_user_operation::<CreateComment>(args).await,
-        UserOperation::EditComment => do_user_operation::<EditComment>(args).await,
-        UserOperation::DeleteComment => do_user_operation::<DeleteComment>(args).await,
-        UserOperation::RemoveComment => do_user_operation::<RemoveComment>(args).await,
-        UserOperation::MarkCommentAsRead => do_user_operation::<MarkCommentAsRead>(args).await,
-        UserOperation::SaveComment => do_user_operation::<SaveComment>(args).await,
-        UserOperation::GetComments => do_user_operation::<GetComments>(args).await,
-        UserOperation::CreateCommentLike => do_user_operation::<CreateCommentLike>(args).await,
+        UserOperation::Register => rate_limiter.register().wrap(ip, fut).await,
+        UserOperation::CreatePost => rate_limiter.post().wrap(ip, fut).await,
+        UserOperation::CreateCommunity => rate_limiter.register().wrap(ip, fut).await,
+        _ => rate_limiter.message().wrap(ip, fut).await,
       }
     }
   }
similarity index 76%
rename from src/websocket/handlers.rs
rename to lemmy_websocket/src/handlers.rs
index 75e638f94e34786ff8c7fd531a962d896ebd839f..258098d6276a298b919cb63b8d6139a265067692 100644 (file)
@@ -1,59 +1,12 @@
 use crate::{
-  api::Perform,
-  websocket::chat_server::{ChatServer, SessionInfo},
-  LemmyContext,
+  chat_server::{ChatServer, SessionInfo},
+  messages::*,
 };
 use actix::{Actor, Context, Handler, ResponseFuture};
-use actix_web::web;
 use lemmy_db::naive_now;
-use lemmy_rate_limit::RateLimit;
-use lemmy_structs::websocket::*;
-use lemmy_utils::{ConnectionId, IPAddr, LemmyError};
 use log::{error, info};
 use rand::Rng;
-use serde::{Deserialize, Serialize};
-
-pub(super) struct Args<'a> {
-  pub(super) context: LemmyContext,
-  pub(super) rate_limiter: RateLimit,
-  pub(super) id: ConnectionId,
-  pub(super) ip: IPAddr,
-  pub(super) op: UserOperation,
-  pub(super) data: &'a str,
-}
-
-pub(super) async fn do_user_operation<'a, 'b, Data>(args: Args<'b>) -> Result<String, LemmyError>
-where
-  for<'de> Data: Deserialize<'de> + 'a,
-  Data: Perform,
-{
-  let Args {
-    context,
-    rate_limiter,
-    id,
-    ip,
-    op,
-    data,
-  } = args;
-
-  let data = data.to_string();
-  let op2 = op.clone();
-
-  let fut = async move {
-    let parsed_data: Data = serde_json::from_str(&data)?;
-    let res = parsed_data
-      .perform(&web::Data::new(context), Some(id))
-      .await?;
-    to_json_string(&op, &res)
-  };
-
-  match op2 {
-    UserOperation::Register => rate_limiter.register().wrap(ip, fut).await,
-    UserOperation::CreatePost => rate_limiter.post().wrap(ip, fut).await,
-    UserOperation::CreateCommunity => rate_limiter.register().wrap(ip, fut).await,
-    _ => rate_limiter.message().wrap(ip, fut).await,
-  }
-}
+use serde::Serialize;
 
 /// Make actor from `ChatServer`
 impl Actor for ChatServer {
@@ -241,26 +194,6 @@ impl Handler<GetCommunityUsersOnline> for ChatServer {
   }
 }
 
-#[derive(Serialize)]
-struct WebsocketResponse<T> {
-  op: String,
-  data: T,
-}
-
-pub(super) fn to_json_string<Response>(
-  op: &UserOperation,
-  data: &Response,
-) -> Result<String, LemmyError>
-where
-  Response: Serialize,
-{
-  let response = WebsocketResponse {
-    op: op.to_string(),
-    data,
-  };
-  Ok(serde_json::to_string(&response)?)
-}
-
 impl Handler<CaptchaItem> for ChatServer {
   type Result = ();
 
diff --git a/lemmy_websocket/src/lib.rs b/lemmy_websocket/src/lib.rs
new file mode 100644 (file)
index 0000000..26b00a0
--- /dev/null
@@ -0,0 +1,144 @@
+#[macro_use]
+extern crate strum_macros;
+
+use crate::chat_server::ChatServer;
+use actix::Addr;
+use background_jobs::QueueHandle;
+use lemmy_db::DbPool;
+use lemmy_utils::LemmyError;
+use reqwest::Client;
+use serde::Serialize;
+
+pub mod chat_server;
+pub mod handlers;
+pub mod messages;
+
+pub struct LemmyContext {
+  pub pool: DbPool,
+  pub chat_server: Addr<ChatServer>,
+  pub client: Client,
+  pub activity_queue: QueueHandle,
+}
+
+impl LemmyContext {
+  pub fn create(
+    pool: DbPool,
+    chat_server: Addr<ChatServer>,
+    client: Client,
+    activity_queue: QueueHandle,
+  ) -> LemmyContext {
+    LemmyContext {
+      pool,
+      chat_server,
+      client,
+      activity_queue,
+    }
+  }
+  pub fn pool(&self) -> &DbPool {
+    &self.pool
+  }
+  pub fn chat_server(&self) -> &Addr<ChatServer> {
+    &self.chat_server
+  }
+  pub fn client(&self) -> &Client {
+    &self.client
+  }
+  pub fn activity_queue(&self) -> &QueueHandle {
+    &self.activity_queue
+  }
+}
+
+impl Clone for LemmyContext {
+  fn clone(&self) -> Self {
+    LemmyContext {
+      pool: self.pool.clone(),
+      chat_server: self.chat_server.clone(),
+      client: self.client.clone(),
+      activity_queue: self.activity_queue.clone(),
+    }
+  }
+}
+
+#[derive(Serialize)]
+struct WebsocketResponse<T> {
+  op: String,
+  data: T,
+}
+
+pub fn serialize_websocket_message<Response>(
+  op: &UserOperation,
+  data: &Response,
+) -> Result<String, LemmyError>
+where
+  Response: Serialize,
+{
+  let response = WebsocketResponse {
+    op: op.to_string(),
+    data,
+  };
+  Ok(serde_json::to_string(&response)?)
+}
+
+#[derive(EnumString, ToString, Debug, Clone)]
+pub enum UserOperation {
+  Login,
+  Register,
+  GetCaptcha,
+  CreateCommunity,
+  CreatePost,
+  ListCommunities,
+  ListCategories,
+  GetPost,
+  GetCommunity,
+  CreateComment,
+  EditComment,
+  DeleteComment,
+  RemoveComment,
+  MarkCommentAsRead,
+  SaveComment,
+  CreateCommentLike,
+  GetPosts,
+  CreatePostLike,
+  EditPost,
+  DeletePost,
+  RemovePost,
+  LockPost,
+  StickyPost,
+  SavePost,
+  EditCommunity,
+  DeleteCommunity,
+  RemoveCommunity,
+  FollowCommunity,
+  GetFollowedCommunities,
+  GetUserDetails,
+  GetReplies,
+  GetUserMentions,
+  MarkUserMentionAsRead,
+  GetModlog,
+  BanFromCommunity,
+  AddModToCommunity,
+  CreateSite,
+  EditSite,
+  GetSite,
+  AddAdmin,
+  BanUser,
+  Search,
+  MarkAllAsRead,
+  SaveUserSettings,
+  TransferCommunity,
+  TransferSite,
+  DeleteAccount,
+  PasswordReset,
+  PasswordChange,
+  CreatePrivateMessage,
+  EditPrivateMessage,
+  DeletePrivateMessage,
+  MarkPrivateMessageAsRead,
+  GetPrivateMessages,
+  UserJoin,
+  GetComments,
+  GetSiteConfig,
+  SaveSiteConfig,
+  PostJoin,
+  CommunityJoin,
+}
diff --git a/lemmy_websocket/src/messages.rs b/lemmy_websocket/src/messages.rs
new file mode 100644 (file)
index 0000000..d9f8320
--- /dev/null
@@ -0,0 +1,132 @@
+use crate::UserOperation;
+use actix::{prelude::*, Recipient};
+use lemmy_structs::{comment::CommentResponse, post::PostResponse};
+use lemmy_utils::{CommunityId, ConnectionId, IPAddr, PostId, UserId};
+use serde::{Deserialize, Serialize};
+
+/// Chat server sends this messages to session
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct WSMessage(pub String);
+
+/// Message for chat server communications
+
+/// New chat session is created
+#[derive(Message)]
+#[rtype(usize)]
+pub struct Connect {
+  pub addr: Recipient<WSMessage>,
+  pub ip: IPAddr,
+}
+
+/// Session is disconnected
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct Disconnect {
+  pub id: ConnectionId,
+  pub ip: IPAddr,
+}
+
+/// The messages sent to websocket clients
+#[derive(Serialize, Deserialize, Message)]
+#[rtype(result = "Result<String, std::convert::Infallible>")]
+pub struct StandardMessage {
+  /// Id of the client session
+  pub id: ConnectionId,
+  /// Peer message
+  pub msg: String,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendAllMessage<Response> {
+  pub op: UserOperation,
+  pub response: Response,
+  pub websocket_id: Option<ConnectionId>,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendUserRoomMessage<Response> {
+  pub op: UserOperation,
+  pub response: Response,
+  pub recipient_id: UserId,
+  pub websocket_id: Option<ConnectionId>,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendCommunityRoomMessage<Response> {
+  pub op: UserOperation,
+  pub response: Response,
+  pub community_id: CommunityId,
+  pub websocket_id: Option<ConnectionId>,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendPost {
+  pub op: UserOperation,
+  pub post: PostResponse,
+  pub websocket_id: Option<ConnectionId>,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendComment {
+  pub op: UserOperation,
+  pub comment: CommentResponse,
+  pub websocket_id: Option<ConnectionId>,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct JoinUserRoom {
+  pub user_id: UserId,
+  pub id: ConnectionId,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct JoinCommunityRoom {
+  pub community_id: CommunityId,
+  pub id: ConnectionId,
+}
+
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct JoinPostRoom {
+  pub post_id: PostId,
+  pub id: ConnectionId,
+}
+
+#[derive(Message)]
+#[rtype(usize)]
+pub struct GetUsersOnline;
+
+#[derive(Message)]
+#[rtype(usize)]
+pub struct GetPostUsersOnline {
+  pub post_id: PostId,
+}
+
+#[derive(Message)]
+#[rtype(usize)]
+pub struct GetCommunityUsersOnline {
+  pub community_id: CommunityId,
+}
+
+#[derive(Message, Debug)]
+#[rtype(result = "()")]
+pub struct CaptchaItem {
+  pub uuid: String,
+  pub answer: String,
+  pub expires: chrono::NaiveDateTime,
+}
+
+#[derive(Message)]
+#[rtype(bool)]
+pub struct CheckCaptcha {
+  pub uuid: String,
+  pub answer: String,
+}
diff --git a/src/api/mod.rs b/src/api/mod.rs
deleted file mode 100644 (file)
index d63f38e..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-use crate::{api::claims::Claims, DbPool, LemmyContext};
-use actix_web::web::Data;
-use lemmy_db::{
-  community::Community,
-  community_view::CommunityUserBanView,
-  post::Post,
-  user::User_,
-  Crud,
-};
-use lemmy_structs::blocking;
-use lemmy_utils::{APIError, ConnectionId, LemmyError};
-
-pub mod claims;
-pub mod comment;
-pub mod community;
-pub mod post;
-pub mod site;
-pub mod user;
-
-#[async_trait::async_trait(?Send)]
-pub trait Perform {
-  type Response: serde::ser::Serialize + Send;
-
-  async fn perform(
-    &self,
-    context: &Data<LemmyContext>,
-    websocket_id: Option<ConnectionId>,
-  ) -> Result<Self::Response, LemmyError>;
-}
-
-pub(in crate::api) async fn is_mod_or_admin(
-  pool: &DbPool,
-  user_id: i32,
-  community_id: i32,
-) -> Result<(), LemmyError> {
-  let is_mod_or_admin = blocking(pool, move |conn| {
-    Community::is_mod_or_admin(conn, user_id, community_id)
-  })
-  .await?;
-  if !is_mod_or_admin {
-    return Err(APIError::err("not_a_mod_or_admin").into());
-  }
-  Ok(())
-}
-pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> {
-  let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
-  if !user.admin {
-    return Err(APIError::err("not_an_admin").into());
-  }
-  Ok(())
-}
-
-pub(in crate::api) async fn get_post(post_id: i32, pool: &DbPool) -> Result<Post, LemmyError> {
-  match blocking(pool, move |conn| Post::read(conn, post_id)).await? {
-    Ok(post) => Ok(post),
-    Err(_e) => Err(APIError::err("couldnt_find_post").into()),
-  }
-}
-
-pub(in crate::api) async fn get_user_from_jwt(
-  jwt: &str,
-  pool: &DbPool,
-) -> Result<User_, LemmyError> {
-  let claims = match Claims::decode(&jwt) {
-    Ok(claims) => claims.claims,
-    Err(_e) => return Err(APIError::err("not_logged_in").into()),
-  };
-  let user_id = claims.id;
-  let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
-  // Check for a site ban
-  if user.banned {
-    return Err(APIError::err("site_ban").into());
-  }
-  Ok(user)
-}
-
-pub(in crate::api) async fn get_user_from_jwt_opt(
-  jwt: &Option<String>,
-  pool: &DbPool,
-) -> Result<Option<User_>, LemmyError> {
-  match jwt {
-    Some(jwt) => Ok(Some(get_user_from_jwt(jwt, pool).await?)),
-    None => Ok(None),
-  }
-}
-
-pub(in crate::api) async fn check_community_ban(
-  user_id: i32,
-  community_id: i32,
-  pool: &DbPool,
-) -> Result<(), LemmyError> {
-  let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
-  if blocking(pool, is_banned).await? {
-    Err(APIError::err("community_ban").into())
-  } else {
-    Ok(())
-  }
-}
index 5d5f00b0de01960d0181212995656c5ca2bfffce..7e5754d46e54cc835476839e53cadd3d27748cb0 100644 (file)
@@ -1,307 +1,4 @@
 #![recursion_limit = "512"]
-#[macro_use]
-extern crate lazy_static;
-extern crate actix;
-extern crate actix_web;
-extern crate base64;
-extern crate bcrypt;
-extern crate captcha;
-extern crate chrono;
-extern crate diesel;
-extern crate dotenv;
-extern crate jsonwebtoken;
-extern crate log;
-extern crate openssl;
-extern crate reqwest;
-extern crate rss;
-extern crate serde;
-extern crate serde_json;
-extern crate sha2;
-extern crate strum;
 
-pub mod api;
-pub mod apub;
 pub mod code_migrations;
-pub mod request;
 pub mod routes;
-pub mod version;
-pub mod websocket;
-
-use crate::{
-  request::{retry, RecvError},
-  websocket::chat_server::ChatServer,
-};
-use actix::Addr;
-use anyhow::anyhow;
-use background_jobs::QueueHandle;
-use lemmy_db::DbPool;
-use lemmy_utils::{apub::get_apub_protocol_string, settings::Settings, LemmyError};
-use log::error;
-use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
-use reqwest::Client;
-use serde::Deserialize;
-use std::process::Command;
-
-pub struct LemmyContext {
-  pub pool: DbPool,
-  pub chat_server: Addr<ChatServer>,
-  pub client: Client,
-  pub activity_queue: QueueHandle,
-}
-
-impl LemmyContext {
-  pub fn new(
-    pool: DbPool,
-    chat_server: Addr<ChatServer>,
-    client: Client,
-    activity_queue: QueueHandle,
-  ) -> LemmyContext {
-    LemmyContext {
-      pool,
-      chat_server,
-      client,
-      activity_queue,
-    }
-  }
-  pub fn pool(&self) -> &DbPool {
-    &self.pool
-  }
-  pub fn chat_server(&self) -> &Addr<ChatServer> {
-    &self.chat_server
-  }
-  pub fn client(&self) -> &Client {
-    &self.client
-  }
-  pub fn activity_queue(&self) -> &QueueHandle {
-    &self.activity_queue
-  }
-}
-
-impl Clone for LemmyContext {
-  fn clone(&self) -> Self {
-    LemmyContext::new(
-      self.pool.clone(),
-      self.chat_server.clone(),
-      self.client.clone(),
-      self.activity_queue.clone(),
-    )
-  }
-}
-
-#[derive(Deserialize, Debug)]
-pub struct IframelyResponse {
-  title: Option<String>,
-  description: Option<String>,
-  thumbnail_url: Option<String>,
-  html: Option<String>,
-}
-
-pub async fn fetch_iframely(client: &Client, url: &str) -> Result<IframelyResponse, LemmyError> {
-  let fetch_url = format!("http://iframely/oembed?url={}", url);
-
-  let response = retry(|| client.get(&fetch_url).send()).await?;
-
-  let res: IframelyResponse = response
-    .json()
-    .await
-    .map_err(|e| RecvError(e.to_string()))?;
-  Ok(res)
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct PictrsResponse {
-  files: Vec<PictrsFile>,
-  msg: String,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct PictrsFile {
-  file: String,
-  delete_token: String,
-}
-
-pub async fn fetch_pictrs(client: &Client, image_url: &str) -> Result<PictrsResponse, LemmyError> {
-  is_image_content_type(client, image_url).await?;
-
-  let fetch_url = format!(
-    "http://pictrs:8080/image/download?url={}",
-    utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed
-  );
-
-  let response = retry(|| client.get(&fetch_url).send()).await?;
-
-  let response: PictrsResponse = response
-    .json()
-    .await
-    .map_err(|e| RecvError(e.to_string()))?;
-
-  if response.msg == "ok" {
-    Ok(response)
-  } else {
-    Err(anyhow!("{}", &response.msg).into())
-  }
-}
-
-async fn fetch_iframely_and_pictrs_data(
-  client: &Client,
-  url: Option<String>,
-) -> (
-  Option<String>,
-  Option<String>,
-  Option<String>,
-  Option<String>,
-) {
-  match &url {
-    Some(url) => {
-      // Fetch iframely data
-      let (iframely_title, iframely_description, iframely_thumbnail_url, iframely_html) =
-        match fetch_iframely(client, url).await {
-          Ok(res) => (res.title, res.description, res.thumbnail_url, res.html),
-          Err(e) => {
-            error!("iframely err: {}", e);
-            (None, None, None, None)
-          }
-        };
-
-      // Fetch pictrs thumbnail
-      let pictrs_hash = match iframely_thumbnail_url {
-        Some(iframely_thumbnail_url) => match fetch_pictrs(client, &iframely_thumbnail_url).await {
-          Ok(res) => Some(res.files[0].file.to_owned()),
-          Err(e) => {
-            error!("pictrs err: {}", e);
-            None
-          }
-        },
-        // Try to generate a small thumbnail if iframely is not supported
-        None => match fetch_pictrs(client, &url).await {
-          Ok(res) => Some(res.files[0].file.to_owned()),
-          Err(e) => {
-            error!("pictrs err: {}", e);
-            None
-          }
-        },
-      };
-
-      // The full urls are necessary for federation
-      let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
-        Some(format!(
-          "{}://{}/pictrs/image/{}",
-          get_apub_protocol_string(),
-          Settings::get().hostname,
-          pictrs_hash
-        ))
-      } else {
-        None
-      };
-
-      (
-        iframely_title,
-        iframely_description,
-        iframely_html,
-        pictrs_thumbnail,
-      )
-    }
-    None => (None, None, None, None),
-  }
-}
-
-pub async fn is_image_content_type(client: &Client, test: &str) -> Result<(), LemmyError> {
-  let response = retry(|| client.get(test).send()).await?;
-
-  if response
-    .headers()
-    .get("Content-Type")
-    .ok_or_else(|| anyhow!("No Content-Type header"))?
-    .to_str()?
-    .starts_with("image/")
-  {
-    Ok(())
-  } else {
-    Err(anyhow!("Not an image type.").into())
-  }
-}
-
-pub fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyError> {
-  let mut built_text = String::new();
-
-  // Building proper speech text for espeak
-  for mut c in captcha.chars() {
-    let new_str = if c.is_alphabetic() {
-      if c.is_lowercase() {
-        c.make_ascii_uppercase();
-        format!("lower case {} ... ", c)
-      } else {
-        c.make_ascii_uppercase();
-        format!("capital {} ... ", c)
-      }
-    } else {
-      format!("{} ...", c)
-    };
-
-    built_text.push_str(&new_str);
-  }
-
-  espeak_wav_base64(&built_text)
-}
-
-pub fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
-  // Make a temp file path
-  let uuid = uuid::Uuid::new_v4().to_string();
-  let file_path = format!("/tmp/lemmy_espeak_{}.wav", &uuid);
-
-  // Write the wav file
-  Command::new("espeak")
-    .arg("-w")
-    .arg(&file_path)
-    .arg(text)
-    .status()?;
-
-  // Read the wav file bytes
-  let bytes = std::fs::read(&file_path)?;
-
-  // Delete the file
-  std::fs::remove_file(file_path)?;
-
-  // Convert to base64
-  let base64 = base64::encode(bytes);
-
-  Ok(base64)
-}
-
-#[cfg(test)]
-mod tests {
-  use crate::{captcha_espeak_wav_base64, is_image_content_type};
-
-  #[test]
-  fn test_image() {
-    actix_rt::System::new("tset_image").block_on(async move {
-      let client = reqwest::Client::default();
-      assert!(is_image_content_type(&client, "https://1734811051.rsc.cdn77.org/data/images/full/365645/as-virus-kills-navajos-in-their-homes-tribal-women-provide-lifeline.jpg?w=600?w=650").await.is_ok());
-      assert!(is_image_content_type(&client,
-                                    "https://twitter.com/BenjaminNorton/status/1259922424272957440?s=20"
-      )
-        .await.is_err()
-      );
-    });
-  }
-
-  #[test]
-  fn test_espeak() {
-    assert!(captcha_espeak_wav_base64("WxRt2l").is_ok())
-  }
-
-  // These helped with testing
-  // #[test]
-  // fn test_iframely() {
-  //   let res = fetch_iframely(client, "https://www.redspark.nu/?p=15341").await;
-  //   assert!(res.is_ok());
-  // }
-
-  // #[test]
-  // fn test_pictshare() {
-  //   let res = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpg");
-  //   assert!(res.is_ok());
-  //   let res_other = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpgaoeu");
-  //   assert!(res_other.is_err());
-  // }
-}
index d14e006e2fb75be8fedc938804d68dd58e1b7a29..dea60c0a77aa5ae78bf8715547cb0219bf62620f 100644 (file)
@@ -16,17 +16,14 @@ use diesel::{
   PgConnection,
 };
 use lazy_static::lazy_static;
+use lemmy_api::match_websocket_operation;
+use lemmy_apub::activity_queue::create_activity_queue;
 use lemmy_db::get_database_url_from_env;
 use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
-use lemmy_server::{
-  apub::activity_queue::create_activity_queue,
-  code_migrations::run_advanced_migrations,
-  routes::*,
-  websocket::chat_server::ChatServer,
-  LemmyContext,
-};
+use lemmy_server::{code_migrations::run_advanced_migrations, routes::*};
 use lemmy_structs::blocking;
 use lemmy_utils::{settings::Settings, LemmyError, CACHE_CONTROL_REGEX};
+use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
 use reqwest::Client;
 use std::sync::Arc;
 use tokio::sync::Mutex;
@@ -77,6 +74,7 @@ async fn main() -> Result<(), LemmyError> {
   let chat_server = ChatServer::startup(
     pool.clone(),
     rate_limiter.clone(),
+    |c, i, o, d| Box::pin(match_websocket_operation(c, i, o, d)),
     Client::default(),
     activity_queue.clone(),
   )
@@ -84,7 +82,7 @@ async fn main() -> Result<(), LemmyError> {
 
   // Create Http server with websocket support
   HttpServer::new(move || {
-    let context = LemmyContext::new(
+    let context = LemmyContext::create(
       pool.clone(),
       chat_server.to_owned(),
       Client::default(),
index 7e019168b5251f18c3ceb60807a92237d8c07d04..7a8ddbf1ec8042516c4abea2195bfef27bcb03e6 100644 (file)
@@ -1,7 +1,8 @@
-use crate::{api::Perform, LemmyContext};
 use actix_web::{error::ErrorBadRequest, *};
+use lemmy_api::Perform;
 use lemmy_rate_limit::RateLimit;
 use lemmy_structs::{comment::*, community::*, post::*, site::*, user::*};
+use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 
 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
index 2a0c81b2351e58265edd4e70073bc9b74817b7cc..36cfb85184b19d5f171d7c401463ef330cd1d7a0 100644 (file)
@@ -1,4 +1,6 @@
-use crate::apub::{
+use actix_web::*;
+use http_signature_normalization_actix::digest::middleware::VerifyDigest;
+use lemmy_apub::{
   comment::get_apub_comment,
   community::*,
   inbox::{community_inbox::community_inbox, shared_inbox::shared_inbox, user_inbox::user_inbox},
@@ -6,8 +8,6 @@ use crate::apub::{
   user::*,
   APUB_JSON_CONTENT_TYPE,
 };
-use actix_web::*;
-use http_signature_normalization_actix::digest::middleware::VerifyDigest;
 use lemmy_utils::settings::Settings;
 use sha2::{Digest, Sha256};
 
index 9669bfcc0523c9650d9f3a416ad0ec5165521b1e..2c36ac2335a4ad7c97cf1c348bfa004bf7401ca7 100644 (file)
@@ -1,8 +1,8 @@
-use crate::{api::claims::Claims, LemmyContext};
 use actix_web::{error::ErrorBadRequest, *};
 use anyhow::anyhow;
 use chrono::{DateTime, NaiveDateTime, Utc};
 use diesel::PgConnection;
+use lemmy_api::claims::Claims;
 use lemmy_db::{
   comment_view::{ReplyQueryBuilder, ReplyView},
   community::Community,
@@ -15,6 +15,7 @@ use lemmy_db::{
 };
 use lemmy_structs::blocking;
 use lemmy_utils::{settings::Settings, utils::markdown_to_html, LemmyError};
+use lemmy_websocket::LemmyContext;
 use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder};
 use serde::Deserialize;
 use std::str::FromStr;
index 15c5a23575c3b5a87be8e25f4d692cf9ee3599aa..984151c429c333fe05eaeea65c9b236029da9d00 100644 (file)
@@ -1,9 +1,10 @@
-use crate::{version, LemmyContext};
 use actix_web::{body::Body, error::ErrorBadRequest, *};
 use anyhow::anyhow;
+use lemmy_api::version;
 use lemmy_db::site_view::SiteView;
 use lemmy_structs::blocking;
 use lemmy_utils::{apub::get_apub_protocol_string, settings::Settings, LemmyError};
+use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index 53a87b124df6c85b3ebdd6b1e05cac845a73e953..bef94e6f9bca5476dc55e4258b2b507715db0c63 100644 (file)
@@ -1,38 +1,21 @@
-use crate::LemmyContext;
 use actix_web::{error::ErrorBadRequest, web::Query, *};
 use anyhow::anyhow;
 use lemmy_db::{community::Community, user::User_};
-use lemmy_structs::blocking;
+use lemmy_structs::{blocking, WebFingerLink, WebFingerResponse};
 use lemmy_utils::{
   settings::Settings,
   LemmyError,
   WEBFINGER_COMMUNITY_REGEX,
   WEBFINGER_USER_REGEX,
 };
-use serde::{Deserialize, Serialize};
+use lemmy_websocket::LemmyContext;
+use serde::Deserialize;
 
 #[derive(Deserialize)]
 pub struct Params {
   resource: String,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
-pub struct WebFingerResponse {
-  pub subject: String,
-  pub aliases: Vec<String>,
-  pub links: Vec<WebFingerLink>,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct WebFingerLink {
-  pub rel: Option<String>,
-  #[serde(rename(serialize = "type", deserialize = "type"))]
-  pub type_: Option<String>,
-  pub href: Option<String>,
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub template: Option<String>,
-}
-
 pub fn config(cfg: &mut web::ServiceConfig) {
   if Settings::get().federation.enabled {
     cfg.route(
index aaa7ef37aead80dd841467b11baba14bc80e06a6..9bfd6ca14778f83ef9d7234972a3b250dae79178 100644 (file)
@@ -1,9 +1,12 @@
-use crate::{websocket::chat_server::ChatServer, LemmyContext};
 use actix::prelude::*;
 use actix_web::*;
 use actix_web_actors::ws;
-use lemmy_structs::websocket::{Connect, Disconnect, StandardMessage, WSMessage};
 use lemmy_utils::utils::get_ip;
+use lemmy_websocket::{
+  chat_server::ChatServer,
+  messages::{Connect, Disconnect, StandardMessage, WSMessage},
+  LemmyContext,
+};
 use log::{debug, error, info};
 use std::time::{Duration, Instant};
 
diff --git a/src/websocket/mod.rs b/src/websocket/mod.rs
deleted file mode 100644 (file)
index e892f78..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod chat_server;
-pub mod handlers;