Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

open.spotify.com: ads #22231

Closed
8 of 9 tasks
gettysburg opened this issue Jan 27, 2024 · 2 comments
Closed
8 of 9 tasks

open.spotify.com: ads #22231

gettysburg opened this issue Jan 27, 2024 · 2 comments

Comments

@gettysburg
Copy link

gettysburg commented Jan 27, 2024

Prerequisites

  • This is NOT a YouTube, Facebook or Twitch report. These sites MUST be reported by clicking their respective links.
  • I read and understand the policy about what is a valid filter issue.
  • I verified that this issue is not a duplicate. (Search here to find out.)
  • I did not remove any of the default filter lists, or I have verified that the issue was not caused by removing any of the default lists.
  • I did not enable additional filter lists, or I have verified that the issue still occurs without enabling additional filter lists.
  • I do not have custom filters/rules, or I have verified that the issue still occurs without custom filters/rules.
  • I am not using uBlock Origin (uBO) along with other content blocker extensions.
  • I have verified that the web browser's built-in blocker or DNS blocking (standalone or through a VPN) is not causing the issue.
  • I did not answer truthfully to ALL the above checkboxes.

URL(s) where the issue occurs.

https://open.spotify.com

Description

All banners are removed, and audio ads are silenced.

However, the audio ads still break playback, and make it stop for a few seconds completely.

Is there a way to skip the audio ads altogether on the web player?

Having to wait a variable amount of time once an ad plays is not optimal.

There is a working AdBlocker for the Windows version of Spotify, which applies various patches through pattern scans to essentially modify JavaScript files before the browser engine executes them, here are some relevant ones:

