Tsumino Tweaks

Offline tag search support and nhentai redirection when clicking on the book cover on a book information page

Tính đến 25-05-2019. Xem phiên bản mới nhất.

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

Bạn sẽ cần cài đặt một tiện ích mở rộng như Tampermonkey hoặc Violentmonkey để cài đặt kịch bản này.

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.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

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        Tsumino Tweaks
// @description Offline tag search support and nhentai redirection when clicking on the book cover on a book information page
// @namespace   xspeed.net
// @version     2
// @icon        https://static.nhentai.net/img/logo.650c98bbb08e.svg
// @match       *://www.tsumino.com/*
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_xmlhttpRequest
// ==/UserScript==

(function() {
  'use strict';
  
  var jsonError = function(data) {
    alert(JSON.stringify(data));
  }
  
  if (location.href.indexOf('/Book/Info/') != -1) {
    
    var title = $('.row>.book-title').text();
    
    var ix = title.indexOf('/');
    if (ix != -1) {
      title = title.substring(0, ix);
    }
    
    ix = title.indexOf('|');
    if (ix != -1) {
      title = title.substring(0, ix);
    }
    
    var url = 'https://nhentai.net/search/?q=english+' + title.replace(/[^a-z0-9+]+/gi, '+');
    var elem = $('.book-page-cover > a[href^="/Read/View/"]');
    
    elem.attr('href', '#');
    elem.unbind('click');
    elem.click(function() {
      var onerror = function() {
        location.assign(url);
      }
      
      var onload = function(resp) {
        var respDoc = $(resp.responseText);
        var cover = respDoc.find('.cover');
        if (cover && cover.attr('href')) {
          location.assign('https://nhentai.net' + cover.attr('href') + '1/');
        }
        else {
          onerror();
        }
      };

      GM_xmlhttpRequest({ method: "GET", url: url, onload: onload, onerror: onerror });
    });
  }
  
  else {
    
    var tagSearch = $('#tagDataSearch');
    if (tagSearch.length) {
      
      var tagMode = false;
      var tagData = GM_getValue('tagData', '[]');
      var tagList = JSON.parse(tagData);
      var oldAdapter = null;
      
      var offlineQuery = function(params, callback) {
        var res = [];
      
        if (params && params.term && params.term.length != 0) {
          var term = params.term.toLowerCase();
          
          for (var tag of tagList) {
            if (tag[0].toLowerCase().indexOf(term) != -1) {
              res.push(tag[0]);
              if (res.length > 4) break;
            }
          }
        }
        
        callback({ results: res.map(x => ({ key: 0, text: x, id: x })) });
      };
      
      tagSearch.next().html('<button id="tagsRefresh" type="button" class="book-read-button" style="padding: 5px 10px; margin: 5px 0;">Refresh tag list</button> Loaded tags: <span id=tagsCount>0</span>')
      
      $('#tagsCount').text(Object.keys(tagList).length);

      $('#selTagType').change(function() {
        
        var selData = $('#selTagValue').data('select2');
        
        if ($(this).val() == 1 && !tagMode) {
          oldAdapter = selData.dataAdapter.query;
          tagMode = true;
          selData.dataAdapter.query = offlineQuery;
        }
        else if (tagMode) {
          selData.dataAdapter.query = oldAdapter;
          tagMode = false;
        }
        
      });
      
      setTimeout(function() {
        $('#selTagValue').data('select2').dataAdapter.query = offlineQuery;
        tagMode = true;
      }, 1000);
      
      $('#tagsRefresh').click(function() {
        
        this.disabled = true;
        $('#tagsCount').text('0...')
        
        var parseTable = function(doc) {
          doc.find('.table.table-striped').find('tr').each(function() {
            var row = $(this).children('td');
            var id = row.first().text().trim();
            if (id.length > 0) tagList.push([id, parseInt(row.eq(1).text())]);
          });
        };
        
        var onload = function(resp) {
          var respDoc = $(resp.responseText);
          
          tagList = [];
          
          var hrefSet = new Set();
          respDoc.find('a[href*="/Tags/Index/1/"]').each(function() {
            var ix = this.href.indexOf('?');
            if (ix != -1) hrefSet.add(this.href);
          });
          hrefSet = Array.from(hrefSet);
          
          var process = function(resp) {
            parseTable($(resp.responseText));
            
            var next = hrefSet.pop();
            if (next) {
              $('#tagsCount').text(Object.keys(tagList).length + '...');
              
              GM_xmlhttpRequest({ method: "GET", url: next, onload: process, onerror: jsonError });
            }
            else {
              tagList.sort((a, b) => b[1] - a[1]);
              
              $('#tagsCount').text(Object.keys(tagList).length);
              GM_setValue('tagData', JSON.stringify(tagList));

              $('#tagsRefresh').prop('disabled', false);
            }
          };
          
          process(resp);
          
        };
        
        GM_xmlhttpRequest({ method: "GET", url: 'https://www.tsumino.com/Tags', onload: onload, onerror: jsonError });
        
      });
    }
  }
})();