ElBort / eRepublik Friend's Tool

// ==UserScript==
// @name eRepublik Friend's Tool
// @namespace https://www.erepublik.com/en/citizen/profile/2524994
// @version 1.0.3
// @description eRepublik tool that allows you to bulk send friend requests to citizens and also delete all your dead friends
// @author El Bort
// @icon https://i.imgur.com/OHLPAY7.png
// @run-at document-end
// @include https://*.erepublik.com/*/main/party-members/*
// @include https://www.erepublik.com/*/main/rankings-parties/1/*
// @include https://*.erepublik.com/*/main/citizen-friends/*
// @include https://www.erepublik.com/*/main/rankings-military/1/*
// @downloadURL https://openuserjs.org/install/ElBort/eRepublik_Friends_Tool.user.js
// @updateURL https://openuserjs.org/meta/ElBort/eRepublik_Friends_Tool.meta.js
// @copyright 2021, ElBort (https://openuserjs.org/users/ElBort)
// @license MIT
// ==/UserScript==

setTimeout((()=>{e.main()}),2e3);class e{static main(){console.log("♪ Yo quiero tener un millón de amigos ♫"),o.init(),this.isWindowIn("/party-members/")?r.init():this.isWindowIn("/rankings-parties/")?n.init():this.isWindowIn(`/citizen-friends/${this.getCitizenId()}`)&&s.init()}static getToken(){return SERVER_DATA.csrfToken}static isWindowIn(e){return window.location.href.indexOf(e)>=0}static humanMessage(e){erepublik.functions.displayHumanMsgError(e)}static getCitizenId(){return erepublik.citizen.citizenId}static getLanguage(){return erepublik.settings.culture}}class t{static progress(e,t){let i=0;for(const s of e)s.then((()=>{i++,t({amount:i,total:e.length,percentage:100*i/e.length})}));return Promise.all(e)}}class i{constructor(e){this.ids=e}task(e="addFriend"){console.log(e,this),a.closeHide(),a.updateTitle("addFriend"===e?"Sending friend requests...":"Removing friends..."),a.updateDescription({title:"Progress",text:"Don't close this window"});let i=[];this.ids.forEach(((t,s)=>{let r=this.promise(s,e);i.push(r)})),t.progress(i,(e=>{a.updateProgress(e)})).then((t=>{a.updateTitle("Done"),a.closeShow(),"addFriend"===e?this.addFriend(t):this.removeFriend(t)})).catch((e=>{a.updateTitle("Error"),a.updateDescription({title:"Try again later",text:"Something went wrong"}),a.closeShow(),console.error(e)}))}promise(e,t="addFriend"){return new Promise(((i,s)=>{this.addRemoveFriend(e,t).then((e=>{i(e)})).catch((e=>{s(e)}))}))}addRemoveFriend(t,i="addFriend"){return fetch(`https://www.erepublik.com/${e.getLanguage()}/main/citizen-addRemoveFriend`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:i,citizenId:t,url:`//www.erepublik.com/${e.getLanguage()}/main/citizen-addRemoveFriend`,_token:e.getToken()})})}addFriend(e){let t=e.filter((e=>e.error&&e.message.startsWith("You are already friends"))),i=e.filter((e=>e.error&&e.message.includes("already has a friendship request pending"))),s=e.filter((e=>!e.error));a.updateDescription({title:"Results:",text:`\n            ${t.length?t.length+" already friends<br>":""}\n            ${i.length?i.length+" pending requests<br>":""}\n            ${s.length?s.length+" new requests":""}\n        `})}removeFriend(e){let t=e.filter((e=>e.status&&e.message.startsWith("You are no longer friends"))),i=e.filter((e=>e.error));a.updateDescription({title:"Results:",text:`\n            ${t.length?t.length+" dead friends deleted<br>":""}\n            ${i.length?i.length+" unsuccessful removes":""}\n        `})}}class s{static list=[];static init(){this.draw(),this.listen()}static draw(){document.querySelector(".prev").insertAdjacentHTML("beforebegin",'<li id="delListRC" class="prev"><a class="std_global_btn redColor"><span>💀</span></a></li>')}static listen(){document.querySelector("#delListRC").addEventListener("click",(()=>this.onClickRemoveDeath()))}static onClickRemoveDeath(){a.init(),a.updateTitle("Remove death friends"),a.updateProgress({percentage:0}),a.closeShow(),a.removeButtonShow(),this.getDeathFriends()}static getDeathFriends(){a.closeHide(),a.removeButtonHide(),a.updateTitle("Fetching dead friends..."),a.updateDescription({title:"Progress",text:"Don't close this window"});let e=[];for(let t=1;t<=this.calculatePages();t++){let i=this.promise(t);e.push(i)}t.progress(e,(e=>{a.updateProgress(e)})).then((e=>{if(this.list=e.flat(),a.updateTitle("Done"),a.closeShow(),!this.list.length)return a.updateDescription({title:"Remove dead friends",text:"There is no death friends to remove..."});a.updateDescription({title:"Remove dead friends",text:`Do you want to remove ${this.list.length} dead friends?`}),a.removeButtonShow()})).catch((e=>{a.updateTitle("Error"),a.updateDescription({title:"Try again later",text:"Something went wrong"}),a.closeShow(),console.error(e)}))}static promise(e){return new Promise(((t,i)=>{this.getPage(e).then((e=>e.json())).then((e=>{let i=(new DOMParser).parseFromString(e.content,"text/html").documentElement.querySelectorAll(".dead"),s=Array.from(i).map((e=>parseInt(e.id.match(/[0-9]{1,}/)[0])));t(s)})).catch((e=>{i(e)}))}))}static getPage(t){return fetch(`https://www.erepublik.com/es/main/citizen-friends/${e.getCitizenId()}/${t}/list`)}static getTotalFriends(){return parseInt(document.querySelector(".pager > p").innerText.match(/\d(?:[,\d]*\.\d+|[,\d]*)/g)[2])}static calculatePages(){return Math.ceil(this.getTotalFriends()/20)}}class r{static list=[];static init(){this.draw(),this.listen()}static draw(){document.querySelector(".holder > a").insertAdjacentHTML("beforebegin",'<a id="addFriendsRc" class="std_global_btn smallSize floatRight margin greenColor"><span>❤</span></a>')}static listen(){document.querySelector("#addFriendsRc").addEventListener("click",(()=>{this.list=[],this.onClickCheck()}))}static onClickCheck(){a.init(),document.querySelectorAll(".nameholder").forEach((e=>{let t=parseInt(e.attributes.href.value.split("/").pop());this.list.push(t)})),new i(this.list).task()}}class n{static list=[];static init(){this.draw(),this.listen()}static draw(){document.querySelectorAll(".bestof > tbody > tr").forEach(((e,t)=>{if(0===t)return;let i=e.querySelector(".dotted").attributes.href.value.match(/\-([0-9]{1,})(\/1)/)[1];e.querySelector("td:last-child > span").innerHTML+=`<a id="${i}" class="std_global_btn smallSize floatRight margin greenColor checkStatusRC"><span>❤</span></a>`}))}static listen(){document.querySelectorAll(".checkStatusRC").forEach((e=>{e.addEventListener("click",(e=>{this.list=[],this.onClickCheck(e.currentTarget.id)}))}))}static async onClickCheck(t){a.init();try{let s=await fetch(`https://www.erepublik.com/${e.getLanguage()}/main/party-members/${t}`),r=await s.text();(new DOMParser).parseFromString(r,"text/html").documentElement.querySelectorAll(".nameholder").forEach((e=>{let t=e.attributes.href.value.split("/").pop();this.list.push(t)})),new i(this.list).task()}catch(e){a.updateTitle("Error"),a.updateDescription({title:"Try again later",text:"Something went wrong"}),a.closeShow(),console.error(e)}}}class o{static init(){this.draw(),this.hide()}static draw(){document.querySelector("body").innerHTML+=this.html}static show(){document.querySelector("#overlayRc").style.display="block"}static hide(){document.querySelector("#overlayRc").style.display="none"}static html='<div id="overlayRc" class="lb_overlay" style="height: 2355px; position: absolute; width: 100%; inset: 0px; z-index: 25003; background: black; opacity: 0.8; display: none;"></div>'}class a{static init(){this.draw(),this.listeners()}static draw(){document.querySelector("#overlayRc").insertAdjacentHTML("beforebegin",this.html),o.show(),this.closeHide(),this.removeButtonHide()}static undraw(){o.hide(),document.querySelector("#robertoCarlos").remove()}static listeners(){document.querySelector("#stopRc, #robertoCarlos > .close").addEventListener("click",(()=>this.close())),document.querySelector("#removeFriendsRc").addEventListener("click",(()=>this.removeDeaths()))}static updateProgress(e){document.querySelector("#progressRc").innerText=`${Math.round(e.percentage)}%`}static updateTitle(e){document.querySelector("#infoRc > h2").innerText=e}static updateDescription({title:e,text:t}){document.querySelector("#infoRc > h6").innerHTML=e,document.querySelector("#infoRc > p").innerHTML=t}static closeShow(){document.querySelector("#robertoCarlos .close").style.display="inline-block",document.querySelector("#stopRc").style.display="inline-block"}static closeHide(){document.querySelector("#robertoCarlos .close").style.display="none",document.querySelector("#stopRc").style.display="none"}static close(){this.undraw()}static removeButtonShow(){document.querySelector("#removeFriendsRc").style.display="inline-block"}static removeButtonHide(){document.querySelector("#removeFriendsRc").style.display="none"}static removeDeaths(){if(!s.list.length)return e.humanMessage("There is not dead friends to remove");new i(s.list).task("removeFriend")}static html='\n<section id="robertoCarlos" class="unifiedPromoPopup" style="left: 50%; margin-left: -267px; z-index: 25004; position: fixed; top: 50%; margin-top: -197px; display: block;">\n  <a class="close" style="cursor: pointer;"></a>\n  <div class="promoContainer">\n    <div class="character valentinesDay"></div>\n    <section class="promoArea">\n      <article id="infoRc" class="promoContent">\n        <div class="details">\n          <div class="img valentines"></div>\n          <div class="countdown">\n            <span id="progressRc" class="hasCountdown">0%</span>\n          </div>\n        </div>\n        <h2 class="name">Initializing</h2>\n        <h6 class="description"></h6>\n        <p class="description"></p>\n\t\t<a id="stopRc" class="cta" style="cursor: pointer;">Close</a>\n        <a id="removeFriendsRc" class="cta battle" style="cursor: pointer;">❌ Remove</a><br>\n      </article>\n    </section>\n  </div>\n</section>'}