Compare commits

..

30 Commits

Author SHA1 Message Date
aa7d0a615b Merge 635f1940f8 into 4e827e120f 2024-07-09 15:25:06 +00:00
635f1940f8 Update package.json 2024-07-09 17:25:04 +02:00
4c60067fc6 22.4 verified locally 2024-07-07 12:22:35 +02:00
625c5498d4 bumping node version to 20 2024-07-07 12:08:11 +02:00
6ac25ca857 Merge branch 'master' of github.com:Mastermindzh/tidal-hifi into develop 2024-07-07 11:53:33 +02:00
1f856eedbd Extended openApi info + deps update 2024-07-07 11:51:04 +02:00
4e827e120f Merge pull request #431 from Mastermindzh/snyk-upgrade-de4b5154b7445fb3cf5ec389f4c5715f
[Snyk] Upgrade sass from 1.77.4 to 1.77.5
2024-07-04 10:23:34 +02:00
snyk-bot
5b62154ebc fix: upgrade sass from 1.77.4 to 1.77.5
Snyk has created this PR to upgrade sass from 1.77.4 to 1.77.5.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-07-03 05:18:29 +00:00
8b09759e5e Merge pull request #424 from Times-Z/master
doc: update swagger with all routes
2024-06-25 09:49:55 +02:00
22b4668639 docs: updated swagger docs for player and legacy 2024-06-25 09:46:45 +02:00
15cc6bb6d4 Merge pull request #425 from Mastermindzh/snyk-upgrade-f3026437cbeaad8aa72daea7d39ede0c
[Snyk] Upgrade sass from 1.77.2 to 1.77.4
2024-06-24 11:26:17 +02:00
e0e9d99173 Merge branch 'master' into snyk-upgrade-f3026437cbeaad8aa72daea7d39ede0c 2024-06-24 11:13:10 +02:00
daa797fc00 Merge pull request #427 from Mastermindzh/snyk-upgrade-fc345622b53226751fadf4ff2a3da0b1
[Snyk] Upgrade swagger-ui-express from 5.0.0 to 5.0.1
2024-06-24 10:56:04 +02:00
snyk-bot
4e011a47d8 fix: upgrade swagger-ui-express from 5.0.0 to 5.0.1
Snyk has created this PR to upgrade swagger-ui-express from 5.0.0 to 5.0.1.

