Greasy Fork

Greasy Fork is available in English.

【小破站必备2022】 哔哩哔哩(bilibili|B站)自动增强--功能快捷键,视频智能解析,每日任务等

🔥🔥🔥推荐! 浸入式虚拟会员体验,功能智能自动化,让你的 B站 比别人的更强。自动跳转多 P 视频(UP 上传视频)上次观看进度,快捷键增强,每日任务(签到&分享),会员番剧无感解析,视频已看标签等等,具体看脚本介绍~

当前为 2022-04-03 提交的版本,查看 最新版本

// ==UserScript==
// @name         【小破站必备2022】 哔哩哔哩(bilibili|B站)自动增强--功能快捷键,视频智能解析,每日任务等
// @namespace    http://tampermonkey.net/
// @version      0.0.15
// @icon         https://cdn.jsdelivr.net/gh/Anjude/pubsrc@img/1.png
// @description  🔥🔥🔥推荐! 浸入式虚拟会员体验,功能智能自动化,让你的 B站 比别人的更强。自动跳转多 P 视频(UP 上传视频)上次观看进度,快捷键增强,每日任务(签到&分享),会员番剧无感解析,视频已看标签等等,具体看脚本介绍~
// @author       豆小匠Coding
// @match        https://*.bilibili.com/*
// @grant        GM_openInTab
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_xmlhttpRequest
// @original-script   https://github.com/Anjude/tampermonkey
// @require      https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.2.1/jquery.min.js
// @require     http://greasyfork.icu/scripts/412159-mydrag/code/MyDrag.js?version=858320
// ==/UserScript==

