您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
開場したら自動で入場します
// ==UserScript== // @name Niconico Live Auto Enter // @description 開場したら自動で入場します // @version 0.2.4 // @include https://live.nicovideo.jp/watch/* // @grant GM_xmlhttpRequest // @author xulapp // @namespace https://twitter.com/xulapp // @license MIT // ==/UserScript== /* eslint-env browser, greasemonkey */ 'use strict'; function atLeast(promises, num) { return new Promise((resolve, reject) => { const resolved = []; const rejected = []; function ok(arg) { resolved.push(arg); added(); } function ng(err) { rejected.push(err); added(); } function added() { if (resolved.length + rejected.length < promises.length) return; if (resolved.length < num) reject(rejected); else resolve(resolved); } for (let p of promises) Promise.resolve(p).then(ok, ng); }); } const getJST = (() => { const servers = [ '//ntp-a1.nict.go.jp/cgi-bin/json', '//ntp-b1.nict.go.jp/cgi-bin/json', ]; let diff = 0; function getJST() { return Date.now() + diff; } function get(options) { if (typeof options === 'string') options = {url: options}; return new Promise((onload, onerror) => { GM_xmlhttpRequest(Object.assign({}, options, {onload, onerror})); }); } function getJSON(...args) { return get(...args).then(res => JSON.parse(res.responseText)); } function fetchDiff(server) { return getJSON(`${server}?${Date.now() / 1000}`).then(res => { const rt = Date.now() / 1000; const {it, st} = res; return (st - (it + rt) / 2) * 1000; }); } function onload(arr) { if (arr.length) diff = arr.reduce((a, b) => a + b) / arr.length | 0; console.log(`時差を取得しました [${diff < 0 ? '' : '+'}${diff}ms]`); return diff; } function onerror(err) { console.log('時差の取得に失敗しました'); for (let res of err) if (res instanceof Error) console.log(res.message); else console.log(` ${res.status} ${res.statusText} ${res.finalUrl}`); return null; } getJST.ready = atLeast(servers.map(fetchDiff), 1).then(onload, onerror); return getJST; })(); getJST.ready.then(() => { const notificationTitle = 'Niconico Live Auto Enter'; const notificationDefaults = { icon: (document.querySelector('meta[itemprop="thumbnail"]') || 0).content, tag: 'niconico-live-auto-enter', autoClose: 5000, }; const programTitle = (document.querySelector('.program-title[itemprop="name"]') || 0).textContent; const published = Date.parse((document.querySelector('.kaijo meta[itemprop="datePublished"]') || 0).content); const notified = {}; if (!published || getRemaining() <= 0) return; const timer = () => { const remaining = getRemaining(); if (remaining <= 0) { notifyEnter(); enter(); return; } const sec = getRemainingSeconds(); const wait = sec < 1 ? 0 : sec < 10 ? 100 : sec < 3600 ? 1000 : 10000; setTimeout(timer, wait); const target = roundRemaining(remaining); if (target in notified) return; notifyRemaining(remaining); notified[target] = true; }; timer(); function getRemainingSeconds() { return (published - getJST()) / 1000; } function getRemaining() { return Math.ceil(getRemainingSeconds() / 60); } function roundRemaining(remaining) { for (let m of [0, 1, 3, 5, 10, 20, 30]) if (remaining <= m) return m; return Math.ceil(remaining / 60) * 60; } function notify(body, options) { options = Object.assign({body}, notificationDefaults, options); return new Promise((resolve, reject) => { Notification.requestPermission(status => { if (status !== 'granted') { reject(status); return; } const n = new Notification(notificationTitle, options); if (options.autoClose) setTimeout(() => n.close(), options.autoClose); resolve(n); }); }); } function notifyRemaining(remaining) { const minutes = remaining % 60; const hours = remaining / 60 % 24 | 0; const days = remaining / 60 / 24 | 0; const timeStr = []; if (days) timeStr.push(`${days} 日`); if (hours) timeStr.push(`${hours} 時間`); if (minutes || !timeStr.length) timeStr.push(`${minutes} 分`); notify(`${programTitle}\n\n開場まで、あと ${timeStr.join(' ')} です。`); } function notifyEnter() { notify('入場します!'); } function enter() { location.reload(true); } });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址