1
0
Fork 0
slack-emojinator/upload.py

197 lines
5.9 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python
2015-02-22 16:29:55 +00:00
# Upload files named on ARGV as Slack emoji.
# https://github.com/smashwilson/slack-emojinator
2015-02-22 16:29:55 +00:00
from __future__ import print_function
import argparse
2015-02-22 16:29:55 +00:00
import os
import re
from time import sleep
2015-02-22 16:29:55 +00:00
2015-02-25 03:57:48 +00:00
from bs4 import BeautifulSoup
import requests
try:
raw_input
except NameError:
raw_input = input
2018-08-25 05:06:36 +00:00
URL_CUSTOMIZE = "https://{team_name}.slack.com/customize/emoji"
URL_ADD = "https://{team_name}.slack.com/api/emoji.add"
URL_LIST = "https://{team_name}.slack.com/api/emoji.adminList"
API_TOKEN_REGEX = r'.*(?:\"?api_token\"?):\s*\"([^"]+)\".*'
2018-08-25 05:06:36 +00:00
API_TOKEN_PATTERN = re.compile(API_TOKEN_REGEX)
class ParseError(Exception):
pass
def _session(args):
assert args.cookie, "Cookie required"
assert args.team_name, "Team name required"
session = requests.session()
session.headers = {'Cookie': args.cookie}
2018-08-25 05:06:36 +00:00
session.url_customize = URL_CUSTOMIZE.format(team_name=args.team_name)
session.url_add = URL_ADD.format(team_name=args.team_name)
session.url_list = URL_LIST.format(team_name=args.team_name)
session.api_token = _fetch_api_token(session)
return session
2015-02-22 16:29:55 +00:00
def _argparse():
parser = argparse.ArgumentParser(
description='Bulk upload emoji to slack'
)
parser.add_argument(
'--team-name', '-t',
default=os.getenv('SLACK_TEAM'),
help='Defaults to the $SLACK_TEAM environment variable.'
)
parser.add_argument(
'--cookie', '-c',
default=os.getenv('SLACK_COOKIE'),
help='Defaults to the $SLACK_COOKIE environment variable.'
)
parser.add_argument(
'--prefix', '-p',
default=os.getenv('EMOJI_NAME_PREFIX', ''),
help='Prefix to add to genereted emoji name. '
'Defaults to the $EMOJI_NAME_PREFIX environment variable.'
)
parser.add_argument(
'--suffix', '-s',
default=os.getenv('EMOJI_NAME_SUFFIX', ''),
help='Suffix to add to generated emoji name. '
'Defaults to the $EMOJI_NAME_SUFFIX environment variable.'
)
parser.add_argument(
'slackmoji_files',
nargs='+',
help=('Paths to slackmoji, e.g. if you '
'unzipped http://cultofthepartyparrot.com/parrots.zip '
'in your home dir, then use ~/parrots/*'),
)
args = parser.parse_args()
if not args.team_name:
args.team_name = raw_input('Please enter the team name: ').strip()
if not args.cookie:
args.cookie = raw_input('Please enter the "emoji" cookie: ').strip()
return args
2015-02-22 16:29:55 +00:00
2018-08-25 05:06:36 +00:00
def _fetch_api_token(session):
# Fetch the form first, to get an api_token.
r = session.get(session.url_customize)
r.raise_for_status()
soup = BeautifulSoup(r.text, "html.parser")
all_script = soup.findAll("script")
for script in all_script:
2020-06-24 08:29:03 +00:00
if not script.string:
continue
for line in script.string.splitlines():
2018-08-25 05:06:36 +00:00
if 'api_token' in line:
# api_token: "xoxs-12345-abcdefg....",
# "api_token":"xoxs-12345-abcdefg....",
match_group = API_TOKEN_PATTERN.match(line.strip())
2022-07-20 08:30:47 +00:00
if match_group:
return match_group.group(1)
2018-08-25 05:06:36 +00:00
print("No api_token found in page. Search your https://<teamname>.slack.com/customize/emoji "
"page source for \"api_token\" and enter its value manually.")
return raw_input(
'Please enter the api_token ("xoxs-12345-abcdefg....") from the page: ').strip()
2018-08-25 05:06:36 +00:00
def main():
args = _argparse()
session = _session(args)
existing_emojis = get_current_emoji_list(session)
uploaded = 0
skipped = 0
def process_file(filename):
nonlocal skipped
nonlocal uploaded
print("Processing {}.".format(filename))
emoji_name = '{}{}{}'.format(
args.prefix.strip(),
os.path.splitext(os.path.basename(filename))[0],
args.suffix.strip()
)
if emoji_name in existing_emojis:
print("Skipping {}. Emoji already exists".format(emoji_name))
skipped += 1
else:
upload_emoji(session, emoji_name, filename)
print("{} upload complete.".format(filename))
uploaded += 1
for slackmoji_file in args.slackmoji_files:
if os.path.isdir(slackmoji_file):
for file in os.listdir(slackmoji_file):
filename = os.path.join(slackmoji_file, file)
process_file(filename)
else:
process_file(slackmoji_file)
print('\nUploaded {} emojis. ({} already existed)'.format(uploaded, skipped))
2015-02-22 16:29:55 +00:00
2015-02-25 03:57:48 +00:00
def get_current_emoji_list(session):
2018-08-25 05:06:36 +00:00
page = 1
result = []
while True:
data = {
'query': '',
'page': page,
'count': 1000,
'token': session.api_token
}
resp = session.post(session.url_list, data=data)
resp.raise_for_status()
response_json = resp.json()
2018-08-25 05:06:36 +00:00
result.extend(map(lambda e: e["name"], response_json["emoji"]))
if page >= response_json["paging"]["pages"]:
break
page = page + 1
return result
def upload_emoji(session, emoji_name, filename):
2015-02-22 16:29:55 +00:00
data = {
'mode': 'data',
2018-08-25 05:06:36 +00:00
'name': emoji_name,
'token': session.api_token
2015-02-22 16:29:55 +00:00
}
2018-08-25 05:06:36 +00:00
while True:
with open(filename, 'rb') as f:
files = {'image': f}
resp = session.post(session.url_add, data=data, files=files, allow_redirects=False)
if resp.status_code == 429:
wait = int(resp.headers.get('retry-after', 1))
print("429 Too Many Requests!, sleeping for %d seconds" % wait)
sleep(wait)
continue
resp.raise_for_status()
# Slack returns 200 OK even if upload fails, so check for status.
response_json = resp.json()
if not response_json['ok']:
print("Error with uploading %s: %s" % (emoji_name, response_json))
break
if __name__ == '__main__':
main()