Greasy Fork is available in English.
You see it too long time.
- // ==UserScript==
- // @name 你看的时间太长了
- // @namespace You see it too long time.
- // @version 0.1.1
- // @author 稻米鼠
- // @description You see it too long time.
- // @run-at document-idle
- // @homepage https://meta.appinn.net/t/11501
- // @supportURL https://meta.appinn.com/t/11501
- // @match *://*/*
- // @noframes
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_listValues
- // ==/UserScript==
- // 模式 0:限制总观看时间;模式 1:限制每个网站观看时间
- // const youSeeItTooLongTimeMode = 1
- // 最大观看时长,单位:分钟
- // const howMinutesCanYouWatchIt = 60
- /* 以下无需修改 */
- const oldLoadFun = window.onload
- window.onload = async function(){
- oldLoadFun && oldLoadFun()
- // 获取当前所需时间对象
- const getNow = ()=>{
- const nowUTC = new Date()
- const now = Number((+nowUTC/1000).toFixed()) - nowUTC.getTimezoneOffset()*60
- const day = now - now%86400
- return { now, day }
- }
- // 储存当前数据
- const storeData = async (long)=>{
- await GM_setValue(window.location.hostname, JSON.stringify({
- day: start.day,
- long: long
- }))
- }
- // 获取存储的数据
- const getData = async (key=window.location.hostname)=>{
- if(await GM_getValue(key)){
- try {
- const temp = JSON.parse(await GM_getValue(key))
- // 如果有合理的数据,并且是当天数据
- if(temp.day && temp.day === start.day && temp.long){
- return temp
- }
- } catch (error) {}
- }
- return false
- }
- // 储存配置数据
- const storeConfig = async (mode=1, max=3600)=>{
- const config = {
- mode: isNaN(mode) ? 1 : mode,
- max: isNaN(max) ? 3600 : max
- }
- await GM_setValue('options', JSON.stringify(config))
- return config
- }
- // 获取配置数据
- const getConfig = async ()=>{
- if(await GM_getValue('options')){
- try {
- const temp = JSON.parse(await GM_getValue('options'))
- // 如果有合理的数据,并且是当天数据
- if(!isNaN(temp.mode) && !isNaN(temp.max)){
- return temp
- }
- } catch (error) {
- this.console.log(error)
- }
- }
- return await storeConfig()
- }
- // 修改网页标题
- const changeTitle = title=>{
- document.title = title+document.title.replace(/^【[\d:-]+】/i, '')
- }
- // 两位数字
- const dbNum = num=>{
- return num<10 ? '0'+num : num
- }
- // 窗口是否最小化
- const isMin = ()=>{
- let isWinMin = false;
- if (window.outerWidth != undefined) {
- isWinMin = window.outerWidth <= 160 && window.outerHeight <= 27;
- } else {
- isWinMin = window.screenTop < -30000 && window.screenLeft < -30000;
- }
- return isWinMin;
- }
- // 处理 hash 指令
- const hashCommand = async (hash, options)=>{
- if(/^#clear$/i.test(hash)){
- await storeData( 0 )
- window.location.hash = ''
- return
- }
- if(/^#clearAll$/i.test(hash)){
- const keys = await GM_listValues()
- for (let key of keys) {
- if(key==='options'){ continue }
- GM_deleteValue(key);
- }
- window.location.hash = ''
- return
- }
- if(/^#close$/i.test(hash)){
- await storeData( 1.25*options.max )
- window.location.hash = ''
- return
- }
- if(/^#add\d+$/i.test(hash)){
- let add = +hash.replace(/^#add(\d+)$/, '$1')
- add = isNaN(add) ? 0 : add*60
- const siteData = await getData()
- let historyLong = siteData ? siteData.long : 0
- historyLong = historyLong<add ? 0 : historyLong-add
- await storeData(historyLong)
- window.location.hash = ''
- return
- }
- if(/^#sub\d+$/i.test(hash)){
- let sub = +hash.replace(/^#sub(\d+)$/, '$1')
- sub = isNaN(sub) ? 0 : sub*60
- const siteData = await getData()
- let historyLong = siteData ? siteData.long : 0
- historyLong = historyLong+sub
- await storeData(historyLong)
- window.location.hash = ''
- return
- }
- if(/^#mode\d$/i.test(hash)){
- let mode = +hash.replace(/^#mode(\d)$/, '$1')
- mode = isNaN(mode) ? 1 : (mode===0 ? 0 : 1)
- await storeConfig(mode, options.max)
- window.location.hash = ''
- return
- }
- if(/^#max\d+$/i.test(hash)){
- let max = +hash.replace(/^#max(\d+)$/, '$1')
- if(isNaN(max)){ return }
- max = 60*max
- await storeConfig(options.mode, max)
- window.location.hash = ''
- return
- }
- if(/^#maxadd\d+$/i.test(hash)){
- let add = +hash.replace(/^#maxadd(\d+)$/, '$1')
- if(isNaN(add)){ return }
- const max = options.max + 60*add
- await storeConfig(options.mode, max)
- window.location.hash = ''
- return
- }
- if(/^#maxsub\d+$/i.test(hash)){
- let sub = +hash.replace(/^#maxsub(\d+)$/, '$1')
- if(isNaN(sub)){ return }
- const max = options.max - 60*sub
- await storeConfig(options.mode, max>=0 ? max : 0)
- window.location.hash = ''
- return
- }
- }
- // 时间更新
- const refreshTime = async ()=>{
- const n = getNow() // 获取当前时间
- // 如果页面在后台或者窗口最小化,仅更新起始对象中的最后更新时间
- if(document.visibilityState !== 'visible' || isMin()){
- start.lastTime = n.now
- return
- }
- // 获取当前配置
- const options = await getConfig()
- // 检测指令
- await hashCommand(window.location.hash, options)
- // 如果是当天
- const siteData = await getData()
- start.historyLong = n.day === start.day
- ? (siteData ? siteData.long : 0) + n.now - start.lastTime
- : n.now%86400
- start.day = n.day
- start.lastTime = n.now
- await storeData(start.historyLong)
- let lastTime = options.max
- if(options.mode){
- lastTime = options.max - start.historyLong
- }else{
- const keys = await GM_listValues()
- for (let key of keys) {
- if(key==='options'){ continue }
- const m = await getData(key)
- if(m.day === start.day){
- lastTime -= m.long
- }else{
- m && GM_deleteValue(key);
- }
- }
- }
- if(lastTime < 0){
- const alpha = 1 + 4*lastTime/options.max
- const opacity = ( alpha>1 ? 1 : ( alpha<0 ? 0 : alpha ) ).toFixed(2)
- document.querySelector('body').style.opacity = opacity
- if(document.fullscreenElement){// 如果全屏
- document.fullscreenElement.style.opacity = opacity
- }
- if(alpha<0){
- if(document.fullscreenElement){ document.exitFullscreen() } // 如果全屏则退出
- document.querySelector('html').style.backgroundImage = 'url("https://i.v2ex.co/WJ15n12m.png")'
- document.querySelector('html').style.backgroundPosition = 'center top'
- document.querySelector('html').style.backgroundRepeat = 'no-repeat'
- document.querySelector('html').style.backgroundAttachment = 'fixed'
- window.clearInterval(timer)
- }
- }else{
- document.querySelector('body').style.opacity = 1
- }
- const lastTimeToShow = (lastTime>=0 ? '' : '-')
- + dbNum( Math.floor( Math.abs(lastTime)/60) )
- + ':'
- + dbNum( Math.abs(lastTime)%60 )
- changeTitle('【'+lastTimeToShow+'】')
- }
- // 初始化 启动程序
- const start = getNow()
- const siteData = await getData()
- start.lastTime = start.now
- start.historyLong = siteData ? siteData.long : 0
- await storeData( start.historyLong )
- refreshTime()
- const timer = window.setInterval(refreshTime, 1e3)
- }