Merge pull request #32 from zrose584/add_sponsorblock

add sponsorblock.js
This commit is contained in:
James Taylor 2020-10-21 18:53:34 -07:00 committed by GitHub
commit 8b54a5f3aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 68 additions and 8 deletions

View File

@ -41,6 +41,7 @@ The Youtube API is not used, so no keys or anything are needed. It uses the same
1. Shown by default, with click to hide
2. Hidden by default, with click to show
3. Never shown
* Optionally skip sponsored segments using [SponsorBlock](https://github.com/ajayyy/SponsorBlock)'s API
## Planned features
- [ ] Putting videos from subscriptions or local playlists into the related videos

View File

@ -85,6 +85,7 @@ site_handlers = {
'ytimg.com': proxy_site,
'yt3.ggpht.com': proxy_site,
'lh3.googleusercontent.com': proxy_site,
'sponsor.ajay.app': proxy_site,
'googlevideo.com': proxy_video,
}

View File

@ -142,6 +142,13 @@ For security reasons, enabling this is not recommended.''',
'comment': '',
}),
('use_sponsorblock_js', {
'label': 'Enable sponsorblock.js',
'type': bool,
'default': False,
'comment': '',
}),
('theme', {
'type': int,
'default': 0,

View File

@ -8,6 +8,10 @@ from sys import exc_info
yt_app = flask.Flask(__name__)
yt_app.config['TEMPLATES_AUTO_RELOAD'] = True
yt_app.url_map.strict_slashes = False
# yt_app.jinja_env.trim_blocks = True
# yt_app.jinja_env.lstrip_blocks = True
yt_app.add_url_rule('/settings', 'settings_page', settings.settings_page, methods=['POST', 'GET'])

View File

@ -37,9 +37,8 @@ function onKeyDown(e) {
else tt.mode = "showing";
}
else if (c == "t") {
let video_id = JSON.parse(Q(".video-info input[name=video_info_list]").value).id
let ts = Math.floor(Q("video").currentTime);
copyTextToClipboard(`https://youtu.be/${video_id}?t=${ts}`);
copyTextToClipboard(`https://youtu.be/${data.video_id}?t=${ts}`);
}
}

View File

@ -0,0 +1,40 @@
"use strict";
// from: https://git.gir.st/subscriptionfeed.git/blob/59a590d:/app/youtube/templates/watch.html.j2#l28
var sha256=function a(b){function c(a,b){return a>>>b|a<<32-b}for(var d,e,f=Math.pow,g=f(2,32),h="length",i="",j=[],k=8*b[h],l=a.h=a.h||[],m=a.k=a.k||[],n=m[h],o={},p=2;64>n;p++)if(!o[p]){for(d=0;313>d;d+=p)o[d]=p;l[n]=f(p,.5)*g|0,m[n++]=f(p,1/3)*g|0}for(b+="\x80";b[h]%64-56;)b+="\x00";for(d=0;d<b[h];d++){if(e=b.charCodeAt(d),e>>8)return;j[d>>2]|=e<<(3-d)%4*8}for(j[j[h]]=k/g|0,j[j[h]]=k,e=0;e<j[h];){var q=j.slice(e,e+=16),r=l;for(l=l.slice(0,8),d=0;64>d;d++){var s=q[d-15],t=q[d-2],u=l[0],v=l[4],w=l[7]+(c(v,6)^c(v,11)^c(v,25))+(v&l[5]^~v&l[6])+m[d]+(q[d]=16>d?q[d]:q[d-16]+(c(s,7)^c(s,18)^s>>>3)+q[d-7]+(c(t,17)^c(t,19)^t>>>10)|0),x=(c(u,2)^c(u,13)^c(u,22))+(u&l[1]^u&l[2]^l[1]&l[2]);l=[w+x|0].concat(l),l[4]=l[4]+w|0}for(d=0;8>d;d++)l[d]=l[d]+r[d]|0}for(d=0;8>d;d++)for(e=3;e+1;e--){var y=l[d]>>8*e&255;i+=(16>y?0:"")+y.toString(16)}return i}; /*https://geraintluff.github.io/sha256/sha256.min.js (public domain)*/
window.addEventListener("load", load_sponsorblock);
document.addEventListener('DOMContentLoaded', ()=>{
const check = document.querySelector("#skip_sponsors");
check.addEventListener("change", () => {if (check.checked) load_sponsorblock()});
});
function load_sponsorblock(){
const info_elem = Q('#skip_n');
if (info_elem.innerText.length) return; // already fetched
const hash = sha256(data.video_id).substr(0,4);
const video_obj = Q("video");
let url = `/https://sponsor.ajay.app/api/skipSegments/${hash}`;
fetch(url)
.then(response => response.json())
.then(r => {
for (const video of r) {
if (video.videoID != data.video_id) continue;
info_elem.innerText = `(${video.segments.length} segments)`;
const cat_n = video.segments.map(e=>e.category).sort()
.reduce((acc,e) => (acc[e]=(acc[e]||0)+1, acc), {});
info_elem.title = Object.entries(cat_n).map(e=>e.join(': ')).join(', ');
for (const segment of video.segments) {
const [start, stop] = segment.segment;
if (segment.category != "sponsor") continue;
video_obj.addEventListener("timeupdate", function() {
if (Q("#skip_sponsors").checked &&
this.currentTime >= start &&
this.currentTime < stop-1) {
this.currentTime = stop;
}
});
}
}
});
}

View File

@ -482,6 +482,12 @@ Reload without invidious (for usage of new identity button).</a>
<p>Used Invidious as fallback.</p>
{% endif %}
<p class="allowed-countries">Allowed countries: {{ allowed_countries|join(', ') }}</p>
{% if settings.use_sponsorblock_js %}
<ul class="more-actions">
<li><label><input type=checkbox id=skip_sponsors checked>skip sponsors</label> <span id=skip_n></span>
</ul>
{% endif %}
</div>
</details>
</div>
@ -677,12 +683,10 @@ Reload without invidious (for usage of new identity button).</a>
{% endif %}
{% endif %}
<script> data = {{ js_data|tojson }} </script>
<script src="/youtube.com/static/js/common.js"></script>
<script src="/youtube.com/static/js/transcript-table.js"></script>
{% if settings.use_video_hotkeys %}
<script src="/youtube.com/static/js/hotkeys.js"></script>
{% endif %}
{% if settings.use_comments_js %}
<script src="/youtube.com/static/js/comments.js"></script>
{% endif %}
{% if settings.use_video_hotkeys %} <script src="/youtube.com/static/js/hotkeys.js"></script> {% endif %}
{% if settings.use_comments_js %} <script src="/youtube.com/static/js/comments.js"></script> {% endif %}
{% if settings.use_sponsorblock_js %} <script src="/youtube.com/static/js/sponsorblock.js"></script> {% endif %}
{% endblock main %}

View File

@ -493,6 +493,10 @@ def get_watch_page(video_id=None):
invidious_reload_button = info['invidious_reload_button'],
video_url = util.URL_ORIGIN + '/watch?v=' + video_id,
time_start = time_start,
js_data = {
'video_id': video_info['id'],
}
)