Epix Auto Friend

Automatically adds all the Epix friends links from the gamescom discord server

目前為 2024-08-13 提交的版本,檢視 最新版本

// ==UserScript==
// @name        Epix Auto Friend
// @namespace   Violentmonkey Scripts
// @match       https://discord.com/channels/574865170694799400/1259933715409145966*
// @inject-into content
// @grant       GM_addStyle
// @grant       GM_getValue
// @grant       GM_setValue
// @version     1.0
// @author      UpDownLeftDie
// @license     MIT
// @description Automatically adds all the Epix friends links from the gamescom discord server

// ==/UserScript==

let EPIX_IDS = [];
let DISCORD_TOKEN = '';
let EPIX_FRIENDS = [];

function main() {
  EPIX_FRIENDS = GM_getValue('epixFriends') || [];
  EPIX_IDS = GM_getValue('epixIds') || [];
  DISCORD_TOKEN = localStorage.getItem("token")?.replaceAll('\"', '');
  console.log({EPIX_FRIENDS, EPIX_IDS, DISCORD_TOKEN: !!DISCORD_TOKEN});

  const epixButton = document.createElement('button');
  epixButton.setAttribute('id', 'epixButton');
  epixButton.setAttribute('type', 'button');
  epixButton.innerHTML = 'Run Epix Friend Adder';
  document.querySelector('h1').appendChild(epixButton);

  document.getElementById("epixButton").addEventListener("click", handleButton, false);
}

async function handleButton(event) {
  await getEpixIds();

  const epixButton = document.getElementById('epixButton');
  epixButton.setAttribute('disabled', true);
  epixButton.innerHTML = 'Running...';


  let messages = [];
  do {
    const minId = GM_getValue('discordMinId');
    console.log({minId});
    messages = await getDiscordMessages(minId);
    const codes = getEpixCodes(messages);
    console.log({messages, codes});
    if (codes.length <= 0 && messages.length > 0) {
       GM_setValue('discordMinId', messages[messages.length - 1][0].id);
    }
    for(let i in codes) {
      const promises = EPIX_IDS.map(epixId => connectRequest(epixId, codes[i].code));
      let responses = await Promise.all(promises);
      let json = await responses[0].json();
      const status = json?.data?.status.toUpperCase();
      updateFriends(status, codes[i]);
    }
  } while(messages.length >= 25);

  epixButton.innerHTML = 'Done!';
}

async function getEpixIds() {
  return new Promise((resolve, reject) => {
    const inputValue = EPIX_IDS?.length ? EPIX_IDS.join(',') : '';
    const dialog = document.createElement('dialog');
    dialog.setAttribute('open', true);
    dialog.setAttribute('id', 'epixIdsDialog')
    dialog.innerHTML = `
      <p>Enter your Epix user id(s) (<strong>NOT the same as your invite id!</strong>)</p>
      To get this go to your <a href="https://www.gamescom.global/en/epix" target="_blank">profile</a>:
        <ol>
          <li>open dev tools</li>
          <li>refresh the page</li>
          <li>look at network requests for "user?userId=XXXXXXX"</li>
        </ol>
      <form method="dialog">
        <input id="epixIds" placeholder="b5629b160f555ab4b08ef8e49568b7dd, a49f9b160f555vd4b08ef8e49568b7a2" value="${inputValue}" />
        <button id="epixIdAddButton">START</button>
      </form>
    `;
    document.body.appendChild(dialog);
    document.getElementById("epixIdAddButton").addEventListener("click", ()=> {
      const idStr = document.getElementById("epixIds").value;
      const ids = idStr.split(',').reduce((acc, curr) => {
        const id = curr.replace(/\W/gi, '');
        if (!id) return acc;
        acc.push(id);
        return acc;
      }, []);
      EPIX_IDS = ids;
      GM_setValue('epixIds', EPIX_IDS);
      dialog.parentNode.removeChild(dialog);
      resolve();
    }, false);
  });
}

function getEpixCodes(discordMessages) {
  const codes = discordMessages.reduce((acc, curr) => {
    const message = curr[0]
    const match = message.content.match(/epix-connect=([\w\d]{7})/i);
    if (match?.[1] && !EPIX_FRIENDS.includes(match[1])) {
      acc.push({code: match[1], messageId: message.id});
    }
    return acc;
  }, [])

  return codes;
}


function updateFriends(status, code) {
  if (status === "CONNECTION_SUCCESSFUL" || status === "ALREADY_MATCHED") {
    EPIX_FRIENDS.push(code.code);
    GM_setValue('epixFriends', EPIX_FRIENDS);
    GM_setValue('discordMinId', code.messageId);
  }

}



//--- Style our newly added elements using CSS.
GM_addStyle (`
  #epixButton {
    margin-left: 10px;
  }

  #epixIdsDialog {
    margin-top: 5rem;
  }
  #epixIdsDialog ol {
    list-style: auto;
    padding-left: 35px;
    margin-bottom: 10px;
  }
  #epixIdsDialog input {
    width: 100%;
  }
  #epixIdsDialog button {
    margin: 5px auto;
    display: block;
    font-size: large;
    background: greenyellow;
    padding: 2px 10px;
  }
`);


async function connectRequest(userId, profileId) {
  return fetch("https://wfppjum4x2.execute-api.eu-central-1.amazonaws.com/production/connection-request", {
    "referrer": "https://www.gamescom.global/",
    "referrerPolicy": "strict-origin-when-cross-origin",
    "body": `{"userId":"${userId}","profileId":"${profileId}"}`,
    "method": "POST",
    "mode": "cors",
    "credentials": "omit"
  });
}


async function getDiscordMessages(minId) {
  const params = queryString([
    ['limit', 25],
    ['channel_id', '1259933715409145966'],
    ['min_id', minId],
    ['sort_by', 'timestamp'],
    ['sort_order', 'asc'],
    ['has','link'],
  ]);
  const res = await fetch(`https://discord.com/api/v9/guilds/574865170694799400/messages/search?${params}`, {
    "headers": {
      "accept": "*/*",
      "authorization": DISCORD_TOKEN
    },
    "referrer": "https://discord.com/channels/574865170694799400/1259933715409145966",
    "referrerPolicy": "strict-origin-when-cross-origin",
    "method": "GET",
    "mode": "cors",
    "credentials": "include"
  });
  if (!res.ok) {
    console.error({ERROR: res.error});
    return;
  }

  const data = await res.json();
  return data.messages;
}


const queryString = params => params.filter(p => p[1] !== undefined).map(p => p[0] + '=' + encodeURIComponent(p[1])).join('&');

(new MutationObserver(check)).observe(document, {childList: true, subtree: true});
function check(changes, observer) {
  if(document.querySelector('h1')) {
    observer.disconnect();
    main();
  }
}