mirror of
https://github.com/miaowware/qrm2.git
synced 2026-06-02 05:54:40 -04:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62b549619e | |||
| 5910fc5191 | |||
| 2db9dee951 | |||
| e33d5f7213 | |||
| 0a278fe14f | |||
| 75bf8a638e | |||
| 9e36aab469 | |||
| cb1aed4278 | |||
| c27c0b8a48 | |||
| 9d419b159d | |||
| 858223b148 | |||
| d36702f2b3 | |||
| 6dfa35a8eb | |||
| 9f4bb04364 | |||
| 3de71f7325 | |||
| 22d60ed30f | |||
| 1cdbc66b5c | |||
| ea7cc7823a | |||
| 22c2cab4d1 | |||
| 63b1d81955 | |||
| 6e54a27f14 | |||
| f6d69f7498 | |||
| c569fdb422 | |||
| 98b2f30dcc | |||
| 1cb7ef5861 | |||
| bb3ee319b6 | |||
| aaec204c43 | |||
| 4c276bbc4d | |||
| 89e26dbd2b | |||
| 52995a8160 | |||
| 4e572fa6d8 | |||
| 08d611e8c4 | |||
| a140f74273 | |||
| 137b275c78 | |||
| 9f72a63202 | |||
| 1eed538d2c |
@@ -0,0 +1,87 @@
|
||||
name: Bug Report
|
||||
description: Report a bug to help us improve this project
|
||||
labels: [bug, 'needs triage']
|
||||
body:
|
||||
- id: description
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: There was a crash when...
|
||||
validations:
|
||||
required: true
|
||||
- id: steps
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Clear steps to reproduce the bug.
|
||||
placeholder: |
|
||||
1. Do the thing
|
||||
2. Do the other thing
|
||||
3. ???
|
||||
4. Crash :(
|
||||
validations:
|
||||
required: true
|
||||
- id: expected
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
placeholder: The app is supposed to show that thing.
|
||||
validations:
|
||||
required: true
|
||||
- id: source
|
||||
type: dropdown
|
||||
attributes:
|
||||
label: How did you download qrm?
|
||||
options:
|
||||
- Official Docker package
|
||||
- Git (clone)
|
||||
- Zip download on the releases package
|
||||
- I do not know (user of official instance)
|
||||
validations:
|
||||
required: true
|
||||
- id: runtime
|
||||
type: dropdown
|
||||
attributes:
|
||||
label: How are you running qrm?
|
||||
options:
|
||||
- docker-compose
|
||||
- Daemon (systemd, etc)
|
||||
- Docker
|
||||
- Command line (./run.sh)
|
||||
- I do not know (user of official instance)
|
||||
validations:
|
||||
required: true
|
||||
- id: version
|
||||
type: input
|
||||
attributes:
|
||||
label: What qrm version are you running?
|
||||
description: The version number, or the commit id if `dev` version. You can find both in `?info`.
|
||||
placeholder: v2.5.2
|
||||
validations:
|
||||
required: true
|
||||
- id: environment
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Environment
|
||||
description: If relevant, include list of software used and versions
|
||||
placeholder: |
|
||||
- Linux 5.8
|
||||
- Docker 19.04
|
||||
- id: logs
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Logs
|
||||
description: If you have a log associated with the bug (tracebacks, etc), paste it directly here.
|
||||
render: none
|
||||
# - id: context
|
||||
# type: textarea
|
||||
# attributes:
|
||||
# label: Additional context, screenshots, etc
|
||||
# description: Add any other relevant context about the problem here.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Additional context, screenshots, etc
|
||||
Add any other relevant context about the problem here.
|
||||
@@ -0,0 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request
|
||||
url: https://github.com/miaowware/qrm2/discussions/new?category=ideas
|
||||
about: Suggest an idea for this project
|
||||
- name: Support
|
||||
url: https://github.com/miaowware/qrm2/discussions/new?category=support
|
||||
about: Get help with qrm in GitHub Discussions
|
||||
- name: Support (Discord)
|
||||
url: https://discord.gg/SwyjdDN
|
||||
about: Get help with qrm on Discord
|
||||
+16
-2
@@ -7,6 +7,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
## [2.7.0] - 2021-04-03
|
||||
### Added
|
||||
- `?tex` command to render a LaTeX expression.
|
||||
- Configuration option to use another rTeX instance for `?tex`.
|
||||
- `?miltime` command to show the current time in all 25 military timezones.
|
||||
### Changed
|
||||
- Main name and aliases of `?bandplan`.
|
||||
- Recategorized the commands.
|
||||
### Fixed
|
||||
- Lack of input sanitisation in `?xkcd`.
|
||||
- Incorrect capitalisation of the categories in the `?help` command.
|
||||
|
||||
|
||||
## [2.6.0] - 2021-03-18
|
||||
### Added
|
||||
- MUF and foF2 maps from [prop.kc2g.com](https://prop.kc2g.com/).
|
||||
@@ -77,7 +90,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [2.3.1] - 2020-04-02
|
||||
### Fixed
|
||||
- Wordlist containing innappropriate words.
|
||||
- Wordlist containing inappropriate words.
|
||||
|
||||
|
||||
## [2.3.0] - 2020-03-30
|
||||
@@ -173,7 +186,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
## 1.0.0 - 2019-07-31 [YANKED]
|
||||
|
||||
|
||||
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.6.0...HEAD
|
||||
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.7.0...HEAD
|
||||
[2.7.0]: https://github.com/miaowware/qrm2/releases/tag/v2.7.0
|
||||
[2.6.0]: https://github.com/miaowware/qrm2/releases/tag/v2.6.0
|
||||
[2.5.1]: https://github.com/miaowware/qrm2/releases/tag/v2.5.1
|
||||
[2.5.0]: https://github.com/miaowware/qrm2/releases/tag/v2.5.0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
1. Make sure the `master` branch is up to date, then make yourself a new branch with a descriptive name.
|
||||
1. Once the forked repo is cloned and on the proper branch, you can set up the development environment.
|
||||
1. Install python 3.9 or higher.
|
||||
1. Install `libcairo` and `libjpeg`. Package names may vary by distro or OS.
|
||||
1. Run `make dev-install`.
|
||||
This should install everything you need to develop and run qrm.
|
||||
1. [Create a bot and token][2], and add it to `data/keys.py`.
|
||||
|
||||
@@ -18,6 +18,8 @@ Requires Python 3.9 or newer.
|
||||
|
||||
Prep the environment. For more information on extra options, see the [quick-bot-no-pain Makefile documentation](https://github.com/0x5c/quick-bot-no-pain/blob/master/docs/makefile.md).
|
||||
|
||||
Install `libcairo` and `libjpeg` (package names may vary by distro or OS). Then run:
|
||||
|
||||
```
|
||||
$ make install
|
||||
```
|
||||
@@ -30,13 +32,13 @@ $ run.sh
|
||||
|
||||
## Contributing
|
||||
|
||||
Check out the [contribution guidelines](/CONTRIBUTING.md) for more information about how to contribute to this project.
|
||||
Check out the [development](/DEVELOPING.md) and [contribution guidelines](https://github.com/miaowware/.github/blob/master/CONTRIBUTING.md) for more information about how to contribute to this project.
|
||||
|
||||
All issues and requests related to resources (including maps, band charts, data) should be added in [miaowware/qrm-resources](https://github.com/miaowware/qrm-resources).
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This program is released under the terms of the GNU General Public License,
|
||||
version 2. See `COPYING` for full license text.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Common tools for the bot.
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -9,6 +9,7 @@ the GNU General Public License, version 2.
|
||||
|
||||
|
||||
import collections
|
||||
import enum
|
||||
import json
|
||||
import re
|
||||
import traceback
|
||||
@@ -26,7 +27,7 @@ from discord import Emoji, Reaction, PartialEmoji
|
||||
import data.options as opt
|
||||
|
||||
|
||||
__all__ = ["colours", "cat", "emojis", "paths", "ImageMetadata", "ImagesGroup",
|
||||
__all__ = ["colours", "BoltCats", "Cats", "emojis", "paths", "ImageMetadata", "ImagesGroup",
|
||||
"embed_factory", "error_embed_factory", "add_react", "check_if_owner"]
|
||||
|
||||
|
||||
@@ -39,16 +40,24 @@ colours = SimpleNamespace(
|
||||
timeout=0xF26522,
|
||||
)
|
||||
|
||||
|
||||
class BoltCats(enum.Enum):
|
||||
ADMIN = "Bot Control"
|
||||
INFO = "Bot Information"
|
||||
|
||||
|
||||
# meow
|
||||
cat = SimpleNamespace(
|
||||
lookup="Information Lookup",
|
||||
fun="Fun",
|
||||
maps="Mapping",
|
||||
ref="Reference",
|
||||
study="Exam Study",
|
||||
weather="Land and Space Weather",
|
||||
admin="Bot Control",
|
||||
)
|
||||
class Cats(enum.Enum):
|
||||
CALC = "Calculators"
|
||||
CODES = "Code References and Tools"
|
||||
FUN = "Fun"
|
||||
LOOKUP = "Information Lookup"
|
||||
REF = "Reference"
|
||||
STUDY = "Exam Study"
|
||||
TIME = "Time and Time Zones"
|
||||
UTILS = "Utilities"
|
||||
WEATHER = "Land and Space Weather"
|
||||
|
||||
|
||||
emojis = SimpleNamespace(
|
||||
check_mark="✅",
|
||||
@@ -57,7 +66,8 @@ emojis = SimpleNamespace(
|
||||
question="❓",
|
||||
no_entry="⛔",
|
||||
bangbang="‼️",
|
||||
clock="⏱",
|
||||
clock="🕗",
|
||||
stopwatch="⏱",
|
||||
a="🇦",
|
||||
b="🇧",
|
||||
c="🇨",
|
||||
@@ -100,7 +110,7 @@ class ImagesGroup(collections.abc.Mapping):
|
||||
def __len__(self):
|
||||
return len(self._images)
|
||||
|
||||
def __getitem__(self, key: str):
|
||||
def __getitem__(self, key: str) -> ImageMetadata:
|
||||
return self._images[key]
|
||||
|
||||
def __iter__(self):
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
ae7q extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -29,13 +29,13 @@ class AE7QCog(commands.Cog):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
|
||||
@commands.group(name="ae7q", aliases=["ae"], case_insensitive=True, category=cmn.cat.lookup)
|
||||
@commands.group(name="ae7q", aliases=["ae"], case_insensitive=True, category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_lookup(self, ctx: commands.Context):
|
||||
"""Looks up a callsign, FRN, or Licensee ID on [ae7q.com](http://ae7q.com/)."""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help(ctx.command)
|
||||
|
||||
@_ae7q_lookup.command(name="call", aliases=["c"], category=cmn.cat.lookup)
|
||||
@_ae7q_lookup.command(name="call", aliases=["c"], category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_call(self, ctx: commands.Context, callsign: str):
|
||||
"""Looks up the history of a callsign on [ae7q.com](http://ae7q.com/)."""
|
||||
with ctx.typing():
|
||||
@@ -109,7 +109,7 @@ class AE7QCog(commands.Cog):
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@_ae7q_lookup.command(name="trustee", aliases=["t"], category=cmn.cat.lookup)
|
||||
@_ae7q_lookup.command(name="trustee", aliases=["t"], category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_trustee(self, ctx: commands.Context, callsign: str):
|
||||
"""Looks up the licenses for which a licensee is trustee on [ae7q.com](http://ae7q.com/)."""
|
||||
with ctx.typing():
|
||||
@@ -184,7 +184,7 @@ class AE7QCog(commands.Cog):
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@_ae7q_lookup.command(name="applications", aliases=["a"], category=cmn.cat.lookup)
|
||||
@_ae7q_lookup.command(name="applications", aliases=["a"], category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_applications(self, ctx: commands.Context, callsign: str):
|
||||
"""Looks up the application history for a callsign on [ae7q.com](http://ae7q.com/)."""
|
||||
"""
|
||||
@@ -262,7 +262,7 @@ class AE7QCog(commands.Cog):
|
||||
raise NotImplementedError("Application history lookup not yet supported. "
|
||||
"Check back in a later version of the bot.")
|
||||
|
||||
@_ae7q_lookup.command(name="frn", aliases=["f"], category=cmn.cat.lookup)
|
||||
@_ae7q_lookup.command(name="frn", aliases=["f"], category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_frn(self, ctx: commands.Context, frn: str):
|
||||
"""Looks up the history of an FRN on [ae7q.com](http://ae7q.com/)."""
|
||||
"""
|
||||
@@ -337,7 +337,7 @@ class AE7QCog(commands.Cog):
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@_ae7q_lookup.command(name="licensee", aliases=["l"], category=cmn.cat.lookup)
|
||||
@_ae7q_lookup.command(name="licensee", aliases=["l"], category=cmn.Cats.LOOKUP)
|
||||
async def _ae7q_licensee(self, ctx: commands.Context, licensee_id: str):
|
||||
"""Looks up the history of a licensee ID on [ae7q.com](http://ae7q.com/)."""
|
||||
with ctx.typing():
|
||||
|
||||
+14
-10
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Base extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -23,7 +23,11 @@ from data import options as opt
|
||||
|
||||
class QrmHelpCommand(commands.HelpCommand):
|
||||
def __init__(self):
|
||||
super().__init__(command_attrs={"help": "Shows help about qrm or a command", "aliases": ["h"]})
|
||||
super().__init__(command_attrs={
|
||||
"help": "Shows help about qrm or a command",
|
||||
"aliases": ["h"],
|
||||
"category": cmn.BoltCats.INFO
|
||||
})
|
||||
self.verify_checks = True
|
||||
self.context: commands.Context
|
||||
|
||||
@@ -73,7 +77,7 @@ class QrmHelpCommand(commands.HelpCommand):
|
||||
continue
|
||||
names = sorted([cmd.name for cmd in cmds])
|
||||
if cat is not None:
|
||||
embed.add_field(name=cat.title(), value=", ".join(names), inline=False)
|
||||
embed.add_field(name=cat.value, value=", ".join(names), inline=False)
|
||||
else:
|
||||
embed.add_field(name="Other", value=", ".join(names), inline=False)
|
||||
await self.context.send(embed=embed)
|
||||
@@ -136,7 +140,7 @@ class BaseCog(commands.Cog):
|
||||
self.bot_invite = (f"https://discordapp.com/oauth2/authorize?client_id={self.bot.user.id}"
|
||||
f"&scope=bot&permissions={opt.invite_perms}")
|
||||
|
||||
@commands.command(name="info", aliases=["about"])
|
||||
@commands.command(name="info", aliases=["about"], category=cmn.BoltCats.INFO)
|
||||
async def _info(self, ctx: commands.Context):
|
||||
"""Shows info about qrm."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -154,7 +158,7 @@ class BaseCog(commands.Cog):
|
||||
embed.set_thumbnail(url=str(self.bot.user.avatar_url))
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="ping", aliases=["beep"])
|
||||
@commands.command(name="ping", aliases=["beep"], category=cmn.BoltCats.INFO)
|
||||
async def _ping(self, ctx: commands.Context):
|
||||
"""Shows the current latency to the discord endpoint."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -167,7 +171,7 @@ class BaseCog(commands.Cog):
|
||||
embed.description = f"Current ping is {self.bot.latency*1000:.1f} ms"
|
||||
await ctx.send(content, embed=embed)
|
||||
|
||||
@commands.command(name="changelog", aliases=["clog"])
|
||||
@commands.command(name="changelog", aliases=["clog"], category=cmn.BoltCats.INFO)
|
||||
async def _changelog(self, ctx: commands.Context, version: str = "latest"):
|
||||
"""Shows what has changed in a bot version. Defaults to the latest version."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -203,7 +207,7 @@ class BaseCog(commands.Cog):
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="issue")
|
||||
@commands.command(name="issue", category=cmn.BoltCats.INFO)
|
||||
async def _issue(self, ctx: commands.Context):
|
||||
"""Shows how to create a bug report or feature request about the bot."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -215,7 +219,7 @@ class BaseCog(commands.Cog):
|
||||
[miaowware/qrm-resources](https://github.com/miaowware/qrm-resources/issues)."""
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="donate", aliases=["tip"])
|
||||
@commands.command(name="donate", aliases=["tip"], category=cmn.BoltCats.INFO)
|
||||
async def _donate(self, ctx: commands.Context):
|
||||
"""Shows ways to help support development of the bot via donations."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -226,7 +230,7 @@ class BaseCog(commands.Cog):
|
||||
embed.add_field(name=title, value=url, inline=False)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="invite", enabled=opt.enable_invite_cmd)
|
||||
@commands.command(name="invite", enabled=opt.enable_invite_cmd, category=cmn.BoltCats.INFO)
|
||||
async def _invite(self, ctx: commands.Context):
|
||||
"""Generates a link to invite the bot to a server."""
|
||||
if not (await self.bot.application_info()).bot_public:
|
||||
@@ -236,7 +240,7 @@ class BaseCog(commands.Cog):
|
||||
embed.description = self.bot_invite
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="echo", aliases=["e"], category=cmn.cat.admin)
|
||||
@commands.command(name="echo", aliases=["e"], category=cmn.BoltCats.ADMIN)
|
||||
@commands.check(cmn.check_if_owner)
|
||||
async def _echo(self, ctx: commands.Context,
|
||||
channel: Union[cmn.GlobalChannelConverter, commands.UserConverter], *, msg: str):
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""
|
||||
QRZ extension for qrm
|
||||
Callsign Lookup extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2020 classabbyamp, 0x5c (as qrz.py)
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -40,7 +41,7 @@ class QRZCog(commands.Cog):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@commands.command(name="call", aliases=["qrz"], category=cmn.cat.lookup)
|
||||
@commands.command(name="call", aliases=["qrz"], category=cmn.Cats.LOOKUP)
|
||||
async def _qrz_lookup(self, ctx: commands.Context, callsign: str, *flags):
|
||||
"""Looks up a callsign on [QRZ.com](https://www.qrz.com/). Add `--link` to only link the QRZ page."""
|
||||
flags = [f.lower() for f in flags]
|
||||
@@ -1,7 +1,8 @@
|
||||
"""
|
||||
Ham extension for qrm
|
||||
Codes extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c (as ham.py)
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -9,18 +10,15 @@ the GNU General Public License, version 2.
|
||||
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
from resources import callsign_info
|
||||
|
||||
|
||||
class HamCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.pfxs = callsign_info.options
|
||||
with open(cmn.paths.resources / "phonetics.1.json") as file:
|
||||
d = json.load(file)
|
||||
self.phonetics: dict[str, str] = d["phonetics"]
|
||||
@@ -28,7 +26,7 @@ class HamCog(commands.Cog):
|
||||
with open(cmn.paths.resources / "qcodes.1.json") as file:
|
||||
self.qcodes: dict = json.load(file)
|
||||
|
||||
@commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref)
|
||||
@commands.command(name="qcode", aliases=["q"], category=cmn.Cats.CODES)
|
||||
async def _qcode_lookup(self, ctx: commands.Context, qcode: str):
|
||||
"""Looks up the meaning of a Q Code."""
|
||||
qcode = qcode.upper()
|
||||
@@ -42,7 +40,7 @@ class HamCog(commands.Cog):
|
||||
embed.colour = cmn.colours.bad
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="phonetics", aliases=["ph", "phoneticize", "phoneticise", "phone"], category=cmn.cat.ref)
|
||||
@commands.command(name="phonetics", aliases=["ph", "phoneticize", "phoneticise", "phone"], category=cmn.Cats.CODES)
|
||||
async def _phonetics_lookup(self, ctx: commands.Context, *, msg: str):
|
||||
"""Returns NATO phonetics for a word or phrase."""
|
||||
result = ""
|
||||
@@ -58,51 +56,7 @@ class HamCog(commands.Cog):
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="utc", aliases=["z"], category=cmn.cat.ref)
|
||||
async def _utc_lookup(self, ctx: commands.Context):
|
||||
"""Returns the current time in UTC."""
|
||||
now = datetime.utcnow()
|
||||
result = "**" + now.strftime("%Y-%m-%d %H:%M") + "Z**"
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "The current time is:"
|
||||
embed.description = result
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref)
|
||||
async def _vanity_prefixes(self, ctx: commands.Context, country: str = ""):
|
||||
"""Lists valid callsign prefixes for different countries."""
|
||||
country = country.lower()
|
||||
embed = cmn.embed_factory(ctx)
|
||||
if country not in self.pfxs:
|
||||
desc = "Possible arguments are:\n"
|
||||
for key, val in self.pfxs.items():
|
||||
desc += f"`{key}`: {val.title}{(' ' + val.emoji if val.emoji else '')}\n"
|
||||
embed.title = f"{country} Not Found!"
|
||||
embed.description = desc
|
||||
embed.colour = cmn.colours.bad
|
||||
await ctx.send(embed=embed)
|
||||
return
|
||||
else:
|
||||
data = self.pfxs[country]
|
||||
embed.title = data.title + (" " + data.emoji if data.emoji else "")
|
||||
embed.description = data.desc
|
||||
embed.colour = cmn.colours.good
|
||||
|
||||
for name, val in data.calls.items():
|
||||
embed.add_field(name=name, value=val, inline=False)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="contests", aliases=["cc", "tests"], category=cmn.cat.ref)
|
||||
async def _contests(self, ctx: commands.Context):
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "Contest Calendar"
|
||||
embed.description = ("*We are currently rewriting the old, Chrome-based `contests` command. In the meantime, "
|
||||
"use [the website](https://www.contestcalendar.com/weeklycont.php).*")
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="phoneticweight", aliases=["pw"], category=cmn.cat.ref)
|
||||
@commands.command(name="phoneticweight", aliases=["pw"], category=cmn.Cats.CODES)
|
||||
async def _weight(self, ctx: commands.Context, *, msg: str):
|
||||
"""Calculates the phonetic weight of a callsign or message."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
Contest Calendar extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
"""
|
||||
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
|
||||
|
||||
class ContestCalendarCog(commands.Cog):
|
||||
@commands.command(name="contests", aliases=["cc", "tests"], category=cmn.Cats.LOOKUP)
|
||||
async def _contests(self, ctx: commands.Context):
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "Contest Calendar"
|
||||
embed.description = ("*We are currently rewriting the old, Chrome-based `contests` command. In the meantime, "
|
||||
"use [the website](https://www.contestcalendar.com/weeklycont.php).*")
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(ContestCalendarCog(bot))
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Conversion extension for qrm
|
||||
---
|
||||
Copyright (C) 2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2020-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -67,7 +67,7 @@ class DbConvCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(name="dbconv", aliases=["dbc"], category=cmn.cat.ref)
|
||||
@commands.command(name="dbconv", aliases=["dbc"], category=cmn.Cats.CALC)
|
||||
async def _db_conv(self, ctx: commands.Context,
|
||||
value: Optional[float] = None,
|
||||
unit_from: Optional[UnitConverter] = None,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""
|
||||
Lookup extension for qrm
|
||||
DXCC Prefix Lookup extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2020 classabbyamp, 0x5c (as lookup.py)
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -21,7 +22,7 @@ import common as cmn
|
||||
cty_path = Path("./data/cty.json")
|
||||
|
||||
|
||||
class LookupCog(commands.Cog):
|
||||
class DXCCCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
try:
|
||||
@@ -29,19 +30,7 @@ class LookupCog(commands.Cog):
|
||||
except OSError:
|
||||
self.cty = BigCty()
|
||||
|
||||
# TODO: See #107
|
||||
# @commands.command(name="sat", category=cmn.cat.lookup)
|
||||
# async def _sat_lookup(self, ctx: commands.Context, sat_name: str, grid1: str, grid2: str = None):
|
||||
# """Links to info about satellite passes on satmatch.com."""
|
||||
# now = datetime.utcnow().strftime("%Y-%m-%d%%20%H:%M")
|
||||
# if grid2 is None or grid2 == "":
|
||||
# await ctx.send(f"http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}"
|
||||
# f"?search_start_time={now}&duration_hrs=24")
|
||||
# else:
|
||||
# await ctx.send(f"http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}"
|
||||
# f"/obs2/{grid2}?search_start_time={now}&duration_hrs=24")
|
||||
|
||||
@commands.command(name="dxcc", aliases=["dx"], category=cmn.cat.lookup)
|
||||
@commands.command(name="dxcc", aliases=["dx"], category=cmn.Cats.LOOKUP)
|
||||
async def _dxcc_lookup(self, ctx: commands.Context, query: str):
|
||||
"""Gets DXCC info about a callsign prefix."""
|
||||
query = query.upper()
|
||||
@@ -82,6 +71,6 @@ def run_update(cty_obj, dump_loc):
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
lookupcog = LookupCog(bot)
|
||||
bot.add_cog(lookupcog)
|
||||
lookupcog._update_cty.start()
|
||||
dxcccog = DXCCCog(bot)
|
||||
bot.add_cog(dxcccog)
|
||||
dxcccog._update_cty.start()
|
||||
+9
-9
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Fun extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -26,22 +26,22 @@ class FunCog(commands.Cog):
|
||||
with open(cmn.paths.resources / "words.1.txt") as words_file:
|
||||
self.words = words_file.read().lower().splitlines()
|
||||
|
||||
@commands.command(name="xkcd", aliases=["x"], category=cmn.cat.fun)
|
||||
async def _xkcd(self, ctx: commands.Context, number: str):
|
||||
@commands.command(name="xkcd", aliases=["x"], category=cmn.Cats.FUN)
|
||||
async def _xkcd(self, ctx: commands.Context, number: int):
|
||||
"""Looks up an xkcd comic by number."""
|
||||
await ctx.send("http://xkcd.com/" + number)
|
||||
await ctx.send("http://xkcd.com/" + str(number))
|
||||
|
||||
@commands.command(name="tar", category=cmn.cat.fun)
|
||||
@commands.command(name="tar", category=cmn.Cats.FUN)
|
||||
async def _tar(self, ctx: commands.Context):
|
||||
"""Returns xkcd: tar."""
|
||||
await ctx.send("http://xkcd.com/1168")
|
||||
|
||||
@commands.command(name="standards", category=cmn.cat.fun)
|
||||
@commands.command(name="standards", category=cmn.Cats.FUN)
|
||||
async def _standards(self, ctx: commands.Context):
|
||||
"""Returns xkcd: Standards."""
|
||||
await ctx.send("http://xkcd.com/927")
|
||||
|
||||
@commands.command(name="worksplit", aliases=["split", "ft8"], category=cmn.cat.fun)
|
||||
@commands.command(name="worksplit", aliases=["split", "ft8"], category=cmn.Cats.FUN)
|
||||
async def _worksplit(self, ctx: commands.Context):
|
||||
"""Posts "Work split you lids"."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
@@ -49,12 +49,12 @@ class FunCog(commands.Cog):
|
||||
embed.set_image(url=opt.resources_url + self.imgs["worksplit"])
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="xd", hidden=True, category=cmn.cat.fun)
|
||||
@commands.command(name="xd", hidden=True, category=cmn.Cats.FUN)
|
||||
async def _xd(self, ctx: commands.Context):
|
||||
"""ecks dee"""
|
||||
await ctx.send("ECKS DEE :smirk:")
|
||||
|
||||
@commands.command(name="funetics", aliases=["fun"], category=cmn.cat.fun)
|
||||
@commands.command(name="funetics", aliases=["fun"], category=cmn.Cats.FUN)
|
||||
async def _funetics_lookup(self, ctx: commands.Context, *, msg: str):
|
||||
"""Generates fun/wacky phonetics for a word or phrase."""
|
||||
result = ""
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Grid extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -19,7 +19,7 @@ class GridCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(name="grid", category=cmn.cat.maps)
|
||||
@commands.command(name="grid", category=cmn.Cats.CALC)
|
||||
async def _grid_sq_lookup(self, ctx: commands.Context, lat: float, lon: float):
|
||||
("""Calculates the grid square for latitude and longitude coordinates."""
|
||||
"""\n\nCoordinates should be in decimal format, with negative being latitude South and longitude West."""
|
||||
@@ -33,7 +33,7 @@ class GridCog(commands.Cog):
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="latlong", aliases=["latlon", "loc", "ungrid"], category=cmn.cat.maps)
|
||||
@commands.command(name="latlong", aliases=["latlon", "loc", "ungrid"], category=cmn.Cats.CALC)
|
||||
async def _location_lookup(self, ctx: commands.Context, grid: str):
|
||||
("""Calculates the latitude and longitude for the center of a grid locator."""
|
||||
"""\n\nTo calculate the grid locator from a latitude and longitude, use `grid`"""
|
||||
@@ -49,7 +49,7 @@ class GridCog(commands.Cog):
|
||||
"latlong` to see other names for this command.*"))
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="griddistance", aliases=["griddist", "distance", "dist"], category=cmn.cat.maps)
|
||||
@commands.command(name="griddistance", aliases=["griddist", "distance", "dist"], category=cmn.Cats.CALC)
|
||||
async def _dist_lookup(self, ctx: commands.Context, grid1: str, grid2: str):
|
||||
"""Calculates the great circle distance and azimuthal bearing between two grid locators."""
|
||||
g1 = gridtools.Grid(grid1)
|
||||
|
||||
+28
-58
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Image extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -9,7 +9,6 @@ the GNU General Public License, version 2.
|
||||
|
||||
|
||||
import aiohttp
|
||||
from datetime import datetime
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
@@ -19,73 +18,44 @@ import data.options as opt
|
||||
|
||||
|
||||
class ImageCog(commands.Cog):
|
||||
gl_baseurl = "https://www.fourmilab.ch/cgi-bin/uncgi/Earth?img=ETOPO1_day-m.evif&dynimg=y&opt=-p"
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.bandcharts = cmn.ImagesGroup(cmn.paths.resources / "bandcharts.1.json")
|
||||
self.maps = cmn.ImagesGroup(cmn.paths.resources / "maps.1.json")
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
|
||||
@commands.command(name="bandplan", aliases=["plan", "bands"], category=cmn.cat.ref)
|
||||
async def _bandplan(self, ctx: commands.Context, region: str = ""):
|
||||
@commands.command(name="bandchart", aliases=["bandplan", "plan", "bands"], category=cmn.Cats.REF)
|
||||
async def _bandcharts(self, ctx: commands.Context, chart_id: str = ""):
|
||||
"""Gets the frequency allocations chart for a given country."""
|
||||
async with ctx.typing():
|
||||
arg = region.lower()
|
||||
embed = cmn.embed_factory(ctx)
|
||||
if arg not in self.bandcharts:
|
||||
desc = "Possible arguments are:\n"
|
||||
for key, img in self.bandcharts.items():
|
||||
desc += f"`{key}`: {img.name}{(' ' + img.emoji if img.emoji else '')}\n"
|
||||
embed.title = "Bandplan Not Found!"
|
||||
embed.description = desc
|
||||
embed.colour = cmn.colours.bad
|
||||
await ctx.send(embed=embed)
|
||||
return
|
||||
metadata: cmn.ImageMetadata = self.bandcharts[arg]
|
||||
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=opt.resources_url + metadata.filename)
|
||||
await ctx.send(embed=embed)
|
||||
await ctx.send(embed=create_embed(ctx, "Bandchart", self.bandcharts, chart_id))
|
||||
|
||||
@commands.command(name="map", category=cmn.cat.maps)
|
||||
@commands.command(name="map", category=cmn.Cats.REF)
|
||||
async def _map(self, ctx: commands.Context, map_id: str = ""):
|
||||
"""Posts a ham-relevant map."""
|
||||
async with ctx.typing():
|
||||
arg = map_id.lower()
|
||||
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)
|
||||
return
|
||||
metadata: cmn.ImageMetadata = self.maps[arg]
|
||||
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=opt.resources_url + metadata.filename)
|
||||
await ctx.send(embed=embed)
|
||||
await ctx.send(embed=create_embed(ctx, "Map", self.maps, map_id))
|
||||
|
||||
@commands.command(name="grayline", aliases=["greyline", "grey", "gray", "gl"], category=cmn.cat.maps)
|
||||
async def _grayline(self, ctx: commands.Context):
|
||||
"""Gets a map of the current greyline, where HF propagation is the best."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "Current Greyline Conditions"
|
||||
embed.colour = cmn.colours.good
|
||||
date_params = f"&date=1&utc={datetime.utcnow():%Y-%m-%d+%H:%M:%S}"
|
||||
embed.set_image(url=self.gl_baseurl + date_params)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def create_embed(ctx: commands.Context, not_found_name: str, db: cmn.ImagesGroup, img_id: str):
|
||||
"""Creates an embed for the image and its metadata, or list available images in the group."""
|
||||
img_id = img_id.lower()
|
||||
embed = cmn.embed_factory(ctx)
|
||||
if img_id not in db:
|
||||
desc = "Possible arguments are:\n"
|
||||
for key, img in db.items():
|
||||
desc += f"`{key}`: {img.name}{(' ' + img.emoji if img.emoji else '')}\n"
|
||||
embed.title = f"{not_found_name} Not Found!"
|
||||
embed.description = desc
|
||||
embed.colour = cmn.colours.bad
|
||||
return embed
|
||||
metadata = db[img_id]
|
||||
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=opt.resources_url + metadata.filename)
|
||||
return embed
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""
|
||||
Weather extension for qrm
|
||||
Land Weather extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2020 classabbyamp, 0x5c (as weather.py)
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -26,21 +27,7 @@ class WeatherCog(commands.Cog):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
|
||||
@commands.command(name="solarweather", aliases=["solar", "bandconditions", "cond", "condx", "conditions"],
|
||||
category=cmn.cat.weather)
|
||||
async def solarweather(self, ctx: commands.Context):
|
||||
"""Gets a solar weather report."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "☀️ Current Solar Weather"
|
||||
if ctx.invoked_with in ["bandconditions", "cond", "condx", "conditions"]:
|
||||
embed.add_field(name="⚠️ Deprecated Command Alias",
|
||||
value=(f"This command has been renamed to `{ctx.prefix}solar`!\n"
|
||||
"The alias you used will be removed in the next version."))
|
||||
embed.colour = cmn.colours.good
|
||||
embed.set_image(url="http://www.hamqsl.com/solarsun.php")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.group(name="weather", aliases=["wttr"], case_insensitive=True, category=cmn.cat.weather)
|
||||
@commands.group(name="weather", aliases=["wttr"], case_insensitive=True, category=cmn.Cats.WEATHER)
|
||||
async def _weather_conditions(self, ctx: commands.Context):
|
||||
"""Gets local weather conditions from [wttr.in](http://wttr.in/).
|
||||
|
||||
@@ -57,7 +44,7 @@ class WeatherCog(commands.Cog):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help(ctx.command)
|
||||
|
||||
@_weather_conditions.command(name="forecast", aliases=["fc", "future"], category=cmn.cat.weather)
|
||||
@_weather_conditions.command(name="forecast", aliases=["fc", "future"], category=cmn.Cats.WEATHER)
|
||||
async def _weather_conditions_forecast(self, ctx: commands.Context, *, location: str):
|
||||
"""Gets local weather forecast for the next three days from [wttr.in](http://wttr.in/).
|
||||
See help of the `weather` command for possible location types and options."""
|
||||
@@ -83,7 +70,7 @@ class WeatherCog(commands.Cog):
|
||||
embed.set_image(url=f"http://wttr.in/{loc}_{units}pnFQ.png")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@_weather_conditions.command(name="now", aliases=["n"], category=cmn.cat.weather)
|
||||
@_weather_conditions.command(name="now", aliases=["n"], category=cmn.Cats.WEATHER)
|
||||
async def _weather_conditions_now(self, ctx: commands.Context, *, location: str):
|
||||
"""Gets current local weather conditions from [wttr.in](http://wttr.in/).
|
||||
See help of the `weather` command for possible location types and options."""
|
||||
@@ -109,7 +96,7 @@ class WeatherCog(commands.Cog):
|
||||
embed.set_image(url=f"http://wttr.in/{loc}_0{units}pnFQ.png")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="metar", category=cmn.cat.weather)
|
||||
@commands.command(name="metar", category=cmn.Cats.WEATHER)
|
||||
async def metar(self, ctx: commands.Context, airport: str, hours: int = 0):
|
||||
"""Gets current raw METAR (Meteorological Terminal Aviation Routine Weather Report) for an airport. \
|
||||
Optionally, a number of hours can be given to show a number of hours of historical METAR data.
|
||||
@@ -118,7 +105,7 @@ class WeatherCog(commands.Cog):
|
||||
[ICAO code](https://en.wikipedia.org/wiki/List_of_airports_by_IATA_and_ICAO_code)."""
|
||||
await ctx.send(embed=await self.gen_metar_taf_embed(ctx, airport, hours, False))
|
||||
|
||||
@commands.command(name="taf", category=cmn.cat.weather)
|
||||
@commands.command(name="taf", category=cmn.Cats.WEATHER)
|
||||
async def taf(self, ctx: commands.Context, airport: str):
|
||||
"""Gets forecasted raw TAF (Terminal Aerodrome Forecast) data for an airport. Includes the latest METAR data.
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Morse Code extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -23,7 +23,7 @@ class MorseCog(commands.Cog):
|
||||
self.morse: dict[str, str] = d["morse"]
|
||||
self.ascii: dict[str, int] = d["ascii"]
|
||||
|
||||
@commands.command(name="morse", aliases=["cw"], category=cmn.cat.ref)
|
||||
@commands.command(name="morse", aliases=["cw"], category=cmn.Cats.CODES)
|
||||
async def _morse(self, ctx: commands.Context, *, msg: str):
|
||||
"""Converts ASCII to international morse code."""
|
||||
result = ""
|
||||
@@ -39,7 +39,7 @@ class MorseCog(commands.Cog):
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="unmorse", aliases=["demorse", "uncw", "decw"], category=cmn.cat.ref)
|
||||
@commands.command(name="unmorse", aliases=["demorse", "uncw", "decw"], category=cmn.Cats.CODES)
|
||||
async def _unmorse(self, ctx: commands.Context, *, msg: str):
|
||||
"""Converts international morse code to ASCII."""
|
||||
result = ""
|
||||
@@ -59,7 +59,7 @@ class MorseCog(commands.Cog):
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="cwweight", aliases=["weight", "cww"], category=cmn.cat.ref)
|
||||
@commands.command(name="cwweight", aliases=["weight", "cww"], category=cmn.Cats.CODES)
|
||||
async def _weight(self, ctx: commands.Context, *, msg: str):
|
||||
"""Calculates the CW weight of a callsign or message."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Prefixes Lookup extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
"""
|
||||
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
from resources import callsign_info
|
||||
|
||||
|
||||
class PrefixesCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.pfxs = callsign_info.options
|
||||
|
||||
@commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.Cats.REF)
|
||||
async def _vanity_prefixes(self, ctx: commands.Context, country: str = ""):
|
||||
"""Lists valid callsign prefixes for different countries."""
|
||||
country = country.lower()
|
||||
embed = cmn.embed_factory(ctx)
|
||||
if country not in self.pfxs:
|
||||
desc = "Possible arguments are:\n"
|
||||
for key, val in self.pfxs.items():
|
||||
desc += f"`{key}`: {val.title}{(' ' + val.emoji if val.emoji else '')}\n"
|
||||
embed.title = f"{country} Not Found!"
|
||||
embed.description = desc
|
||||
embed.colour = cmn.colours.bad
|
||||
await ctx.send(embed=embed)
|
||||
return
|
||||
else:
|
||||
data = self.pfxs[country]
|
||||
embed.title = data.title + (" " + data.emoji if data.emoji else "")
|
||||
embed.description = data.desc
|
||||
embed.colour = cmn.colours.good
|
||||
|
||||
for name, val in data.calls.items():
|
||||
embed.add_field(name=name, value=val, inline=False)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(PrefixesCog(bot))
|
||||
+30
-3
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Propagation extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -12,6 +12,7 @@ from io import BytesIO
|
||||
|
||||
import aiohttp
|
||||
import cairosvg
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
import discord.ext.commands as commands
|
||||
@@ -22,12 +23,14 @@ import common as cmn
|
||||
class PropagationCog(commands.Cog):
|
||||
muf_url = "https://prop.kc2g.com/renders/current/mufd-normal-now.svg"
|
||||
fof2_url = "https://prop.kc2g.com/renders/current/fof2-normal-now.svg"
|
||||
gl_baseurl = "https://www.fourmilab.ch/cgi-bin/uncgi/Earth?img=ETOPO1_day-m.evif&dynimg=y&opt=-p"
|
||||
n0nbh_sun_url = "http://www.hamqsl.com/solarsun.php"
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
|
||||
@commands.command(name="mufmap", aliases=["muf"], category=cmn.cat.weather)
|
||||
@commands.command(name="mufmap", aliases=["muf"], category=cmn.Cats.WEATHER)
|
||||
async def mufmap(self, ctx: commands.Context):
|
||||
"""Shows a world map of the Maximum Usable Frequency (MUF)."""
|
||||
async with ctx.typing():
|
||||
@@ -41,7 +44,7 @@ class PropagationCog(commands.Cog):
|
||||
embed.set_image(url="attachment://muf_map.png")
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.command(name="fof2map", aliases=["fof2", "critfreq"], category=cmn.cat.weather)
|
||||
@commands.command(name="fof2map", aliases=["fof2", "critfreq"], category=cmn.Cats.WEATHER)
|
||||
async def fof2map(self, ctx: commands.Context):
|
||||
"""Shows a world map of the Critical Frequency (foF2)."""
|
||||
async with ctx.typing():
|
||||
@@ -55,6 +58,30 @@ class PropagationCog(commands.Cog):
|
||||
embed.set_image(url="attachment://fof2_map.png")
|
||||
await ctx.send(file=file, embed=embed)
|
||||
|
||||
@commands.command(name="grayline", aliases=["greyline", "grey", "gray", "gl"], category=cmn.Cats.WEATHER)
|
||||
async def grayline(self, ctx: commands.Context):
|
||||
"""Gets a map of the current greyline, where HF propagation is the best."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "Current Greyline Conditions"
|
||||
embed.colour = cmn.colours.good
|
||||
date_params = f"&date=1&utc={datetime.utcnow():%Y-%m-%d+%H:%M:%S}"
|
||||
embed.set_image(url=self.gl_baseurl + date_params)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="solarweather", aliases=["solar", "bandconditions", "cond", "condx", "conditions"],
|
||||
category=cmn.Cats.WEATHER)
|
||||
async def solarweather(self, ctx: commands.Context):
|
||||
"""Gets a solar weather report."""
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "☀️ Current Solar Weather"
|
||||
if ctx.invoked_with in ["bandconditions", "cond", "condx", "conditions"]:
|
||||
embed.add_field(name="⚠️ Deprecated Command Alias",
|
||||
value=(f"This command has been renamed to `{ctx.prefix}solar`!\n"
|
||||
"The alias you used will be removed in the next version."))
|
||||
embed.colour = cmn.colours.good
|
||||
embed.set_image(url=self.n0nbh_sun_url)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(PropagationCog(bot))
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Study extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -31,7 +31,7 @@ class StudyCog(commands.Cog):
|
||||
self.source = "Data courtesy of [HamStudy.org](https://hamstudy.org/)"
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
|
||||
@commands.command(name="hamstudy", aliases=["rq", "randomquestion", "randomq"], category=cmn.cat.study)
|
||||
@commands.command(name="hamstudy", aliases=["rq", "randomquestion", "randomq"], category=cmn.Cats.STUDY)
|
||||
async def _random_question(self, ctx: commands.Context, country: str = "", level: str = "", element: str = ""):
|
||||
"""Gets a random question from [HamStudy's](https://hamstudy.org) question pools."""
|
||||
with ctx.typing():
|
||||
@@ -170,7 +170,7 @@ class StudyCog(commands.Cog):
|
||||
except asyncio.TimeoutError:
|
||||
embed.set_field_at(1, name="Answers", value=answers_str_bolded, inline=False)
|
||||
embed.set_field_at(2, name="Answer",
|
||||
value=(f"{cmn.emojis.clock} "
|
||||
value=(f"{cmn.emojis.stopwatch} "
|
||||
f"**Timed out!** The correct answer was {self.choices[question['answer']]}"))
|
||||
embed.colour = cmn.colours.timeout
|
||||
await q_msg.edit(embed=embed)
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
TeX extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
"""
|
||||
|
||||
|
||||
import aiohttp
|
||||
from io import BytesIO
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import discord
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
import data.options as opt
|
||||
|
||||
|
||||
class TexCog(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
|
||||
with open(cmn.paths.resources / "template.1.tex") as latex_template:
|
||||
self.template = latex_template.read()
|
||||
|
||||
@commands.command(name="tex", aliases=["latex"], category=cmn.Cats.UTILS)
|
||||
async def tex(self, ctx: commands.Context, *, expr: str):
|
||||
"""Renders a LaTeX expression."""
|
||||
payload = {
|
||||
"format": "png",
|
||||
"code": self.template.replace("#CONTENT#", expr),
|
||||
"quality": 50
|
||||
}
|
||||
|
||||
with ctx.typing():
|
||||
# ask rTeX to render our expression
|
||||
async with self.session.post(urljoin(opt.rtex_instance, "api/v2"), json=payload) as r:
|
||||
if r.status != 200:
|
||||
raise cmn.BotHTTPError(r)
|
||||
|
||||
render_result = await r.json()
|
||||
if render_result["status"] != "success":
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "LaTeX Rendering Failed!"
|
||||
embed.description = render_result.get("description", "Unknown error")
|
||||
embed.colour = cmn.colours.bad
|
||||
await ctx.send(embed=embed)
|
||||
return
|
||||
|
||||
# if rendering went well, download the file given in the response
|
||||
async with self.session.get(urljoin(opt.rtex_instance, "api/v2/" + render_result["filename"])) as r:
|
||||
png_buffer = BytesIO(await r.read())
|
||||
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "LaTeX Expression"
|
||||
embed.description = "Rendered by [rTeX](https://rtex.probablyaweb.site/)."
|
||||
embed.set_image(url="attachment://tex.png")
|
||||
await ctx.send(file=discord.File(png_buffer, "tex.png"), embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(TexCog(bot))
|
||||
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
Time extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
|
||||
|
||||
class TimeCog(commands.Cog):
|
||||
offsets = [
|
||||
("Y", "", timedelta(hours=-12)),
|
||||
("X", "", timedelta(hours=-11)),
|
||||
("W", "", timedelta(hours=-10)),
|
||||
("V", "", timedelta(hours=-9)),
|
||||
("U", "", timedelta(hours=-8)),
|
||||
("T", "", timedelta(hours=-7)),
|
||||
("S", "", timedelta(hours=-6)),
|
||||
("R", "", timedelta(hours=-5)),
|
||||
("Q", "", timedelta(hours=-4)),
|
||||
("P", "", timedelta(hours=-3)),
|
||||
("O", "", timedelta(hours=-2)),
|
||||
("N", "", timedelta(hours=-1)),
|
||||
("Z", "UTC", timedelta(hours=0)),
|
||||
("A", "", timedelta(hours=+1)),
|
||||
("B", "", timedelta(hours=+2)),
|
||||
("C", "", timedelta(hours=+3)),
|
||||
("D", "", timedelta(hours=+4)),
|
||||
("E", "", timedelta(hours=+5)),
|
||||
("F", "", timedelta(hours=+6)),
|
||||
("G", "", timedelta(hours=+7)),
|
||||
("H", "", timedelta(hours=+8)),
|
||||
("I", "", timedelta(hours=+9)),
|
||||
("K", "", timedelta(hours=+10)),
|
||||
("L", "", timedelta(hours=+11)),
|
||||
("M", "", timedelta(hours=+12))
|
||||
]
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(name="utc", aliases=["z"], category=cmn.Cats.TIME)
|
||||
async def _utc_lookup(self, ctx: commands.Context):
|
||||
"""Returns the current time in UTC."""
|
||||
now = datetime.utcnow()
|
||||
result = "**" + now.strftime("%Y-%m-%d %H:%M") + "Z**"
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = "The current time is:"
|
||||
embed.description = result
|
||||
embed.colour = cmn.colours.good
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="miltime", category=cmn.Cats.TIME)
|
||||
async def miltime(self, ctx: commands.Context):
|
||||
"""Prints the current time in all 25 military time zones."""
|
||||
time = ctx.message.created_at
|
||||
embed = cmn.embed_factory(ctx)
|
||||
embed.title = f"{cmn.emojis.clock} Military Time Zones Now"
|
||||
embed.colour = cmn.colours.good
|
||||
embed.description = "```"
|
||||
embed.description += "\n".join([f"{x}: {time + z :%Y-%m-%d %H:%M} {y}" for x, y, z in self.offsets])
|
||||
embed.description += "```"
|
||||
embed.add_field(name="Notes", value=(
|
||||
"**J** is not present in the table, and is used for local time.\n"
|
||||
"The zones are referenced by their letters, using phonetics.\n"
|
||||
f"You can check the NATO phonetics for a letter using the `{ctx.prefix}phonetics` command."
|
||||
))
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(TimeCog(bot))
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Static info about the bot.
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -15,5 +15,5 @@ contributing = """Check out the [source on GitHub](https://github.com/miaowware/
|
||||
|
||||
All issues and requests related to resources (including maps, band charts, data) should be added \
|
||||
in [miaowware/qrm-resources](https://github.com/miaowware/qrm-resources)."""
|
||||
release = "2.6.0"
|
||||
release = "2.7.0"
|
||||
bot_server = "https://discord.gg/Ntbg3J4"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"""
|
||||
qrm, a bot for Discord
|
||||
---
|
||||
Copyright (C) 2019-2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
@@ -74,7 +74,7 @@ bot.qrm.debug_mode = debug_mode
|
||||
|
||||
# --- Commands ---
|
||||
|
||||
@bot.command(name="restart", aliases=["rs"], category=cmn.cat.admin)
|
||||
@bot.command(name="restart", aliases=["rs"], category=cmn.BoltCats.ADMIN)
|
||||
@commands.check(cmn.check_if_owner)
|
||||
async def _restart_bot(ctx: commands.Context):
|
||||
"""Restarts the bot."""
|
||||
@@ -85,7 +85,7 @@ async def _restart_bot(ctx: commands.Context):
|
||||
await bot.logout()
|
||||
|
||||
|
||||
@bot.command(name="shutdown", aliases=["shut"], category=cmn.cat.admin)
|
||||
@bot.command(name="shutdown", aliases=["shut"], category=cmn.BoltCats.ADMIN)
|
||||
@commands.check(cmn.check_if_owner)
|
||||
async def _shutdown_bot(ctx: commands.Context):
|
||||
"""Shuts down the bot."""
|
||||
@@ -96,7 +96,7 @@ async def _shutdown_bot(ctx: commands.Context):
|
||||
await bot.logout()
|
||||
|
||||
|
||||
@bot.group(name="extctl", aliases=["ex"], case_insensitive=True, category=cmn.cat.admin)
|
||||
@bot.group(name="extctl", aliases=["ex"], case_insensitive=True, category=cmn.BoltCats.ADMIN)
|
||||
@commands.check(cmn.check_if_owner)
|
||||
async def _extctl(ctx: commands.Context):
|
||||
"""Extension control commands.
|
||||
@@ -275,7 +275,8 @@ resource_versions = {
|
||||
"morse": "v1",
|
||||
"phonetics": "v1",
|
||||
"qcodes": "v1",
|
||||
"funetics": "v1"
|
||||
"funetics": "v1",
|
||||
"latex_template": "v1",
|
||||
}
|
||||
|
||||
bot.qrm.rm = ResourcesManager(cmn.paths.resources, opt.resources_url, resource_versions)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resource schemas generator for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Information about callsigns for the prefixes command in hamcog.
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of discord-qrmbot and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Information about callsigns for the CA prefixes command in hamcog.
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of discord-qrmbot and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Information about callsigns for the US prefixes command in hamcog.
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of discord-qrmbot and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
A listing of hamstudy command resources
|
||||
---
|
||||
Copyright (C) 2019-2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of discord-qrmbot and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -31,19 +31,23 @@ owners_uids = (200102491231092736, 564766093051166729)
|
||||
|
||||
# The extensions to load when running the bot.
|
||||
exts = [
|
||||
"ae7q",
|
||||
"base",
|
||||
"ae7q",
|
||||
"callsign",
|
||||
"codes",
|
||||
"contests",
|
||||
"dbconv",
|
||||
"dxcc",
|
||||
"fun",
|
||||
"grid",
|
||||
"ham",
|
||||
"image",
|
||||
"lookup",
|
||||
"land_weather",
|
||||
"morse",
|
||||
"qrz",
|
||||
"study",
|
||||
"weather",
|
||||
"dbconv",
|
||||
"prefixes",
|
||||
"propagation",
|
||||
"study",
|
||||
"tex",
|
||||
"time",
|
||||
]
|
||||
|
||||
# URL to the resources
|
||||
@@ -86,3 +90,6 @@ msg_reacts = {}
|
||||
|
||||
# A :pika: emote's ID, None for no emote :c
|
||||
pika = 658733876176355338
|
||||
|
||||
# Base URL to a deployment of rTeX, which performs LaTeX rendering.
|
||||
rtex_instance = "https://rtex.probablyaweb.site/"
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Wrapper to handle aiohttp connector creation.
|
||||
---
|
||||
Copyright (C) 2020 Abigail Gold, 0x5c
|
||||
Copyright (C) 2020-2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resources manager for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resource index models for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 Abigail Gold, 0x5c
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
|
||||
This file is part of qrm2 and is released under the terms of
|
||||
the GNU General Public License, version 2.
|
||||
|
||||
Reference in New Issue
Block a user