NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Ficscript(Ficbook.net) // @author Dimava // @include https://ficbook.net/* // @include http://ficbook.net/* // @version 1 // @grant none // ==/UserScript==// ==UserScript== // @name Ficscript(Ficbook.net) // @author Dimava // @include https://ficbook.net/* // @include http://ficbook.net/* // @version 1.4 // @grant none // ==/UserScript== function setHiddenAuthors(authorsId) { localStorage.setItem('ficbookFilter.hiddenAuthors', JSON.stringify(authorsId) ) } function setHiddenWritings(writingsId) { localStorage.setItem('ficbookFilter.hiddenWritings', JSON.stringify(writingsId) ) } function getHiddenAuthors() { var str = localStorage.getItem('ficbookFilter.hiddenAuthors') return str ? JSON.parse(str) : [ ] } function getHiddenWritings() { var str = localStorage.getItem('ficbookFilter.hiddenWritings') return str ? JSON.parse(str) : [ ] } function createEIbuttons() { // Create export button var $exportBtn = $('<div class="exportBtn"></div>').attr('title', 'Экспортировать бан-список').html('E').appendTo(document.body) $exportBtn.click(function () { var data = JSON.stringify({ authors: getHiddenAuthors(), writings: getHiddenWritings() }) var $a = $('<a/>').attr('href', 'data:text/plain,' + data).attr('download', 'ficbook-filters.json').appendTo(document.body) $a[0].click() $a.remove() }) // Create import button var $fileInput = $('<input type="file"/>').css({ position: 'absolute', top: '-10000px', left: '-10000px' }).appendTo(document.body) var $importBtn = $exportBtn.clone().css({ right: '110px' }).attr('title', 'Импортировать бан-список').html('I').appendTo(document.body) $importBtn.click(function () { $fileInput.click() }) $fileInput.change(function () { try { var fileReader = new FileReader() fileReader.readAsText(this.files[0]) fileReader.onloadend = function () { try { var json = JSON.parse(this.result) } catch (e) { alert('Ошибка. Файл бан-списка поврежден.\n' + 'По умолчанию это обычно "ficbook-filters.json".\n' + 'Может быть, вы выбрали какой-то другой файл?') return } setHiddenWritings(json.writings) setHiddenAuthors(json.authors) alert('Импортировано ' + json.writings.length + ' произведений и ' + json.authors.length + ' авторов.\n' + 'Обновите страницу чтобы применить фильтры немедленно.') } } catch (e) { alert('Ошибка. Файл бан-списка поврежден.') console.error(e.toString()) } }) console.log('createEIbuttons applied'); } // Hide writings function hideFics() { // Load hidden authors and writings var hiddenAuthors = getHiddenAuthors() var hiddenWritings = getHiddenWritings() // Hide writings $('.fanfic_thumb').each(function () { var $title = $('a.title', this), title = $title.text(), writingId = parseInt($title.attr('href').match(/\/(\d+)$/) [1], 10), text = $('b:eq(1)', this).closest('small').text(), pageCount = parseInt(text.match(/(\d+)\s+страниц/) [1]), slash = text.indexOf('(яой)') >= 0, writingHidden = hiddenWritings.indexOf(writingId) >= 0, $author = $('>tbody>tr:eq(1)>td:eq(0) a:eq(0)', this), authorId = parseInt($author.attr('href').match(/\/(\d+)$/) [1], 10), authorHidden = hiddenAuthors.indexOf(authorId) >= 0, $thumb = $(this), $ficbox = $thumb.closest('.ficbox') function hideThisFic($hideReason) { $resurrectBtn = $ficbox.addClass('hiddenfic').prepend('<tr class="rsrbox"><td colspan=9></td></tr>').find('td:first').html('<span class="rsrBtn">' + $hideReason + '</span> <a href="' + $title.attr('href') + '">"' + title + '"</a> от <a href="' + $author.attr('href') + '">' + $author.text() + '</a>.').find('span').attr('title', 'Да ВОССТАНЬ!'); $ficbox.children().css('background-color', 'rgba(255,255,255,0.5)').css('transition', 'background-color 1s').find('>tr:not(.rsrbox)').hide(); $resurrectBtn.hover(function () { $(this).parents('.ficbox').find('>*>tr:not(.rsrbox)').show(); }, function () { $(this).parents('.ficbox').find('>*>tr:not(.rsrbox)').hide() }).click(function () { if (authorHidden) { hiddenAuthors = getHiddenAuthors() // could be updated on the other tab hiddenAuthors.splice(hiddenAuthors.indexOf(authorId), 1) setHiddenAuthors(hiddenAuthors) } if (writingHidden) { hiddenWritings = getHiddenWritings() // could be updated on the other tab hiddenWritings.splice(hiddenWritings.indexOf(writingId), 1) setHiddenWritings(hiddenWritings) } $(this).parents('.ficbox').removeClass('hiddenfic').children().css('background-color', 'transparent').find('tr').show().end().find('.rsrbox').remove(); return false }) } if (writingHidden) hideThisFic('Отфильтрован фанф') else if (authorHidden) hideThisFic('Отфильтрован по автору') else if (slash) hideThisFic('Отфильтрован <i>слеш</i>') else if (pageCount < 30) hideThisFic('Отфильтрован по длине (' + pageCount + ')') // Add removing writing button var $rmWritingBtn = $('<span class="removeFic"></span>').attr('title', 'Забанить это произведение').html('✖') $title.parent().append($rmWritingBtn) $rmWritingBtn.click(function () { alert() hiddenWritings = getHiddenWritings() // could be updated on the other tab hiddenWritings.push(writingId) setHiddenWritings(hiddenWritings) hideThisFic('Отфильтрован фанф') return false }) // Add removing author button var $rmAuthorBtn = $('<span class="removeFic removeAuthor"></span>').attr('title', 'Забанить ВСЕ произведения этого автора').html('✖') $title.closest('.ficbox').find('small:first a:first').after($rmAuthorBtn); $rmAuthorBtn.click(function () { hiddenAuthors = getHiddenAuthors() // could be updated on the other tab hiddenAuthors.push(authorId) setHiddenAuthors(hiddenAuthors) hideThisFic('Отфильтрован по автору') return false }) }) console.log('hideFics applied'); } // // // // location detector v1 function getLoc() { var a = window.location.pathname.split('/'); var b = window.location.href.split('='); var c = ''; for (i = 1; i < a.length; i++) { c += (a[i].charAt(0) <= '9' && a[i].charAt(0) >= '0') ? '0' : a[i].charAt(0); } for (i = 1; i < b.length; i++) { c += (b[i].charAt(0) <= '9' && b[i].charAt(0) >= '0') ? '0' : b[i].charAt(0); } return c; } function testLoc(a) { var c = getLoc() for (var i = 0; i < arguments.length; i++) { if (arguments[i] == c) return true; } return false; } // // ficboxes classifier v1 : adds .ficbox class function classFics() { if ($('table.fanfic_thumb').length > 0) { if (testLoc('hcu')) { // create ficboxes $('table:has(.fanfic_thumb):not(:has(h1))').addClass('ficbox'); } else { $('table.fanfic_thumb').addClass('ficbox'); } $('.ficbox:has(.new_parts_in_title)').addClass('newfic'); // select updated $('table[style="background-color: #ffff99"]').addClass('newfic').attr('style', ''); return true; } else { return false; } console.log('classFics applied'); } // // everything compressor function compressFics() { // chapter TRASHHIDER v1 if (testLoc('r00')) { if ($('.fanfic_reward_list').length > 15) { // hide 16+ rewards $('.fanfic_reward_list:eq(0)').html('x' + $('.fanfic_reward_list:gt(0)').length); $('.fanfic_reward_list:gt(0)').hide(); $('.fanfic_reward_list').parent().find('br:gt(1)').remove(); } $('.give_reward_fic').hide(); // hide reward giver $('.public_beta_info').hide(); // hide beta info $('hr:first').nextUntil('table').css('display', 'inline').css('padding-right', '0'); // collapce font setter $($('.choose_font').contents().filter(function () { return this.nodeType == 3; })).remove(); $('hr:first').nextUntil('table').addClass('hoverVisible').find('br').hide(); } // contents compressor if (testLoc('r0')) { $('<div class="partListContainer"><div></div></div>').insertAfter($('.part_list').prev().prev()).children().append($('.part_list').prev().text($('.main_cell h1:first').text()).css('margin', '5px')).append('<h6>' + $('.main_cell td:last span.urlize:first').html() + '</h6>').parent().append($('.part_list').prepend('<div class="partListTop">^ ^ ^</div>').append('<div class="partListBottom">^ ^ ^</div>')); } console.log('compressFics applied'); } // // checker : adds checkboxes to open multiple fics at once function checkFics() { $('.ficbox>*>tr:has(.title)').append('<td align="right" style="width: 30px;"><input type="checkbox" class="openAll"></td>'); $('.ficbox td[style]:not([width])').attr('colspan', '2') $('.openAll').click(function () { $('#openAll').show(); $('.openAll').css('opacity', '1') }); $('<button id="openAll">Открыть<br>выбранные</button>').appendTo($('body')).click(function () { $('input.openAll:checked').each(function () { window.open($(this).parent().parent().find('.title') [0].href, '_blank' ); }); $('.ficbox').has('input.openAll:checked').children().css('background-color', 'rgba(127,255,0,0.3)'); }); console.log('checkFics applied'); } // // load new collections v1 : shows new fics in updated collection (/home/collections?type=other) function loadCols(callback) { collectionsNotLoaded = $('tr[style] .collection_thumb').length; if (collectionsNotLoaded == 0) { callback() } $('tr[style] .collection_thumb').each(function () { $(this).after('<div style="display:none">!div!</div>').next().load($(this).find('.title a') [0].href, function () { $(this).after($(this).find('.fic_and_collection[style]').each(function () { $(this).append($(this).children().eq(0)) }) ); $(this).html('!!!div!!!'); collectionsNotLoaded--; if (collectionsNotLoaded == 0) { callback() } } ) }) console.log('loadCols applied'); } // // keypress handler v2 function handleKeys() { $(document).keydown(function (e) { var tag = e.target.tagName.toLowerCase(); var keyStr = (e.ctrlKey ? '[Ctrl] + ' : '') + (e.shiftKey ? '[Shift] + ' : '') + '[' + (typeof e.key == 'undefined' ? ('#' + e.which) : e.key) + ']' + ' pressed' + ((tag != 'input' && tag != 'textarea') ? '' : ' inside input') + ((getSelectedText() == '') ? '' : ' with "' + getSelectedText() + '" selected'); var keyCode = (e.ctrlKey ? 'c' : '') + (e.shiftKey ? 's' : '') + ('#' + e.which) + ((tag != 'input' && tag != 'textarea') ? '' : 'i') + ((getSelectedText() == '' || getSelectedText == '\n') ? '' : '{}'); console.log(keyCode + ' : ' + keyStr); switch (keyCode) { case 's#37': // s#37 : [Shift] + [ArrowLeft] pressed {open prev or first chap} if (testLoc('r0') && $('.part_list a:first') [0]) window.location.href = $('.part_list a:first') [0].href; else if (testLoc('r00') && $('td[width="45%"]:first a') [0]) document.location.href = $('td[width="45%"]:first a') [0].href; break case 's#39': // s#39 : [Shift] + [ArrowRight] pressed {open next ol last chap} if (testLoc('r0') && $('.part_list a:last') [0]) window.location.href = $('.part_list a:last') [0].href; else if (testLoc('r00') && $('td[width="45%"]:last a') [0]) document.location.href = $('td[width="45%"]:last a') [0].href; break case 's#38': // s#38 : [Shift] + [ArrowUp] pressed {open contents} if (testLoc('r00') && $('td[align="center"] a') [0]) document.location.href = $('td[align="center"] a') [0].href; break case '#39': // #39 : [ArrowRight] pressed {open next chap if read} if (testLoc('r00') && $('td[width="45%"]:last a') [0] && ($('td[width="45%"]:last a') [0].getBoundingClientRect().top - window.innerHeight < 163)) document.location.href = $('td[width="45%"]:last a') [0].href; break } }); console.log('handleKeys applied'); } // // scroll : scrolls page down to somewhere function scrollFic() { if (testLoc('r0')) { $('.part_list').scrollTop(9999); $('.partListContainer') [0].scrollIntoView(); } } // // style function styleFics() { var styleStr = '<style>' + '.ficbox{margin:15px 0}' + '.newfic{background-color:#ff9;}' + '.rsrbox {color:#888; transition: background-color 0.3s; background-color: rgba(255,255,255,0.3);}' + '.rsrBtn:hover {color:red;cursor:pointer}' + '.rsrbox:hover {background-color: white}' + '.hiddenfic{border-collapse:collapse;margin:0}' + '.hiddenfic>*>tr:not(.rsrbox) {opacity: 0.5; background-color: white}' + '.openAll{opacity:0.1; transition: opacity 0.3s;}' + '.openAll:hover {opacity: 1 !important}' + '#openAll{display: none; position: fixed; right: 270px; bottom: 0px}' + '.exportBtn{position: fixed; bottom: 20px; right: 80px; color: white; background-color: rgba(0, 0, 0, 0.52); border-radius: 3px; width: 25px; text-align: center; height: 24px; line-height: 24px; cursor: pointer; font-size: 18px;opacity:0.1;transition: opacity 0.3s;}' + '.exportBtn:hover{opacity:1}' + '.removeFic{cursor: pointer; color: white; font-weight: bold; display: inline-block; background: rgb(136, 1, 1); border-radius: 10px; height: 20px; line-height: 19px; width: 20px;text-align: center;opacity:0.1;transition: opacity 0.3s;}' + '.removeAuthor{height: 14px; width: 14px; line-height: 14px; font-size: 12px; margin-left: 3px}' + '.removeFic:hover{opacity:1}' + '.hiddenfic .removeFic{display: none;}' + '.partListContainer{max-height:98vh;display:flex;flex-direction:column;box-shadow:0px 0px 2px inset,0px 0px 2px;margin-right:10px;padding:0px 5px 5px 0}' + '.partListBottom{font-size: 15px; height: 10px; overflow: hidden; text-align: center;}' + '.partListTop{font-size: 15px; height: 11px; overflow: hidden; text-align: center;transform: rotate(180deg);}' + '.part_list{overflow-y: auto}' + 'h6{margin:0;padding: 0 15px 10px 15px}' /*!!!*/ + 'table{border-collapse:collapse}' /*!!!*/ + 'td{padding-top: 0 !important;padding-bottom: 0 !important;}' + '.hoverVisible{opacity:0.1;transition: opacity 0.3s;}' + '.hoverVisible:hover{opacity:1}' + '</style>' $('<style></style>').appendTo($('head')).html(styleStr); console.log('styleFics applied'); } // // calls function callFicscript() { console.log('ficscript start'); styleFics(); loadCols(function () { classFics(); if (testLoc('p', 'hc', 'hco', 'hcu', 'c0', 'c0a', 'c0a0', 'c0u')) { createEIbuttons(); hideFics(); } //removethis /* if (testLoc('hf')) { $('.new_top').each(function () { window.open(this.href, '_blank'); }) }*/ checkFics(); compressFics(); handleKeys(); scrollFic(); }) // unsafeWindow.callFicscript = callFicscript; console.log('ficscript end') } // callFicscript();