Skip to content

Instantly share code, notes, and snippets.

@thisisrachelramos
Forked from dogeared/00_README
Last active April 6, 2021 08:33
Show Gist options
  • Save thisisrachelramos/0a139a3f53d36b5b24359bcc99b39b3a to your computer and use it in GitHub Desktop.
Save thisisrachelramos/0a139a3f53d36b5b24359bcc99b39b3a to your computer and use it in GitHub Desktop.
Extracting / Exporting custom emoji from Slack
This builds off the excellent work of @lmarkus.
The scripts below can be used in conjunction with the Neutral Face Emoji Tools Google Chrome extension to (bulk!)
export emojis from one Slack team and import into another team:
https://chrome.google.com/webstore/detail/neutral-face-emoji-tools/anchoacphlfbdomdlomnbbfhcmcdmjej
Original work here: https://gist.github.com/lmarkus/8722f56baf8c47045621
Steps:
1) Run js in dev tools
2) Save json object in a txt file
3) Run bash script
4) Drag and drop all of the downloaded emojis in the bulk uploader
enabled through the chrome extension
#!/usr/bin/env bash
# Use:
# Make this file executable, and feed it the results from the Slack emoji URL dump. Files will be downloaded to `output`
# chmod +x downloadSlackEmojis.sh
# ./downloadSlackEmojis.sh emojiURLs.txt
#
# Note: This depends on the jq utility for parsing json from the command line - https://stedolan.github.io/jq/
mkdir -p output;
jq -r '.[] | "curl -s -o \"output/\(.name)\(.extension)\" \"\(.url)\""' $1 | \
while read -r line; do eval "$line"; done
# You can now drag and drop all the emoji files in the output folder to the Bulk Emoji Uploader space that you'll see on
# the https://<team>.slack.com/customize/emoji page if you've installed the chrome extension
# https://chrome.google.com/webstore/detail/neutral-face-emoji-tools/anchoacphlfbdomdlomnbbfhcmcdmjej
// Login to your team through the browser.
// Go to: https://<team name>.slack.com/customize/emoji
// Run this on the browser's dev tools javascript console
// This code scrolls to bottom of page to load all emojis
// (bc of virtualized list not revelaing all of the elements).
// Slow connections may wish to adjust the above factor past 2.5
var scrollTime = $(document).height() * 2.5
$("html, body").animate({ scrollTop: $(document).height() }, scrollTime);
var emojis = $('.emoji_row');
var numEmojis = emojis.size();
var pre = document.createElement('pre');
pre.append('[\n');
// After waiting for the scroll, grab url/name for each emoji
// and populate a json object that will appear at the bottom of the page
window.setTimeout(function() {
emojis.each(function(index) {
var url = $(this).find('td:nth-child(1) span').attr('data-original');
var extension = url.substring(url.lastIndexOf('.'));
var name = $(this).find('td:nth-child(2)').html().replace(/:|\s/g, '');
pre.append(JSON.stringify({ name: name, extension: extension, url: url }));
if (index == (numEmojis - 1)) {
pre.append('\n]');
} else {
pre.append(',\n');
}
});
console.log(pre);
}, scrollTime + 1000);
// Now, at the bottom of the page you'll see the json representation of all the emoji data
// copy and paste the json into a file (named "emojiURLs.txt" in "downloadSlackEmojis.sh" instructions)
// and use with downloadSlackEmojis.sh
@leetrout
Copy link

On my org is a paginated list now... Also Uncaught ReferenceError: scrollTime is not defined

@thisisrachelramos
Copy link
Author

Added scrollTime var fix, @leetrout
To solve pagination you would probably have to go to each page and run the js script and just append to the json object manually

@samuelasher
Copy link

samuelasher commented Aug 10, 2018

I got the following error:

VM458:24 Uncaught ReferenceError: eFile is not defined
    at <anonymous>:24:17

Should efile have been defined earlier in the script? This is how I ran it in the console @itsrachelle.
emoji_console

EDIT: This worked fine once I replaced eFile with pre.

@Outclazz
Copy link

Thank you for the procedure to follow and the explanations, it's very practical.

