format project

This commit is contained in:
JasonLandbridge
2024-09-04 11:24:16 +02:00
parent 0b9c51f79f
commit d902880604
44 changed files with 3712 additions and 3109 deletions

View File

@@ -27,8 +27,8 @@ jobs:
commit_message: "build: dereferenced Plex Media Server API Spec updated" commit_message: "build: dereferenced Plex Media Server API Spec updated"
skip_checkout: true skip_checkout: true
skip_fetch: true skip_fetch: true
add_options: '-f' add_options: "-f"
file_pattern: './output/*.yaml' file_pattern: "./output/*.yaml"
skip_dirty_check: true skip_dirty_check: true
- name: Pushes Dereferenced Specification File - name: Pushes Dereferenced Specification File
@@ -42,4 +42,3 @@ jobs:
user_email: lukeslakemail@gmail.com user_email: lukeslakemail@gmail.com
user_name: lukehagar user_name: lukehagar
commit_message: Updating PMS Spec commit_message: Updating PMS Spec

View File

@@ -1,7 +1,7 @@
name: 'Project Setup' name: "Project Setup"
description: 'Setup Bun and install dependencies' description: "Setup Bun and install dependencies"
runs: runs:
using: 'composite' using: "composite"
steps: steps:
- name: Setup Bun - name: Setup Bun
uses: oven-sh/setup-bun@v2 uses: oven-sh/setup-bun@v2

View File

