Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/http_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,16 +736,45 @@ async fn get_user_notes(
Ok(Json(notes))
}

/// SSE `data:` payload の union (#781 Phase 4)。discriminator は SSE の
/// `event:` フィールド (out-of-band) なので untagged oneOf として文書化する。
/// `event:` 名と variant の対応:
/// note/mention → StreamNote/StreamMentionEvent、note-updated →
/// StreamNoteUpdatedEvent、note-capture-updated → StreamNoteCaptureEvent、
/// notification → StreamNotificationEvent、main-{eventType} → StreamMainEvent、
/// chat → StreamChatMessageEvent、chat-deleted / chat-reacted / chat-unreacted →
/// StreamChatMessage{Deleted,Reacted,Unreacted}Event、status → StreamStatusEvent
#[derive(serde::Serialize, ToSchema)]
#[serde(untagged)]
#[allow(dead_code, clippy::large_enum_variant)] // OpenAPI ドキュメント専用の型
enum SseEventPayload {
Note(crate::streaming::StreamNoteEvent),
Notification(crate::streaming::StreamNotificationEvent),
Mention(crate::streaming::StreamMentionEvent),
Main(crate::streaming::StreamMainEvent),
NoteUpdated(crate::streaming::StreamNoteUpdatedEvent),
NoteCaptureUpdated(crate::streaming::StreamNoteCaptureEvent),
ChatMessage(crate::streaming::StreamChatMessageEvent),
ChatMessageDeleted(crate::streaming::StreamChatMessageDeletedEvent),
ChatMessageReacted(crate::streaming::StreamChatMessageReactedEvent),
ChatMessageUnreacted(crate::streaming::StreamChatMessageUnreactedEvent),
Status(crate::streaming::StreamStatusEvent),
}

#[utoipa::path(
get, path = "/api/events", tag = "events",
security(("bearer_auth" = [])),
params(SseQueryParams),
responses(
(status = 200,
description = "Server-sent event stream (`text/event-stream`). Each event \
carries an `event:` type and a JSON `data:` payload. OpenAPI cannot model \
a streaming body, so the schema is shown as a string.",
content_type = "text/event-stream", body = String),
carries an `event:` type and a JSON `data:` payload typed as \
`SseEventPayload` — the `event:` name selects the variant \
(`note` / `mention` / `note-updated` / `note-capture-updated` / \
`notification` / `main-{eventType}` / `chat` / `chat-deleted` / \
`chat-reacted` / `chat-unreacted` / `status`). \
The `type` query param filters by event-name prefix.",
content_type = "text/event-stream", body = SseEventPayload),
(status = 401, description = "Unauthorized", body = ApiErrorResponse),
)
)]
Expand Down
22 changes: 11 additions & 11 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,7 @@ pub struct Channel {
pub color: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct ChatMessage {
Expand All @@ -961,15 +961,15 @@ pub struct ChatMessage {
pub reactions: Vec<ChatMessageReaction>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct ChatMessageReaction {
pub user: Option<ChatReactionUser>,
pub reaction: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct ChatReactionUser {
Expand All @@ -980,7 +980,7 @@ pub struct ChatReactionUser {
pub avatar_url: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct ChatUser {
Expand All @@ -995,7 +995,7 @@ pub struct ChatUser {
pub avatar_decorations: Vec<AvatarDecoration>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct ChatRoom {
Expand Down Expand Up @@ -1082,7 +1082,7 @@ impl std::fmt::Debug for AuthResult {
/// Adjacent tagging (`updateType` + `body`) preserves the historical wire shape
/// `{ updateType: "reacted", body: { ... } }` so the JSON consumers read is
/// unchanged while the contract becomes typed end-to-end.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(tag = "updateType", content = "body", rename_all = "camelCase")]
pub enum NoteUpdateBody {
Expand Down Expand Up @@ -1110,7 +1110,7 @@ impl NoteUpdateBody {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct NoteReactedBody {
Expand All @@ -1123,15 +1123,15 @@ pub struct NoteReactedBody {
pub user_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(untagged)]
pub enum ReactionEmoji {
Custom { name: String, url: String },
Code(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct NoteUnreactedBody {
Expand All @@ -1140,7 +1140,7 @@ pub struct NoteUnreactedBody {
pub user_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct NotePollVotedBody {
Expand All @@ -1149,7 +1149,7 @@ pub struct NotePollVotedBody {
pub user_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct NoteDeletedBody {
Expand Down
26 changes: 14 additions & 12 deletions src/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl StreamEvent {
}

/// `stream-status` で報告する接続状態 (#781)。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "lowercase")]
pub enum StreamConnectionState {
Expand All @@ -179,16 +179,17 @@ pub enum StreamConnectionState {
Disconnected,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamNoteEvent {
pub account_id: String,
pub subscription_id: String,
#[schema(value_type = NormalizedNote)]
pub note: Arc<NormalizedNote>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamNotificationEvent {
Expand All @@ -197,16 +198,17 @@ pub struct StreamNotificationEvent {
pub notification: NormalizedNotification,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamMentionEvent {
pub account_id: String,
pub subscription_id: String,
#[schema(value_type = NormalizedNote)]
pub note: Arc<NormalizedNote>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamChatMessageEvent {
Expand All @@ -215,7 +217,7 @@ pub struct StreamChatMessageEvent {
pub message: ChatMessage,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamChatMessageDeletedEvent {
Expand All @@ -235,7 +237,7 @@ struct ChatReactionWsBody {
user: Option<ChatReactionUser>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamChatMessageReactedEvent {
Expand All @@ -246,7 +248,7 @@ pub struct StreamChatMessageReactedEvent {
pub user: Option<ChatReactionUser>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamChatMessageUnreactedEvent {
Expand All @@ -257,7 +259,7 @@ pub struct StreamChatMessageUnreactedEvent {
pub user: Option<ChatReactionUser>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamMainEvent {
Expand All @@ -267,7 +269,7 @@ pub struct StreamMainEvent {
pub body: Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamNoteUpdatedEvent {
Expand All @@ -279,7 +281,7 @@ pub struct StreamNoteUpdatedEvent {
pub update: NoteUpdateBody,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamNoteCaptureEvent {
Expand All @@ -289,7 +291,7 @@ pub struct StreamNoteCaptureEvent {
pub update: NoteUpdateBody,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct StreamStatusEvent {
Expand Down
Loading