1
0
mirror of https://github.com/pixeltris/TwitchAdSolutions.git synced 2024-11-25 20:02:52 +01:00

Fix worker hook #236

- Inject into every worker
- Remove unused proxy code from vaft
- Add additional source stream request to vaft
- Make log inside hookWorkerFetch consistent between vaft/video-swap-new
This commit is contained in:
pixeltris 2024-04-12 12:46:45 +01:00
parent 726254a5cb
commit 044d1fb3bb
4 changed files with 84 additions and 204 deletions

View File

@ -58,7 +58,8 @@ twitch-videoad.js text/javascript
scope.ClientVersion = 'null'; scope.ClientVersion = 'null';
scope.ClientSession = 'null'; scope.ClientSession = 'null';
scope.PlayerType2 = 'embed'; //Source scope.PlayerType2 = 'embed'; //Source
scope.PlayerType3 = 'autoplay'; //360p scope.PlayerType3 = 'site'; //Source
scope.PlayerType4 = 'autoplay'; //360p
scope.CurrentChannelName = null; scope.CurrentChannelName = null;
scope.UsherParams = null; scope.UsherParams = null;
scope.WasShowingAd = false; scope.WasShowingAd = false;
@ -68,9 +69,6 @@ twitch-videoad.js text/javascript
scope.StreamInfosByUrl = []; scope.StreamInfosByUrl = [];
scope.MainUrlByUrl = []; scope.MainUrlByUrl = [];
scope.EncodingCacheTimeout = 60000; scope.EncodingCacheTimeout = 60000;
scope.DefaultProxyType = null;
scope.DefaultForcedQuality = null;
scope.DefaultProxyQuality = null;
scope.ClientIntegrityHeader = null; scope.ClientIntegrityHeader = null;
scope.AuthorizationHeader = null; scope.AuthorizationHeader = null;
} }
@ -78,20 +76,14 @@ twitch-videoad.js text/javascript
var TwitchAdblockSettings = { var TwitchAdblockSettings = {
BannerVisible: true, BannerVisible: true,
ForcedQuality: null, ForcedQuality: null,
ProxyType: null,
ProxyQuality: null,
}; };
var twitchMainWorker = null; var twitchWorkers = [];
var adBlockDiv = null; var adBlockDiv = null;
var OriginalVideoPlayerQuality = null; var OriginalVideoPlayerQuality = null;
var IsPlayerAutoQuality = null; var IsPlayerAutoQuality = null;
const oldWorker = window.Worker; const oldWorker = window.Worker;
window.Worker = class Worker extends oldWorker { window.Worker = class Worker extends oldWorker {
constructor(twitchBlobUrl) { constructor(twitchBlobUrl) {
if (twitchMainWorker) {
super(twitchBlobUrl);
return;
}
var jsURL = getWasmWorkerUrl(twitchBlobUrl); var jsURL = getWasmWorkerUrl(twitchBlobUrl);
if (typeof jsURL !== 'string') { if (typeof jsURL !== 'string') {
super(twitchBlobUrl); super(twitchBlobUrl);
@ -132,7 +124,7 @@ twitch-videoad.js text/javascript
importScripts('${jsURL}'); importScripts('${jsURL}');
`; `;
super(URL.createObjectURL(new Blob([newBlobStr]))); super(URL.createObjectURL(new Blob([newBlobStr])));
twitchMainWorker = this; twitchWorkers.push(this);
this.onmessage = function(e) { this.onmessage = function(e) {
if (e.data.key == 'ShowAdBlockBanner') { if (e.data.key == 'ShowAdBlockBanner') {
if (!TwitchAdblockSettings.BannerVisible) { if (!TwitchAdblockSettings.BannerVisible) {
@ -268,7 +260,7 @@ twitch-videoad.js text/javascript
return req.responseText.split("'")[1]; return req.responseText.split("'")[1];
} }
function hookWorkerFetch() { function hookWorkerFetch() {
console.log('Twitch adblocker is enabled'); console.log('hookWorkerFetch');
var realFetch = fetch; var realFetch = fetch;
fetch = async function(url, options) { fetch = async function(url, options) {
if (typeof url === 'string') { if (typeof url === 'string') {
@ -282,6 +274,9 @@ twitch-videoad.js text/javascript
if (weaverText.includes(AdSignifier)) { if (weaverText.includes(AdSignifier)) {
weaverText = await processM3U8(url, responseText, realFetch, PlayerType3); weaverText = await processM3U8(url, responseText, realFetch, PlayerType3);
} }
if (weaverText.includes(AdSignifier)) {
weaverText = await processM3U8(url, responseText, realFetch, PlayerType4);
}
resolve(new Response(weaverText)); resolve(new Response(weaverText));
}; };
var send = function() { var send = function() {
@ -413,9 +408,6 @@ twitch-videoad.js text/javascript
} }
async function getStreamForResolution(streamInfo, resolutionInfo, encodingsM3u8, fallbackStreamStr, playerType, realFetch) { async function getStreamForResolution(streamInfo, resolutionInfo, encodingsM3u8, fallbackStreamStr, playerType, realFetch) {
var qualityOverride = null; var qualityOverride = null;
if (playerType === 'proxy') {
qualityOverride = TwitchAdblockSettings.ProxyQuality ? TwitchAdblockSettings.ProxyQuality : DefaultProxyQuality;
}
if (streamInfo.EncodingsM3U8Cache[playerType].Resolution != resolutionInfo.Resolution || if (streamInfo.EncodingsM3U8Cache[playerType].Resolution != resolutionInfo.Resolution ||
streamInfo.EncodingsM3U8Cache[playerType].RequestTime < Date.now() - EncodingCacheTimeout) { streamInfo.EncodingsM3U8Cache[playerType].RequestTime < Date.now() - EncodingCacheTimeout) {
console.log(`Blocking ads (type:${playerType}, resolution:${resolutionInfo.Resolution}, frameRate:${resolutionInfo.FrameRate}, qualityOverride:${qualityOverride})`); console.log(`Blocking ads (type:${playerType}, resolution:${resolutionInfo.Resolution}, frameRate:${resolutionInfo.FrameRate}, qualityOverride:${qualityOverride})`);
@ -521,28 +513,6 @@ twitch-videoad.js text/javascript
Resolution: null Resolution: null
}; };
} }
if (playerType === 'proxy') {
try {
var proxyType = TwitchAdblockSettings.ProxyType ? TwitchAdblockSettings.ProxyType : DefaultProxyType;
var encodingsM3u8Response = null;
/*var tempUrl = stripUnusedParams(MainUrlByUrl[url]);
const match = /(hls|vod)\/(.+?)$/gim.exec(tempUrl);*/
switch (proxyType) {
case 'TTV LOL':
encodingsM3u8Response = await realFetch('https://api.ttv.lol/playlist/' + CurrentChannelName + '.m3u8%3Fallow_source%3Dtrue'/* + encodeURIComponent(match[2])*/, {headers: {'X-Donate-To': 'https://ttv.lol/donate'}});
break;
/*case 'Purple Adblock':// Broken...
encodingsM3u8Response = await realFetch('https://eu1.jupter.ga/channel/' + CurrentChannelName);*/
case 'Falan':// https://greasyfork.org/en/scripts/425139-twitch-ad-fix/code
encodingsM3u8Response = await realFetch(atob('aHR0cHM6Ly9qaWdnbGUuYmV5cGF6YXJpZ3VydXN1LndvcmtlcnMuZGV2') + '/hls/' + CurrentChannelName + '.m3u8%3Fallow_source%3Dtrue'/* + encodeURIComponent(match[2])*/);
break;
}
if (encodingsM3u8Response && encodingsM3u8Response.status === 200) {
return getStreamForResolution(streamInfo, currentResolution, await encodingsM3u8Response.text(), textStr, playerType, realFetch);
}
} catch (err) {}
return textStr;
}
var accessTokenResponse = await getAccessToken(CurrentChannelName, playerType); var accessTokenResponse = await getAccessToken(CurrentChannelName, playerType);
if (accessTokenResponse.status === 200) { if (accessTokenResponse.status === 200) {
var accessToken = await accessTokenResponse.json(); var accessToken = await accessTokenResponse.json();
@ -798,27 +768,23 @@ twitch-videoad.js text/javascript
} catch (err) {} } catch (err) {}
} catch (err) {} } catch (err) {}
} }
window.reloadTwitchPlayer = doTwitchPlayerTask;
var localDeviceID = null; var localDeviceID = null;
localDeviceID = window.localStorage.getItem('local_copy_unique_id'); localDeviceID = window.localStorage.getItem('local_copy_unique_id');
function postTwitchWorkerMessage(key, value) {
twitchWorkers.forEach((worker) => {
worker.postMessage({key: key, value: value});
});
}
function hookFetch() { function hookFetch() {
var realFetch = window.fetch; var realFetch = window.fetch;
window.fetch = function(url, init, ...args) { window.fetch = function(url, init, ...args) {
if (typeof url === 'string') { if (typeof url === 'string') {
//Check if squad stream. //Check if squad stream.
if (window.location.pathname.includes('/squad')) { if (window.location.pathname.includes('/squad')) {
if (twitchMainWorker) { postTwitchWorkerMessage('UpdateIsSquadStream', true);
twitchMainWorker.postMessage({
key: 'UpdateIsSquadStream',
value: true
});
}
} else { } else {
if (twitchMainWorker) { postTwitchWorkerMessage('UpdateIsSquadStream', false);
twitchMainWorker.postMessage({
key: 'UpdateIsSquadStream',
value: false
});
}
} }
if (url.includes('/access_token') || url.includes('gql')) { if (url.includes('/access_token') || url.includes('gql')) {
//Device ID is used when notifying Twitch of ads. //Device ID is used when notifying Twitch of ads.
@ -833,39 +799,30 @@ twitch-videoad.js text/javascript
GQLDeviceID = localDeviceID.replace('"', ''); GQLDeviceID = localDeviceID.replace('"', '');
GQLDeviceID = GQLDeviceID.replace('"', ''); GQLDeviceID = GQLDeviceID.replace('"', '');
} }
if (GQLDeviceID && twitchMainWorker) { if (GQLDeviceID) {
if (typeof init.headers['X-Device-Id'] === 'string') { if (typeof init.headers['X-Device-Id'] === 'string') {
init.headers['X-Device-Id'] = GQLDeviceID; init.headers['X-Device-Id'] = GQLDeviceID;
} }
if (typeof init.headers['Device-ID'] === 'string') { if (typeof init.headers['Device-ID'] === 'string') {
init.headers['Device-ID'] = GQLDeviceID; init.headers['Device-ID'] = GQLDeviceID;
} }
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateDeviceId', GQLDeviceID);
key: 'UpdateDeviceId',
value: GQLDeviceID
});
} }
//Client version is used in GQL requests. //Client version is used in GQL requests.
var clientVersion = init.headers['Client-Version']; var clientVersion = init.headers['Client-Version'];
if (clientVersion && typeof clientVersion == 'string') { if (clientVersion && typeof clientVersion == 'string') {
ClientVersion = clientVersion; ClientVersion = clientVersion;
} }
if (ClientVersion && twitchMainWorker) { if (ClientVersion) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientVersion', ClientVersion);
key: 'UpdateClientVersion',
value: ClientVersion
});
} }
//Client session is used in GQL requests. //Client session is used in GQL requests.
var clientSession = init.headers['Client-Session-Id']; var clientSession = init.headers['Client-Session-Id'];
if (clientSession && typeof clientSession == 'string') { if (clientSession && typeof clientSession == 'string') {
ClientSession = clientSession; ClientSession = clientSession;
} }
if (ClientSession && twitchMainWorker) { if (ClientSession) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientSession', ClientSession);
key: 'UpdateClientSession',
value: ClientSession
});
} }
//Client ID is used in GQL requests. //Client ID is used in GQL requests.
if (url.includes('gql') && init && typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) { if (url.includes('gql') && init && typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) {
@ -878,27 +835,18 @@ twitch-videoad.js text/javascript
ClientID = clientId; ClientID = clientId;
} }
} }
if (ClientID && twitchMainWorker) { if (ClientID) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientId', ClientID);
key: 'UpdateClientId',
value: ClientID
});
} }
//Client integrity header //Client integrity header
ClientIntegrityHeader = init.headers['Client-Integrity']; ClientIntegrityHeader = init.headers['Client-Integrity'];
if (ClientIntegrityHeader && twitchMainWorker) { if (ClientIntegrityHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientIntegrityHeader', ClientIntegrityHeader);
key: 'UpdateClientIntegrityHeader',
value: init.headers['Client-Integrity']
});
} }
//Authorization header //Authorization header
AuthorizationHeader = init.headers['Authorization']; AuthorizationHeader = init.headers['Authorization'];
if (AuthorizationHeader && twitchMainWorker) { if (AuthorizationHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateAuthorizationHeader', AuthorizationHeader);
key: 'UpdateAuthorizationHeader',
value: init.headers['Authorization']
});
} }
} }
//To prevent pause/resume loop for mid-rolls. //To prevent pause/resume loop for mid-rolls.

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name TwitchAdSolutions (vaft) // @name TwitchAdSolutions (vaft)
// @namespace https://github.com/pixeltris/TwitchAdSolutions // @namespace https://github.com/pixeltris/TwitchAdSolutions
// @version 6.0.0 // @version 7.0.0
// @description Multiple solutions for blocking Twitch ads (vaft) // @description Multiple solutions for blocking Twitch ads (vaft)
// @updateURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/vaft/vaft.user.js // @updateURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/vaft/vaft.user.js
// @downloadURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/vaft/vaft.user.js // @downloadURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/vaft/vaft.user.js
@ -70,7 +70,8 @@
scope.ClientVersion = 'null'; scope.ClientVersion = 'null';
scope.ClientSession = 'null'; scope.ClientSession = 'null';
scope.PlayerType2 = 'embed'; //Source scope.PlayerType2 = 'embed'; //Source
scope.PlayerType3 = 'autoplay'; //360p scope.PlayerType3 = 'site'; //Source
scope.PlayerType4 = 'autoplay'; //360p
scope.CurrentChannelName = null; scope.CurrentChannelName = null;
scope.UsherParams = null; scope.UsherParams = null;
scope.WasShowingAd = false; scope.WasShowingAd = false;
@ -80,9 +81,6 @@
scope.StreamInfosByUrl = []; scope.StreamInfosByUrl = [];
scope.MainUrlByUrl = []; scope.MainUrlByUrl = [];
scope.EncodingCacheTimeout = 60000; scope.EncodingCacheTimeout = 60000;
scope.DefaultProxyType = null;
scope.DefaultForcedQuality = null;
scope.DefaultProxyQuality = null;
scope.ClientIntegrityHeader = null; scope.ClientIntegrityHeader = null;
scope.AuthorizationHeader = null; scope.AuthorizationHeader = null;
} }
@ -90,20 +88,14 @@
var TwitchAdblockSettings = { var TwitchAdblockSettings = {
BannerVisible: true, BannerVisible: true,
ForcedQuality: null, ForcedQuality: null,
ProxyType: null,
ProxyQuality: null,
}; };
var twitchMainWorker = null; var twitchWorkers = [];
var adBlockDiv = null; var adBlockDiv = null;
var OriginalVideoPlayerQuality = null; var OriginalVideoPlayerQuality = null;
var IsPlayerAutoQuality = null; var IsPlayerAutoQuality = null;
const oldWorker = window.Worker; const oldWorker = window.Worker;
window.Worker = class Worker extends oldWorker { window.Worker = class Worker extends oldWorker {
constructor(twitchBlobUrl) { constructor(twitchBlobUrl) {
if (twitchMainWorker) {
super(twitchBlobUrl);
return;
}
var jsURL = getWasmWorkerUrl(twitchBlobUrl); var jsURL = getWasmWorkerUrl(twitchBlobUrl);
if (typeof jsURL !== 'string') { if (typeof jsURL !== 'string') {
super(twitchBlobUrl); super(twitchBlobUrl);
@ -144,7 +136,7 @@
importScripts('${jsURL}'); importScripts('${jsURL}');
`; `;
super(URL.createObjectURL(new Blob([newBlobStr]))); super(URL.createObjectURL(new Blob([newBlobStr])));
twitchMainWorker = this; twitchWorkers.push(this);
this.onmessage = function(e) { this.onmessage = function(e) {
if (e.data.key == 'ShowAdBlockBanner') { if (e.data.key == 'ShowAdBlockBanner') {
if (!TwitchAdblockSettings.BannerVisible) { if (!TwitchAdblockSettings.BannerVisible) {
@ -280,7 +272,7 @@
return req.responseText.split("'")[1]; return req.responseText.split("'")[1];
} }
function hookWorkerFetch() { function hookWorkerFetch() {
console.log('Twitch adblocker is enabled'); console.log('hookWorkerFetch');
var realFetch = fetch; var realFetch = fetch;
fetch = async function(url, options) { fetch = async function(url, options) {
if (typeof url === 'string') { if (typeof url === 'string') {
@ -294,6 +286,9 @@
if (weaverText.includes(AdSignifier)) { if (weaverText.includes(AdSignifier)) {
weaverText = await processM3U8(url, responseText, realFetch, PlayerType3); weaverText = await processM3U8(url, responseText, realFetch, PlayerType3);
} }
if (weaverText.includes(AdSignifier)) {
weaverText = await processM3U8(url, responseText, realFetch, PlayerType4);
}
resolve(new Response(weaverText)); resolve(new Response(weaverText));
}; };
var send = function() { var send = function() {
@ -425,9 +420,6 @@
} }
async function getStreamForResolution(streamInfo, resolutionInfo, encodingsM3u8, fallbackStreamStr, playerType, realFetch) { async function getStreamForResolution(streamInfo, resolutionInfo, encodingsM3u8, fallbackStreamStr, playerType, realFetch) {
var qualityOverride = null; var qualityOverride = null;
if (playerType === 'proxy') {
qualityOverride = TwitchAdblockSettings.ProxyQuality ? TwitchAdblockSettings.ProxyQuality : DefaultProxyQuality;
}
if (streamInfo.EncodingsM3U8Cache[playerType].Resolution != resolutionInfo.Resolution || if (streamInfo.EncodingsM3U8Cache[playerType].Resolution != resolutionInfo.Resolution ||
streamInfo.EncodingsM3U8Cache[playerType].RequestTime < Date.now() - EncodingCacheTimeout) { streamInfo.EncodingsM3U8Cache[playerType].RequestTime < Date.now() - EncodingCacheTimeout) {
console.log(`Blocking ads (type:${playerType}, resolution:${resolutionInfo.Resolution}, frameRate:${resolutionInfo.FrameRate}, qualityOverride:${qualityOverride})`); console.log(`Blocking ads (type:${playerType}, resolution:${resolutionInfo.Resolution}, frameRate:${resolutionInfo.FrameRate}, qualityOverride:${qualityOverride})`);
@ -533,28 +525,6 @@
Resolution: null Resolution: null
}; };
} }
if (playerType === 'proxy') {
try {
var proxyType = TwitchAdblockSettings.ProxyType ? TwitchAdblockSettings.ProxyType : DefaultProxyType;
var encodingsM3u8Response = null;
/*var tempUrl = stripUnusedParams(MainUrlByUrl[url]);
const match = /(hls|vod)\/(.+?)$/gim.exec(tempUrl);*/
switch (proxyType) {
case 'TTV LOL':
encodingsM3u8Response = await realFetch('https://api.ttv.lol/playlist/' + CurrentChannelName + '.m3u8%3Fallow_source%3Dtrue'/* + encodeURIComponent(match[2])*/, {headers: {'X-Donate-To': 'https://ttv.lol/donate'}});
break;
/*case 'Purple Adblock':// Broken...
encodingsM3u8Response = await realFetch('https://eu1.jupter.ga/channel/' + CurrentChannelName);*/
case 'Falan':// https://greasyfork.org/en/scripts/425139-twitch-ad-fix/code
encodingsM3u8Response = await realFetch(atob('aHR0cHM6Ly9qaWdnbGUuYmV5cGF6YXJpZ3VydXN1LndvcmtlcnMuZGV2') + '/hls/' + CurrentChannelName + '.m3u8%3Fallow_source%3Dtrue'/* + encodeURIComponent(match[2])*/);
break;
}
if (encodingsM3u8Response && encodingsM3u8Response.status === 200) {
return getStreamForResolution(streamInfo, currentResolution, await encodingsM3u8Response.text(), textStr, playerType, realFetch);
}
} catch (err) {}
return textStr;
}
var accessTokenResponse = await getAccessToken(CurrentChannelName, playerType); var accessTokenResponse = await getAccessToken(CurrentChannelName, playerType);
if (accessTokenResponse.status === 200) { if (accessTokenResponse.status === 200) {
var accessToken = await accessTokenResponse.json(); var accessToken = await accessTokenResponse.json();
@ -810,27 +780,23 @@
} catch (err) {} } catch (err) {}
} catch (err) {} } catch (err) {}
} }
window.reloadTwitchPlayer = doTwitchPlayerTask;
var localDeviceID = null; var localDeviceID = null;
localDeviceID = window.localStorage.getItem('local_copy_unique_id'); localDeviceID = window.localStorage.getItem('local_copy_unique_id');
function postTwitchWorkerMessage(key, value) {
twitchWorkers.forEach((worker) => {
worker.postMessage({key: key, value: value});
});
}
function hookFetch() { function hookFetch() {
var realFetch = window.fetch; var realFetch = window.fetch;
window.fetch = function(url, init, ...args) { window.fetch = function(url, init, ...args) {
if (typeof url === 'string') { if (typeof url === 'string') {
//Check if squad stream. //Check if squad stream.
if (window.location.pathname.includes('/squad')) { if (window.location.pathname.includes('/squad')) {
if (twitchMainWorker) { postTwitchWorkerMessage('UpdateIsSquadStream', true);
twitchMainWorker.postMessage({
key: 'UpdateIsSquadStream',
value: true
});
}
} else { } else {
if (twitchMainWorker) { postTwitchWorkerMessage('UpdateIsSquadStream', false);
twitchMainWorker.postMessage({
key: 'UpdateIsSquadStream',
value: false
});
}
} }
if (url.includes('/access_token') || url.includes('gql')) { if (url.includes('/access_token') || url.includes('gql')) {
//Device ID is used when notifying Twitch of ads. //Device ID is used when notifying Twitch of ads.
@ -845,39 +811,30 @@
GQLDeviceID = localDeviceID.replace('"', ''); GQLDeviceID = localDeviceID.replace('"', '');
GQLDeviceID = GQLDeviceID.replace('"', ''); GQLDeviceID = GQLDeviceID.replace('"', '');
} }
if (GQLDeviceID && twitchMainWorker) { if (GQLDeviceID) {
if (typeof init.headers['X-Device-Id'] === 'string') { if (typeof init.headers['X-Device-Id'] === 'string') {
init.headers['X-Device-Id'] = GQLDeviceID; init.headers['X-Device-Id'] = GQLDeviceID;
} }
if (typeof init.headers['Device-ID'] === 'string') { if (typeof init.headers['Device-ID'] === 'string') {
init.headers['Device-ID'] = GQLDeviceID; init.headers['Device-ID'] = GQLDeviceID;
} }
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateDeviceId', GQLDeviceID);
key: 'UpdateDeviceId',
value: GQLDeviceID
});
} }
//Client version is used in GQL requests. //Client version is used in GQL requests.
var clientVersion = init.headers['Client-Version']; var clientVersion = init.headers['Client-Version'];
if (clientVersion && typeof clientVersion == 'string') { if (clientVersion && typeof clientVersion == 'string') {
ClientVersion = clientVersion; ClientVersion = clientVersion;
} }
if (ClientVersion && twitchMainWorker) { if (ClientVersion) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientVersion', ClientVersion);
key: 'UpdateClientVersion',
value: ClientVersion
});
} }
//Client session is used in GQL requests. //Client session is used in GQL requests.
var clientSession = init.headers['Client-Session-Id']; var clientSession = init.headers['Client-Session-Id'];
if (clientSession && typeof clientSession == 'string') { if (clientSession && typeof clientSession == 'string') {
ClientSession = clientSession; ClientSession = clientSession;
} }
if (ClientSession && twitchMainWorker) { if (ClientSession) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientSession', ClientSession);
key: 'UpdateClientSession',
value: ClientSession
});
} }
//Client ID is used in GQL requests. //Client ID is used in GQL requests.
if (url.includes('gql') && init && typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) { if (url.includes('gql') && init && typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) {
@ -890,27 +847,18 @@
ClientID = clientId; ClientID = clientId;
} }
} }
if (ClientID && twitchMainWorker) { if (ClientID) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientId', ClientID);
key: 'UpdateClientId',
value: ClientID
});
} }
//Client integrity header //Client integrity header
ClientIntegrityHeader = init.headers['Client-Integrity']; ClientIntegrityHeader = init.headers['Client-Integrity'];
if (ClientIntegrityHeader && twitchMainWorker) { if (ClientIntegrityHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientIntegrityHeader', ClientIntegrityHeader);
key: 'UpdateClientIntegrityHeader',
value: init.headers['Client-Integrity']
});
} }
//Authorization header //Authorization header
AuthorizationHeader = init.headers['Authorization']; AuthorizationHeader = init.headers['Authorization'];
if (AuthorizationHeader && twitchMainWorker) { if (AuthorizationHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateAuthorizationHeader', AuthorizationHeader);
key: 'UpdateAuthorizationHeader',
value: init.headers['Authorization']
});
} }
} }
//To prevent pause/resume loop for mid-rolls. //To prevent pause/resume loop for mid-rolls.

