NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name HF Extensions // @author Sakuto // @namespace http://www.sakuto.be // @description Add a lot of new functionality to improve experience on HackForums // @include *hackforums.net/* // @version 0.57 // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_notification // @grant GM_openInTab // @grant GM_addStyle // @grant GM_getResourceText // @require https://raw.github.com/sizzlemctwizzle/GM_config/master/gm_config.js // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js // @require http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js // ==/UserScript== // == To do List == // - Supprimer le tupple dans addink // - Optimiser chargement des resultats via un buffer // - Ignorer certaines catégories // - Ignorer les sujets fermés // - Ajout de template de post automatique // - Afficher les templates au dessus de la zone de post // - Scammer database -> Application directement sur la userbar // - Implémenter bouton de dons ? // - Ajouter highlight de code // == Fin To Do == // - Add link to reputation given page var predefinedStyle = "\ #HFU_config {background:#333; color:#CCC; font-size:14px; } \ #HFU_config_header {color:#FFF; padding-bottom: 20px;} \ #HFU_config .section_desc {background:#072948; color:#FFF; border:none; font-size:14px;} \ #HFU_config .section_header {display:none !important;} \ #HFU_config .config_var {text-align:left;} \ #HFU_config .field_label {font-size:14px; font-weight:normal} \ #HFU_config * {font-family:Verdana, Arial, Sans-Serif; font-weight:normal}\ #HFU_config label { display: inline-block; width: 600px;}\ #HFU_config input[type=radio] { display: inline-block; }\ "; var linkList = []; if(GM_getValue('ignoredSignature') == undefined) { GM_setValue('ignoredSignature', ['-1']); } GM_config.init( { 'id': 'HFU_config', 'title': 'HF Extensions - Configuration', 'fields': { // Search pages 'optimizeSearch': { 'section': ['', 'Search'], 'labelPos': 'left', 'label': 'Optimize the search result page', 'type': 'checkbox', 'default': true }, 'numberOfPageToRetrieve': { 'labelPos': 'left', 'label': 'Number of Page To retrieve (5 maximum)', 'type': 'int', 'default': 4, 'max': 5 }, 'hideNoNewMessage': { 'labelPos': 'left', 'label': 'Hide thread wihout new message?', 'type': 'checkbox', 'default': false, }, 'hideMessageTitle': { 'labelPos': 'left', 'label': 'Hide the message title', 'type': 'checkbox', 'default': false, }, // Reputation Option 'boolReputationCheck': { 'section': ['', 'Reputation'], 'labelPos': 'left', 'label': 'Get Notification when you receive a new rep ?', 'type': 'checkbox', 'default': true }, 'delayForReputationCheck': { 'label': 'If precedent is check : Number of minutes between check on reputation', 'labelPos': 'left', 'type': 'int', 'default': 2, 'min': 1 }, 'addLinkToReputation': { 'label': 'Do you want to add link to reputation message', 'labelPos': 'left', 'type': 'checkbox', 'default': true }, // Messages Options 'addCounterForMessage': { 'section': ['', 'Messages'], 'labelPos': 'left', 'label': 'Add a counter for the characters below textarea ?', 'type': 'checkbox', 'default': true }, 'quoteToPM': { 'labelPos': 'left', 'label': 'Add an option to send a PM with the quoted message', 'type': 'checkbox', 'default': false }, 'enableHighlight': { 'labelPos': 'left', 'label': 'Enable custom highlight for code tag', 'type': 'checkbox', 'default': true }, 'removeSignature': { 'labelPos': 'left', 'label': 'Allow removance of some users signature', 'type': 'checkbox', 'default': true } }, 'css': predefinedStyle }); // Main function $(function() { init(); $("head").append('<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/monokai.min.css" rel="stylesheet" type="text/css">'); if(GM_config.get('enableHighlight')) { $('div.codeblock code').each(function(i, block) { hljs.highlightBlock(block); }); } // Add a counter below every textarea to show how many characters you writed if(GM_config.get('addCounterForMessage')) { if(window.location.href.indexOf('showthread') > 0) addCounterForCharacters('#message'); if(window.location.href.indexOf('newreply') > 0) addCounterForCharacters('#message_new', '.messageEditor'); } // Send a notification when you receive new reputation if(GM_config.get('boolReputationCheck')) { if(dateObject.getTime() >= GM_getValue('reputationTimeout')) { GM_setValue('reputationTimeout', dateObject.getTime() + 60 * GM_config.get('delayForReputationCheck')); checkReputation(); } } // Add link to reputation message if(GM_config.get('addLinkToReputation')) { if(window.location.href.indexOf('reputation.php') > 0 || window.location.href.indexOf('repsgiven.php') > 0) { $("[class^=trow_reputation_]").each(function() { this.innerHTML = transformIntoUrl(this.innerHTML); }); } } // Merge many pages of results as one and hide duplicate message if(GM_config.get('optimizeSearch')) { if(window.location.href.indexOf('action=results') > 0) { console.log("Start optimizing"); if(document.referrer.indexOf('member.php') < 0) { console.log("Optimizing"); optimizeSearch(); } } } // Add a Quote To PM button if(GM_config.get('quoteToPM')) { if(window.location.href.indexOf('showthread.php') > 0) { addQuoteToPM(); } if(window.location.href.indexOf('private.php?action=send') > 0) { if(GM_getValue('storedMessage') != null) { $('#message_new').val(GM_getValue('storedMessage')); GM_setValue('storedMessage', null); } } } // Remove some users signature if(GM_config.get('removeSignature')) { if(window.location.href.indexOf('showthread.php') > 0) { $(' <a href="#" class="bitButton removeSignature">Delete Sig</a>').appendTo('.post_management_buttons'); removeSignatureFromMessage(); } $('.removeSignature').on('click', function(e) { $selectedMessage = $(this).parent().parent().parent().parent(); var authorId = getDataFromUrl('uid', $('tr:nth-child(2) strong .largetext a', $selectedMessage).attr('href')); var ignored = GM_getValue('ignoredSignature'); ignored.push(authorId); GM_setValue('ignoredSignature', ignored); removeSignatureFromMessage(); e.preventDefault(); }); } }); /******************************/ /* Main Function */ /******************************/ function init() { $("#panel a:contains('Log Out')").after(' — <a href="#" id="HFUConfig">HFU Config</a>'); dateObject = new Date(); if(GM_getValue('userId') === undefined) { GM_setValue('userId', getDataFromUrl('uid', $("#panel a:first").attr('href'))); } if(GM_getValue('reputationTimeout') === undefined) { GM_setValue('reputationTimeout', dateObject.getTime()); } // Capture click on configuration $("#HFUConfig").on('click', function(e) { GM_config.open(); e.preventDefault(); }); } function addQuoteToPM() { $('<a href="#" class="bitButton quoteToPM">Quote to PM</a>').appendTo('.post_management_buttons'); $('.quoteToPM').on('click', function(e) { $selectedMessage = $(this).parent().parent().parent().parent(); var authorId = getDataFromUrl('uid', $('tr:nth-child(2) strong .largetext a', $selectedMessage).attr('href')); GM_setValue('storedMessage', '[quote]' + $('tr:nth-child(3) .post_body', $selectedMessage).text().trim() + '[/quote]'); GM_openInTab(window.location.origin + '/private.php?action=send&uid=' + authorId + '&subject=Answer%20to%20one%20of%20your%20message'); e.preventDefault(); }); } function removeSignatureFromMessage() { $("#posts table").each(function() { var authorId = getDataFromUrl('uid', $('tr:nth-child(2) strong .largetext a', this).attr('href')); if(authorId != undefined) { if(GM_getValue('ignoredSignature').indexOf(authorId) != -1) { $('.post_content div', this)[1].remove(); $('.post_content hr', this).remove(); } } }); } function optimizeSearch() { actualPage = (getDataFromUrl('page')) ? getDataFromUrl('page') : 1; promiseArray = []; $("table:nth-child(2) tr:gt(1)").empty(); for(var page = ((actualPage*GM_config.get('numberOfPageToRetrieve')) - GM_config.get('numberOfPageToRetrieve')); page < actualPage * GM_config.get('numberOfPageToRetrieve'); page++) { promiseArray.push(retrieveContentFromUrl(window.location.href + "&page=" + page)); } Promise.all(promiseArray).then(function(results) { for(var page = 0; page < results.length; page++) { retrieveLinkFromContent($(results[page])); } }); } // Retrieve all the link from a content given. function retrieveLinkFromContent(content, adresse) { var clonedLink; $("table:nth-child(2) tr:gt(1)", content).each(function() { clonedLink = $(this).clone(); this.remove(); if(addList($("td:nth-child(3) a:nth-child(1)", this).text(), $("td:nth-child(3) a:nth-child(1)", this).attr('href')) === 0) { if($(" > * ", clonedLink).length > 1) { if(GM_config.get("hideNoNewMessage")) { if($("td:nth-child(1) img", this).attr('src') != "http://hackforums.net/images/modern_bl/dot_folder.gif") if($("td:nth-child(1) img", this).attr('src') != "http://hackforums.net/images/modern_bl/dot_lockfolder.gif") if($("td:nth-child(1) img", this).attr('src') != "http://hackforums.net/images/modern_bl/dot_hotfolder.gif") $("table:nth-child(2)").append(changeLinkToLastPost(clonedLink)); } else { $("table:nth-child(2)").append(changeLinkToLastPost(clonedLink)); } } } }); } // Add a link to the list if it's not yet in it. function addList(title, link) { for(var j = 0; j < linkList.length; j++) { if(linkList[j].urlTitle === title) { return 1; } } linkList.push({urlTitle: title, urlLink: link}); return 0; } // Return Promise of the content of the passed URL function retrieveContentFromUrl(url) { return new Promise(function(resolve, request) { GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { resolve(response.responseText); } }); }); } function checkReputation() { var reputationPage = retrieveContentFromUrl(window.location.origin + "/reputation.php?uid=" + GM_getValue('userId'), 1); reputationPage.then(function(result) { var lastReputationReceived = $("td [class^=trow_reputation_]", result).first().parent().parent(); var userReputation = $(".repvoteleft", lastReputationReceived).text(); var reasonReputation = $(".repvotemid", lastReputationReceived).text(); var dateReputation = $(".repvoteright", lastReputationReceived).text(); if(GM_getValue('lastReputation') != reasonReputation && reasonReputation != "") { GM_notification(reasonReputation + "\r\n" + dateReputation, "You received a new Reputation from " + userReputation, null, function() { GM_openInTab(window.location.origin +"/reputation.php?uid=" + GM_getValue('userId')) }); GM_setValue('lastReputation', reasonReputation); } }); } function addCounterForCharacters(textarea, divToAppend) { divToAppend = (divToAppend == null) ? textarea : divToAppend; $(divToAppend).after('<div id="messageCounter"><span>0</span>/25 Characteres needed</div><br>'); $(textarea).on('keyup', function(e) { $("#messageCounter span").html(this.value.length); }); } /******************************/ /* Global Function */ /******************************/ // Add the lastPost action to the url on the node passed function changeLinkToLastPost(elementNode) { if(GM_config.get("hideMessageTitle")) { var threadTitle = $("td:nth-child(3) span", elementNode).html(); if(threadTitle != null) { threadTitle = threadTitle.split("<br>").shift(); $("td:nth-child(3) span", elementNode).html(""); $("td:nth-child(3)", elementNode).html(threadTitle); } } var _href = $("td:nth-child(3) a:nth-child(1)", elementNode).attr('href'); $("td:nth-child(3) a:nth-child(1)", elementNode).attr('href', _href + "&action=lastpost"); return elementNode; } // Allow you to retrieve get parameter from URL function getDataFromUrl(VarSearch, url){ var SearchString = (url == null) ? window.location.search.substring(1) : url; var VariableArray = SearchString.split('&'); for(var i = 0; i < VariableArray.length; i++){ var KeyValuePair = VariableArray[i].split('='); if(KeyValuePair[0] == VarSearch){ return KeyValuePair[1]; } } } // Detect and transform into a clickable link every valid URL in a passed content function transformIntoUrl(text) { if(text.indexOf('img src') > 0) { return text; } var urlRegex = /(https?:\/\/[^\s]+)/g; return text.replace(urlRegex, '<a href="$1">$1</a>'); }