Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux Support - Puppeteer for Token Fetching #35

Open
Novattz opened this issue May 1, 2024 · 3 comments
Open

Linux Support - Puppeteer for Token Fetching #35

Novattz opened this issue May 1, 2024 · 3 comments
Labels
needs looking into Further analysis is needed suggestion New feature or request

Comments

@Novattz
Copy link

Novattz commented May 1, 2024

Collect discord tokens with puppeteer for linux users.

Install these in the same directory as Discord-Backup!

  • npm install puppeteer @gilgames/discord-detours

Make a javascript file in the same directory as Discord-Backup.

  • sudo nano index.js

Initial login script

  • Place this script in index.js and log in to discord via a non-headless browser:
let puppeteer = require('puppeteer');
const detours = require("@gilgames/discord-detours");

(async () => {
    const browser = await puppeteer.launch({ userDataDir: './user_data', headless: false });
    const page = await browser.newPage();
    await page.goto('https://discord.com/channels/@me');
    await page.setViewport({ width: 1080, height: 1024 });
    const serializedAPI = detours.serializeModule(detours.api);
    await page.evaluate(detours.injectModule, serializedAPI);
    const token = await page.evaluate(() => window.discordDetours.findFunctionByName("getToken")());
    console.log(token);
    await browser.close(); 
})();
  • After logging in, replace the initial login script in index.js with this one to automatically fetch the token on subsequent runs:
let puppeteer = require('puppeteer');
const detours = require("@gilgames/discord-detours");

(async () => {
    const browser = await puppeteer.launch({ userDataDir: './user_data' });
    const page = await browser.newPage();
    await page.goto('https://discord.com/channels/@me');
    await page.setViewport({ width: 1080, height: 1024 });
    const serializedAPI = require("@gilgames/discord-detours").serializeModule(require("@gilgames/discord-detours").api);
    await page.evaluate(detours.injectModule, serializedAPI);
    const token = await page.evaluate(() => window.discordDetours.findFunctionByName("getToken")());
    const user_info = await page.evaluate(() => {
        const usernameElement = document.querySelector('span[class="text-gray-400 font-semibold"]');
        const username = usernameElement ? usernameElement.innerText.split('#')[0] : 'Unknown';
        const discriminator = usernameElement ? usernameElement.innerText.split('#')[1] : '0000';
        return { username, discriminator };
    });
    console.log(JSON.stringify({ token, username: user_info.username, discriminator: user_info.discriminator }));
    await browser.close();
})();
  • Modified fetch_tokens.py
import subprocess
import json

def fetch():
    try:
        result = subprocess.run(['node', 'index.js'], capture_output=True, text=True, check=True)
        token_data = json.loads(result.stdout)
        return [[token_data['token'], f"{token_data['username']}#{token_data['discriminator']}", token_data['token'], "Discord"]]
    except subprocess.CalledProcessError as e:
        print(f"Failed to execute script: {e}")
        return []
    except json.JSONDecodeError as e:
        print(f"Error decoding JSON from script output: {e}")
        return []
  • This will now allow you to automatically backup and restore using the built in choices in main.py without having to manually get your token.
@itschasa
Copy link
Owner

itschasa commented May 1, 2024

this does not have to be done in javascript, id rather keep all the code in the same language for something like this, so a single binary can be used with ease

@Novattz
Copy link
Author

Novattz commented May 1, 2024

this does not have to be done in javascript, id rather keep all the code in the same language for something like this, so a single binary can be used with ease

Interacting with the keyring that stores the token is outside of what i was able to do and i settled for this instead. while i do know its not an ideal approach its better then having nothing at all for a program that is really useful for users.

@Novattz
Copy link
Author

Novattz commented May 2, 2024

Alternative approach if people would like to only use python:

import os
import plyvel

DATABASE_PATH = os.path.expanduser('~/.config/discord/Local Storage/leveldb/')

def open_db():
    try:
        db = plyvel.DB(DATABASE_PATH, create_if_missing=False)
        return db
    except Exception as e:
        raise Exception(f"Error opening database: {e}")

def get_token():
    try:
        db = open_db()
        key = b'\x5f\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x69\x73\x63\x6f\x72\x64\x61\x70\x70\x2e\x63\x6f\x6d\x00\x01\x74\x6f\x6b\x65\x6e'
        token = db.get(key)
        if token is None:
            raise KeyError("Token not found in database")
        return token.decode('utf-8')
    finally:
        db.close()

def fetch():
    try:
        print(get_token())
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    fetch()

Although doing token checking wasn't something i was able to figure out. Requires plyvel

@itschasa itschasa added suggestion New feature or request needs looking into Further analysis is needed labels Jun 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs looking into Further analysis is needed suggestion New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants