Skip to content

Commit

Permalink
🔖 Release version 2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
younesaassila authored Jun 19, 2023
2 parents 6380100 + 6b9e3ba commit dcd03ce
Show file tree
Hide file tree
Showing 32 changed files with 452 additions and 184 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ttv-lol-pro",
"version": "2.0.2",
"version": "2.1.0",
"description": "TTV LOL PRO removes most livestream ads from Twitch.",
"@parcel/bundler-default": {
"minBundles": 10000000,
Expand Down
41 changes: 17 additions & 24 deletions src/background/background.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import browser from "webextension-polyfill";
import isChromium from "../common/ts/isChromium";
import updateProxySettings from "../common/ts/updateProxySettings";
import store from "../store";
import checkForOpenedTwitchTabs from "./handlers/checkForOpenedTwitchTabs";
import onAuthRequired from "./handlers/onAuthRequired";
import onBeforeSendHeaders from "./handlers/onBeforeSendHeaders";
import onBeforeUsherRequest from "./handlers/onBeforeUsherRequest";
import onBeforeVideoWeaverRequest from "./handlers/onBeforeVideoWeaverRequest";
import onHeadersReceived from "./handlers/onHeadersReceived";
import onProxyRequest from "./handlers/onProxyRequest";
import onResponseStarted from "./handlers/onResponseStarted";
import onStartupStoreCleanup from "./handlers/onStartupStoreCleanup";
import onTabCreated from "./handlers/onTabCreated";
import onTabRemoved from "./handlers/onTabRemoved";
import onTabUpdated from "./handlers/onTabUpdated";

console.info("🚀 Background script loaded.");

Expand All @@ -22,13 +23,19 @@ browser.webRequest.onAuthRequired.addListener(
["blocking"]
);

// Monitor proxied status of requests.
browser.webRequest.onResponseStarted.addListener(onResponseStarted, {
urls: ["https://*.ttvnw.net/*", "https://*.twitch.tv/*"],
});

if (isChromium) {
const setProxySettings = () => {
if (store.readyState !== "complete")
return store.addEventListener("load", setProxySettings);
updateProxySettings();
};
setProxySettings();
// Check if there are any opened Twitch tabs on startup.
checkForOpenedTwitchTabs();

// Keep track of opened Twitch tabs to enable/disable the PAC script.
browser.tabs.onCreated.addListener(onTabCreated);
browser.tabs.onUpdated.addListener(onTabUpdated);
browser.tabs.onRemoved.addListener(onTabRemoved);
} else {
// Block tracking pixels.
browser.webRequest.onBeforeRequest.addListener(
Expand All @@ -37,15 +44,6 @@ if (isChromium) {
["blocking"]
);

// Map channel names to Video Weaver URLs.
browser.webRequest.onBeforeRequest.addListener(
onBeforeUsherRequest,
{
urls: ["https://usher.ttvnw.net/api/channel/hls/*"],
},
["blocking"]
);

// Proxy requests.
browser.proxy.onRequest.addListener(
onProxyRequest,
Expand All @@ -72,9 +70,4 @@ if (isChromium) {
},
["blocking"]
);

// Monitor responses of proxied requests.
browser.webRequest.onHeadersReceived.addListener(onHeadersReceived, {
urls: ["https://*.ttvnw.net/*", "https://*.twitch.tv/*"],
});
}
30 changes: 30 additions & 0 deletions src/background/handlers/checkForOpenedTwitchTabs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import browser from "webextension-polyfill";
import isChromium from "../../common/ts/isChromium";
import {
clearProxySettings,
updateProxySettings,
} from "../../common/ts/proxySettings";
import store from "../../store";

export default function checkForOpenedTwitchTabs() {
if (store.readyState !== "complete")
return store.addEventListener("load", checkForOpenedTwitchTabs);

browser.tabs
.query({ url: ["https://www.twitch.tv/*", "https://m.twitch.tv/*"] })
.then(tabs => {
if (tabs.length === 0) {
if (isChromium) clearProxySettings();
return;
}
console.log(
`🔍 Found ${tabs.length} opened Twitch tabs: ${tabs
.map(tab => tab.id)
.join(", ")}`
);
if (isChromium) {
updateProxySettings();
}
store.state.openedTwitchTabs = tabs.map(tab => tab.id);
});
}
61 changes: 0 additions & 61 deletions src/background/handlers/onBeforeUsherRequest.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/background/handlers/onProxyRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export default async function onProxyRequest(

function getProxyInfoArrayFromUrls(urls: string[]): ProxyInfo[] {
return [
...urls.map(url => getProxyInfoFromUrl(url)),
...urls.map(getProxyInfoFromUrl),
{ type: "direct" } as ProxyInfo, // Fallback to direct connection if all proxies fail.
];
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { WebRequest } from "webextension-polyfill";
import findChannelFromVideoWeaverUrl from "../../common/ts/findChannelFromVideoWeaverUrl";
import getHostFromUrl from "../../common/ts/getHostFromUrl";
import getProxyInfoFromUrl from "../../common/ts/getProxyInfoFromUrl";
import isChromium from "../../common/ts/isChromium";
import {
passportHostRegex,
twitchGqlHostRegex,
twitchTvHostRegex,
usherHostRegex,
videoWeaverHostRegex,
} from "../../common/ts/regexes";
import { getStreamStatus, setStreamStatus } from "../../common/ts/streamStatus";
import store from "../../store";
import type { ProxyInfo, StreamStatus } from "../../types";
import type { ProxyInfo } from "../../types";

export default function onHeadersReceived(
details: WebRequest.OnHeadersReceivedDetailsType & {
export default function onResponseStarted(
details: WebRequest.OnResponseStartedDetailsType & {
proxyInfo?: ProxyInfo;
}
): void | WebRequest.BlockingResponseOrPromise {
): void {
const host = getHostFromUrl(details.url);
if (!host) return;

Expand Down Expand Up @@ -77,25 +80,31 @@ export default function onHeadersReceived(
}

function getProxyFromDetails(
details: WebRequest.OnHeadersReceivedDetailsType & {
details: WebRequest.OnResponseStartedDetailsType & {
proxyInfo?: ProxyInfo;
}
): string | null {
const proxyInfo = details.proxyInfo; // Firefox only.
if (!proxyInfo || proxyInfo.type === "direct") return null;
return `${proxyInfo.host}:${proxyInfo.port}`;
}

function getStreamStatus(channelName: string | null): StreamStatus | null {
if (!channelName) return null;
return store.state.streamStatuses[channelName] ?? null;
}

function setStreamStatus(
channelName: string | null,
streamStatus: StreamStatus
): boolean {
if (!channelName) return false;
store.state.streamStatuses[channelName] = streamStatus;
return true;
if (isChromium) {
const ip = details.ip;
if (!ip) return null;
const dnsResponse = store.state.dnsResponses.find(
dnsResponse => dnsResponse.ips.indexOf(ip) !== -1
);
if (!dnsResponse) return null;
const proxies = [
...store.state.optimizedProxies,
...store.state.normalProxies,
];
const proxyInfoArray = proxies.map(getProxyInfoFromUrl);
const possibleProxies = proxyInfoArray.filter(
proxy => proxy.host === dnsResponse.host
);
if (possibleProxies.length === 1)
return `${possibleProxies[0].host}:${possibleProxies[0].port}`;
return dnsResponse.host;
} else {
const proxyInfo = details.proxyInfo; // Firefox only.
if (!proxyInfo || proxyInfo.type === "direct") return null;
return `${proxyInfo.host}:${proxyInfo.port}`;
}
}
2 changes: 2 additions & 0 deletions src/background/handlers/onStartupStoreCleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export default function onStartupStoreCleanup(): void {
if (store.readyState !== "complete")
return store.addEventListener("load", onStartupStoreCleanup);

store.state.dnsResponses = [];
store.state.openedTwitchTabs = [];
store.state.streamStatuses = {};
store.state.videoWeaverUrlsByChannel = {};
}
18 changes: 18 additions & 0 deletions src/background/handlers/onTabCreated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Tabs } from "webextension-polyfill";
import getHostFromUrl from "../../common/ts/getHostFromUrl";
import isChromium from "../../common/ts/isChromium";
import { updateProxySettings } from "../../common/ts/proxySettings";
import { twitchTvHostRegex } from "../../common/ts/regexes";
import store from "../../store";

export default function onTabCreated(tab: Tabs.Tab): void {
if (!tab.url) return;
const host = getHostFromUrl(tab.url);
if (twitchTvHostRegex.test(host)) {
console.log(`➕ Opened Twitch tab: ${tab.id}`);
if (isChromium && store.state.openedTwitchTabs.length === 0) {
updateProxySettings();
}
store.state.openedTwitchTabs.push(tab.id);
}
}
14 changes: 14 additions & 0 deletions src/background/handlers/onTabRemoved.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import isChromium from "../../common/ts/isChromium";
import { clearProxySettings } from "../../common/ts/proxySettings";
import store from "../../store";

export default function onTabRemoved(tabId: number): void {
const index = store.state.openedTwitchTabs.indexOf(tabId);
if (index !== -1) {
console.log(`➖ Closed Twitch tab: ${tabId}`);
store.state.openedTwitchTabs.splice(index, 1);
if (isChromium && store.state.openedTwitchTabs.length === 0) {
clearProxySettings();
}
}
}
42 changes: 42 additions & 0 deletions src/background/handlers/onTabUpdated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Tabs } from "webextension-polyfill";
import getHostFromUrl from "../../common/ts/getHostFromUrl";
import isChromium from "../../common/ts/isChromium";
import {
clearProxySettings,
updateProxySettings,
} from "../../common/ts/proxySettings";
import { twitchTvHostRegex } from "../../common/ts/regexes";
import store from "../../store";

export default function onTabUpdated(
tabId: number,
changeInfo: Tabs.OnUpdatedChangeInfoType,
tab: Tabs.Tab
): void {
// Also check for `changeInfo.status === "complete"` because the `url` property
// is not always accurate when navigating to a new page.
if (!(changeInfo.url || changeInfo.status === "complete")) return;

const url = changeInfo.url || tab.url;
const host = getHostFromUrl(url);
const isTwitchTab = twitchTvHostRegex.test(host);
const wasTwitchTab = store.state.openedTwitchTabs.includes(tabId);

if (isTwitchTab && !wasTwitchTab) {
console.log(`➕ Opened Twitch tab: ${tabId}`);
if (isChromium && store.state.openedTwitchTabs.length === 0) {
updateProxySettings();
}
store.state.openedTwitchTabs.push(tabId);
}
if (!isTwitchTab && wasTwitchTab) {
const index = store.state.openedTwitchTabs.indexOf(tabId);
if (index !== -1) {
console.log(`➖ Closed Twitch tab: ${tabId}`);
store.state.openedTwitchTabs.splice(index, 1);
if (isChromium && store.state.openedTwitchTabs.length === 0) {
clearProxySettings();
}
}
}
}
37 changes: 37 additions & 0 deletions src/common/ts/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Read a file from the user's computer.
* @param accept
* @returns
*/
export async function readFile(accept = "text/plain;charset=utf-8") {
return new Promise<string>((resolve, reject) => {
const input = document.createElement("input");
input.type = "file";
input.accept = accept;
input.addEventListener("change", async e => {
const input = e.target as HTMLInputElement;
const file = input.files?.[0];
if (!file) return reject("No file selected");
const data = await file.text();
return resolve(data);
});
input.click();
});
}

/**
* Save a file to the user's computer.
* @param filename
* @param content
* @param type
*/
export function saveFile(
filename: string,
content: string,
type = "text/plain;charset=utf-8"
) {
const a = document.createElement("a");
a.setAttribute("href", `data:${type},` + encodeURIComponent(content));
a.setAttribute("download", filename);
a.click();
}
Loading

0 comments on commit dcd03ce

Please sign in to comment.