if (file_name == L"home-hpto.css") {
		const auto hpto = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:flex;");
		if (hpto.is_found()) {
			if (hpto.write<const char*>(".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:none;")) {
				Logger::Log(L"hptocss patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"hptocss patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"hptocss - failed not found!", Logger::LogLevel::Error);
		}
	}

This one disables the ads I believe:

		const auto skipads = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"adsEnabled:!0");
		if (skipads.is_found()) {
			if (skipads.offset(12).write<const char>('1')) {
				Logger::Log(L"adsEnabled patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"adsEnabled - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"adsEnabled - failed not found!", Logger::LogLevel::Error);
		}

Here are the other needed modifications:

		if (sponsorship.is_found()) {
			if (sponsorship.offset(5).write<const char*>(std::string(15, ' ').append("\"").c_str())) {
				Logger::Log(L"sponsorship patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"sponsorship patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"sponsorship - failed not found!", Logger::LogLevel::Error);
		}

		const auto skipsentry = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"sentry.io");
		if (skipsentry.is_found()) {
			if (skipsentry.write<const char*>("localhost")) {
				Logger::Log(L"sentry.io -> localhost patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"sentry.io -> localhost - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"sentry.io -> localhost - failed not found!", Logger::LogLevel::Error);
		}

		const auto ishptoenable = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"hptoEnabled:!0");
		if (ishptoenable.is_found())
		{
			if (ishptoenable.offset(13).write<const char>('1')) {
				Logger::Log(L"hptoEnabled patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"hptoEnabled - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"hptoEnabled - failed not found!", Logger::LogLevel::Error);
		}

		const auto ishptohidden = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"isHptoHidden:!0");
		if (ishptohidden.is_found()) {
			if (ishptohidden.offset(14).write<const char>('1')) {
				Logger::Log(L"isHptoHidden patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"isHptoHidden - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"isHptoHidden - failed not found!", Logger::LogLevel::Error);
		}

		const auto sp_localhost = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"sp://ads/v1/ads/");
		if (sp_localhost.is_found()) {
			if (sp_localhost.write<const char*>("sp://localhost//")) {
				Logger::Log(L"sp://ads/v1/ads/ patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"sp://ads/v1/ads/ - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"sp://ads/v1/ads/ - failed not found!", Logger::LogLevel::Error);
		}

		const auto premium_free = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"\"free\"===e.session?.productState?.catalogue?.toLowerCase(),r=e=>\"premium\"===e.session?.productState?.catalogue?.toLowerCase()");
		if (premium_free.is_found()) {
			//Print(L"{}", premium_free.read<const char*>());
			if (premium_free.write<const char*>("\"premium\"===e.session?.productState?.catalogue?.toLowerCase(),r=e=>\"free\"===e.session?.productState?.catalogue?.toLowerCase()")) {
				Logger::Log(L"premium patched!", Logger::LogLevel::Info);
			}
			else {
				Logger::Log(L"premium - patch failed!", Logger::LogLevel::Error);
			}
		}
		else {
			Logger::Log(L"premium - failed not found!", Logger::LogLevel::Error);
		}

Code taken from: https://github.com/mrpond/BlockTheSpot/blob/master/src/Modify.cpp

Now, I know this is for the Windows version and C(++) code, but the patches they apply here could also be applied or injected through uBO, what they do instead is hook the web browsers file parser, and change content in the JavaScript files as they are parsed and executed.

I am very certain that uBlock Origin could also integrate this.

Since the Spotify Windows Client is essentially just a browser engine that loads the web player, with some extra app features, applying the same patches from above through filters and injection should work the same.

That way, Spotify Web would believe you already own premium, and ads are disabled through that one variable in xpui.js, and as a result, never even presenting you with audio ads again.

Note that the desktop version also blocks access to some URL's, I can compile a list if wanted.

It would be nice to have fully functioning filters, without the ads getting stuck or taking a long time to recover to play the next song.

I am a long time C/C++ developer, so if you need help interpreting the code, just ask.

For example, for the variable adsEnabled:

const auto skipads = PatternScanner::ScanFirst(reinterpret_cast<std::size_t>(buffer), bufferSize, L"adsEnabled:!0");

they perform a pattern scan, and then modify the 0 to a 1 (since it is already negated by the exclamation mark):

skipads.offset(12).write<const char>('1')

Essentially uBO would have to parse files, search for strings and modify them before the web browser actually runs the JS code.

I believe this is, at least, on Firefox, possible.

As said before, I know C/C++ very well, but am not very prolific with the filter engines and syntax of uBO at all, I have essentially never read up on how it all works.

Please let me know your thoughts on this.. going through the source files for BlockTheSpot probably also won't hurt.

Thank you.

Other extensions used

Old Reddit Redirect
Tampermonkey
Remove DNT (DoNotTrack) Header from Requests
Search by Image
Return YouTube Dislike

Screenshot(s)

No screenshots.

Configuration

Details
Firefox: 115
filterset (summary):
 network: 320910
 cosmetic: 250576
 scriptlet: 49548
 html: 2259
listset (total-discarded, last-updated):
 added:
  adguard-generic: 81884-7055, 16h.40m
  adguard-mobile: 9098-20, 16h.40m
  adguard-spyware-url: 1424-103, 16h.40m
  adguard-spyware: 89713-26976, 16h.40m
  block-lan: 56-0, 16h.40m
  curben-phishing: 97767-28, 16h.40m
  adguard-social: 22473-878, 16h.40m
  adguard-cookies: 28464-63, 16h.40m
  ublock-cookies-adguard: 911-0, 16h.40m
  adguard-popup-overlays: 26878-1682, 16h.40m
  adguard-mobile-app-banners: 4920-1074, 16h.40m
  adguard-other-annoyances: 14138-334, 16h.40m
  [12 lists not shown]: [too many]
 default:
  user-filters: 0-0, never
  ublock-filters: 37434-440, 2h.30m Δ
  ublock-badware: 7800-10, 2h.30m Δ
  ublock-privacy: 988-0, 2h.30m Δ
  ublock-unbreak: 2244-1, 2h.30m Δ
  ublock-quick-fixes: 136-0, 2h.30m Δ
  easylist: 79953-1006, 2h.30m Δ
  easyprivacy: 43568-1109, 2h.30m Δ
  urlhaus-1: 8535-0, 16h.39m
  plowe-0: 3786-84, 16h.39m
filterset (user): [empty]
userSettings:
 advancedUserEnabled: true
 cloudStorageEnabled: true
hiddenSettings:
 autoUpdateAssetFetchPeriod: 5
 autoUpdateDelayAfterLaunch: 15
supportStats:
 allReadyAfter: 574 ms (selfie)
 maxAssetCacheWait: 445 ms
 cacheBackend: indexedDB
popupPanel:
 blocked: 18
 network:
  spotify.com: 2
  cookielaw.org: 1
  doubleclick.net: 3
  googleoptimize.com: 1
  scdn.co: 1
  sentry.io: 10
 extended:
  ##span[dir="auto"][draggable="true"]:style(user-select: auto!imp…
  ##+js(set-constant, rwt, noopFunc)
  ##+js(trusted-set-cookie, SOCS, CAESHAgBEhJnd3NfMjAyMzA2MTItMF9S…
  ##+js(remove-attr, ping, div[id="search"] a[data-ved][ping])
@ItsProfessional
Copy link
Member

ItsProfessional commented Jan 27, 2024

  • I verified that this issue is not a duplicate. (Search here to find out.)

You didn't. #22198

@ItsProfessional ItsProfessional closed this as not planned Won't fix, can't repro, duplicate, stale Jan 27, 2024
@ItsProfessional ItsProfessional changed the title open.spotify.com: breakage and possible permanent fix for audio ads open.spotify.com: ads Jan 27, 2024
@gettysburg
Copy link
Author

gettysburg commented Jan 27, 2024

Yes, I admit I lied on that one and did not check, but it seems you don't understand the purpose of the thread, the approach the developers of the desktop adblock tool took might work for uBO as well.

Why bother with so many rules when setting one variable is enough?

Should I re-post the same idea in that thread, linking back to this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants