feat(social): add listening activity, shared rooms and modern chat
ci / api / api (push) Canceled after 0s
ci / module boundaries / boundaries (push) Canceled after 0s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Canceled after 11m29s
ci / db / db (push) Canceled after 11m22s
ci / mobile / mobile (Metro-бандл Android) (push) Canceled after 6m43s
ci / recommender / recommender (push) Canceled after 6m47s
ci / ts / ts (packages + web) (push) Canceled after 1s
ci / api / api (push) Canceled after 0s
ci / module boundaries / boundaries (push) Canceled after 0s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Canceled after 11m29s
ci / db / db (push) Canceled after 11m22s
ci / mobile / mobile (Metro-бандл Android) (push) Canceled after 6m43s
ci / recommender / recommender (push) Canceled after 6m47s
ci / ts / ts (packages + web) (push) Canceled after 1s
This commit is contained in:
1 parent
0a05bfe2cd
commit
11a16cd023
59 files changed
+5022
-542
No files matched your search
@@ -4,6 +4,139 @@
|
||||
*/
|
||||
|
||||
export interface paths {
|
||||
"/api/v1/me/social/recommendations": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put: operations["setFriendsRecommendations"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/listening": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getListeningState"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/listening/preferences": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put: operations["setListeningPreferences"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/listening/actions": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** @description Join requests target the host; invites target a guest and use the sender's own stream. Accept/decline/cancel target a request UUID. Leave/end target the room UUID. Automatic acceptance always respects the receiving user's admission policy. No control transfer. */
|
||||
post: operations["listeningAction"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/listening/state": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
/** @description Only the room owner's source device may publish. Monotonic sequence prevents stale updates; room expires after 30 seconds without host heartbeat. */
|
||||
put: operations["publishListeningState"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/activity": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
/** @description Ephemeral playback lease, expires after 90 seconds. Ignored when visibility is nobody. Sequence is monotonic per device; paused updates clear only that device. No offline replay. */
|
||||
put: operations["publishListeningActivity"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/activity/visibility": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
/** @description Applies to all devices. Nobody clears all current activity immediately. */
|
||||
put: operations["setActivityVisibility"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/social/activity/{userId}/playlist": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** @description Read-only current playlist subject to live visibility, friendship, blocking and expiry. Does not create or reveal a permanent share token. */
|
||||
get: operations["getActivityPlaylist"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -74,6 +207,41 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/chats/{peerId}/meta": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
peerId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getChatMeta"];
|
||||
put: operations["setChatTyping"];
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/me/social/chats/{peerId}/messages/{messageId}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
/** @description Friends only. Edit/delete are sender-only. Delete removes content for both participants; react toggles one allowed emoji. Reply targets must belong to the same conversation. */
|
||||
patch: operations["updateChatMessage"];
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/admin/server/updates": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1692,6 +1860,111 @@ export interface paths {
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
schemas: {
|
||||
ListeningPreferences: {
|
||||
requests: components["schemas"]["ActivityVisibility"];
|
||||
auto_accept: components["schemas"]["ActivityVisibility"];
|
||||
/** @default true */
|
||||
autoplay: boolean;
|
||||
};
|
||||
ListeningAction: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** @enum {string} */
|
||||
action: "join" | "invite" | "accept" | "decline" | "cancel" | "leave" | "end";
|
||||
/** Format: uuid */
|
||||
target_id: string;
|
||||
/** Format: uuid */
|
||||
device_id?: string;
|
||||
/** Format: uuid */
|
||||
track_id?: string;
|
||||
position_ms?: number;
|
||||
playing?: boolean;
|
||||
};
|
||||
ListeningRoomInput: {
|
||||
/** Format: uuid */
|
||||
room_id: string;
|
||||
/** Format: uuid */
|
||||
device_id: string;
|
||||
/** Format: int64 */
|
||||
sequence: number;
|
||||
/** Format: uuid */
|
||||
track_id?: string;
|
||||
playing: boolean;
|
||||
position_ms: number;
|
||||
};
|
||||
ListeningRoom: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** Format: uuid */
|
||||
owner_id: string;
|
||||
owner_name: string;
|
||||
/** Format: uuid */
|
||||
device_id: string;
|
||||
/** Format: uuid */
|
||||
track_id: string | null;
|
||||
position_ms: number;
|
||||
playing: boolean;
|
||||
/** Format: date-time */
|
||||
updated_at: string;
|
||||
participants: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
};
|
||||
ListeningRequest: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
/** Format: uuid */
|
||||
sender_id: string;
|
||||
sender_name: string;
|
||||
/** Format: uuid */
|
||||
recipient_id: string;
|
||||
/** Format: uuid */
|
||||
owner_id: string;
|
||||
/** @enum {string} */
|
||||
kind: "join" | "invite";
|
||||
/** Format: date-time */
|
||||
expires_at: string;
|
||||
};
|
||||
ListeningState: {
|
||||
preferences: components["schemas"]["ListeningPreferences"];
|
||||
room: components["schemas"]["ListeningRoom"] | null;
|
||||
requests: components["schemas"]["ListeningRequest"][];
|
||||
/** Format: date-time */
|
||||
server_time: string;
|
||||
};
|
||||
/**
|
||||
* @default nobody
|
||||
* @enum {string}
|
||||
*/
|
||||
ActivityVisibility: "nobody" | "friends" | "everyone";
|
||||
ListeningActivityInput: {
|
||||
/** Format: uuid */
|
||||
device_id: string;
|
||||
/** Format: int64 */
|
||||
sequence: number;
|
||||
playing: boolean;
|
||||
/** @default 0 */
|
||||
position_ms: number;
|
||||
/** Format: uuid */
|
||||
track_id?: string;
|
||||
/** @enum {string} */
|
||||
context: "other" | "wave" | "playlist";
|
||||
/** Format: uuid */
|
||||
playlist_id?: string;
|
||||
};
|
||||
ListeningActivity: {
|
||||
/** Format: uuid */
|
||||
track_id: string;
|
||||
track_title: string;
|
||||
artist: string;
|
||||
/** @enum {string} */
|
||||
context: "other" | "wave" | "playlist";
|
||||
/** Format: uuid */
|
||||
playlist_id?: string;
|
||||
playlist_name?: string;
|
||||
};
|
||||
SocialPerson: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
@@ -1700,6 +1973,7 @@ export interface components {
|
||||
/** @enum {string} */
|
||||
relationship: "none" | "incoming" | "outgoing" | "friend" | "blocked";
|
||||
unread: number;
|
||||
activity?: components["schemas"]["ListeningActivity"];
|
||||
};
|
||||
SocialNotification: {
|
||||
/** Format: uuid */
|
||||
@@ -1708,12 +1982,15 @@ export interface components {
|
||||
actor_id: string;
|
||||
actor_name: string;
|
||||
/** @enum {string} */
|
||||
kind: "friend_request" | "friend_accepted" | "message" | "music";
|
||||
kind: "friend_request" | "friend_accepted" | "message" | "music" | "listening_request" | "listening_invite" | "listening_accepted";
|
||||
/** Format: date-time */
|
||||
created_at: string;
|
||||
read: boolean;
|
||||
};
|
||||
SocialInbox: {
|
||||
/** @default true */
|
||||
friends_recommendations: boolean;
|
||||
activity_visibility: components["schemas"]["ActivityVisibility"];
|
||||
people: components["schemas"]["SocialPerson"][];
|
||||
notifications: components["schemas"]["SocialNotification"][];
|
||||
unread: number;
|
||||
@@ -1734,6 +2011,8 @@ export interface components {
|
||||
attachment_kind: "none" | "track" | "playlist";
|
||||
/** Format: uuid */
|
||||
attachment_id?: string;
|
||||
/** Format: uuid */
|
||||
reply_to?: string;
|
||||
};
|
||||
DirectMessage: {
|
||||
/** Format: uuid */
|
||||
@@ -1750,6 +2029,18 @@ export interface components {
|
||||
/** Format: date-time */
|
||||
created_at: string;
|
||||
read: boolean;
|
||||
/** Format: uuid */
|
||||
reply_to?: string;
|
||||
reply_preview?: string;
|
||||
/** Format: date-time */
|
||||
edited_at?: string;
|
||||
deleted?: boolean;
|
||||
reactions?: components["schemas"]["MessageReaction"][];
|
||||
};
|
||||
MessageReaction: {
|
||||
emoji: string;
|
||||
count: number;
|
||||
mine: boolean;
|
||||
};
|
||||
ServerSource: {
|
||||
id: string;
|
||||
@@ -2917,6 +3208,192 @@ export interface components {
|
||||
}
|
||||
export type $defs = Record<string, never>;
|
||||
export interface operations {
|
||||
setFriendsRecommendations: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Saved */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getListeningState: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Listening preferences, current room and pending requests */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListeningState"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
setListeningPreferences: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListeningPreferences"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Saved */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
listeningAction: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListeningAction"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Applied */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
publishListeningState: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListeningRoomInput"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Applied */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
publishListeningActivity: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListeningActivityInput"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Applied */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
setActivityVisibility: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
visibility: components["schemas"]["ActivityVisibility"];
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Saved */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getActivityPlaylist: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
userId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Read-only playlist */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["Playlist"];
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getSocial: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2988,6 +3465,7 @@ export interface operations {
|
||||
parameters: {
|
||||
query?: {
|
||||
before?: number;
|
||||
q?: string;
|
||||
};
|
||||
header?: never;
|
||||
path: {
|
||||
@@ -3036,6 +3514,90 @@ export interface operations {
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getChatMeta: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
peerId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Ephemeral typing indicator, friends only */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
typing: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
setChatTyping: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
peerId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
typing: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Applied */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
updateChatMessage: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
peerId: string;
|
||||
messageId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
/** @enum {string} */
|
||||
action: "edit" | "delete" | "react";
|
||||
text?: string;
|
||||
/** @enum {string} */
|
||||
emoji?: "❤️" | "👍" | "🔥" | "😂" | "🎵" | "👏";
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Applied */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
default: components["responses"]["Problem"];
|
||||
};
|
||||
};
|
||||
getServerUpdates: {
|
||||
parameters: {
|
||||
query?: {
|
||||
|
||||
Reference in new issue
Block a user