Greasy Fork

Greasy Fork is available in English.

豆瓣鱼

在豆瓣读书页面展示多抓鱼价格

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         豆瓣鱼
// @namespace    wong2
// @version      1.2
// @description  在豆瓣读书页面展示多抓鱼价格
// @author       wong2
// @match        https://book.douban.com/subject/*
// @match        https://www.duozhuayu.com/books/*
// @require      https://cdn.jsdelivr.net/combine/npm/[email protected],npm/[email protected]/build/qrcode.min.js
// @grant        GM.xmlHttpRequest
// ==/UserScript==

(function () {

  var key = 'DkOliWvFNR7C4WvR'.split('').map(function(c) {
    return c.charCodeAt()
  })
  var iv = 'GQWKUE2CVGOOBKXU'.split('').map(function(c) {
    return c.charCodeAt()
  })
  var aesCfb = new aesjs.ModeOfOperation.cfb(key, iv)

  function encrypt(text) {
    var textBytes = aesjs.utils.utf8.toBytes(text)
    var encryptedBytes = aesCfb.encrypt(textBytes)
    return aesjs.utils.hex.fromBytes(encryptedBytes)
  }

  function getCustomRequestHeaders() {
    var timestamp = Date.now()
    var userId = 0
    var securityKey = Math.floor(100000000 * Math.random())
    var token = encrypt([timestamp, userId, securityKey].join(':'))
    var requestId = [userId, timestamp, Math.round(100000 * Math.random())].join('-')
    return {
      'x-timestamp': timestamp,
      'x-security-key': securityKey,
      'x-user-id': userId,
      'x-request-token': token,
      'x-request-misc': '{"platform":"browser"}',
      'x-api-version': '0.0.3',
      'x-request-id': requestId,
    }
  }

  function searchBooksByTitle(title) {
    return new Promise(function(resolve, reject) {
      GM.xmlHttpRequest({
        method: 'GET',
        url: 'https://www.duozhuayu.com/api/search?type=normal&q=' + encodeURIComponent(title),
        headers: getCustomRequestHeaders(),
        onload: function(response) {
          var resp = JSON.parse(response.responseText)
          var books = resp.data.filter(function(item) {
            return item.type === 'book'
          }).map(function(item) {
            return item.book
          })
          resolve(books)
        },
      })
    })
  }

  function searchBook(title, isbn) {
    return searchBooksByTitle(title).then(function(books) {
      if (!isbn) {
        return books[0]
      }
      return books.filter(function(book) {
        return book.isbn13 == isbn
      })[0]
    })
  }

  function showInSidebar(book) {
    var price = book.price
    var goods = book.goods
    if (goods.length) {
      price = goods[goods.length - 1].price
    }
    var link = 'https://www.duozhuayu.com/books/' + book.id
    var html = [
      '<div class="gray_ad">',
        '<h2>',
          '<span>在多抓鱼有售</span>',
          '&nbsp;·&nbsp;·&nbsp;·&nbsp;·&nbsp;·&nbsp;·',
        '</h2>',
        '<div class="market-banner">',
          '<span class="title">' + (goods.length ? '库存' + goods.length + '册' : '缺货') + '&nbsp;</span>',
          '<span class="price">' + (price / 100).toFixed(2) + '元起</span>',
          '<span class="price"> <del>' + (book.originalPrice / 100).toFixed(2) + '元</del> </span>',
          '<span class="actions">',
            '<a class="buy-btn buy" target="_blank" href="' + link + '">去看看</a>',
          '</span>',
        '</div>',
      '</div>',
    ].join('')
    var sidebar = document.querySelector('.aside')
    sidebar.innerHTML = html + sidebar.innerHTML
  }

  function runInDoubanPage() {
    var title = document.querySelector('h1 span').innerText
    var matches = document.getElementById('info').innerText.match(/\d{13}/)
    var isbn = matches && matches[0]
    searchBook(title, isbn).then(function(book) {
      if (book) {
        showInSidebar(book)
      }
    })
  }

  function replaceDuozhuayuQRCode() {
    QRCode.toDataURL(location.href, function(err, dataUrl) {
      var img = document.body.querySelector('.Modal-body img')
      img.src = dataUrl
    })
  }

  function runInDuozhuayuPage() {
    var observer = new MutationObserver(function(mutations) {
      for (var i = 0; i < mutations.length; i++) {
        var nodes = mutations[i].addedNodes
        for (var j = 0; j < nodes.length; j++) {
          var node = nodes[j]
          if (node.querySelector('.Modal-body')) {
            return replaceDuozhuayuQRCode()
          }
        }
      }
    })
    observer.observe(document.body, { childList: true })
  }

  if (/book.douban.com/.test(location.href)) {
    runInDoubanPage()
  } else {
    runInDuozhuayuPage()
  }

})()