use axum::Router; use axum::routing::{delete, get, post, put}; use crate::handlers::attachments::{ create_attachment, download_attachment, finalize_attachment, get_attachment, }; use crate::handlers::bookmarks::{ create_bookmark, delete_bookmark, list_bookmarks, update_bookmark, }; use crate::handlers::dms::{close_dm, list_dms, open_dm}; use crate::handlers::drafts::{get_draft, list_my_drafts, upsert_draft}; use crate::handlers::emojis::{delete_emoji, emoji_image, list_emojis, upload_emoji}; use crate::handlers::messages::{ bulk_delete_messages, delete_message, forward_message, get_message, list_message_history, list_messages, list_pins, send_message, set_message_pin, update_message, }; use crate::handlers::presence::{get_presence, list_space_presences, set_presence}; use crate::handlers::reactions::{add_reaction, list_reactions, remove_reaction}; use crate::handlers::read_state::{ get_read_state, list_space_read_states, mark_read, mark_thread_read, }; use crate::handlers::reminders::{cancel_reminder, create_reminder, list_reminders}; use crate::handlers::rooms::{ accept_room_invite, add_room_members, create_room_invite, get_room, join_room, leave_room, list_room_members, list_space_rooms, reject_room_invite, update_room, }; use crate::handlers::settings::{get_room_setting, update_room_setting}; use crate::handlers::threads::{ create_thread, follow_thread, get_thread, list_my_threads, list_threads, unfollow_thread, update_thread, }; use crate::handlers::voice::{ approve_hand, cancel_hand, deny_hand, get_voice_layout, kick_participant, list_hands, livekit_webhook, moderate_mute, raise_hand, revoke_hand, save_voice_layout, start_recording, stop_recording, voice_config, voice_participants, voice_space_states, voice_token, }; use crate::handlers::webhooks::{create_webhook, delete_webhook, list_webhooks, post_via_webhook}; use crate::services::service::ChatService; use crate::share::guard::chat_guard; pub fn router( service: ChatService, space_service: space::services::service::SpaceService, ) -> Router { let space_room_routes = Router::new() .route( "/chat/spaces/{space_name}/rooms", axum::routing::post(space::handlers::create_room::create_room), ) .route( "/chat/rooms/{room_id}", delete(space::handlers::delete_room::delete_room), ) .with_state(space_service) .route_layer(axum::middleware::from_fn_with_state( service.clone(), chat_guard, )); let guarded = Router::new() .route("/chat/spaces/{space_name}/rooms", get(list_space_rooms)) .route("/chat/rooms/{room_id}", get(get_room).patch(update_room)) .route( "/chat/rooms/{room_id}/members/@me", axum::routing::put(join_room).delete(leave_room), ) .route( "/chat/rooms/{room_id}/members", get(list_room_members).post(add_room_members), ) .route( "/chat/rooms/{room_id}/members/{user_id}", get(crate::handlers::room_admin::get_room_member) .patch(crate::handlers::room_admin::update_room_member) .delete(crate::handlers::room_admin::kick_room_member), ) .route( "/chat/rooms/{room_id}/bans", get(crate::handlers::room_admin::list_room_bans) .post(crate::handlers::room_admin::ban_room_member), ) .route( "/chat/rooms/{room_id}/bans/{user_id}", delete(crate::handlers::room_admin::unban_room_member), ) .route( "/chat/rooms/{room_id}/owner", put(crate::handlers::room_admin::transfer_room_owner), ) .route( "/chat/rooms/{room_id}/invites", post(create_room_invite).get(crate::handlers::rooms::list_room_invites), ) .route( "/chat/rooms/{room_id}/invites/{invite_id}", delete(crate::handlers::rooms::revoke_room_invite), ) .route("/chat/invites/accept", post(accept_room_invite)) .route("/chat/invites/reject", post(reject_room_invite)) .route( "/chat/rooms/{room_id}/messages", get(list_messages).post(send_message), ) .route( "/chat/rooms/{room_id}/messages/bulk-delete", post(bulk_delete_messages), ) .route( "/chat/rooms/{room_id}/messages/{message_id}", get(get_message) .patch(update_message) .delete(delete_message), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/pin", axum::routing::put(set_message_pin), ) .route("/chat/rooms/{room_id}/pins", get(list_pins)) .route( "/chat/rooms/{room_id}/messages/{message_id}/forward", post(forward_message), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/history", get(list_message_history), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/threads", post(create_thread), ) .route("/chat/rooms/{room_id}/threads", get(list_threads)) .route("/chat/threads", get(list_my_threads)) .route( "/chat/threads/{thread_id}", get(get_thread).patch(update_thread), ) .route( "/chat/threads/{thread_id}/members/@me", axum::routing::put(follow_thread).delete(unfollow_thread), ) .route( "/chat/threads/{thread_id}/read-state", axum::routing::put(mark_thread_read), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/reactions", get(list_reactions), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/reactions/@me", axum::routing::put(add_reaction).delete(remove_reaction), ) .route( "/chat/rooms/{room_id}/messages/{message_id}/reminders", post(create_reminder), ) .route("/chat/reminders", get(list_reminders)) .route( "/chat/reminders/{reminder_id}", axum::routing::delete(cancel_reminder) .patch(crate::handlers::reminders::update_reminder), ) .route( "/chat/rooms/{room_id}/read-state", get(get_read_state).put(mark_read), ) .route( "/chat/spaces/{space_name}/read-states", get(list_space_read_states), ) .route("/chat/dms", get(list_dms).post(open_dm)) .route("/chat/dms/{room_id}", axum::routing::delete(close_dm)) .route("/chat/attachments", post(create_attachment)) .route("/chat/attachments/{attachment_id}", get(get_attachment)) .route( "/chat/attachments/{attachment_id}/finalize", post(finalize_attachment), ) .route( "/chat/attachments/{attachment_id}/file", get(download_attachment), ) .route( "/chat/spaces/{space_name}/emojis", get(list_emojis).post(upload_emoji), ) .route( "/chat/spaces/{space_name}/emojis/{emoji_id}", get(crate::handlers::emojis::get_emoji).delete(delete_emoji), ) .route( "/chat/spaces/{space_name}/emojis/{emoji_id}/image", get(emoji_image), ) .route( "/chat/rooms/{room_id}/bookmarks", get(list_bookmarks).post(create_bookmark), ) .route( "/chat/rooms/{room_id}/bookmarks/{bookmark_id}", axum::routing::patch(update_bookmark).delete(delete_bookmark), ) .route( "/chat/rooms/{room_id}/draft", get(get_draft) .put(upsert_draft) .delete(crate::handlers::drafts::delete_draft), ) .route("/chat/drafts", get(list_my_drafts)) .route("/chat/presence", axum::routing::put(set_presence)) .route("/chat/users/{user_id}/presence", get(get_presence)) .route( "/chat/spaces/{space_name}/presences", get(list_space_presences), ) .route( "/chat/rooms/{room_id}/settings", get(get_room_setting).put(update_room_setting), ) .route( "/chat/rooms/{room_id}/webhooks", get(list_webhooks).post(create_webhook), ) .route( "/chat/rooms/{room_id}/webhooks/{webhook_id}", axum::routing::delete(delete_webhook).patch(crate::handlers::webhooks::update_webhook), ) .route( "/chat/rooms/{room_id}/outbound-webhooks", get(crate::handlers::webhooks::list_outbound_webhooks) .post(crate::handlers::webhooks::create_outbound_webhook), ) .route( "/chat/rooms/{room_id}/outbound-webhooks/{webhook_id}", axum::routing::patch(crate::handlers::webhooks::update_outbound_webhook) .delete(crate::handlers::webhooks::delete_outbound_webhook), ) .route("/chat/voice/config", get(voice_config)) .route("/chat/rooms/{room_id}/voice/token", post(voice_token)) .route( "/chat/rooms/{room_id}/voice/participants", get(voice_participants), ) .route( "/chat/rooms/{room_id}/voice/participants/{user_id}", delete(kick_participant), ) .route( "/chat/rooms/{room_id}/voice/participants/{user_id}/mute", post(moderate_mute), ) .route( "/chat/spaces/{space_name}/voice-states", get(voice_space_states), ) .route( "/chat/rooms/{room_id}/voice/layout", get(get_voice_layout).put(save_voice_layout), ) .route( "/chat/rooms/{room_id}/voice/hands", get(list_hands).post(raise_hand), ) .route("/chat/rooms/{room_id}/voice/hands/@me", delete(cancel_hand)) .route( "/chat/rooms/{room_id}/voice/hands/{user_id}/approve", post(approve_hand), ) .route( "/chat/rooms/{room_id}/voice/hands/{user_id}/deny", post(deny_hand), ) .route( "/chat/rooms/{room_id}/voice/hands/{user_id}/revoke", post(revoke_hand), ) .route( "/chat/rooms/{room_id}/voice/recording/start", post(start_recording), ) .route( "/chat/rooms/{room_id}/voice/recording/stop", post(stop_recording), ) .route_layer(axum::middleware::from_fn_with_state( service.clone(), chat_guard, )); let open = Router::new() .route("/chat/hooks/{token}", post(post_via_webhook)) .route("/chat/livekit/webhook", post(livekit_webhook)); guarded.merge(open).merge(space_room_routes) } /// 内部路由:只由服务间调用(`x-gitdata-service-key` 校验),不暴露给浏览器。 /// /// 连接生命周期是聊天在线态与推送"在线免打扰"的唯一写入点:事件通道由 /// KenEvent 负责,只有它知道某条 socket 何时建立、续期、断开。 pub fn internal_router(_service: ChatService) -> Router { Router::new() .route("/chat/connections", post(crate::handlers::connection::open)) .route( "/chat/connections/heartbeat", post(crate::handlers::connection::heartbeat), ) .route( "/chat/connections/close", post(crate::handlers::connection::close), ) }