{ "schemes": [ "http", "https" ], "swagger": "2.0", "info": { "description": "Backend API for watch-party app.", "title": "Watch Party Backend API", "contact": {}, "version": "1.0" }, "host": "localhost:8082", "basePath": "/", "paths": { "/api/v1/archive": { "post": { "description": "Move one or many IDs from `current` to `current_archive`.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "archive" ], "summary": "Move shows to archive", "parameters": [ { "description": "IDs to move", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/httpapi.MoveReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.MoveRes" } }, "400": { "description": "empty ids", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "move failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } }, "/api/v1/current": { "get": { "description": "Returns the current row from `current` table.", "produces": [ "application/json" ], "tags": [ "current" ], "summary": "Get current show", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.CurrentResponse" } }, "404": { "description": "no current row found", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "query failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } }, "post": { "description": "Set the current show ID and start time.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "current" ], "summary": "Set current show", "parameters": [ { "description": "Current show payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/httpapi.SetCurrentReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.CurrentResponse" } }, "400": { "description": "invalid payload or invalid time", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "404": { "description": "id not found", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "update failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } }, "/api/v1/danime": { "get": { "description": "Fetch metadata from dアニメストア WS030101 by partId.", "produces": [ "application/json" ], "tags": [ "scraper" ], "summary": "Fetch dアニメ episode metadata", "parameters": [ { "type": "string", "description": "dアニメ partId", "name": "part_id", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.DanimeEpisodeResponse" } }, "400": { "description": "missing part_id", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "502": { "description": "scrape failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } }, "/api/v1/oauth/firebase": { "post": { "description": "Validate Firebase ID token and return basic claims.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Verify Firebase ID token", "parameters": [ { "description": "Firebase ID token", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/httpapi.FirebaseOAuthReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.FirebaseOAuthRes" } }, "400": { "description": "invalid payload", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "401": { "description": "invalid token", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "503": { "description": "auth disabled", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } }, "/api/v1/oauth/firebase/claim-admin": { "post": { "description": "Set the \\\"admin\\\" custom claim for the user represented by the ID token.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Claim Firebase admin", "parameters": [ { "description": "Firebase ID token", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/httpapi.FirebaseAdminClaimReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/httpapi.FirebaseAdminClaimRes" } }, "400": { "description": "invalid payload", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "401": { "description": "invalid token", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "claim failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "503": { "description": "auth disabled", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } }, "/api/v1/shows": { "get": { "description": "List all rows from `current` table.", "produces": [ "application/json" ], "tags": [ "shows" ], "summary": "List current shows", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/httpapi.CurrentResponse" } } }, "500": { "description": "list failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } }, "post": { "description": "Insert a new show into `current`.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "shows" ], "summary": "Create show", "parameters": [ { "description": "New show payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/httpapi.CreateShowReq" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/httpapi.CurrentResponse" } }, "400": { "description": "invalid payload or invalid time/duration", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "create failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } }, "delete": { "description": "Delete a row from `current` by ID.", "produces": [ "application/json" ], "tags": [ "shows" ], "summary": "Delete show", "parameters": [ { "type": "integer", "format": "int64", "description": "Show ID", "name": "id", "in": "query", "required": true } ], "responses": { "204": { "description": "No Content" }, "400": { "description": "invalid id", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "404": { "description": "id not found", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } }, "500": { "description": "delete failed", "schema": { "$ref": "#/definitions/httpapi.HTTPError" } } } } } }, "definitions": { "httpapi.CreateShowReq": { "type": "object", "required": [ "ep_num", "ep_title", "playback_length", "season_name" ], "properties": { "ep_num": { "type": "integer", "example": 1 }, "ep_title": { "type": "string", "example": "Pilot" }, "playback_length": { "type": "string", "example": "00:24:00" }, "season_name": { "type": "string", "example": "Season 1" }, "start_time": { "description": "optional; defaults to 22:00:00", "type": "string", "example": "10:00:00" } } }, "httpapi.CurrentResponse": { "type": "object", "properties": { "current_ep": { "type": "boolean", "example": false }, "date_created": { "type": "string", "example": "2024-02-01T15:04:05Z" }, "ep_num": { "type": "integer", "example": 1 }, "ep_title": { "type": "string", "example": "Pilot" }, "id": { "type": "integer", "example": 123 }, "playback_length": { "type": "string", "example": "00:24:00" }, "season_name": { "type": "string", "example": "Season 1" }, "start_time": { "type": "string", "example": "10:00:00" } } }, "httpapi.DanimeEpisodeResponse": { "type": "object", "properties": { "ep_num": { "type": "integer", "example": 21 }, "ep_title": { "type": "string", "example": "あったんだ。確かに" }, "playback_length": { "type": "string", "example": "00:23:50" }, "season_name": { "type": "string", "example": "フルーツバスケット 2nd season" } } }, "httpapi.FirebaseAdminClaimReq": { "type": "object", "required": [ "id_token" ], "properties": { "id_token": { "type": "string", "example": "\u003cfirebase-id-token\u003e" } } }, "httpapi.FirebaseAdminClaimRes": { "type": "object", "properties": { "admin": { "type": "boolean", "example": true }, "custom_claims": { "type": "object", "additionalProperties": true }, "email": { "type": "string", "example": "user@example.com" }, "uid": { "type": "string", "example": "abc123" } } }, "httpapi.FirebaseOAuthReq": { "type": "object", "required": [ "id_token" ], "properties": { "id_token": { "type": "string", "example": "\u003cfirebase-id-token\u003e" } } }, "httpapi.FirebaseOAuthRes": { "type": "object", "properties": { "email": { "type": "string", "example": "user@example.com" }, "expires": { "type": "integer", "example": 1700000000 }, "issuer": { "type": "string", "example": "https://securetoken.google.com/\u003cproject\u003e" }, "uid": { "type": "string", "example": "abc123" } } }, "httpapi.HTTPError": { "type": "object", "properties": { "error": { "type": "string", "example": "invalid payload" } } }, "httpapi.MoveReq": { "type": "object", "properties": { "id": { "type": "integer", "example": 123 }, "ids": { "type": "array", "items": { "type": "integer" } } } }, "httpapi.MoveRes": { "type": "object", "properties": { "deleted": { "type": "integer" }, "deleted_ids": { "type": "array", "items": { "type": "integer" } }, "inserted": { "type": "integer" }, "moved_ids": { "type": "array", "items": { "type": "integer" } }, "skipped": { "type": "integer" }, "skipped_ids": { "type": "array", "items": { "type": "integer" } } } }, "httpapi.SetCurrentReq": { "type": "object", "required": [ "id", "start_time" ], "properties": { "id": { "type": "integer", "example": 123 }, "start_time": { "type": "string", "example": "21:00:00" } } } } }