ui stuff
This commit is contained in:
parent
0d79b42072
commit
d1a68c635c
5 changed files with 384 additions and 94 deletions
126
src/db.rs
126
src/db.rs
|
|
@ -1,15 +1,18 @@
|
|||
use anyhow::{Result, anyhow};
|
||||
use chrono::{Duration, Utc};
|
||||
use sea_orm::{
|
||||
ActiveModelTrait, ActiveValue::Set, ColumnTrait, DatabaseConnection,
|
||||
Condition, DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect,
|
||||
ActiveModelTrait, ActiveValue::Set, ColumnTrait, Condition, DatabaseConnection,
|
||||
DatabaseTransaction, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect,
|
||||
TransactionTrait, sea_query::OnConflict,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
entity::{channels, direct_messages, guild_members, guilds, invites, messages, users},
|
||||
models::{BasicUser, Channel, DmConversation, DmMessageWithAuthor, Guild, Invite, MessageWithAuthor, User},
|
||||
models::{
|
||||
BasicUser, Channel, DmConversation, DmMessageWithAuthor, Guild, Invite, MessageWithAuthor,
|
||||
User,
|
||||
},
|
||||
};
|
||||
|
||||
pub const CHANNEL_KIND_TEXT: &str = "text";
|
||||
|
|
@ -42,7 +45,10 @@ pub async fn upsert_user_from_oidc(
|
|||
users::Column::DisplayName,
|
||||
users::Column::AvatarUrl,
|
||||
])
|
||||
.value(users::Column::UpdatedAt, sea_orm::sea_query::Expr::current_timestamp())
|
||||
.value(
|
||||
users::Column::UpdatedAt,
|
||||
sea_orm::sea_query::Expr::current_timestamp(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.exec_with_returning(db)
|
||||
|
|
@ -75,6 +81,15 @@ pub async fn list_guild_members(db: &DatabaseConnection, guild_id: Uuid) -> Resu
|
|||
.collect())
|
||||
}
|
||||
|
||||
pub async fn list_guild_member_ids(db: &DatabaseConnection, guild_id: Uuid) -> Result<Vec<Uuid>> {
|
||||
let rows = guild_members::Entity::find()
|
||||
.filter(guild_members::Column::GuildId.eq(guild_id))
|
||||
.all(db)
|
||||
.await?;
|
||||
|
||||
Ok(rows.into_iter().map(|m| m.user_id).collect())
|
||||
}
|
||||
|
||||
pub async fn list_guilds_for_user(db: &DatabaseConnection, user_id: Uuid) -> Result<Vec<Guild>> {
|
||||
let rows = guild_members::Entity::find()
|
||||
.filter(guild_members::Column::UserId.eq(user_id))
|
||||
|
|
@ -88,7 +103,11 @@ pub async fn list_guilds_for_user(db: &DatabaseConnection, user_id: Uuid) -> Res
|
|||
.collect())
|
||||
}
|
||||
|
||||
pub async fn create_guild(db: &DatabaseConnection, owner_user_id: Uuid, name: &str) -> Result<Guild> {
|
||||
pub async fn create_guild(
|
||||
db: &DatabaseConnection,
|
||||
owner_user_id: Uuid,
|
||||
name: &str,
|
||||
) -> Result<Guild> {
|
||||
let guild = guilds::Entity::insert(guilds::ActiveModel {
|
||||
id: Set(Uuid::new_v4()),
|
||||
name: Set(name.to_string()),
|
||||
|
|
@ -104,9 +123,12 @@ pub async fn create_guild(db: &DatabaseConnection, owner_user_id: Uuid, name: &s
|
|||
..Default::default()
|
||||
})
|
||||
.on_conflict(
|
||||
OnConflict::columns([guild_members::Column::GuildId, guild_members::Column::UserId])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
OnConflict::columns([
|
||||
guild_members::Column::GuildId,
|
||||
guild_members::Column::UserId,
|
||||
])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(db)
|
||||
.await?;
|
||||
|
|
@ -176,9 +198,12 @@ pub async fn join_invite(db: &DatabaseConnection, code: &str, user_id: Uuid) ->
|
|||
..Default::default()
|
||||
})
|
||||
.on_conflict(
|
||||
OnConflict::columns([guild_members::Column::GuildId, guild_members::Column::UserId])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
OnConflict::columns([
|
||||
guild_members::Column::GuildId,
|
||||
guild_members::Column::UserId,
|
||||
])
|
||||
.do_nothing()
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(&txn)
|
||||
.await?;
|
||||
|
|
@ -215,12 +240,18 @@ pub async fn create_channel(
|
|||
Ok(map_channel(channel))
|
||||
}
|
||||
|
||||
pub async fn get_channel_by_id(db: &DatabaseConnection, channel_id: Uuid) -> Result<Option<Channel>> {
|
||||
pub async fn get_channel_by_id(
|
||||
db: &DatabaseConnection,
|
||||
channel_id: Uuid,
|
||||
) -> Result<Option<Channel>> {
|
||||
let row = channels::Entity::find_by_id(channel_id).one(db).await?;
|
||||
Ok(row.map(map_channel))
|
||||
}
|
||||
|
||||
pub async fn list_channels_for_guild(db: &DatabaseConnection, guild_id: Uuid) -> Result<Vec<Channel>> {
|
||||
pub async fn list_channels_for_guild(
|
||||
db: &DatabaseConnection,
|
||||
guild_id: Uuid,
|
||||
) -> Result<Vec<Channel>> {
|
||||
let channels = channels::Entity::find()
|
||||
.filter(channels::Column::GuildId.eq(guild_id))
|
||||
.order_by_asc(channels::Column::CreatedAt)
|
||||
|
|
@ -230,7 +261,10 @@ pub async fn list_channels_for_guild(db: &DatabaseConnection, guild_id: Uuid) ->
|
|||
Ok(channels.into_iter().map(map_channel).collect())
|
||||
}
|
||||
|
||||
pub async fn list_voice_channels_for_guild(db: &DatabaseConnection, guild_id: Uuid) -> Result<Vec<Channel>> {
|
||||
pub async fn list_voice_channels_for_guild(
|
||||
db: &DatabaseConnection,
|
||||
guild_id: Uuid,
|
||||
) -> Result<Vec<Channel>> {
|
||||
let channels = channels::Entity::find()
|
||||
.filter(channels::Column::GuildId.eq(guild_id))
|
||||
.filter(channels::Column::Kind.eq(CHANNEL_KIND_VOICE))
|
||||
|
|
@ -241,7 +275,11 @@ pub async fn list_voice_channels_for_guild(db: &DatabaseConnection, guild_id: Uu
|
|||
Ok(channels.into_iter().map(map_channel).collect())
|
||||
}
|
||||
|
||||
pub async fn is_member_of_guild(db: &DatabaseConnection, guild_id: Uuid, user_id: Uuid) -> Result<bool> {
|
||||
pub async fn is_member_of_guild(
|
||||
db: &DatabaseConnection,
|
||||
guild_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> Result<bool> {
|
||||
let count = guild_members::Entity::find()
|
||||
.filter(guild_members::Column::GuildId.eq(guild_id))
|
||||
.filter(guild_members::Column::UserId.eq(user_id))
|
||||
|
|
@ -251,7 +289,10 @@ pub async fn is_member_of_guild(db: &DatabaseConnection, guild_id: Uuid, user_id
|
|||
Ok(count > 0)
|
||||
}
|
||||
|
||||
pub async fn guild_id_for_channel(db: &DatabaseConnection, channel_id: Uuid) -> Result<Option<Uuid>> {
|
||||
pub async fn guild_id_for_channel(
|
||||
db: &DatabaseConnection,
|
||||
channel_id: Uuid,
|
||||
) -> Result<Option<Uuid>> {
|
||||
let guild_id = channels::Entity::find_by_id(channel_id)
|
||||
.select_only()
|
||||
.column(channels::Column::GuildId)
|
||||
|
|
@ -267,18 +308,30 @@ pub async fn create_message(
|
|||
channel_id: Uuid,
|
||||
author_user_id: Uuid,
|
||||
body: &str,
|
||||
) -> Result<()> {
|
||||
messages::Entity::insert(messages::ActiveModel {
|
||||
) -> Result<MessageWithAuthor> {
|
||||
let model = messages::Entity::insert(messages::ActiveModel {
|
||||
id: Set(Uuid::new_v4()),
|
||||
channel_id: Set(channel_id),
|
||||
author_user_id: Set(author_user_id),
|
||||
body: Set(body.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.exec(db)
|
||||
.exec_with_returning(db)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
let user = users::Entity::find_by_id(author_user_id)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("author not found"))?;
|
||||
|
||||
Ok(MessageWithAuthor {
|
||||
id: model.id,
|
||||
channel_id: model.channel_id,
|
||||
author_user_id: model.author_user_id,
|
||||
author_display_name: user.display_name,
|
||||
body: model.body,
|
||||
created_at: model.created_at,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn list_messages(
|
||||
|
|
@ -317,18 +370,30 @@ pub async fn create_direct_message(
|
|||
sender_user_id: Uuid,
|
||||
recipient_user_id: Uuid,
|
||||
body: &str,
|
||||
) -> Result<()> {
|
||||
direct_messages::Entity::insert(direct_messages::ActiveModel {
|
||||
) -> Result<DmMessageWithAuthor> {
|
||||
let model = direct_messages::Entity::insert(direct_messages::ActiveModel {
|
||||
id: Set(Uuid::new_v4()),
|
||||
sender_user_id: Set(sender_user_id),
|
||||
recipient_user_id: Set(recipient_user_id),
|
||||
body: Set(body.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.exec(db)
|
||||
.exec_with_returning(db)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
let user = users::Entity::find_by_id(sender_user_id)
|
||||
.one(db)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("sender not found"))?;
|
||||
|
||||
Ok(DmMessageWithAuthor {
|
||||
id: model.id,
|
||||
author_user_id: model.sender_user_id,
|
||||
recipient_user_id: model.recipient_user_id,
|
||||
author_display_name: user.display_name,
|
||||
body: model.body,
|
||||
created_at: model.created_at,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn list_direct_messages(
|
||||
|
|
@ -385,7 +450,10 @@ pub async fn list_direct_messages(
|
|||
.collect())
|
||||
}
|
||||
|
||||
pub async fn list_dm_conversations(db: &DatabaseConnection, current_user_id: Uuid) -> Result<Vec<DmConversation>> {
|
||||
pub async fn list_dm_conversations(
|
||||
db: &DatabaseConnection,
|
||||
current_user_id: Uuid,
|
||||
) -> Result<Vec<DmConversation>> {
|
||||
let rows = direct_messages::Entity::find()
|
||||
.filter(
|
||||
Condition::any()
|
||||
|
|
@ -396,7 +464,8 @@ pub async fn list_dm_conversations(db: &DatabaseConnection, current_user_id: Uui
|
|||
.all(db)
|
||||
.await?;
|
||||
|
||||
let mut latest_by_peer = std::collections::HashMap::<Uuid, chrono::DateTime<chrono::FixedOffset>>::new();
|
||||
let mut latest_by_peer =
|
||||
std::collections::HashMap::<Uuid, chrono::DateTime<chrono::FixedOffset>>::new();
|
||||
for row in rows {
|
||||
let peer_id = if row.sender_user_id == current_user_id {
|
||||
row.recipient_user_id
|
||||
|
|
@ -496,7 +565,10 @@ fn validate_invite(invite: &invites::Model) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn increment_invite_use_count(txn: &DatabaseTransaction, invite: invites::Model) -> Result<()> {
|
||||
async fn increment_invite_use_count(
|
||||
txn: &DatabaseTransaction,
|
||||
invite: invites::Model,
|
||||
) -> Result<()> {
|
||||
let next_count = invite.use_count + 1;
|
||||
let mut active: invites::ActiveModel = invite.into();
|
||||
active.use_count = Set(next_count);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue