refactor: remove livechat related code and dependencies
ZhenYi committed
Deleted lib/auth/src/handlers/livechat_token.rs lib/auth/src/handlers/livechat_token.rs +0 −32
@@ -1,32 +0,0 @@
1use axum::extract::State;
2use export::rest::{AppResponseData, NoData};
3use serde::Serialize;
4use session::Session;
5use utoipa::ToSchema;
6
7use crate::errors::ApiError;
8use crate::services::AuthService;
9use session::share::session::require_uid;
10
11#[derive(Debug, Serialize, ToSchema)]
12pub struct LivechatTokenResp {
13 pub token: Option<String>,
14}
15
16#[utoipa::path(
17 post,
18 path = "/auth/livechat/token",
19 tag = "auth",
20 responses(
21 (status = 200, description = "livechat token issued", body = AppResponseData<LivechatTokenResp>),
22 (status = 401, description = "unauthorized", body = AppResponseData<NoData>)
23 )
24)]
25pub async fn livechat_token(
26 State(service): State<AuthService>,
27 session: Session,
28) -> Result<AppResponseData<LivechatTokenResp>, ApiError> {
29 let uid = require_uid(&session)?;
30 let token = service.issue_livechat_token(uid).await?;
31 Ok(AppResponseData::ok(LivechatTokenResp { token }))
32}
Modified lib/auth/src/handlers/mod.rs lib/auth/src/handlers/mod.rs +0 −1 View lib/auth/src/handlers/mod.rs
@@ -19,7 +19,6 @@
1919pub mod list_agreements;
2020pub mod list_notifications;
2121pub mod list_ssh_keys;
22pub mod livechat_token;
2322pub mod login;
2423pub mod login_2fa;
2524pub mod logout;
Deleted lib/auth/src/services/livechat.rs lib/auth/src/services/livechat.rs +0 −21
@@ -1,21 +0,0 @@
1use uuid::Uuid;
2
3use super::AuthService;
4use crate::errors::AuthError;
5
6impl AuthService {
7 pub async fn issue_livechat_token(&self, uid: Uuid) -> Result<Option<String>, AuthError> {
8 let Some(ref mut lc) = self.state.livechat.clone() else {
9 return Ok(None);
10 };
11
12 let request = lc::proto_gen::livechat::auth::IssueTokenRequest {
13 identity: uid.to_string(),
14 scope: "chat".into(),
15 ttl_seconds: 86400,
16 };
17
18 let resp = lc.auth_mut().issue_token(request).await?;
19 Ok(Some(resp.token))
20 }
21}
Modified lib/auth/src/services/login.rs lib/auth/src/services/login.rs +0 −16 View lib/auth/src/services/login.rs
@@ -33,8 +33,6 @@
3333 pub user: UserPublic,
3434 pub needs_2fa: bool,
3535 pub challenge: Option<String>,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 pub livechat_token: Option<String>,
3836}
3937
4038#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
@@ -113,7 +111,6 @@
113111 user: UserPublic::from(&user),
114112 needs_2fa: true,
115113 challenge: Some(Uuid::now_v7().to_string()),
116 livechat_token: None,
117114 });
118115 }
119116
@@ -279,23 +276,10 @@
279276 active.updated_at = Set(now);
280277 let _ = active.update(db.write()).await;
281278
282 let livechat_token = match self.issue_livechat_token(user.uid).await {
283 Ok(Some(token)) => {
284 tracing::debug!("issued livechat token for user {}", user.uid);
285 Some(token)
286 }
287 Ok(None) => None,
288 Err(e) => {
289 tracing::warn!(error = %e, "failed to issue livechat token");
290 None
291 }
292 };
293
294279 Ok(LoginResp {
295280 user: UserPublic::from(user),
296281 needs_2fa: false,
297282 challenge: None,
298 livechat_token,
299283 })
300284 }
301285
Modified lib/auth/src/services/mod.rs lib/auth/src/services/mod.rs +0 −1 View lib/auth/src/services/mod.rs
@@ -15,7 +15,6 @@
1515pub mod agreements;
1616pub mod deletion;
1717pub mod email;
18pub mod livechat;
1918pub mod login;
2019pub mod logout;
2120pub mod notifications;
Modified lib/auth/src/errors.rs lib/auth/src/errors.rs +0 −6 View lib/auth/src/errors.rs
@@ -81,12 +81,6 @@
8181 msg.contains("unique") || msg.contains("duplicate") || msg.contains("23505")
8282}
8383
84impl From<lc::Error> for AuthError {
85 fn from(error: lc::Error) -> Self {
86 Self::Internal(format!("livechat error: {error}"))
87 }
88}
89
9084impl From<redis::RedisError> for AuthError {
9185 fn from(error: redis::RedisError) -> Self {
9286 Self::Internal(format!("redis error: {error}"))
Modified lib/auth/src/routes.rs lib/auth/src/routes.rs +0 −2 View lib/auth/src/routes.rs
@@ -23,7 +23,6 @@
2323use crate::handlers::list_agreements::list_agreements;
2424use crate::handlers::list_notifications::list_notifications;
2525use crate::handlers::list_ssh_keys::list_ssh_keys;
26use crate::handlers::livechat_token::livechat_token;
2726use crate::handlers::login::login;
2827use crate::handlers::login_2fa::login_2fa;
2928use crate::handlers::logout::logout;
@@ -119,7 +118,6 @@
119118 .route("/deletion", get(deletion_status).post(request_deletion))
120119 .route("/deletion/cancel", post(cancel_deletion))
121120 .route("/suspension", get(active_suspension))
122 .route("/auth/livechat/token", post(livechat_token))
123121 .route_layer(middleware::from_fn_with_state(service, auth_guard));
124122
125123 public.merge(authed)
Modified lib/auth/Cargo.toml lib/auth/Cargo.toml +0 −1 View lib/auth/Cargo.toml
@@ -22,7 +22,6 @@
2222sha1 = { workspace = true }
2323uuid = { workspace = true }
2424hkdf = { workspace = true }
25lc = { workspace = true }
2625time = { workspace = true }
2726argon2 = { workspace = true }
2827aes-gcm = { workspace = true }
Modified lib/config/src/lib.rs lib/config/src/lib.rs +0 −4 View lib/config/src/lib.rs
@@ -7,7 +7,6 @@
77pub mod git;
88pub mod githost;
99pub mod issues;
10pub mod livechat;
1110pub mod pow;
1211pub mod redis;
1312pub mod s3;
@@ -30,7 +29,6 @@
3029use crate::git::GitConfig;
3130use crate::githost::GithostConfig;
3231use crate::issues::IssueConfig;
33use crate::livechat::LivechatConfig;
3432use crate::pow::PowConfig;
3533use crate::redis::RedisConfig;
3634use crate::s3::S3Config;
@@ -59,7 +57,6 @@
5957 pub email_queue: EmailQueueConfig,
6058 pub apihost: ApihostConfig,
6159 pub githost: GithostConfig,
62 pub livechat: LivechatConfig,
6360}
6461
6562impl AppConfig {
@@ -79,7 +76,6 @@
7976 .map_err(ConfigError::Validation)?;
8077 self.apihost.is_valid().map_err(ConfigError::Validation)?;
8178 self.githost.is_valid().map_err(ConfigError::Validation)?;
82 self.livechat.is_valid().map_err(ConfigError::Validation)?;
8379 Ok(())
8480 }
8581}
Deleted lib/config/src/livechat.rs lib/config/src/livechat.rs +0 −58
@@ -1,58 +0,0 @@
1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize)]
4#[serde(default)]
5pub struct LivechatConfig {
6 pub enabled: Option<bool>,
7 pub endpoint: Option<String>,
8 pub request_timeout_secs: Option<u64>,
9 pub tls_ca_path: Option<String>,
10 pub tls_cert_path: Option<String>,
11 pub tls_key_path: Option<String>,
12}
13
14impl LivechatConfig {
15 pub fn enabled(&self) -> bool {
16 self.enabled.unwrap_or(true)
17 }
18
19 pub fn endpoint(&self) -> &str {
20 self.endpoint.as_deref().unwrap_or("")
21 }
22
23 pub fn request_timeout_secs(&self) -> u64 {
24 self.request_timeout_secs.unwrap_or(30)
25 }
26
27 pub fn tls_ca_path(&self) -> Option<&str> {
28 self.tls_ca_path.as_deref().filter(|s| !s.is_empty())
29 }
30
31 pub fn tls_cert_path(&self) -> Option<&str> {
32 self.tls_cert_path.as_deref().filter(|s| !s.is_empty())
33 }
34
35 pub fn tls_key_path(&self) -> Option<&str> {
36 self.tls_key_path.as_deref().filter(|s| !s.is_empty())
37 }
38
39 pub fn is_valid(&self) -> Result<(), String> {
40 if !self.enabled() {
41 return Ok(());
42 }
43 let endpoint = self
44 .endpoint
45 .as_deref()
46 .filter(|s| !s.is_empty())
47 .ok_or_else(|| "livechat.endpoint must be set when enabled".to_string())?;
48 if !(endpoint.starts_with("http://") || endpoint.starts_with("https://")) {
49 return Err(format!(
50 "livechat.endpoint must start with http:// or https://, got {endpoint:?}"
51 ));
52 }
53 if matches!(self.request_timeout_secs, Some(0)) {
54 return Err("livechat.request_timeout_secs must be greater than 0".to_string());
55 }
56 Ok(())
57 }
58}
Deleted lib/config/src/mailbaby.rs lib/config/src/mailbaby.rs +0 −212
@@ -1,212 +0,0 @@
1use std::time::Duration;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum MailbabyChannel {
8 #[default]
9 Rest,
10 Grpc,
11}
12
13impl MailbabyChannel {
14 pub fn parse(value: &str) -> Option<Self> {
15 if value.eq_ignore_ascii_case("rest") {
16 Some(Self::Rest)
17 } else if value.eq_ignore_ascii_case("grpc") {
18 Some(Self::Grpc)
19 } else {
20 None
21 }
22 }
23}
24
25#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(rename_all = "snake_case")]
27pub enum MailbabyAuthScheme {
28 #[default]
29 Header,
30 Bearer,
31 Query,
32}
33
34impl MailbabyAuthScheme {
35 pub fn parse(value: &str) -> Option<Self> {
36 if value.eq_ignore_ascii_case("header") {
37 Some(Self::Header)
38 } else if value.eq_ignore_ascii_case("bearer") {
39 Some(Self::Bearer)
40 } else if value.eq_ignore_ascii_case("query") {
41 Some(Self::Query)
42 } else {
43 None
44 }
45 }
46}
47
48#[derive(Debug, Clone, Default, Serialize, Deserialize)]
49#[serde(default)]
50pub struct MailbabyConfig {
51 pub enabled: Option<bool>,
52 pub channel: Option<MailbabyChannel>,
53 pub url: Option<String>,
54 pub api_key: Option<String>,
55 pub auth_scheme: Option<MailbabyAuthScheme>,
56 pub api_key_header: Option<String>,
57 pub account: Option<String>,
58 pub from_address: Option<String>,
59 pub from_name: Option<String>,
60 pub reply_to: Option<String>,
61 pub request_timeout_secs: Option<u64>,
62}
63
64impl MailbabyConfig {
65 pub fn new(url: impl Into<String>) -> Self {
66 Self {
67 url: Some(url.into()),
68 ..Self::default()
69 }
70 }
71
72 pub fn with_enabled(mut self, enabled: bool) -> Self {
73 self.enabled = Some(enabled);
74 self
75 }
76
77 pub fn with_channel(mut self, channel: MailbabyChannel) -> Self {
78 self.channel = Some(channel);
79 self
80 }
81
82 pub fn with_api_key(mut self, key: impl Into<String>) -> Self {
83 self.api_key = Some(key.into());
84 self
85 }
86
87 pub fn with_auth_scheme(mut self, scheme: MailbabyAuthScheme) -> Self {
88 self.auth_scheme = Some(scheme);
89 self
90 }
91
92 pub fn with_api_key_header(mut self, header: impl Into<String>) -> Self {
93 self.api_key_header = Some(header.into());
94 self
95 }
96
97 pub fn with_account(mut self, account: impl Into<String>) -> Self {
98 self.account = Some(account.into());
99 self
100 }
101
102 pub fn with_from_address(mut self, address: impl Into<String>) -> Self {
103 self.from_address = Some(address.into());
104 self
105 }
106
107 pub fn with_from_name(mut self, name: impl Into<String>) -> Self {
108 self.from_name = Some(name.into());
109 self
110 }
111
112 pub fn with_reply_to(mut self, address: impl Into<String>) -> Self {
113 self.reply_to = Some(address.into());
114 self
115 }
116
117 pub fn with_request_timeout_secs(mut self, secs: u64) -> Self {
118 self.request_timeout_secs = Some(secs);
119 self
120 }
121
122 pub fn enabled(&self) -> bool {
123 self.enabled.unwrap_or(true)
124 }
125
126 pub fn channel(&self) -> MailbabyChannel {
127 self.channel.unwrap_or_default()
128 }
129
130 pub fn url(&self) -> &str {
131 self.url.as_deref().unwrap_or("")
132 }
133
134 pub fn api_key(&self) -> Option<&str> {
135 self.api_key.as_deref().filter(|s| !s.is_empty())
136 }
137
138 pub fn auth_scheme(&self) -> MailbabyAuthScheme {
139 self.auth_scheme.unwrap_or_default()
140 }
141
142 pub fn api_key_header(&self) -> Option<&str> {
143 self.api_key_header.as_deref().filter(|s| !s.is_empty())
144 }
145
146 pub fn account(&self) -> Option<&str> {
147 self.account.as_deref().filter(|s| !s.is_empty())
148 }
149
150 pub fn from_address(&self) -> Option<&str> {
151 self.from_address.as_deref().filter(|s| !s.is_empty())
152 }
153
154 pub fn from_name(&self) -> Option<&str> {
155 self.from_name.as_deref().filter(|s| !s.is_empty())
156 }
157
158 pub fn reply_to(&self) -> Option<&str> {
159 self.reply_to.as_deref().filter(|s| !s.is_empty())
160 }
161
162 pub fn request_timeout(&self) -> Duration {
163 Duration::from_secs(self.request_timeout_secs.unwrap_or(30))
164 }
165
166 pub fn validate(&self) -> Result<(), String> {
167 if !self.enabled() {
168 return Ok(());
169 }
170
171 let url = self
172 .url
173 .as_deref()
174 .filter(|s| !s.is_empty())
175 .ok_or_else(|| "mailbaby.url must be set when enabled".to_string())?;
176 if !(url.starts_with("http://") || url.starts_with("https://")) {
177 return Err(format!(
178 "mailbaby.url must start with http:// or https://, got {url:?}"
179 ));
180 }
181
182 if self.channel() == MailbabyChannel::Grpc
183 && self.auth_scheme() == MailbabyAuthScheme::Query
184 {
185 return Err("mailbaby.auth_scheme = query is not supported over grpc".to_string());
186 }
187
188 if self.api_key.as_deref().is_some_and(|s| s.is_empty()) {
189 return Err("mailbaby.api_key must not be empty".to_string());
190 }
191 if self.api_key_header.as_deref().is_some_and(|s| s.is_empty()) {
192 return Err("mailbaby.api_key_header must not be empty".to_string());
193 }
194
195 for (name, value) in [
196 ("account", self.account.as_deref()),
197 ("from_address", self.from_address.as_deref()),
198 ("from_name", self.from_name.as_deref()),
199 ("reply_to", self.reply_to.as_deref()),
200 ] {
201 if value.is_some_and(|v| v.is_empty()) {
202 return Err(format!("mailbaby.{name} must not be empty"));
203 }
204 }
205
206 if matches!(self.request_timeout_secs, Some(0)) {
207 return Err("mailbaby.request_timeout_secs must be greater than 0".to_string());
208 }
209
210 Ok(())
211 }
212}
No newline at end of file
Modified lib/export/src/lib.rs lib/export/src/lib.rs +0 −20 View lib/export/src/lib.rs
@@ -5,12 +5,10 @@
55pub mod storage;
66
77use std::sync::Arc;
8use std::time::Duration;
98
109use config::AppConfig;
1110pub use database::{AppDatabase, DatabaseRole};
1211pub use error::ExportError;
13pub use lc::LivechatClient;
1412pub use redis::{AppRedis, RedisConnection};
1513pub use storage::AppStorage;
1614
@@ -23,7 +21,6 @@
2321 pub storage: Arc<AppStorage>,
2422 pub email: EmailService,
2523 pub config: AppConfig,
26 pub livechat: Option<LivechatClient>,
2724}
2825
2926impl AppState {
@@ -47,29 +44,12 @@
4744 .await;
4845 let email = builder.build().await?;
4946
50 let livechat = if config.livechat.enabled() {
51 let timeout = Duration::from_secs(config.livechat.request_timeout_secs());
52 match LivechatClient::connect_with_timeout(config.livechat.endpoint(), timeout).await {
53 Ok(client) => {
54 tracing::info!("connected to livechat at {}", config.livechat.endpoint());
55 Some(client)
56 }
57 Err(e) => {
58 tracing::warn!(error = %e, "failed to connect to livechat, continuing without it");
59 None
60 }
61 }
62 } else {
63 None
64 };
65
6647 Ok(Self {
6748 database,
6849 redis,
6950 storage,
7051 email,
7152 config,
72 livechat,
7353 })
7454 }
7555}
Modified lib/export/Cargo.toml lib/export/Cargo.toml +0 −1 View lib/export/Cargo.toml
@@ -5,7 +5,6 @@
55
66[dependencies]
77config = { workspace = true }
8lc = { workspace = true }
98storage = { workspace = true }
109sea-orm = { workspace = true }
1110redis = { workspace = true }
Deleted lib/lc/proto/auth.proto lib/lc/proto/auth.proto +0 −31
@@ -1,31 +0,0 @@
1syntax = "proto3";
2
3package livechat.auth;
4
5service Auth {
6 rpc IssueToken(IssueTokenRequest) returns (IssueTokenResponse);
7 rpc VerifyToken(VerifyTokenRequest) returns (VerifyTokenResponse);
8}
9
10message IssueTokenRequest {
11 string identity = 1;
12 string scope = 2;
13 int64 ttl_seconds = 3;
14}
15
16message IssueTokenResponse {
17 string token = 1;
18 int64 expires_at = 2;
19}
20
21message VerifyTokenRequest {
22 string token = 1;
23 string expected_scope = 2;
24}
25
26message VerifyTokenResponse {
27 bool valid = 1;
28 string identity = 2;
29 string scope = 3;
30 int64 expires_at = 4;
31}
No newline at end of file
Deleted lib/lc/proto/dm.proto lib/lc/proto/dm.proto +0 −68
@@ -1,68 +0,0 @@
1syntax = "proto3";
2package livechat.dm;
3
4import "room.proto";
5
6service DirectMessageService {
7 rpc OpenDm (OpenDmRequest) returns (DmRoomResponse);
8 rpc ListDms (ListDmsRequest) returns (ListDmsResponse);
9 rpc SendDmMessage (SendDmMessageRequest) returns (MessageResponse);
10 rpc FetchDmHistory (FetchDmHistoryRequest) returns (FetchDmHistoryResponse);
11 rpc CloseDm (CloseDmRequest) returns (CloseDmResponse);
12}
13
14message OpenDmRequest {
15 string user_id = 1;
16 string peer_user_id = 2;
17}
18
19message ListDmsRequest {
20 string user_id = 1;
21}
22
23message SendDmMessageRequest {
24 string user_id = 1;
25 string channel_id = 2;
26 livechat.room.SendMessage message = 3;
27}
28
29message FetchDmHistoryRequest {
30 string user_id = 1;
31 string channel_id = 2;
32 optional string before = 3;
33 optional string after = 4;
34 optional int64 before_seq = 5;
35 optional int64 after_seq = 6;
36 optional uint32 limit = 7;
37}
38
39message CloseDmRequest {
40 string user_id = 1;
41 string channel_id = 2;
42}
43
44message DmRoomResponse {
45 livechat.room.Room room = 1;
46}
47
48message MessageResponse {
49 livechat.room.Message message = 1;
50}
51
52message ListDmsResponse {
53 repeated DmChannelSummary dms = 1;
54}
55
56message FetchDmHistoryResponse {
57 repeated livechat.room.Message messages = 1;
58}
59
60message CloseDmResponse {
61 string channel_id = 1;
62}
63
64message DmChannelSummary {
65 livechat.room.Room room = 1;
66 string peer_user_id = 2;
67 livechat.room.Message last_message = 3;
68}
No newline at end of file
Deleted lib/lc/proto/member.proto lib/lc/proto/member.proto +0 −59
@@ -1,59 +0,0 @@
1syntax = "proto3";
2
3package livechat.member;
4
5service MemberService {
6 rpc JoinRoom(JoinRoomRequest) returns (MemberResponse);
7 rpc LeaveRoom(LeaveRoomRequest) returns (LeaveRoomResponse);
8 rpc ListMembers(ListMembersRequest) returns (ListMembersResponse);
9 rpc GetMember(GetMemberRequest) returns (MemberResponse);
10 rpc SetMemberRoles(SetMemberRolesRequest) returns (MemberResponse);
11}
12
13message Member {
14 string room_id = 1;
15 string user_id = 2;
16 optional string nick = 3;
17 repeated string roles = 4;
18 int64 joined_at = 5;
19}
20
21message JoinRoomRequest {
22 string user_id = 1;
23 string room_id = 2;
24 optional string nick = 3;
25 repeated string roles = 4;
26}
27
28message LeaveRoomRequest {
29 string room_id = 1;
30 string user_id = 2;
31}
32
33message GetMemberRequest {
34 string room_id = 1;
35 string user_id = 2;
36}
37
38message ListMembersRequest {
39 string room_id = 1;
40}
41
42message SetMemberRolesRequest {
43 string room_id = 1;
44 string user_id = 2;
45 repeated string roles = 3;
46}
47
48message MemberResponse {
49 Member member = 1;
50}
51
52message ListMembersResponse {
53 repeated Member members = 1;
54}
55
56message LeaveRoomResponse {
57 string room_id = 1;
58 string user_id = 2;
59}
No newline at end of file
Deleted lib/lc/proto/room.proto lib/lc/proto/room.proto +0 −138
@@ -1,138 +0,0 @@
1syntax = "proto3";
2
3package livechat.room;
4
5service RoomService {
6 rpc CreateRoom(CreateRoomRequest) returns (RoomResponse);
7 rpc ModifyRoom(ModifyRoomRequest) returns (RoomResponse);
8 rpc DeleteRoom(DeleteRoomRequest) returns (DeleteRoomResponse);
9 rpc GetRoom(GetRoomRequest) returns (RoomResponse);
10 rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse);
11 rpc SetOverwrite(SetOverwriteRequest) returns (SetOverwriteResponse);
12}
13
14enum RoomKind {
15 ROOM_KIND_UNSPECIFIED = 0;
16 ROOM_KIND_TEXT = 1;
17 ROOM_KIND_VOICE = 2;
18 ROOM_KIND_STAGE = 3;
19 ROOM_KIND_NEWS = 4;
20 ROOM_KIND_THREAD = 5;
21 ROOM_KIND_CATEGORY = 6;
22 ROOM_KIND_DIRECT_MESSAGE = 8;
23 ROOM_KIND_UNKNOWN = 7;
24}
25
26message PermissionOverwrite {
27 string id = 1;
28 int32 type = 2;
29 string allow = 3;
30 string deny = 4;
31}
32
33message Room {
34 string id = 1;
35 RoomKind kind = 2;
36 optional int32 position = 4;
37 repeated PermissionOverwrite permission_overwrites = 5;
38 optional string name = 6;
39 optional string topic = 7;
40 optional bool nsfw = 8;
41 optional string last_message_id = 9;
42 optional uint32 bitrate = 10;
43 optional uint32 user_limit = 11;
44 optional string parent_id = 12;
45 optional uint32 rate_limit_per_user = 13;
46 optional string owner_id = 14;
47 optional string pair_hash = 15;
48}
49
50message CreateRoomRequest {
51 string user_id = 1;
52 RoomKind kind = 2;
53 optional string name = 4;
54 optional string topic = 5;
55 optional bool nsfw = 6;
56 optional int32 position = 7;
57 optional uint32 bitrate = 8;
58 optional uint32 user_limit = 9;
59 optional string parent_id = 10;
60 optional uint32 rate_limit_per_user = 11;
61}
62
63message ModifyRoomRequest {
64 string user_id = 1;
65 string room_id = 2;
66 optional string name = 3;
67 optional string topic = 4;
68 optional bool nsfw = 5;
69 optional int32 position = 6;
70 optional uint32 bitrate = 7;
71 optional uint32 user_limit = 8;
72 optional string parent_id = 9;
73 optional uint32 rate_limit_per_user = 10;
74}
75
76message DeleteRoomRequest {
77 string user_id = 1;
78 string room_id = 2;
79}
80
81message GetRoomRequest {
82 string user_id = 1;
83 string room_id = 2;
84}
85
86message ListRoomsRequest {
87 string user_id = 1;
88}
89
90message SetOverwriteRequest {
91 string user_id = 1;
92 string room_id = 2;
93 PermissionOverwrite overwrite = 3;
94}
95
96message RoomResponse {
97 Room room = 1;
98}
99
100message ListRoomsResponse {
101 repeated Room rooms = 1;
102}
103
104message DeleteRoomResponse {
105 string room_id = 1;
106}
107
108message SetOverwriteResponse {
109 string room_id = 1;
110}
111
112message Message {
113 string id = 1;
114 string room_id = 2;
115 string author_id = 3;
116 optional string content = 4;
117 optional string timestamp = 5;
118 optional string edited_timestamp = 6;
119 bool tts = 7;
120 bool mention_everyone = 8;
121 repeated string mention_user_ids = 9;
122 repeated string mention_roles = 10;
123 repeated string mention_room_ids = 11;
124 bool pinned = 12;
125 optional string webhook_id = 13;
126 optional uint64 flags = 14;
127 optional int64 seq = 15;
128}
129
130message SendMessage {
131 optional string content = 1;
132 optional bool tts = 2;
133 optional bool mention_everyone = 3;
134 repeated string mention_user_ids = 4;
135 repeated string mention_roles = 5;
136 optional string nonce = 6;
137 optional uint64 flags = 7;
138}
No newline at end of file
Deleted lib/lc/src/auth.rs lib/lc/src/auth.rs +0 −31
@@ -1,31 +0,0 @@
1use crate::proto_gen::livechat::auth::{
2 IssueTokenRequest, IssueTokenResponse, VerifyTokenRequest, VerifyTokenResponse,
3 auth_client::AuthClient,
4};
5
6#[derive(Clone)]
7pub struct Client {
8 inner: AuthClient<tonic::transport::Channel>,
9}
10
11impl Client {
12 pub fn new(channel: tonic::transport::Channel) -> Self {
13 Self {
14 inner: AuthClient::new(channel),
15 }
16 }
17
18 pub async fn issue_token(
19 &mut self,
20 request: IssueTokenRequest,
21 ) -> Result<IssueTokenResponse, crate::Error> {
22 Ok(self.inner.issue_token(request).await?.into_inner())
23 }
24
25 pub async fn verify_token(
26 &mut self,
27 request: VerifyTokenRequest,
28 ) -> Result<VerifyTokenResponse, crate::Error> {
29 Ok(self.inner.verify_token(request).await?.into_inner())
30 }
31}
Deleted lib/lc/src/dm.rs lib/lc/src/dm.rs +0 −52
@@ -1,52 +0,0 @@
1use crate::proto_gen::livechat::dm::{
2 CloseDmRequest, FetchDmHistoryRequest, ListDmsRequest, OpenDmRequest, SendDmMessageRequest,
3 direct_message_service_client::DirectMessageServiceClient,
4};
5
6#[derive(Clone)]
7pub struct Client {
8 inner: DirectMessageServiceClient<tonic::transport::Channel>,
9}
10
11impl Client {
12 pub fn new(channel: tonic::transport::Channel) -> Self {
13 Self {
14 inner: DirectMessageServiceClient::new(channel),
15 }
16 }
17
18 pub async fn open_dm(
19 &mut self,
20 request: OpenDmRequest,
21 ) -> Result<crate::proto_gen::livechat::dm::DmRoomResponse, crate::Error> {
22 Ok(self.inner.open_dm(request).await?.into_inner())
23 }
24
25 pub async fn list_dms(
26 &mut self,
27 request: ListDmsRequest,
28 ) -> Result<crate::proto_gen::livechat::dm::ListDmsResponse, crate::Error> {
29 Ok(self.inner.list_dms(request).await?.into_inner())
30 }
31
32 pub async fn send_dm_message(
33 &mut self,
34 request: SendDmMessageRequest,
35 ) -> Result<crate::proto_gen::livechat::dm::MessageResponse, crate::Error> {
36 Ok(self.inner.send_dm_message(request).await?.into_inner())
37 }
38
39 pub async fn fetch_dm_history(
40 &mut self,
41 request: FetchDmHistoryRequest,
42 ) -> Result<crate::proto_gen::livechat::dm::FetchDmHistoryResponse, crate::Error> {
43 Ok(self.inner.fetch_dm_history(request).await?.into_inner())
44 }
45
46 pub async fn close_dm(
47 &mut self,
48 request: CloseDmRequest,
49 ) -> Result<crate::proto_gen::livechat::dm::CloseDmResponse, crate::Error> {
50 Ok(self.inner.close_dm(request).await?.into_inner())
51 }
52}
Deleted lib/lc/src/lib.rs lib/lc/src/lib.rs +0 −105
@@ -1,105 +0,0 @@
1pub mod proto_gen {
2 pub mod livechat {
3 pub mod auth {
4 tonic::include_proto!("livechat.auth");
5 }
6 pub mod room {
7 tonic::include_proto!("livechat.room");
8 }
9 pub mod member {
10 tonic::include_proto!("livechat.member");
11 }
12 pub mod dm {
13 tonic::include_proto!("livechat.dm");
14 }
15 }
16}
17
18pub mod auth;
19pub mod dm;
20pub mod member;
21pub mod room;
22
23use std::time::Duration;
24use tonic::transport::{Channel, Endpoint};
25
26#[derive(Debug, thiserror::Error)]
27pub enum Error {
28 #[error("gRPC error: {0}")]
29 Grpc(#[from] tonic::Status),
30 #[error("transport error: {0}")]
31 Transport(#[from] tonic::transport::Error),
32}
33
34#[derive(Clone)]
35pub struct LivechatClient {
36 channel: Channel,
37 auth: auth::Client,
38 room: room::Client,
39 member: member::Client,
40 dm: dm::Client,
41}
42
43impl LivechatClient {
44 pub async fn connect(endpoint: impl Into<String>) -> Result<Self, Error> {
45 let channel = Endpoint::from_shared(endpoint.into())?.connect().await?;
46 Ok(Self::from_channel(channel))
47 }
48
49 pub async fn connect_with_timeout(
50 endpoint: impl Into<String>,
51 timeout: Duration,
52 ) -> Result<Self, Error> {
53 let channel = Endpoint::from_shared(endpoint.into())?
54 .timeout(timeout)
55 .connect()
56 .await?;
57 Ok(Self::from_channel(channel))
58 }
59
60 pub fn from_channel(channel: Channel) -> Self {
61 Self {
62 channel: channel.clone(),
63 auth: auth::Client::new(channel.clone()),
64 room: room::Client::new(channel.clone()),
65 member: member::Client::new(channel.clone()),
66 dm: dm::Client::new(channel),
67 }
68 }
69
70 pub fn channel(&self) -> &Channel {
71 &self.channel
72 }
73
74 pub fn auth(&self) -> &auth::Client {
75 &self.auth
76 }
77
78 pub fn auth_mut(&mut self) -> &mut auth::Client {
79 &mut self.auth
80 }
81
82 pub fn room(&self) -> &room::Client {
83 &self.room
84 }
85
86 pub fn room_mut(&mut self) -> &mut room::Client {
87 &mut self.room
88 }
89
90 pub fn member(&self) -> &member::Client {
91 &self.member
92 }
93
94 pub fn member_mut(&mut self) -> &mut member::Client {
95 &mut self.member
96 }
97
98 pub fn dm(&self) -> &dm::Client {
99 &self.dm
100 }
101
102 pub fn dm_mut(&mut self) -> &mut dm::Client {
103 &mut self.dm
104 }
105}
Deleted lib/lc/src/member.rs lib/lc/src/member.rs +0 −52
@@ -1,52 +0,0 @@
1use crate::proto_gen::livechat::member::{
2 GetMemberRequest, JoinRoomRequest, LeaveRoomRequest, ListMembersRequest, MemberResponse,
3 SetMemberRolesRequest, member_service_client::MemberServiceClient,
4};
5
6#[derive(Clone)]
7pub struct Client {
8 inner: MemberServiceClient<tonic::transport::Channel>,
9}
10
11impl Client {
12 pub fn new(channel: tonic::transport::Channel) -> Self {
13 Self {
14 inner: MemberServiceClient::new(channel),
15 }
16 }
17
18 pub async fn join_room(
19 &mut self,
20 request: JoinRoomRequest,
21 ) -> Result<MemberResponse, crate::Error> {
22 Ok(self.inner.join_room(request).await?.into_inner())
23 }
24
25 pub async fn leave_room(
26 &mut self,
27 request: LeaveRoomRequest,
28 ) -> Result<crate::proto_gen::livechat::member::LeaveRoomResponse, crate::Error> {
29 Ok(self.inner.leave_room(request).await?.into_inner())
30 }
31
32 pub async fn list_members(
33 &mut self,
34 request: ListMembersRequest,
35 ) -> Result<crate::proto_gen::livechat::member::ListMembersResponse, crate::Error> {
36 Ok(self.inner.list_members(request).await?.into_inner())
37 }
38
39 pub async fn get_member(
40 &mut self,
41 request: GetMemberRequest,
42 ) -> Result<MemberResponse, crate::Error> {
43 Ok(self.inner.get_member(request).await?.into_inner())
44 }
45
46 pub async fn set_member_roles(
47 &mut self,
48 request: SetMemberRolesRequest,
49 ) -> Result<MemberResponse, crate::Error> {
50 Ok(self.inner.set_member_roles(request).await?.into_inner())
51 }
52}
Deleted lib/lc/src/room.rs lib/lc/src/room.rs +0 −59
@@ -1,59 +0,0 @@
1use crate::proto_gen::livechat::room::{
2 CreateRoomRequest, DeleteRoomRequest, GetRoomRequest, ListRoomsRequest, ModifyRoomRequest,
3 RoomResponse, SetOverwriteRequest, room_service_client::RoomServiceClient,
4};
5
6#[derive(Clone)]
7pub struct Client {
8 inner: RoomServiceClient<tonic::transport::Channel>,
9}
10
11impl Client {
12 pub fn new(channel: tonic::transport::Channel) -> Self {
13 Self {
14 inner: RoomServiceClient::new(channel),
15 }
16 }
17
18 pub async fn create_room(
19 &mut self,
20 request: CreateRoomRequest,
21 ) -> Result<RoomResponse, crate::Error> {
22 Ok(self.inner.create_room(request).await?.into_inner())
23 }
24
25 pub async fn modify_room(
26 &mut self,
27 request: ModifyRoomRequest,
28 ) -> Result<RoomResponse, crate::Error> {
29 Ok(self.inner.modify_room(request).await?.into_inner())
30 }
31
32 pub async fn delete_room(
33 &mut self,
34 request: DeleteRoomRequest,
35 ) -> Result<crate::proto_gen::livechat::room::DeleteRoomResponse, crate::Error> {
36 Ok(self.inner.delete_room(request).await?.into_inner())
37 }
38
39 pub async fn get_room(
40 &mut self,
41 request: GetRoomRequest,
42 ) -> Result<RoomResponse, crate::Error> {
43 Ok(self.inner.get_room(request).await?.into_inner())
44 }
45
46 pub async fn list_rooms(
47 &mut self,
48 request: ListRoomsRequest,
49 ) -> Result<crate::proto_gen::livechat::room::ListRoomsResponse, crate::Error> {
50 Ok(self.inner.list_rooms(request).await?.into_inner())
51 }
52
53 pub async fn set_overwrite(
54 &mut self,
55 request: SetOverwriteRequest,
56 ) -> Result<crate::proto_gen::livechat::room::SetOverwriteResponse, crate::Error> {
57 Ok(self.inner.set_overwrite(request).await?.into_inner())
58 }
59}
Deleted lib/lc/build.rs lib/lc/build.rs +0 −20
@@ -1,20 +0,0 @@
1fn main() -> Result<(), Box<dyn std::error::Error>> {
2 println!("cargo:rerun-if-changed=proto/auth.proto");
3 println!("cargo:rerun-if-changed=proto/room.proto");
4 println!("cargo:rerun-if-changed=proto/member.proto");
5 println!("cargo:rerun-if-changed=proto/dm.proto");
6 tonic_prost_build::configure()
7 .file_descriptor_set_path(
8 std::path::PathBuf::from(std::env::var("OUT_DIR")?).join("livechat_descriptor.bin"),
9 )
10 .compile_protos(
11 &[
12 "proto/auth.proto",
13 "proto/room.proto",
14 "proto/member.proto",
15 "proto/dm.proto",
16 ],
17 &["proto/"],
18 )?;
19 Ok(())
20}
Deleted lib/lc/Cargo.toml lib/lc/Cargo.toml +0 −16
@@ -1,16 +0,0 @@
1[package]
2name = "lc"
3version.workspace = true
4edition.workspace = true
5
6[dependencies]
7tonic = { workspace = true, features = ["transport", "tls-native-roots"] }
8tonic-prost = { workspace = true }
9prost = { workspace = true }
10serde = { workspace = true, features = ["derive"] }
11serde_json = { workspace = true }
12thiserror = { workspace = true }
13tracing = { workspace = true }
14
15[build-dependencies]
16tonic-prost-build = { workspace = true }
No newline at end of file
Modified lib/models/src/room/rooms.rs lib/models/src/room/rooms.rs +0 −14 View lib/models/src/room/rooms.rs
@@ -41,20 +41,6 @@
4141 DirectMessage,
4242}
4343
44impl RoomKind {
45 pub fn to_proto_value(&self) -> i32 {
46 match self {
47 RoomKind::GuildRoom | RoomKind::Text | RoomKind::GroupDm => 1,
48 RoomKind::Voice => 2,
49 RoomKind::Stage => 3,
50 RoomKind::News => 4,
51 RoomKind::Thread => 5,
52 RoomKind::Category => 6,
53 RoomKind::DirectMessage | RoomKind::Dm => 8,
54 }
55 }
56}
57
5844#[sea_orm::model]
5945#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
6046#[sea_orm(table_name = "rooms")]
Modified lib/space/src/services/members.rs lib/space/src/services/members.rs +19 −31 View lib/space/src/services/members.rs
@@ -194,38 +194,26 @@
194194 .await?
195195 };
196196
197 if let Some(ref mut lc) = self.state.livechat.clone() {
198 let public_rooms = models::room::rooms::Entity::find()
199 .filter(models::room::rooms::Column::SpaceId.eq(space.id))
200 .filter(models::room::rooms::Column::IsPrivate.eq(false))
201 .filter(models::room::rooms::Column::IsActive.eq(true))
202 .all(self.db().read())
203 .await?;
197 let public_rooms = models::room::rooms::Entity::find()
198 .filter(models::room::rooms::Column::SpaceId.eq(space.id))
199 .filter(models::room::rooms::Column::IsPrivate.eq(false))
200 .filter(models::room::rooms::Column::IsActive.eq(true))
201 .all(self.db().read())
202 .await?;
204203
205 for room in &public_rooms {
206 let join_req = lc::proto_gen::livechat::member::JoinRoomRequest {
207 user_id: saved.user_id.to_string(),
208 room_id: room.id.to_string(),
209 nick: None,
210 roles: vec![],
211 };
212 if let Err(e) = lc.member_mut().join_room(join_req).await {
213 tracing::warn!(error = %e, room_id = %room.id, user_id = %saved.user_id, "failed to join member to livechat room");
214 }
215
216 let now = OffsetDateTime::now_utc();
217 let rm = models::room::room_members::ActiveModel {
218 room_id: Set(room.id),
219 user_id: Set(saved.user_id),
220 nick: Set(None),
221 joined_at: Set(now),
222 left_at: Set(None),
223 created_at: Set(now),
224 updated_at: Set(Some(now)),
225 };
226 if let Err(e) = rm.insert(self.db().write()).await {
227 tracing::warn!(error = %e, room_id = %room.id, user_id = %saved.user_id, "failed to create room_members record");
228 }
204 for room in &public_rooms {
205 let now = OffsetDateTime::now_utc();
206 let rm = models::room::room_members::ActiveModel {
207 room_id: Set(room.id),
208 user_id: Set(saved.user_id),
209 nick: Set(None),
210 joined_at: Set(now),
211 left_at: Set(None),
212 created_at: Set(now),
213 updated_at: Set(Some(now)),
214 };
215 if let Err(e) = rm.insert(self.db().write()).await {
216 tracing::warn!(error = %e, room_id = %room.id, user_id = %saved.user_id, "failed to create room_members record");
229217 }
230218 }
231219
Modified lib/space/src/services/rooms.rs lib/space/src/services/rooms.rs +0 −44 View lib/space/src/services/rooms.rs
@@ -1,5 +1,3 @@
1use lc::proto_gen::livechat::member::JoinRoomRequest;
2use lc::proto_gen::livechat::room::CreateRoomRequest;
31use models::room::room_members;
42use models::room::rooms::{self, RoomKind};
53use models::space::space_members::{self, MemberStatus};
@@ -198,38 +196,6 @@
198196 })
199197 .await?;
200198
201 if let Some(ref mut lc) = self.state.livechat.clone() {
202 let proto_kind = cmd.kind.to_proto_value();
203 let create_req = CreateRoomRequest {
204 user_id: caller.to_string(),
205 kind: proto_kind,
206 name: Some(name.to_string()),
207 topic: cmd.topic.clone(),
208 nsfw: Some(cmd.nsfw),
209 position: Some(position as i32),
210 bitrate: None,
211 user_limit: cmd.user_limit.map(|v| v as u32),
212 parent_id: cmd.parent_id.map(|id| id.to_string()),
213 rate_limit_per_user: cmd.rate_limit_per_user.map(|v| v as u32),
214 };
215
216 if let Err(e) = lc.room_mut().create_room(create_req).await {
217 tracing::warn!(error = %e, room_id = %room_id, "failed to create room on livechat");
218 }
219
220 for uid in &member_uids {
221 let join_req = JoinRoomRequest {
222 user_id: uid.to_string(),
223 room_id: room_id.to_string(),
224 nick: None,
225 roles: vec![],
226 };
227 if let Err(e) = lc.member_mut().join_room(join_req).await {
228 tracing::warn!(error = %e, room_id = %room_id, user_id = %uid, "failed to join member to livechat room");
229 }
230 }
231 }
232
233199 Ok(RoomDto::from(inserted))
234200 }
235201
@@ -262,16 +228,6 @@
262228 am.is_active = Set(false);
263229 am.updated_at = Set(now);
264230 am.update(self.db().write()).await?;
265
266 if let Some(ref mut lc) = self.state.livechat.clone() {
267 let req = lc::proto_gen::livechat::room::DeleteRoomRequest {
268 user_id: caller.to_string(),
269 room_id: room_id.to_string(),
270 };
271 if let Err(e) = lc.room_mut().delete_room(req).await {
272 tracing::warn!(error = %e, room_id = %room_id, "failed to delete room on livechat");
273 }
274 }
275231
276232 Ok(())
277233 }
Modified lib/space/src/errors.rs lib/space/src/errors.rs +0 −6 View lib/space/src/errors.rs
@@ -78,12 +78,6 @@
7878 }
7979}
8080
81impl From<lc::Error> for SpaceError {
82 fn from(error: lc::Error) -> Self {
83 Self::Internal(format!("livechat error: {error}"))
84 }
85}
86
8781impl From<serde_json::Error> for SpaceError {
8882 fn from(error: serde_json::Error) -> Self {
8983 Self::BadRequest(format!("invalid payload: {error}"))
Modified lib/space/Cargo.toml lib/space/Cargo.toml +0 −1 View lib/space/Cargo.toml
@@ -19,5 +19,4 @@
1919uuid = { workspace = true }
2020time = { workspace = true }
2121base64 = { workspace = true }
22lc = { workspace = true }
2322tracing = { workspace = true }
No newline at end of file
Modified Cargo.lock Cargo.lock +3 −242 View Cargo.lock
@@ -596,7 +596,6 @@
596596 "export",
597597 "hkdf",
598598 "hmac 0.13.0",
599 "lc",
600599 "maud",
601600 "models",
602601 "pow-solver",
@@ -2032,7 +2031,6 @@
20322031 "axum",
20332032 "config",
20342033 "email",
2035 "lc",
20362034 "redis",
20372035 "sea-orm",
20382036 "serde",
@@ -2163,12 +2161,6 @@
21632161]
21642162
21652163[[package]]
2166name = "fixedbitset"
2167version = "0.5.7"
2168source = "registry+https://github.com/rust-lang/crates.io-index"
2169checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
2170
2171[[package]]
21722164name = "flate2"
21732165version = "1.1.9"
21742166source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2198,12 +2190,6 @@
21982190
21992191[[package]]
22002192name = "foldhash"
2201version = "0.1.5"
2202source = "registry+https://github.com/rust-lang/crates.io-index"
2203checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
2204
2205[[package]]
2206name = "foldhash"
22072193version = "0.2.0"
22082194source = "registry+https://github.com/rust-lang/crates.io-index"
22092195checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
@@ -3630,25 +3616,6 @@
36303616]
36313617
36323618[[package]]
3633name = "h2"
3634version = "0.4.19"
3635source = "registry+https://github.com/rust-lang/crates.io-index"
3636checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
3637dependencies = [
3638 "atomic-waker",
3639 "bytes",
3640 "fnv",
3641 "futures-core",
3642 "futures-sink",
3643 "http 1.5.0",
3644 "indexmap",
3645 "slab",
3646 "tokio",
3647 "tokio-util",
3648 "tracing",
3649]
3650
3651[[package]]
36523619name = "half"
36533620version = "2.7.1"
36543621source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3699,15 +3666,6 @@
36993666version = "0.14.5"
37003667source = "registry+https://github.com/rust-lang/crates.io-index"
37013668checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
3702
3703[[package]]
3704name = "hashbrown"
3705version = "0.15.5"
3706source = "registry+https://github.com/rust-lang/crates.io-index"
3707checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
3708dependencies = [
3709 "foldhash 0.1.5",
3710]
37113669
37123670[[package]]
37133671name = "hashbrown"
@@ -3717,7 +3675,7 @@
37173675dependencies = [
37183676 "allocator-api2",
37193677 "equivalent",
3720 "foldhash 0.2.0",
3678 "foldhash",
37213679]
37223680
37233681[[package]]
@@ -3728,7 +3686,7 @@
37283686dependencies = [
37293687 "allocator-api2",
37303688 "equivalent",
3731 "foldhash 0.2.0",
3689 "foldhash",
37323690]
37333691
37343692[[package]]
@@ -3921,7 +3879,7 @@
39213879 "futures-channel",
39223880 "futures-core",
39233881 "futures-util",
3924 "h2 0.3.27",
3882 "h2",
39253883 "http 0.2.12",
39263884 "http-body 0.4.6",
39273885 "httparse",
@@ -3945,7 +3903,6 @@
39453903 "bytes",
39463904 "futures-channel",
39473905 "futures-core",
3948 "h2 0.4.19",
39493906 "http 1.5.0",
39503907 "http-body 1.1.0",
39513908 "httparse",
@@ -3954,7 +3911,6 @@
39543911 "pin-project-lite",
39553912 "smallvec",
39563913 "tokio",
3957 "want",
39583914]
39593915
39603916[[package]]
@@ -3969,19 +3925,6 @@
39693925]
39703926
39713927[[package]]
3972name = "hyper-timeout"
3973version = "0.5.2"
3974source = "registry+https://github.com/rust-lang/crates.io-index"
3975checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
3976dependencies = [
3977 "hyper 1.11.0",
3978 "hyper-util",
3979 "pin-project-lite",
3980 "tokio",
3981 "tower-service",
3982]
3983
3984[[package]]
39853928name = "hyper-tls"
39863929version = "0.5.0"
39873930source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4001,17 +3944,12 @@
40013944checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
40023945dependencies = [
40033946 "bytes",
4004 "futures-channel",
4005 "futures-util",
40063947 "http 1.5.0",
40073948 "http-body 1.1.0",
40083949 "hyper 1.11.0",
4009 "libc",
40103950 "pin-project-lite",
4011 "socket2 0.6.5",
40123951 "tokio",
40133952 "tower-service",
4014 "tracing",
40153953]
40163954
40173955[[package]]
@@ -4738,20 +4676,6 @@
47384676]
47394677
47404678[[package]]
4741name = "lc"
4742version = "1.0.0"
4743dependencies = [
4744 "prost",
4745 "serde",
4746 "serde_json",
4747 "thiserror 2.0.20",
4748 "tonic",
4749 "tonic-prost",
4750 "tonic-prost-build",
4751 "tracing",
4752]
4753
4754[[package]]
47554679name = "lettre"
47564680version = "0.11.23"
47574681source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5199,12 +5123,6 @@
51995123]
52005124
52015125[[package]]
5202name = "multimap"
5203version = "0.10.1"
5204source = "registry+https://github.com/rust-lang/crates.io-index"
5205checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
5206
5207[[package]]
52085126name = "native-tls"
52095127version = "0.2.18"
52105128source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5798,17 +5716,6 @@
57985716]
57995717
58005718[[package]]
5801name = "petgraph"
5802version = "0.8.3"
5803source = "registry+https://github.com/rust-lang/crates.io-index"
5804checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
5805dependencies = [
5806 "fixedbitset",
5807 "hashbrown 0.15.5",
5808 "indexmap",
5809]
5810
5811[[package]]
58125719name = "pgvector"
58135720version = "0.4.2"
58145721source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6028,16 +5935,6 @@
60285935]
60295936
60305937[[package]]
6031name = "prettyplease"
6032version = "0.2.37"
6033source = "registry+https://github.com/rust-lang/crates.io-index"
6034checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
6035dependencies = [
6036 "proc-macro2",
6037 "syn 2.0.119",
6038]
6039
6040[[package]]
60415938name = "primefield"
60425939version = "0.14.0"
60435940source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6116,59 +6013,6 @@
61166013]
61176014
61186015[[package]]
6119name = "prost"
6120version = "0.14.4"
6121source = "registry+https://github.com/rust-lang/crates.io-index"
6122checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1"
6123dependencies = [
6124 "bytes",
6125 "prost-derive",
6126]
6127
6128[[package]]
6129name = "prost-build"
6130version = "0.14.4"
6131source = "registry+https://github.com/rust-lang/crates.io-index"
6132checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042"
6133dependencies = [
6134 "heck 0.5.0",
6135 "itertools 0.14.0",
6136 "log 0.4.33",
6137 "multimap",
6138 "petgraph",
6139 "prettyplease",
6140 "prost",
6141 "prost-types",
6142 "pulldown-cmark",
6143 "pulldown-cmark-to-cmark",
6144 "regex",
6145 "syn 2.0.119",
6146 "tempfile",
6147]
6148
6149[[package]]
6150name = "prost-derive"
6151version = "0.14.4"
6152source = "registry+https://github.com/rust-lang/crates.io-index"
6153checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
6154dependencies = [
6155 "anyhow",
6156 "itertools 0.14.0",
6157 "proc-macro2",
6158 "quote",
6159 "syn 2.0.119",
6160]
6161
6162[[package]]
6163name = "prost-types"
6164version = "0.14.4"
6165source = "registry+https://github.com/rust-lang/crates.io-index"
6166checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a"
6167dependencies = [
6168 "prost",
6169]
6170
6171[[package]]
61726016name = "psm"
61736017version = "0.1.32"
61746018source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6217,15 +6061,6 @@
62176061checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
62186062
62196063[[package]]
6220name = "pulldown-cmark-to-cmark"
6221version = "22.0.1"
6222source = "registry+https://github.com/rust-lang/crates.io-index"
6223checksum = "ab1ad36992cead65f02aa399a373a42730922f1525d988172634fdefdecb8a60"
6224dependencies = [
6225 "pulldown-cmark",
6226]
6227
6228[[package]]
62296064name = "quick-xml"
62306065version = "0.28.2"
62316066source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7456,7 +7291,6 @@
74567291 "config",
74577292 "email",
74587293 "export",
7459 "lc",
74607294 "models",
74617295 "sea-orm",
74627296 "serde",
@@ -8258,76 +8092,6 @@
82588092checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
82598093
82608094[[package]]
8261name = "tonic"
8262version = "0.14.6"
8263source = "registry+https://github.com/rust-lang/crates.io-index"
8264checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
8265dependencies = [
8266 "async-trait",
8267 "axum",
8268 "base64 0.22.1",
8269 "bytes",
8270 "h2 0.4.19",
8271 "http 1.5.0",
8272 "http-body 1.1.0",
8273 "http-body-util",
8274 "hyper 1.11.0",
8275 "hyper-timeout",
8276 "hyper-util",
8277 "percent-encoding 2.3.2",
8278 "pin-project",
8279 "rustls-native-certs",
8280 "socket2 0.6.5",
8281 "sync_wrapper",
8282 "tokio",
8283 "tokio-rustls",
8284 "tokio-stream",
8285 "tower",
8286 "tower-layer",
8287 "tower-service",
8288 "tracing",
8289]
8290
8291[[package]]
8292name = "tonic-build"
8293version = "0.14.6"
8294source = "registry+https://github.com/rust-lang/crates.io-index"
8295checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322"
8296dependencies = [
8297 "prettyplease",
8298 "proc-macro2",
8299 "quote",
8300 "syn 2.0.119",
8301]
8302
8303[[package]]
8304name = "tonic-prost"
8305version = "0.14.6"
8306source = "registry+https://github.com/rust-lang/crates.io-index"
8307checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0"
8308dependencies = [
8309 "bytes",
8310 "prost",
8311 "tonic",
8312]
8313
8314[[package]]
8315name = "tonic-prost-build"
8316version = "0.14.6"
8317source = "registry+https://github.com/rust-lang/crates.io-index"
8318checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27"
8319dependencies = [
8320 "prettyplease",
8321 "proc-macro2",
8322 "prost-build",
8323 "prost-types",
8324 "quote",
8325 "syn 2.0.119",
8326 "tempfile",
8327 "tonic-build",
8328]
8329
8330[[package]]
83318095name = "tower"
83328096version = "0.5.3"
83338097source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -8335,12 +8099,9 @@
83358099dependencies = [
83368100 "futures-core",
83378101 "futures-util",
8338 "indexmap",
83398102 "pin-project-lite",
8340 "slab",
83418103 "sync_wrapper",
83428104 "tokio",
8343 "tokio-util",
83448105 "tower-layer",
83458106 "tower-service",
83468107 "tracing",
Modified Cargo.toml Cargo.toml +0 −6 View Cargo.toml
@@ -14,7 +14,6 @@
1414 "lib/issues",
1515 "lib/git",
1616 "lib/webapi",
17 "lib/lc",
1817 "app/apihost",
1918 "app/githost",
2019 "app/mails",
@@ -45,7 +44,6 @@
4544issues = { path = "lib/issues" }
4645git = { path = "lib/git" }
4746webapi = { path = "lib/webapi" }
48lc = { path = "lib/lc" }
4947
5048
5149
@@ -99,8 +97,4 @@
9997lettre = { version = "0.11", default-features = false, features = ["smtp-transport", "tokio1-rustls", "ring", "rustls-native-certs", "builder"] }
10098anyhow = "1"
10199tracing-subscriber = { version = "0.3", features = ["env-filter"] }
102tonic = "0.14"
103prost = "0.14"
104tonic-prost = "0.14"
105tonic-prost-build = "0.14"
106100