171 lines
4.8 KiB
Python
Executable file
171 lines
4.8 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
from argparse import ArgumentParser, Namespace
|
|
|
|
from json import load
|
|
from pathlib import Path
|
|
from logging import error, info, debug, INFO, DEBUG, FileHandler
|
|
from sys import exit
|
|
from os import listdir
|
|
from os.path import splitext
|
|
from discord import Client, Intents
|
|
|
|
# Set default paths for config and emoji dir, and supported file formats
|
|
DEFAULT_CONFIG_PATH = "config.json"
|
|
DEFAULT_EMOJI_DIR = "emojis/"
|
|
SUPPORTED_FORMATS = [".jpeg", ".jpg", ".png", ".gif"]
|
|
|
|
|
|
class EmojiUploadClient(Client):
|
|
emoji_dir: Path = Path("")
|
|
guild_id: str = ""
|
|
|
|
async def on_ready(self):
|
|
"""Key function to run upon startup."""
|
|
|
|
info(f"Logged on as {self.user}")
|
|
|
|
# Attempt to upload emoji after startup.
|
|
await self.upload_emoji()
|
|
|
|
async def upload_emoji(self):
|
|
"""Uses emoji_dir and guild_id to upload all emoji in the directory
|
|
to the specified guild.
|
|
"""
|
|
|
|
info(f'Attempting to upload emoji at "{self.emoji_dir}"...')
|
|
|
|
# Check guild_id is numeric.
|
|
if not self.guild_id.isnumeric():
|
|
error(f"Not a proper guild_id: {self.guild_id}")
|
|
exit(1)
|
|
|
|
# Obtain guild object.
|
|
guild = self.get_guild(int(self.guild_id))
|
|
|
|
# Grab list of emoji files.
|
|
emoji_files = listdir(self.emoji_dir)
|
|
|
|
# Iterate through emojis and attempt to upload them.
|
|
for emoji in emoji_files:
|
|
current_emoji_filepath = f"{self.emoji_dir}/{emoji}"
|
|
(file_name, file_extension) = splitext(emoji)
|
|
|
|
# Validate that the image is a supported format.
|
|
if file_extension not in SUPPORTED_FORMATS:
|
|
debug(f'Skipping: "{current_emoji_filepath}"')
|
|
continue
|
|
|
|
# Try to upload the custom emoji.
|
|
debug(f"Attempting to upload: {current_emoji_filepath}")
|
|
with open(current_emoji_filepath, "rb") as img:
|
|
await guild.create_custom_emoji(name=file_name, image=img.read())
|
|
|
|
# Disconnect the client.
|
|
info("All emojis attempted, disconnecting.")
|
|
await self.close()
|
|
|
|
|
|
def parse_config(config_file: Path) -> tuple:
|
|
try:
|
|
with open(config_file) as config:
|
|
parse_config = load(config)
|
|
return (parse_config["api_key"], parse_config["guild_id"])
|
|
except Exception:
|
|
error(f"There was an error parsing the config file at: {config_file}")
|
|
exit(1)
|
|
return
|
|
|
|
|
|
def parse_opts(opts: Namespace) -> tuple:
|
|
"""Parse out opts for config and emoji paths.
|
|
|
|
Args:
|
|
opts (Namespace): Opts object to be parsed.
|
|
|
|
Returns:
|
|
(config_path, emoji_dir): Tuple of opts paths parsed.
|
|
"""
|
|
try:
|
|
info(
|
|
f"""
|
|
config_file: {opts.config_file}
|
|
emoji_dir: {opts.emoji_dir}
|
|
"""
|
|
)
|
|
config_file = Path(opts.config_file)
|
|
emoji_dir = Path(opts.emoji_dir)
|
|
except Exception:
|
|
error(f"{Exception}\nCould not successfully parse arguments.")
|
|
exit(1)
|
|
|
|
if not config_file.exists():
|
|
error(f'No config file found at "{config_file}".')
|
|
exit(1)
|
|
|
|
if not emoji_dir.exists():
|
|
error(f'"{emoji_dir}" is not a valid directory.')
|
|
exit(1)
|
|
|
|
if opts.verbose:
|
|
log_level = DEBUG
|
|
else:
|
|
log_level = INFO
|
|
|
|
return (config_file, emoji_dir, log_level)
|
|
|
|
|
|
def make_args() -> ArgumentParser:
|
|
"""Create an ArgumentParser object.
|
|
|
|
Returns:
|
|
ArgumentParser: ArgumentParser object
|
|
"""
|
|
|
|
parser = ArgumentParser()
|
|
parser.add_argument(
|
|
"-c",
|
|
"--config-file",
|
|
default=DEFAULT_CONFIG_PATH,
|
|
help=f"Path to config json, defaults to: {DEFAULT_CONFIG_PATH}",
|
|
)
|
|
parser.add_argument(
|
|
"-e",
|
|
"--emoji-dir",
|
|
default=DEFAULT_EMOJI_DIR,
|
|
help=f"Path to emoji directory, defaults to: {DEFAULT_EMOJI_DIR}",
|
|
)
|
|
parser.add_argument(
|
|
"-v",
|
|
"--verbose",
|
|
action="store_true",
|
|
help="Sets the logging level to DEBUG.",
|
|
)
|
|
return parser
|
|
|
|
|
|
def main(argv: list[str] | None = None, print_stdout: bool | None = True):
|
|
args = make_args()
|
|
opts = args.parse_args(argv)
|
|
|
|
# Parse out the config filepath, emoji directory, and verbose flag.
|
|
config_file, emoji_dir, log_level = parse_opts(opts)
|
|
|
|
# Parse out the api key and the guild id.
|
|
(api_key, guild_id) = parse_config(config_file)
|
|
|
|
# Create Discord API Client object and set properties.
|
|
client = EmojiUploadClient(intents=Intents.default())
|
|
client.emoji_dir = emoji_dir
|
|
client.guild_id = guild_id
|
|
|
|
# Set up logging for Discord API Client
|
|
handler = FileHandler(filename="emoji_uploader.log", encoding="utf-8", mode="w")
|
|
|
|
# Run the Discord API Client.
|
|
client.run(api_key, log_handler=handler, root_logger=True, log_level=log_level)
|
|
exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|