View File

@ -34,14 +34,10 @@ twitch-videoad.js text/javascript
scope.AuthorizationHeader = null; scope.AuthorizationHeader = null;
} }
declareOptions(window); declareOptions(window);
var twitchMainWorker = null; var twitchWorkers = [];
const oldWorker = window.Worker; const oldWorker = window.Worker;
window.Worker = class Worker extends oldWorker { window.Worker = class Worker extends oldWorker {
constructor(twitchBlobUrl) { constructor(twitchBlobUrl) {
if (twitchMainWorker) {
super(twitchBlobUrl);
return;
}
var jsURL = getWasmWorkerUrl(twitchBlobUrl); var jsURL = getWasmWorkerUrl(twitchBlobUrl);
if (typeof jsURL !== 'string') { if (typeof jsURL !== 'string') {
super(twitchBlobUrl); super(twitchBlobUrl);
@ -71,7 +67,7 @@ twitch-videoad.js text/javascript
importScripts('${jsURL}'); importScripts('${jsURL}');
` `
super(URL.createObjectURL(new Blob([newBlobStr]))); super(URL.createObjectURL(new Blob([newBlobStr])));
twitchMainWorker = this; twitchWorkers.push(this);
this.onmessage = function(e) { this.onmessage = function(e) {
// NOTE: Removed adDiv caching as '.video-player' can change between streams? // NOTE: Removed adDiv caching as '.video-player' can change between streams?
if (e.data.key == 'UboShowAdBanner') { if (e.data.key == 'UboShowAdBanner') {
@ -443,6 +439,11 @@ twitch-videoad.js text/javascript
return 0; return 0;
} }
} }
function postTwitchWorkerMessage(key, value) {
twitchWorkers.forEach((worker) => {
worker.postMessage({key: key, value: value});
});
}
function hookFetch() { function hookFetch() {
var realFetch = window.fetch; var realFetch = window.fetch;
window.fetch = function(url, init, ...args) { window.fetch = function(url, init, ...args) {
@ -455,11 +456,8 @@ twitch-videoad.js text/javascript
if (typeof deviceId === 'string') { if (typeof deviceId === 'string') {
gql_device_id = deviceId; gql_device_id = deviceId;
} }
if (gql_device_id && twitchMainWorker) { if (gql_device_id) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UboUpdateDeviceId', gql_device_id);
key: 'UboUpdateDeviceId',
value: gql_device_id
});
} }
if (typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) { if (typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) {
if (OPT_ACCESS_TOKEN_PLAYER_TYPE) { if (OPT_ACCESS_TOKEN_PLAYER_TYPE) {
@ -483,20 +481,14 @@ twitch-videoad.js text/javascript
} }
if (typeof init.headers['Client-Integrity'] === 'string') { if (typeof init.headers['Client-Integrity'] === 'string') {
ClientIntegrityHeader = init.headers['Client-Integrity']; ClientIntegrityHeader = init.headers['Client-Integrity'];
if (ClientIntegrityHeader && twitchMainWorker) { if (ClientIntegrityHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientIntegrityHeader', init.headers['Client-Integrity']);
key: 'UpdateClientIntegrityHeader',
value: init.headers['Client-Integrity']
});
} }
} }
if (typeof init.headers['Authorization'] === 'string') { if (typeof init.headers['Authorization'] === 'string') {
AuthorizationHeader = init.headers['Authorization']; AuthorizationHeader = init.headers['Authorization'];
if (AuthorizationHeader && twitchMainWorker) { if (AuthorizationHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateAuthorizationHeader', init.headers['Authorization']);
key: 'UpdateAuthorizationHeader',
value: init.headers['Authorization']
});
} }
} }
} }

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name TwitchAdSolutions (video-swap-new) // @name TwitchAdSolutions (video-swap-new)
// @namespace https://github.com/pixeltris/TwitchAdSolutions // @namespace https://github.com/pixeltris/TwitchAdSolutions
// @version 1.23 // @version 1.24
// @updateURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/video-swap-new/video-swap-new.user.js // @updateURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/video-swap-new/video-swap-new.user.js
// @downloadURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/video-swap-new/video-swap-new.user.js // @downloadURL https://github.com/pixeltris/TwitchAdSolutions/raw/master/video-swap-new/video-swap-new.user.js
// @description Multiple solutions for blocking Twitch ads (video-swap-new) // @description Multiple solutions for blocking Twitch ads (video-swap-new)
@ -46,14 +46,10 @@
scope.AuthorizationHeader = null; scope.AuthorizationHeader = null;
} }
declareOptions(window); declareOptions(window);
var twitchMainWorker = null; var twitchWorkers = [];
const oldWorker = window.Worker; const oldWorker = window.Worker;
window.Worker = class Worker extends oldWorker { window.Worker = class Worker extends oldWorker {
constructor(twitchBlobUrl) { constructor(twitchBlobUrl) {
if (twitchMainWorker) {
super(twitchBlobUrl);
return;
}
var jsURL = getWasmWorkerUrl(twitchBlobUrl); var jsURL = getWasmWorkerUrl(twitchBlobUrl);
if (typeof jsURL !== 'string') { if (typeof jsURL !== 'string') {
super(twitchBlobUrl); super(twitchBlobUrl);
@ -83,7 +79,7 @@
importScripts('${jsURL}'); importScripts('${jsURL}');
` `
super(URL.createObjectURL(new Blob([newBlobStr]))); super(URL.createObjectURL(new Blob([newBlobStr])));
twitchMainWorker = this; twitchWorkers.push(this);
this.onmessage = function(e) { this.onmessage = function(e) {
// NOTE: Removed adDiv caching as '.video-player' can change between streams? // NOTE: Removed adDiv caching as '.video-player' can change between streams?
if (e.data.key == 'UboShowAdBanner') { if (e.data.key == 'UboShowAdBanner') {
@ -455,6 +451,11 @@
return 0; return 0;
} }
} }
function postTwitchWorkerMessage(key, value) {
twitchWorkers.forEach((worker) => {
worker.postMessage({key: key, value: value});
});
}
function hookFetch() { function hookFetch() {
var realFetch = window.fetch; var realFetch = window.fetch;
window.fetch = function(url, init, ...args) { window.fetch = function(url, init, ...args) {
@ -467,11 +468,8 @@
if (typeof deviceId === 'string') { if (typeof deviceId === 'string') {
gql_device_id = deviceId; gql_device_id = deviceId;
} }
if (gql_device_id && twitchMainWorker) { if (gql_device_id) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UboUpdateDeviceId', gql_device_id);
key: 'UboUpdateDeviceId',
value: gql_device_id
});
} }
if (typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) { if (typeof init.body === 'string' && init.body.includes('PlaybackAccessToken')) {
if (OPT_ACCESS_TOKEN_PLAYER_TYPE) { if (OPT_ACCESS_TOKEN_PLAYER_TYPE) {
@ -495,20 +493,14 @@
} }
if (typeof init.headers['Client-Integrity'] === 'string') { if (typeof init.headers['Client-Integrity'] === 'string') {
ClientIntegrityHeader = init.headers['Client-Integrity']; ClientIntegrityHeader = init.headers['Client-Integrity'];
if (ClientIntegrityHeader && twitchMainWorker) { if (ClientIntegrityHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateClientIntegrityHeader', init.headers['Client-Integrity']);
key: 'UpdateClientIntegrityHeader',
value: init.headers['Client-Integrity']
});
} }
} }
if (typeof init.headers['Authorization'] === 'string') { if (typeof init.headers['Authorization'] === 'string') {
AuthorizationHeader = init.headers['Authorization']; AuthorizationHeader = init.headers['Authorization'];
if (AuthorizationHeader && twitchMainWorker) { if (AuthorizationHeader) {
twitchMainWorker.postMessage({ postTwitchWorkerMessage('UpdateAuthorizationHeader', init.headers['Authorization']);
key: 'UpdateAuthorizationHeader',
value: init.headers['Authorization']
});
} }
} }
} }