Scriptlets icon indicating copy to clipboard operation
Scriptlets copied to clipboard

'm3u-prune' does not work in AdGuard for MacOS

Open Alex-302 opened this issue 1 year ago • 2 comments

US IP is required. AdGuard for Mac 2.16.1.1862 nightly.

Steps to reproduce

  1. Open https://www.adultswim.com/streams/

Actual behaviour

Ad preroll (with the ad label. They also have unblockable video ad in the stream).

Example of m3u8 file https://regex101.com/r/jYclr1/1

Details

image

I also checked in Chrome with the browser extension - with following unblocking rules I see ads:

adultswim.com#@%#//scriptlet('m3u-prune', '/vod-media-aka.warnermediacdn.com\/mtg\d+\/.*\d{3,4}x\d{3,4}-.*\.ts/', '.m3u8')
adultswim.com#@%#//scriptlet('m3u-prune', '/ad-slate|warnermediacdn\.com\/mtg|warnermediacdn\.com\/prod01/', '.m3u8')
@@||adultswim-vodlive.cdn.turner.com^$removeparam=caid,domain=adultswim-vodlive.cdn.turner.com

When I disable the first unblocking rule, ads are blocked.

Alex-302 avatar Dec 20 '24 13:12 Alex-302

I can reproduce it in Safari only and the same problem occurs with trusted-replace-xhr-response. The same can be checked on https://developer.apple.com/streaming/examples/advanced-stream-dv-atmos.html In Chrome .m3u8 file is downloaded through xhr, but it looks like that not in Safari. According to https://github.com/video-dev/hls.js#compatibility:

Safari browsers (iOS, iPadOS, and macOS) have built-in HLS support through the plain video "tag" source URL.

So if I understand correctly, Safari natively download it, so it cannot be intercepted by scriptlet (only by $replace/$hls and similar rules) or perhaps I'm missing something and can it be done somehow?

AdamWr avatar Jan 17 '25 14:01 AdamWr

As a workaround we could override HTMLVideoElement.prototype.canPlayType (https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType) and for specific types ("application/vnd.apple.mpegURL", "application/x-mpegURL", "audio/mpegurl", "audio/x-mpegurl") return empty string. This way it would cause that .m3u8 file will be downloaded not natively but by xhr, and ads should be blocked.

For example:

adultswim.com#%#(()=>{const e=new Set(["application/vnd.apple.mpegURL","application/x-mpegURL","audio/mpegurl","audio/x-mpegurl"]),p={apply:(p,o,a)=>{const n=a[0];return location.href.includes("/streams")&&e.has(n)?"":Reflect.apply(p,o,a)}};window.HTMLVideoElement.prototype.canPlayType=new Proxy(window.HTMLVideoElement.prototype.canPlayType,p)})();
Code:
(() => {
    const streamLocation = '/streams';
    const notAllowedTypes = new Set([
        'application/vnd.apple.mpegURL',
        'application/x-mpegURL',
        'audio/mpegurl',
        'audio/x-mpegurl',
    ]);
    const wrapper = (target, thisArg, args) => {
        const type = args[0];
        // Override the return value of canPlayType to empty string if the type is not allowed
        // and only if the location is the stream location.
        // For some reason it breaks not live videos in Safari, on "adultswim.com/videos/"
        if (location.href.includes(streamLocation) && notAllowedTypes.has(type)) {
            return '';
        }
        return Reflect.apply(target, thisArg, args);
    };

    const handler = {
        apply: wrapper,
    };
    window.HTMLVideoElement.prototype.canPlayType = new Proxy(
        window.HTMLVideoElement.prototype.canPlayType,
        handler,
    );
})();

But it should be done only for live streams, because for some reason it breaks video player on https://www.adultswim.com/videos/ (only in Safari). Ads on https://www.adultswim.com/videos/ are blocked without overriding canPlayType, so it's fine, I guess.

AdamWr avatar Jan 18 '25 10:01 AdamWr