Skip to content

Instantly share code, notes, and snippets.

@Amar1729
Last active September 28, 2022 19:05
Show Gist options
  • Save Amar1729/e0d1018a88d2a7a2fe1f6e9fd998ceaf to your computer and use it in GitHub Desktop.
Save Amar1729/e0d1018a88d2a7a2fe1f6e9fd998ceaf to your computer and use it in GitHub Desktop.
Batch upload icon links as emojis to mattermost
#! /usr/bin/env python3
import os
import sys
import time
from typing import Any, Generator
# local
import iface
API = iface.API(iface.URL)
def get_emoji_image(emoji_name: str) -> bytes:
emoji = API.do_request(f"emoji/name/{emoji_name}").json()
return API.do_request(f"emoji/{emoji['id']}/image").content
def same_image_emojis(bad_name: str) -> Generator[Any, None, None]:
"""
Generator of emoji IDs to delete.
"""
c = 0
bad_image = get_emoji_image(bad_name)
print(f"Got image of length: {len(bad_image)}")
for emoji in API.emoji_list():
data = get_emoji_image(emoji["name"])
if data == bad_image:
print(f"{emoji['name']}")
yield emoji
time.sleep(1)
c += 1
if c % 100 == 0:
print(f"passed {c} images")
def delete_emoji(emoji):
"""
Save the emoji in imgs/ just in case (and as a roundabout logging system)
Then delete the emoji.
"""
fname = os.path.join("imgs", f"{emoji['name']}.png")
with open(fname, "wb") as f:
f.write(get_emoji_image(emoji["name"]))
API.emoji_delete(emoji["id"])
def delete_by_name(emoji_name: str):
emoji = API.do_request(f"emoji/name/{emoji_name}").json()
delete_emoji(emoji)
if __name__ == "__main__":
# get a command line arg as a given bad emoji
# delete all emojis that have the same image data as that one
for emoji in same_image_emojis(sys.argv[1]):
delete_emoji(emoji)
#! /usr/bin/env python3
import argparse
import getpass
import requests
# define this to point to your mattermost host
# MATTERMOST = ""
URL = f"https://{MATTERMOST}/api/v4"
class API:
def __init__(self, url):
self.url = url
self.login()
def login(self):
print("username:")
payload = {
"login_id": input(),
"password": getpass.getpass(),
}
r = requests.post(URL + "/users/login", json=payload)
self.token = r.headers["Token"]
def do_request(self, endpoint, params=None):
headers = {
"Authorization": "Bearer {}".format(self.token),
}
return requests.get("{}/{}".format(self.url, endpoint), headers=headers, params=params)
def emoji_list(self):
page = 0
while True:
emojis = self.do_request("emoji", {"page": page}).json()
if emojis:
for emoji in emojis:
yield emoji
page += 1
else:
break
def emoji_delete(self, _id):
"""delete an emoji by ID"""
headers = {
"Authorization": "Bearer {}".format(self.token),
}
endpoint = "emoji/{}".format(_id)
return requests.delete("{}/{}".format(self.url, endpoint), headers=headers)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--action", choices=["list", "delete"], help="what to do")
parser.add_argument("--id", help="if deleting, emoji ID to delete")
args = parser.parse_args()
api = API(URL)
if args.action == "list":
from pprint import pprint
pprint(list(api.emoji_list()))
elif args.action == "delete":
if not args.id:
raise Exception("--id required when deleting.")
api.emoji_delete(args.id)
if __name__ == "__main__":
main()
#!/usr/bin/env bash
# Author: Amar Paul
# Add custom emojis to a mattermost server.
# Usage:
# Expects a yaml/ dir with .yaml files, formatted as such:
# - name: <name_of_emoji>
# src: <src_url>
#
# Script will read yaml files, download each src from URL
# into imgs/ directory, then upload to mattermost using the
# mattermost /emoji endpoint.
# https://api.mattermost.com/#tag/emoji
#
# Full usage:
# <script> [--user USER] [--url MATTERMOST_URL] [action]
# MATTERMOST_URL is read from env if set.
# USER can be determined from `whoami`
#
# actions:
# --download-yamls <file>
# dl all the .yaml files listed in <file> into yamls/
# (expects file to be at least one line of YAML URLs)
# --list
# --upload imgname imgfile
#
# no param: (default)
# downloads images specified by .yamls and uploads them to mattermost
# expects yaml files in the yamls/ dir
#
# Note:
# This script isn't smart about what's already on the server,
# so uploading an emoji with a name that already exists will
# return a {success: false} json from the server and continue.
#
# It also doesn't know if an image has already been downloaded.
#
# Depends on `jq' for some JSON parsing.
#
# Some yaml-formatted emoji packs:
# https://github.com/amtypaldos/rocketchat-emoji-upload
ESC="$(printf '\033')"
GRN="${ESC}[31;1m"
RED="${ESC}[32;1m"
NOC="${ESC}[30;0m"
USER="$(whoami)"
url="${MATTERMOST_URL}"
retfile=login-return.json
get_uid () { cat $retfile | tail -n1 | jq -r '.id' ;}
get_auth () { cat $retfile | grep '^Token' | tr -d '\r' | sed -e 's/.*: //' ;}
_login () {
echo -n "Password for <$USER>: "
read -s password
curl -i ${url}/users/login \
-d "{\"login_id\":\"${USER}\",\"password\":\"${password}\"}" \
> $retfile
}
general () {
curl "${url}/${endpoint}" \
-H "Authorization: Bearer $(get_auth)"
}
list_emojis () {
curl "${url}/emoji" \
-H "Authorization: Bearer $(get_auth)"
}
get_file () {
(pushd imgs/ && wget $1 && popd) &>/dev/null
echo "imgs/${1##*/}"
}
upload_emoji () {
printf "name=$1, "
printf "emoji=@$2"
printf "\n"
curl "${url}/emoji" \
-F emoji="{\"creator_id\":\"$(get_uid)\",\"name\":\"$1\"}" \
-H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer $(get_auth)" \
-F "image=@$2"
printf "\n\n"
}
grab_files () {
local name=""
local src=""
if [[ $(uname) == "Darwin" ]]; then
alias grep=ggrep
fi
for ym in yamls/*yaml; do
while read -r line || [[ -n "$line" ]]; do
if echo $line | grep -o "^[^\W]*- name: " > /dev/null; then
name="${line#*- name: }"
fi
if echo $line | grep -o "^[^\W]*src: " > /dev/null; then
src="${line#*src: }"
echo "${GRN}Downloading: ${NOC}$src"
src="$(get_file $src)"
fi
if [[ -n "$name" ]] && [[ -n "$src" ]]; then
printf "${RED}Uploading : ${NOC}"
upload_emoji $name $src
name=""
src=""
fi
done < $ym
done
}
dl_yamls () {
[[ ! -e $1 ]] && echo "File: $1 doesn't exist." && exit 1
[[ ! -d yamls/ ]] && mkdir -p yamls
pushd yamls/ >/dev/null
while read -r line || [[ -n "$line" ]]; do
wget $line
done < ../$1
popd >/dev/null
}
#
#
#
# default action
action=grab_files
while [[ $# -gt 0 ]]; do
case $1 in
--user)
USER=$2
shift; shift
;;
--url)
url=${2%/}
shift; shift
;;
--list)
action=list_emojis
shift
;;
--download-yamls)
dl_yamls $2
exit 0
;;
--upload)
upload_emoji $2 $3
exit 0
;;
--general)
action=general
endpoint=$2
shift; shift
;;
*)
shift
;;
esac
done
[[ -z $USER ]] && echo "Required: --user" && exit 1
[[ -z $url ]] && echo "Required: --url" && exit 1
[[ $action != "_logout" ]] && [[ ! -e $retfile ]] && _login
[[ ! -d imgs/ ]] && mkdir -p imgs
[[ ! -d yamls/ ]] && echo "Required directory: yamls/" && exit 1
$action
@Amar1729
Copy link
Author

Amar1729 commented Sep 9, 2020

@avislash
Copy link

I just ran this for the first time today. I'm using MatterMost Server version 6. To get this to work there's a couple of things that need to change now....

1.) Anywhere you are using curl you need to change it to be ${url}/api/v4 followed by the endpoint

For example to use curl to upload an emoji you now need to use ${url}/api/v4/emoji instead of ${url}/emoji similarly for login it now need to be ${url}/api/v4/users/login

2.) The the JSON Token now comes down as "token" so you need to update the get_auth function to be
get_auth () { cat $retfile | grep '^token' | tr -d '\r' | sed -e 's/.*: //' ;}

Other than that I was just able to use this script to upload a ton of emojis to my MM server. Thanks Paul!

@Amar1729
Copy link
Author

Interesting, thanks for the note! As far as url goes, i made the mistake of setting my MATTERMOST_URL as mattermost.domain/api/v4 in my environment explicitly, which is why none of the curl statements use /api/v4 properly. I should have been clear about that in the comments.

Glad it still works with those changes!

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