But, I would like to know how to run downloadSlackEmojis.sh on Windows (I don't have Linux)? Is there a simple command that could be translated?

@ksa-real
Copy link

ksa-real commented Aug 26, 2018

Didn't work for me because of pagination. The above js scrolls the doc to the bottom, but not the actual container with items. For my long list I've tried the following:

var imgContainer = new Map();
var t = $('div.c-virtual_list__scroll_container')[0];
// Populate items present on the page at start
for (imgEl of $('img.p-customize_emoji_list__image')) {
    imgContainer.set(imgEl.alt, imgEl);
}
t.addEventListener("DOMNodeInserted", function(event) {
  el = event.target;
  imgElResults = $(el).find('img.p-customize_emoji_list__image');
  if (imgElResults.length) {
    imgEl = imgElResults[0];
    if (!imgContainer.has(imgEl.alt)) {
      imgContainer.set(imgEl.alt, imgEl);
    }
  }
}, false);
// Now scroll to the bottom and then to the top so that list populates. Scrolling to the top is not necessary if the list was at top already. 
var emojiArr = ['[\n'];
var emojiIndex = 0;
imgContainer.forEach(function(value, key, map) {
	var url = value.src;
	var extension = url.substring(url.lastIndexOf('.')); // key is name
	emojiArr.push(JSON.stringify({ name: key, extension: extension, url: url }) + (++emojiIndex < map.size ? ',\n' : '\n]'));
});
console.log(emojiArr.join(''));

Then copy the output and use as in original file.

@jlezard
Copy link

jlezard commented Aug 30, 2018

@ksa-real your script works great but, I don't quite get how you got the scroll working ? many thanks

@JPablomr
Copy link

JPablomr commented Sep 3, 2018

@ksa-real's version relies on you doing the scroll manually, as the container adds and removes objects as you scroll.

This one will scroll for you:

// Helper
// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}


// Create a Map where we're going to store all of the images.
var imgContainer = new Map();
var t = $('div.c-virtual_list__scroll_container')[0];
// Populate items present on the page at start
for (imgEl of $('img.p-customize_emoji_list__image')) {
    imgContainer.set(imgEl.alt, imgEl);
}
t.addEventListener("DOMNodeInserted", function(event) {
  el = event.target;
  imgElResults = $(el).find('img.p-customize_emoji_list__image');
  if (imgElResults.length) {
    imgEl = imgElResults[0];
    if (!imgContainer.has(imgEl.alt)) {
      imgContainer.set(imgEl.alt, imgEl);
    }
  }
}, false);

// Now scroll to the bottom and then to the top so that list populates.
// Track the inside container's position
var scrollPosition = $('.c-scrollbar__hider')[0].scrollTop;
// Bump this higher if it's stopping mid-list.
var SLEEP_TIME = 750;

while(true) {
  // We're not sure how big the container is as it's loaded dynamically
  // So we scroll in increments of 500
  var newScrollPosition = $('.c-scrollbar__hider')[0].scrollTop += 500;
  // We know we've hit the bottom when the position stops changing
  if (newScrollPosition == scrollPosition) {
    break;
  }
  // Otherwise let's track the current position and keep going
  scrollPosition = newScrollPosition;
  // Sleep so the page can load the new emojis
  await sleep(SLEEP_TIME);
}

// Create the Array from the imgContainer map
var emojiArr = ['[\n'];
var emojiIndex = 0;
imgContainer.forEach(function(value, key, map) {
	var url = value.src;
	var extension = url.substring(url.lastIndexOf('.')); // key is name
	emojiArr.push(JSON.stringify({ name: key, extension: extension, url: url }) + (++emojiIndex < map.size ? ',\n' : '\n]'));
});
console.log(emojiArr.join(''));

@KrisClegg
Copy link

@JPablomr your script works wonders, but for some reason, in Chrome, the virtual list stops loading after about 4 loads (manual or with your script)

FireFox will continue to load the virtual list indefinitely, but I get this error in the console:

SyntaxError: await is only valid in async functions and async generators debugger eval code:43:2

I tried to replace await sleep(SLEEP_TIME); in your script w/ the following: (async () => {await sleep(SLEEP_TIME);})(); but that doesn't seem to be doing the trick. Any thoughts on how to make the script FireFox dev console friendly?

@lmarkus
Copy link

lmarkus commented Feb 2, 2019

UPDATE for 2019:
Hi folks... Author of the original gist here.
There's a much easier way to get the emoji list. I've updated the original gist, and added a Readme with the new approach.
( https://gist.github.com/lmarkus/8722f56baf8c47045621 )

Thanks to all the folks that have contributed to enhancing this solution over the years. ❤️ OpenSource!

Enjoy your emoji, and give me a follow on twitter @lennymarkus

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