@@ -5,13 +5,15 @@ Automation and SDKs provided by [Speakeasy](https://speakeasyapi.dev/)
An Open Source OpenAPI Specification for Plex Media Server An Open Source OpenAPI Specification for Plex Media Server
## Documentation ## Documentation
[API Documentation](https://plexapi.dev) [API Documentation](https://plexapi.dev)
## SDKs ## SDKs
The following SDKs are generated from the OpenAPI Specification. They are automatically generated and may not be fully tested. If you find any issues, please open an issue on the respective repository. The following SDKs are generated from the OpenAPI Specification. They are automatically generated and may not be fully tested. If you find any issues, please open an issue on the respective repository.
| Language | Repository | Releases | Other | | Language | Repository | Releases | Other |
| -------- | ---------- | ------- | ----- | | --------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
| Python | [GitHub](https://github.com/LukeHagar/plexpy) | [PyPI](https://pypi.org/project/plex-api-client/) | - | | Python | [GitHub](https://github.com/LukeHagar/plexpy) | [PyPI](https://pypi.org/project/plex-api-client/) | - |
| JavaScript/TypeScript | [GitHub](https://github.com/LukeHagar/plexjs) | [NPM](https://www.npmjs.com/package/@lukehagar/plexjs) \ [JSR](https://jsr.io/@lukehagar/plexjs) | - | | JavaScript/TypeScript | [GitHub](https://github.com/LukeHagar/plexjs) | [NPM](https://www.npmjs.com/package/@lukehagar/plexjs) \ [JSR](https://jsr.io/@lukehagar/plexjs) | - |
| Go | [GitHub](https://github.com/LukeHagar/plexgo) | [Releases](https://github.com/LukeHagar/plexgo/releases) | [GoDoc](https://pkg.go.dev/github.com/LukeHagar/plexgo) | | Go | [GitHub](https://github.com/LukeHagar/plexgo) | [Releases](https://github.com/LukeHagar/plexgo/releases) | [GoDoc](https://pkg.go.dev/github.com/LukeHagar/plexgo) |
@@ -22,4 +24,5 @@ The following SDKs are generated from the OpenAPI Specification. They are automa
| C# | [GitHub](https://github.com/LukeHagar/plexcsharp) | [Releases](https://github.com/LukeHagar/plexcsharp/releases) | - | | C# | [GitHub](https://github.com/LukeHagar/plexcsharp) | [Releases](https://github.com/LukeHagar/plexcsharp/releases) | - |
## Questions? ## Questions?
Reach out to me on the [Discord Server](https://discord.gg/mxqjsJHwUm) Reach out to me on the [Discord Server](https://discord.gg/mxqjsJHwUm)

View File

@@ -3,9 +3,9 @@ x-examples:
Example 1: Example 1:
id: 373040866 id: 373040866
code: 7RQZ code: 7RQZ
product: '0' product: "0"
trusted: false trusted: false
qr: 'https://plex.tv/api/v2/pins/qr/7RQZ' qr: "https://plex.tv/api/v2/pins/qr/7RQZ"
clientIdentifier: 9klpwueublnfbvlx95w83ah9 clientIdentifier: 9klpwueublnfbvlx95w83ah9
location: location:
code: NL code: NL
@@ -14,23 +14,23 @@ x-examples:
country: The Netherlands country: The Netherlands
city: Breda city: Breda
time_zone: Europe/Amsterdam time_zone: Europe/Amsterdam
postal_code: '4814' postal_code: "4814"
in_privacy_restricted_country: true in_privacy_restricted_country: true
in_privacy_restricted_region: true in_privacy_restricted_region: true
subdivisions: North Brabant subdivisions: North Brabant
coordinates: '51.5869, 4.7471' coordinates: "51.5869, 4.7471"
expiresIn: 876 expiresIn: 876
createdAt: '2024-07-16T17:03:05Z' createdAt: "2024-07-16T17:03:05Z"
expiresAt: '2024-07-16T17:18:05Z' expiresAt: "2024-07-16T17:18:05Z"
authToken: null authToken: null
newRegistration: null newRegistration: null
title: AuthPinContainer title: AuthPinContainer
examples: examples:
- id: 308667304 - id: 308667304
code: 7RQZ code: 7RQZ
product: '0' product: "0"
trusted: false trusted: false
qr: 'https://plex.tv/api/v2/pins/qr/7RQZ' qr: "https://plex.tv/api/v2/pins/qr/7RQZ"
clientIdentifier: string clientIdentifier: string
location: location:
code: VI code: VI
@@ -43,10 +43,10 @@ examples:
in_privacy_restricted_country: true in_privacy_restricted_country: true
in_privacy_restricted_region: true in_privacy_restricted_region: true
subdivisions: Saint Thomas subdivisions: Saint Thomas
coordinates: '18.3381, -64.8941' coordinates: "18.3381, -64.8941"
expiresIn: 876 expiresIn: 876
createdAt: '2024-07-16T17:03:05Z' createdAt: "2024-07-16T17:03:05Z"
expiresAt: '2024-07-16T17:18:05Z' expiresAt: "2024-07-16T17:18:05Z"
authToken: null authToken: null
newRegistration: null newRegistration: null
required: required:
@@ -69,13 +69,13 @@ properties:
example: 7RQZ example: 7RQZ
product: product:
type: string type: string
example: '0' example: "0"
trusted: trusted:
type: boolean type: boolean
default: false default: false
qr: qr:
type: string type: string
example: 'https://plex.tv/api/v2/pins/qr/7RQZ' example: "https://plex.tv/api/v2/pins/qr/7RQZ"
clientIdentifier: clientIdentifier:
type: string type: string
description: The X-Client-Identifier used in the request description: The X-Client-Identifier used in the request
@@ -84,17 +84,17 @@ properties:
expiresIn: expiresIn:
type: integer type: integer
example: 876 example: 876
description: 'The number of seconds this pin expires, by default 900 seconds' description: "The number of seconds this pin expires, by default 900 seconds"
default: 900 default: 900
createdAt: createdAt:
type: string type: string
example: '2024-07-16T17:03:05Z' example: "2024-07-16T17:03:05Z"
format: date-time format: date-time
expiresAt: expiresAt:
type: string type: string
format: date-time format: date-time
example: '2024-07-16T17:18:05Z' example: "2024-07-16T17:18:05Z"
authToken: authToken:
type: 'null' type: "null"
newRegistration: newRegistration:
type: 'null' type: "null"

View File

@@ -9,7 +9,7 @@ examples:
sharedServers: [] sharedServers: []
sharedSources: [] sharedSources: []
status: accepted status: accepted
thumb: 'https://plex.tv/users/7d1916e0d8f6e76b/avatar?c=1694481578' thumb: "https://plex.tv/users/7d1916e0d8f6e76b/avatar?c=1694481578"
title: username123 title: username123
username: username123 username: username123
uuid: 7d1916e0d8f6e76b uuid: 7d1916e0d8f6e76b
@@ -38,7 +38,7 @@ properties:
- null - null
type: type:
- string - string
- 'null' - "null"
description: The account full name description: The account full name
home: home:
type: boolean type: boolean
@@ -67,7 +67,7 @@ properties:
description: Current friend request status description: Current friend request status
thumb: thumb:
type: string type: string
example: 'https://plex.tv/users/7d1916e0d8f6e76b/avatar?c=1694481578' example: "https://plex.tv/users/7d1916e0d8f6e76b/avatar?c=1694481578"
format: uri format: uri
description: URL of the account thumbnail description: URL of the account thumbnail
title: title:

View File

@@ -1,6 +1,6 @@
title: GeoData title: GeoData
type: object type: object
description: 'Geo location data' description: "Geo location data"
examples: examples:
- code: VI - code: VI
continent_code: NA continent_code: NA
@@ -12,7 +12,7 @@ examples:
in_privacy_restricted_country: true in_privacy_restricted_country: true
in_privacy_restricted_region: true in_privacy_restricted_region: true
subdivisions: Saint Thomas subdivisions: Saint Thomas
coordinates: '18.3381, -64.8941' coordinates: "18.3381, -64.8941"
required: required:
- code - code
- continent_code - continent_code
@@ -71,5 +71,5 @@ properties:
example: Saint Thomas example: Saint Thomas
coordinates: coordinates:
type: string type: string
description: 'The geographical coordinates (latitude, longitude) of the location.' description: "The geographical coordinates (latitude, longitude) of the location."
example: '18.3381, -64.8941' example: "18.3381, -64.8941"

View File

@@ -20,19 +20,19 @@ properties:
id: id:
type: type:
- string - string
- 'null' - "null"
mode: mode:
type: type:
- string - string
- 'null' - "null"
renewsAt: renewsAt:
oneOf: oneOf:
- $ref: './common/PlexDateTime.yaml' - $ref: "./common/PlexDateTime.yaml"
- type: 'null' - type: "null"
endsAt: endsAt:
oneOf: oneOf:
- $ref: './common/PlexDateTime.yaml' - $ref: "./common/PlexDateTime.yaml"
- type: 'null' - type: "null"
canceled: canceled:
type: boolean type: boolean
example: false example: false
@@ -67,7 +67,7 @@ properties:
transfer: transfer:
type: type:
- string - string
- 'null' - "null"
state: state:
example: ended example: ended
enum: enum:
@@ -83,4 +83,4 @@ properties:
paymentMethodId: paymentMethodId:
type: type:
- integer - integer
- 'null' - "null"

View File

@@ -73,8 +73,8 @@ properties:
description: Date the account subscribed to Plex Pass description: Date the account subscribed to Plex Pass
type: type:
- string - string
- 'null' - "null"
example: '2021-04-12T18:21:12Z' example: "2021-04-12T18:21:12Z"
status: status:
description: String representation of subscriptionActive description: String representation of subscriptionActive
example: Inactive example: Inactive
@@ -85,9 +85,9 @@ properties:
description: Payment service used for your Plex Pass subscription description: Payment service used for your Plex Pass subscription
type: type:
- string - string
- 'null' - "null"
plan: plan:
description: Name of Plex Pass subscription plan description: Name of Plex Pass subscription plan
type: type:
- string - string
- 'null' - "null"

View File

@@ -2,8 +2,8 @@ title: UserPlexAccount
type: object type: object
examples: examples:
- adsConsent: true - adsConsent: true
adsConsentReminderAt: '2019-08-24T14:15:22Z' adsConsentReminderAt: "2019-08-24T14:15:22Z"
adsConsentSetAt: '2019-08-24T14:15:22Z' adsConsentSetAt: "2019-08-24T14:15:22Z"
anonymous: false anonymous: false
authToken: CxoUzBTSV5hsxjTpFKaf authToken: CxoUzBTSV5hsxjTpFKaf
backupCodesCreated: false backupCodesCreated: false
@@ -29,14 +29,14 @@ examples:
- id: string - id: string
mode: string mode: string
renewsAt: string renewsAt: string
endsAt: '1556281940' endsAt: "1556281940"
canceled: '0' canceled: "0"
gracePeriod: '0' gracePeriod: "0"
onHold: '0' onHold: "0"
canReactivate: '0' canReactivate: "0"
canUpgrade: '0' canUpgrade: "0"
canDowngrade: '0' canDowngrade: "0"
canConvert: '0' canConvert: "0"
type: plexpass type: plexpass
transfer: string transfer: string
state: ended state: ended
@@ -58,10 +58,10 @@ examples:
restricted: false restricted: false
roles: roles:
- string - string
scrobbleTypes: '' scrobbleTypes: ""
services: services:
- identifier: metadata-dev - identifier: metadata-dev
endpoint: 'https://epg.provider.plex.tv' endpoint: "https://epg.provider.plex.tv"
token: DjoMtqFAGRL1uVtCyF1dKIorTbShJeqv token: DjoMtqFAGRL1uVtCyF1dKIorTbShJeqv
secret: string secret: string
status: online status: online
@@ -69,7 +69,7 @@ examples:
features: features:
- Android - Dolby Vision - Android - Dolby Vision
active: true active: true
subscribedAt: '2021-04-12T18:21:12Z' subscribedAt: "2021-04-12T18:21:12Z"
status: Inactive status: Inactive
paymentService: string paymentService: string
plan: string plan: string
@@ -78,11 +78,11 @@ examples:
- features: - features:
- Android - Dolby Vision - Android - Dolby Vision
active: true active: true
subscribedAt: '2021-04-12T18:21:12Z' subscribedAt: "2021-04-12T18:21:12Z"
status: Inactive status: Inactive
paymentService: string paymentService: string
plan: string plan: string
thumb: 'https://plex.tv/users/a4f43c1ebfde43a5/avatar?c=8372075101' thumb: "https://plex.tv/users/a4f43c1ebfde43a5/avatar?c=8372075101"
title: UsernameTitle title: UsernameTitle
trials: trials:
- {} - {}
@@ -132,24 +132,24 @@ properties:
adsConsent: adsConsent:
type: type:
- boolean - boolean
- 'null' - "null"
description: Unknown description: Unknown
adsConsentReminderAt: adsConsentReminderAt:
type: type:
- string - string
- 'null' - "null"
description: Unknown description: Unknown
format: date-time format: date-time
adsConsentSetAt: adsConsentSetAt:
type: type:
- string - string
- 'null' - "null"
description: Unknown description: Unknown
format: date-time format: date-time
anonymous: anonymous:
type: type:
- boolean - boolean
- 'null' - "null"
description: Unknown description: Unknown
default: false default: false
authToken: authToken:
@@ -192,7 +192,7 @@ properties:
description: List of devices your allowed to use with this account description: List of devices your allowed to use with this account
items: items:
type: string type: string
example: '[]' example: "[]"
guest: guest:
type: boolean type: boolean
description: If the account is a Plex Home guest user description: If the account is a Plex Home guest user
@@ -227,7 +227,7 @@ properties:
locale: locale:
type: type:
- string - string
- 'null' - "null"
description: The account locale description: The account locale
mailingListActive: mailingListActive:
type: boolean type: boolean
@@ -245,7 +245,7 @@ properties:
format: int32 format: int32
pin: pin:
type: string type: string
description: '[Might be removed] The hashed Plex Home PIN ' description: "[Might be removed] The hashed Plex Home PIN "
deprecated: true deprecated: true
profile: profile:
$ref: ./UserProfile.yaml $ref: ./UserProfile.yaml
@@ -264,7 +264,7 @@ properties:
default: false default: false
roles: roles:
type: array type: array
description: '[Might be removed] List of account roles. Plexpass membership listed here' description: "[Might be removed] List of account roles. Plexpass membership listed here"
items: items:
type: string type: string
scrobbleTypes: scrobbleTypes:
@@ -286,17 +286,17 @@ properties:
example: metadata-dev example: metadata-dev
endpoint: endpoint:
type: string type: string
example: 'https://epg.provider.plex.tv' example: "https://epg.provider.plex.tv"
format: uri format: uri
token: token:
type: type:
- string - string
- 'null' - "null"
example: DjoMtqFAGRL1uVtCyF1dKIorTbShJeqv example: DjoMtqFAGRL1uVtCyF1dKIorTbShJeqv
secret: secret:
type: type:
- string - string
- 'null' - "null"
status: status:
example: online example: online
enum: enum:
@@ -308,7 +308,7 @@ properties:
subscriptionDescription: subscriptionDescription:
type: type:
- string - string
- 'null' - "null"
description: Description of the Plex Pass subscription description: Description of the Plex Pass subscription
subscriptions: subscriptions:
type: array type: array
@@ -318,7 +318,7 @@ properties:
type: string type: string
description: URL of the account thumbnail description: URL of the account thumbnail
format: uri format: uri
example: 'https://plex.tv/users/a4f43c1ebfde43a5/avatar?c=8372075101' example: "https://plex.tv/users/a4f43c1ebfde43a5/avatar?c=8372075101"
title: title:
type: string type: string
description: The title of the account (username or friendly name) description: The title of the account (username or friendly name)

View File

@@ -12,18 +12,18 @@ properties:
defaultAudioLanguage: defaultAudioLanguage:
type: type:
- string - string
- 'null' - "null"
example: ja example: ja
description: The preferred audio language for the account description: The preferred audio language for the account
defaultSubtitleLanguage: defaultSubtitleLanguage:
type: type:
- string - string
- 'null' - "null"
example: en example: en
description: The preferred subtitle language for the account description: The preferred subtitle language for the account
autoSelectSubtitle: autoSelectSubtitle:
example: 1 example: 1
description: 'The auto-select subtitle mode (0 = Manually selected, 1 = Shown with foreign audio, 2 = Always enabled)' description: "The auto-select subtitle mode (0 = Manually selected, 1 = Shown with foreign audio, 2 = Always enabled)"
enum: enum:
- 0 - 0
- 1 - 1
@@ -32,13 +32,13 @@ properties:
- 0 - 0
- 1 - 1
example: 1 example: 1
description: 'The subtitles for the deaf or hard-of-hearing (SDH) searches mode (0 = Prefer non-SDH subtitles, 1 = Prefer SDH subtitles, 2 = Only show SDH subtitles, 3 = Only shown non-SDH subtitles)' description: "The subtitles for the deaf or hard-of-hearing (SDH) searches mode (0 = Prefer non-SDH subtitles, 1 = Prefer SDH subtitles, 2 = Only show SDH subtitles, 3 = Only shown non-SDH subtitles)"
defaultSubtitleForced: defaultSubtitleForced:
enum: enum:
- 0 - 0
- 1 - 1
example: 0 example: 0
description: 'The forced subtitles searches mode (0 = Prefer non-forced subtitles, 1 = Prefer forced subtitles, 2 = Only show forced subtitles, 3 = Only show non-forced subtitles)' description: "The forced subtitles searches mode (0 = Prefer non-forced subtitles, 1 = Prefer forced subtitles, 2 = Only show forced subtitles, 3 = Only show non-forced subtitles)"
watchedIndicator: watchedIndicator:
enum: enum:
- 0 - 0

View File

@@ -5,4 +5,3 @@ schema:
type: integer type: integer
example: 9518 example: 9518
required: true required: true

View File

@@ -8,4 +8,3 @@ schema:
format: int32 format: int32
example: 9518 example: 9518
required: true required: true

View File

@@ -4,4 +4,3 @@ required: false
schema: schema:
type: string type: string
example: "Linux" example: "Linux"

View File

@@ -1,13 +1,13 @@
get: get:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
tags: tags:
- Plex - Plex
summary: Get Companions Data summary: Get Companions Data
description: Get Companions Data description: Get Companions Data
operationId: getCompanionsData operationId: getCompanionsData
responses: responses:
'200': "200":
description: Companions Data description: Companions Data
content: content:
application/json: application/json:
@@ -28,21 +28,21 @@ get:
example: tv.plex.sonos example: tv.plex.sonos
baseURL: baseURL:
type: string type: string
example: 'https://sonos.plex.tv' example: "https://sonos.plex.tv"
format: uri format: uri
title: title:
type: string type: string
example: Sonos example: Sonos
linkURL: linkURL:
type: string type: string
example: 'https://sonos.plex.tv/link' example: "https://sonos.plex.tv/link"
provides: provides:
type: string type: string
example: 'client,player' example: "client,player"
token: token:
type: string type: string
description: The plex authtoken used to identify with description: The plex authtoken used to identify with
'400': "400":
$ref: ../../responses/400.yaml $ref: ../../responses/400.yaml
'401': "401":
$ref: ../../responses/401.yaml $ref: ../../responses/401.yaml

View File

@@ -1,13 +1,13 @@
get: get:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
tags: tags:
- Plex - Plex
summary: Get list of friends of the user logged in summary: Get list of friends of the user logged in
description: Get friends of provided auth token. description: Get friends of provided auth token.
operationId: getUserFriends operationId: getUserFriends
responses: responses:
'200': "200":
description: Friends Data description: Friends Data
content: content:
application/json: application/json:
@@ -15,7 +15,7 @@ get:
type: array type: array
items: items:
$ref: ../../models/Friend.yaml $ref: ../../models/Friend.yaml
'400': "400":
$ref: '../../responses/400.yaml' $ref: "../../responses/400.yaml"
'401': "401":
$ref: '../../responses/401.yaml' $ref: "../../responses/401.yaml"

View File

@@ -1,6 +1,6 @@
get: get:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
security: [] # No security required security: [] # No security required
tags: tags:
- Plex - Plex
@@ -8,13 +8,13 @@ get:
description: Returns the geolocation and locale data of the caller description: Returns the geolocation and locale data of the caller
operationId: getGeoData operationId: getGeoData
responses: responses:
'200': "200":
description: Gets the geo location data of the user description: Gets the geo location data of the user
content: content:
application/json: application/json:
schema: schema:
$ref: ../../models/GeoData.yaml $ref: ../../models/GeoData.yaml
'400': "400":
$ref: ../../responses/400.yaml $ref: ../../responses/400.yaml
'401': "401":
$ref: ../../responses/401.yaml $ref: ../../responses/401.yaml

View File

@@ -113,7 +113,8 @@ get:
example: Firefly example: Firefly
summary: summary:
type: string type: string
example: Captain Malcolm 'Mal' Reynolds is a former galactic war veteran who is example:
Captain Malcolm 'Mal' Reynolds is a former galactic war veteran who is
the captain of the transport ship "Serenity". Mal and his crew, the captain of the transport ship "Serenity". Mal and his crew,
ensign Zoe Alleyne Washburne; Zoe's husband, pilot Hoban 'Wash' ensign Zoe Alleyne Washburne; Zoe's husband, pilot Hoban 'Wash'
Washburne; muscular mercenary Jayne Cobb; young mechanic Kaylee Washburne; muscular mercenary Jayne Cobb; young mechanic Kaylee

View File

@@ -60,7 +60,7 @@ get:
example: /:/resources/movie.png example: /:/resources/movie.png
key: key:
type: string type: string
example: '1' example: "1"
type: type:
type: string type: string
example: movie example: movie
@@ -80,11 +80,11 @@ get:
type: string type: string
example: 322a231a-b7f7-49f5-920f-14c61199cd30 example: 322a231a-b7f7-49f5-920f-14c61199cd30
updatedAt: updatedAt:
$ref: '../../models/common/PlexDateTime.yaml' $ref: "../../models/common/PlexDateTime.yaml"
createdAt: createdAt:
$ref: '../../models/common/PlexDateTime.yaml' $ref: "../../models/common/PlexDateTime.yaml"
scannedAt: scannedAt:
$ref: '../../models/common/PlexDateTime.yaml' $ref: "../../models/common/PlexDateTime.yaml"
content: content:
type: boolean type: boolean
example: true example: true

View File

@@ -18,7 +18,7 @@ get:
- $ref: "../../../../../parameters/image/upscale.yaml" - $ref: "../../../../../parameters/image/upscale.yaml"
- $ref: "../../../../../parameters/plex/x-plex-token.yaml" - $ref: "../../../../../parameters/plex/x-plex-token.yaml"
responses: responses:
'200': "200":
description: Successful response returning an image description: Successful response returning an image
headers: headers:
X-Plex-Protocol: X-Plex-Protocol:

View File

@@ -89,7 +89,8 @@ get:
example: PG-13 example: PG-13
summary: summary:
type: string type: string
example: Serenity continues the story of the TV series it was based upon example:
Serenity continues the story of the TV series it was based upon
("Firefly"). River Tam had a secret - one in which she's not ("Firefly"). River Tam had a secret - one in which she's not
even aware - so dangerous, no one's safe, as an Alliance even aware - so dangerous, no one's safe, as an Alliance
operative's sent to capture her, and all others are considered operative's sent to capture her, and all others are considered

View File

@@ -18,7 +18,7 @@ get:
- $ref: "../../../../../parameters/image/upscale.yaml" - $ref: "../../../../../parameters/image/upscale.yaml"
- $ref: "../../../../../parameters/plex/x-plex-token.yaml" - $ref: "../../../../../parameters/plex/x-plex-token.yaml"
responses: responses:
'200': "200":
description: Successful response returning an image description: Successful response returning an image
headers: headers:
X-Plex-Protocol: X-Plex-Protocol:

View File

@@ -5,10 +5,10 @@ get:
description: Retrieves media providers and their features from the Plex server. description: Retrieves media providers and their features from the Plex server.
operationId: get-media-providers operationId: get-media-providers
parameters: parameters:
- $ref: '../../../parameters/accept-application-json.yaml' - $ref: "../../../parameters/accept-application-json.yaml"
- $ref: '../../../parameters/plex/x-plex-token.yaml' - $ref: "../../../parameters/plex/x-plex-token.yaml"
responses: responses:
'200': "200":
description: Media providers and their features description: Media providers and their features
content: content:
application/json: application/json:

View File

@@ -16,15 +16,15 @@ get:
schema: schema:
type: integer type: integer
responses: responses:
'200': "200":
description: The Pin with a non-null authToken when it has been verified by the user description: The Pin with a non-null authToken when it has been verified by the user
content: content:
application/json: application/json:
schema: schema:
$ref: ../../models/AuthPinContainer.yaml $ref: ../../models/AuthPinContainer.yaml
'400': "400":
$ref: ../../responses/400-MissingIdentifier.yaml $ref: ../../responses/400-MissingIdentifier.yaml
'404': "404":
description: Not Found or Expired description: Not Found or Expired
content: content:
application/json: application/json:

View File

@@ -1,6 +1,6 @@
post: post:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
tags: tags:
- Plex - Plex
summary: Get a Pin summary: Get a Pin
@@ -21,12 +21,11 @@ post:
- $ref: ../../parameters/plex/x-plex-identifier.yaml - $ref: ../../parameters/plex/x-plex-identifier.yaml
- $ref: ../../parameters/plex/x-plex-product.yaml - $ref: ../../parameters/plex/x-plex-product.yaml
responses: responses:
'200': "200":
description: Requests a new pin id used in the authentication flow description: Requests a new pin id used in the authentication flow
content: content:
application/json: application/json:
schema: schema:
$ref: ../../models/AuthPinContainer.yaml $ref: ../../models/AuthPinContainer.yaml
'400': "400":
$ref: ../../responses/400-MissingIdentifier.yaml $ref: ../../responses/400-MissingIdentifier.yaml

View File

@@ -1,6 +1,6 @@
get: get:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
security: [] security: []
tags: tags:
- Plex - Plex
@@ -34,7 +34,7 @@ get:
- 0 - 0
- 1 - 1
responses: responses:
'200': "200":
description: List of Plex Devices. This includes Plex hosted servers and clients description: List of Plex Devices. This includes Plex hosted servers and clients
content: content:
application/json: application/json:
@@ -42,7 +42,7 @@ get:
type: array type: array
items: items:
$ref: ../../models/PlexDevice.yaml $ref: ../../models/PlexDevice.yaml
'400': "400":
$ref: '../../responses/400.yaml' $ref: "../../responses/400.yaml"
'401': "401":
$ref: '../../responses/401.yaml' $ref: "../../responses/401.yaml"

View File

@@ -36,7 +36,7 @@ get:
in: query in: query
schema: schema:
type: object type: object
pattern: '^[A-Za-z][A-Za-z0-9]*[>=<]{0,2}$' pattern: "^[A-Za-z][A-Za-z0-9]*[>=<]{0,2}$"
example: example:
viewed-at-greater-than: viewed-at-greater-than:
value: viewedAt> value: viewedAt>

View File

@@ -1,22 +1,22 @@
get: get:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
tags: tags:
- Authentication - Authentication
summary: Get User Data By Token summary: Get User Data By Token
description: Get the User data from the provided X-Plex-Token description: Get the User data from the provided X-Plex-Token
operationId: getUserDetails operationId: getUserDetails
parameters: parameters:
- $ref: '../../parameters/plex/x-plex-token.yaml' - $ref: "../../parameters/plex/x-plex-token.yaml"
- $ref: "../../parameters/accept-application-json.yaml" - $ref: "../../parameters/accept-application-json.yaml"
responses: responses:
'200': "200":
description: Logged in user details description: Logged in user details
content: content:
application/json: application/json:
schema: schema:
$ref: ../../models/UserPlexAccount.yaml $ref: ../../models/UserPlexAccount.yaml
'400': "400":
$ref: '../../responses/400.yaml' $ref: "../../responses/400.yaml"
'401': "401":
$ref: '../../responses/401.yaml' $ref: "../../responses/401.yaml"

View File

@@ -1,6 +1,6 @@
post: post:
servers: servers:
- url: 'https://plex.tv/api/v2' - url: "https://plex.tv/api/v2"
security: [] security: []
tags: tags:
- Authentication - Authentication
@@ -31,7 +31,7 @@ post:
default: false default: false
description: Login credentials description: Login credentials
responses: responses:
'201': "201":
description: Returns the user account data with a valid auth token description: Returns the user account data with a valid auth token
content: content:
application/json: application/json:
@@ -51,7 +51,7 @@ post:
type: array type: array
items: items:
type: object type: object
'400': "400":
$ref: '../../responses/400.yaml' $ref: "../../responses/400.yaml"
'401': "401":
$ref: '../../responses/401.yaml' $ref: "../../responses/401.yaml"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,414 +1,414 @@
import {validateResponseSpec} from "../../utils/"; import { validateResponseSpec } from "../../utils/"
import {describe, it} from 'vitest' import { describe, it } from "vitest"
describe('GET /library/sections', () => { describe("GET /library/sections", () => {
it('should validate the 200 response when the API spec is valid', () => { it("should validate the 200 response when the API spec is valid", () => {
const response = { const response = {
"MediaContainer": { MediaContainer: {
"size": 14, size: 14,
"allowSync": false, allowSync: false,
"title1": "Plex Library", title1: "Plex Library",
"Directory": [ Directory: [
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/7/composite/1893047123", composite: "/library/sections/7/composite/1893047123",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/movie.png", thumb: "/:/resources/movie.png",
"key": "7", key: "7",
"type": "movie", type: "movie",
"title": "Kids Movies", title: "Kids Movies",
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"scanner": "Plex Movie", scanner: "Plex Movie",
"language": "en-US", language: "en-US",
"uuid": "a1b2c3d4e5f67890", uuid: "a1b2c3d4e5f67890",
"updatedAt": 1728394001, updatedAt: 1728394001,
"createdAt": 1598476504, createdAt: 1598476504,
"scannedAt": 1893047123, scannedAt: 1893047123,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 4738921, contentChangedAt: 4738921,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 25, id: 25,
"path": "/KidsMovies" path: "/KidsMovies"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/13/composite/1893047124", composite: "/library/sections/13/composite/1893047124",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/movie.png", thumb: "/:/resources/movie.png",
"key": "13", key: "13",
"type": "movie", type: "movie",
"title": "Kids Movies NL", title: "Kids Movies NL",
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"scanner": "Plex Movie", scanner: "Plex Movie",
"language": "nl-NL", language: "nl-NL",
"uuid": "b2c3d4e5f67890a1", uuid: "b2c3d4e5f67890a1",
"updatedAt": 1680007500, updatedAt: 1680007500,
"createdAt": 1680007500, createdAt: 1680007500,
"scannedAt": 1893047124, scannedAt: 1893047124,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 5283714, contentChangedAt: 5283714,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 23, id: 23,
"path": "/KidsMoviesNL" path: "/KidsMoviesNL"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/1/composite/1893047130", composite: "/library/sections/1/composite/1893047130",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/movie.png", thumb: "/:/resources/movie.png",
"key": "1", key: "1",
"type": "movie", type: "movie",
"title": "Movies", title: "Movies",
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"scanner": "Plex Movie", scanner: "Plex Movie",
"language": "en-US", language: "en-US",
"uuid": "c3d4e5f67890a1b2", uuid: "c3d4e5f67890a1b2",
"updatedAt": 1728394005, updatedAt: 1728394005,
"createdAt": 1598476200, createdAt: 1598476200,
"scannedAt": 1893047130, scannedAt: 1893047130,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 6379184, contentChangedAt: 6379184,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 18, id: 18,
"path": "/Movies" path: "/Movies"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/6/composite/1893047135", composite: "/library/sections/6/composite/1893047135",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/movie.png", thumb: "/:/resources/movie.png",
"key": "6", key: "6",
"type": "movie", type: "movie",
"title": "Movies (Documentaries)", title: "Movies (Documentaries)",
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"scanner": "Plex Movie", scanner: "Plex Movie",
"language": "en-US", language: "en-US",
"uuid": "d4e5f67890a1b2c3", uuid: "d4e5f67890a1b2c3",
"updatedAt": 1728394010, updatedAt: 1728394010,
"createdAt": 1598476302, createdAt: 1598476302,
"scannedAt": 1893047135, scannedAt: 1893047135,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 5293874, contentChangedAt: 5293874,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 29, id: 29,
"path": "/Movies (Documentaries)" path: "/Movies (Documentaries)"
}, },
{ {
"id": 15, id: 15,
"path": "/Plex Library/Documentaries" path: "/Plex Library/Documentaries"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/15/composite/1893047145", composite: "/library/sections/15/composite/1893047145",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/movie.png", thumb: "/:/resources/movie.png",
"key": "15", key: "15",
"type": "movie", type: "movie",
"title": "Test Media Movies", title: "Test Media Movies",
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"scanner": "Plex Movie", scanner: "Plex Movie",
"language": "en-US", language: "en-US",
"uuid": "e5f67890a1b2c3d4", uuid: "e5f67890a1b2c3d4",
"updatedAt": 1689075000, updatedAt: 1689075000,
"createdAt": 1689075000, createdAt: 1689075000,
"scannedAt": 1893047145, scannedAt: 1893047145,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 5182738, contentChangedAt: 5182738,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 27, id: 27,
"path": "/TestMedia/Movies" path: "/TestMedia/Movies"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/3/composite/1893047110", composite: "/library/sections/3/composite/1893047110",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "3", key: "3",
"type": "show", type: "show",
"title": "Anime", title: "Anime",
"agent": "com.plexapp.agents.hama", agent: "com.plexapp.agents.hama",
"scanner": "Plex Series Scanner", scanner: "Plex Series Scanner",
"language": "en", language: "en",
"uuid": "f67890a1b2c3d4e5", uuid: "f67890a1b2c3d4e5",
"updatedAt": 1684970001, updatedAt: 1684970001,
"createdAt": 1598476000, createdAt: 1598476000,
"scannedAt": 1893047110, scannedAt: 1893047110,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 8379201, contentChangedAt: 8379201,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 17, id: 17,
"path": "/Anime" path: "/Anime"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/12/composite/1893047125", composite: "/library/sections/12/composite/1893047125",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "12", key: "12",
"type": "show", type: "show",
"title": "Kids Tv Shows NL", title: "Kids Tv Shows NL",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "nl-NL", language: "nl-NL",
"uuid": "67890a1b2c3d4e5f", uuid: "67890a1b2c3d4e5f",
"updatedAt": 1728394002, updatedAt: 1728394002,
"createdAt": 1680007400, createdAt: 1680007400,
"scannedAt": 1893047125, scannedAt: 1893047125,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 5948203, contentChangedAt: 5948203,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 22, id: 22,
"path": "/KidsTvShowsNL" path: "/KidsTvShowsNL"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/14/composite/1893047145", composite: "/library/sections/14/composite/1893047145",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "14", key: "14",
"type": "show", type: "show",
"title": "Reality TV (NL)", title: "Reality TV (NL)",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "nl-NL", language: "nl-NL",
"uuid": "890a1b2c3d4e5f67", uuid: "890a1b2c3d4e5f67",
"updatedAt": 1728394007, updatedAt: 1728394007,
"createdAt": 1601860600, createdAt: 1601860600,
"scannedAt": 1893047145, scannedAt: 1893047145,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 6283720, contentChangedAt: 6283720,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 26, id: 26,
"path": "/Reality TV NL" path: "/Reality TV NL"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/2/composite/1893047150", composite: "/library/sections/2/composite/1893047150",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "2", key: "2",
"type": "show", type: "show",
"title": "TV Series ", title: "TV Series ",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "en-US", language: "en-US",
"uuid": "a1b2c3d4e5f67890", uuid: "a1b2c3d4e5f67890",
"updatedAt": 1728394003, updatedAt: 1728394003,
"createdAt": 1598476100, createdAt: 1598476100,
"scannedAt": 1893047150, scannedAt: 1893047150,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 6472184, contentChangedAt: 6472184,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 32, id: 32,
"path": "/TV Shows" path: "/TV Shows"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/16/composite/1893047155", composite: "/library/sections/16/composite/1893047155",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "16", key: "16",
"type": "show", type: "show",
"title": "TV Shows (Documentaries)", title: "TV Shows (Documentaries)",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "en-US", language: "en-US",
"uuid": "b2c3d4e5f67890a1", uuid: "b2c3d4e5f67890a1",
"updatedAt": 1689076000, updatedAt: 1689076000,
"createdAt": 1689076000, createdAt: 1689076000,
"scannedAt": 1893047155, scannedAt: 1893047155,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 4920835, contentChangedAt: 4920835,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 28, id: 28,
"path": "/TV Shows (Documentaries)" path: "/TV Shows (Documentaries)"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/17/composite/1893047155", composite: "/library/sections/17/composite/1893047155",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "17", key: "17",
"type": "show", type: "show",
"title": "TV Shows (Kids)", title: "TV Shows (Kids)",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "en-US", language: "en-US",
"uuid": "c3d4e5f67890a1b2", uuid: "c3d4e5f67890a1b2",
"updatedAt": 1689077000, updatedAt: 1689077000,
"createdAt": 1689077000, createdAt: 1689077000,
"scannedAt": 1893047155, scannedAt: 1893047155,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 5309283, contentChangedAt: 5309283,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 31, id: 31,
"path": "/TV Shows (Kids)" path: "/TV Shows (Kids)"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/show-fanart.jpg", art: "/:/resources/show-fanart.jpg",
"composite": "/library/sections/10/composite/1893047170", composite: "/library/sections/10/composite/1893047170",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/show.png", thumb: "/:/resources/show.png",
"key": "10", key: "10",
"type": "show", type: "show",
"title": "TV Shows (Reality)", title: "TV Shows (Reality)",
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"scanner": "Plex TV Series", scanner: "Plex TV Series",
"language": "en-US", language: "en-US",
"uuid": "d4e5f67890a1b2c3", uuid: "d4e5f67890a1b2c3",
"updatedAt": 1689078000, updatedAt: 1689078000,
"createdAt": 1626704821, createdAt: 1626704821,
"scannedAt": 1893047170, scannedAt: 1893047170,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 7291885, contentChangedAt: 7291885,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 30, id: 30,
"path": "/TV Shows (Reality)" path: "/TV Shows (Reality)"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/artist-fanart.jpg", art: "/:/resources/artist-fanart.jpg",
"composite": "/library/sections/9/composite/1893047140", composite: "/library/sections/9/composite/1893047140",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/artist.png", thumb: "/:/resources/artist.png",
"key": "9", key: "9",
"type": "artist", type: "artist",
"title": "Music", title: "Music",
"agent": "tv.plex.agents.music", agent: "tv.plex.agents.music",
"scanner": "Plex Music", scanner: "Plex Music",
"language": "en-US", language: "en-US",
"uuid": "e5f67890a1b2c3d4", uuid: "e5f67890a1b2c3d4",
"updatedAt": 1684974922, updatedAt: 1684974922,
"createdAt": 1598476740, createdAt: 1598476740,
"scannedAt": 1893047140, scannedAt: 1893047140,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 7204063, contentChangedAt: 7204063,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 24, id: 24,
"path": "/Music" path: "/Music"
} }
] ]
}, },
{ {
"allowSync": true, allowSync: true,
"art": "/:/resources/movie-fanart.jpg", art: "/:/resources/movie-fanart.jpg",
"composite": "/library/sections/5/composite/1893047123", composite: "/library/sections/5/composite/1893047123",
"filters": true, filters: true,
"refreshing": false, refreshing: false,
"thumb": "/:/resources/video.png", thumb: "/:/resources/video.png",
"key": "5", key: "5",
"type": "movie", type: "movie",
"title": "Graduation", title: "Graduation",
"agent": "com.plexapp.agents.none", agent: "com.plexapp.agents.none",
"scanner": "Plex Video Files Scanner", scanner: "Plex Video Files Scanner",
"language": "xn", language: "xn",
"uuid": "f67890a1b2c3d4e5", uuid: "f67890a1b2c3d4e5",
"updatedAt": 1684974733, updatedAt: 1684974733,
"createdAt": 1598475949, createdAt: 1598475949,
"scannedAt": 1893047123, scannedAt: 1893047123,
"content": true, content: true,
"directory": true, directory: true,
"contentChangedAt": 3828909, contentChangedAt: 3828909,
"hidden": 0, hidden: 0,
"Location": [ Location: [
{ {
"id": 14, id: 14,
"path": "/Plex Library/Conspiracy" path: "/Plex Library/Conspiracy"
} }
] ]
} }
] ]
} }
}; }
validateResponseSpec("/library/sections", "get", 200, response) validateResponseSpec("/library/sections", "get", 200, response)
}); })
}) })

