Skip to content

Instantly share code, notes, and snippets.

@Davr1
Last active February 13, 2022 10:56
Show Gist options
  • Save Davr1/42e64ec0b2ae4b02d2753d75d60122b9 to your computer and use it in GitHub Desktop.
Save Davr1/42e64ec0b2ae4b02d2753d75d60122b9 to your computer and use it in GitHub Desktop.
import requests
import re
import json
output = open("output.css", "w+")
# b"\xef\xb8\x8f" or \ufe0f or 65039 or emoji variation 16 is a character used to convert emojis between monochrome and colored.
# It was causing some issues because of inconsistencies between the emoji lists, so I just removed it
src = requests.get("https://canary.discord.com/assets/257f691a0fec8c6680a9.js")._content.replace(b"\xef\xb8\x8f", b"").decode("utf-8").replace("\n", "")
new_emojis = json.loads(requests.get("https://static.revolt.chat/mutant/downloads/1.0/mtnt_1.0_data.json")._content.decode("utf-8"))
# finds matching asset ids and asset hashes in the source code, and puts them into a dictionary
# - example: 694020:(e,t,n)=>{e.exports=n.p+"96ecbefe46bb434c13f5a89802b5ec94.svg"} -> {694020:"96ecbefe46bb434c13f5a89802b5ec94"}
# int(float()) might seem useless, but there are a few ids like 694e3 that use scientific notation and can't be directly converted into an integer
assetid_assethash_map = {int(float(asset[0])): asset[1] for asset in re.findall(r"([\de]+):\(e,t,n\)=>{e\.exports=n\.p\+\"([a-z0-9.]+)\.[a-z]+\"}", src)}
# finds the codepoint:assetid map and turns it into a dictionary
# - example: "./1f486-1f3ff-200d-2640-fe0f.svg":694020 -> {"./1f486-1f3ff-200d-2640-fe0f.svg":694020}
codepoint_assetid_map = json.loads(re.search(r"553895:\(e,t,n\)=>{var r=({(.*?)})", src).group(1))
formatted_codepoint_assethash_map = {}
for emoji in codepoint_assetid_map.items():
# separates the codepoints into individual characters and converts them into hex and then into unicode
# each string is then saved into a new dictionary, with the matching assethash as the value
# example: {"./1f486-1f3ff-200d-2640-fe0f.svg":694020} + {694020:"96ecbefe46bb434c13f5a89802b5ec94"} -> {"\u1f486\u1f3ff\u200d\u2640":"96ecbefe46bb434c13f5a89802b5ec94"}
formatted_codepoint_assethash_map["".join([chr(int(character, 16)) for character in re.findall(r"[0-9a-f]+", emoji[0].replace("fe0f", ""))])] = assetid_assethash_map[int(emoji[1])]
# finds the unicode emoji map and saves the shortcode and surrogates into a new dictionary
# - example: {"names":["flushed"],"surrogates":"😳","unicodeVersion":6} -> {"😳":"flushed"}
unicode_emoji_map = json.loads(re.search(r"503033:e=>{\"use strict\";e\.exports=JSON\.parse\('(.*?)'\)}", src).group(1))
simplified_emoji_map = {}
for category in unicode_emoji_map:
for emoji in unicode_emoji_map[category]:
simplified_emoji_map[emoji["surrogates"]] = emoji["names"][0]
if "diversityChildren" in emoji:
for emoji_modifiers in emoji["diversityChildren"]:
simplified_emoji_map[emoji_modifiers["surrogates"]] = emoji_modifiers["names"][0]
# manually created emoji button cycle
# original image can be found here https://discord.com/assets/15e026451fd814e2d1a13e49c8076978.png
emoji_cycle = [
[128512, 128515, 128516, 128513, 128518, 128517, 128514, 129315, 9786, 128522, 128519],
[128578, 128579, 128521, 128524, 129394, 128525, 129392, 128536, 128535, 128537, 128538],
[128523, 128539, 128541, 128540, 129322, 129320, 129488, 129299, 128526, 129321, 129395],
[128527, 128530, 128542, 128532, 128543, 128533, 128577, 9785, 128547, 128534, 128555],
[128553, 129402, 128546, 128557, 128548, 128563]
]
for row_index, row in enumerate(emoji_cycle):
for column_index, column in enumerate(row):
for lookupemoji in new_emojis:
if lookupemoji["code"] == [column]:
output.write(".emojiButton-3FRTuj .sprite-2lxwfc[style*='background-position: %ipx %ipx;'] { background: center/contain no-repeat url('https://static.revolt.chat/mutant/short/%s') !important; }\n"
% (
column_index * -22,
row_index * -22,
lookupemoji["src"]
)
)
for emoji in new_emojis:
if emoji["code"] != "!": continue
emoji_string = ""
# turns decimal numbers into text
# - example: [129489,127999,8205,9992,65039] -> 👨🏿‍✈
for character in emoji["code"]:
if character != 65039:
emoji_string += chr(character)
# adds color tags to the source url
emoji_src = emoji["src"]
if "color" in emoji:
emoji_src = emoji_src.replace(" [hmn]", "_hmn")
if emoji["color"] == "default":
emoji_src = emoji_src.replace(".", "_y2.")
else:
emoji_src = emoji_src.replace(".", f"_{emoji['color']}.")
if emoji_string in formatted_codepoint_assethash_map:
if emoji_string in simplified_emoji_map:
output.write("[src='/assets/%s.svg'], [data-name='%s']>.emojiSpriteImage-3ykvhZ { background: center/contain no-repeat url('https://static.revolt.chat/mutant/short/%s') !important; object-position: -9999px; }\n"
% (
formatted_codepoint_assethash_map[emoji_string],
simplified_emoji_map[emoji_string].replace('_tone', r'::skin-tone-'),
emoji_src
)
)
else:
# special case for emojis without static shortcodes, such as skin tones
output.write("[src='/assets/%s.svg'] { background: center/contain no-repeat url('https://static.revolt.chat/mutant/short/%s') !important; object-position: -9999px; }\n"
% (
formatted_codepoint_assethash_map[emoji_string],
emoji_src
)
)
# another special case for diversity emojis
if emoji["code"] in [[128079], [128079, 127995], [128079, 127996], [128079, 127997], [128079, 127998], [128079, 127999]]:
output.write("[style*='background-image: url(\"/assets/%s.svg\")'] { background: center/contain no-repeat url('https://static.revolt.chat/mutant/short/%s') !important; }\n"
% (
formatted_codepoint_assethash_map[emoji_string],
emoji_src
)
)
output.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment