SponsorBlock (#1130)
* SponsorBlock: enable/url settings * SponsorBlock: fetch and display skipped fragments * SponsorBlock: skip sponsor blocks * npm add node-forge * SponsorBlock: use hash prefix API * SponsorBlock: configurable toast on skipped segment * SponsorBlock: add /api/ to url, remove trailing slash
This commit is contained in:
parent
1096310c9b
commit
440b04bbf0
|
@ -13739,8 +13739,7 @@
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||||
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
|
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node-gyp": {
|
"node-gyp": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"markdown": "^0.5.0",
|
"markdown": "^0.5.0",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
"nedb": "^1.8.0",
|
"nedb": "^1.8.0",
|
||||||
|
"node-forge": "^0.10.0",
|
||||||
"opml-to-json": "^1.0.1",
|
"opml-to-json": "^1.0.1",
|
||||||
"rss-parser": "^3.12.0",
|
"rss-parser": "^3.12.0",
|
||||||
"socks-proxy-agent": "^5.0.0",
|
"socks-proxy-agent": "^5.0.0",
|
||||||
|
|
|
@ -66,6 +66,10 @@ export default Vue.extend({
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
videoId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
|
@ -149,6 +153,14 @@ export default Vue.extend({
|
||||||
|
|
||||||
autoplayVideos: function () {
|
autoplayVideos: function () {
|
||||||
return this.$store.getters.getAutoplayVideos
|
return this.$store.getters.getAutoplayVideos
|
||||||
|
},
|
||||||
|
|
||||||
|
useSponsorBlock: function () {
|
||||||
|
return this.$store.getters.getUseSponsorBlock
|
||||||
|
},
|
||||||
|
|
||||||
|
sponsorBlockShowSkippedToast: function () {
|
||||||
|
return this.$store.getters.getSponsorBlockShowSkippedToast
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
|
@ -274,6 +286,109 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
setTimeout(() => { this.fetchSponsorBlockInfo() }, 100)
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchSponsorBlockInfo() {
|
||||||
|
if (this.useSponsorBlock) {
|
||||||
|
this.$store.dispatch('sponsorBlockSkipSegments', {
|
||||||
|
videoId: this.videoId,
|
||||||
|
categories: ['sponsor']
|
||||||
|
}).then((skipSegments) => {
|
||||||
|
this.player.on('timeupdate', () => {
|
||||||
|
this.skipSponsorBlocks(skipSegments)
|
||||||
|
})
|
||||||
|
skipSegments.forEach(({
|
||||||
|
category,
|
||||||
|
segment: [startTime, endTime]
|
||||||
|
}) => {
|
||||||
|
this.addSponsorBlockMarker({
|
||||||
|
time: startTime,
|
||||||
|
duration: endTime - startTime,
|
||||||
|
color: this.sponsorBlockCategoryColor(category)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
skipSponsorBlocks(skipSegments) {
|
||||||
|
const currentTime = this.player.currentTime()
|
||||||
|
let newTime = null
|
||||||
|
let skippedCategory = null
|
||||||
|
skipSegments.forEach(({ category, segment: [startTime, endTime] }) => {
|
||||||
|
if (startTime <= currentTime && currentTime < endTime) {
|
||||||
|
newTime = endTime
|
||||||
|
skippedCategory = category
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (newTime !== null) {
|
||||||
|
if (this.sponsorBlockShowSkippedToast) {
|
||||||
|
this.showSkippedSponsorSegmentInformation(skippedCategory)
|
||||||
|
}
|
||||||
|
this.player.currentTime(newTime)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showSkippedSponsorSegmentInformation(category) {
|
||||||
|
const translatedCategory = this.sponsorBlockTranslatedCategory(category)
|
||||||
|
this.showToast({
|
||||||
|
message: `${this.$t('Video.Skipped segment')} ${translatedCategory}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
sponsorBlockTranslatedCategory(category) {
|
||||||
|
switch (category) {
|
||||||
|
case 'sponsor':
|
||||||
|
return this.$t('Video.Sponsor Block category.sponsor')
|
||||||
|
case 'intro':
|
||||||
|
return this.$t('Video.Sponsor Block category.intro')
|
||||||
|
case 'outro':
|
||||||
|
return this.$t('Video.Sponsor Block category.outro')
|
||||||
|
case 'selfpromo':
|
||||||
|
return this.$t('Video.Sponsor Block category.self-promotion')
|
||||||
|
case 'interaction':
|
||||||
|
return this.$t('Video.Sponsor Block category.interaction')
|
||||||
|
case 'music_offtopic':
|
||||||
|
return this.$t('Video.Sponsor Block category.music offtopic')
|
||||||
|
default:
|
||||||
|
console.error(`Unknown translation for SponsorBlock category ${category}`)
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
sponsorBlockCategoryColor(category) {
|
||||||
|
// TODO: allow to set these colors in settings
|
||||||
|
switch (category) {
|
||||||
|
case 'sponsor':
|
||||||
|
return '#00d400'
|
||||||
|
case 'intro':
|
||||||
|
return '#00ffff'
|
||||||
|
case 'outro':
|
||||||
|
return '#0202ed'
|
||||||
|
case 'selfpromo':
|
||||||
|
return '#ffff00'
|
||||||
|
case 'interaction':
|
||||||
|
return '#cc00ff'
|
||||||
|
case 'music_offtopic':
|
||||||
|
return '#ff9900'
|
||||||
|
default:
|
||||||
|
console.error(`Unknown SponsorBlock category ${category}`)
|
||||||
|
return 'yellow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addSponsorBlockMarker(marker) {
|
||||||
|
const markerDiv = videojs.dom.createEl('div', {}, {})
|
||||||
|
|
||||||
|
markerDiv.className = 'sponsorBlockMarker'
|
||||||
|
markerDiv.style.height = '100%'
|
||||||
|
markerDiv.style.position = 'absolute'
|
||||||
|
markerDiv.style['background-color'] = marker.color
|
||||||
|
markerDiv.style.width = (marker.duration / this.player.duration()) * 100 + '%'
|
||||||
|
markerDiv.style.marginLeft = (marker.time / this.player.duration()) * 100 + '%'
|
||||||
|
|
||||||
|
this.player.el().querySelector('.vjs-progress-holder').appendChild(markerDiv)
|
||||||
},
|
},
|
||||||
|
|
||||||
checkAspectRatio() {
|
checkAspectRatio() {
|
||||||
|
@ -1186,6 +1301,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
...mapActions([
|
...mapActions([
|
||||||
|
'showToast',
|
||||||
'calculateColorLuminance'
|
'calculateColorLuminance'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 85%;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 680px) {
|
||||||
|
.card {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 500px) {
|
||||||
|
.sponsorBlockSettingsFlexBox {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
|
import FtCard from '../ft-card/ft-card.vue'
|
||||||
|
import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
|
||||||
|
import FtInput from '../ft-input/ft-input.vue'
|
||||||
|
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
name: 'SponsorBlockSettings',
|
||||||
|
components: {
|
||||||
|
'ft-card': FtCard,
|
||||||
|
'ft-toggle-switch': FtToggleSwitch,
|
||||||
|
'ft-input': FtInput,
|
||||||
|
'ft-flex-box': FtFlexBox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
useSponsorBlock: function () {
|
||||||
|
return this.$store.getters.getUseSponsorBlock
|
||||||
|
},
|
||||||
|
sponsorBlockUrl: function () {
|
||||||
|
return this.$store.getters.getSponsorBlockUrl
|
||||||
|
},
|
||||||
|
sponsorBlockShowSkippedToast: function () {
|
||||||
|
return this.$store.getters.getSponsorBlockShowSkippedToast
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleUpdateSponsorBlock: function (value) {
|
||||||
|
this.updateUseSponsorBlock(value)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUpdateSponsorBlockUrl: function (value) {
|
||||||
|
const sponsorBlockUrlWithoutTrailingSlash = value.replace(/\/$/, '')
|
||||||
|
const sponsorBlockUrlWithoutApiSuffix = sponsorBlockUrlWithoutTrailingSlash.replace(/\/api$/, '')
|
||||||
|
this.updateSponsorBlockUrl(sponsorBlockUrlWithoutApiSuffix)
|
||||||
|
},
|
||||||
|
|
||||||
|
handleUpdateSponsorBlockShowSkippedToast: function (value) {
|
||||||
|
this.updateSponsorBlockShowSkippedToast(value)
|
||||||
|
},
|
||||||
|
|
||||||
|
...mapActions([
|
||||||
|
'updateUseSponsorBlock',
|
||||||
|
'updateSponsorBlockUrl',
|
||||||
|
'updateSponsorBlockShowSkippedToast'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<ft-card
|
||||||
|
class="relative card"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="videoTitle"
|
||||||
|
>
|
||||||
|
{{ $t("Settings.SponsorBlock Settings.SponsorBlock Settings") }}
|
||||||
|
</h3>
|
||||||
|
<ft-flex-box class="sponsorBlockSettingsFlexBox">
|
||||||
|
<ft-toggle-switch
|
||||||
|
:label="$t('Settings.SponsorBlock Settings.Enable SponsorBlock')"
|
||||||
|
:default-value="useSponsorBlock"
|
||||||
|
@change="handleUpdateSponsorBlock"
|
||||||
|
/>
|
||||||
|
</ft-flex-box>
|
||||||
|
<ft-flex-box class="sponsorBlockSettingsFlexBox">
|
||||||
|
<ft-toggle-switch
|
||||||
|
:label="$t('Settings.SponsorBlock Settings.Notify when sponsor segment is skipped')"
|
||||||
|
:default-value="sponsorBlockShowSkippedToast"
|
||||||
|
@change="handleUpdateSponsorBlockShowSkippedToast"
|
||||||
|
/>
|
||||||
|
</ft-flex-box>
|
||||||
|
<ft-flex-box>
|
||||||
|
<ft-input
|
||||||
|
:placeholder="$t('Settings.SponsorBlock Settings[\'SponsorBlock API Url (Default is https://sponsor.ajay.app)\']')"
|
||||||
|
:show-arrow="false"
|
||||||
|
:show-label="true"
|
||||||
|
:value="sponsorBlockUrl"
|
||||||
|
@input="handleUpdateSponsorBlockUrl"
|
||||||
|
/>
|
||||||
|
</ft-flex-box>
|
||||||
|
</ft-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./sponsor-block-settings.js" />
|
||||||
|
<style scoped src="./sponsor-block-settings.css" />
|
|
@ -78,7 +78,10 @@ const state = {
|
||||||
hidePopularVideos: false,
|
hidePopularVideos: false,
|
||||||
hidePlaylists: false,
|
hidePlaylists: false,
|
||||||
hideLiveChat: false,
|
hideLiveChat: false,
|
||||||
hideActiveSubscriptions: false
|
hideActiveSubscriptions: false,
|
||||||
|
useSponsorBlock: false,
|
||||||
|
sponsorBlockUrl: 'https://sponsor.ajay.app',
|
||||||
|
sponsorBlockShowSkippedToast: true
|
||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
|
@ -264,6 +267,18 @@ const getters = {
|
||||||
|
|
||||||
getHideActiveSubscriptions: () => {
|
getHideActiveSubscriptions: () => {
|
||||||
return state.hideActiveSubscriptions
|
return state.hideActiveSubscriptions
|
||||||
|
},
|
||||||
|
|
||||||
|
getUseSponsorBlock: () => {
|
||||||
|
return state.useSponsorBlock
|
||||||
|
},
|
||||||
|
|
||||||
|
getSponsorBlockUrl: () => {
|
||||||
|
return state.sponsorBlockUrl
|
||||||
|
},
|
||||||
|
|
||||||
|
getSponsorBlockShowSkippedToast: () => {
|
||||||
|
return state.sponsorBlockShowSkippedToast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,6 +432,14 @@ const actions = {
|
||||||
case 'hideActiveSubscriptions':
|
case 'hideActiveSubscriptions':
|
||||||
commit('setHideActiveSubscriptions', result.value)
|
commit('setHideActiveSubscriptions', result.value)
|
||||||
break
|
break
|
||||||
|
case 'useSponsorBlock':
|
||||||
|
commit('setUseSponsorBlock', result.value)
|
||||||
|
break
|
||||||
|
case 'sponsorBlockUrl':
|
||||||
|
commit('setSponsorBlockUrl', result.value)
|
||||||
|
break
|
||||||
|
case 'sponsorBlockShowSkippedToast':
|
||||||
|
commit('setSponsorBlockShowSkippedToast', result.value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
resolve()
|
resolve()
|
||||||
|
@ -786,6 +809,30 @@ const actions = {
|
||||||
commit('setHideLiveChat', hideLiveChat)
|
commit('setHideLiveChat', hideLiveChat)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateUseSponsorBlock ({ commit }, useSponsorBlock) {
|
||||||
|
settingsDb.update({ _id: 'useSponsorBlock' }, { _id: 'useSponsorBlock', value: useSponsorBlock }, { upsert: true }, (err, numReplaced) => {
|
||||||
|
if (!err) {
|
||||||
|
commit('setUseSponsorBlock', useSponsorBlock)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSponsorBlockUrl ({ commit }, sponsorBlockUrl) {
|
||||||
|
settingsDb.update({ _id: 'sponsorBlockUrl' }, { _id: 'sponsorBlockUrl', value: sponsorBlockUrl }, { upsert: true }, (err, numReplaced) => {
|
||||||
|
if (!err) {
|
||||||
|
commit('setSponsorBlockUrl', sponsorBlockUrl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSponsorBlockShowSkippedToast ({ commit }, sponsorBlockShowSkippedToast) {
|
||||||
|
settingsDb.update({ _id: 'sponsorBlockShowSkippedToast' }, { _id: 'sponsorBlockShowSkippedToast', value: sponsorBlockShowSkippedToast }, { upsert: true }, (err, numReplaced) => {
|
||||||
|
if (!err) {
|
||||||
|
commit('setSponsorBlockShowSkippedToast', sponsorBlockShowSkippedToast)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,6 +991,15 @@ const mutations = {
|
||||||
},
|
},
|
||||||
setHideActiveSubscriptions (state, hideActiveSubscriptions) {
|
setHideActiveSubscriptions (state, hideActiveSubscriptions) {
|
||||||
state.hideActiveSubscriptions = hideActiveSubscriptions
|
state.hideActiveSubscriptions = hideActiveSubscriptions
|
||||||
|
},
|
||||||
|
setUseSponsorBlock (state, useSponsorBlock) {
|
||||||
|
state.useSponsorBlock = useSponsorBlock
|
||||||
|
},
|
||||||
|
setSponsorBlockUrl (state, sponsorBlockUrl) {
|
||||||
|
state.sponsorBlockUrl = sponsorBlockUrl
|
||||||
|
},
|
||||||
|
setSponsorBlockShowSkippedToast (state, sponsorBlockShowSkippedToast) {
|
||||||
|
state.sponsorBlockShowSkippedToast = sponsorBlockShowSkippedToast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import $ from 'jquery'
|
||||||
|
import forge from 'node-forge'
|
||||||
|
|
||||||
|
const state = {}
|
||||||
|
const getters = {}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
sponsorBlockSkipSegments ({ rootState }, { videoId, categories }) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const messageDigestSha256 = forge.md.sha256.create()
|
||||||
|
messageDigestSha256.update(videoId)
|
||||||
|
const videoIdHashPrefix = messageDigestSha256.digest().toHex().substring(0, 4)
|
||||||
|
const requestUrl = `${rootState.settings.sponsorBlockUrl}/api/skipSegments/${videoIdHashPrefix}?categories=${JSON.stringify(categories)}`
|
||||||
|
|
||||||
|
$.getJSON(requestUrl, (response) => {
|
||||||
|
const segments = response
|
||||||
|
.filter((result) => result.videoID === videoId)
|
||||||
|
.flatMap((result) => result.segments)
|
||||||
|
resolve(segments)
|
||||||
|
}).fail((xhr, textStatus, error) => {
|
||||||
|
console.log(xhr)
|
||||||
|
console.log(textStatus)
|
||||||
|
console.log(requestUrl)
|
||||||
|
console.log(error)
|
||||||
|
reject(xhr)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mutations = {}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
state,
|
||||||
|
getters,
|
||||||
|
actions,
|
||||||
|
mutations
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import PrivacySettings from '../../components/privacy-settings/privacy-settings.
|
||||||
import DataSettings from '../../components/data-settings/data-settings.vue'
|
import DataSettings from '../../components/data-settings/data-settings.vue'
|
||||||
import DistractionSettings from '../../components/distraction-settings/distraction-settings.vue'
|
import DistractionSettings from '../../components/distraction-settings/distraction-settings.vue'
|
||||||
import ProxySettings from '../../components/proxy-settings/proxy-settings.vue'
|
import ProxySettings from '../../components/proxy-settings/proxy-settings.vue'
|
||||||
|
import SponsorBlockSettings from '../../components/sponsor-block-settings/sponsor-block-settings.vue'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
|
@ -22,6 +23,7 @@ export default Vue.extend({
|
||||||
'privacy-settings': PrivacySettings,
|
'privacy-settings': PrivacySettings,
|
||||||
'data-settings': DataSettings,
|
'data-settings': DataSettings,
|
||||||
'distraction-settings': DistractionSettings,
|
'distraction-settings': DistractionSettings,
|
||||||
'proxy-settings': ProxySettings
|
'proxy-settings': ProxySettings,
|
||||||
|
'sponsor-block-settings': SponsorBlockSettings
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<privacy-settings />
|
<privacy-settings />
|
||||||
<data-settings />
|
<data-settings />
|
||||||
<proxy-settings />
|
<proxy-settings />
|
||||||
|
<sponsor-block-settings />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
:storyboard-src="videoStoryboardSrc"
|
:storyboard-src="videoStoryboardSrc"
|
||||||
:format="activeFormat"
|
:format="activeFormat"
|
||||||
:thumbnail="thumbnail"
|
:thumbnail="thumbnail"
|
||||||
|
:video-id="videoId"
|
||||||
class="videoPlayer"
|
class="videoPlayer"
|
||||||
:class="{ theatrePlayer: useTheatreMode }"
|
:class="{ theatrePlayer: useTheatreMode }"
|
||||||
@ready="checkIfWatched"
|
@ready="checkIfWatched"
|
||||||
|
|
|
@ -280,6 +280,11 @@ Settings:
|
||||||
Region: Region
|
Region: Region
|
||||||
City: City
|
City: City
|
||||||
Error getting network information. Is your proxy configured properly?: Error getting network information. Is your proxy configured properly?
|
Error getting network information. Is your proxy configured properly?: Error getting network information. Is your proxy configured properly?
|
||||||
|
SponsorBlock Settings:
|
||||||
|
SponsorBlock Settings: SponsorBlock Settings
|
||||||
|
Enable SponsorBlock: Enable SponsorBlock
|
||||||
|
'SponsorBlock API Url (Default is https://sponsor.ajay.app)': SponsorBlock API Url (Default is https://sponsor.ajay.app)
|
||||||
|
Notify when sponsor segment is skipped: Notify when sponsor segment is skipped
|
||||||
About:
|
About:
|
||||||
#On About page
|
#On About page
|
||||||
About: About
|
About: About
|
||||||
|
@ -472,6 +477,14 @@ Video:
|
||||||
translated from English: translated from English
|
translated from English: translated from English
|
||||||
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
||||||
Publicationtemplate: $ % ago
|
Publicationtemplate: $ % ago
|
||||||
|
Skipped segment: Skipped segment
|
||||||
|
Sponsor Block category:
|
||||||
|
sponsor: sponsor
|
||||||
|
intro: intro
|
||||||
|
outro: outro
|
||||||
|
self-promotion: self-promotion
|
||||||
|
interaction: interaction
|
||||||
|
music offtopic: music offtopic
|
||||||
#& Videos
|
#& Videos
|
||||||
Videos:
|
Videos:
|
||||||
#& Sort By
|
#& Sort By
|
||||||
|
|
Loading…
Reference in New Issue