Compare commits

...

99 Commits

Author SHA1 Message Date
Ajay Ramachandran
f4a129b346 Merge pull request #307 from ajayyy/experimental
Skipping fixes
2020-03-30 14:34:31 -04:00
Ajay Ramachandran
6d60a90533 Increased version number. 2020-03-30 14:18:11 -04:00
Ajay Ramachandran
0d33794636 Fixed almost zero second sponsors skipping a little too late. 2020-03-30 14:11:46 -04:00
Ajay Ramachandran
e62d46f2dd Improved zero second skipping for directly loaded videos 2020-03-30 14:07:35 -04:00
Ajay Ramachandran
7f36c7eec3 Merge pull request #302 from Joe-Dowd/restrict-keybindings
Restrict keybindings
2020-03-26 12:35:28 -04:00
Ajay Ramachandran
08d28798c6 Localised key errors 2020-03-26 12:30:06 -04:00
Ajay Ramachandran
fe33277d8f Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into restrict-keybindings 2020-03-26 12:27:06 -04:00
Ajay Ramachandran
feec5b4e22 Added spacing and separated code into a function 2020-03-26 12:26:47 -04:00
Ajay Ramachandran
62b5e90d87 Merge pull request #300 from Joe-Dowd/debug-output
Added copy debug information to clipboard options element.
2020-03-26 12:19:07 -04:00
Ajay Ramachandran
2c980a269d Fixed sponsorTimes data on export and import 2020-03-26 12:18:52 -04:00
Ajay Ramachandran
1da60e38a1 Merge pull request #304 from ajayyy/experimental
Scheduling fixes
2020-03-25 19:01:43 -04:00
Ajay Ramachandran
ed67cc52fe Fixed mobile YouTube starting sponsor detection that are not exactly 0 seconds. 2020-03-21 20:59:08 -04:00
Joe-Dowd
b614dce91a Added more restricted characters 2020-03-20 19:55:29 +00:00
Joe-Dowd
c013c7ef0f added N and i to the list of restricted characters 2020-03-20 19:50:38 +00:00
Joe-Dowd
c78e2cd214 Fixed mod keys when setting keybinding 2020-03-20 19:39:37 +00:00
Joe-Dowd
da5a3841bd Added restrictions to keybindings. 2020-03-20 15:35:23 +00:00
Joe Dowd
e73d79071c Added copy debug information to clipboard options element. 2020-03-18 00:15:04 +00:00
Ajay Ramachandran
0467dd5d21 Made sure no skips are scheduled while paused 2020-03-11 19:39:08 -04:00
Ajay Ramachandran
5f879bceab Fixed where repo-token was inputted in release workflow 2020-03-10 23:30:53 -04:00
Ajay Ramachandran
457bd15e17 Merge pull request #298 from ajayyy/experimental
Options Improvements
2020-03-10 23:24:36 -04:00
Ajay Ramachandran
cc1b8ee499 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into experimental 2020-03-10 23:23:30 -04:00
Ajay Ramachandran
4a9ed1348e Increase version number 2020-03-10 23:23:10 -04:00
Ajay Ramachandran
5595420be6 Removed redundant if statement 2020-03-10 23:22:57 -04:00
Ajay Ramachandran
191e9ceb6f Makes sure the playing and play listener both don't get called at the same time.
This led to double notices.
2020-03-10 23:22:17 -04:00
Ajay Ramachandran
1e26faa57c Update README.md 2020-03-10 12:11:08 -04:00
Ajay Ramachandran
030256c9e1 Enable checkbox when the permission prompt is successful 2020-03-10 02:14:00 -04:00
Ajay Ramachandran
77eff12d9b Merge pull request #261 from OfficialNoob/patch-1
Made decodeStoredItem detect item type
2020-03-10 01:21:10 -04:00
Ajay Ramachandran
2967fce013 Update README.md 2020-03-10 00:57:44 -04:00
Ajay Ramachandran
db1def623a Update README.md 2020-03-10 00:56:58 -04:00
Ajay Ramachandran
140e324bf1 Update README.md 2020-03-10 00:55:18 -04:00
Ajay Ramachandran
f0bf051259 Properly ask for permissions when changing the server address 2020-03-10 00:48:53 -04:00
Ajay Ramachandran
2ec47d52cd Added basic options import/export 2020-03-10 00:33:50 -04:00
Ajay Ramachandran
50002cfbbd Fix github token using the wrong key in release workflow 2020-03-09 23:10:59 -04:00
Ajay Ramachandran
6ccd4b8b37 Merge pull request #297 from ajayyy/experimental
Fix non zero second skips
2020-03-09 23:05:45 -04:00
Ajay Ramachandran
c0894afff9 Prevent manual skipping votes from affecting to UI and happening when auto vote is off 2020-03-09 23:03:24 -04:00
Ajay Ramachandran
09f244150c Fixed skipping for non zero second sponsors.
Also now using the playing event to fix issues with mobile YouTube skipping.
2020-03-09 23:00:39 -04:00
Ajay Ramachandran
efec8b320c Increase version num 2020-03-09 18:38:02 -04:00
Ajay Ramachandran
e6ea9f77e9 Fixed skip scheduling for auto skip 2020-03-09 18:34:33 -04:00
Ajay Ramachandran
0813aa4ba3 Prevent release workflow from running multiple times 2020-03-09 18:30:57 -04:00
Ajay Ramachandran
ba575f6b8d Merge pull request #296 from ajayyy/experimental
Prevent manual skips from triggering a view and improved skip schedule for manual skip
2020-03-09 18:20:11 -04:00
Ajay Ramachandran
ff9b2338e0 Fixed scheduling being wrong when manual skip is enabled 2020-03-09 18:12:05 -04:00
Ajay Ramachandran
d2bb4b38e3 Increased version number 2020-03-09 18:07:29 -04:00
Ajay Ramachandran
760c08dd0c Prevent manual skips from triggering a view 2020-03-09 18:07:06 -04:00
Ajay Ramachandran
50517eb462 Switched upload to release action 2020-03-09 11:15:29 -04:00
Ajay Ramachandran
e77425c21e Merge pull request #294 from ajayyy/experimental
Another potential fix for zero second sponsor freezing
2020-03-09 11:04:26 -04:00
Ajay Ramachandran
f63abb053d Revert to only using workflows 2020-03-09 11:02:14 -04:00
Ajay Ramachandran
7b5703aa04 Fixed action format 2020-03-09 10:56:06 -04:00
Ajay Ramachandran
d641066312 Checkout in CI 2020-03-09 10:52:43 -04:00
Ajay Ramachandran
44ca8d47d8 Moved CI into the right place 2020-03-09 10:51:26 -04:00
Ajay Ramachandran
d5f41bf4ad Fixed CI 2020-03-09 10:49:50 -04:00
Ajay Ramachandran
73e8926444 Start skip schedule from skip time to prevent slow video updates from breaking it. 2020-03-09 10:43:13 -04:00
Ajay Ramachandran
5ad694af65 Increase version number 2020-03-08 23:26:46 -04:00
Ajay Ramachandran
d7f7acb219 Fixed release action 2020-03-08 23:20:41 -04:00
Ajay Ramachandran
b4be51333a Merge pull request #293 from ajayyy/experimental
Fixed double sponsor skip for zero second sponsors
2020-03-08 23:17:48 -04:00
Ajay Ramachandran
ae94811a00 Increase version number 2020-03-08 23:16:50 -04:00
Ajay Ramachandran
a484f2f2cc Fixed double sponsor skip for zero second sponsors 2020-03-08 23:16:09 -04:00
Ajay Ramachandran
9cce4e734d Merge pull request #292 from grishka/russian
Fix Russian translation and add missing strings
2020-03-07 12:34:48 -05:00
Grishka
3c63644213 fix 2020-03-07 13:45:56 +03:00
Grishka
ad25bc34de Add missing Russian strings 2020-03-07 13:37:58 +03:00
Ajay Ramachandran
0241e15691 Only seek if the video is not paused 2020-02-28 15:06:08 -05:00
Ajay Ramachandran
af9a6b8a84 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into experimental 2020-02-28 14:09:21 -05:00
Ajay Ramachandran
329b188435 Checkout before using other CI 2020-02-27 22:23:33 -05:00
Ajay Ramachandran
2e49bb73c5 Merge pull request #290 from ajayyy/experimental
Potentially fixed zero second skip spam
2020-02-27 22:21:33 -05:00
Ajay Ramachandran
5158020293 Potentially fixed zero second skip spam 2020-02-27 22:20:30 -05:00
Ajay Ramachandran
feaf80ad1e Merge pull request #289 from Joe-Dowd/messages-typo
Typo in en messages locale "skipeed -> skipped"
2020-02-25 15:14:01 -05:00
Joe Dowd
7fbd89159e Typo in en messages locale skipped 2020-02-25 18:25:28 +00:00
Ajay Ramachandran
716861da18 Fixed beta builds 2020-02-23 20:49:17 -05:00
Ajay Ramachandran
d0a34d423c Fix release CI 2020-02-23 20:42:12 -05:00
Ajay Ramachandran
adfba72f19 Merge pull request #286 from ajayyy/experimental
Mobile fix + mobile update notice
2020-02-23 20:40:48 -05:00
Ajay Ramachandran
f00337c376 Increase version number. 2020-02-23 20:39:29 -05:00
Ajay Ramachandran
737a023b65 Added mobile support message. 2020-02-23 20:39:13 -05:00
Ajay Ramachandran
5551344355 Fixed mobile notice zoom on Firefox 2020-02-23 16:14:18 -05:00
Ajay Ramachandran
07f64382fb Merge pull request #285 from cherryblossom000/patch-1
Fix "0 sponsor" in popup
2020-02-23 11:21:21 -05:00
Ajay Ramachandran
1c7cde2a19 Changed to !== 2020-02-23 11:20:21 -05:00
cherryblossom
8510a7f3d8 Fix popup saying "0 sponsor" 2020-02-23 17:03:18 +11:00
Ajay Ramachandran
db60b11a17 Merge pull request #284 from ajayyy/experimental
CI Improvements
2020-02-20 15:38:35 -05:00
Ajay Ramachandran
6a212b762a Fixed invalid release workflow 2020-02-20 12:21:30 -05:00
Ajay Ramachandran
c8ec2922cf Added makedir to CI 2020-02-20 12:17:51 -05:00
Ajay Ramachandran
b629b7d333 Added basic release workflow 2020-02-20 12:14:01 -05:00
Ajay Ramachandran
514a8b62d6 Added beta build to CI 2020-02-20 11:39:06 -05:00
Ajay Ramachandran
cd11618a5d Merge pull request #283 from ajayyy/experimental
New skipping mechanism fixes
2020-02-20 11:25:32 -05:00
Ajay Ramachandran
8be3cb157a Increased version number 2020-02-20 11:23:44 -05:00
Ajay Ramachandran
4ca57cc025 Fixed preview sponsors not skipping when only they are there. 2020-02-19 13:45:00 -05:00
Ajay Ramachandran
397bcc94c5 Remove redundant code 2020-02-19 13:35:05 -05:00
Ajay Ramachandran
8b28bccfd7 Run dev now uses dev build. 2020-02-19 12:57:22 -05:00
Ajay Ramachandran
c6107057d9 Firefox dev environment now loads Firefox uBlock Origin 2020-02-19 12:54:58 -05:00
Ajay Ramachandran
ab2a9530e9 Sped up zero second sponsors a tiny bit 2020-02-19 12:41:22 -05:00
Ajay Ramachandran
bfc771bd99 Removed unused variables 2020-02-19 12:37:39 -05:00
Ajay Ramachandran
e75e588755 Sped up direct links a tiny bit. 2020-02-19 12:37:17 -05:00
Ajay Ramachandran
0266bb49ca Fixed typo 2020-02-19 12:35:10 -05:00
Ajay Ramachandran
9e693fd555 Update README.md 2020-02-19 12:33:48 -05:00
Ajay Ramachandran
8d82a6a3e6 Fixed data old format migration. 2020-02-14 23:20:11 -05:00
Ajay Ramachandran
88a8fda566 Moved window.SB creation for security reasons. 2020-02-14 23:16:01 -05:00
Official Noob
995fe072bd Merge pull request #1 from ajayyy/master
Update
2020-02-09 22:15:27 +00:00
Ajay Ramachandran
8cdbebd6de Added the config as a global variable. 2020-02-08 20:16:26 -05:00
Ajay Ramachandran
94af8ab301 Prevent all strings from being parsed as JSON. 2020-02-08 20:15:49 -05:00
Ajay Ramachandran
be3a4a4e91 Added support for old format. 2020-02-08 20:08:34 -05:00
Official Noob
1c17464c94 config => defaults 2020-02-04 23:29:11 +00:00
Official Noob
8896c5707a Made decodeStoredItem detect item type
Not tested because SB.config cant be used anymore :(
2020-02-04 22:16:40 +00:00
18 changed files with 840 additions and 126 deletions

View File

@@ -23,6 +23,10 @@ jobs:
with:
name: ChromeExtension
path: dist
- run: mkdir ./builds
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtension.zip ./dist
# Create Firefox artifacts
- name: Create Firefox artifacts
@@ -31,4 +35,28 @@ jobs:
with:
name: FirefoxExtension
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist
# Create Beta artifacts (Builds with the name changed to beta)
- name: Create Chrome Beta artifacts
run: npm run build:chrome -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: ChromeExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist
- name: Create Firefox Beta artifacts
run: npm run build:firefox -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: FirefoxExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist

76
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: Upload Release Build
on:
release:
types: [published]
jobs:
build:
name: Upload Release
runs-on: ubuntu-latest
steps:
# Initialization
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
- run: npm install
- name: Copy configuration
run: cp config.json.example config.json
# Create Chrome artifacts
- name: Create Chrome artifacts
run: npm run build:chrome
- uses: actions/upload-artifact@v1
with:
name: ChromeExtension
path: dist
- run: mkdir ./builds
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtension.zip ./dist
# Create Firefox artifacts
- name: Create Firefox artifacts
run: npm run build:firefox
- uses: actions/upload-artifact@v1
with:
name: FirefoxExtension
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist
# Create Beta artifacts (Builds with the name changed to beta)
- name: Create Chrome Beta artifacts
run: npm run build:chrome -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: ChromeExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist
- name: Create Firefox Beta artifacts
run: npm run build:firefox -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: FirefoxExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist
# Upload each release asset
- name: Upload to release
uses: Shopify/upload-to-release@master
with:
args: builds/ChromeExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to release
uses: Shopify/upload-to-release@master
with:
args: builds/FirefoxExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -40,37 +40,35 @@ The backend server code is available here: https://github.com/ajayyy/SponsorBloc
It is a simple Sqlite database that will hold all the timing data.
To make sure that this project doesn't die, I have made the database publicly downloadable at https://api.sponsor.ajay.app/database.db. So, you can download a backup or get archive.org to take a backup for you if you want.
To make sure that this project doesn't die, I have made the database publicly downloadable at https://sponsor.ajay.app/database.db. You can download a backup or get archive.org to take a backup for you if you want.
Hopefully this project can be combined with projects like [this](https://github.com/Sponsoff/sponsorship_remover) and use this data to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea.
The dataset and API are now being used in some [ports](https://github.com/ajayyy/SponsorBlock/wiki/Unofficial-Ports) as well as a [neural network](https://github.com/andrewzlee/NeuralBlock).
A [previous project](https://github.com/Sponsoff/sponsorship_remover) attempted to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea starting from a crowd-sourced system instead.
# API
You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#api-docs).
# Build Yourself
# Building
You can load this project as an unpacked extension. Make sure to rename the `config.json.example` file to `config.json` before installing.
There are also other build scripts available. Install `npm`, then run `npm install` in the repository to install dependencies.
There are also other build scripts available. Install `npm`, then run `npm install` in the repository.
Run `npm run build` to generate a Chrome extension.
Use `npm run build:firefox` to generate a Firefox extension.
The result is in `dist`. This can be loaded as an unpacked extension
## Developing with a clean profile
Run `npm run dev` to run the extension using a clean browser profile with hot reloading. Use `npm run dev:firefox` for Firefox. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
## Packing
Run `npm run build` to generate a packed Chrome extension.
Use `npm run build:firefox` to generate a Firefox extension.
The result is in `dist`.
# Credit
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) used to be used.
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) previously was used.
Original code from [YTSponsorSkip](https://github.com/OfficialNoob/YTSponsorSkip), but not much of the code is left.
Originally forked from [YTSponsorSkip](https://github.com/OfficialNoob/YTSponsorSkip), but zero code remains.
Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a>

View File

@@ -0,0 +1,4 @@
{
"name": "BETA - SponsorBlock"
}

View File

@@ -0,0 +1,8 @@
{
"browser_specific_settings": {
"gecko": {
"id": "sponsorBlockerBETA@ajay.app"
}
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "__MSG_Name__",
"version": "1.2.14",
"version": "1.2.23",
"default_locale": "en",
"description": "__MSG_Description__",
"content_scripts": [{

View File

@@ -24,16 +24,19 @@
},
"scripts": {
"web-run": "npm run web-run:chrome",
"web-run:firefox": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm",
"web-run:firefox": "cd dist && web-ext run --start-url https://addons.mozilla.org/firefox/addon/ublock-origin/",
"web-run:chrome": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm -t chromium",
"build": "npm run build:chrome",
"build:chrome": "webpack --env.browser=chrome --config webpack/webpack.prod.js",
"build:firefox": "webpack --env.browser=firefox --config webpack/webpack.prod.js",
"build:dev": "npm run build:dev:chrome",
"build:dev:chrome": "webpack --env.browser=chrome --config webpack/webpack.dev.js",
"build:dev:firefox": "webpack --env.browser=firefox --config webpack/webpack.dev.js",
"build:watch": "npm run build:watch:chrome",
"build:watch:chrome": "webpack --env.browser=chrome --config webpack/webpack.dev.js --watch",
"build:watch:firefox": "webpack --env.browser=firefox --config webpack/webpack.dev.js --watch",
"dev": "npm run build && concurrently \"npm run web-run\" \"npm run build:watch\"",
"dev:firefox": "npm run build:firefox && concurrently \"npm run web-run:firefox\" \"npm run build:watch:firefox\"",
"dev": "npm run build:dev && concurrently \"npm run web-run\" \"npm run build:watch\"",
"dev:firefox": "npm run build:dev:firefox && concurrently \"npm run web-run:firefox\" \"npm run build:watch:firefox\"",
"clean": "rimraf dist",
"test": "npx jest"
},

View File

@@ -160,7 +160,7 @@
"message": "Click the button below when the sponsorship starts and ends to record and\nsubmit it to the database."
},
"popupHint": {
"message": "Hint: Press the semicolon key while focused on a video report the start/end of a sponsor and quote to submit. (This can be changed in the options)"
"message": "Hint: Press the semicolon key while focused on a video to report the start/end of a sponsor and quote to submit. (This can be changed in the options)"
},
"lastTimes": {
"message": "Latest Sponsor Message Times Chosen"
@@ -226,7 +226,7 @@
"message": "Show Notice Again"
},
"longDescription": {
"message": "SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.",
"message": "SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.",
"description": "Full description of the extension on the store pages."
},
"website": {
@@ -381,17 +381,11 @@
"whatAutoUpvote": {
"message": "With this enabled, the extension will upvote all submissions you view if you do not report them. If the notice is disabled, this will not occur."
},
"invidiousInfo1": {
"message": "Invidious (the 3rd party YouTube site) support has been added!"
},
"invidiousInfo2": {
"message": "You MUST enable it in the options for it to work."
},
"minDuration": {
"message": "Minimum duration (seconds):"
},
"minDurationDescription": {
"message": "Sponsor segments shorter than the set value will not be skipeed or show in the player."
"message": "Sponsor segments shorter than the set value will not be skipped or show in the player."
},
"shortCheck": {
"message": "The following submission is shorter than your minimum duration option. This could mean that this is already submitted, and just being ignored due to this option. Are you sure you would like to submit?"
@@ -428,5 +422,44 @@
},
"whatUnlistedCheck": {
"message": "This setting will significantly slow down SponsorBlock. Sponsor lookups require sending the video ID to the server. If you are concerned about unlisted video IDs being sent over the internet, enable this option."
},
"mobileUpdateInfo": {
"message": "m.youtube.com is now supported"
},
"exportOptions": {
"message": "Import/Export All Options"
},
"whatExportOptions": {
"message": "This is your entire configuration in JSON. This includes your userID, so be sure to share this wisely."
},
"setOptions": {
"message": "Set Options"
},
"exportOptionsWarning": {
"message": "Warning: Changing the options is permanent and can break your install. Are you sure you would like to do this? Make sure to backup your old one just in case."
},
"incorrectlyFormattedOptions": {
"message": "This JSON is not formatted correctly. Your options have not been changed."
},
"copyDebugInformation": {
"message": "Copy Debug Information To Clipboard"
},
"copyDebugInformationFailed": {
"message": "Failed to write to clipboard"
},
"copyDebugInformationOptions": {
"message": "Copies information to the clipboard to be provided to a developer when raising a bug / when a developer requests it. Sensitive information such as your user ID, whitelisted channels, and custom server address have been removed. However it does contain information such as your useragent, browser, operating system, and extension version number. "
},
"copyDebugInformationComplete": {
"message": "The debug information has been copied to the clip board. Feel free to remove any information you would rather not share. Save this in a text file or paste into the bug report."
},
"theKey": {
"message": "The key"
},
"keyAlreadyUsedByYouTube": {
"message": "is already used by youtube. Please select another key."
},
"keyAlreadyUsed": {
"message": "is bound to another action. Please select another key."
}
}

View File

@@ -28,10 +28,10 @@
"message": "Канал добавлен в белый список!"
},
"Sponsor": {
"message": "Спонсор"
"message": "спонсора"
},
"Sponsors": {
"message": "Спонсоры"
"message": "спонсоров"
},
"Segment": {
"message": "спонсорская вставка"
@@ -123,5 +123,299 @@
},
"submitCheck": {
"message": "Вы уверены, что хотите отправить эту информацию?"
},
"whitelistChannel": {
"message": "Добавить канал в белый список"
},
"removeFromWhitelist": {
"message": "Удалить канал из белого списка"
},
"voteOnTime": {
"message": "Проголосовать за время спонсорской вставки"
},
"recordTimes": {
"message": "Записать время спонсорской вставки"
},
"soFarUHSubmited": {
"message": "На данный момент Вы отправили"
},
"savedPeopleFrom": {
"message": "Вы помогли людям сэкономить "
},
"viewLeaderboard": {
"message": "Посмотреть доску почёта"
},
"here": {
"message": "здесь"
},
"recordTimesDescription": {
"message": "Нажмите кнопку ниже, когда спонсорская вставка начинается и заканчивается, чтобы записать\nи отправить её в базу данных."
},
"popupHint": {
"message": "Подсказка: нажмите ;, чтобы сообщить начало/конец спонсорской вставки, и \", чтобы отправить. (Это можно изменить в настройках)"
},
"lastTimes": {
"message": "Последнее выбранное время спонсорской вставки"
},
"clearTimesButton": {
"message": "Очистить время"
},
"submitTimesButton": {
"message": "Отправить время"
},
"publicStats": {
"message": "Оно используется на публичной странице статистики, чтобы показать Ваш вклад. Её можно посмотреть "
},
"setUsername": {
"message": "Установить имя пользователя"
},
"discordAdvert": {
"message": "Присоединяйтесь к официальному серверу Discord, чтобы оставить предложения и обратную связь!"
},
"hideThis": {
"message": "Скрыть это"
},
"Options": {
"message": "Настройки"
},
"showButtons": {
"message": "Показывать кнопки в плеере YouTube"
},
"hideButtons": {
"message": "Скрыть кнопки в плеере YouTube"
},
"hideButtonsDescription": {
"message": "Эта настройка скрывает кнопки для отправки спонсорских вставок, которые появляются в плеере YouTube. Они могут раздражать\n некоторых. Вместо кнопок для отправки спонсорских вставок можно использовать это всплывающее окно. Чтобы скрыть\nуведомление, нажмите кнопку \"Не показывать снова\" в уведомлении. Вы всегда сможете включить эти настройки обратно."
},
"showInfoButton": {
"message": "Показывать кнопку информации в плеере YouTube"
},
"hideInfoButton": {
"message": "Скрыть кнопку информации в плеере YouTube"
},
"whatInfoButton": {
"message": "Эта кнопка открывает всплывающее окно на странице YouTube."
},
"hideDeleteButton": {
"message": "Скрыть кнопку удаления в плеере YouTube"
},
"showDeleteButton": {
"message": "Показывать кнопку удаления в плеере YouTube"
},
"whatDeleteButton": {
"message": "Эта кнопка позволяет Вам очистить все спонсорские вставки в плеере YouTube."
},
"disableViewTracking": {
"message": "Отключить отслеживание количества пропусков спонсорских вставок"
},
"enableViewTracking": {
"message": "Включить отслеживание количества пропусков спонсорских вставок"
},
"whatViewTracking": {
"message": "Эта возможность отслеживает, какие спонсорские вставки Вы пропустили, чтобы помочь пользователям узнать, насколько их\nвклад помог другим, и используется как метрика, чтобы убедиться, что спам не попадает в базу данных. Расширение отправляет\nсообщение на сервер каждый раз, когда Вы пропускаете спонсорскую вставку. Надеемся, большая часть пользователей не поменяет эту настройку, так что у нас будет точная статистика просмотров :)"
},
"showNotice": {
"message": "Показывать уведомление снова"
},
"longDescription": {
"message": "SponsorBlock — это расширение, которое пропускает спонсорские вставки в видео на YouTube. SponsorBlock — это краудсорсинговое расширение, которое позволяет каждому отправить время начала и конца спонсорских сегментов в видео на YouTube. После того, как кто-нибудь отправляет эту информацию, все остальные пользователи расширения будут автоматически пропускать спонсорские сегменты.",
"description": "Полное описание расширения на страницах магазинов."
},
"website": {
"message": "Сайт",
"description": "Используется на странице магазина Firefox"
},
"sourceCode": {
"message": "Исходный код",
"description": "Используется на странице магазина Firefox"
},
"noticeUpdate": {
"message": "Уведомление было обновлено!",
"description": "The first line of the message displayed after the notice was upgraded."
},
"noticeUpdate2": {
"message": "Если оно Вам всё равно не нравится, нажмите \"не показывать\".",
"description": "The second line of the message displayed after the notice was upgraded."
},
"setStartSponsorShortcut": {
"message": "Назначить горячую клавишу для начала спонсорской вставки"
},
"setSubmitKeybind": {
"message": "Назначить горячую клавишу для отправки"
},
"keybindDescription": {
"message": "Нажмите клавишу, чтобы выбрать её"
},
"keybindDescriptionComplete": {
"message": "Клавиша назначена на: "
},
"0": {
"message": "Таймаут подключения. Проверьте ваше соединение с интернетом. Если ваш интернет работает, сервер, скорее всего, перегружен или лежит."
},
"disableSkipping": {
"message": "Отключить SponsorBlock"
},
"enableSkipping": {
"message": "Включить SponsorBlock"
},
"yourWork": {
"message": "Ваша работа",
"description": "Used to describe the section that will show you the statistics from your submissions."
},
"502": {
"message": "Похоже, сервер перегружен. Попробуйте ещё раз через несколько секунд."
},
"errorCode": {
"message": "Код ошибки: "
},
"noticeTitleNotSkipped": {
"message": "Пропустить спонсорскую вставку?"
},
"skip": {
"message": "Пропустить"
},
"disableAutoSkip": {
"message": "Отключить автоматический пропуск"
},
"enableAutoSkip": {
"message": "Включить автоматический пропуск"
},
"autoSkipDescription": {
"message": "Автоматический пропуск будет пропускать спонсорские вставки за Вас. Если выключено, будет показываться уведомление с предложением пропустить."
},
"youHaveSkipped": {
"message": "Вы пропустили "
},
"youHaveSaved": {
"message": "Вы сэкономили "
},
"minLower": {
"message": "минуту"
},
"minsLower": {
"message": "минут"
},
"hourLower": {
"message": "час"
},
"hoursLower": {
"message": "часов"
},
"youHaveSavedTime": {
"message": "Вы сэкономили людям"
},
"youHaveSavedTimeEnd": {
"message": " их жизней."
},
"guildlinesSummary": {
"message": "- Убедитесь, что Ваш сегмент содержит только платную интеграцию, и больше ничего.\n- Убедитесь, что пропуск этого сегмента не пропустит никакой ценный контент\n- Если всё видео целиком спонсорское, пожалуйста, не сообщайте о нём. Система для сообщения о целых видео скоро выйдет.\n- Пожалуйста, не сообщайте об отказах от ответственности, которые могут показать предвзятость (если видео с обзором проплачено, не пропускайте, когда они это упоминают)."
},
"statusReminder": {
"message": "Смотрите состояние сервера на status.sponsor.ajay.app."
},
"changeUserID": {
"message": "Импортировать/экспортировать Ваш идентификатор пользователя"
},
"whatChangeUserID": {
"message": "Это нужно держать в секрете. Это как пароль, не стоит им ни с кем делиться. Если он у кого-то есть, он сможет выдать себя за Вас."
},
"setUserID": {
"message": "Установить идентификатор пользователя"
},
"userIDChangeWarning": {
"message": "Внимание: изменение идентификатора пользователя необратимо. Вы действительно хотите это сделать? Сделайте резервную копию вашего старого на всякий случай."
},
"createdBy": {
"message": "Создано"
},
"autoSkip": {
"message": "Автоматический пропуск"
},
"showSkipNotice": {
"message": "Показывать уведомление после пропуска спонсорской вставки"
},
"keybindCurrentlySet": {
"message": ". Он сейчас назначен на:"
},
"supportInvidious": {
"message": "Поддержка Invidious"
},
"supportInvidiousDescription": {
"message": "Invidious (invidio.us) — это неофициальный клиент YouTube. Чтобы включить поддержку, Вам понадобится принять дополнительные разрешения. Это НЕ работает в приватном режиме в Chrome и других вариантах Chromium."
},
"optionsInfo": {
"message": "Включить поддержку Invidious, выключить автоматический пропуск, скрыть кнопки и не только."
},
"addInvidiousInstance": {
"message": "Добавить инстанс Invidious"
},
"addInvidiousInstanceDescription": {
"message": "Добавить свой инстанс Invidious. Формат: ТОЛЬКО домен. Например, invidious.ajay.app"
},
"add": {
"message": "Добавить"
},
"addInvidiousInstanceError": {
"message": "Это неправильный домен. Введите ТОЛЬКО домен. Например, invidious.ajay.app"
},
"resetInvidiousInstance": {
"message": "Сбросить список инстансов Invidious"
},
"resetInvidiousInstanceAlert": {
"message": "Вы собираетесь сбросить список инстансов Invidious"
},
"currentInstances": {
"message": "Текущие инстансы:"
},
"enableAutoUpvote": {
"message": "Автоматически голосовать \"за\""
},
"whatAutoUpvote": {
"message": "Если это включено, расширение будет голосовать \"за\" все предложения других пользователей, если Вы на них не пожалуетесь. Если уведомление отключено, это не будет происходить."
},
"minDuration": {
"message": "Минимальная длительность (секунд):"
},
"minDurationDescription": {
"message": "Спонсорские сегменты короче этого значения не будут пропускаться и не будут показаны в плеере."
},
"shortCheck": {
"message": "Следующий диапазон времени короче, чем Ваша настройка минимальной длительности. Это может означать, что он уже был отправлен, и просто игнорируется из-за этой настройки. Вы действительно хотите отправить?"
},
"showUploadButton": {
"message": "Показывать кнопку отправки"
},
"whatUploadButton": {
"message": "Эта кнопка появляется в плеере YouTube после того, как Вы выбрали отметку времени и готовы к отправке."
},
"customServerAddress": {
"message": "Адрес сервера SponsorBlock"
},
"customServerAddressDescription": {
"message": "Адрес, по которому SponsorBlock обращается к серверу.\nМеняйте только если Вы подняли свой сервер."
},
"save": {
"message": "Сохранить"
},
"reset": {
"message": "Сбросить"
},
"customAddressError": {
"message": "Этот адрес неправильного формата. Убедитесь, что он начинается с http:// или https://, и что на конце нет слэшей."
},
"areYouSureReset": {
"message": "Вы действительно хотите это сбросить?"
},
"confirmPrivacy": {
"message": "Было обнаружено, что это видео непубличное. Нажмите \"отмена\", если не хотите проверять его на спонсоров."
},
"unlistedCheck": {
"message": "Игнорировать непубличные видео"
},
"whatUnlistedCheck": {
"message": "Эта настройка значительно замедлит SponsorBlock. Поиск спонсоров требует отправки идентификатора видео на сервер. Если Вас беспокоит отправка идентификаторов непубличных видео по интернету, включите эту настройку."
},
"mobileUpdateInfo": {
"message": "m.youtube.com теперь поддерживается"
}
}

View File

@@ -307,6 +307,46 @@
<br/>
<br/>
<div option-type="private-text-change" sync-option="*" confirm-message="exportOptionsWarning">
<div class="option-button trigger-button">
__MSG_exportOptions__
</div>
<br/>
<div class="small-description">__MSG_whatExportOptions__</div>
<div class="option-hidden-section hidden">
<br/>
<input class="option-text-box" type="text">
<br/>
<br/>
<div class="option-button text-change-set">
__MSG_setOptions__
</div>
</div>
</div>
<br/>
<br/>
<div option-type="button-press" sync-option="copyDebugInformation" confirm-message="copyDebugInformation">
<div class="option-button trigger-button">
__MSG_copyDebugInformation__
</div>
<br/>
<div class="small-description">__MSG_copyDebugInformationOptions__</div>
</div>
<br/>
<br/>
<div option-type="text-change" sync-option="serverAddress">
<label class="text-label-container">

View File

@@ -1,5 +1,8 @@
import * as Types from "./types";
import Config from "./config";
// Make the config public for debugging purposes
(<any> window).SB = Config;
import Utils from "./utils";
var utils = new Utils({
@@ -86,9 +89,9 @@ chrome.runtime.onInstalled.addListener(function (object) {
//save this UUID
Config.config.userID = newUserID;
//TODO: Remove when invidious support is old
//TODO: Remove when mobile support is old
// Don't show this to new users
Config.config.invidiousUpdateInfoShowCount = 6;
// Config.config.mobileUpdateShowCount = 1;
}
}, 1500);
});

View File

@@ -20,12 +20,12 @@ interface SBConfig {
hideDiscordLaunches: number,
hideDiscordLink: boolean,
invidiousInstances: string[],
invidiousUpdateInfoShowCount: number,
autoUpvote: boolean,
supportInvidious: boolean,
serverAddress: string,
minDuration: number,
checkForUnlistedVideos: boolean
checkForUnlistedVideos: boolean,
mobileUpdateShowCount: number
}
interface SBObject {
@@ -33,6 +33,10 @@ interface SBObject {
defaults: SBConfig;
localConfig: SBConfig;
config: SBConfig;
// Functions
encodeStoredItem<T>(data: T): T | Array<any>;
convertJSON(): void;
}
// Allows a SBMap to be conveted into json form
@@ -84,13 +88,8 @@ class SBMap<T, U> extends Map {
return result;
}
toJSON() {
return Array.from(this.entries());
}
}
var Config: SBObject = {
/**
* Callback function when an option is updated
@@ -116,29 +115,33 @@ var Config: SBObject = {
hideDiscordLaunches: 0,
hideDiscordLink: false,
invidiousInstances: ["invidio.us", "invidiou.sh", "invidious.snopyta.org"],
invidiousUpdateInfoShowCount: 0,
autoUpvote: true,
supportInvidious: false,
serverAddress: CompileConfig.serverAddress,
minDuration: 0,
checkForUnlistedVideos: false
checkForUnlistedVideos: false,
mobileUpdateShowCount: 0
},
localConfig: null,
config: null
config: null,
// Functions
encodeStoredItem,
convertJSON
};
// Function setup
/**
* A SBMap cannot be stored in the chrome storage.
* This data will be encoded into an array instead as specified by the toJSON function.
* This data will be encoded into an array instead
*
* @param data
*/
function encodeStoredItem(data) {
function encodeStoredItem<T>(data: T): T | Array<any> {
// if data is SBMap convert to json for storing
if(!(data instanceof SBMap)) return data;
return JSON.stringify(data);
return Array.from(data.entries());
}
/**
@@ -147,19 +150,31 @@ function encodeStoredItem(data) {
*
* @param {*} data
*/
function decodeStoredItem(id: string, data) {
if(typeof data !== "string") return data;
try {
let str = JSON.parse(data);
if(!Array.isArray(str)) return data;
return new SBMap(id, str);
} catch(e) {
function decodeStoredItem<T>(id: string, data: T): T | SBMap<string, any> {
if (!Config.defaults[id]) return data;
// If all else fails, return the data
return data;
if (Config.defaults[id] instanceof SBMap) {
try {
let jsonData: any = data;
// Check if data is stored in the old format for SBMap (a JSON string)
if (typeof data === "string") {
try {
jsonData = JSON.parse(data);
} catch(e) {
// Continue normally (out of this if statement)
}
}
if (!Array.isArray(jsonData)) return data;
return new SBMap(id, jsonData);
} catch(e) {
console.error("Failed to parse SBMap: " + id);
}
}
// If all else fails, return the data
return data;
}
function configProxy(): any {
@@ -232,7 +247,7 @@ function resetConfig() {
Config.config = Config.defaults;
};
function convertJSON() {
function convertJSON(): void {
Object.keys(Config.localConfig).forEach(key => {
Config.localConfig[key] = decodeStoredItem(key, Config.localConfig[key]);
});

View File

@@ -43,8 +43,14 @@ var lastPreviewBarUpdate;
//whether the duration listener listening for the duration changes of the video has been setup yet
var durationListenerSetUp = false;
// Timestamp of the last duration change
var lastDurationChange = 0;
// Is the video currently being switched
var switchingVideos = null;
// Used by the play and playing listeners to make sure two aren't
// called at the same time
var lastCheckTime = 0;
var lastCheckVideoTime = -1;
//the channel this video is about
var channelURL;
@@ -66,10 +72,7 @@ var previewResetter: NodeJS.Timeout = null;
var controls = null;
// Direct Links after the config is loaded
utils.wait(() => Config.config !== null).then(() => videoIDChange(getYouTubeVideoID(document.URL)));
//the last time looked at (used to see if this time is in the interval)
var lastTime = -1;
utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYouTubeVideoID(document.URL)));
//the amount of times the sponsor lookup has retried
//this only happens if there is an error
@@ -240,8 +243,8 @@ document.onkeydown = function(e: KeyboardEvent){
}
function resetValues() {
//reset last sponsor times
lastTime = -1;
lastCheckTime = 0;
lastCheckVideoTime = -1;
//reset sponsor times
sponsorTimes = null;
@@ -255,6 +258,13 @@ function resetValues() {
//reset sponsor data found check
sponsorDataFound = false;
if (switchingVideos === null) {
// When first loading a video, it is not switching videos
switchingVideos = false;
} else {
switchingVideos = true;
}
}
async function videoIDChange(id) {
@@ -430,14 +440,14 @@ function createPreviewBar(): void {
* This happens when the resolution changes or at random time to clear memory.
*/
function durationChangeListener() {
lastDurationChange = Date.now();
updatePreviewBar();
}
function cancelSponsorSchedule(): void {
if (currentSkipSchedule !== null) {
clearTimeout(currentSkipSchedule);
currentSkipSchedule = null;
}
}
@@ -447,27 +457,42 @@ function cancelSponsorSchedule(): void {
*/
function startSponsorSchedule(currentTime?: number): void {
cancelSponsorSchedule();
if (video.paused) return;
if (sponsorTimes === null || Config.config.disableSkipping || channelWhitelisted){
if (Config.config.disableSkipping || channelWhitelisted){
return;
}
if (currentTime === undefined) currentTime = video.currentTime;
if (currentTime === undefined || currentTime === null) currentTime = video.currentTime;
let skipInfo = getNextSkipIndex(currentTime);
if (skipInfo.index === -1) return;
let skipTime = skipInfo.array[skipInfo.index];
let timeUntilSponsor = skipTime[0] - currentTime;
currentSkipSchedule = setTimeout(() => {
let skippingFunction = () => {
let forcedSkipTime: number = null;
if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) {
skipToTime(video, skipInfo.index, skipInfo.array, skipInfo.openNotice);
startSponsorSchedule();
} else {
startSponsorSchedule();
if (Config.config.disableAutoSkip) {
forcedSkipTime = skipTime[0] + 0.001;
} else {
forcedSkipTime = skipTime[1];
}
}
}, timeUntilSponsor * 1000 * (1 / video.playbackRate));
startSponsorSchedule(forcedSkipTime);
};
if (timeUntilSponsor <= 0) {
skippingFunction();
} else {
currentSkipSchedule = setTimeout(skippingFunction, timeUntilSponsor * 1000 * (1 / video.playbackRate));
}
}
function sponsorsLookup(id: string, channelIDPromise?) {
@@ -488,11 +513,34 @@ function sponsorsLookup(id: string, channelIDPromise?) {
if (!seekListenerSetUp && !Config.config.disableSkipping) {
seekListenerSetUp = true;
video.addEventListener('seeked', () => startSponsorSchedule());
video.addEventListener('play', () => startSponsorSchedule());
video.addEventListener('play', () => {
switchingVideos = false;
// Make sure it doesn't get double called with the playing event
if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) {
lastCheckTime = Date.now();
lastCheckVideoTime = video.currentTime;
startSponsorSchedule();
}
});
video.addEventListener('playing', () => {
// Make sure it doesn't get double called with the play event
if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) {
lastCheckTime = Date.now();
lastCheckVideoTime = video.currentTime;
startSponsorSchedule();
}
});
video.addEventListener('seeked', () => {
if (!video.paused) startSponsorSchedule();
});
video.addEventListener('ratechange', () => startSponsorSchedule());
video.addEventListener('seeking', cancelSponsorSchedule);
video.addEventListener('pause', cancelSponsorSchedule);
startSponsorSchedule();
}
if (channelIDPromise !== undefined) {
@@ -545,27 +593,29 @@ function sponsorsLookup(id: string, channelIDPromise?) {
UUIDs = smallUUIDs;
}
// See if there are any zero second sponsors
let zeroSecondSponsor = false;
for (const time of sponsorTimes) {
if (time[0] <= 0) {
zeroSecondSponsor = true;
break;
}
}
if (!zeroSecondSponsor) {
for (const time of sponsorTimesSubmitting) {
if (time[0] <= 0) {
zeroSecondSponsor = true;
if (!switchingVideos) {
// See if there are any starting sponsors
let startingSponsor: number = -1;
for (const time of sponsorTimes) {
if (time[0] <= video.currentTime && time[0] > startingSponsor && time[1] > video.currentTime) {
startingSponsor = time[0];
break;
}
}
}
if (!startingSponsor) {
for (const time of sponsorTimesSubmitting) {
if (time[0] <= video.currentTime && time[0] > startingSponsor && time[1] > video.currentTime) {
startingSponsor = time[0];
break;
}
}
}
if (zeroSecondSponsor) {
startSponsorSchedule(0);
} else {
startSponsorSchedule();
if (startingSponsor !== -1) {
startSponsorSchedule(startingSponsor);
} else {
startSponsorSchedule();
}
}
// Reset skip save
@@ -767,7 +817,8 @@ function getNextSkipIndex(currentTime: number): {array: number[][], index: numbe
let minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime));
if (minPreviewSponsorTimeIndex == -1 || sponsorStartTimes[minSponsorTimeIndex] < previewSponsorStartTimes[minPreviewSponsorTimeIndex]) {
if ((minPreviewSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) ||
sponsorStartTimes[minSponsorTimeIndex] < previewSponsorStartTimes[minPreviewSponsorTimeIndex]) {
return {
array: sponsorTimes,
index: minSponsorTimeIndex,
@@ -791,6 +842,8 @@ function getNextSkipIndex(currentTime: number): {array: number[][], index: numbe
* @param hideHiddenSponsors
*/
function getStartTimes(sponsorTimes: number[][], minimum?: number, hideHiddenSponsors: boolean = false): number[] {
if (sponsorTimes === null) return [];
let startTimes: number[] = [];
for (let i = 0; i < sponsorTimes.length; i++) {
@@ -802,7 +855,7 @@ function getStartTimes(sponsorTimes: number[][], minimum?: number, hideHiddenSpo
return startTimes;
}
//skip from fhe start time to the end time for a certain index sponsor time
//skip from the start time to the end time for a certain index sponsor time
function skipToTime(v, index, sponsorTimes, openNotice) {
if (!Config.config.disableAutoSkip || previewResetter !== null) {
v.currentTime = sponsorTimes[index][1];
@@ -816,8 +869,16 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
if (openNotice) {
//send out the message saying that a sponsor message was skipped
if (!Config.config.dontShowNotice) {
let skipNotice = new SkipNotice(this, currentUUID, Config.config.disableAutoSkip, skipNoticeContentContainer);
//TODO: Remove this when Mobile support is old
if (Config.config.mobileUpdateShowCount < 1) {
skipNotice.addNoticeInfoMessage(chrome.i18n.getMessage("mobileUpdateInfo"));
Config.config.mobileUpdateShowCount += 1;
}
//auto-upvote this sponsor
if (Config.config.trackViewCount && !Config.config.disableAutoSkip && Config.config.autoUpvote) {
vote(1, currentUUID, null);
@@ -825,16 +886,14 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
}
//send telemetry that a this sponsor was skipped
if (Config.config.trackViewCount && !sponsorSkipped[index]) {
if (Config.config.trackViewCount && !sponsorSkipped[index] && !Config.config.disableAutoSkip) {
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
if (!Config.config.disableAutoSkip) {
// Count this as a skip
Config.config.minutesSaved = Config.config.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60;
Config.config.skipCount = Config.config.skipCount + 1;
// Count this as a skip
Config.config.minutesSaved = Config.config.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60;
Config.config.skipCount = Config.config.skipCount + 1;
sponsorSkipped[index] = true;
}
sponsorSkipped[index] = true;
}
}
}

View File

@@ -1,5 +1,7 @@
'use strict';
import Config from "../config";
/**
* The notice that tells the user that a sponsor was just skipped
*/
@@ -58,7 +60,7 @@ class SkipNotice {
noticeElement.style.zIndex = String(50 + amountOfPreviousNotices);
if (contentContainer().onMobileYouTube) {
noticeElement.style.bottom = "4em";
noticeElement.style.zoom = "0.8";
noticeElement.style.transform = "scale(0.8) translate(10%, 10%)";
}
//add mouse enter and leave listeners
@@ -305,7 +307,7 @@ class SkipNotice {
if (this.manualSkip) {
this.changeNoticeTitle(chrome.i18n.getMessage("noticeTitle"));
this.contentContainer().vote(1, this.UUID, this);
if (Config.config.autoUpvote) this.contentContainer().vote(1, this.UUID);
}
}

View File

@@ -1,4 +1,8 @@
import Config from "./config";
import * as CompileConfig from "../config.json";
// Make the config public for debugging purposes
(<any> window).SB = Config;
import Utils from "./utils";
var utils = new Utils();
@@ -72,7 +76,7 @@ async function init() {
textChangeInput.value = Config.config[textChangeOption];
textChangeSetButton.addEventListener("click", () => {
textChangeSetButton.addEventListener("click", async () => {
// See if anything extra must be done
switch (textChangeOption) {
case "serverAddress":
@@ -84,6 +88,18 @@ async function init() {
return;
}
// Permission needed on Firefox
if (utils.isFirefox()) {
let permissionSuccess = await new Promise((resolve, reject) => {
chrome.permissions.request({
origins: [textChangeInput.value + "/"],
permissions: []
}, resolve);
});
if (!permissionSuccess) return;
}
break;
}
@@ -112,6 +128,16 @@ async function init() {
invidiousInstanceAddInit(<HTMLElement> optionsElements[i], privateTextChangeOption);
}
break;
case "button-press":
let actionButton = optionsElements[i].querySelector(".trigger-button");
switch(optionsElements[i].getAttribute("sync-option")) {
case "copyDebugInformation":
actionButton.addEventListener("click", copyDebugOutputToClipboard);
break;
}
break;
case "keybind-change":
let keybindButton = optionsElements[i].querySelector(".trigger-button");
@@ -259,6 +285,8 @@ function invidiousOnClick(checkbox: HTMLInputElement, option: string) {
if (!granted) {
Config.config[option] = false;
checkbox.checked = false;
} else {
checkbox.checked = true;
}
});
} else {
@@ -291,7 +319,7 @@ function activateKeybindChange(element: HTMLElement) {
element.querySelector(".option-hidden-section").classList.remove("hidden");
document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true});
document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true});
}
/**
@@ -303,25 +331,60 @@ function activateKeybindChange(element: HTMLElement) {
function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) {
var key = e.key;
let button = element.querySelector(".trigger-button");
if (["Shift", "Control", "Meta", "Alt", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Tab"].indexOf(key) !== -1) {
// Wait for more
document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true});
} else {
let button: HTMLElement = element.querySelector(".trigger-button");
let option = element.getAttribute("sync-option");
// Don't allow keys which are already listened for by youtube
let restrictedKeys = "1234567890,.jklftcibmJKLFTCIBMNP/<> -+";
if (restrictedKeys.indexOf(key) !== -1 ) {
closeKeybindOption(element, button);
alert(chrome.i18n.getMessage("theKey") + " " + key + " " + chrome.i18n.getMessage("keyAlreadyUsedByYouTube"));
return;
}
// Make sure keybind isn't used by the other listener
// TODO: If other keybindings are going to be added, we need a better way to find the other keys used.
let otherKeybind = (option === "startSponsorKeybind") ? Config.config['submitKeybind'] : Config.config['startSponsorKeybind'];
if (key === otherKeybind) {
closeKeybindOption(element, button);
alert(chrome.i18n.getMessage("theKey") + " " + key + " " + chrome.i18n.getMessage("keyAlreadyUsed"));
return;
}
// cancel setting a keybind
if (key === "Escape") {
closeKeybindOption(element, button);
return;
}
Config.config[option] = key;
let status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete");
let statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = key;
// cancel setting a keybind
if (key === "Escape") {
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
return;
}
}
let option = element.getAttribute("sync-option");
Config.config[option] = key;
let status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete");
let statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = key;
/**
* Closes the menu for editing the keybind
*
* @param element
* @param button
*/
function closeKeybindOption(element: HTMLElement, button: HTMLElement) {
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
}
@@ -345,15 +408,57 @@ function activatePrivateTextChange(element: HTMLElement) {
element.querySelector(".option-hidden-section").classList.remove("hidden");
return;
}
textBox.value = Config.config[option];
let result = Config.config[option];
// See if anything extra must be done
switch (option) {
case "*":
let jsonData = JSON.parse(JSON.stringify(Config.localConfig));
// Fix sponsorTimes data as it is destroyed from the JSON stringify
jsonData.sponsorTimes = Config.encodeStoredItem(Config.localConfig.sponsorTimes);
result = JSON.stringify(jsonData);
break;
}
textBox.value = result;
let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", () => {
let confirmMessage = element.getAttribute("confirm-message");
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
Config.config[option] = textBox.value;
// See if anything extra must be done
switch (option) {
case "*":
try {
let newConfig = JSON.parse(textBox.value);
for (const key in newConfig) {
Config.config[key] = newConfig[key];
}
Config.convertJSON();
// Reload options on page
init();
if (newConfig.supportInvidious) {
let checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input");
checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious");
}
} catch (e) {
alert(chrome.i18n.getMessage("incorrectlyFormattedOptions"));
}
break;
default:
Config.config[option] = textBox.value;
}
}
});
@@ -381,4 +486,36 @@ function validateServerAddress(input: string): string {
}
return input;
}
function copyDebugOutputToClipboard() {
// Build output debug information object
let output = {
debug: {
userAgent: navigator.userAgent,
platform: navigator.platform,
language: navigator.language,
extensionVersion: chrome.runtime.getManifest().version
},
config: JSON.parse(JSON.stringify(Config.localConfig)) // Deep clone config object
};
// Fix sponsorTimes data as it is destroyed from the JSON stringify
output.config.sponsorTimes = Config.encodeStoredItem(Config.localConfig.sponsorTimes);
// Sanitise sensitive user config values
delete output.config.userID;
output.config.serverAddress = (output.config.serverAddress === CompileConfig.serverAddress)
? "Default server address" : "Custom server address";
output.config.invidiousInstances = output.config.invidiousInstances.length;
output.config.whitelistedChannels = output.config.whitelistedChannels.length;
// Copy object to clipboard
navigator.clipboard.writeText(JSON.stringify(output, null, 4))
.then(() => {
alert(chrome.i18n.getMessage("copyDebugInformationComplete"));
})
.catch(err => {
alert(chrome.i18n.getMessage("copyDebugInformationFailed"));
});;
}

View File

@@ -157,7 +157,7 @@ async function runThePopup(messageListener?: MessageListener) {
//get the amount of times this user has contributed and display it to thank them
if (Config.config.sponsorTimesContributed != undefined) {
if (Config.config.sponsorTimesContributed > 1) {
if (Config.config.sponsorTimesContributed !== 1) {
PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else {
PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor");

View File

@@ -42,7 +42,8 @@ module.exports = env => ({
),
new BuildManifest({
browser: env.browser,
pretty: env.mode === "production"
pretty: env.mode === "production",
stream: env.stream
})
]
});

View File

@@ -8,6 +8,8 @@ const fs = require('fs');
const manifest = require("../manifest/manifest.json");
const firefoxManifestExtra = require("../manifest/firefox-manifest-extra.json");
const chromeManifestExtra = require("../manifest/chrome-manifest-extra.json");
const betaManifestExtra = require("../manifest/beta-manifest-extra.json");
const firefoxBetaManifestExtra = require("../manifest/firefox-beta-manifest-extra.json");
// schema for options object
const schema = {
@@ -18,6 +20,9 @@ const schema = {
},
pretty: {
type: 'boolean'
},
steam: {
type: 'string'
}
}
};
@@ -40,6 +45,14 @@ class BuildManifest {
mergeObjects(manifest, chromeManifestExtra);
}
if (this.options.stream === "beta") {
mergeObjects(manifest, betaManifestExtra);
if (this.options.browser.toLowerCase() === "firefox") {
mergeObjects(manifest, firefoxBetaManifestExtra);
}
}
let result = JSON.stringify(manifest);
if (this.options.pretty) result = JSON.stringify(manifest, null, 2);