♻️ Refactor project
232
.gitignore
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,macos,node
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=windows,visualstudiocode,macos,node
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
# Support for Project snippet scope
|
||||
.vscode/*.code-snippets
|
||||
|
||||
# Ignore code-workspaces
|
||||
*.code-workspace
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,macos,node
|
||||
|
||||
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
||||
|
3
.prettierrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"arrowParens": "avoid"
|
||||
}
|
59
README.md
@ -1,12 +1,59 @@
|
||||
# TTV.LOL browser extensions
|
||||
<h1 align="center">
|
||||
<img src="src/images/icon.png" height="100" width="100" alt="Icon" />
|
||||
<br />
|
||||
TTV LOL
|
||||
<br />
|
||||
</h1>
|
||||
|
||||
This respository contains the browser extensions for [TTV.LOL](https://ttv.lol).
|
||||
<div align="center">
|
||||
<a href="https://github.com/younesaassila/ttv-lol/issues">
|
||||
<img
|
||||
alt="GitHub issues"
|
||||
src="https://img.shields.io/github/issues/younesaassila/ttv-lol"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/younesaassila/ttv-lol/network">
|
||||
<img
|
||||
alt="GitHub forks"
|
||||
src="https://img.shields.io/github/forks/younesaassila/ttv-lol"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/younesaassila/ttv-lol/stargazers">
|
||||
<img
|
||||
alt="GitHub stars"
|
||||
src="https://img.shields.io/github/stars/younesaassila/ttv-lol"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
# Chrome webstore
|
||||
<br />
|
||||
|
||||
The extension can be installed via the chrome webstore [here](https://chrome.google.com/webstore/detail/ttv-lol/ofbbahodfeppoklmgjiokgfdgcndngjm).
|
||||
```text
|
||||
This is a fork of the original project at https://github.com/TTV-LOL/extensions
|
||||
```
|
||||
|
||||
# Firefox Addon
|
||||
>
|
||||
|
||||
The extension can be installed via the Firefox addons store [here](https://addons.mozilla.org/en-US/firefox/addon/ttv-lol/).
|
||||
[TTV LOL](https://ttv.lol/) removes livestream ads from [Twitch](https://www.twitch.tv/).
|
||||
|
||||
This fork:
|
||||
|
||||
- disables TTV LOL for channels you are subscribed to.
|
||||
|
||||
## Installation
|
||||
|
||||
### Chrome
|
||||
|
||||
1. Download the latest version of this extension in the "Releases" section (ZIP file)
|
||||
1. Unzip the ZIP file you just downloaded
|
||||
1. Go to `chrome://extensions`
|
||||
1. Turn on `Developer mode`
|
||||
1. Click on `Load unpacked`
|
||||
1. Select the unzipped folder you just created
|
||||
|
||||
### Firefox
|
||||
|
||||
1. Download the latest version of this extension in the "Releases" section (ZIP file)
|
||||
1. Go to `about:addons`
|
||||
1. Click on the gear icon then select "Install Add-on From File…"
|
||||
1. Select the ZIP file you just downloaded
|
||||
|
@ -1,68 +0,0 @@
|
||||
html {
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
background: #151619;
|
||||
color: #c9cbcd;
|
||||
font-family: Open Sans,Segoe UI,sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 6px;
|
||||
color: #c3c4ca;
|
||||
font-weight: bold;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
transition: all 150ms ease-in-out;
|
||||
}
|
||||
.button:hover {
|
||||
background-color: #1d1f23;
|
||||
}
|
||||
.button:not(:first-of-type) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
.discord {
|
||||
overflow: visible;
|
||||
margin-right: 3px;
|
||||
display: inline-block;
|
||||
}
|
||||
.button-arrow .arrow-icon {
|
||||
overflow: visible;
|
||||
margin-left: 3px;
|
||||
margin-bottom: -2px;
|
||||
width: 8px;
|
||||
}
|
||||
.icon {
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.buton-text{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.button-arrow .arrow-head {
|
||||
transform: translateX(0);
|
||||
transition: transform 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow .arrow-body {
|
||||
opacity: 0;
|
||||
transform: scaleX(1);
|
||||
transition: transform 150ms ease-in-out, opacity 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow:hover .arrow-head {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
.button-arrow:hover .arrow-body {
|
||||
opacity: 1;
|
||||
transform: scaleX(2);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../css/styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div style="background-color: #202127; border-radius: 8px; margin: 30px;">
|
||||
<img width="60%" src="../img/ttvlol.png">
|
||||
</div>
|
||||
<div class="button-group">
|
||||
|
||||
<a href="https://ttv.lol/donate" target="_blank" class="button button-arrow">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="16" height="16" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
Donate
|
||||
<svg viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
|
||||
<g class="arrow-head">
|
||||
<path d="M1 1C4.5 4 5 4.38484 5 4.5C5 4.61516 4.5 5 1 8" stroke="currentColor" stroke-width="2"/>
|
||||
</g>
|
||||
<g class="arrow-body">
|
||||
<path d="M3.5 4.5H0" stroke="currentColor" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<a href="https://discord.gg/NAv7AFAyTF" target="_blank" class="button button-arrow">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" style="margin-right: 3px;" width="16" height="16" fill="currentColor" class="bi bi-discord" viewBox="0 0 16 16">
|
||||
<path d="M6.552 6.712c-.456 0-.816.4-.816.888s.368.888.816.888c.456 0 .816-.4.816-.888.008-.488-.36-.888-.816-.888zm2.92 0c-.456 0-.816.4-.816.888s.368.888.816.888c.456 0 .816-.4.816-.888s-.36-.888-.816-.888z"/>
|
||||
<path d="M13.36 0H2.64C1.736 0 1 .736 1 1.648v10.816c0 .912.736 1.648 1.64 1.648h9.072l-.424-1.48 1.024.952.968.896L15 16V1.648C15 .736 14.264 0 13.36 0zm-3.088 10.448s-.288-.344-.528-.648c1.048-.296 1.448-.952 1.448-.952-.328.216-.64.368-.92.472-.4.168-.784.28-1.16.344a5.604 5.604 0 0 1-2.072-.008 6.716 6.716 0 0 1-1.176-.344 4.688 4.688 0 0 1-.584-.272c-.024-.016-.048-.024-.072-.04-.016-.008-.024-.016-.032-.024-.144-.08-.224-.136-.224-.136s.384.64 1.4.944c-.24.304-.536.664-.536.664-1.768-.056-2.44-1.216-2.44-1.216 0-2.576 1.152-4.664 1.152-4.664 1.152-.864 2.248-.84 2.248-.84l.08.096c-1.44.416-2.104 1.048-2.104 1.048s.176-.096.472-.232c.856-.376 1.536-.48 1.816-.504.048-.008.088-.016.136-.016a6.521 6.521 0 0 1 4.024.752s-.632-.6-1.992-1.016l.112-.128s1.096-.024 2.248.84c0 0 1.152 2.088 1.152 4.664 0 0-.68 1.16-2.448 1.216z"/>
|
||||
</svg>
|
||||
Discord
|
||||
<svg viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
|
||||
<g class="arrow-head">
|
||||
<path d="M1 1C4.5 4 5 4.38484 5 4.5C5 4.61516 4.5 5 1 8" stroke="currentColor" stroke-width="2"/>
|
||||
</g>
|
||||
<g class="arrow-body">
|
||||
<path d="M3.5 4.5H0" stroke="currentColor" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,57 +0,0 @@
|
||||
function stripUnusedParams(str, params) {
|
||||
if (!params) {
|
||||
params = [ 'token', 'sig' ];
|
||||
}
|
||||
var tempUrl = new URL('https://localhost/' + str);
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
tempUrl.searchParams.delete(params[i]);
|
||||
}
|
||||
return tempUrl.pathname.substring(1) + tempUrl.search;
|
||||
}
|
||||
|
||||
function onPlaylistBeforeRequest(details) {
|
||||
|
||||
details.url = stripUnusedParams(details.url, null);
|
||||
|
||||
// (hls\/|vod\/)(.+?)$
|
||||
const match = /(hls|vod)\/(.+?)$/gim.exec(details.url);
|
||||
|
||||
if (match !== null && match.length > 1) {
|
||||
var playlistType = match[1] == "vod" ? "vod" : "playlist";
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", `https://api.ttv.lol/ping`, false);
|
||||
req.send();
|
||||
|
||||
// validate that our API is online, if not fallback to standard stream with ads
|
||||
if (req.status != 200) {
|
||||
return {
|
||||
redirectUrl: details.url
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
redirectUrl: `https://api.ttv.lol/${playlistType}/${encodeURIComponent(match[2])}`,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
chrome.webRequest.onBeforeRequest.addListener(
|
||||
onPlaylistBeforeRequest,
|
||||
{ urls: ["https://usher.ttvnw.net/api/channel/hls/*", "https://usher.ttvnw.net/vod/*"] },
|
||||
["blocking", "extraHeaders"]
|
||||
);
|
||||
|
||||
function onBeforeSendHeaders(req) {
|
||||
req.requestHeaders.push({ name: 'X-Donate-To', value: "https://ttv.lol/donate" })
|
||||
return {
|
||||
requestHeaders: req.requestHeaders
|
||||
}
|
||||
}
|
||||
|
||||
chrome.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{ urls: ["https://api.ttv.lol/playlist/*", "https://api.ttv.lol/vod/*"] },
|
||||
["blocking", "requestHeaders"]
|
||||
);
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"background": {
|
||||
"persistent": true,
|
||||
"scripts": [
|
||||
"js/background.js"
|
||||
]
|
||||
},
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"default_popup": "common/html/popup.html",
|
||||
"default_title": "TTV LOL"
|
||||
},
|
||||
"description": "TTV LOL",
|
||||
"icons": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"manifest_version": 2,
|
||||
"name": "TTV LOL",
|
||||
"permissions": [
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"https://*.twitch.tv/*",
|
||||
"https://usher.ttvnw.net/*",
|
||||
"https://api.ttv.lol/*"
|
||||
],
|
||||
"version": "0.0.0.4"
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
html, body {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
background: #151619;
|
||||
color: #c9cbcd;
|
||||
font-family: Open Sans,Segoe UI,sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 6px;
|
||||
color: #c3c4ca;
|
||||
font-weight: bold;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
transition: all 150ms ease-in-out;
|
||||
}
|
||||
.button:hover {
|
||||
background-color: #1d1f23;
|
||||
}
|
||||
.button:not(:first-of-type) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
.discord {
|
||||
overflow: visible;
|
||||
margin-right: 3px;
|
||||
display: inline-block;
|
||||
}
|
||||
.button-arrow .arrow-icon {
|
||||
overflow: visible;
|
||||
margin-left: 3px;
|
||||
margin-bottom: -2px;
|
||||
width: 8px;
|
||||
}
|
||||
.icon {
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.buton-text{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.button-arrow .arrow-head {
|
||||
transform: translateX(0);
|
||||
transition: transform 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow .arrow-body {
|
||||
opacity: 0;
|
||||
transform: scaleX(1);
|
||||
transition: transform 150ms ease-in-out, opacity 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow:hover .arrow-head {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
.button-arrow:hover .arrow-body {
|
||||
opacity: 1;
|
||||
transform: scaleX(2);
|
||||
}
|
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 4.0 KiB |
@ -1,58 +0,0 @@
|
||||
function stripUnusedParams(str, params) {
|
||||
if (!params) {
|
||||
params = [ 'token', 'sig' ];
|
||||
}
|
||||
var tempUrl = new URL('https://localhost/' + str);
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
tempUrl.searchParams.delete(params[i]);
|
||||
}
|
||||
return tempUrl.pathname.substring(1) + tempUrl.search;
|
||||
}
|
||||
|
||||
function onPlaylistBeforeRequest(details) {
|
||||
|
||||
details.url = stripUnusedParams(details.url, null);
|
||||
|
||||
// (hls\/|vod\/)(.+?)$
|
||||
const match = /(hls|vod)\/(.+?)$/gim.exec(details.url);
|
||||
|
||||
if (match !== null && match.length > 1) {
|
||||
var playlistType = match[1] == "vod" ? "vod" : "playlist";
|
||||
|
||||
return new Promise(resolve => {
|
||||
fetch(
|
||||
'https://api.ttv.lol/ping',
|
||||
{
|
||||
method: 'GET',
|
||||
}).then(r => {
|
||||
if (r.status == 200) {
|
||||
resolve({ redirectUrl: `https://api.ttv.lol/${playlistType}/${encodeURIComponent(match[2])}` });
|
||||
} else {
|
||||
resolve({});
|
||||
}
|
||||
}).catch((error) => {
|
||||
resolve({});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeRequest.addListener(
|
||||
onPlaylistBeforeRequest,
|
||||
{ urls: ["https://usher.ttvnw.net/api/channel/hls/*", "https://usher.ttvnw.net/vod/*"] },
|
||||
["blocking"]
|
||||
);
|
||||
|
||||
function onBeforeSendHeaders(req) {
|
||||
req.requestHeaders.push({ name: 'X-Donate-To', value: "https://ttv.lol/donate" })
|
||||
return {
|
||||
requestHeaders: req.requestHeaders
|
||||
}
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{ urls: ["https://api.ttv.lol/playlist/*", "https://api.ttv.lol/vod/*"] },
|
||||
["blocking", "requestHeaders"]
|
||||
);
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"background": {
|
||||
"persistent": true,
|
||||
"scripts": [
|
||||
"js/background.js"
|
||||
]
|
||||
},
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"default_popup": "common/html/popup.html",
|
||||
"default_title": "TTV LOL"
|
||||
},
|
||||
"description": "TTV LOL",
|
||||
"icons": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"manifest_version": 2,
|
||||
"name": "TTV LOL",
|
||||
"permissions": [
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"https://*.twitch.tv/*",
|
||||
"https://usher.ttvnw.net/*",
|
||||
"https://api.ttv.lol/*"
|
||||
],
|
||||
"version": "0.0.0.4"
|
||||
}
|
4364
package-lock.json
generated
Normal file
38
package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "ttv-lol",
|
||||
"version": "1.0.0-younesaassila",
|
||||
"description": "TTV LOL removes livestream ads from twitch.tv",
|
||||
"targets": {
|
||||
"webext-dev": {
|
||||
"sourceMap": {
|
||||
"inline": true,
|
||||
"inlineSources": true
|
||||
}
|
||||
},
|
||||
"webext-prod": {}
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "parcel src/manifest.json --host localhost --target webext-dev",
|
||||
"lint": "prettier --write ./src",
|
||||
"build": "parcel build src/manifest.json --target webext-prod"
|
||||
},
|
||||
"keywords": [
|
||||
"twitch",
|
||||
"web-extension",
|
||||
"adblocker"
|
||||
],
|
||||
"author": "TTV-LOL (https://github.com/TTV-LOL)",
|
||||
"contributors": [
|
||||
"Younes Aassila (https://github.com/younesaassila)"
|
||||
],
|
||||
"license": "UNLICENSED",
|
||||
"devDependencies": {
|
||||
"@parcel/config-webextension": "^2.5.0",
|
||||
"@types/webextension-polyfill": "^0.8.3",
|
||||
"parcel": "^2.5.0",
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "^4.6.4",
|
||||
"webextension-polyfill": "^0.9.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
70
src/common/css/styles.css
Normal file
@ -0,0 +1,70 @@
|
||||
html,
|
||||
body {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
html {
|
||||
background: #151619;
|
||||
color: #c9cbcd;
|
||||
font-family: Open Sans, Segoe UI, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 6px;
|
||||
color: #c3c4ca;
|
||||
font-weight: bold;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
transition: all 150ms ease-in-out;
|
||||
}
|
||||
.button:hover {
|
||||
background-color: #1d1f23;
|
||||
}
|
||||
.button:not(:first-of-type) {
|
||||
margin-left: 15px;
|
||||
}
|
||||
.discord {
|
||||
overflow: visible;
|
||||
margin-right: 3px;
|
||||
display: inline-block;
|
||||
}
|
||||
.button-arrow .arrow-icon {
|
||||
overflow: visible;
|
||||
margin-left: 3px;
|
||||
margin-bottom: -2px;
|
||||
width: 8px;
|
||||
}
|
||||
.icon {
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.buton-text {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.button-arrow .arrow-head {
|
||||
transform: translateX(0);
|
||||
transition: transform 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow .arrow-body {
|
||||
opacity: 0;
|
||||
transform: scaleX(1);
|
||||
transition: transform 150ms ease-in-out, opacity 150ms ease-in-out;
|
||||
}
|
||||
.button-arrow:hover .arrow-head {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
.button-arrow:hover .arrow-body {
|
||||
opacity: 1;
|
||||
transform: scaleX(2);
|
||||
}
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
27
src/manifest.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "TTV LOL (Younes Aassila's Fork)",
|
||||
"description": "TTV LOL removes livestream ads from twitch.tv",
|
||||
"version": "1.0.0",
|
||||
"background": {
|
||||
"persistent": true,
|
||||
"scripts": ["ts/background.ts"]
|
||||
},
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"default_title": "TTV LOL",
|
||||
"default_popup": "common/html/popup.html"
|
||||
},
|
||||
"icons": {
|
||||
"128": "images/icon.png"
|
||||
},
|
||||
"permissions": [
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"https://*.twitch.tv/*",
|
||||
"https://usher.ttvnw.net/*",
|
||||
"https://api.ttv.lol/*"
|
||||
]
|
||||
}
|
59
src/ts/background.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import browser, { WebRequest } from "webextension-polyfill";
|
||||
import { PlaylistType } from "../types";
|
||||
|
||||
function onBeforeRequest(details: WebRequest.OnBeforeRequestDetailsType) {
|
||||
const match = /(hls|vod)\/(.+?)$/gim.exec(details.url);
|
||||
if (match == null) return {};
|
||||
|
||||
const [_, type, path] = match;
|
||||
if (type == null || path == null) return {};
|
||||
|
||||
const playlistType =
|
||||
type.toLowerCase() === "vod" ? PlaylistType.VOD : PlaylistType.Playlist;
|
||||
|
||||
// Synchronous XMLHttpRequest is required for the plugin to work in Chrome.
|
||||
const request = new XMLHttpRequest();
|
||||
request.open("GET", `https://api.ttv.lol/ping`, false);
|
||||
request.send();
|
||||
|
||||
if (request.status === 200) {
|
||||
console.info("[TTV LOL] Successfully pinged TTV LOL's server.");
|
||||
return {
|
||||
redirectUrl: `https://api.ttv.lol/${playlistType}/${encodeURIComponent(
|
||||
path
|
||||
)}`,
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeRequest.addListener(
|
||||
onBeforeRequest,
|
||||
{
|
||||
urls: [
|
||||
"https://usher.ttvnw.net/api/channel/hls/*",
|
||||
"https://usher.ttvnw.net/vod/*",
|
||||
],
|
||||
},
|
||||
["blocking"]
|
||||
);
|
||||
|
||||
function onBeforeSendHeaders(
|
||||
details: WebRequest.OnBeforeSendHeadersDetailsType
|
||||
) {
|
||||
console.log(`[TTV LOL] ${details.method} ${details.url}`);
|
||||
details.requestHeaders.push({
|
||||
name: "X-Donate-To",
|
||||
value: "https://ttv.lol/donate",
|
||||
});
|
||||
return {
|
||||
requestHeaders: details.requestHeaders,
|
||||
};
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{ urls: ["https://api.ttv.lol/playlist/*", "https://api.ttv.lol/vod/*"] },
|
||||
["blocking", "requestHeaders"]
|
||||
);
|
4
src/types.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export enum PlaylistType {
|
||||
Playlist = "playlist",
|
||||
VOD = "vod",
|
||||
}
|