(function () {
  'use strict'
  // @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
  // 检查版本
  const RELEASE_VERSION = '0.0.15'
  let ENV = 'RELEASE'
  // ENV = 'DEBUG'
  const updateVersion = ENV === 'DEBUG' || RELEASE_VERSION !== GM_getValue('RELEASE_VERSION')
  updateVersion && GM_setValue('RELEASE_VERSION', RELEASE_VERSION)
  startHttpProxy()
  /**
   * 默认设置
   * `${e.altKey}${e.ctrlKey}${e.shiftKey}${pressKey}`
   */
  let defaultBili2sConf = {
    shortcutMap: {
      upToTop: '000U',   // 回到顶部
      takeNote: '000N',  // 打开视频笔记
      lightOff: '000L',  // 开关宽屏模式
      notePicShot: '101P',   // 笔记-视频截图
      noteTimePoint: '101T',   // 笔记-时间标记
      changeParseApi: '100V',   // 解锁视频
      showMenu: '100M',   // 打开菜单
    },
    videoRecordMap: {}, // 视频记录
    multiUnceasing: true,   // 多集自动连播
    singleUncreasing: false,    // 单集自动连播
    autoUnlockVideo: false, // 是否自动解锁视频
    shareDate: '2022/1/1',
    lastClearup: new Date().toLocaleString(),
    parseApiIndex: 0, // 解析接口选择
    pretendVip: false,
    installTime: null
  }

  // 网站配置
  const siteConfig = {
    delay2s: 2000,
    scrollBtnList: [
      'div.item.back-top', // 首页
      'button.primary-btn.top-btn', // 新版首页
      'div.item.backup',  // up视频,
      'div.tool-item.backup.iconfont.icon-up',  // 
      '#app > div.to-top', // up主所有视频
      '#cheese_guide > div > div'  // 课堂
    ],
    noteBtnList: [
      'div.note-btn', // 普通up视频
      'span.note-btn'  // 课堂视频
    ],
    notePanelList: ['div.resizable-component.bili-note' // 普通up视频 
    ],
    lightOffBtn: ['div.squirtle-single-setting-other-choice.squirtle-lightoff',
      'div.bilibili-player-fl.bilibili-player-video-btn-setting-right-others-content-lightoff.bui.bui-checkbox.bui-dark > input'],
    wideScreenBtn: ['div.squirtle-widescreen-wrap.squirtle-block-wrap > div', // bangumi 视频
      'div.bilibili-player-video-btn.bilibili-player-video-btn-widescreen' // up 视频
    ],
    videoSettingBtn: ['div.bilibili-player-video-btn.bilibili-player-video-btn-setting'],
    picBtnList: ['span.ql-capture-btn'],
    pointBtnList: ['span.ql-tag-btn'],
    multiPageBox: ['#multi_page > div.cur-list'],
    chapListItem: ['div.cur-list > ul > li.on'],
    trendBtnList: ['div.share-btns > div:nth-child(6)',
      'div.share-info > div > div > span'],
    shareBtnList: ['div.share-info'],
    unceasingBtnList: ['span.switch-button'],
    searchResBox: [
      '#video-list > ul',
      'div.video-list', // 搜索页
      'div.video.search-all-list > div', // 搜索页
      'div.mixin-list > ul.video-list',    // 番剧
      'div.flow-loader > ul',
      'div.rcmd-box',  // 首页推荐
      'div.section.video > div.content',  // UP主页
      '#submit-video-list > ul.list-list',  // UP主页,更多视频
      '#submit-video-list > ul.cube-list',  // UP主页,更多视频
      // '#reco_list > div.rec-list',  // 相关视频
    ],
    vipIcon: 'bili-avatar-icon--big-vip',
    vipSpan: [
      'div.avatar-container > div > div > span',
      'div.big-avatar-container--default > a > div > span',
      'a.header-entry-avatar > div > span',
    ],
    vipLabel: 'div.h-vipType',
    playerBox: ['#player_module'],
    videoBox: ['video'],
    vipAdClose: ['div.twp-mask > div > i'],
    parseApiList: [ // 解析链接均收集自网络,经过简单测试
      { url: 'https://vip.parwix.com:4433/player/?url=', name: 'Parwix解析系统' },
      { url: 'https://z1.m1907.cn/?jx=', name: 'm1907' },
      { url: 'https://www.yemu.xyz/?url=', name: '夜幕解析' },
      { url: 'https://vip.bljiex.cc/?v=', name: 'BL解析' },
      { url: 'https://yparse.jn1.cc/index.php?url=', name: '云解析' },
      { url: 'https://vip.mmkv.cn/tv.php?url=', name: 'mmkv' },
      { url: 'https://vip5.jiexi.one/?url=', name: '爱爱蓝光解析' },
      // { url: 'https://www.1717yun.com/jx/ty.php?url=', name: '1717云解析' },
      // { url: 'https://jx.rdhk.net/?v=', name: '4080视频解析' },
      // { url: 'https://go.yh0523.cn/y.cy?url=', name: '盘古云解析' },
      // { url: 'https://17kyun.com/api.php?url=', name: '17kyun' },
      // { url: 'https://lecurl.cn/?url=', name: 'dplayer - by-le' },
    ],
    bangumiLi: ['li.ep-item.cursor.badge.visited'],
    shortcutList: {
      upToTop: '回到顶部',
      takeNote: '打开/关闭笔记',
      changeParseApi: '切换视频解析接口',
      showMenu: '打开菜单',
      notePicShot: '笔记-视频截图',
      noteTimePoint: '笔记-时间标志',
      lightOff: '开关宽屏模式'
    },  // shortcut list
    scSetting: ''
  }

  let bili2sConf = GM_getValue('bili2sConf') || defaultBili2sConf

  if (updateVersion) {
    let shortcutMap = Object.assign({}, defaultBili2sConf.shortcutMap)
    bili2sConf = Object.assign(defaultBili2sConf, bili2sConf)
    bili2sConf.shortcutMap = Object.assign(shortcutMap, bili2sConf.shortcutMap)
    console.log(shortcutMap, defaultBili2sConf.shortcutMap, bili2sConf.shortcutMap)
    GM_setValue('bili2sConf', bili2sConf)
    Toast('脚本已更新')
  }

  if (!bili2sConf.installTime) {
    bili2sConf.installTime = new Date().toLocaleString()
    GM_setValue('bili2sConf', bili2sConf)
    alert('首次使用,前往微信小程序,随时反馈!')
    window.GM_openInTab(
      'https://cdn.jsdelivr.net/gh/Anjude/pubsrc@img/TW-TamperMonkey.png',
      { active: true, insert: true, setParent: true }
    )
  }

  const delayExecute = (execution, delayMs) => {
    setTimeout(() => {
      execution()
    }, delayMs || siteConfig.delay2s);
  }

  const getElement = (list) => {
    if (typeof list === 'string') return document.querySelector(list)
    let btn = document.querySelector(list[0])
    list.forEach(e => { btn = document.querySelector(e) || btn })
    return btn
  }

  const getBvid = (href) => {
    let res = /video\/([0-9|a-z|A-Z]*)/ig.exec(href || document.location.href)
    return res === null ? false : res[1]
  }

  // 改编自 github 网友贡献的代码,详情请参见 github 的提交记录
  const LightOff = () => {
    let settingBtn = getElement(siteConfig.videoSettingBtn)
    settingBtn?.dispatchEvent(new MouseEvent('mouseover'))
    settingBtn?.dispatchEvent(new MouseEvent('mouseout'))

    let wideScreenBtn = getElement(siteConfig.wideScreenBtn)
    let lightOffBtn = getElement(siteConfig.lightOffBtn)
    let scrollDistance = window.location.href.match('bangumi') ? 50 : 100

    wideScreenBtn.click()
    lightOffBtn.click()
    window.scrollTo(0, scrollDistance)
  }

  const UpToTop = () => { // 回到顶部
    let scrollBtn = getElement(siteConfig.scrollBtnList)
    if (scrollBtn) scrollBtn.click()
  }

  const TakeNote = () => {
    let noteBtn = getElement(siteConfig.noteBtnList)
    let nodePanel = getElement(siteConfig.notePanelList)
    let res = nodePanel || (() => {
      noteBtn.click()
      return false
    })()
    if (!res) return

    nodePanel.style.display = nodePanel.style.display === 'none'
      ? '' : 'none'
  }

  const NotePicShot = () => {
    let picBtn = getElement(siteConfig.picBtnList)
    picBtn.click()
  }

  const NoteTimePoint = () => {
    let pointBtn = getElement(siteConfig.pointBtnList)
    pointBtn.click()
  }

  const keyCtrl = () => {

  }

  const blockKey = (e) => {
    let isBlock = false

    // do sth if isBlock should be true

    return isBlock
  }

  const setShortcut = (command) => {
    let commandString = getShortCut(command)
    let scSetting = siteConfig.scSetting
    let innerTextList = document.querySelector(`#${scSetting}`).innerHTML.split(':')
    document.querySelector(`#${scSetting}`).innerHTML = innerTextList[0] + ': ' + commandString
    siteConfig.scm[scSetting] = command
  }

  let focus = false   // 输入中
  $(document).ready(() => {
    $(document).delegate('input, textarea',
      'focus', () => { focus = true })
    $(document).delegate('input, textarea',
      'blur', () => { focus = false })
    $(document).keydown((e) => {
      // 如果正在打字或者特殊情况,屏蔽快捷键
      if (!e.altKey && !e.shiftKey && !e.ctrlKey
        && (focus || blockKey(e))) {
        return
      }
      const k = (key) => key ? 1 : 0
      let pressKey = String.fromCharCode(e.keyCode)
      let command = `${k(e.altKey)}${k(e.ctrlKey)}${k(e.shiftKey)}${pressKey}`
      let keyMap = bili2sConf.shortcutMap

      // console.log('键盘:', command, siteConfig.scSetting)
      if (siteConfig.scSetting) { return setShortcut(command) }
      switch (command) {
        case keyMap.upToTop:
          return UpToTop()
        case keyMap.lightOff:
          return LightOff()
        case keyMap.takeNote:
          return TakeNote()
        case keyMap.changeParseApi:
          return ChangeParseApi()
        case keyMap.showMenu:
          return document.querySelector('#sc-box').style.display = ''
        case keyMap.notePicShot:
          return NotePicShot()
        case keyMap.noteTimePoint:
          return NoteTimePoint()
        default:
          keyCtrl(command)  // 一些不常用的小操作,集中一个函数处理
      }
    })
  })

  const chapListener = (res) => {
    let listItem = getElement(siteConfig.chapListItem)?.innerHTML
    if (!listItem) {
      console.log('非多集视频')
      return
    }
    let regxList = /video\/([0-9a-zA-Z]*)\?p=(\d+).*title=.(.*?).><div/i.exec(listItem)
    let bvid = regxList[1]
    bili2sConf.videoRecordMap[bvid] = Object.assign(bili2sConf.videoRecordMap[bvid] || {}, {
      p: regxList[2],
      title: regxList[3],
      updateTime: new Date().toLocaleString()
    })
    GM_setValue('bili2sConf', bili2sConf)
  }

  const multiPageJump = async () => {
    let bvid = getBvid()
    let videoHis = bili2sConf.videoRecordMap[bvid]
    videoHis && (() => {
      let hrefRegexp = new RegExp(`${bvid}\\?p=\\d+`, 'i')
      if (hrefRegexp.test(window.location.href)) { return }
      let curChapLi = document.querySelector(`div.cur-list > ul > li:nth-child(${videoHis.p}) > a > div`)
      if (!curChapLi) {
        return delayExecute(multiPageJump)
      }
      curChapLi.click()
      Toast(`小助手: 跳转上次观看 P${videoHis.p}`)
    })()
  }

  const setVideoRecord = () => {
    let bvid = getBvid()
    let videoRecord = bili2sConf.videoRecordMap[bvid] || {
      docTitle: document.title,
      p: 1
    }
    videoRecord.updateTime = new Date().toLocaleString()
    bili2sConf.videoRecordMap[bvid] = Object.assign(bili2sConf.videoRecordMap[bvid] || {}, videoRecord)
    // console.log(bili2sConf.videoRecordMap[bvid], videoRecord)
    GM_setValue('bili2sConf', bili2sConf)
  }

  const dealUnceasing = (isMultiPage) => {
    // 处理连播
    let switchCase = isMultiPage ? 'multiUnceasing' : 'singleUncreasing'
    let unceasingBtn = getElement(siteConfig.unceasingBtnList)
    if (!unceasingBtn) {
      return delayExecute(dealUnceasing)
    }
    let curUnceasing = /switch-button on/.test(unceasingBtn.getAttribute('class'))
    curUnceasing === bili2sConf[switchCase]
      || unceasingBtn.click()
    unceasingBtn.addEventListener("click", (e) => {
      // 过滤脚本模拟点击
      if (e.isTrusted) {
        bili2sConf[switchCase] = !/switch-button on/.test(unceasingBtn.getAttribute('class'))
        GM_setValue('bili2sConf', bili2sConf);
      }
    })
  }

  const doShare = () => {
    console.log('[B站小助手]: 开始分享!')
    let shareBtn = getElement(siteConfig.shareBtnList)
    shareBtn?.dispatchEvent(new MouseEvent('mouseover'))

    let trendBtn = getElement(siteConfig.trendBtnList)
    if (!trendBtn) {
      return delayExecute(doShare)
    }
    trendBtn.click()
    document.body.lastChild.remove()
    shareBtn?.dispatchEvent(new MouseEvent('mouseout'))
    bili2sConf.shareDate = new Date().toLocaleDateString()
    GM_setValue('bili2sConf', bili2sConf)
    console.log('[B站小助手]: 分享完成!')
    Toast('小助手: 今日分享任务达成')
  }

  const dealRead = (res) => {
    siteConfig.searchResBox.forEach(boxPath => {
      let searchResBox = getElement(boxPath)
      // console.log(searchResBox)
      searchResBox && searchResBox.childNodes.forEach(e => {
        if (!e.innerHTML) return
        e.style.position = 'relative'
        let bvid = getBvid(e.innerHTML)
        if (!bvid) return
        let addDiv = document.createElement("div")
        addDiv.className = 'video-view'
        if (bili2sConf.videoRecordMap[bvid]) {
          addDiv.innerHTML = '已看'
          addDiv.style.opacity = 0.9;
          addDiv.style.color = 'red';
        } else {
          // addDiv.innerHTML = "未看";
        }
        e.prepend(addDiv);
      })
    })
  }

  const ChangeParseApi = () => {
    let curIndex = bili2sConf.parseApiIndex
    bili2sConf.parseApiIndex = (curIndex + 1) % siteConfig.parseApiList.length
    UnlockBangumi(bili2sConf.parseApiIndex, false, true)
    GM_setValue('bili2sConf', bili2sConf)
    Toast(`B站小助手: 解析接口${bili2sConf.parseApiIndex + 1} ${siteConfig.parseApiList[bili2sConf.parseApiIndex].name}`)
  }

  const UnlockBangumi = (parseApiIndex = 0, setAutoUnlock, forceUnlock) => {
    if (setAutoUnlock) {
      let set = !bili2sConf.autoUnlockVideo
      bili2sConf.autoUnlockVideo = set
      GM_setValue('bili2sConf', bili2sConf)
      Toast(`B站小助手:${set ? '开启' : '关闭'}自动解锁!`)
    }
    parseApiIndex %= siteConfig.parseApiList.length
    let videoInfo = getElement(siteConfig.bangumiLi)?.innerHTML
    if (!forceUnlock && (!bili2sConf.autoUnlockVideo
      || videoInfo && !/>(会员|付费|受限)<\/div>/.test(videoInfo)
      || !videoInfo)
    ) { return $('#anjude-iframe').length && location.reload() }

    let parseApi = siteConfig.parseApiList[parseApiIndex]
    let newPlayer = document.createElement('iframe')
    newPlayer.id = 'anjude-iframe'
    newPlayer.height = '100%'
    newPlayer.width = '100%'
    newPlayer.src = parseApi.url + window.location.href
    newPlayer.setAttribute('allow', 'autoplay')
    newPlayer.setAttribute('frameborder', 'no')
    newPlayer.setAttribute('border', '0')
    newPlayer.setAttribute('allowfullscreen', 'true')
    newPlayer.setAttribute('webkitallowfullscreen', 'webkitallowfullscreen')

    let playerBox = getElement(siteConfig.playerBox)
    let videoBox = getElement(siteConfig.videoBox)

    if (videoBox) {
      videoBox.muted = true
      videoBox.pause()
    }

    playerBox.innerHTML = ''
    playerBox.append(newPlayer)

    let monitorTimes = 0
    let vipAdMonitor = setInterval(() => {
      monitorTimes++
      let closeAd = getElement(siteConfig.vipAdClose)
      if (closeAd || monitorTimes >= (5 * 60 * 1000 / 200)) {
        closeAd.click()
        clearInterval(vipAdMonitor)
      }
    }, 200);
    Toast(`B站小助手: 解析完成`, 500)
  }

  const pretendVip = () => {
    siteConfig.vipSpan.forEach(e => {
      let vipSpan = getElement(e)
      vipSpan && vipSpan.classList.add(siteConfig.vipIcon)
    })
    let vipLabel = getElement(siteConfig.vipLabel)
    if (vipLabel) {
      let newClass = vipLabel.getAttribute('class').replace('disable', '')
      vipLabel.setAttribute('class', newClass)
    }
  }

  const executeByUri = (responseURL, result) => {
    /\/player\/playurl/.test(responseURL)
      && chapListener(result);
    (/x\/web-interface\/search/.test(responseURL)
      || /x\/web-interface\/index\/top\/rcmd/.test(responseURL)
      || /x\/space\/arc/.test(responseURL))
      && dealRead(result);
    (/pgc\/view\/web\/section\/order/.test(responseURL)
      || /pgc\/season\/episode\/web\/info/.test(responseURL))
      && UnlockBangumi(bili2sConf.parseApiIndex);
  }

  const runScript = () => {
    let date = new Date().toLocaleDateString()
    let href = window.location.href
    let isMultiPage = getElement(siteConfig.multiPageBox)
    if (isMultiPage) {
      multiPageJump()
    }
    if (/\/video\//.test(href)) {
      setVideoRecord()
      dealUnceasing(isMultiPage)
      dealRead()
      date === bili2sConf.shareDate || doShare()
    }
    if (/bilibili.com\/bangumi/.test(href)) {
      addParseBtn()
    }
    if (/search.bilibili.com/.test(href)) {
      dealRead()
    }
    bili2sConf.pretendVip && pretendVip()
  }

  // 执行脚本
  try {
    // console.log('[B站小助手]:', bili2sConf)
    GM_addStyle(getCss())
    setCommand()
    setTimeout(() => {
      runScript()
    }, siteConfig.delay2s);
    clearupStore()
  } catch (err) {
    console.log('[B站小助手]:', err.name, err.message)
    if (confirm(`【B站小助手】: 请截图(到 我的 - 客服 处)反馈 ${err}`)) {
      window.GM_openInTab(
        'https://cdn.jsdelivr.net/gh/Anjude/pubsrc@img/TW-TamperMonkey.png',
        { active: true, insert: true, setParent: true }
      )
    }
  }

  function resetScript() {
    GM_deleteValue('bili2sConf')
  }

  function helper() {
    let str = ``
    let list = str.match(/https?:\/\/[0-9a-zA-Z./?_-]*=/ig)
    list.forEach((e, i) => {
      setTimeout(() => {
        console.log(i, i === list.length - 1);
        window.open(`${e}https://www.bilibili.com/bangumi/play/ep457778?spm_id_from=333.999.0.0`, 'target')
      }, i * 15000)
    })
  }

  function clearupStore() {
    const getDayDiff = (d) => {
      return (new Date() - new Date(d)) / (1000 * 60 * 60 * 24)
    }
    let dayDiff = getDayDiff(bili2sConf.lastClearup)
    if (dayDiff < 30) return    // 每月清理一次数据
    console.log('[B站小助手]:开始清理!')

    let recordMapKeys = Object.keys(bili2sConf.videoRecordMap)
    recordMapKeys.forEach(e => {
      let updateTime = bili2sConf.videoRecordMap[e].updateTime
      if (getDayDiff(updateTime) > 365 * 2) {
        delete bili2sConf.videoRecordMap[e]
      }
    })
    bili2sConf.lastClearup = new Date().toLocaleString()
    GM_setValue('bili2sConf', bili2sConf)
  }

  function startHttpProxy() {
    XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, {
      apply: (target, thisArg, args) => {
        thisArg.addEventListener('load', event => {
          try {
            // console.log(111, event.target.responseURL)
            let { responseText, responseURL } = event.target
            if (!/^{.*}$/.test(responseText)) return
            const result = JSON.parse(responseText);
            setTimeout(() => {
              executeByUri(responseURL, result)
            }, siteConfig.delay2s / 4);
          } catch (err) { }
        })
        return target.apply(thisArg, args)
      }
    })
  }

  function addParseBtn() {
    let ele = $(`
    <div id="anjude-parse" class="mobile-info">
    <i class="iconfont icon-play"></i>
    <span>解析</span>
    </div>
    `)
    $('#toolbar_module').append(ele)
    document.querySelector("#anjude-parse").addEventListener('click', ChangeParseApi)
  }

  function Toast(message = "已完成", time = 2000) {
    /*设置信息框停留的默认时间*/
    let el = document.createElement("div")
    el.setAttribute("class", "web-toast")
    el.innerHTML = message
    document.body.appendChild(el);
    el.classList.add("fadeIn");
    setTimeout(() => {
      el.classList.remove("fadeIn")
      el.classList.add("fadeOut")
      /*监听动画结束,移除提示信息元素*/
      el.addEventListener("animationend", () => {
        document.body.removeChild(el)
      })
      el.addEventListener("webkitAnimationEnd", () => {
        document.body.removeChild(el)
      })
    }, time)
  }

  function getShortCut(command) {
    // console.log(command);
    let res = ''
    if (parseInt(command[0])) res += 'Alt+'
    if (parseInt(command[1])) res += 'Ctrl+'
    if (parseInt(command[2])) res += 'Shift+'
    res += command[3]
    return res
  }

  function clearCommandStatus(SL) {
    SL.forEach(e => { document.querySelector(`#${e}`).style.color = '' })
  }

  function setCommand() {
    initSettingPanel()
    GM_registerMenuCommand('设置脚本', () => {
      document.querySelector('#sc-box').style.display = ''
    })
    GM_registerMenuCommand('重置脚本', () => {
      if (confirm('重置后观看记录、快捷键修改等数据将清空!')) {
        resetScript()
      }
    })
  }

  function initSettingPanel() {
    let SCL = siteConfig.shortcutList
    siteConfig.scm = bili2sConf.shortcutMap
    let scItem = ''
    Object.keys(SCL).forEach(e => {
      scItem += `<div id="${e}">${SCL[e]}快捷键: ${getShortCut(siteConfig.scm[e])}</div>`
    })
    let boxHtml = $(`
<div id="sc-box" style="display:none;width:300px;">
<div id="sc-title" style="width: 100%;height: 20px;
text-align: center;font-size: 16px;padding: 20px;">
快捷键设置(点击选中设置)
</div>
<div style="display:flex; font-size: 15px;flex-direction: column;">
<label>假装是大会员 <input type="checkbox" id="pretend-vip" ${bili2sConf.pretendVip ? 'checked' : ''} /></label>
<label>自动解锁会员视频 <input type="checkbox" id="auto-unlockvideo" ${bili2sConf.autoUnlockVideo ? 'checked' : ''} /></label>
</div>
<div style="font-size: 15px;">
${scItem}
</div>
<div style="justify-content:center; display: flex; padding: 10px;">
<button id="anjude-scok-btn" style="color: white; font-size:16px; border-radius: 2px;
background: green;padding: 3px;">设置完成</button>
</div>
<a style="font-size: 12px; color: blue;" target="_blank" href="http://greasyfork.icu/zh-CN/scripts/437941/feedback">好用的话,去给个好评咯~</a>
<a id="badguy" style="font-size: 12px; color: red;margin-left: 10px;">烂脚本,我要差评!</a>
<img id="miniprogram" style="display: none;" src="https://cdn.jsdelivr.net/gh/Anjude/pubsrc@img/TW-TamperMonkey.png">
</div>
    `)
    $(document.body).append(boxHtml)
    new MyDrag($('#sc-box')[0], { handle: $('#sc-title')[0] })
    Object.keys(SCL).forEach(v => {
      document.querySelector(`#${v}`).addEventListener('click', function (e) {
        siteConfig.scSetting = this.id
        clearCommandStatus(Object.keys(SCL))
        this.style.color = 'green'
      })
    })
    document.querySelector('#anjude-scok-btn').addEventListener('click', function (e) {
      // 设置快捷键,缓存数据
      siteConfig.scSetting = ''
      bili2sConf.shortcutMap = siteConfig.scm
      GM_setValue('bili2sConf', bili2sConf)
      document.querySelector('#sc-box').style.display = 'none'
    })
    document.querySelector('#auto-unlockvideo').addEventListener('click', function (e) {
      UnlockBangumi(bili2sConf.parseApiIndex, true)
    })
    document.querySelector('#pretend-vip').addEventListener('click', function (e) {
      bili2sConf.pretendVip = !bili2sConf.pretendVip
      GM_setValue('bili2sConf', bili2sConf)
      Toast('小助手: 刷新页面后生效')
    })
    document.querySelector('#badguy').addEventListener('click', function (e) {
      let cur = document.querySelector('#miniprogram').style.display
      document.querySelector('#miniprogram').style.display = cur ? '' : 'none'
    })
    updateVersion && (document.querySelector('#sc-box').style.display = '')
  }

  function getCss() {
    return `
    #anjude-parse{
      color: orange;
      margin-left: 20px;
    }
    a{text-decoration:none;}
    #pretend-vip,
    #auto-unlockvideo{
      background-color: initial;
	    cursor: default;
	    appearance: checkbox;
	    box-sizing: border-box;
	    padding: initial;
	    border: initial;
    }
    #sc-box{
        padding: 10px;border-radius: 5px; 
        background: #F6F6F6;border: #44b549 2px solid;
    }
    .video-view{
      display:inline-block;
      position:absolute;
      left:0px; top:0px;
      background:#FFF; color:#666;
      opacity: 0.8; padding:1px 5px;
      z-index:999;
    }
    @keyframes fadeIn {
    0%    {opacity: 0}
        100%  {opacity: 1}
    }
    @keyframes fadeOut {
        0%    {opacity: 1}
        100%  {opacity: 0}
    }
    .web-toast{
        position: fixed;
        background: rgba(0, 0, 0, 0.7);
        color: #fff;
        font-size: 14px;
        line-height: 1;
        padding:10px;
        border-radius: 3px;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
        z-index: 9999;
        white-space: nowrap;
    }
    .fadeOut{
        animation: fadeOut .5s;
    }
    .fadeIn{
        animation:fadeIn .5s;
    }
    `}
})();