您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show available groups *of all servers* on the homepage, joiner page and inside a group
// ==UserScript== // @name TagPro Groups on Homepage // @version 2.4 // @description Show available groups *of all servers* on the homepage, joiner page and inside a group // @author Ko // @supportURL https://www.reddit.com/message/compose/?to=Wilcooo // @website https://redd.it/no-post-yet // @download https://raw.githubusercontent.com/wilcooo/TagPro-GroupsOnHomepage/master/tpgoh.user.js // @match http://*.koalabeast.com* // @match http://tagpro.gg/ // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @license MIT // @icon https://raw.githubusercontent.com/wilcooo/TagPro-GroupsOnHomepage/master/icon.png // @require https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.0/socket.io.slim.js // @require https://greasyfork.org/scripts/371240/code/TagPro%20Userscript%20Library.js // @connect koalabeast.com // @namespace https://greasyfork.org/users/152992 // ==/UserScript== /* global tagpro, io, tpul */ var short_name = 'groups_on_homepage'; // An alphabetic (no spaces/numbers, preferably lowercase) distinctive name for the script. var version = GM_info.script.version; // The version number is automatically fetched from the metadata. tagpro.ready(function(){ tagpro.scripts = Object.assign( tagpro.scripts || {}, {short_name:{version:version}} ); }); console.log('START: ' + GM_info.script.name + ' (v' + version + ' by ' + GM_info.script.author + ')'); // Userscripts load in the order that they appear in Tamermonkey. // Set this option to true if you want this script to be inserted to // the page above than previously load scripts, instead of below. const insertBefore = false; var settings = tpul.settings.addSettings({ id: short_name, title: "Configure Groups on Homepage", tooltipText: "Groups on Homepage", icon: "https://raw.githubusercontent.com/wilcooo/TagPro-GroupsOnHomepage/master/icon.png", fields: { groups_on_home: { label: 'Show all public groups (worldwide) on the homepage', type: 'checkbox', default: true, }, groups_on_find: { label: 'Show all public groups (worldwide) while finding a game', type: 'checkbox', default: true, }, groups_on_groups: { label: 'Show all public groups (worldwide) on the /groups page, instead of just the current server\'s groups', type: 'checkbox', default: true, }, groups_in_group: { label: 'Show all public groups (worldwide) while in a group', type: 'checkbox', default: true, }, position: { label: 'Position of the groups on the homepage', type: 'select', options: ['top','bottom'], default: 'top', }, interval: { label: 'How often should this script update the groups, so you don\'t have to F5 all the time? Choose an amount of seconds, or set to 0 to never update', type: 'int', min: 0, max: 600, default: 60 }, }, events: { open: function () { // Changing the layout a bit after the config panel is opened... [...this.frame.getElementsByClassName('field_label')].forEach( function(el) { el.classList.remove('col-xs-4'); el.classList.add('col-xs-8'); el.nextElementSibling.classList.remove('col-xs-8'); el.nextElementSibling.classList.add('col-xs-4'); } ); }, save: function() { // Making sure (most) options take effect immediately after a save... position = settings.get("position"); groups_on_home = settings.get("groups_on_home"); groups_on_find = settings.get("groups_on_find"); groups_on_groups = settings.get("groups_on_groups"); groups_in_group = settings.get("groups_in_group"); interval = settings.get("interval"); // Update the position of the groups if necessary: var groups_div = document.getElementById('GroPro-groups'); update_groups(); groups_div.classList.remove('hidden'); if (window.location.pathname === '/' && !groups_on_home || window.location.pathname.match(/^\/groups\/[a-z]{8}$/) && !groups_in_group || window.location.pathname === '/groups' && !groups_on_groups || window.location.pathname === '/games/find' && !groups_on_find ) { groups_div.classList.add('hidden'); } } } }); var position = settings.get("position"), groups_on_home = settings.get("groups_on_home"), groups_on_find = settings.get("groups_on_find"), groups_on_groups = settings.get("groups_on_groups"), groups_in_group = settings.get("groups_in_group"), interval = settings.get("interval"); const servers = ['centra','pi','chord','diameter','origin','sphere','radius','orbit']; // We don't use this api anymore, since anonymous xmlhttpRequests are now possible. //const groups_api = 'https://script.google.com/macros/s/AKfycbxF5kcVoFbqmLlbHB2_nJ_dCRoh2iOXDpFyzAq0Kw2UDjM7qEHf/exec'; var warned = false; function get_groups() {return new Promise(function(resolve,reject) { var parser = new DOMParser(), groups = [], pending = 0; servers.forEach(function(server) { pending ++; GM_xmlhttpRequest({ url: 'http://tagpro-'+server+'.koalabeast.com/groups/', anonymous: true, onload: done, onerror: done, timeout: 5000, context: server, }); }); function done(response){ pending --; if (response.finalUrl.includes('groupAuth')) { //if (!warned) warned = tagpro.helpers.displayError("Sorry, your IP address has been flagged - so the GroupsOnHome script can't yet show you the groups. No worries though, I'm working on a fix for this."); console.error("Sorry, your IP address has been flagged - so the GroupsOnHome script can't yet show you the groups. No worries though, I'm working on a fix for this."); groups.flagged = true; } if (response.response) { var groups_doc = parser.parseFromString(response.response, "text/html"); for (var group_item of groups_doc.getElementsByClassName('group-item')) { var group = { server: response.context }; groups.push(group); for (var el of group_item.querySelectorAll("*") ) { if (el.classList.contains('group-type')) { group.type = el.innerText.trim(); } else if (el.classList.contains('group-name')) { group.name = el.innerText.trim(); } else if (el.tagName == "A") { if (el.href.startsWith("http")) group.link = el.href; else group.link = "http://tagpro-"+group.server+".koalabeast.com"+el.href; } else if (el.innerText.trim().startsWith('Leader')) { group.leader = el.innerText.slice(el.innerText.indexOf(":")+1); } else if (el.innerText.trim().startsWith('Players')) { group.players = el.innerText.slice(el.innerText.indexOf(":")+1); } } } } else console.error("Couldn't get groups on "+response.context, response); if (pending === 0) resolve(groups); } });} function update_groups() { if (!(window.location.pathname === '/groups' && groups_on_groups || // If we are on the groups selection page window.location.pathname.match(/^\/groups\/[a-z]{8}$/) && groups_in_group || // If we are in a group window.location.pathname === '/games/find' && groups_on_find || // In the process of joining a game window.location.pathname === '/' && groups_on_home )) // If we are on the homepage { return; } // Relocate the groups container // Add the container to the userscript-div and make unhide that if (groups_list.parentElement.id == "GroPro-groups") { var pos = document.getElementById('userscript-'+position) || document.getElementById('userscript-home') || document.getElementById('userscript-top') || (location.host.startsWith("tagpro.") && document.getElementsByClassName('header')[0]); if (!pos) return tagpro.helpers.displayError('Sorry, something went wrong while trying to show you the groups of all servers. Error code: Giraffe (inform /u/Wilcooo if you want me to fix it)'); if (insertBefore) pos.insertBefore(container, pos.firstChild); else pos.append(container); pos.classList.remove('hidden'); } groups_list.className = 'row groups-list'; var groups_list_cache = GM_getValue('groups-list-cache',{}); groups_list.innerHTML = '<div class=spinner align=center> <div class=spinner-item></div> <div class=spinner-item></div> <div class=spinner-item></div> <div class=spinner-item></div>'; if (Date.now() - groups_list_cache.time < 65e3) groups_list.innerHTML += groups_list_cache.html; // Get ping and server stats for each server window.addEventListener('load',function(){ servers.forEach( function(server) { var host = 'http://tagpro-'+server+'.koalabeast.com:80'; var connection = io.connect(host, {transports: ["websocket"]}); connection.on('connect',function(){ var ping = -Date.now(); connection.emit('stats',{},function(stats) { ping += Date.now(); styleSheet.insertRule('.'+server+'-stats:after { content:"(ping: '+ping+', '+stats.players+' players in '+stats.games+' games)"; color:#868686; font-style:italic; font-size:small; }'); styleSheet.insertRule('.'+server+'-stats .spinner { display:none !important; }'); }); }); }); }); get_groups().then(function(groups) { groups_list.innerHTML = ''; for (var group of groups) { var group_html = `<div class="col-sm-6 col-md-4"> <div class="group-item"> <div class="row"> <div class="col-md-12"> <div class="pull-right group-type"> `+group.type+` </div> <div class="group-name ellipsis"> `+group.name+` </div> </div> <div class="col-xs-6"> <div class="ellipsis"> Leader: `+group.leader+` </div> <div class="ellipsis"> Players: `+group.players+` </div> </div> <div class="col-xs-6"> <a class="btn btn-primary pull-right ellipsis" href="`+group.link+`"> Join Group </a> </div> <div class="col-xs-12 ellipsis `+group.server+`-stats"> Server: `+group.server[0].toUpperCase() + group.server.slice(1)+` <div class=spinner style="display:inline"> <div class=spinner-item></div> <div class=spinner-item></div> <div class=spinner-item></div> </div> </div> </div> </div> </div>`; groups_list.innerHTML += group_html; } if (groups.flagged) { groups_list.innerHTML = ` <div class="col-sm-6 col-md-4"> <div class="group-item" style="height:118px; font-size:smaller; color:lightgray"> Sorry, your IP address has been flagged by TagPro - so the GroupsOnHome script can't yet show you the groups. No worries though, I'm working on a fix for this. </div> </div>`; } else if (groups.length === 0) { groups_list.innerHTML = ` <div class="col-sm-6 col-md-4"> <div class="group-item" style="height:118px"> <div class="row"> <div class="col-md-12"> <div class="group-name">No public groups available. Create one!</div> </div> </div> </div> </div>`; } if (window.location.pathname !== '/groups') { groups_list.innerHTML += `<div class="col-sm-6 col-md-4"> <div class="group-item"> <div class="row"> <form method="post" action="/groups/create"> <div class="col-md-12"> <input name="name" class="group-name" style="background:0;border:0;width:100%;height:27px" value="Your group"> </div> <div class="col-md-12"><br></div> <div class="col-xs-6"> <label tabindex="0" class="btn btn-default input-label ellipsis"> <input tabindex="-1" type="checkbox" name="public"> Public Group </label> </div><div class="col-xs-6"> <button class="btn btn-primary ellipsis pull-right" style="">Create Group</button> </div> </form> </div> </div> </div>`; } for (var label of document.getElementsByClassName('input-label')) { label.onkeydown = function(keydown) { if (keydown.code == 'Space') { keydown.preventDefault(); keydown.target.firstElementChild.checked ^= true; } if (keydown.code == 'Enter') { keydown.preventDefault(); keydown.target.closest('form').submit(); } }; } GM_setValue('groups-list-cache', {'html': groups_list.innerHTML, 'time': Date.now()}); }); clearTimeout(timeout); if (interval) timeout = setTimeout(update_groups, 1000*interval); } var timeout = -1, groups_list = document.querySelector(".groups-list") || document.createElement('div'); // Create a container for the groups if (!groups_list.parentElement) { var container = document.createElement('div'); container.id = 'GroPro-groups'; container.className = 'container'; container.appendChild(groups_list); } update_groups(); document.head.appendChild( document.createElement('style' )); var styleSheet = document.styleSheets[ document.styleSheets.length -1 ]; styleSheet.insertRule( '.ellipsis { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }' );