See this package in npm:
swagger-ui-express

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-22 20:28:34 +00:00
snyk-bot
965d19318e fix: upgrade sass from 1.77.2 to 1.77.4
Snyk has created this PR to upgrade sass from 1.77.2 to 1.77.4.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-21 20:55:14 +00:00
TimesZ
403354186e doc: update swagger with all routes & deprecated old image api route 2024-06-21 19:08:27 +02:00
9cd89c9f31 Merge pull request #423 from Mastermindzh/dependabot/npm_and_yarn/ws-7.5.10
chore(deps): bump ws from 7.5.9 to 7.5.10
2024-06-20 15:10:02 +02:00
dependabot[bot]
c7b97a49c4 chore(deps): bump ws from 7.5.9 to 7.5.10
Bumps [ws](https://github.com/websockets/ws) from 7.5.9 to 7.5.10.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.5.9...7.5.10)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 19:01:45 +00:00
c63e05357e Update README.md 2024-06-16 05:23:28 +02:00
42dac4a7f1 Merge pull request #420 from Mastermindzh/snyk-upgrade-9156bcae7d2be2477cf56414a066139f
[Snyk] Upgrade axios from 1.7.1 to 1.7.2
2024-06-13 13:38:10 +02:00
snyk-bot
595895dbc1 fix: upgrade axios from 1.7.1 to 1.7.2
Snyk has created this PR to upgrade axios from 1.7.1 to 1.7.2.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-13 05:53:24 +00:00
1ff94e45a7 Merge pull request #418 from Mastermindzh/dependabot/npm_and_yarn/braces-3.0.3
chore(deps): bump braces from 3.0.2 to 3.0.3
2024-06-11 10:28:50 +02:00
dependabot[bot]
95776d1aab chore(deps): bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-11 07:43:23 +00:00
5669cb4c6a Merge pull request #417 from Mastermindzh/snyk-upgrade-338b304353e209764e7b225a59b9a6ea
[Snyk] Upgrade sass from 1.75.0 to 1.77.2
2024-06-11 09:42:56 +02:00
5946c47442 Merge pull request #416 from Mastermindzh/snyk-upgrade-81ed892136e18f6714c0baec6619f4b2
[Snyk] Upgrade axios from 1.6.8 to 1.7.1
2024-06-11 09:42:39 +02:00
snyk-bot
111238f6b2 fix: upgrade sass from 1.75.0 to 1.77.2
Snyk has created this PR to upgrade sass from 1.75.0 to 1.77.2.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-11 04:40:11 +00:00
snyk-bot
65a4600c4d fix: upgrade axios from 1.6.8 to 1.7.1
Snyk has created this PR to upgrade axios from 1.6.8 to 1.7.1.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-06-11 04:40:07 +00:00
dd6f81386f Merge pull request #414 from Mastermindzh/version/next
fix: Fixed  not finding album name whilst on queue page
2024-06-09 18:51:37 +02:00
54316d31b5 Added all mediaInfo to mpris interface using the prefix 2024-06-09 16:16:25 +02:00
28a9458dfc fix: Fixed not finding album name whilst on queue page 2024-06-09 15:50:49 +02:00
13 changed files with 2388 additions and 866 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 22.4
- run: npm install
- run: npm run build
@@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 20
- run: npm install
- run: npm run build
@@ -41,6 +41,6 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 20
- run: npm install
- run: npm run build

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 22.4
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 20
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master
@@ -49,7 +49,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 19
node-version: 20
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master

View File

@@ -3,6 +3,18 @@
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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
<https://github.com/Times-Z>
## [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]
- Fixed `getAlbumName` not finding album name whilst on queue page
- Added all mediaInfo to mpris interface using the `custom:` prefix
## [5.14]

View File

@@ -26,7 +26,7 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
- [Using source](#using-source)
- [Integrations](#integrations)
- [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)
- [Donations](#donations)
- [Images](#images)
@@ -131,7 +131,7 @@ nix-env -iA nixpkgs.tidal-hifi
To install and work with the code on this project follow these steps:
- `git clone [https://github.com/Mastermindzh/tidal-hifi.git](https://github.com/Mastermindzh/tidal-hifi.git)`
- `git clone https://github.com/Mastermindzh/tidal-hifi.git`
- `cd tidal-hifi`
- `npm install`
- `npm run watch` to watch for auto-reload of Typescript/SCSS changes.
@@ -153,11 +153,13 @@ Integrations with other projects that are not included natively:
## 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.
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
- [Castlabs](https://castlabs.com/)

2352
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "5.14.0",
"version": "5.15.0",
"description": "Tidal on Electron with widevine(hifi) support",
"main": "ts-dist/main.js",
"scripts": {
@@ -42,43 +42,43 @@
"dependencies": {
"@electron/remote": "^2.1.2",
"@types/swagger-jsdoc": "^6.0.4",
"axios": "^1.6.8",
"axios": "^1.7.2",
"cors": "^2.8.5",
"discord-rpc": "^4.0.1",
"electron-store": "^8.2.0",
"electron-store": "^8.0.0",
"express": "^4.19.2",
"hotkeys-js": "^3.13.7",
"mpris-service": "^2.1.2",
"request": "^2.88.2",
"sass": "^1.75.0",
"swagger-ui-express": "^5.0.0"
"sass": "^1.77.6",
"swagger-ui-express": "^5.0.1"
},
"devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0",
"@types/cors": "^2.8.17",
"@types/discord-rpc": "^4.0.8",
"@types/express": "^4.17.21",
"@types/node": "^20.12.12",
"@types/node": "^20.14.10",
"@types/request": "^2.48.12",
"@types/swagger-ui-express": "^4.1.6",
"@typescript-eslint/eslint-plugin": "^6.18.0",
"@typescript-eslint/parser": "^6.18.0",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"copyfiles": "^2.4.1",
"electron": "git+https://github.com/castlabs/electron-releases#v28.1.1+wvcus",
"electron-builder": "^24.9.1",
"electron": "git+https://github.com/castlabs/electron-releases#v31.1.0+wvcus",
"electron-builder": "~24.13.3",
"eslint": "^8.56.0",
"js-yaml": "^4.1.0",
"markdown-toc": "^1.2.0",
"nodemon": "^3.0.2",
"prettier": "^3.1.1",
"stylelint": "^16.1.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-config-standard-scss": "^13.0.0",
"nodemon": "^3.1.4",
"prettier": "^3.3.2",
"stylelint": "^16.6.1",
"stylelint-config-standard": "^36.0.1",
"stylelint-config-standard-scss": "^13.1.0",
"stylelint-prettier": "^5.0.0",
"swagger-jsdoc": "^6.2.8",
"ts-node": "^10.9.2",
"tsc-watch": "^6.0.4",
"typescript": "^5.3.3"
"tsc-watch": "^6.2.0",
"typescript": "^5.5.3"
},
"prettier": "@mastermindzh/prettier-config"
}
}

View File

@@ -3,7 +3,110 @@ import fs from "fs";
import { mediaInfo } from "../../../scripts/mediaInfo";
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 }));
/**
* @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);
};

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { BrowserWindow } from "electron";
import { Router } from "express";
import { globalEvents } from "../../../constants/globalEvents";
@@ -12,19 +11,148 @@ export const addPlaybackControl = (expressApp: Router, mainWindow: BrowserWindow
const windowEvent = handleWindowEvent(mainWindow);
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) => {
expressApp.post(createRoute(route), (req, res) => windowEvent(res, action));
};
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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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) => {
if (mediaInfo.status === MediaStatus.playing) {
windowEvent(res, globalEvents.pause);

View File

@@ -13,19 +13,132 @@ import { getCurrentImage } from "./features/current";
* @param mainWindow
*/
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);
if (settingsStore.get(settings.playBackControl)) {
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));
/**
* @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) =>
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));
/**
* @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));
/**
* @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));
/**
* @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) => {
if (mediaInfo.status === MediaStatus.playing) {
handleGlobalEvent(res, globalEvents.pause);

View File

@@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "TIDAL Hi-Fi API",
"version": "5.14.0",
"version": "5.15.0",
"description": "",
"license": {
"name": "MIT",
@@ -18,6 +18,210 @@
"url": "swagger.json"
},
"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": {
"get": {
"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": {
"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": {
"type": "array",
"items": {
@@ -122,6 +566,14 @@
}
},
"tags": [
{
"name": "current",
"description": "The current media info API"
},
{
"name": "player",
"description": "The player control API"
},
{
"name": "settings",
"description": "The settings management API"

View File

@@ -147,7 +147,7 @@
<p class="group__title">API</p>
<div class="group__description">
<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.
</p>
</div>
@@ -246,7 +246,7 @@
<div class="group__option" class="hidden">
<div class="group__description">
<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>
<label class="switch">
<input id="discord_show_song" type="checkbox" />
@@ -443,7 +443,7 @@
<h4>TIDAL Hi-Fi</h4>
<div class="about-section__version">
<a target="_blank" rel="noopener"
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.14.0">5.14.0</a>
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.15.0">5.15.0</a>
</div>
<div class="about-section__links">
<a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/"

View File

@@ -18,6 +18,7 @@ import { MediaStatus } from "./models/mediaStatus";
import { RepeatState } from "./models/repeatState";
import { downloadFile } from "./scripts/download";
import { addHotkey } from "./scripts/hotkeys";
import { ObjectToDotNotation } from "./scripts/objectUtilities";
import { settingsStore } from "./scripts/settings";
import { setTitle } from "./scripts/window-functions";
@@ -58,6 +59,7 @@ const elements = {
mediaItem: "[data-type='mediaItem']",
album_header_title: '*[class^="playingFrom"] span:nth-child(2)',
playing_from: '*[class^="playingFrom"] span:nth-child(2)',
queue_album: "*[class^=playQueueItemsContainer] *[class^=groupTitle] span:nth-child(2)",
currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']",
album_name_cell: '[class^="album"]',
tracklist_row: '[data-test="tracklist-row"]',
@@ -72,7 +74,7 @@ const elements = {
},
/**
* Get the icon of the current song
* Get the icon of the current media
*/
getSongIcon: function () {
const figure = this.get("media");
@@ -88,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
*/
getArtistsArray: function () {
@@ -133,6 +135,12 @@ const elements = {
}
}
// see whether we're on the queue page and get it from there
const queueAlbumName = elements.getText("queue_album");
if (queueAlbumName) {
return queueAlbumName;
}
return "";
},
@@ -187,7 +195,7 @@ function getUpdateFrequency() {
}
/**
* Play or pause the current song
* Play or pause the current media
*/
function playPause() {
const play = elements.get("play");
@@ -467,6 +475,7 @@ function updateMpris(mediaInfo: MediaInfo) {
"mpris:length": convertDuration(mediaInfo.duration) * 1000 * 1000,
"mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(),
},
...ObjectToDotNotation(mediaInfo, "custom:"),
};
player.playbackStatus = mediaInfo.status === MediaStatus.paused ? "Paused" : "Playing";
}

View File

@@ -0,0 +1,13 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const ObjectToDotNotation = (obj: any, prefix: string = "", target: any = {}) => {
Object.keys(obj).forEach((key: string) => {
if (typeof obj[key] === "object" && obj[key] !== null) {
ObjectToDotNotation(obj[key], prefix + key + ".", target);
} else {
const dotLocation = prefix + key;
target[dotLocation] = obj[key];
return target;
}
});
return target;
};