您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
show present time of the livestream
当前为
// ==UserScript== // @name Youtube Live Clock // @name:zh-TW Youtube Live Clock // @namespace https://greasyfork.org/scripts/453367 // @version 1.6.0 // @description show present time of the livestream // @description:zh-TW 顯示直播當下的時間 // @author Derek // @match *://www.youtube.com/* // @grant none // ==/UserScript== //you can choose your ideal date format by changing the FORMAT's value below const FORMAT = 1 /* 1: 2022/10/31 06:37:10 2: 10/31/2022 06:37:10 3: 31/10/2022 06:37:10 4: Mon 31/10/2022 06:37:10 5: Monday 31/10/2022 06:37:10 */ const $ = (element) => document.querySelector(element) const $$ = (element) => document.querySelectorAll(element) const abbr = { week: { Sun: 'Sunday', Mon: 'Monday', Tue: 'Tuesday', Wed: 'Wednesday', Thu: 'Thursday', Fri: 'Friday', Sat: 'Saturday' }, month: { Jan: 'January', Feb: 'February', Mar: 'March', Apr: 'April', May: 'May', Jun: 'June', Jul: 'July', Aug: 'August', Sep: 'September', Oct: 'October', Nov: 'November', Dec: 'December' } } const twoDigit = (num) => num.toString().padStart(2, '0') const timeFormat = (time) => { let second = time % 60 let minute = Math.floor((time % 3600) / 60) let hour = Math.floor(time / 3600) return hour > 0 ? `${hour}:${twoDigit(minute)}:${twoDigit(second)}` : `${minute}:${twoDigit(second)}` } const dateFormat = (presentTime) => { const [week, , day, year, time] = presentTime.toString().split(' ') const month = twoDigit(presentTime.getMonth() + 1) return { 1: ` (${year}/${month}/${day} ${time})`, 2: ` (${month}/${day}/${year} ${time})`, 3: ` (${day}/${month}/${year} ${time})`, 4: ` (${week} ${day}/${month}/${year} ${time})`, 5: ` (${abbr.week[week]} ${day}/${month}/${year} ${time})` } [FORMAT] } let liveData = null let progressBar = null let clockElement = null const waitProgressBar = () => { return new Promise((resolve, reject) => { const startTime = Date.now() const checkInterval = setInterval(() => { progressBar = $('.ytp-progress-bar') if (progressBar !== null) { clearInterval(checkInterval) resolve() } if (Date.now() - startTime > 10000) { clearInterval(checkInterval) reject('Wait time exceeded') } }, 500) }) } const getLiveClock = () => { if (!clockElement) { clockElement = document.createElement('span') clockElement.setAttribute('class', 'present-time') $('.ytp-time-display').childNodes[1].appendChild(clockElement) } return clockElement } const updateLiveTime = () => { try { if (liveData) { const progressTime = progressBar.getAttribute('aria-valuenow') return liveData[0].endDate ? dateFormat(new Date(Date.parse(liveData[0].startDate) + progressTime * 1000)) : timeFormat(progressTime) } else return '' } catch (error) { console.log('Youtube Live Clock: can\'t get liveData', error) return '' } } const startLiveClock = async () => { try { await waitProgressBar() liveData = JSON.parse($('.ytd-player-microformat-renderer').textContent).publication $('.ytp-live-badge').style = 'margin-left: 10px' const observer = new MutationObserver(() => { getLiveClock().textContent = updateLiveTime() }) observer.observe(progressBar, { attributes: true }) } catch (error) { console.log('Youtube Live Clock: error starting clock', error) } } const main = () => { if (window.location.href.includes('/watch?v=')) startLiveClock() } document.addEventListener('yt-navigate-finish', main)