View File

@@ -1,221 +1,222 @@
import {validateResponseSpec} from "@utils"; import { validateResponseSpec } from "@utils"
import {describe, it} from 'vitest' import { describe, it } from "vitest"
describe('GET /media/providers', () => { describe("GET /media/providers", () => {
it('should validate the 200 response when the API spec is valid', () => { it("should validate the 200 response when the API spec is valid", () => {
const response = { const response = {
"MediaContainer": { MediaContainer: {
"size": 7, size: 7,
"allowCameraUpload": false, allowCameraUpload: false,
"allowChannelAccess": false, allowChannelAccess: false,
"allowSharing": true, allowSharing: true,
"allowSync": true, allowSync: true,
"allowTuners": false, allowTuners: false,
"backgroundProcessing": true, backgroundProcessing: true,
"certificate": true, certificate: true,
"companionProxy": true, companionProxy: true,
"countryCode": "uk", countryCode: "uk",
"diagnostics": "streaminglogs,databases", diagnostics: "streaminglogs,databases",
"eventStream": true, eventStream: true,
"friendlyName": "desktop-titan", friendlyName: "desktop-titan",
"livetv": 12, livetv: 12,
"machineIdentifier": "cf18e74b-7e92-403f-b95a-a99e1f83f77b", machineIdentifier: "cf18e74b-7e92-403f-b95a-a99e1f83f77b",
"musicAnalysis": 3, musicAnalysis: 3,
"myPlex": true, myPlex: true,
"myPlexMappingState": "linked", myPlexMappingState: "linked",
"myPlexSigninState": "active", myPlexSigninState: "active",
"myPlexSubscription": true, myPlexSubscription: true,
"myPlexUsername": "random.jason@outlook.com", myPlexUsername: "random.jason@outlook.com",
"offlineTranscode": 4, offlineTranscode: 4,
"ownerFeatures": "5f36ef7d-bf9e-48a4-9399-6fddf0ea47b8,2e5687c9-9e71-4712-aec5-0198a93ff56f,3b84a6a9-bcfa-438b-b732-62cb3fcb6732,7d197f42-dc48-4e7b-a758-b6d52ffb216d", ownerFeatures:
"platform": "Linux", "5f36ef7d-bf9e-48a4-9399-6fddf0ea47b8,2e5687c9-9e71-4712-aec5-0198a93ff56f,3b84a6a9-bcfa-438b-b732-62cb3fcb6732,7d197f42-dc48-4e7b-a758-b6d52ffb216d",
"platformVersion": "18.04 (Build 12345)", platform: "Linux",
"pluginHost": true, platformVersion: "18.04 (Build 12345)",
"pushNotifications": true, pluginHost: true,
"readOnlyLibraries": true, pushNotifications: true,
"streamingBrainABRVersion": 5, readOnlyLibraries: true,
"streamingBrainVersion": 4, streamingBrainABRVersion: 5,
"sync": true, streamingBrainVersion: 4,
"transcoderActiveVideoSessions": 2, sync: true,
"transcoderAudio": true, transcoderActiveVideoSessions: 2,
"transcoderLyrics": true, transcoderAudio: true,
"transcoderSubtitles": true, transcoderLyrics: true,
"transcoderVideo": true, transcoderSubtitles: true,
"transcoderVideoBitrates": "150,250,350,500,1000,2000,4000", transcoderVideo: true,
"transcoderVideoQualities": "2,3,5,7,9", transcoderVideoBitrates: "150,250,350,500,1000,2000,4000",
"transcoderVideoResolutions": "160,320,480,720,1080", transcoderVideoQualities: "2,3,5,7,9",
"updatedAt": 1835421007, transcoderVideoResolutions: "160,320,480,720,1080",
"updater": true, updatedAt: 1835421007,
"version": "3.40.9.1536-745a67c45", updater: true,
"voiceSearch": true, version: "3.40.9.1536-745a67c45",
"MediaProvider": [ voiceSearch: true,
MediaProvider: [
{ {
"identifier": "com.plexapp.plugins.library", identifier: "com.plexapp.plugins.library",
"title": "Random Library", title: "Random Library",
"types": "photo,audio,video", types: "photo,audio,video",
"protocols": "stream,http", protocols: "stream,http",
"Feature": [ Feature: [
{ {
"key": "/library/sections/new", key: "/library/sections/new",
"type": "content", type: "content",
"Directory": [ Directory: [
{ {
"hubKey": "/hubs/home", hubKey: "/hubs/home",
"title": "Main Hub" title: "Main Hub"
}, },
{ {
"agent": "tv.plex.agents.movie", agent: "tv.plex.agents.movie",
"language": "fr-FR", language: "fr-FR",
"refreshing": false, refreshing: false,
"scanner": "Random Movie Scanner", scanner: "Random Movie Scanner",
"uuid": "9b8e23c4-592c-4d3d-b2b6-7e5d1843c7a8", uuid: "9b8e23c4-592c-4d3d-b2b6-7e5d1843c7a8",
"id": "5", id: "5",
"key": "/library/sections/5", key: "/library/sections/5",
"hubKey": "/hubs/sections/5", hubKey: "/hubs/sections/5",
"type": "movie", type: "movie",
"title": "Films", title: "Films",
"updatedAt": 1835420739, updatedAt: 1835420739,
"scannedAt": 1835420123, scannedAt: 1835420123,
"Pivot": [ Pivot: [
{ {
"id": "recommended", id: "recommended",
"key": "/hubs/sections/5", key: "/hubs/sections/5",
"type": "hub", type: "hub",
"title": "Popular", title: "Popular",
"context": "content.popular", context: "content.popular",
"symbol": "star" symbol: "star"
}, },
{ {
"id": "library", id: "library",
"key": "/library/sections/5/all?type=5", key: "/library/sections/5/all?type=5",
"type": "list", type: "list",
"title": "Film Library", title: "Film Library",
"context": "content.library", context: "content.library",
"symbol": "library" symbol: "library"
}, },
{ {
"id": "categories", id: "categories",
"key": "/library/sections/5/categories", key: "/library/sections/5/categories",
"type": "list", type: "list",
"title": "Film Categories", title: "Film Categories",
"context": "content.categories", context: "content.categories",
"symbol": "stack" symbol: "stack"
} }
] ]
}, },
{ {
"agent": "tv.plex.agents.series", agent: "tv.plex.agents.series",
"language": "de-DE", language: "de-DE",
"refreshing": false, refreshing: false,
"scanner": "Random TV Series Scanner", scanner: "Random TV Series Scanner",
"uuid": "af5832e1-3246-4e31-9f48-b24f670d95d7", uuid: "af5832e1-3246-4e31-9f48-b24f670d95d7",
"id": "6", id: "6",
"key": "/library/sections/6", key: "/library/sections/6",
"hubKey": "/hubs/sections/6", hubKey: "/hubs/sections/6",
"type": "show", type: "show",
"title": "Shows", title: "Shows",
"updatedAt": 1835413943, updatedAt: 1835413943,
"scannedAt": 1835413688, scannedAt: 1835413688,
"Pivot": [ Pivot: [
{ {
"id": "trending", id: "trending",
"key": "/hubs/sections/6", key: "/hubs/sections/6",
"type": "hub", type: "hub",
"title": "Trending Shows", title: "Trending Shows",
"context": "content.trending", context: "content.trending",
"symbol": "fire" symbol: "fire"
}, },
{ {
"id": "library", id: "library",
"key": "/library/sections/6/all?type=6", key: "/library/sections/6/all?type=6",
"type": "list", type: "list",
"title": "TV Library", title: "TV Library",
"context": "content.library", context: "content.library",
"symbol": "library" symbol: "library"
}, },
{ {
"id": "categories", id: "categories",
"key": "/library/sections/6/categories", key: "/library/sections/6/categories",
"type": "list", type: "list",
"title": "Show Categories", title: "Show Categories",
"context": "content.categories", context: "content.categories",
"symbol": "stack" symbol: "stack"
} }
] ]
} }
] ]
}, },
{ {
"key": "/hubs/search/new", key: "/hubs/search/new",
"type": "search" type: "search"
}, },
{ {
"key": "/library/matches/new", key: "/library/matches/new",
"type": "match" type: "match"
}, },
{ {
"key": "/library/metadata/new", key: "/library/metadata/new",
"type": "metadata" type: "metadata"
}, },
{ {
"key": "/photo/:/transcode", key: "/photo/:/transcode",
"type": "imagetranscoder" type: "imagetranscoder"
}, },
{ {
"key": "/hubs/promoted/new", key: "/hubs/promoted/new",
"type": "promoted" type: "promoted"
}, },
{ {
"key": "/hubs/continueWatching/new", key: "/hubs/continueWatching/new",
"type": "continuewatching" type: "continuewatching"
}, },
{ {
"key": "/actions/new", key: "/actions/new",
"type": "actions", type: "actions",
"Action": [ Action: [
{ {
"id": "addToContinueWatching", id: "addToContinueWatching",
"key": "/actions/addToContinueWatching" key: "/actions/addToContinueWatching"
} }
] ]
}, },
{ {
"flavor": "global", flavor: "global",
"key": "/playlists/new", key: "/playlists/new",
"type": "playlist" type: "playlist"
}, },
{ {
"flavor": "global", flavor: "global",
"key": "/playQueues/new", key: "/playQueues/new",
"type": "playqueue" type: "playqueue"
}, },
{ {
"key": "/library/collections/new", key: "/library/collections/new",
"type": "collection" type: "collection"
}, },
{ {
"scrobbleKey": "/:/scrobble/new", scrobbleKey: "/:/scrobble/new",
"unscrobbleKey": "/:/unscrobble/new", unscrobbleKey: "/:/unscrobble/new",
"key": "/:/timeline/new", key: "/:/timeline/new",
"type": "timeline" type: "timeline"
}, },
{ {
"type": "queryParser" type: "queryParser"
}, },
{ {
"flavor": "global", flavor: "global",
"type": "subscribe" type: "subscribe"
}, },
{ {
"key": "/library/search/new", key: "/library/search/new",
"type": "universalsearch" type: "universalsearch"
} }
] ]
} }
] ]
} }
} ; }
validateResponseSpec("/media/providers", "get", 200, response) validateResponseSpec("/media/providers", "get", 200, response)
}); })
}) })

