Skip to content

Instantly share code, notes, and snippets.

@D-Brox
Last active November 1, 2023 16:42
Show Gist options
  • Save D-Brox/527b1ad84d8b8fc817680f1a1c3cc9c3 to your computer and use it in GitHub Desktop.
Save D-Brox/527b1ad84d8b8fc817680f1a1c3cc9c3 to your computer and use it in GitHub Desktop.
Unbork themes guide

Canary broke themes again -_-

What happened?

Discord's css is minified, with it's classes following the format name-hash. When they pushed a new asset to the canary build, the classes got renamed:

This means the classes on the themes don't relate to any discord class anymore.

So what now?

Luckily, thanks to Davri1, we were able to extract the css classes from the assets in both the stable build and the canary build. This means we can create a dictionary for the old and new classes

This is done in a 3 step proccess:

  1. The classes are grouped in the js asset. We can then find perfect matches between groups
  2. Sometimes some classes are deprecated, added or moved around in the new asset. We then need to find the best pairs of grouped classes. In other words, groups with high similarity
  3. The few unmatched classes get matched with the first unused class (usually the only one left of their kind)

With this information we can do a simple search and replace for all the classes.


Automation tools

Tool link
Update-Classes - replace classes of single css and scss files website
Discor-Theme-Updater - replace classes of single css and scss files website
Class Finder v2 - find pairs of classes using the url's of the js assets py script
canary-broke-themes-again.py - automaticaly find theme files and replace classes* py script
* some files may not work on windows due to codec issue. Use the site instead in those cases

If a theme doesn't work after patching with the site or the script, check if it uses a remote file, something like this:

@import url("https://github.com/user/repo/raw/master/filename.scss");

If there is an import like this, download the file, place it in that theme's folder, change the extentions to scss, and change the import to something like:

@import "./filename.scss"

JS snippets

  • CSS replacer (source)
    Use Console (Ctrl+Shift+i)
    Find and replace classes from a link (replace RAW_LINK_TO_THEME with the link to the css file you want to convert)
output = await Promise.all([
    fetch("https://cdn.discordapp.com/attachments/126228856477712384/930142142595211344/classes.json").then(res => res.json()),
    fetch("RAW_LINK_TO_THEME").then(res => res.text())
]).then(([classes, theme]) => {
    for (let i = 0; i < classes.length; i++) {
        const [ptb, canary] = classes[i];

        for (let i = 0; i < ptb.length; i++) {
            const ptbClass = ptb[i];
            const canaryClass = canary[i];

            theme = theme.replaceAll(ptbClass, canaryClass);
        }
    }    

    return theme;
})

After that, copy output to a file

  • Theme fixer (source)
    Use Simple Eval's .eval_async command
    Automaticaly find theme files and replace classes.
const path = require('path');
const fs  = require("fs");
const glob = require('glob');
const { get } = require('powercord/http');
const homedir = require("os").homedir();

let keep_old = true;
let use_old = true;
let fix_quickcss = true;
let default_path = true;
let powercorddir = "";
if (default_path) powercorddir = path.join(homedir,"powercord");
else powercorddir = ""; // replace with custom powercord folder location

const buf = await get("https://gist.githubusercontent.com/D-Brox/5ea0d9cec29c4921a9e397163f447646/raw/classes2.txt").then(r => r.body);
let classes = buf.toString().split("\n").map( r => r.split(" = "));
let themesdir = path.join(powercorddir,"src","Powercord","themes"); // change this if you want to run in other places
let files = glob.sync("**/*.*css",{ cwd: themesdir});

let exists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
let replace_classes = (file_path) => {
    let css = "";
    if (use_old && exists(file_path+".old")) css = fs.readFileSync(file_path+".old").toString();
    else {css = fs.readFileSync(file_path).toString();
          if (keep_old && !exists(file_path+".old")) fs.copyFileSync(file_path,file_path+".old");}
    if (css.includes("@import url")) console.log("%s contains remote imports", file_path);
    for (let i in classes) css = css.replace(new RegExp(classes[i][0], 'g'),classes[i][1]);
    fs.writeFileSync(file_path,css);
}

files.map(f => replace_classes(path.join(themesdir,f)));
if (fix_quickcss) replace_classes(path.join(powercorddir,"/src/Powercord/plugins/pc-moduleManager/quickcss.css"));
  • Class list (source)
    Use Console (Ctrl+Shift+i), useful for theme devs
    List all (div) classnames matching your input
Array.from(document.getElementsByTagName('*')).forEach((keys) => {
    if (keys.getAttribute('class') && keys.getAttribute('class').includes('YOUR_CLASSNAME'))
    console.log(keys.getAttribute('class'));
})

What if it happens again?

We now have the tools necessary to fix themes in the future by using just the js assets. That way we could fix themes in a couple of minutes, if this ever happens again.

@biast12
Copy link

biast12 commented Oct 17, 2023

laynetheepic has changed his name to lanye74, so the PC-Theme-Converter is at https://lanye74.github.io/projects/pc-theme-converter/

@D-Brox
Copy link
Author

D-Brox commented Oct 17, 2023

@biast12 I updated the link

@Aely0
Copy link

Aely0 commented Oct 26, 2023

The name of that project was also changed https://lanye74.github.io/projects/discord-theme-updater/

@D-Brox
Copy link
Author

D-Brox commented Oct 29, 2023

@Andris0 Updated again

@biast12
Copy link

biast12 commented Oct 29, 2023

Would suggest using this instead: https://syndishanx.github.io/Website/Update_Classes.html, it's being updated and maintained since the creator (@SyndiShanX) is active and updates it frequently

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment