94list-laravel-tampermonkey

对接 94list-laravel 的油猴脚本

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name              94list-laravel-tampermonkey
// @namespace         https://github.com/huankong233/94list-laravel-tampermonkey
// @version           0.0.4
// @author            huan_kong
// @description       对接 94list-laravel 的油猴脚本
// @license           MIT
// @homepage          https://github.com/huankong233/94list-laravel-tampermonkey
// @supportURL        https://github.com/huankong233/94list-laravel-tampermonkey
// @icon              https://huankong.top/favicon.ico
// @match             *://pan.baidu.com/disk/main*
// @match             *://pan.baidu.com/disk/home*
// @match             *://yun.baidu.com/disk/main*
// @match             *://yun.baidu.com/disk/home*
// @connect           localhost
// @connect           127.0.0.1
// @connect           *
// @require           https://registry.npmmirror.com/jquery/3.7.1/files/dist/jquery.min.js
// @require           https://registry.npmmirror.com/sweetalert2/11.10.6/files/dist/sweetalert2.all.min.js
// @grant             GM_xmlhttpRequest
// @grant             GM_addStyle
// @grant             GM_setClipboard
// @grant             GM_registerMenuCommand
// @grant             GM_setValue
// @grant             GM_getValue
// ==/UserScript==

$(async function () {
  GM_registerMenuCommand('⚙️ 设置', () => {
    Swal.fire({
      title: '⚙️ 设置',
      html: `<div>
        <p>94list-laravel-site-url</p>
        <input type="text" id="siteUrl" value=${GM_getValue('94list-laravel-site-url', '')}>
        <p>94list-laravel-site-password</p>
        <input type="text" id="sitePassword" value=${GM_getValue(
          '94list-laravel-site-password',
          ''
        )}>
        <p>94list-laravel-site-aria2-host</p>
        <input type="text" id="siteAriaHost" value=${GM_getValue(
          '94list-laravel-site-aria2-host',
          ''
        )}>
        <p>94list-laravel-site-aria2-secret</p>
        <input type="text" id="siteAriaSecret" value=${GM_getValue(
          '94list-laravel-site-aria2-secret',
          ''
        )}>
      </div>`,
      icon: 'info',
      showConfirmButton: true
    }).then(() => {
      GM_setValue('94list-laravel-site-url', document.querySelector('#siteUrl').value)
      GM_setValue('94list-laravel-site-password', document.querySelector('#sitePassword').value)
      GM_setValue('94list-laravel-site-aria2-host', document.querySelector('#siteAriaHost').value)
      GM_setValue(
        '94list-laravel-site-aria2-secret',
        document.querySelector('#siteAriaSecret').value
      )
      location.reload()
    })
  })

  function setLocalStorage(key, url) {
    GM_setValue(key, url)
    location.reload()
  }

  const request = params => {
    return new Promise((resolve, reject) =>
      GM_xmlhttpRequest({
        ...params,
        onload: res => (res.status === 200 ? resolve(res) : reject(res)),
        onerror: err => reject(err)
      })
    )
  }

  const getPt = () => {
    if (document.location.href.indexOf('.baidu.com/disk/home') > 0) return 'home'
    if (document.location.href.indexOf('.baidu.com/disk/main') > 0) return 'main'
    return ''
  }
  const pt = getPt()

  GM_addStyle(
    `input{outline-style:none;border:1px solid #c0c4cc;border-radius:5px;width:100%;height:100%;padding:0;padding:10px 15px;box-sizing:border-box}.hk table{width:100%;border-collapse:collapse;margin:25px 0;font-size:.9em;font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;min-width:400px;box-shadow:0 0 20px rgba(0,0,0,0.15)}.hk thead tr{background-color:#009879;color:#fff;text-align:center;}.hk .line{line-height:60px}.hk th,.hk td{padding:12px 15px;width:138px;height:85px;overflow:overlay;display:inline-block;}.hk tbody tr{border-bottom:1px solid #ddd}.hk tbody tr:nth-of-type(even){background-color:#f3f3f3}.hk td{height:100px;}.hk td.line{line-height:75px;}.homeButton button{display: inline-block;line-height: 1;white-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;color: #606266;-webkit-appearance: none;text-align: center;-webkit-box-sizing: border-box;box-sizing: border-box;outline: 0;margin: 0;-webkit-transition: .1s;transition: .1s;font-weight: 500;padding: 12px 36px;font-size: 14px;border-radius: 4px;height: 32px;padding: 8px 12px;font-size: 14px;color: #fff;background-color: #ff436a;border-color: #ff436a;border-radius: 3px;text-transform: none;outline: none;border: none;margin-right:none !important;}.homeButton{display: inline-block;}`
  )

  if (pt === 'home') {
    $('.tcuLAu').prepend(
      '<div class="homeButton wp-s-agile-tool-bar__h-group"><button style="margin-right:10px;" id="94listDownBtn" class="u-button nd-file-list-toolbar-action-item is-need-left-sep u-button--primary u-button--default u-button--small is-has-icon  u-button--danger"><i class="iconfont icon-download"></i><span>94list-laravel</span></button></div>'
    )
    GM_addStyle(
      `.hk th,.hk td{width:108px !important;height:60px !important;}.hk td{height:75px !important;}`
    )
  } else if (pt === 'main') {
    $('.wp-s-agile-tool-bar__header.is-header-tool').prepend(
      '<div class="wp-s-agile-tool-bar__h-group"><button style="margin-right:10px;" id="94listDownBtn" class="u-button nd-file-list-toolbar-action-item is-need-left-sep u-button--primary u-button--default u-button--small is-has-icon  u-button--danger"><i class="iconfont icon-download"></i><span>94list-laravel</span></button></div>'
    )
  }

  const siteUrl = GM_getValue('94list-laravel-site-url')
  const password = GM_getValue('94list-laravel-site-password')

  if (!siteUrl | (siteUrl === 'null')) {
    await Swal.fire({
      title: '请先设置 94list-laravel-site-url',
      html: `<input type="text" id="siteUrl">`
    })
    setLocalStorage('94list-laravel-site-url', document.querySelector('#siteUrl').value)
  }

  const serevrConfig = await request({
    method: 'POST',
    url: siteUrl + '/api/user/getConfig',
    responseType: 'json'
  })
    .then(res => res.response.data)
    .catch(_ => {
      Swal.fire({
        icon: 'error',
        title: '系统提示',
        text: '请求服务器失败!'
      }).then(_ => setLocalStorage('94list-laravel-site-url', null))
    })

  if (serevrConfig.havePassword && !password | (password === 'null')) {
    await Swal.fire({
      title: '请先设置 94list-laravel-site-password',
      html: `<input type="text" id="sitePassword">`
    })
    setLocalStorage('94list-laravel-site-password', document.querySelector('#sitePassword').value)
  }

  const match = /"bdstoken":"(\w+)"/.exec($('html').html())
  if (match === null) {
    Swal.fire({
      icon: 'error',
      title: '系统提示',
      text: '未知错误!'
    }).then(_ => location.reload())
  }
  const bdstoken = match[1]

  const getSelectedList = function () {
    if (pt === 'home') {
      return require('system-core:context/context.js').instanceForSystem.list.getSelected()
    } else if (pt === 'main') {
      let mainList = document.querySelector('.nd-main-list')
      if (!mainList) mainList = document.querySelector('.nd-new-main-list')
      return mainList.__vue__.selectedList
    }
  }

  $('#94listDownBtn').on('click', async function () {
    if ($('tr.selected img[src*="ceH8M5EZYnGhnBKRceGqmaZXPPw2xbO+1x"]').length > 0) {
      Swal.fire({
        icon: 'error',
        title: '系统提示',
        text: '不支持文件夹解析'
      })
      return
    }
    const selectedIds = getSelectedList().map(v => v.fs_id)
    if (selectedIds.length === 0) {
      Swal.fire({
        title: '系统提示',
        text: '请选择需要下载的文件',
        icon: 'error'
      })
      return
    }
    function getRangeCode(len = 6) {
      const orgStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
      let returnStr = ''
      for (let i = 0; i < len; i++) {
        returnStr += orgStr.charAt(Math.floor(Math.random() * orgStr.length))
      }
      return returnStr
    }
    Swal.fire({
      title: false,
      text: '服务器请求中',
      showCloseButton: false,
      showCancelButton: false,
      showConfirmButton: false,
      didOpen: () => Swal.showLoading()
    })
    const pwd = getRangeCode(4)
    const shareLink = await $.ajax({
      method: 'post',
      url: `https://pan.baidu.com/share/set?channel=chunlei&bdstoken=${bdstoken}period=1&pwd=${pwd}&eflag_disable=true&channel_list=%5B%5D&schannel=4&fid_list=[${selectedIds}]`
    })
    if (shareLink.show_msg) {
      Swal.fire({
        title: '系统提示',
        text: shareLink.show_msg,
        icon: 'error'
      })
      return
    }
    const url = shareLink.link
    const shareFileList = await request({
      method: 'post',
      url: siteUrl + '/api/user/getFileList',
      headers: {
        'Content-Type': 'application/json'
      },
      data: JSON.stringify({
        dir: '/',
        url,
        pwd,
        password
      }),
      responseType: 'json'
    }).catch(err => {
      Swal.fire({
        icon: 'error',
        title: '系统提示',
        text: err.response.message
      }).then(_ =>
        err.response.message == '密码不匹配'
          ? setLocalStorage('94list-laravel-site-password', null)
          : location.reload()
      )
    })
    const shareSign = await request({
      method: 'post',
      url: siteUrl + '/api/user/getSign',
      headers: {
        'Content-Type': 'application/json'
      },
      data: JSON.stringify({
        uk: shareFileList.response.data.uk,
        shareid: shareFileList.response.data.shareid,
        password
      }),
      responseType: 'json'
    }).catch(err => {
      Swal.fire({
        icon: 'error',
        title: '系统提示',
        text: err.response.message
      }).then(_ =>
        err.response.message == '密码不匹配'
          ? setLocalStorage('94list-laravel-site-password', null)
          : location.reload()
      )
    })
    const downLinks = await request({
      method: 'post',
      url: siteUrl + '/api/user/downloadFiles',
      headers: {
        'Content-Type': 'application/json'
      },
      data: JSON.stringify({
        fs_ids: selectedIds,
        timestamp: shareSign.response.data.timestamp,
        uk: shareFileList.response.data.uk,
        sign: shareSign.response.data.sign,
        randsk: shareFileList.response.data.randsk,
        shareid: shareFileList.response.data.shareid,
        password
      }),
      responseType: 'json'
    }).catch(err => {
      Swal.fire({
        icon: 'error',
        title: '系统提示',
        text: err.response.message
      }).then(_ =>
        err.response.message == '密码不匹配'
          ? setLocalStorage('94list-laravel-site-password', null)
          : location.reload()
      )
    })
    Swal.close()

    Swal.fire({
      html: `<h3>当前下载UA: ${serevrConfig.userAgent}</h3><div class="hk"><table><thead><tr><th class="line">文件名</th><th class="line">地址</th><th class="line">操作</th></tr></thead><tbody></tbody></table></div>`
    })

    downLinks.response.data.forEach(link => {
      $('.swal2-html-container .hk table tbody').append(`
      <tr>
          <td class="line">${link.server_filename}</td>
          <td>${link.dlink}</td>
          <td><button class="aria" data-dlink="${link.dlink}" data-filename="${link.server_filename}">发送到Aria2</button><button class="idm" data-dlink="${link.dlink}" data-filename="${link.server_filename}">尝试调用IDM</button><button class="copy" data-dlink="${link.dlink}">复制链接</button></td>
      </tr>`)
    })

    $('.hk button.aria').on('click', async function () {
      let aria2Host = GM_getValue('94list-laravel-site-aria2-host')
      if (!aria2Host || aria2Host === 'null') {
        await Swal.fire({
          title: '请先设置 94list-laravel-site-aria2-host',
          html: `<input type="text" id="siteAriaHost">`
        })

        aria2Host = document.querySelector('#siteAriaHost').value
        GM_setValue('94list-laravel-site-aria2-host', aria2Host)
      }

      let aria2Secret = GM_getValue('94list-laravel-site-aria2-secret')

      await request({
        method: 'post',
        url: aria2Host,
        headers: {
          'Content-Type': 'application/json'
        },
        data: JSON.stringify({
          jsonrpc: '2.0',
          id: '94list-laravel-tampermonkey',
          method: 'aria2.addUri',
          params: [
            `token:${aria2Secret}`,
            [$(this).data('dlink')],
            {
              out: $(this).data('filename'),
              header: [`User-Agent: ${serevrConfig.userAgent}`]
            }
          ]
        })
      }).catch(err => alert('请求aria2失败,请检查控制台输出'))
    })

    $('.hk button.idm').on('click', async function () {
      const blob = await request({
        method: 'get',
        url: $(this).data('dlink'),
        responseType: 'blob',
        headers: { 'User-Agent': serevrConfig.userAgent }
      })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = $(this).data('filename')
      a.click()
      URL.revokeObjectURL(url)
    })

    $('.hk button.copy').on('click', function () {
      GM_setClipboard($(this).data('dlink'), 'dlink')
    })
  })
})