View File

@@ -1,236 +1,320 @@
import {validateResponseSpec} from "../../utils/"; import { validateResponseSpec } from "../../utils/"
import {describe, expect, it} from 'vitest' import { describe, expect, it } from "vitest"
describe('POST /users/signin', () => { describe("POST /users/signin", () => {
it('should validate the 201 response when the API spec is valid', () => { it("should validate the 201 response when the API spec is valid", () => {
const response = { const response = {
"id": 62735028, id: 62735028,
"uuid": "b9h6f3c8k1", uuid: "b9h6f3c8k1",
"username": "ZjFvKLCb", username: "ZjFvKLCb",
"title": "ZjFvKLCb", title: "ZjFvKLCb",
"email": "c9eMdShR@example.com", email: "c9eMdShR@example.com",
"friendlyName": "", friendlyName: "",
"locale": null, locale: null,
"confirmed": false, confirmed: false,
"joinedAt": 1552593531, joinedAt: 1552593531,
"emailOnlyAuth": false, emailOnlyAuth: false,
"hasPassword": true, hasPassword: true,
"protected": false, protected: false,
"thumb": "https://plex.tv/users/b9h6f3c8k1/avatar?c=1724402119", thumb: "https://plex.tv/users/b9h6f3c8k1/avatar?c=1724402119",
"authToken": "jx9nTbVbHk1gM", authToken: "jx9nTbVbHk1gM",
"mailingListStatus": "unsubscribed", mailingListStatus: "unsubscribed",
"mailingListActive": false, mailingListActive: false,
"scrobbleTypes": "", scrobbleTypes: "",
"country": "ES", country: "ES",
"subscription": { subscription: {
"active": false, active: false,
"subscribedAt": "2019-03-16T15:20:12Z", subscribedAt: "2019-03-16T15:20:12Z",
"status": "Inactive", status: "Inactive",
"paymentService": null, paymentService: null,
"plan": null, plan: null,
"features": ["guided-upgrade", "increase-password-complexity", "upgrade-3ds2", "ad-countdown-timer", "adaptive_bitrate", "amazon-loop-debug", "Android - Dolby Vision", "Android - PiP", "avod-ad-analysis", "avod-new-media", "blacklist_get_signin", "CU Sunset", "client-radio-stations", "cloudflare-turnstile-required", "comments_and_replies_push_notifications", "friend_request_push_notifications", "community_access_plex_tv", "companions_sonos", "custom-home-removal", "disable_home_user_friendships", "disable_sharing_friendships", "drm_support", "le_isrg_root_x1", "federated-auth", "home", "HRK_enable_EUR", "ios14-privacy-banner", "iterable-notification-tokens", "keep-payment-method", "kevin-bacon", "korea-consent", "lets_encrypt", "lightning-dvr-pivot", "livetv", "live-tv-support-incomplete-segments", "tuner-sharing", "metadata_search", "vod_cloudflare", "new_plex_pass_prices", "news-provider-sunset-modal", "photos-favorites", "photos-metadata-edition", "pms_health", "rate-limit-client-token", "shared_server_notification", "shared_source_notification", "scrobbling-service-plex-tv", "collections", "radio", "exclude restrictions", "signin_with_apple", "spring_serve_ad_provider", "transcoder_cache", "TREBLE-show-features", "two-factor-authentication", "unsupportedtuners", "vod-schema", "watch-together-invite", "web_server_dashboard"] features: [
"guided-upgrade",
"increase-password-complexity",
"upgrade-3ds2",
"ad-countdown-timer",
"adaptive_bitrate",
"amazon-loop-debug",
"Android - Dolby Vision",
"Android - PiP",
"avod-ad-analysis",
"avod-new-media",
"blacklist_get_signin",
"CU Sunset",
"client-radio-stations",
"cloudflare-turnstile-required",
"comments_and_replies_push_notifications",
"friend_request_push_notifications",
"community_access_plex_tv",
"companions_sonos",
"custom-home-removal",
"disable_home_user_friendships",
"disable_sharing_friendships",
"drm_support",
"le_isrg_root_x1",
"federated-auth",
"home",
"HRK_enable_EUR",
"ios14-privacy-banner",
"iterable-notification-tokens",
"keep-payment-method",
"kevin-bacon",
"korea-consent",
"lets_encrypt",
"lightning-dvr-pivot",
"livetv",
"live-tv-support-incomplete-segments",
"tuner-sharing",
"metadata_search",
"vod_cloudflare",
"new_plex_pass_prices",
"news-provider-sunset-modal",
"photos-favorites",
"photos-metadata-edition",
"pms_health",
"rate-limit-client-token",
"shared_server_notification",
"shared_source_notification",
"scrobbling-service-plex-tv",
"collections",
"radio",
"exclude restrictions",
"signin_with_apple",
"spring_serve_ad_provider",
"transcoder_cache",
"TREBLE-show-features",
"two-factor-authentication",
"unsupportedtuners",
"vod-schema",
"watch-together-invite",
"web_server_dashboard"
]
}, },
"subscriptionDescription": null, subscriptionDescription: null,
"restricted": false, restricted: false,
"anonymous": false, anonymous: false,
"home": false, home: false,
"guest": false, guest: false,
"homeSize": 1, homeSize: 1,
"homeAdmin": false, homeAdmin: false,
"maxHomeSize": 15, maxHomeSize: 15,
"rememberExpiresAt": 1725611719, rememberExpiresAt: 1725611719,
"profile": { profile: {
"autoSelectAudio": true, autoSelectAudio: true,
"defaultAudioLanguage": "ja", defaultAudioLanguage: "ja",
"defaultSubtitleLanguage": "en", defaultSubtitleLanguage: "en",
"autoSelectSubtitle": 1, autoSelectSubtitle: 1,
"defaultSubtitleAccessibility": 0, defaultSubtitleAccessibility: 0,
"defaultSubtitleForced": 0, defaultSubtitleForced: 0,
"watchedIndicator": 1, watchedIndicator: 1,
"mediaReviewsVisibility": 0 mediaReviewsVisibility: 0
}, },
"entitlements": [], entitlements: [],
"subscriptions": [], subscriptions: [],
"pastSubscriptions": [{ pastSubscriptions: [
"id": null, {
"mode": null, id: null,
"renewsAt": null, mode: null,
"endsAt": 1556281940, renewsAt: null,
"billing": { endsAt: 1556281940,
"paymentMethodId": null, "internalPaymentMethod": {} billing: {
paymentMethodId: null,
internalPaymentMethod: {}
}, },
"canceled": false, canceled: false,
"gracePeriod": false, gracePeriod: false,
"onHold": false, onHold: false,
"canReactivate": false, canReactivate: false,
"canUpgrade": false, canUpgrade: false,
"canDowngrade": false, canDowngrade: false,
"canConvert": false, canConvert: false,
"type": "plexpass", type: "plexpass",
"transfer": null, transfer: null,
"state": "ended" state: "ended"
}], }
"trials": [], ],
"services": [{ trials: [],
"identifier": "epg", services: [
"endpoint": "https://epg.provider.plex.tv", {
"token": "d2h7zUjKgT5oLwQ3cQ6d", identifier: "epg",
"secret": null, endpoint: "https://epg.provider.plex.tv",
"status": "online" token: "d2h7zUjKgT5oLwQ3cQ6d",
}, { secret: null,
"identifier": "epg-staging", status: "online"
"endpoint": "https://epg-staging.provider.plex.tv", },
"token": "r7m1nVfPhU4eRwM7eR5a", {
"secret": null, identifier: "epg-staging",
"status": "online" endpoint: "https://epg-staging.provider.plex.tv",
}, { token: "r7m1nVfPhU4eRwM7eR5a",
"identifier": "epg-dev", secret: null,
"endpoint": "https://epg-dev.provider.plex.tv", status: "online"
"token": "z4w2sLxPbJ3iRkY2hN8f", },
"secret": null, {
"status": "online" identifier: "epg-dev",
}, { endpoint: "https://epg-dev.provider.plex.tv",
"identifier": "eyeq", token: "z4w2sLxPbJ3iRkY2hN8f",
"endpoint": "https://c4412416.ipg.web.cddbp.net/webapi/xml/1.0/", secret: null,
"token": "g1v9kWxHdT3jNiY6dF4b", status: "online"
"secret": null, },
"status": "online" {
}, { identifier: "eyeq",
"identifier": "eyeq-channel-icons", endpoint: "https://c4412416.ipg.web.cddbp.net/webapi/xml/1.0/",
"endpoint": "http://akamai-b.cdn.cddbp.net/cds/2.0/image", token: "g1v9kWxHdT3jNiY6dF4b",
"token": null, secret: null,
"secret": null, status: "online"
"status": "online" },
}, { {
"identifier": "graph-dev", identifier: "eyeq-channel-icons",
"endpoint": "https://community-dev.plex.tv", endpoint: "http://akamai-b.cdn.cddbp.net/cds/2.0/image",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, { },
"identifier": "graph-staging", {
"endpoint": "https://community-staging.plex.tv", identifier: "graph-dev",
"token": null, endpoint: "https://community-dev.plex.tv",
"secret": null, token: null,
"status": "online" secret: null,
}, { status: "online"
"identifier": "community-dev", },
"endpoint": "https://community-dev.plex.tv", {
"token": null, identifier: "graph-staging",
"secret": null, endpoint: "https://community-staging.plex.tv",
"status": "online" token: null,
}, { secret: null,
"identifier": "community-staging", status: "online"
"endpoint": "https://community-staging.plex.tv", },
"token": null, {
"secret": null, identifier: "community-dev",
"status": "online" endpoint: "https://community-dev.plex.tv",
}, { token: null,
"identifier": "community", secret: null,
"endpoint": "https://community.plex.tv", status: "online"
"token": null, },
"secret": null, {
"status": "online" identifier: "community-staging",
}, { endpoint: "https://community-staging.plex.tv",
"identifier": "metadata", token: null,
"endpoint": "https://metadata.provider.plex.tv", secret: null,
"token": "h5z3rQxLhJ2lRyB4gN7v", status: "online"
"secret": null, },
"status": "online" {
}, { identifier: "community",
"identifier": "scrobbling", endpoint: "https://community.plex.tv",
"endpoint": "https://scrobbles.plex.tv", token: null,
"token": "s6y1wTxFpL7jMxC3nR8e", secret: null,
"secret": null, status: "online"
"status": "online" },
}, { {
"identifier": "metadata-dev", identifier: "metadata",
"endpoint": "https://metadata-dev.provider.plex.tv", endpoint: "https://metadata.provider.plex.tv",
"token": "j2h4tWmNpO3lRyD7vF9x", token: "h5z3rQxLhJ2lRyB4gN7v",
"secret": null, secret: null,
"status": "online" status: "online"
}, { },
"identifier": "metadata-provider", {
"endpoint": "https://mpm.plex.tv/", identifier: "scrobbling",
"token": null, endpoint: "https://scrobbles.plex.tv",
"secret": null, token: "s6y1wTxFpL7jMxC3nR8e",
"status": "online" secret: null,
}, { status: "online"
"identifier": "tmsapi", },
"endpoint": "https://tmsapi.plex.tv/v1.1/", {
"token": "p7c8xVhLpM5oTzQ1wR2b", identifier: "metadata-dev",
"secret": null, endpoint: "https://metadata-dev.provider.plex.tv",
"status": "online" token: "j2h4tWmNpO3lRyD7vF9x",
}, { secret: null,
"identifier": "subtitles-search", status: "online"
"endpoint": "https://metadata.provider.plex.tv/library/streams/matches", },
"token": "t8f3kWqNhP6uLyX4mC2y", {
"secret": null, identifier: "metadata-provider",
"status": "online" endpoint: "https://mpm.plex.tv/",
}, { token: null,
"identifier": "acoustid", secret: null,
"endpoint": "https://acoustid.plex.tv/", status: "online"
"token": "l5n7rQxHpV2oRyD9gF6b", },
"secret": null, {
"status": "online" identifier: "tmsapi",
}, { endpoint: "https://tmsapi.plex.tv/v1.1/",
"identifier": "lyricfind", token: "p7c8xVhLpM5oTzQ1wR2b",
"endpoint": "https://lyricfind.plex.tv/", secret: null,
"token": "m3y4tUjKlN8fMxC7oQ2b", status: "online"
"secret": "a1d5vWxHpQ6oLyT4gR3c", },
"status": "online" {
}, { identifier: "subtitles-search",
"identifier": "lyricfind-search", endpoint: "https://metadata.provider.plex.tv/library/streams/matches",
"endpoint": "https://lyricfind.plex.tv/", token: "t8f3kWqNhP6uLyX4mC2y",
"token": "q6c8wTxFpO9kLrZ2hV5b", secret: null,
"secret": null, status: "online"
"status": "online" },
}, { {
"identifier": "tvdb", identifier: "acoustid",
"endpoint": "https://api4.thetvdb.com/", endpoint: "https://acoustid.plex.tv/",
"token": "r4h7zUjMgL1fTzN3yP5x", token: "l5n7rQxHpV2oRyD9gF6b",
"secret": null, secret: null,
"status": "online" status: "online"
}], },
"adsConsent": null, {
"adsConsentSetAt": null, identifier: "lyricfind",
"adsConsentReminderAt": null, endpoint: "https://lyricfind.plex.tv/",
"experimentalFeatures": false, token: "m3y4tUjKlN8fMxC7oQ2b",
"twoFactorEnabled": false, secret: "a1d5vWxHpQ6oLyT4gR3c",
"backupCodesCreated": false, status: "online"
"attributionPartner": null },
}; {
identifier: "lyricfind-search",
endpoint: "https://lyricfind.plex.tv/",
token: "q6c8wTxFpO9kLrZ2hV5b",
secret: null,
status: "online"
},
{
identifier: "tvdb",
endpoint: "https://api4.thetvdb.com/",
token: "r4h7zUjMgL1fTzN3yP5x",
secret: null,
status: "online"
}
],
adsConsent: null,
adsConsentSetAt: null,
adsConsentReminderAt: null,
experimentalFeatures: false,
twoFactorEnabled: false,
backupCodesCreated: false,
attributionPartner: null
}
validateResponseSpec("/users/signin", "post", 201, response) validateResponseSpec("/users/signin", "post", 201, response)
}); })
it('should validate the 201 response when the API spec is valid', () => { it("should validate the 201 response when the API spec is valid", () => {
const response = { const response = {
"id": 475829302, id: 475829302,
"uuid": "a1b2c3d4e5f67890", uuid: "a1b2c3d4e5f67890",
"username": "user12345", username: "user12345",
"title": "user12345", title: "user12345",
"email": "user12345@example.com", email: "user12345@example.com",
"friendlyName": "", friendlyName: "",
"locale": null, locale: null,
"confirmed": false, confirmed: false,
"joinedAt": 1633376532, joinedAt: 1633376532,
"emailOnlyAuth": false, emailOnlyAuth: false,
"hasPassword": true, hasPassword: true,
"protected": false, protected: false,
"thumb": "https://plex.tv/users/a1b2c3d4e5f67890/avatar?c=1234567890", thumb: "https://plex.tv/users/a1b2c3d4e5f67890/avatar?c=1234567890",
"authToken": "gHjKlMnOpQrStUvWxYz", authToken: "gHjKlMnOpQrStUvWxYz",
"mailingListStatus": "active", mailingListStatus: "active",
"mailingListActive": true, mailingListActive: true,
"scrobbleTypes": "", scrobbleTypes: "",
"country": "IT", country: "IT",
"subscription": { subscription: {
"active": false, active: false,
"subscribedAt": null, subscribedAt: null,
"status": "Inactive", status: "Inactive",
"paymentService": null, paymentService: null,
"plan": null, plan: null,
"features": [ features: [
"guided-upgrade", "guided-upgrade",
"increase-password-complexity", "increase-password-complexity",
"upgrade-3ds2", "upgrade-3ds2",
@@ -290,174 +374,172 @@ describe('POST /users/signin', () => {
"web_server_dashboard" "web_server_dashboard"
] ]
}, },
"subscriptionDescription": null, subscriptionDescription: null,
"restricted": false, restricted: false,
"anonymous": null, anonymous: null,
"home": false, home: false,
"guest": false, guest: false,
"homeSize": 1, homeSize: 1,
"homeAdmin": false, homeAdmin: false,
"maxHomeSize": 15, maxHomeSize: 15,
"rememberExpiresAt": 1725684008, rememberExpiresAt: 1725684008,
"profile": { profile: {
"autoSelectAudio": true, autoSelectAudio: true,
"defaultAudioLanguage": null, defaultAudioLanguage: null,
"defaultSubtitleLanguage": null, defaultSubtitleLanguage: null,
"autoSelectSubtitle": 1, autoSelectSubtitle: 1,
"defaultSubtitleAccessibility": 0, defaultSubtitleAccessibility: 0,
"defaultSubtitleForced": 0, defaultSubtitleForced: 0,
"watchedIndicator": 1, watchedIndicator: 1,
"mediaReviewsVisibility": 0 mediaReviewsVisibility: 0
}, },
"entitlements": [], entitlements: [],
"subscriptions": [], subscriptions: [],
"pastSubscriptions": [], pastSubscriptions: [],
"trials": [], trials: [],
"services": [ services: [
{ {
"identifier": "epg", identifier: "epg",
"endpoint": "https://epg.provider.plex.tv", endpoint: "https://epg.provider.plex.tv",
"token": "A1B2C3D4E5F6G7H8I9J0", token: "A1B2C3D4E5F6G7H8I9J0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "epg-staging", identifier: "epg-staging",
"endpoint": "https://epg-staging.provider.plex.tv", endpoint: "https://epg-staging.provider.plex.tv",
"token": "J9I8H7G6F5E4D3C2B1A0", token: "J9I8H7G6F5E4D3C2B1A0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "epg-dev", identifier: "epg-dev",
"endpoint": "https://epg-dev.provider.plex.tv", endpoint: "https://epg-dev.provider.plex.tv",
"token": "0J9I8H7G6F5E4D3C2B1A", token: "0J9I8H7G6F5E4D3C2B1A",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "eyeq", identifier: "eyeq",
"endpoint": "https://c4412416.ipg.web.cddbp.net/webapi/xml/1.0/", endpoint: "https://c4412416.ipg.web.cddbp.net/webapi/xml/1.0/",
"token": "Z1X2C3V4B5N6M7Q8W9R0", token: "Z1X2C3V4B5N6M7Q8W9R0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "eyeq-channel-icons", identifier: "eyeq-channel-icons",
"endpoint": "http://akamai-b.cdn.cddbp.net/cds/2.0/image", endpoint: "http://akamai-b.cdn.cddbp.net/cds/2.0/image",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "graph-dev", identifier: "graph-dev",
"endpoint": "https://community-dev.plex.tv", endpoint: "https://community-dev.plex.tv",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "graph-staging", identifier: "graph-staging",
"endpoint": "https://community-staging.plex.tv", endpoint: "https://community-staging.plex.tv",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "community-dev", identifier: "community-dev",
"endpoint": "https://community-dev.plex.tv", endpoint: "https://community-dev.plex.tv",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "community-staging", identifier: "community-staging",
"endpoint": "https://community-staging.plex.tv", endpoint: "https://community-staging.plex.tv",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "community", identifier: "community",
"endpoint": "https://community.plex.tv", endpoint: "https://community.plex.tv",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "metadata", identifier: "metadata",
"endpoint": "https://metadata.provider.plex.tv", endpoint: "https://metadata.provider.plex.tv",
"token": "K1L2M3N4O5P6Q7R8S9T0", token: "K1L2M3N4O5P6Q7R8S9T0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "metadata-dev", identifier: "metadata-dev",
"endpoint": "https://metadata-dev.provider.plex.tv", endpoint: "https://metadata-dev.provider.plex.tv",
"token": "T0S9R8Q7P6O5N4M3L2K1", token: "T0S9R8Q7P6O5N4M3L2K1",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "metadata-provider", identifier: "metadata-provider",
"endpoint": "https://mpm.plex.tv/", endpoint: "https://mpm.plex.tv/",
"token": null, token: null,
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "tmsapi", identifier: "tmsapi",
"endpoint": "https://tmsapi.plex.tv/v1.1/", endpoint: "https://tmsapi.plex.tv/v1.1/",
"token": "F1G2H3J4K5L6M7N8O9P0", token: "F1G2H3J4K5L6M7N8O9P0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "subtitles-search", identifier: "subtitles-search",
"endpoint": "https://metadata.provider.plex.tv/library/streams/matches", endpoint: "https://metadata.provider.plex.tv/library/streams/matches",
"token": "Q1W2E3R4T5Y6U7I8O9P0", token: "Q1W2E3R4T5Y6U7I8O9P0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "acoustid", identifier: "acoustid",
"endpoint": "https://acoustid.plex.tv/", endpoint: "https://acoustid.plex.tv/",
"token": "1A2S3D4F5G6H7J8K9L0", token: "1A2S3D4F5G6H7J8K9L0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "lyricfind", identifier: "lyricfind",
"endpoint": "https://lyricfind.plex.tv/", endpoint: "https://lyricfind.plex.tv/",
"token": "Z9X8C7V6B5N4M3Q2W1E0", token: "Z9X8C7V6B5N4M3Q2W1E0",
"secret": "X1C2V3B4N5M6Q7W8E9R0", secret: "X1C2V3B4N5M6Q7W8E9R0",
"status": "online" status: "online"
}, },
{ {
"identifier": "lyricfind-search", identifier: "lyricfind-search",
"endpoint": "https://lyricfind.plex.tv/", endpoint: "https://lyricfind.plex.tv/",
"token": "F6D5S4A3J2K1L8P7O9M0", token: "F6D5S4A3J2K1L8P7O9M0",
"secret": null, secret: null,
"status": "online" status: "online"
}, },
{ {
"identifier": "tvdb", identifier: "tvdb",
"endpoint": "https://api4.thetvdb.com/", endpoint: "https://api4.thetvdb.com/",
"token": "L1K2J3H4G5F6D7S8A9P0", token: "L1K2J3H4G5F6D7S8A9P0",
"secret": null, secret: null,
"status": "online" status: "online"
} }
], ],
"adsConsent": null, adsConsent: null,
"adsConsentSetAt": null, adsConsentSetAt: null,
"adsConsentReminderAt": null, adsConsentReminderAt: null,
"experimentalFeatures": false, experimentalFeatures: false,
"twoFactorEnabled": false, twoFactorEnabled: false,
"backupCodesCreated": false, backupCodesCreated: false,
"attributionPartner": null attributionPartner: null
} }
;
validateResponseSpec("/users/signin", "post", 201, response) validateResponseSpec("/users/signin", "post", 201, response)
}) })
}) })

View File

@@ -1,25 +1,26 @@
import PMSSpec from '../../output/plex-media-server-spec-dereferenced.yaml'; import PMSSpec from "../../output/plex-media-server-spec-dereferenced.yaml"
import Ajv from "ajv"; import Ajv from "ajv"
import addFormats from "ajv-formats"; import addFormats from "ajv-formats"
import {expect} from 'vitest' import { expect } from "vitest"
export function validateResponseSpec(path: string, type: 'get' | 'post' | 'delete', statusCode: number, response: any): void {
const ajv = new Ajv({allErrors: true, strict: false});
ajv.addSchema(PMSSpec, "API.yaml");
addFormats(ajv);
export function validateResponseSpec(
path: string,
type: "get" | "post" | "delete",
statusCode: number,
response: any
): void {
const ajv = new Ajv({ allErrors: true, strict: false })
ajv.addSchema(PMSSpec, "API.yaml")
addFormats(ajv)
// Convert JSONPath to JSON Pointer // Convert JSONPath to JSON Pointer
const pathPointer = `/paths/${path.replace(/\//g, `~1`)}/${type}/responses/${statusCode}/content/application~1json/schema` const pathPointer = `/paths/${path.replace(/\//g, `~1`)}/${type}/responses/${statusCode}/content/application~1json/schema`
const validate = ajv.validate({$ref: "API.yaml#" + pathPointer}, response); const validate = ajv.validate({ $ref: "API.yaml#" + pathPointer }, response)
if (!validate) { if (!validate) {
console.error(ajv.errors); console.error(ajv.errors)
} }
expect(validate).toBe(true); expect(validate).toBe(true)
} }

View File

@@ -1 +1 @@
export * from './import.js'; export * from "./import.js"

View File

@@ -4,16 +4,10 @@
"outDir": "./output", "outDir": "./output",
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": ["./src/*"],
"@utils": [ "@utils": ["./tests/utils/index.ts"]
"./tests/utils/index.ts"
]
}, },
"types": [ "types": ["@modyfi/vite-plugin-yaml/modules"],
"@modyfi/vite-plugin-yaml/modules"
],
"skipLibCheck": true "skipLibCheck": true
}, },
"exclude": [ "exclude": ["node_modules"]
"node_modules"
]
} }

View File

@@ -1,7 +1,7 @@
import ViteYaml from '@modyfi/vite-plugin-yaml'; import ViteYaml from "@modyfi/vite-plugin-yaml"
import tsconfigPaths from 'vite-tsconfig-paths' import tsconfigPaths from "vite-tsconfig-paths"
import { defineConfig } from 'vite' import { defineConfig } from "vite"
export default defineConfig({ export default defineConfig({
plugins: [tsconfigPaths(), ViteYaml()], plugins: [tsconfigPaths(), ViteYaml()]
}) })