diff --git a/CHANGELOG.md b/CHANGELOG.md index 43df85b..9f81906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Added +- Flag emojis to commands with countries. +- Image attribution and description to "image" commands. +- New key in options.py: pika. + ## [v2.0.0] - 2019-12-16 ### Added @@ -31,7 +36,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Cleaned up code to comply with the PEP8 Standard - Issue in morse and unmorse commands where spaces were not interpreted correctly + ## v1.0.0 - 2019-07-31 [YANKED] + [Unreleased]: https://github.com/classabbyamp/discord-qrm2/compare/v2.0.0...HEAD [v2.0.0]: https://github.com/classabbyamp/discord-qrm2/releases/tag/v2.0.0 diff --git a/common.py b/common.py index b0f08fa..2822302 100644 --- a/common.py +++ b/common.py @@ -13,14 +13,16 @@ General Public License, version 2. """ +import collections +import json import traceback +from pathlib import Path from datetime import datetime from types import SimpleNamespace import discord import discord.ext.commands as commands - import data.options as opt @@ -43,6 +45,50 @@ cat = SimpleNamespace(lookup='Information Lookup', emojis = SimpleNamespace(good='βœ…', bad='❌') +paths = SimpleNamespace(data=Path("./data/"), + resources=Path("./resources/"), + bandcharts=Path("./resources/img/bandcharts/"), + maps=Path("./resources/img/maps/")) + + +# --- Classes --- + +class ImageMetadata: + """Represents the metadata of a single image.""" + def __init__(self, metadata: list): + self.filename: str = metadata[0] + self.name: str = metadata[1] + self.long_name: str = metadata[2] + self.description: str = metadata[3] + self.source: str = metadata[4] + self.emoji: str = metadata[5] + + +class ImagesGroup(collections.abc.Mapping): + """Represents a group of images, loaded from a meta.json file.""" + def __init__(self, file_path): + self._images = {} + self.path = file_path + + with open(file_path, "r") as file: + images: dict = json.load(file) + for key, imgdata in images.items(): + self._images[key] = ImageMetadata(imgdata) + + # Wrappers to implement dict-like functionality + def __len__(self): + return len(self._images) + + def __getitem__(self, key: str): + return self._images[key] + + def __iter__(self): + return iter(self._images) + + # str(): Simply return what it would be for the underlaying dict + def __str__(self): + return str(self._images) + # --- Helper functions --- diff --git a/dev-notes/metadata-format.md b/dev-notes/metadata-format.md new file mode 100644 index 0000000..fe7cb57 --- /dev/null +++ b/dev-notes/metadata-format.md @@ -0,0 +1,24 @@ +# File metadata format + +Used for grouping info such as name, description, source, and such. + + +## Format + +*`id` is the dictionary key, and the list items are the attributes for each files.* + +`meta.json` +```json +{ + "id": ["filename", "name", "long_name", "description", "source", "emoji"] +} +``` + +| Attribute | Description | Examples | +| ------------- | ----------------------------------------------- | ------------------------------------------------ | +| `filename` | The file name of the file, without the path. | `ca.png`, `itu.png` | +| `name` | The name of the file. | `Canada`, `ITU Zones` | +| `long_name` | The long name (title) of the file. | `Worldwide map of ITU Zones` | +| `description` | The description accompanying the file. | `Full radio allocations chart for all services.` | +| `source` | The source of the file. | `Instituto Federal de Telecomunicaciones (IFT)` | +| `emoji` | A Unicode emoji associated with the file. | `πŸ“»`, `πŸ‡¨πŸ‡¦` | diff --git a/exts/image.py b/exts/image.py index 5e6e048..c4f92d9 100644 --- a/exts/image.py +++ b/exts/image.py @@ -18,34 +18,64 @@ import common as cmn class ImageCog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot + self.bandcharts = cmn.ImagesGroup(cmn.paths.bandcharts / "meta.json") + self.maps = cmn.ImagesGroup(cmn.paths.maps / "meta.json") self.session = bot.qrm.session @commands.command(name="bandplan", aliases=['plan', 'bands'], category=cmn.cat.ref) async def _bandplan(self, ctx: commands.Context, region: str = ''): '''Posts an image of Frequency Allocations.''' - name = {'cn': 'Chinese', - 'ca': 'Canadian', - 'nl': 'Dutch', - 'us': 'US', - 'mx': 'Mexican'} arg = region.lower() with ctx.typing(): embed = cmn.embed_factory(ctx) - if arg not in name: + if arg not in self.bandcharts: desc = 'Possible arguments are:\n' - for abbrev, title in name.items(): - desc += f'`{abbrev}`: {title}\n' + for key, img in self.bandcharts.items(): + desc += f'`{key}`: {img.name}{(" " + img.emoji if img.emoji else "")}\n' embed.title = f'Bandplan Not Found!' embed.description = desc embed.colour = cmn.colours.bad await ctx.send(embed=embed) else: - img = discord.File(f"resources/images/bandchart/{arg}bandchart.png", - filename=f'{arg}bandchart.png') - embed.title = f'{name[arg]} Amateur Radio Bands' + metadata: cmn.ImageMetadata = self.bandcharts[arg] + img = discord.File(cmn.paths.bandcharts / metadata.filename, + filename=metadata.filename) + if metadata.description: + embed.description = metadata.description + if metadata.source: + embed.add_field(name="Source", value=metadata.source) + embed.title = metadata.long_name + (" " + metadata.emoji if metadata.emoji else "") embed.colour = cmn.colours.good - embed.set_image(url=f'attachment://{arg}bandchart.png') + embed.set_image(url='attachment://' + metadata.filename) + await ctx.send(embed=embed, file=img) + + @commands.command(name="map", category=cmn.cat.maps) + async def _map(self, ctx: commands.Context, map_id: str = ''): + '''Posts an image of a ham-relevant map.''' + arg = map_id.lower() + + with ctx.typing(): + embed = cmn.embed_factory(ctx) + if arg not in self.maps: + desc = 'Possible arguments are:\n' + for key, img in self.maps.items(): + desc += f'`{key}`: {img.name}{(" " + img.emoji if img.emoji else "")}\n' + embed.title = 'Map Not Found!' + embed.description = desc + embed.colour = cmn.colours.bad + await ctx.send(embed=embed) + else: + metadata: cmn.ImageMetadata = self.maps[arg] + img = discord.File(cmn.paths.maps / metadata.filename, + filename=metadata.filename) + if metadata.description: + embed.description = metadata.description + if metadata.source: + embed.add_field(name="Source", value=metadata.source) + embed.title = metadata.long_name + (" " + metadata.emoji if metadata.emoji else "") + embed.colour = cmn.colours.good + embed.set_image(url='attachment://' + metadata.filename) await ctx.send(embed=embed, file=img) @commands.command(name="grayline", aliases=['greyline', 'grey', 'gray', 'gl'], category=cmn.cat.maps) @@ -66,35 +96,6 @@ class ImageCog(commands.Cog): embed.set_image(url=f'attachment://greyline.jpg') await ctx.send(embed=embed, file=discord.File(data, 'greyline.jpg')) - @commands.command(name="map", category=cmn.cat.maps) - async def _map(self, ctx: commands.Context, map_id: str = ''): - '''Posts an image of a ham-relevant map.''' - map_titles = {"cq": 'Worldwide CQ Zones Map', - "itu": 'Worldwide ITU Zones Map', - "arrl": 'ARRL/RAC Section Map', - "rac": 'ARRL/RAC Section Map', - "cn": 'Chinese Callsign Areas', - "us": 'US Callsign Areas'} - - arg = map_id.lower() - with ctx.typing(): - embed = cmn.embed_factory(ctx) - if arg not in map_titles: - desc = 'Possible arguments are:\n' - for abbrev, title in map_titles.items(): - desc += f'`{abbrev}`: {title}\n' - embed.title = 'Map Not Found!' - embed.description = desc - embed.colour = cmn.colours.bad - await ctx.send(embed=embed) - else: - img = discord.File(f"resources/images/map/{arg}map.png", - filename=f'{arg}map.png') - embed.title = f'{map_titles[arg]}' - embed.colour = cmn.colours.good - embed.set_image(url=f'attachment://{arg}map.png') - await ctx.send(embed=embed, file=img) - def setup(bot: commands.Bot): bot.add_cog(ImageCog(bot)) diff --git a/main.py b/main.py index f98c869..a658e27 100644 --- a/main.py +++ b/main.py @@ -98,8 +98,12 @@ async def _extctl_load(ctx: commands.Context, extension: str): await ctx.send(embed=embed) -@_extctl.command(name="reload") +@_extctl.command(name="reload", aliases=["relaod"]) async def _extctl_reload(ctx: commands.Context, extension: str): + if ctx.invoked_with == "relaod": + pika = bot.get_emoji(opt.pika) + if pika: + await cmn.add_react(ctx.message, pika) try: bot.reload_extension(ext_dir + "." + extension) await cmn.add_react(ctx.message, cmn.emojis.good) diff --git a/resources/images/map/cqmap.png b/resources/images/map/cqmap.png deleted file mode 100644 index ba6c042..0000000 Binary files a/resources/images/map/cqmap.png and /dev/null differ diff --git a/resources/images/map/itumap.png b/resources/images/map/itumap.png deleted file mode 100644 index 9905b90..0000000 Binary files a/resources/images/map/itumap.png and /dev/null differ diff --git a/resources/images/map/racmap.png b/resources/images/map/racmap.png deleted file mode 100644 index 2d21664..0000000 Binary files a/resources/images/map/racmap.png and /dev/null differ diff --git a/resources/images/bandchart/cabandchart.png b/resources/img/bandcharts/ca.png similarity index 100% rename from resources/images/bandchart/cabandchart.png rename to resources/img/bandcharts/ca.png diff --git a/resources/images/bandchart/cnbandchart.png b/resources/img/bandcharts/cn.png similarity index 100% rename from resources/images/bandchart/cnbandchart.png rename to resources/img/bandcharts/cn.png diff --git a/resources/img/bandcharts/meta.json b/resources/img/bandcharts/meta.json new file mode 100644 index 0000000..ce082d2 --- /dev/null +++ b/resources/img/bandcharts/meta.json @@ -0,0 +1,7 @@ +{ + "ca": ["ca.png", "Canada", "Amateur radio bands in Canada", "**This bandplan is incomplete**; some bands, like 630m, are simply not present. It also does not cover any band above 30MHz.", "[RAC 0-30MHz Band Plan](https://www.rac.ca/wp-content/uploads/files/pdf/RAC%20Bandplan%20December%201%202015.pdf)", "πŸ‡¨πŸ‡¦"], + "cn": ["cn.png", "China", "Amateur radio bands in China", "", "Created by KN8U and NY7H", "πŸ‡¨πŸ‡³"], + "mx": ["mx.png", "Mexico", "Radio allocations in Mexico", "Full radio allocations chart for all services. No information specific to amateur radio is shown.", "SecretarΓ­a de Comunicaciones y Transportes (SCT) / Instituto Federal de Telecomunicaciones (IFT)", "πŸ‡²πŸ‡½"], + "nl": ["nl.png", "Netherlands", "Amateur radio bands in the Netherlands", "", "", "πŸ‡³πŸ‡±"], + "us": ["us.png", "USA", "Amateur radio bands in the USA", "", "*[ARRL Frequency Chart](https://www.arrl.org/shop/ARRL-Frequency-Chart-11-17/)* [[PDF]](http://www.arrl.org/files/file/Regulatory/Band%20Chart/Band%20Chart%20-%2011X17%20Color.pdf)", "πŸ‡ΊπŸ‡Έ"] +} diff --git a/resources/images/bandchart/mxbandchart.png b/resources/img/bandcharts/mx.png similarity index 100% rename from resources/images/bandchart/mxbandchart.png rename to resources/img/bandcharts/mx.png diff --git a/resources/images/bandchart/nlbandchart.png b/resources/img/bandcharts/nl.png similarity index 100% rename from resources/images/bandchart/nlbandchart.png rename to resources/img/bandcharts/nl.png diff --git a/resources/images/bandchart/usbandchart.png b/resources/img/bandcharts/us.png similarity index 100% rename from resources/images/bandchart/usbandchart.png rename to resources/img/bandcharts/us.png diff --git a/resources/images/map/arrlmap.png b/resources/img/maps/arrl-rac.png similarity index 100% rename from resources/images/map/arrlmap.png rename to resources/img/maps/arrl-rac.png diff --git a/resources/images/map/cnmap.png b/resources/img/maps/cn.png similarity index 100% rename from resources/images/map/cnmap.png rename to resources/img/maps/cn.png diff --git a/resources/img/maps/meta.json b/resources/img/maps/meta.json new file mode 100644 index 0000000..287b23e --- /dev/null +++ b/resources/img/maps/meta.json @@ -0,0 +1,6 @@ +{ + "arrl": ["arrl-rac.png", "ARRL Sections", "ARRL Sections", "", "", "πŸ‡ΊπŸ‡Έ"], + "rac": ["arrl-rac.png", "RAC Sections", "RAC Sections", "", "", "πŸ‡¨πŸ‡¦"], + "cn": ["cn.png", "China's Prefixes", "Map of prefix regions in China", "", "CRAC", "πŸ‡¨πŸ‡³"], + "us": ["us.png", "USA's Prefixes", "Map of prefix regions in the USA", "", "*[ARRL WAS Map](https://www.arrl.org/was-forms)* [[PDF]](http://www.arrl.org/files/file/Awards%20Application%20Forms/WASmap_Color.pdf)", "πŸ‡ΊπŸ‡Έ"] +} diff --git a/resources/images/map/usmap.png b/resources/img/maps/us.png similarity index 100% rename from resources/images/map/usmap.png rename to resources/img/maps/us.png diff --git a/templates/data/options.py b/templates/data/options.py index 194b7ad..87190ad 100644 --- a/templates/data/options.py +++ b/templates/data/options.py @@ -38,6 +38,7 @@ statuses = ["with lids on the air", "with fire"] # Timezone for the status (string) # See https://pythonhosted.org/pytz/ for more info status_tz = 'US/Eastern' + # The text to put in the "playing" status, with start and stop times time_statuses = [('with lids on 3.840', (00, 00), (6, 00)), ('with lids on 7.200', (6, 00), (10, 00)), @@ -48,3 +49,6 @@ time_statuses = [('with lids on 3.840', (00, 00), (6, 00)), # Emoji IDs and keywords for emoji reactions # Use the format {emoji_id (int): ('tuple', 'of', 'lowercase', 'keywords')} msg_reacts = {} + +# A :pika: emote's ID, None for no emote :c +pika = 658733876176355338