Fix GQL requests failing under chrome #363
- Ref https://github.com/AdguardTeam/AdGuardExtra/issues/599
This commit is contained in:
+79
-21
@@ -1,7 +1,7 @@
|
|||||||
twitch-videoad.js text/javascript
|
twitch-videoad.js text/javascript
|
||||||
(function() {
|
(function() {
|
||||||
if ( /(^|\.)twitch\.tv$/.test(document.location.hostname) === false ) { return; }
|
if ( /(^|\.)twitch\.tv$/.test(document.location.hostname) === false ) { return; }
|
||||||
var ourTwitchAdSolutionsVersion = 2;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
var ourTwitchAdSolutionsVersion = 3;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
||||||
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
||||||
console.log("skipping vaft as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
console.log("skipping vaft as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
||||||
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
||||||
@@ -102,6 +102,7 @@ twitch-videoad.js text/javascript
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newBlobStr = `
|
var newBlobStr = `
|
||||||
|
const pendingFetchRequests = new Map();
|
||||||
${getStreamUrlForResolution.toString()}
|
${getStreamUrlForResolution.toString()}
|
||||||
${getStreamForResolution.toString()}
|
${getStreamForResolution.toString()}
|
||||||
${stripUnusedParams.toString()}
|
${stripUnusedParams.toString()}
|
||||||
@@ -131,6 +132,23 @@ twitch-videoad.js text/javascript
|
|||||||
ClientIntegrityHeader = e.data.value;
|
ClientIntegrityHeader = e.data.value;
|
||||||
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
||||||
AuthorizationHeader = e.data.value;
|
AuthorizationHeader = e.data.value;
|
||||||
|
} else if (e.data.key == 'FetchResponse') {
|
||||||
|
const responseData = e.data.value;
|
||||||
|
if (pendingFetchRequests.has(responseData.id)) {
|
||||||
|
const { resolve, reject } = pendingFetchRequests.get(responseData.id);
|
||||||
|
pendingFetchRequests.delete(responseData.id);
|
||||||
|
if (responseData.error) {
|
||||||
|
reject(new Error(responseData.error));
|
||||||
|
} else {
|
||||||
|
// Create a Response object from the response data
|
||||||
|
const response = new Response(responseData.body, {
|
||||||
|
status: responseData.status,
|
||||||
|
statusText: responseData.statusText,
|
||||||
|
headers: responseData.headers
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
hookWorkerFetch();
|
hookWorkerFetch();
|
||||||
@@ -244,6 +262,16 @@ twitch-videoad.js text/javascript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.addEventListener('message', async event => {
|
||||||
|
if (event.data.key == 'FetchRequest') {
|
||||||
|
const fetchRequest = event.data.value;
|
||||||
|
const responseData = await handleWorkerFetchRequest(fetchRequest);
|
||||||
|
this.postMessage({
|
||||||
|
key: 'FetchResponse',
|
||||||
|
value: responseData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
function getAdBlockDiv() {
|
function getAdBlockDiv() {
|
||||||
//To display a notification to the user, that an ad is being blocked.
|
//To display a notification to the user, that an ad is being blocked.
|
||||||
var playerRootDiv = document.querySelector('.video-player');
|
var playerRootDiv = document.querySelector('.video-player');
|
||||||
@@ -655,7 +683,7 @@ twitch-videoad.js text/javascript
|
|||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
function getAccessToken(channelName, playerType, realFetch) {
|
function getAccessToken(channelName, playerType) {
|
||||||
var body = null;
|
var body = null;
|
||||||
var templateQuery = 'query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}';
|
var templateQuery = 'query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}';
|
||||||
body = {
|
body = {
|
||||||
@@ -669,14 +697,9 @@ twitch-videoad.js text/javascript
|
|||||||
'playerType': playerType
|
'playerType': playerType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return gqlRequest(body, realFetch);
|
return gqlRequest(body);
|
||||||
}
|
}
|
||||||
function gqlRequest(body, realFetch) {
|
function gqlRequest(body) {
|
||||||
if (ClientIntegrityHeader == null) {
|
|
||||||
//console.warn('ClientIntegrityHeader is null');
|
|
||||||
//throw 'ClientIntegrityHeader is null';
|
|
||||||
}
|
|
||||||
var fetchFunc = realFetch ? realFetch : fetch;
|
|
||||||
if (!GQLDeviceID) {
|
if (!GQLDeviceID) {
|
||||||
var dcharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
var dcharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
var dcharactersLength = dcharacters.length;
|
var dcharactersLength = dcharacters.length;
|
||||||
@@ -684,18 +707,34 @@ twitch-videoad.js text/javascript
|
|||||||
GQLDeviceID += dcharacters.charAt(Math.floor(Math.random() * dcharactersLength));
|
GQLDeviceID += dcharacters.charAt(Math.floor(Math.random() * dcharactersLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fetchFunc('https://gql.twitch.tv/gql', {
|
var headers = {
|
||||||
method: 'POST',
|
'Client-ID': ClientID,
|
||||||
body: JSON.stringify(body),
|
'Client-Integrity': ClientIntegrityHeader,
|
||||||
headers: {
|
'Device-ID': GQLDeviceID,
|
||||||
'Client-ID': ClientID,
|
'X-Device-Id': GQLDeviceID,
|
||||||
'Client-Integrity': ClientIntegrityHeader,
|
'Client-Version': ClientVersion,
|
||||||
'Device-ID': GQLDeviceID,
|
'Client-Session-Id': ClientSession,
|
||||||
'X-Device-Id': GQLDeviceID,
|
'Authorization': AuthorizationHeader
|
||||||
'Client-Version': ClientVersion,
|
};
|
||||||
'Client-Session-Id': ClientSession,
|
return new Promise((resolve, reject) => {
|
||||||
'Authorization': AuthorizationHeader
|
const requestId = Math.random().toString(36).substring(2, 15);
|
||||||
}
|
const fetchRequest = {
|
||||||
|
id: requestId,
|
||||||
|
url: 'https://gql.twitch.tv/gql',
|
||||||
|
options: {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pendingFetchRequests.set(requestId, {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
});
|
||||||
|
postMessage({
|
||||||
|
key: 'FetchRequest',
|
||||||
|
value: fetchRequest
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function doTwitchPlayerTask(isPausePlay, isCheckQuality, isCorrectBuffer, isAutoQuality, setAutoQuality) {
|
function doTwitchPlayerTask(isPausePlay, isCheckQuality, isCorrectBuffer, isAutoQuality, setAutoQuality) {
|
||||||
@@ -805,6 +844,25 @@ twitch-videoad.js text/javascript
|
|||||||
worker.postMessage({key: key, value: value});
|
worker.postMessage({key: key, value: value});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async function handleWorkerFetchRequest(fetchRequest) {
|
||||||
|
try {
|
||||||
|
const response = await window.fetch(fetchRequest.url, fetchRequest.options);
|
||||||
|
const responseBody = await response.text();
|
||||||
|
const responseObject = {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
body: responseBody
|
||||||
|
};
|
||||||
|
return responseObject;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
function hookFetch() {
|
function hookFetch() {
|
||||||
var realFetch = window.fetch;
|
var realFetch = window.fetch;
|
||||||
window.fetch = function(url, init, ...args) {
|
window.fetch = function(url, init, ...args) {
|
||||||
|
|||||||
+80
-22
@@ -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 17.0.0
|
// @version 18.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
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
var ourTwitchAdSolutionsVersion = 2;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
var ourTwitchAdSolutionsVersion = 3;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
||||||
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
||||||
console.log("skipping vaft as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
console.log("skipping vaft as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
||||||
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
||||||
@@ -114,6 +114,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newBlobStr = `
|
var newBlobStr = `
|
||||||
|
const pendingFetchRequests = new Map();
|
||||||
${getStreamUrlForResolution.toString()}
|
${getStreamUrlForResolution.toString()}
|
||||||
${getStreamForResolution.toString()}
|
${getStreamForResolution.toString()}
|
||||||
${stripUnusedParams.toString()}
|
${stripUnusedParams.toString()}
|
||||||
@@ -143,6 +144,23 @@
|
|||||||
ClientIntegrityHeader = e.data.value;
|
ClientIntegrityHeader = e.data.value;
|
||||||
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
||||||
AuthorizationHeader = e.data.value;
|
AuthorizationHeader = e.data.value;
|
||||||
|
} else if (e.data.key == 'FetchResponse') {
|
||||||
|
const responseData = e.data.value;
|
||||||
|
if (pendingFetchRequests.has(responseData.id)) {
|
||||||
|
const { resolve, reject } = pendingFetchRequests.get(responseData.id);
|
||||||
|
pendingFetchRequests.delete(responseData.id);
|
||||||
|
if (responseData.error) {
|
||||||
|
reject(new Error(responseData.error));
|
||||||
|
} else {
|
||||||
|
// Create a Response object from the response data
|
||||||
|
const response = new Response(responseData.body, {
|
||||||
|
status: responseData.status,
|
||||||
|
statusText: responseData.statusText,
|
||||||
|
headers: responseData.headers
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
hookWorkerFetch();
|
hookWorkerFetch();
|
||||||
@@ -256,6 +274,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.addEventListener('message', async event => {
|
||||||
|
if (event.data.key == 'FetchRequest') {
|
||||||
|
const fetchRequest = event.data.value;
|
||||||
|
const responseData = await handleWorkerFetchRequest(fetchRequest);
|
||||||
|
this.postMessage({
|
||||||
|
key: 'FetchResponse',
|
||||||
|
value: responseData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
function getAdBlockDiv() {
|
function getAdBlockDiv() {
|
||||||
//To display a notification to the user, that an ad is being blocked.
|
//To display a notification to the user, that an ad is being blocked.
|
||||||
var playerRootDiv = document.querySelector('.video-player');
|
var playerRootDiv = document.querySelector('.video-player');
|
||||||
@@ -667,7 +695,7 @@
|
|||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
function getAccessToken(channelName, playerType, realFetch) {
|
function getAccessToken(channelName, playerType) {
|
||||||
var body = null;
|
var body = null;
|
||||||
var templateQuery = 'query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}';
|
var templateQuery = 'query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: "ios", playerBackend: "mediaplayer", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}';
|
||||||
body = {
|
body = {
|
||||||
@@ -681,14 +709,9 @@
|
|||||||
'playerType': playerType
|
'playerType': playerType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return gqlRequest(body, realFetch);
|
return gqlRequest(body);
|
||||||
}
|
}
|
||||||
function gqlRequest(body, realFetch) {
|
function gqlRequest(body) {
|
||||||
if (ClientIntegrityHeader == null) {
|
|
||||||
//console.warn('ClientIntegrityHeader is null');
|
|
||||||
//throw 'ClientIntegrityHeader is null';
|
|
||||||
}
|
|
||||||
var fetchFunc = realFetch ? realFetch : fetch;
|
|
||||||
if (!GQLDeviceID) {
|
if (!GQLDeviceID) {
|
||||||
var dcharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
var dcharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
var dcharactersLength = dcharacters.length;
|
var dcharactersLength = dcharacters.length;
|
||||||
@@ -696,18 +719,34 @@
|
|||||||
GQLDeviceID += dcharacters.charAt(Math.floor(Math.random() * dcharactersLength));
|
GQLDeviceID += dcharacters.charAt(Math.floor(Math.random() * dcharactersLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fetchFunc('https://gql.twitch.tv/gql', {
|
var headers = {
|
||||||
method: 'POST',
|
'Client-ID': ClientID,
|
||||||
body: JSON.stringify(body),
|
'Client-Integrity': ClientIntegrityHeader,
|
||||||
headers: {
|
'Device-ID': GQLDeviceID,
|
||||||
'Client-ID': ClientID,
|
'X-Device-Id': GQLDeviceID,
|
||||||
'Client-Integrity': ClientIntegrityHeader,
|
'Client-Version': ClientVersion,
|
||||||
'Device-ID': GQLDeviceID,
|
'Client-Session-Id': ClientSession,
|
||||||
'X-Device-Id': GQLDeviceID,
|
'Authorization': AuthorizationHeader
|
||||||
'Client-Version': ClientVersion,
|
};
|
||||||
'Client-Session-Id': ClientSession,
|
return new Promise((resolve, reject) => {
|
||||||
'Authorization': AuthorizationHeader
|
const requestId = Math.random().toString(36).substring(2, 15);
|
||||||
}
|
const fetchRequest = {
|
||||||
|
id: requestId,
|
||||||
|
url: 'https://gql.twitch.tv/gql',
|
||||||
|
options: {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pendingFetchRequests.set(requestId, {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
});
|
||||||
|
postMessage({
|
||||||
|
key: 'FetchRequest',
|
||||||
|
value: fetchRequest
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function doTwitchPlayerTask(isPausePlay, isCheckQuality, isCorrectBuffer, isAutoQuality, setAutoQuality) {
|
function doTwitchPlayerTask(isPausePlay, isCheckQuality, isCorrectBuffer, isAutoQuality, setAutoQuality) {
|
||||||
@@ -817,6 +856,25 @@
|
|||||||
worker.postMessage({key: key, value: value});
|
worker.postMessage({key: key, value: value});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async function handleWorkerFetchRequest(fetchRequest) {
|
||||||
|
try {
|
||||||
|
const response = await window.fetch(fetchRequest.url, fetchRequest.options);
|
||||||
|
const responseBody = await response.text();
|
||||||
|
const responseObject = {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
body: responseBody
|
||||||
|
};
|
||||||
|
return responseObject;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
function hookFetch() {
|
function hookFetch() {
|
||||||
var realFetch = window.fetch;
|
var realFetch = window.fetch;
|
||||||
window.fetch = function(url, init, ...args) {
|
window.fetch = function(url, init, ...args) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
twitch-videoad.js text/javascript
|
twitch-videoad.js text/javascript
|
||||||
(function() {
|
(function() {
|
||||||
if ( /(^|\.)twitch\.tv$/.test(document.location.hostname) === false ) { return; }
|
if ( /(^|\.)twitch\.tv$/.test(document.location.hostname) === false ) { return; }
|
||||||
var ourTwitchAdSolutionsVersion = 2;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
var ourTwitchAdSolutionsVersion = 3;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
||||||
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
||||||
console.log("skipping video-swap-new as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
console.log("skipping video-swap-new as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
||||||
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
||||||
@@ -101,6 +101,7 @@ twitch-videoad.js text/javascript
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newBlobStr = `
|
var newBlobStr = `
|
||||||
|
const pendingFetchRequests = new Map();
|
||||||
${processM3U8.toString()}
|
${processM3U8.toString()}
|
||||||
${hookWorkerFetch.toString()}
|
${hookWorkerFetch.toString()}
|
||||||
${declareOptions.toString()}
|
${declareOptions.toString()}
|
||||||
@@ -120,6 +121,23 @@ twitch-videoad.js text/javascript
|
|||||||
ClientIntegrityHeader = e.data.value;
|
ClientIntegrityHeader = e.data.value;
|
||||||
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
||||||
AuthorizationHeader = e.data.value;
|
AuthorizationHeader = e.data.value;
|
||||||
|
} else if (e.data.key == 'FetchResponse') {
|
||||||
|
const responseData = e.data.value;
|
||||||
|
if (pendingFetchRequests.has(responseData.id)) {
|
||||||
|
const { resolve, reject } = pendingFetchRequests.get(responseData.id);
|
||||||
|
pendingFetchRequests.delete(responseData.id);
|
||||||
|
if (responseData.error) {
|
||||||
|
reject(new Error(responseData.error));
|
||||||
|
} else {
|
||||||
|
// Create a Response object from the response data
|
||||||
|
const response = new Response(responseData.body, {
|
||||||
|
status: responseData.status,
|
||||||
|
statusText: responseData.statusText,
|
||||||
|
headers: responseData.headers
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
hookWorkerFetch();
|
hookWorkerFetch();
|
||||||
@@ -152,6 +170,16 @@ twitch-videoad.js text/javascript
|
|||||||
reloadTwitchPlayer(true);
|
reloadTwitchPlayer(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.addEventListener('message', async event => {
|
||||||
|
if (event.data.key == 'FetchRequest') {
|
||||||
|
const fetchRequest = event.data.value;
|
||||||
|
const responseData = await handleWorkerFetchRequest(fetchRequest);
|
||||||
|
this.postMessage({
|
||||||
|
key: 'FetchResponse',
|
||||||
|
value: responseData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
function getAdDiv() {
|
function getAdDiv() {
|
||||||
var playerRootDiv = document.querySelector('.video-player');
|
var playerRootDiv = document.querySelector('.video-player');
|
||||||
var adDiv = null;
|
var adDiv = null;
|
||||||
@@ -317,7 +345,7 @@ twitch-videoad.js text/javascript
|
|||||||
for (var i = 0; i < 2; i++) {
|
for (var i = 0; i < 2; i++) {
|
||||||
var encodingsUrl = url;
|
var encodingsUrl = url;
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
var accessTokenResponse = await getAccessToken(channelName, OPT_BACKUP_PLAYER_TYPE, OPT_BACKUP_PLATFORM, realFetch);
|
var accessTokenResponse = await getAccessToken(channelName, OPT_BACKUP_PLAYER_TYPE, OPT_BACKUP_PLATFORM);
|
||||||
if (accessTokenResponse != null && accessTokenResponse.status === 200) {
|
if (accessTokenResponse != null && accessTokenResponse.status === 200) {
|
||||||
var accessToken = await accessTokenResponse.json();
|
var accessToken = await accessTokenResponse.json();
|
||||||
var urlInfo = new URL('https://usher.ttvnw.net/api/channel/hls/' + channelName + '.m3u8' + (new URL(url)).search);
|
var urlInfo = new URL('https://usher.ttvnw.net/api/channel/hls/' + channelName + '.m3u8' + (new URL(url)).search);
|
||||||
@@ -416,7 +444,7 @@ twitch-videoad.js text/javascript
|
|||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
function getAccessToken(channelName, playerType, platform, realFetch) {
|
function getAccessToken(channelName, playerType, platform) {
|
||||||
if (!platform) {
|
if (!platform) {
|
||||||
platform = 'web';
|
platform = 'web';
|
||||||
}
|
}
|
||||||
@@ -433,23 +461,40 @@ twitch-videoad.js text/javascript
|
|||||||
'playerType': playerType
|
'playerType': playerType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return gqlRequest(body, realFetch);
|
return gqlRequest(body);
|
||||||
}
|
}
|
||||||
function gqlRequest(body, realFetch) {
|
function gqlRequest(body) {
|
||||||
if (ClientIntegrityHeader == null) {
|
if (!gql_device_id) {
|
||||||
//console.warn('ClientIntegrityHeader is null');
|
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
//throw 'ClientIntegrityHeader is null';
|
for (let i = 0; i < 32; i += 1) {
|
||||||
}
|
gql_device_id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
var fetchFunc = realFetch ? realFetch : fetch;
|
|
||||||
return fetchFunc('https://gql.twitch.tv/gql', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
headers: {
|
|
||||||
'Client-Id': CLIENT_ID,
|
|
||||||
'Client-Integrity': ClientIntegrityHeader,
|
|
||||||
'X-Device-Id': gql_device_id,
|
|
||||||
'Authorization': AuthorizationHeader
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
var headers = {
|
||||||
|
'Client-Id': CLIENT_ID,
|
||||||
|
'Client-Integrity': ClientIntegrityHeader,
|
||||||
|
'X-Device-Id': gql_device_id,
|
||||||
|
'Authorization': AuthorizationHeader
|
||||||
|
};
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const requestId = Math.random().toString(36).substring(2, 15);
|
||||||
|
const fetchRequest = {
|
||||||
|
id: requestId,
|
||||||
|
url: 'https://gql.twitch.tv/gql',
|
||||||
|
options: {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pendingFetchRequests.set(requestId, {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
});
|
||||||
|
postMessage({
|
||||||
|
key: 'FetchRequest',
|
||||||
|
value: fetchRequest
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function parseAttributes(str) {
|
function parseAttributes(str) {
|
||||||
@@ -528,6 +573,25 @@ twitch-videoad.js text/javascript
|
|||||||
worker.postMessage({key: key, value: value});
|
worker.postMessage({key: key, value: value});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async function handleWorkerFetchRequest(fetchRequest) {
|
||||||
|
try {
|
||||||
|
const response = await window.fetch(fetchRequest.url, fetchRequest.options);
|
||||||
|
const responseBody = await response.text();
|
||||||
|
const responseObject = {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
body: responseBody
|
||||||
|
};
|
||||||
|
return responseObject;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
function hookFetch() {
|
function hookFetch() {
|
||||||
var realFetch = window.fetch;
|
var realFetch = window.fetch;
|
||||||
window.fetch = function(url, init, ...args) {
|
window.fetch = function(url, init, ...args) {
|
||||||
|
|||||||
@@ -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.35
|
// @version 1.36
|
||||||
// @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)
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
var ourTwitchAdSolutionsVersion = 2;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
var ourTwitchAdSolutionsVersion = 3;// Only bump this when there's a breaking change to Twitch, the script, or there's a conflict with an unmaintained extension which uses this script
|
||||||
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
if (window.twitchAdSolutionsVersion && window.twitchAdSolutionsVersion >= ourTwitchAdSolutionsVersion) {
|
||||||
console.log("skipping video-swap-new as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
console.log("skipping video-swap-new as there's another script active. ourVersion:" + ourTwitchAdSolutionsVersion + " activeVersion:" + window.twitchAdSolutionsVersion);
|
||||||
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
window.twitchAdSolutionsVersion = ourTwitchAdSolutionsVersion;
|
||||||
@@ -113,6 +113,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var newBlobStr = `
|
var newBlobStr = `
|
||||||
|
const pendingFetchRequests = new Map();
|
||||||
${processM3U8.toString()}
|
${processM3U8.toString()}
|
||||||
${hookWorkerFetch.toString()}
|
${hookWorkerFetch.toString()}
|
||||||
${declareOptions.toString()}
|
${declareOptions.toString()}
|
||||||
@@ -132,6 +133,23 @@
|
|||||||
ClientIntegrityHeader = e.data.value;
|
ClientIntegrityHeader = e.data.value;
|
||||||
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
} else if (e.data.key == 'UpdateAuthorizationHeader') {
|
||||||
AuthorizationHeader = e.data.value;
|
AuthorizationHeader = e.data.value;
|
||||||
|
} else if (e.data.key == 'FetchResponse') {
|
||||||
|
const responseData = e.data.value;
|
||||||
|
if (pendingFetchRequests.has(responseData.id)) {
|
||||||
|
const { resolve, reject } = pendingFetchRequests.get(responseData.id);
|
||||||
|
pendingFetchRequests.delete(responseData.id);
|
||||||
|
if (responseData.error) {
|
||||||
|
reject(new Error(responseData.error));
|
||||||
|
} else {
|
||||||
|
// Create a Response object from the response data
|
||||||
|
const response = new Response(responseData.body, {
|
||||||
|
status: responseData.status,
|
||||||
|
statusText: responseData.statusText,
|
||||||
|
headers: responseData.headers
|
||||||
|
});
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
hookWorkerFetch();
|
hookWorkerFetch();
|
||||||
@@ -164,6 +182,16 @@
|
|||||||
reloadTwitchPlayer(true);
|
reloadTwitchPlayer(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.addEventListener('message', async event => {
|
||||||
|
if (event.data.key == 'FetchRequest') {
|
||||||
|
const fetchRequest = event.data.value;
|
||||||
|
const responseData = await handleWorkerFetchRequest(fetchRequest);
|
||||||
|
this.postMessage({
|
||||||
|
key: 'FetchResponse',
|
||||||
|
value: responseData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
function getAdDiv() {
|
function getAdDiv() {
|
||||||
var playerRootDiv = document.querySelector('.video-player');
|
var playerRootDiv = document.querySelector('.video-player');
|
||||||
var adDiv = null;
|
var adDiv = null;
|
||||||
@@ -329,7 +357,7 @@
|
|||||||
for (var i = 0; i < 2; i++) {
|
for (var i = 0; i < 2; i++) {
|
||||||
var encodingsUrl = url;
|
var encodingsUrl = url;
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
var accessTokenResponse = await getAccessToken(channelName, OPT_BACKUP_PLAYER_TYPE, OPT_BACKUP_PLATFORM, realFetch);
|
var accessTokenResponse = await getAccessToken(channelName, OPT_BACKUP_PLAYER_TYPE, OPT_BACKUP_PLATFORM);
|
||||||
if (accessTokenResponse != null && accessTokenResponse.status === 200) {
|
if (accessTokenResponse != null && accessTokenResponse.status === 200) {
|
||||||
var accessToken = await accessTokenResponse.json();
|
var accessToken = await accessTokenResponse.json();
|
||||||
var urlInfo = new URL('https://usher.ttvnw.net/api/channel/hls/' + channelName + '.m3u8' + (new URL(url)).search);
|
var urlInfo = new URL('https://usher.ttvnw.net/api/channel/hls/' + channelName + '.m3u8' + (new URL(url)).search);
|
||||||
@@ -428,7 +456,7 @@
|
|||||||
},
|
},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
function getAccessToken(channelName, playerType, platform, realFetch) {
|
function getAccessToken(channelName, playerType, platform) {
|
||||||
if (!platform) {
|
if (!platform) {
|
||||||
platform = 'web';
|
platform = 'web';
|
||||||
}
|
}
|
||||||
@@ -445,23 +473,40 @@
|
|||||||
'playerType': playerType
|
'playerType': playerType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return gqlRequest(body, realFetch);
|
return gqlRequest(body);
|
||||||
}
|
}
|
||||||
function gqlRequest(body, realFetch) {
|
function gqlRequest(body) {
|
||||||
if (ClientIntegrityHeader == null) {
|
if (!gql_device_id) {
|
||||||
//console.warn('ClientIntegrityHeader is null');
|
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
//throw 'ClientIntegrityHeader is null';
|
for (let i = 0; i < 32; i += 1) {
|
||||||
}
|
gql_device_id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
var fetchFunc = realFetch ? realFetch : fetch;
|
|
||||||
return fetchFunc('https://gql.twitch.tv/gql', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
headers: {
|
|
||||||
'Client-Id': CLIENT_ID,
|
|
||||||
'Client-Integrity': ClientIntegrityHeader,
|
|
||||||
'X-Device-Id': gql_device_id,
|
|
||||||
'Authorization': AuthorizationHeader
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
var headers = {
|
||||||
|
'Client-Id': CLIENT_ID,
|
||||||
|
'Client-Integrity': ClientIntegrityHeader,
|
||||||
|
'X-Device-Id': gql_device_id,
|
||||||
|
'Authorization': AuthorizationHeader
|
||||||
|
};
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const requestId = Math.random().toString(36).substring(2, 15);
|
||||||
|
const fetchRequest = {
|
||||||
|
id: requestId,
|
||||||
|
url: 'https://gql.twitch.tv/gql',
|
||||||
|
options: {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pendingFetchRequests.set(requestId, {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
});
|
||||||
|
postMessage({
|
||||||
|
key: 'FetchRequest',
|
||||||
|
value: fetchRequest
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function parseAttributes(str) {
|
function parseAttributes(str) {
|
||||||
@@ -540,6 +585,25 @@
|
|||||||
worker.postMessage({key: key, value: value});
|
worker.postMessage({key: key, value: value});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async function handleWorkerFetchRequest(fetchRequest) {
|
||||||
|
try {
|
||||||
|
const response = await window.fetch(fetchRequest.url, fetchRequest.options);
|
||||||
|
const responseBody = await response.text();
|
||||||
|
const responseObject = {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
|
body: responseBody
|
||||||
|
};
|
||||||
|
return responseObject;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
id: fetchRequest.id,
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
function hookFetch() {
|
function hookFetch() {
|
||||||
var realFetch = window.fetch;
|
var realFetch = window.fetch;
|
||||||
window.fetch = function(url, init, ...args) {
|
window.fetch = function(url, init, ...args) {
|
||||||
|
|||||||
Reference in New Issue
Block a user