use super::{render_error, ChatsAppQuery, PaginatedQuery}; use crate::{State, assets::initial_context, get_lang, get_user_from_token}; use axum::{ extract::{Path, Query}, response::{Html, IntoResponse, Redirect}, Extension, Json, }; use axum_extra::extract::CookieJar; use tetratto_core::model::{ channels::Message, communities_permissions::CommunityPermission, permissions::FinePermission, Error, }; use serde::Deserialize; #[derive(Deserialize)] pub struct RenderMessage { pub data: String, pub grouped: bool, } pub async fn redirect_request() -> impl IntoResponse { Redirect::to("/chats/0/0") } /// `/chats/{community}/{channel}` /// /// `/chats/0` is for channels the user is part of (not in a community) pub async fn app_request( jar: CookieJar, Extension(data): Extension, Path((selected_community, selected_channel)): Path<(usize, usize)>, Query(props): Query, ) -> impl IntoResponse { let data = data.read().await; let user = match get_user_from_token!(jar, data.0) { Some(ua) => ua, None => { return Err(Html( render_error(Error::NotAllowed, &jar, &data, &None).await, )); } }; let membership = match data .0 .get_membership_by_owner_community(user.id, selected_community) .await { Ok(m) => m, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; let can_manage_channels = membership.role.check(CommunityPermission::MANAGE_CHANNELS) | user.permissions.check(FinePermission::MANAGE_CHANNELS); let communities = match data.0.get_memberships_by_owner(user.id).await { Ok(p) => match data.0.fill_communities(p).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; if selected_community != 0 && selected_channel == 0 { let channels = match data.0.get_channels_by_community(selected_community).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; if let Some(channel) = channels.first() { return Ok(Html(format!( "", selected_community, channel.id, props.nav ))); } } let community = if selected_community != 0 { match data.0.get_community_by_id(selected_community).await { Ok(p) => Some(p), Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), } } else { None }; let channel = if selected_channel != 0 { match data.0.get_channel_by_id(selected_channel).await { Ok(p) => { if !p.check_read(user.id, Some(membership.role)) { return Err(Html( render_error(Error::NotAllowed, &jar, &data, &Some(user)).await, )); } Some(p) } Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), } } else { None }; let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user.clone())).await; context.insert("selected_community", &selected_community); context.insert("selected_channel", &selected_channel); context.insert("membership_role", &membership.role.bits()); context.insert("page", &props.page); context.insert("message", &props.message); context.insert( "can_manage_channels", &if selected_community == 0 { false } else { can_manage_channels }, ); context.insert( "can_manage_channel", &if selected_community == 0 { if let Some(ref channel) = channel { channel.members.contains(&user.id) | (channel.owner == user.id) } else { false } } else { can_manage_channels }, ); context.insert("community", &community); context.insert("channel", &channel); context.insert("communities", &communities); // return Ok(Html(data.1.render("chats/app.html", &context).unwrap())) } /// `/chats/{community}/{channel}/_stream` pub async fn stream_request( jar: CookieJar, Extension(data): Extension, Path((community, channel)): Path<(usize, usize)>, Query(props): Query, ) -> impl IntoResponse { let data = data.read().await; let user = match get_user_from_token!(jar, data.0) { Some(ua) => ua, None => { return Err(Html( render_error(Error::NotAllowed, &jar, &data, &None).await, )); } }; let ignore_users = crate::ignore_users_gen!(user!, data); let membership = match data .0 .get_membership_by_owner_community(user.id, community) .await { Ok(m) => m, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; let can_manage_messages = membership.role.check(CommunityPermission::MANAGE_MESSAGES) | user.permissions.check(FinePermission::MANAGE_MESSAGES); let messages = if props.message == 0 { match data .0 .get_messages_by_channel(channel, 24, props.page) .await { Ok(p) => match data.0.fill_messages(p, &ignore_users).await { Ok(p) => p, Err(e) => { return Err(Html(render_error(e, &jar, &data, &Some(user)).await)); } }, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), } } else { Vec::new() }; let message = if props.message == 0 { None } else { Some(match data.0.get_message_by_id(props.message).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }) }; let message_owner = if let Some(ref message) = message { Some(match data.0.get_user_by_id(message.owner).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }) } else { None }; let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user)).await; context.insert("messages", &messages); context.insert("message", &message); context.insert("message_owner", &message_owner); context.insert("can_manage_messages", &can_manage_messages); context.insert("page", &props.page); context.insert("community", &community); context.insert("channel", &channel); // return Ok(Html(data.1.render("chats/stream.html", &context).unwrap())) } /// `/chats/{community}/{channel}/_render` pub async fn message_request( jar: CookieJar, Extension(data): Extension, Path((community, channel)): Path<(usize, usize)>, Json(req): Json, ) -> impl IntoResponse { let data = data.read().await; let user = match get_user_from_token!(jar, data.0) { Some(ua) => ua, None => { return Err(Html( render_error(Error::NotAllowed, &jar, &data, &None).await, )); } }; let message: (String, Message) = match serde_json::from_str(&req.data) { Ok(m) => m, Err(e) => { return Err(Html( render_error(Error::MiscError(e.to_string()), &jar, &data, &Some(user)).await, )); } }; let message = message.1; let membership = match data .0 .get_membership_by_owner_community(user.id, community) .await { Ok(m) => m, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; let can_manage_messages = membership.role.check(CommunityPermission::MANAGE_MESSAGES) | user.permissions.check(FinePermission::MANAGE_MESSAGES); let owner = match data.0.get_user_by_id(message.owner).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user)).await; context.insert("can_manage_messages", &can_manage_messages); context.insert("message", &message); context.insert("user", &owner); context.insert("channel", &channel); context.insert("community", &community); context.insert("grouped", &req.grouped); // return Ok(Html(data.1.render("chats/message.html", &context).unwrap())) } /// `/chats/{community}/{channel/_channels` pub async fn channels_request( jar: CookieJar, Extension(data): Extension, Path((community, channel_id)): Path<(usize, usize)>, Query(props): Query, ) -> impl IntoResponse { let data = data.read().await; let user = match get_user_from_token!(jar, data.0) { Some(ua) => ua, None => { return Err(Html( render_error(Error::NotAllowed, &jar, &data, &None).await, )); } }; let channels = if community == 0 { match data.0.get_channels_by_user(user.id).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), } } else { match data.0.get_channels_by_community(community).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), } }; let channel = if channel_id != 0 { Some(match data.0.get_channel_by_id(channel_id).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }) } else { None }; let members = if community == 0 && channel.is_some() { let ignore_users = crate::ignore_users_gen!(user!, data); let mut channel = channel.as_ref().unwrap().clone(); channel.members.insert(0, channel.owner); // include the owner in the members list (at the start) Some( match data.0.fill_members(&channel.members, ignore_users).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }, ) } else { None }; let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user)).await; context.insert("channels", &channels); context.insert("page", &props.page); context.insert("members", &members); context.insert("channel", &channel); context.insert("selected_community", &community); context.insert("selected_channel", &channel_id); // return Ok(Html( data.1.render("chats/channels.html", &context).unwrap(), )) }