feat: API now allows you to set the so you can control who can interact with the API.

This commit is contained in:
Rick van Lieshout 2024-06-09 13:07:49 +02:00
parent 0a8efc730d
commit 5b656ae229
7 changed files with 34 additions and 6 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Simplified `MediaInfo` & `Options` types - Simplified `MediaInfo` & `Options` types
- Added `playingFrom` information to the info API - Added `playingFrom` information to the info API
- also changed the way we update Album info since Playing From now shows the correct Album. - also changed the way we update Album info since Playing From now shows the correct Album.
- API now allows you to set the `hostname` so you can control who can interact with the API.
## [5.13.1] ## [5.13.1]

View File

@ -50,6 +50,7 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
- [ListenBrainz](https://listenbrainz.org/?redirect=false) integration - [ListenBrainz](https://listenbrainz.org/?redirect=false) integration
- Songwhip.com integration (hotkey `ctrl + w`) - Songwhip.com integration (hotkey `ctrl + w`)
- Discord RPC integration (showing "now listening", "Browsing", etc) - Discord RPC integration (showing "now listening", "Browsing", etc)
- Flatpak version only works if both Discord and Tidal-HiFi are flatpaks
- MPRIS integration - MPRIS integration
- UI + Json config (`~/.config/tidal-hifi/`, or `~/.var/app/com.mastermindzh.tidal-hifi/` for Flatpak) - UI + Json config (`~/.config/tidal-hifi/`, or `~/.var/app/com.mastermindzh.tidal-hifi/` for Flatpak)

View File

@ -14,6 +14,7 @@ export const settings = {
apiSettings: { apiSettings: {
root: "apiSettings", root: "apiSettings",
port: "apiSettings.port", port: "apiSettings.port",
hostname: "apiSettings.hostname",
}, },
customCSS: "customCSS", customCSS: "customCSS",
disableBackgroundThrottle: "disableBackgroundThrottle", disableBackgroundThrottle: "disableBackgroundThrottle",

View File

@ -1,7 +1,6 @@
import cors from "cors";
import { BrowserWindow, dialog } from "electron"; import { BrowserWindow, dialog } from "electron";
import express from "express"; import express from "express";
import swaggerSpec from "./swagger.json";
import cors from "cors";
import swaggerUi from "swagger-ui-express"; import swaggerUi from "swagger-ui-express";
import { settingsStore } from "../../scripts/settings"; import { settingsStore } from "../../scripts/settings";
import { settings } from "./../../constants/settings"; import { settings } from "./../../constants/settings";
@ -9,12 +8,14 @@ import { addCurrentInfo } from "./features/current";
import { addPlaybackControl } from "./features/player"; import { addPlaybackControl } from "./features/player";
import { addSettingsAPI } from "./features/settings/settings"; import { addSettingsAPI } from "./features/settings/settings";
import { addLegacyApi } from "./legacy"; import { addLegacyApi } from "./legacy";
import swaggerSpec from "./swagger.json";
/** /**
* Function to enable TIDAL Hi-Fi's express api * Function to enable TIDAL Hi-Fi's express api
*/ */
export const startApi = (mainWindow: BrowserWindow) => { export const startApi = (mainWindow: BrowserWindow) => {
const port = settingsStore.get<string, number>(settings.apiSettings.port); const port = settingsStore.get<string, number>(settings.apiSettings.port);
const hostname = settingsStore.get<string, string>(settings.apiSettings.hostname) ?? "127.0.0.1";
const expressApp = express(); const expressApp = express();
expressApp.use(cors()); expressApp.use(cors());
@ -29,7 +30,7 @@ export const startApi = (mainWindow: BrowserWindow) => {
addCurrentInfo(expressApp); addCurrentInfo(expressApp);
addSettingsAPI(expressApp, mainWindow); addSettingsAPI(expressApp, mainWindow);
const expressInstance = expressApp.listen(port, "127.0.0.1"); const expressInstance = expressApp.listen(port, hostname);
expressInstance.on("error", function (e: { code: string }) { expressInstance.on("error", function (e: { code: string }) {
let message = e.code; let message = e.code;
if (e.code === "EADDRINUSE") { if (e.code === "EADDRINUSE") {

View File

@ -24,7 +24,7 @@ const switchesWithSettings = {
switch: "discord_show_song", switch: "discord_show_song",
classToHide: "discord_show_song_options", classToHide: "discord_show_song_options",
settingsKey: settings.discord.showSong, settingsKey: settings.discord.showSong,
} },
}; };
let adBlock: HTMLInputElement, let adBlock: HTMLInputElement,
@ -35,6 +35,7 @@ let adBlock: HTMLInputElement,
enableCustomHotkeys: HTMLInputElement, enableCustomHotkeys: HTMLInputElement,
enableDiscord: HTMLInputElement, enableDiscord: HTMLInputElement,
gpuRasterization: HTMLInputElement, gpuRasterization: HTMLInputElement,
hostname: HTMLInputElement,
menuBar: HTMLInputElement, menuBar: HTMLInputElement,
minimizeOnClose: HTMLInputElement, minimizeOnClose: HTMLInputElement,
mpris: HTMLInputElement, mpris: HTMLInputElement,
@ -127,6 +128,7 @@ function refreshSettings() {
enableDiscord.checked = settingsStore.get(settings.enableDiscord); enableDiscord.checked = settingsStore.get(settings.enableDiscord);
enableWaylandSupport.checked = settingsStore.get(settings.flags.enableWaylandSupport); enableWaylandSupport.checked = settingsStore.get(settings.flags.enableWaylandSupport);
gpuRasterization.checked = settingsStore.get(settings.flags.gpuRasterization); gpuRasterization.checked = settingsStore.get(settings.flags.gpuRasterization);
hostname.value = settingsStore.get(settings.apiSettings.hostname);
menuBar.checked = settingsStore.get(settings.menuBar); menuBar.checked = settingsStore.get(settings.menuBar);
minimizeOnClose.checked = settingsStore.get(settings.minimizeOnClose); minimizeOnClose.checked = settingsStore.get(settings.minimizeOnClose);
mpris.checked = settingsStore.get(settings.mpris); mpris.checked = settingsStore.get(settings.mpris);
@ -243,6 +245,7 @@ window.addEventListener("DOMContentLoaded", () => {
enableDiscord = get("enableDiscord"); enableDiscord = get("enableDiscord");
enableWaylandSupport = get("enableWaylandSupport"); enableWaylandSupport = get("enableWaylandSupport");
gpuRasterization = get("gpuRasterization"); gpuRasterization = get("gpuRasterization");
hostname = get("hostname");
menuBar = get("menuBar"); menuBar = get("menuBar");
minimizeOnClose = get("minimizeOnClose"); minimizeOnClose = get("minimizeOnClose");
mpris = get("mprisCheckbox"); mpris = get("mprisCheckbox");
@ -264,7 +267,7 @@ window.addEventListener("DOMContentLoaded", () => {
discord_button_text = get("discord_button_text"); discord_button_text = get("discord_button_text");
discord_show_song = get("discord_show_song"); discord_show_song = get("discord_show_song");
discord_using_text = get("discord_using_text"); discord_using_text = get("discord_using_text");
discord_idle_text = get("discord_idle_text") discord_idle_text = get("discord_idle_text");
refreshSettings(); refreshSettings();
addInputListener(adBlock, settings.adBlock); addInputListener(adBlock, settings.adBlock);
@ -276,6 +279,7 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(enableDiscord, settings.enableDiscord, switchesWithSettings.discord); addInputListener(enableDiscord, settings.enableDiscord, switchesWithSettings.discord);
addInputListener(enableWaylandSupport, settings.flags.enableWaylandSupport); addInputListener(enableWaylandSupport, settings.flags.enableWaylandSupport);
addInputListener(gpuRasterization, settings.flags.gpuRasterization); addInputListener(gpuRasterization, settings.flags.gpuRasterization);
addInputListener(hostname, settings.apiSettings.hostname);
addInputListener(menuBar, settings.menuBar); addInputListener(menuBar, settings.menuBar);
addInputListener(minimizeOnClose, settings.minimizeOnClose); addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(mpris, settings.mpris); addInputListener(mpris, settings.mpris);
@ -299,7 +303,11 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(discord_details_prefix, settings.discord.detailsPrefix); addInputListener(discord_details_prefix, settings.discord.detailsPrefix);
addInputListener(discord_include_timestamps, settings.discord.includeTimestamps); addInputListener(discord_include_timestamps, settings.discord.includeTimestamps);
addInputListener(discord_button_text, settings.discord.buttonText); addInputListener(discord_button_text, settings.discord.buttonText);
addInputListener(discord_show_song, settings.discord.showSong, switchesWithSettings.discord_show_song); addInputListener(
discord_show_song,
settings.discord.showSong,
switchesWithSettings.discord_show_song
);
addInputListener(discord_idle_text, settings.discord.idleText); addInputListener(discord_idle_text, settings.discord.idleText);
addInputListener(discord_using_text, settings.discord.usingText); addInputListener(discord_using_text, settings.discord.usingText);
}); });

View File

@ -167,6 +167,16 @@
<input id="port" type="number" class="text-input" name="port" /> <input id="port" type="number" class="text-input" name="port" />
</div> </div>
</div> </div>
<div class="group__option">
<div class="group__description">
<h4>API hostname</h4>
<p>By default (127.0.0.1) only local apps can interface with the API. <br />
Change to 0.0.0.0 to allow <strong>anyone</strong> to interact with it. <br />
Other options are available
</p>
<input id="hostname" type="text" class="text-input" name="hostname" />
</div>
</div>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>Playback control</h4> <h4>Playback control</h4>

View File

@ -31,6 +31,7 @@ export const settingsStore = new Store({
api: true, api: true,
apiSettings: { apiSettings: {
port: 47836, port: 47836,
hostname: "127.0.0.1",
}, },
customCSS: [], customCSS: [],
disableBackgroundThrottle: true, disableBackgroundThrottle: true,
@ -101,6 +102,11 @@ export const settingsStore = new Store({
}, },
]); ]);
}, },
"5.14.0": (migrationStore) => {
buildMigration("5.14.0", migrationStore, [
{ key: settings.apiSettings.hostname, value: "127.0.0.1" },
]);
},
}, },
}); });