Merge pull request #218 from thanasistrisp/adblocking

Add real Ad blocking using custom ad filters
This commit is contained in:
Rick van Lieshout 2023-04-21 11:31:24 +02:00 committed by GitHub
commit ba7b2a5717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 958 additions and 119 deletions

View File

@ -4,6 +4,11 @@ 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).
## 5.0.0
- Replaced "skipping arists" with a full implementation of an Adblock mechanism
> Disabled audio & visual ads, unlocked lyrics, suggested track, track info, unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495))
## 4.4.0
- Updated shortcut hint on the menubar to reflect the new `ctrl+=` shortcut.

View File

@ -1,34 +1,35 @@
<h1>
Tidal-hifi
<img src = "./build/icon.png" height="40" align="right" />
</h1>
# Tidal-hifi<img src = "./build/icon.png" height="40" align="right"/>
![GitHub release](https://img.shields.io/github/release/Mastermindzh/tidal-hifi.svg)
The web version of [listen.tidal.com](https://listen.tidal.com) running in electron with hifi support thanks to widevine.
![tidal-hifi preview](./docs/preview.png)
## Table of contents
## Table of Contents
<!-- toc -->
- [Tidal-hifi](#tidal-hifi)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
* [Using releases](#using-releases)
* [Snap](#snap)
* [Arch Linux](#arch-linux)
* [Flatpak](#flatpak)
* [Nix](#nix)
* [Using source](#using-source)
- [Using releases](#using-releases)
- [Snap](#snap)
- [Arch Linux](#arch-linux)
- [Flatpak](#flatpak)
- [Nix](#nix)
- [Using source](#using-source)
- [Features](#features)
- [Integrations](#integrations)
* [Known bugs](#known-bugs)
+ [last.fm doesn't work out of the box. Use rescrobbler as a workaround](#lastfm-doesnt-work-out-of-the-box-use-rescrobbler-as-a-workaround)
- [Known bugs](#known-bugs)
- [last.fm doesn't work out of the box. Use rescrobbler as a workaround](#lastfm-doesnt-work-out-of-the-box-use-rescrobbler-as-a-workaround)
- [Why](#why)
- [Why not extend existing projects?](#why-not-extend-existing-projects)
- [Special thanks to...](#special-thanks-to)
- [Buy me a coffee? Please don't](#buy-me-a-coffee-please-dont)
- [Images](#images)
* [Settings window](#settings-window)
* [User setups](#user-setups)
- [Settings window](#settings-window)
- [User setups](#user-setups)
<!-- tocstop -->
@ -93,7 +94,7 @@ To install and work with the code on this project follow these steps:
- Notifications
- Custom hotkeys ([source](https://defkey.com/tidal-desktop-shortcuts))
- API for status and playback
- [Mute artists automatically (defaults to "Tidal")]("./docs/muting-artists.md")
- Disabled audio & visual ads, unlocked lyrics, suggested track, track info, and unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495))
- Custom [integrations](#integrations)
- [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+=` or `ctrl+0`)
- AlbumArt in integrations ([best-effort](https://github.com/Mastermindzh/tidal-hifi/pull/88#pullrequestreview-840814847))
@ -139,7 +140,7 @@ Whilst there are a handful of projects attempting to run Tidal on Electron they
Sometimes it's just easier to start over, cover my own needs and then making it available to the public :)
## Special thanks to...
## Special thanks to
- [Castlabs](https://castlabs.com/)
For maintaining Electron with Widevine CDM installation, Verified Media Path (VMP), and persistent licenses (StorageID)

View File

@ -1,11 +0,0 @@
# Muting artists
If you feel that some of your music is embarrassing for others you can mute specific artists in the settings window.
This functionality is inspired by the [adblock ticket](https://github.com/Mastermindzh/tidal-hifi/issues/112), and whilst I personally feel you should simply buy Tidal, I also believe in muting sound that you don't want to hear.
Anyway, to block an artist, open the settings window (see image below) and enter a list of artists in the textarea as seen below.
Don't forget to turn the feature on and Tidal-hifi will automatically mute the player whenever that artist is playing.
This will allow you to skip the song without anyone noticing. (you can always say "no idea, it seems to have no audio").
![muted artists settings window](./settings-muted-artists.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

841
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "4.4.0",
"version": "5.0.0",
"description": "Tidal on Electron with widevine(hifi) support",
"main": "src/main.js",
"scripts": {
@ -45,6 +45,7 @@
"electron": "git+https://github.com/castlabs/electron-releases.git#v19.0.5+wvcus",
"electron-builder": "^23.3.3",
"js-yaml": "^3.14.1",
"markdown-toc": "^1.2.0",
"prettier": "^2.7.1",
"sass-lint": "^1.13.1",
"sass-lint-auto-fix": "^0.21.2"

View File

@ -13,10 +13,9 @@ const settings = {
api: "api",
menuBar: "menuBar",
playBackControl: "playBackControl",
muteArtists: "muteArtists",
mutedArtists: "mutedArtists",
skipArtists: "skipArtists",
skippedArtists: "skippedArtists",
adBlock: "adBlock",
disableBackgroundThrottle: "disableBackgroundThrottle",
apiSettings: {
root: "apiSettings",

View File

@ -1,5 +1,13 @@
require("@electron/remote/main").initialize();
const { app, BrowserWindow, components, globalShortcut, ipcMain, protocol } = require("electron");
const {
app,
BrowserWindow,
components,
globalShortcut,
ipcMain,
protocol,
session,
} = require("electron");
const {
settings,
store,
@ -146,6 +154,16 @@ function addGlobalShortcuts() {
app.on("ready", async () => {
if (isMainInstanceOrMultipleInstancesAllowed()) {
await components.whenReady();
// Adblock
if (store.get(settings.adBlock)) {
const filter = { urls: ["https://listen.tidal.com/*"] };
session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
if (details.url.match(/\d\?country/)) callback({ cancel: true });
else callback({ cancel: false });
});
}
createWindow();
addMenu(mainWindow);
createSettingsWindow();

View File

@ -3,15 +3,14 @@ let trayIcon,
mpris,
enableCustomHotkeys,
enableDiscord,
muteArtists,
skipArtists,
notifications,
playBackControl,
api,
port,
menuBar,
mutedArtists,
skippedArtists,
adBlock,
disableBackgroundThrottle,
singleInstance,
disableHardwareMediaKeys,
@ -36,10 +35,9 @@ function refreshSettings() {
enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
enableDiscord.checked = store.get(settings.enableDiscord);
minimizeOnClose.checked = store.get(settings.minimizeOnClose);
muteArtists.checked = store.get(settings.muteArtists);
mutedArtists.value = store.get(settings.mutedArtists).join("\n");
skipArtists.checked = store.get(settings.skipArtists);
skippedArtists.value = store.get(settings.skippedArtists).join("\n");
adBlock.checked = store.get(settings.adBlock);
singleInstance.checked = store.get(settings.singleInstance);
disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys);
gpuRasterization.checked = store.get(settings.flags.gpuRasterization);
@ -66,7 +64,7 @@ function hide() {
*/
function restart() {
app.relaunch();
app.quit();
app.exit();
}
/**
@ -121,10 +119,9 @@ window.addEventListener("DOMContentLoaded", () => {
mpris = get("mprisCheckbox");
enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord");
muteArtists = get("muteArtists");
mutedArtists = get("mutedArtists");
skipArtists = get("skipArtists");
skippedArtists = get("skippedArtists");
adBlock = get("adBlock");
disableBackgroundThrottle = get("disableBackgroundThrottle");
singleInstance = get("singleInstance");
disableHardwareMediaKeys = get("disableHardwareMediaKeys");
@ -142,10 +139,9 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord);
addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(muteArtists, settings.muteArtists);
addTextAreaListener(mutedArtists, settings.mutedArtists);
addInputListener(skipArtists, settings.skipArtists);
addTextAreaListener(skippedArtists, settings.skippedArtists);
addInputListener(adBlock, settings.adBlock);
addInputListener(disableBackgroundThrottle, settings.disableBackgroundThrottle);
addInputListener(singleInstance, settings.singleInstance);
addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys);

View File

@ -48,33 +48,34 @@
<p>Show a notification when a new song starts.</p>
</div>
<label class="switch">
<input id="notifications" type="checkbox">
<input id="notifications" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<h4>Mute Artists automatically</h4>
<p>The following list of artists (1 per line) will be muted automatically.</p>
</div>
<label class="switch">
<input id="muteArtists" type="checkbox">
<span class="switch__slider"></span>
</label>
</div>
<textarea id="mutedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
<div class="group__option">
<div class="group__description">
<h4>Skip Artists automatically</h4>
<p>The following list of artists (1 per line) will be skipped automatically.</p>
</div>
<label class="switch">
<input id="skipArtists" type="checkbox">
<input id="skipArtists" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<textarea id="skippedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
<div class="group__option">
<div class="group__description">
<h4>Block ads</h4>
<p>
Disabled audio & visual ads, unlocked lyrics, suggested track, track info,
unlimited skips
</p>
</div>
<label class="switch">
<input id="adBlock" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
</div>
<div class="group">
<p class="group__title">UI</p>
@ -84,7 +85,7 @@
<p>Always show TIDAL Hi-Fi's menu bar.</p>
</div>
<label class="switch">
<input id="menuBar" type="checkbox">
<input id="menuBar" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -97,7 +98,7 @@
<p>Show TIDAL Hi-Fi's tray icon.</p>
</div>
<label class="switch">
<input id="trayIcon" type="checkbox">
<input id="trayIcon" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -107,7 +108,7 @@
<p>Minimize window on close instead.</p>
</div>
<label class="switch">
<input id="minimizeOnClose" type="checkbox">
<input id="minimizeOnClose" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -120,7 +121,7 @@
</p>
</div>
<label class="switch">
<input id="enableCustomHotkeys" type="checkbox">
<input id="enableCustomHotkeys" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -130,7 +131,7 @@
<p>Prevent opening multiple TIDAL Hi-Fi's instances.</p>
</div>
<label class="switch">
<input id="singleInstance" type="checkbox">
<input id="singleInstance" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -142,8 +143,8 @@
<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. You can optionally
enable playback control as well.
TIDAL Hi-Fi has a built-in web API to allow users to get current song information.
You can optionally enable playback control as well.
</p>
</div>
<div class="group__option">
@ -152,14 +153,14 @@
<p>Enable the TIDAL Hi-Fi web API.</p>
</div>
<label class="switch">
<input id="apiCheckbox" type="checkbox">
<input id="apiCheckbox" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<label for="port">API port</label>
<input id="port" type="text" class="text-input" name="port">
<input id="port" type="text" class="text-input" name="port" />
</div>
</div>
<div class="group__option">
@ -168,7 +169,7 @@
<p>Enable playback control from the web API.</p>
</div>
<label class="switch">
<input id="playBackControl" type="checkbox">
<input id="playBackControl" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -180,18 +181,20 @@
<p class="group__title">Integrations</p>
<div class="group__description">
<p>
TIDAL Hi-Fi is extensible through the use of integrations.
You can enable or disable them here.
TIDAL Hi-Fi is extensible through the use of integrations. You can enable or
disable them here.
</p>
</div>
<div class="group__option">
<div class="group__description">
<h4>MPRIS</h4>
<p>Enable MPRIS interface which provides a mechanism for discovery, querying and basic playback control
on Linux systems.</p>
<p>
Enable MPRIS interface which provides a mechanism for discovery, querying and
basic playback control on Linux systems.
</p>
</div>
<label class="switch">
<input id="mprisCheckbox" type="checkbox">
<input id="mprisCheckbox" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -201,7 +204,7 @@
<p>Show what you're listening to on Discord.</p>
</div>
<label class="switch">
<input id="enableDiscord" type="checkbox">
<input id="enableDiscord" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -215,12 +218,12 @@
<div class="group__description">
<h4>Disable hardware built-in media keys</h4>
<p>
Also prevents certain desktop environments from recognizing the chrome
MPRIS client separately from the custom MPRIS client.
Also prevents certain desktop environments from recognizing the chrome MPRIS
client separately from the custom MPRIS client.
</p>
</div>
<label class="switch">
<input id="disableHardwareMediaKeys" type="checkbox">
<input id="disableHardwareMediaKeys" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -230,17 +233,19 @@
<p>Move a part of the rendering to the GPU for increased performance.</p>
</div>
<label class="switch">
<input id="gpuRasterization" type="checkbox">
<input id="gpuRasterization" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<h4>Disable Background Throttling</h4>
<p>Makes app more responsive while in the background, at the cost of performance.</p>
<p>
Makes app more responsive while in the background, at the cost of performance.
</p>
</div>
<label class="switch">
<input id="disableBackgroundThrottle" type="checkbox">
<input id="disableBackgroundThrottle" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
@ -248,17 +253,20 @@
</section>
<section id="about-section" class="tabs__section about-section">
<img alt="tidal icon" class="about-section__icon" src="./icon.png">
<img alt="tidal icon" class="about-section__icon" src="./icon.png" />
<p class="about-section__text">
<a class="external-link" data-url="https://github.com/Mastermindzh/tidal-hifi">TIDAL Hi-Fi</a>
is made by <a class="external-link" data-url="https://www.rickvanlieshout.com">
Rick van Lieshout</a>. <br>It uses <a class="external-link" data-url="https://castlabs.com/">Castlabs'</a>
is made by
<a class="external-link" data-url="https://www.rickvanlieshout.com">
Rick van Lieshout</a>. <br />It uses
<a class="external-link" data-url="https://castlabs.com/">Castlabs'</a>
version of Electron for widevine support.
</p>
</section>
<footer class="footer">
<p class="footer__note">Some settings may require a restart of TIDAL Hi-Fi. To do so, click the button below:
<p class="footer__note">
Some settings may require a restart of TIDAL Hi-Fi. To do so, click the button below:
</p>
<button class="footer__button" id="restart">Restart TIDAL Hi-Fi</button>
</footer>

View File

@ -13,7 +13,6 @@ const appName = "Tidal Hifi";
let currentSong = "";
let player;
let currentPlayStatus = statuses.paused;
let isMutedArtist = true;
const elements = {
play: '*[data-test="play"]',
@ -301,6 +300,7 @@ function updateMediaInfo(options, notify) {
"xesam:album": options.album,
"mpris:artUrl": options.image,
"mpris:length": convertDuration(options.duration) * 1000 * 1000,
"mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(),
},
};
player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing";
@ -313,10 +313,15 @@ function updateMediaInfo(options, notify) {
* If it's a song it returns the track URL, if not it will return undefined
*/
function getTrackURL() {
const id = getTrackID();
return `https://tidal.com/browse/track/${id}`;
}
function getTrackID() {
const URLelement = elements.get("title").querySelector("a");
if (URLelement !== null) {
const id = URLelement.href.replace(/[^0-9]/g, "");
return `https://tidal.com/browse/track/${id}`;
const id = URLelement.href.replace(/\D/g, "");
return id;
}
return window.location;
@ -329,7 +334,6 @@ setInterval(function () {
const title = elements.getText("title");
const artists = elements.getArtists();
skipArtistsIfFoundInSkippedArtistsList(artists);
muteArtistIfFoundInMutedArtistsList(artists); // doing this here so that nothing can possibly fail before we call this function
const album = elements.getAlbumName();
const current = elements.getText("current");
@ -381,24 +385,6 @@ setInterval(function () {
() => {}
);
/**
* Checks whether the current artist is included in the "muted artists" list and if so it will automatically mute the player
*/
function muteArtistIfFoundInMutedArtistsList(artists) {
if (store.get(settings.muteArtists)) {
const mutedArtists = store.get(settings.mutedArtists);
if (mutedArtists.find((artist) => artist === artists) !== undefined) {
if (!elements.isMuted()) {
isMutedArtist = true;
elements.click("volume");
}
} else if (isMutedArtist && elements.isMuted()) {
elements.click("volume");
isMutedArtist = false;
}
}
}
/**
* automatically skip a song if the artists are found in the list of artists to skip
* @param {*} artists list of artists to skip
@ -411,7 +397,7 @@ setInterval(function () {
}
}
}
}, 1000);
}, 100);
if (process.platform === "linux" && store.get(settings.mpris)) {
try {

View File

@ -10,10 +10,9 @@ const store = new Store({
notifications: true,
api: true,
playBackControl: true,
muteArtists: false,
mutedArtists: ["TIDAL"],
skipArtists: false,
skippedArtists: [""],
adBlock: false,
disableBackgroundThrottle: true,
menuBar: true,
apiSettings: {