aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Taylor <28744867+user234683@users.noreply.github.com>2020-10-21 18:53:34 -0700
committerGitHub <noreply@github.com>2020-10-21 18:53:34 -0700
commit8b54a5f3aa376651bf063baa6893fe9b7f0e2ca0 (patch)
tree6bff6ae507db03e435bb04e3969ef08093f3f8d8
parentf01ef36a37c9112eca3f85d49622c41d68000a69 (diff)
parentaa52c7a42e9573105dfadb07981c7f5f1447ca9d (diff)
downloadyt-local-8b54a5f3aa376651bf063baa6893fe9b7f0e2ca0.tar.lz
yt-local-8b54a5f3aa376651bf063baa6893fe9b7f0e2ca0.tar.xz
yt-local-8b54a5f3aa376651bf063baa6893fe9b7f0e2ca0.zip
Merge pull request #32 from zrose584/add_sponsorblock
add sponsorblock.js
-rw-r--r--README.md1
-rw-r--r--server.py1
-rw-r--r--settings.py7
-rw-r--r--youtube/__init__.py4
-rw-r--r--youtube/static/js/hotkeys.js3
-rw-r--r--youtube/static/js/sponsorblock.js40
-rw-r--r--youtube/templates/watch.html16
-rw-r--r--youtube/watch.py4
8 files changed, 68 insertions, 8 deletions
diff --git a/README.md b/README.md
index 2428ec6..17d92bd 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/server.py b/server.py
index 25d3990..319a140 100644
--- a/server.py
+++ b/server.py
@@ -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,
}
diff --git a/settings.py b/settings.py
index 159a896..e1cec13 100644
--- a/settings.py
+++ b/settings.py
@@ -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,
diff --git a/youtube/__init__.py b/youtube/__init__.py
index 61039d3..6d79e44 100644
--- a/youtube/__init__.py
+++ b/youtube/__init__.py
@@ -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'])
diff --git a/youtube/static/js/hotkeys.js b/youtube/static/js/hotkeys.js
index 5688ef3..e199f3b 100644
--- a/youtube/static/js/hotkeys.js
+++ b/youtube/static/js/hotkeys.js
@@ -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}`);
}
}
diff --git a/youtube/static/js/sponsorblock.js b/youtube/static/js/sponsorblock.js
new file mode 100644
index 0000000..dab4372
--- /dev/null
+++ b/youtube/static/js/sponsorblock.js
@@ -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;
+ }
+ });
+ }
+ }
+ });
+} \ No newline at end of file
diff --git a/youtube/templates/watch.html b/youtube/templates/watch.html
index 3542d94..b6faf21 100644
--- a/youtube/templates/watch.html
+++ b/youtube/templates/watch.html
@@ -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 %}
diff --git a/youtube/watch.py b/youtube/watch.py
index b1d4665..8ef9448 100644
--- a/youtube/watch.py
+++ b/youtube/watch.py
@@ -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'],
+ }
)