mirror of
https://github.com/Mastermindzh/tidal-hifi.git
synced 2024-11-25 23:03:52 +01:00
feat: dependency udpate & openapi extension
This commit is contained in:
parent
4e827e120f
commit
268027734c
@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [5.15.0]
|
||||||
|
|
||||||
|
- Added all missing swagger/openApi info with the help of [Times-Z](https://github.com/Times-Z)
|
||||||
|
- Updated most dependency versions
|
||||||
|
- This includes Electron 31!
|
||||||
|
|
||||||
## [5.14.1]
|
## [5.14.1]
|
||||||
|
|
||||||
- Fixed `getAlbumName` not finding album name whilst on queue page
|
- Fixed `getAlbumName` not finding album name whilst on queue page
|
||||||
|
@ -26,7 +26,7 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
|
|||||||
- [Using source](#using-source)
|
- [Using source](#using-source)
|
||||||
- [Integrations](#integrations)
|
- [Integrations](#integrations)
|
||||||
- [Known bugs](#known-bugs)
|
- [Known bugs](#known-bugs)
|
||||||
- [DRM not working on Windows](#drm-not-working-on-windows)
|
- [DRM not working on Windows (error S6007)](#drm-not-working-on-windows-error-s6007)
|
||||||
- [Special thanks to](#special-thanks-to)
|
- [Special thanks to](#special-thanks-to)
|
||||||
- [Donations](#donations)
|
- [Donations](#donations)
|
||||||
- [Images](#images)
|
- [Images](#images)
|
||||||
@ -153,11 +153,13 @@ Integrations with other projects that are not included natively:
|
|||||||
|
|
||||||
## Known bugs
|
## Known bugs
|
||||||
|
|
||||||
### DRM not working on Windows
|
### DRM not working on Windows (error S6007)
|
||||||
|
|
||||||
Most Windows users run into DRM issues when trying to use TIDAL Hi-Fi.
|
Most Windows users run into DRM issues when trying to use TIDAL Hi-Fi.
|
||||||
Nothing I can do about that I'm afraid... Tidal is working on removing/changing DRM so when they finish with that we can give it another shot.
|
Nothing I can do about that I'm afraid... Tidal is working on removing/changing DRM so when they finish with that we can give it another shot.
|
||||||
|
|
||||||
|
Until then you'll have to use the official app unfortunately.
|
||||||
|
|
||||||
## Special thanks to
|
## Special thanks to
|
||||||
|
|
||||||
- [Castlabs](https://castlabs.com/)
|
- [Castlabs](https://castlabs.com/)
|
||||||
|
1263
package-lock.json
generated
1263
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tidal-hifi",
|
"name": "tidal-hifi",
|
||||||
"version": "5.14.1",
|
"version": "5.15.0",
|
||||||
"description": "Tidal on Electron with widevine(hifi) support",
|
"description": "Tidal on Electron with widevine(hifi) support",
|
||||||
"main": "ts-dist/main.js",
|
"main": "ts-dist/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -45,12 +45,12 @@
|
|||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"discord-rpc": "^4.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
"electron-store": "^8.2.0",
|
"electron-store": "^8.0.0",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"hotkeys-js": "^3.13.7",
|
"hotkeys-js": "^3.13.7",
|
||||||
"mpris-service": "^2.1.2",
|
"mpris-service": "^2.1.2",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"sass": "^1.77.5",
|
"sass": "^1.77.6",
|
||||||
"swagger-ui-express": "^5.0.1"
|
"swagger-ui-express": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -58,27 +58,27 @@
|
|||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/discord-rpc": "^4.0.8",
|
"@types/discord-rpc": "^4.0.8",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/node": "^20.12.12",
|
"@types/node": "^20.14.10",
|
||||||
"@types/request": "^2.48.12",
|
"@types/request": "^2.48.12",
|
||||||
"@types/swagger-ui-express": "^4.1.6",
|
"@types/swagger-ui-express": "^4.1.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.18.0",
|
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||||
"@typescript-eslint/parser": "^6.18.0",
|
"@typescript-eslint/parser": "^7.15.0",
|
||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"electron": "git+https://github.com/castlabs/electron-releases#v28.1.1+wvcus",
|
"electron": "git+https://github.com/castlabs/electron-releases#v31.1.0+wvcus",
|
||||||
"electron-builder": "^24.9.1",
|
"electron-builder": "~24.9.1",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"markdown-toc": "^1.2.0",
|
"markdown-toc": "^1.2.0",
|
||||||
"nodemon": "^3.0.2",
|
"nodemon": "^3.1.4",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.3.2",
|
||||||
"stylelint": "^16.1.0",
|
"stylelint": "^16.6.1",
|
||||||
"stylelint-config-standard": "^36.0.0",
|
"stylelint-config-standard": "^36.0.1",
|
||||||
"stylelint-config-standard-scss": "^13.0.0",
|
"stylelint-config-standard-scss": "^13.1.0",
|
||||||
"stylelint-prettier": "^5.0.0",
|
"stylelint-prettier": "^5.0.0",
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.2.0",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.5.3"
|
||||||
},
|
},
|
||||||
"prettier": "@mastermindzh/prettier-config"
|
"prettier": "@mastermindzh/prettier-config"
|
||||||
}
|
}
|
@ -3,7 +3,110 @@ import fs from "fs";
|
|||||||
import { mediaInfo } from "../../../scripts/mediaInfo";
|
import { mediaInfo } from "../../../scripts/mediaInfo";
|
||||||
|
|
||||||
export const addCurrentInfo = (expressApp: Router) => {
|
export const addCurrentInfo = (expressApp: Router) => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: current
|
||||||
|
* description: The current media info API
|
||||||
|
* components:
|
||||||
|
* schemas:
|
||||||
|
* MediaInfo:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* title:
|
||||||
|
* type: string
|
||||||
|
* artists:
|
||||||
|
* type: string
|
||||||
|
* album:
|
||||||
|
* type: string
|
||||||
|
* icon:
|
||||||
|
* type: string
|
||||||
|
* format: uri
|
||||||
|
* playingFrom:
|
||||||
|
* type: string
|
||||||
|
* status:
|
||||||
|
* type: string
|
||||||
|
* url:
|
||||||
|
* type: string
|
||||||
|
* format: uri
|
||||||
|
* current:
|
||||||
|
* type: string
|
||||||
|
* currentInSeconds:
|
||||||
|
* type: integer
|
||||||
|
* duration:
|
||||||
|
* type: string
|
||||||
|
* durationInSeconds:
|
||||||
|
* type: integer
|
||||||
|
* image:
|
||||||
|
* type: string
|
||||||
|
* format: uri
|
||||||
|
* favorite:
|
||||||
|
* type: boolean
|
||||||
|
* player:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* status:
|
||||||
|
* type: string
|
||||||
|
* shuffle:
|
||||||
|
* type: boolean
|
||||||
|
* repeat:
|
||||||
|
* type: string
|
||||||
|
* artist:
|
||||||
|
* type: string
|
||||||
|
* example:
|
||||||
|
* title: "Sample Title"
|
||||||
|
* artists: "Sample Artist"
|
||||||
|
* album: "Sample Album"
|
||||||
|
* icon: "/path/to/sample/icon.jpg"
|
||||||
|
* playingFrom: "Sample Playlist"
|
||||||
|
* status: "playing"
|
||||||
|
* url: "https://tidal.com/browse/track/sample"
|
||||||
|
* current: "1:23"
|
||||||
|
* currentInSeconds: 83
|
||||||
|
* duration: "3:45"
|
||||||
|
* durationInSeconds: 225
|
||||||
|
* image: "https://example.com/sample-image.jpg"
|
||||||
|
* favorite: true
|
||||||
|
* player:
|
||||||
|
* status: "playing"
|
||||||
|
* shuffle: true
|
||||||
|
* repeat: "one"
|
||||||
|
* artist: "Sample Artist"
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /current:
|
||||||
|
* get:
|
||||||
|
* summary: Get current media info
|
||||||
|
* tags: [current]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Current media info
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/MediaInfo'
|
||||||
|
*/
|
||||||
expressApp.get("/current", (req, res) => res.json({ ...mediaInfo, artist: mediaInfo.artists }));
|
expressApp.get("/current", (req, res) => res.json({ ...mediaInfo, artist: mediaInfo.artists }));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /current/image:
|
||||||
|
* get:
|
||||||
|
* summary: Get current media image
|
||||||
|
* tags: [current]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Current media image
|
||||||
|
* content:
|
||||||
|
* image/png:
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* format: binary
|
||||||
|
* 404:
|
||||||
|
* description: Not found
|
||||||
|
*/
|
||||||
expressApp.get("/current/image", getCurrentImage);
|
expressApp.get("/current/image", getCurrentImage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
import { BrowserWindow } from "electron";
|
import { BrowserWindow } from "electron";
|
||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { globalEvents } from "../../../constants/globalEvents";
|
import { globalEvents } from "../../../constants/globalEvents";
|
||||||
@ -12,19 +11,148 @@ export const addPlaybackControl = (expressApp: Router, mainWindow: BrowserWindow
|
|||||||
const windowEvent = handleWindowEvent(mainWindow);
|
const windowEvent = handleWindowEvent(mainWindow);
|
||||||
const createRoute = (route: string) => `/player${route}`;
|
const createRoute = (route: string) => `/player${route}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: player
|
||||||
|
* description: The player control API
|
||||||
|
* components:
|
||||||
|
* schemas:
|
||||||
|
* OkResponse:
|
||||||
|
* type: string
|
||||||
|
* example: "OK"
|
||||||
|
*/
|
||||||
const createPlayerAction = (route: string, action: string) => {
|
const createPlayerAction = (route: string, action: string) => {
|
||||||
expressApp.post(createRoute(route), (req, res) => windowEvent(res, action));
|
expressApp.post(createRoute(route), (req, res) => windowEvent(res, action));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (settingsStore.get(settings.playBackControl)) {
|
if (settingsStore.get(settings.playBackControl)) {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/play:
|
||||||
|
* post:
|
||||||
|
* summary: Play the current media
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/play", globalEvents.play);
|
createPlayerAction("/play", globalEvents.play);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/favorite/toggle:
|
||||||
|
* post:
|
||||||
|
* summary: Add the current media to your favorites, or remove it if its already added to your favorites
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/favorite/toggle", globalEvents.toggleFavorite);
|
createPlayerAction("/favorite/toggle", globalEvents.toggleFavorite);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/pause:
|
||||||
|
* post:
|
||||||
|
* summary: Pause the current media
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/pause", globalEvents.pause);
|
createPlayerAction("/pause", globalEvents.pause);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/next:
|
||||||
|
* post:
|
||||||
|
* summary: Play the next song
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/next", globalEvents.next);
|
createPlayerAction("/next", globalEvents.next);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/previous:
|
||||||
|
* post:
|
||||||
|
* summary: Play the previous song
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/previous", globalEvents.previous);
|
createPlayerAction("/previous", globalEvents.previous);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/shuffle/toggle:
|
||||||
|
* post:
|
||||||
|
* summary: Play the previous song
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/shuffle/toggle", globalEvents.toggleShuffle);
|
createPlayerAction("/shuffle/toggle", globalEvents.toggleShuffle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/repeat/toggle:
|
||||||
|
* post:
|
||||||
|
* summary: Toggle the repeat status, toggles between "off" , "single" and "all"
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
createPlayerAction("/repeat/toggle", globalEvents.toggleRepeat);
|
createPlayerAction("/repeat/toggle", globalEvents.toggleRepeat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /player/playpause:
|
||||||
|
* post:
|
||||||
|
* summary: Start playing the media if paused, or pause the media if playing
|
||||||
|
* tags: [player]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.post(createRoute("/playpause"), (req, res) => {
|
expressApp.post(createRoute("/playpause"), (req, res) => {
|
||||||
if (mediaInfo.status === MediaStatus.playing) {
|
if (mediaInfo.status === MediaStatus.playing) {
|
||||||
windowEvent(res, globalEvents.pause);
|
windowEvent(res, globalEvents.pause);
|
||||||
|
@ -13,19 +13,132 @@ import { getCurrentImage } from "./features/current";
|
|||||||
* @param mainWindow
|
* @param mainWindow
|
||||||
*/
|
*/
|
||||||
export const addLegacyApi = (expressApp: Router, mainWindow: BrowserWindow) => {
|
export const addLegacyApi = (expressApp: Router, mainWindow: BrowserWindow) => {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /image:
|
||||||
|
* get:
|
||||||
|
* summary: Get current image
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Current image
|
||||||
|
* content:
|
||||||
|
* image/png:
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* format: binary
|
||||||
|
* 404:
|
||||||
|
* description: Not found
|
||||||
|
*/
|
||||||
expressApp.get("/image", getCurrentImage);
|
expressApp.get("/image", getCurrentImage);
|
||||||
|
|
||||||
if (settingsStore.get(settings.playBackControl)) {
|
if (settingsStore.get(settings.playBackControl)) {
|
||||||
addLegacyControls();
|
addLegacyControls();
|
||||||
}
|
}
|
||||||
function addLegacyControls() {
|
function addLegacyControls() {
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /play:
|
||||||
|
* get:
|
||||||
|
* summary: Play the current media
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Action performed
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.get("/play", ({ res }) => handleGlobalEvent(res, globalEvents.play));
|
expressApp.get("/play", ({ res }) => handleGlobalEvent(res, globalEvents.play));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /favorite/toggle:
|
||||||
|
* get:
|
||||||
|
* summary: Add the current media to your favorites, or remove it if its already added to your favorites
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.post("/favorite/toggle", (req, res) =>
|
expressApp.post("/favorite/toggle", (req, res) =>
|
||||||
handleGlobalEvent(res, globalEvents.toggleFavorite)
|
handleGlobalEvent(res, globalEvents.toggleFavorite)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /pause:
|
||||||
|
* get:
|
||||||
|
* summary: Pause the current media
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.get("/pause", (req, res) => handleGlobalEvent(res, globalEvents.pause));
|
expressApp.get("/pause", (req, res) => handleGlobalEvent(res, globalEvents.pause));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /next:
|
||||||
|
* get:
|
||||||
|
* summary: Play the next song
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.get("/next", (req, res) => handleGlobalEvent(res, globalEvents.next));
|
expressApp.get("/next", (req, res) => handleGlobalEvent(res, globalEvents.next));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /previous:
|
||||||
|
* get:
|
||||||
|
* summary: Play the previous song
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.get("/previous", (req, res) => handleGlobalEvent(res, globalEvents.previous));
|
expressApp.get("/previous", (req, res) => handleGlobalEvent(res, globalEvents.previous));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /playpause:
|
||||||
|
* get:
|
||||||
|
* summary: Toggle play/pause
|
||||||
|
* tags: [legacy]
|
||||||
|
* deprecated: true
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Ok
|
||||||
|
* content:
|
||||||
|
* text/plain:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/OkResponse'
|
||||||
|
*/
|
||||||
expressApp.get("/playpause", (req, res) => {
|
expressApp.get("/playpause", (req, res) => {
|
||||||
if (mediaInfo.status === MediaStatus.playing) {
|
if (mediaInfo.status === MediaStatus.playing) {
|
||||||
handleGlobalEvent(res, globalEvents.pause);
|
handleGlobalEvent(res, globalEvents.pause);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"openapi": "3.1.0",
|
"openapi": "3.1.0",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "TIDAL Hi-Fi API",
|
"title": "TIDAL Hi-Fi API",
|
||||||
"version": "5.14.1",
|
"version": "5.15.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": {
|
"license": {
|
||||||
"name": "MIT",
|
"name": "MIT",
|
||||||
@ -18,6 +18,210 @@
|
|||||||
"url": "swagger.json"
|
"url": "swagger.json"
|
||||||
},
|
},
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/current": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get current media info",
|
||||||
|
"tags": [
|
||||||
|
"current"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Current media info",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/MediaInfo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/current/image": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get current media image",
|
||||||
|
"tags": [
|
||||||
|
"current"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Current media image",
|
||||||
|
"content": {
|
||||||
|
"image/png": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "binary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/play": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Play the current media",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/favorite/toggle": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Add the current media to your favorites, or remove it if its already added to your favorites",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/pause": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Pause the current media",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/next": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Play the next song",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/previous": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Play the previous song",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/shuffle/toggle": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Play the previous song",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/repeat/toggle": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Toggle the repeat status, toggles between \"off\" , \"single\" and \"all\"",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/player/playpause": {
|
||||||
|
"post": {
|
||||||
|
"summary": "Start playing the media if paused, or pause the media if playing",
|
||||||
|
"tags": [
|
||||||
|
"player"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/settings/skipped-artists": {
|
"/settings/skipped-artists": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "get a list of artists that TIDAL Hi-Fi will skip if skipping is enabled",
|
"summary": "get a list of artists that TIDAL Hi-Fi will skip if skipping is enabled",
|
||||||
@ -105,10 +309,250 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/image": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get current image",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Current image",
|
||||||
|
"content": {
|
||||||
|
"image/png": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "binary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/play": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Play the current media",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Action performed",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/favorite/toggle": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Add the current media to your favorites, or remove it if its already added to your favorites",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/pause": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Pause the current media",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/next": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Play the next song",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/previous": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Play the previous song",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/playpause": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Toggle play/pause",
|
||||||
|
"tags": [
|
||||||
|
"legacy"
|
||||||
|
],
|
||||||
|
"deprecated": true,
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ok",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/OkResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
"MediaInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"artists": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"album": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
|
"playingFrom": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
|
"current": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"currentInSeconds": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"duration": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"durationInSeconds": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
|
"favorite": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"player": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shuffle": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"repeat": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"artist": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"title": "Sample Title",
|
||||||
|
"artists": "Sample Artist",
|
||||||
|
"album": "Sample Album",
|
||||||
|
"icon": "/path/to/sample/icon.jpg",
|
||||||
|
"playingFrom": "Sample Playlist",
|
||||||
|
"status": "playing",
|
||||||
|
"url": "https://tidal.com/browse/track/sample",
|
||||||
|
"current": "1:23",
|
||||||
|
"currentInSeconds": 83,
|
||||||
|
"duration": "3:45",
|
||||||
|
"durationInSeconds": 225,
|
||||||
|
"image": "https://example.com/sample-image.jpg",
|
||||||
|
"favorite": true,
|
||||||
|
"player": {
|
||||||
|
"status": "playing",
|
||||||
|
"shuffle": true,
|
||||||
|
"repeat": "one"
|
||||||
|
},
|
||||||
|
"artist": "Sample Artist"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OkResponse": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "OK"
|
||||||
|
},
|
||||||
"StringArray": {
|
"StringArray": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
@ -122,6 +566,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": [
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "current",
|
||||||
|
"description": "The current media info API"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "player",
|
||||||
|
"description": "The player control API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "settings",
|
"name": "settings",
|
||||||
"description": "The settings management API"
|
"description": "The settings management API"
|
||||||
|
@ -147,7 +147,7 @@
|
|||||||
<p class="group__title">API</p>
|
<p class="group__title">API</p>
|
||||||
<div class="group__description">
|
<div class="group__description">
|
||||||
<p>
|
<p>
|
||||||
TIDAL Hi-Fi has a built-in web API to allow users to get current song information.
|
TIDAL Hi-Fi has a built-in web API to allow users to get current media information.
|
||||||
You can optionally enable playback control as well.
|
You can optionally enable playback control as well.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -246,7 +246,7 @@
|
|||||||
<div class="group__option" class="hidden">
|
<div class="group__option" class="hidden">
|
||||||
<div class="group__description">
|
<div class="group__description">
|
||||||
<h4>Show song</h4>
|
<h4>Show song</h4>
|
||||||
<p>Show the current song in the Discord client</p>
|
<p>Show the current media in the Discord client</p>
|
||||||
</div>
|
</div>
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
<input id="discord_show_song" type="checkbox" />
|
<input id="discord_show_song" type="checkbox" />
|
||||||
@ -443,7 +443,7 @@
|
|||||||
<h4>TIDAL Hi-Fi</h4>
|
<h4>TIDAL Hi-Fi</h4>
|
||||||
<div class="about-section__version">
|
<div class="about-section__version">
|
||||||
<a target="_blank" rel="noopener"
|
<a target="_blank" rel="noopener"
|
||||||
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.14.1">5.14.1</a>
|
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.15.0">5.15.0</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="about-section__links">
|
<div class="about-section__links">
|
||||||
<a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/"
|
<a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/"
|
||||||
|
@ -74,7 +74,7 @@ const elements = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the icon of the current song
|
* Get the icon of the current media
|
||||||
*/
|
*/
|
||||||
getSongIcon: function () {
|
getSongIcon: function () {
|
||||||
const figure = this.get("media");
|
const figure = this.get("media");
|
||||||
@ -90,7 +90,7 @@ const elements = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns an array of all artists in the current song
|
* returns an array of all artists in the current media
|
||||||
* @returns {Array} artists
|
* @returns {Array} artists
|
||||||
*/
|
*/
|
||||||
getArtistsArray: function () {
|
getArtistsArray: function () {
|
||||||
@ -195,7 +195,7 @@ function getUpdateFrequency() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Play or pause the current song
|
* Play or pause the current media
|
||||||
*/
|
*/
|
||||||
function playPause() {
|
function playPause() {
|
||||||
const play = elements.get("play");
|
const play = elements.get("play");
|
||||||
|
Loading…
Reference in New Issue
Block a user