Skip to content

Instantly share code, notes, and snippets.

@MRuy
Last active May 4, 2023 09:45
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save MRuy/ca74d6a359c487d760f4a698e76fb0d6 to your computer and use it in GitHub Desktop.
Save MRuy/ca74d6a359c487d760f4a698e76fb0d6 to your computer and use it in GitHub Desktop.
Userscripts for sb.ltn.fi

Userscripts for sb.ltn.fi (by Nanobyte)

  • sb.ltn.fi.lastupdate.user.js
    Show the last update time on top center
  • sb.ltn.fi.similarsegments.user.js
    Color highlights segments that are similar on sb.ltn.fi (Only works on video page sorted by starttime)
  • sb.ltn.fi.coloredcategories.user.js
    Color highlights categories
  • sb.ltn.fi.clickablestarttime.user.js
    Makes the startTime clickable
  • SponsorBlock Paste YT-Link (sb.ltn.fi)
    Just paste the YT-Link into the videoID field
  • sb.ltn.fi index page Restoring functionality
// ==UserScript==
// @name SponsorBlock clickable startTime (sb.ltn.fi)
// @namespace sb.ltn.fi.clickable.starttime
// @version 1.0.6
// @description Makes the startTime clickable
// @author Nanobyte
// @match https://sb.ltn.fi/*
// @updateURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.clickablestarttime.user.js
// @downloadURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.clickablestarttime.user.js
// @grant none
// ==/UserScript==
let videoId = '';
const pathArr = window.location.pathname.split('/');
if (pathArr.length > 1) {
switch(pathArr[1]) {
case 'video':
{
const videoFolderIndex = pathArr.indexOf('video');
if (videoFolderIndex !== -1) {
videoId = pathArr[videoFolderIndex + 1];
}
}
break;
case 'uuid':
{
const elYtLink = document.querySelector('.list-group-item a[href*="youtube.com/watch"]');
if (elYtLink) {
const url = new URL(elYtLink.href);
if (url.searchParams.has('v')) {
videoId = url.searchParams.get('v');
}
}
}
break;
default:
{
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.has('v')) {
videoId = searchParams.get('v');
}
}
}
}
if (window.location.pathname.includes('/video/')) {
const folders = window.location.pathname.split('/');
const videoFolderIndex = folders.indexOf('video');
if (videoFolderIndex !== -1) {
videoId = folders[videoFolderIndex + 1];
}
}
else {
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.has('v')) {
videoId = searchParams.get('v');
}
}
(function() {
'use strict';
[...document.querySelectorAll('table')].forEach(table => {
const headers = [...table.querySelectorAll('thead th')].map(item => item.textContent.trim());
if (headers.includes('Start') && headers.includes('End')) {
const startColumnIndex = headers.indexOf('Start');
const videoIDColumnIndex = headers.indexOf('VideoID');
const uuidColumnIndex = headers.indexOf('UUID');
const rows = [...table.querySelectorAll('tbody tr')];
rows.forEach(row => {
const cellEl = row.children[startColumnIndex];
if (videoIDColumnIndex !== -1) {
videoId = row.children[videoIDColumnIndex].children[0].textContent.trim();
}
const UUID = row.children[uuidColumnIndex].querySelector('textarea').value;
let content = cellEl.textContent.trim();
const link = document.createElement('a');
let startTimeSeconds = content.split('.')[0].split(':').map(s=>Number(s)).reverse().map((val,index) => {
return [1, 60, 3600][index] * val;
}).reduce((acc, curr)=>acc+curr, 0);
link.textContent = content;
link.style.color = 'inherit';
const seekTime = Math.max(0, startTimeSeconds - 2);
link.href = `https://www.youtube.com/watch?v=${videoId}${seekTime===0?'':'&t='+seekTime+'s'}#requiredSegment=${UUID}`;
cellEl.innerHTML = '';
cellEl.appendChild(link);
});
}
});
})();
function wrapElement(target, el) {
el.innerHTML = target.innerHTML;
target.innerHTML = el.innerHTML
}
// ==UserScript==
// @name SponsorBlock colored categories (sb.ltn.fi)
// @namespace sb.ltn.fi.sponsorblock.colored.categories
// @version 1.2.0
// @description Color highlights categories
// @author Nanobyte
// @match https://sb.ltn.fi/*
// @updateURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.coloredcategories.user.js
// @downloadURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.coloredcategories.user.js
// @grant GM_addStyle
// ==/UserScript==
const CATEGORIES = 'sponsor,intro,outro,interaction,selfpromo,music_offtopic,preview,poi_highlight,filler,exclusive_access,chapter'.split(',');
const COLORS = '#00d400,#00ffff,#0202ed,#cc00ff,#ffff00,#ff9900,#008fd6,#ff1684,#7300ff,#008a5c,#ffd679'.split(',');
const COLOR_LEN = COLORS.length;
let cssStyle = '.mruy_sbcc{padding:1px 4px;color:#000;display:inline-block;width:100%;border-radius:4px;}';
for (let i=0; i<COLOR_LEN; i++) {
const color = COLORS[i];
const category = CATEGORIES[i];
cssStyle += `.mruy_sbcc_${category}{background-color:${color};}`;
}
GM_addStyle(cssStyle);
(function() {
'use strict';
[...document.querySelectorAll('table')].forEach(table => {
const headers = [...table.querySelectorAll('thead th')].map(item => item.textContent.trim());
if (headers.includes('Start') && headers.includes('End')) {
const columnIndex = headers.indexOf('Category');
const rows = [...table.querySelectorAll('tbody tr')];
rows.forEach(row => {
const categoryEl = row.children[columnIndex];
const category = categoryEl.textContent.trim();
const colorIndex = CATEGORIES.indexOf(category);
if (colorIndex !== -1) {
wrapElementWithColor(categoryEl, category);
}
});
}
});
})();
function wrapElementWithColor(el, category) {
el.innerHTML = `<span class="mruy_sbcc mruy_sbcc_${category}">${el.innerHTML}</span>`;
}
// ==UserScript==
// @name SponsorBlock last update (sb.ltn.fi)
// @namespace sponsorblock.sbltnfi.lastupdate
// @version 1.0.0
// @description Show the last update time on top center
// @author Nanobyte
// @match https://sb.ltn.fi/*
// @updateURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.lastupdate.user.js
// @downloadURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.lastupdate.user.js
// @grant none
// ==/UserScript==
let date, updateTimeEl;
const rtf = new Intl.RelativeTimeFormat('en', { style: 'long' });
(function() {
'use strict';
const col = document.querySelector('.container-fluid .row:last-child .col:first-child');
const str = col.textContent.trim();
if (str.includes('Last update:') && str.includes('All times UTC')) {
const dateStr = str.split('Last update:')[1].split('All times UTC')[0].trim();
let [_, year, month, day, hour, minute, second] = dateStr.match(/(\d+)\-(\d+)\-(\d+)\s(\d+)\:(\d+)\:(\d+)/);
date = Date.UTC(year, Number(month) - 1, day, hour, minute, second);
const div = document.createElement('div');
div.style.position = 'fixed';
div.style.left = '50%';
div.style.top = '0';
div.style.padding = '4px 8px';
div.style.transform = 'translateX(-50%)';
div.style.color = 'white';
div.style.font = 'normal 16px sans-serif';
div.style.textShadow = '0 0 6px black';
div.textContent = `...`;
document.body.appendChild(div);
updateTimeEl = div;
updateTime();
setInterval(updateTime, 1000);
}
})();
function updateTime() {
const now = Date.now();
const diffMs = now - date;
const diffSeconds = Math.round(diffMs / 1000);
let updatedText = '';
if (diffSeconds < 60) {
updatedText = rtf.format(-diffSeconds, 'second');
} else {
const diffMinutes = Math.round(diffSeconds / 60);
updatedText = rtf.format(-diffMinutes, 'minute');
}
updateTimeEl.textContent = `Last update: ${updatedText}`;
}
// ==UserScript==
// @name SponsorBlock similar segments (sb.ltn.fi)
// @namespace sb.ltn.fi.sponsorblock.similar.segments
// @version 1.1.0
// @description Color highlights segments that are similar on sb.ltn.fi (Only works on video page sorted by starttime)
// @author Nanobyte
// @match https://sb.ltn.fi/*videoid=*sort=*starttime*
// @match https://sb.ltn.fi/video/*/*sort=*starttime*
// @match https://sb.ltn.fi/uuid/*/*?sort=starttime*
// @updateURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.similarsegments.user.js
// @downloadURL https://gist.github.com/MRuy/ca74d6a359c487d760f4a698e76fb0d6/raw/sb.ltn.fi.similarsegments.user.js
// @grant none
// ==/UserScript==
const COLORS = '#278ecf,#4bd762,#ffca1f,#ff9416,#d42ae8,#535ad7,#ff402c,#83bfff,#6edb8f,#ffe366,#ffc266,#d284bd,#8784db,#ff7b65,#caeefc,#9adbad,#fff1b2,#ffe0b2,#ffbeb2,#b1afdb'.split(',');
const COLOR_LEN = COLORS.length;
(function() {
'use strict';
[...document.querySelectorAll('table')].forEach(table => {
const headers = [...table.querySelectorAll('thead th')].map(item => item.textContent.trim());
if (headers.includes('Start') && headers.includes('End')) {
const startIndex = headers.indexOf('Start');
const endIndex = headers.indexOf('End');
const rows = [...table.querySelectorAll('tbody tr')];
let lastStarttime = 0;
let lastEndtime = 0;
let matchGroupIndex = 0;
rows.forEach(row => {
const startEl = row.children[startIndex];
const endEl = row.children[endIndex];
const start = parseTime(startEl.textContent.trim());
const end = parseTime(endEl.textContent.trim());
if (isInRange(lastStarttime, start) && isInRange(lastEndtime, end)) {
let color = COLORS[matchGroupIndex % COLOR_LEN];
wrapElementWithColor(startEl, color);
wrapElementWithColor(endEl, color);
} else {
matchGroupIndex++;
let color = COLORS[matchGroupIndex % COLOR_LEN];
wrapElementWithColor(startEl, color);
wrapElementWithColor(endEl, color);
}
lastStarttime = start;
lastEndtime = end;
});
}
});
})();
function parseTime(str) {
const [hours, minutes, seconds] = str.split(':').map(str => parseFloat(str));
return seconds + (minutes * 60) + (hours * 3600);
}
function isInRange(val1, val2, offset=2) {
if (val1 > val2 - offset && val1 < val2 + offset) {
return true;
}
return false;
}
function wrapElementWithColor(el, color) {
let wrapper = document.createElement("td");
el.parentNode.insertBefore(wrapper, el);
el.style = `padding:1px 4px;color:#000;width:100%;border-radius:4px;background:${color}`
wrapper.appendChild(el)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment