25 Commits

Author SHA1 Message Date
classabbyamp 7e35e8949a release v2.4.0 (#254) 2020-09-27 18:03:52 -04:00
classabbyamp 77b572eb3e add a decibel conversion command (#250)
fixes #231
2020-09-27 17:52:52 -04:00
classabbyamp be042a9641 add dev targets to makefile (#252)
fixes #251
2020-09-27 16:52:37 -04:00
classabbyamp 488ae6cc98 fix displaying multiple prefixes, add option to display ?help in status (#249)
* fix displaying multiple prefixes, add option to display ?help in status
Fixes #229

Co-authored-by: 0x5c <dev@0x5c.io>
2020-09-27 16:36:39 -04:00
classabbyamp a65fd04dbd add cq zone, itu zone and region, canadian maps (#248)
* add cq zone, itu zone and region, canadian maps
* update arrl/rac maps
* add attribution to all maps

Fixes #112
Progress on #130

Co-authored-by: 0x5c <dev@0x5c.io>
2020-09-27 16:30:59 -04:00
classabbyamp 6329718d29 Contribution and PR Guidelines (#219)
* Create pull_request_template.md
* add contribution guidelines

fixes #160
2020-09-27 16:18:09 -04:00
classabbyamp 756a15c4c5 added ?worksplit command (#247)
fixes #233
2020-09-27 16:07:21 -04:00
classabbyamp b462527211 add canadian callsign info, improve the prefix info data system
fixes #243
2020-09-24 19:02:12 -04:00
0x5c 93b42e64dc Merge pull request #240 from miaowware/dev-requirements.txt
Add dev-requirements.txt
2020-09-24 10:23:26 -04:00
classabbyamp f6103ef6f1 Merge pull request #245 from miaowware/dockerumentation-v2 2020-09-24 10:18:27 -04:00
Abigail G 090b96482d update docker documentation to mention github registry
also corrected a couple errors
fixes #212
2020-09-24 00:14:45 -04:00
0x5c 6d71974ea1 Add dev-requirements.txt
- Various dev tools like mypy, flake8, and discord.py typing stubs
2020-09-08 03:44:24 -04:00
Abigail Gold 0af82ac241 pin dependency versions (#239) 2020-07-23 00:05:32 -04:00
0x5c 2ba6249b90 Merge pull request #223 from miaowware/action-update
Update linting action
2020-04-19 21:25:08 -04:00
0x5c 2c11dad358 Update linting action
Should now run on PR
2020-04-19 21:10:34 -04:00
Abigail 5f796d479e bump version to 2.3.1 2020-04-02 23:04:29 -04:00
Abigail Gold 3ba55d4c35 update funetics words list (#218)
Fixes #217
2020-04-02 23:02:19 -04:00
Abigail f4ed93dc76 bump version to 2.3.0 2020-03-30 19:00:38 -04:00
Abigail Gold 2cb4b03532 add phonetic weight command (#215)
Fixes #170

Co-authored-by: 0x5c <dev@0x5c.io>
2020-03-30 18:56:29 -04:00
Abigail Gold bc93462c29 convert all OrderedDicts to dictionaries (#214)
Fixes #184

Co-authored-by: 0x5c <dev@0x5c.io>
2020-03-30 18:54:33 -04:00
Abigail Gold 6867c45c8c add ?standards command for xkcd 927 (#213)
Fixes #187
2020-03-30 18:24:50 -04:00
Abigail dcbb7acab8 bump release to 2.2.3 2020-03-29 12:34:58 -04:00
Abigail Gold 3803ce6045 add git commit hash to file "git_commit" for automatically-built docker images (#211) 2020-03-29 12:34:12 -04:00
Abigail Gold 8ca4911072 make commands case-insensitive (#210)
Fixes #209
2020-03-28 19:07:23 -04:00
Abigail Gold 6e2468f04f create github action for docker image creation and publication (#206) 2020-03-28 18:18:29 -04:00
37 changed files with 833 additions and 44332 deletions
+29
View File
@@ -0,0 +1,29 @@
### Description
*Describe the changes you made here.*
Fixes #{issue}
### Type of change
Please delete options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- This change requires a documentation update
### How has this been tested?
*Describe the procedure used for verifying your changes here.*
### Checklist
- [ ] Issue exists for PR
- [ ] Code reviewed by the author
- [ ] Code documented (comments or other documentation)
- [ ] Changes tested
- [ ] `flake8` passes
- [ ] `CHANGELOG.md` updated
- [ ] Informative commit messages
- [ ] Descriptive PR title
+58
View File
@@ -0,0 +1,58 @@
name: Docker Build and Push
on:
push:
# Publish `master` as Docker `dev` image.
branches:
- master
# Publish `v*` tags as releases and as `latest`.
tags:
- v*
env:
IMAGE_NAME: qrm2
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build image
run: |
echo ${{ github.sha }} > git_commit
docker build . --file Dockerfile -t $IMAGE_NAME
- name: Log into Github Package Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin
- name: Log into Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Push image to registries
run: |
GITHUB_IMAGE_ID=docker.pkg.github.com/${{ github.repository }}/$IMAGE_NAME
DOCKER_IMAGE_ID=${{ secrets.DOCKER_USERNAME }}/$IMAGE_NAME
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
[[ "$VERSION" == "master" ]] && VERSION=dev
echo GITHUB_IMAGE_ID=$GITHUB_IMAGE_ID
echo DOCKER_IMAGE_ID=$DOCKER_IMAGE_ID
echo VERSION=$VERSION
# tag for Github Registry
docker tag $IMAGE_NAME $GITHUB_IMAGE_ID:$VERSION
[[ "$VERSION" != "dev" ]] && docker tag $IMAGE_NAME $GITHUB_IMAGE_ID:latest
docker push $GITHUB_IMAGE_ID
# tag for Docker Hub
docker tag $IMAGE_NAME $DOCKER_IMAGE_ID:$VERSION
[[ "$VERSION" != "dev" ]] && docker tag $IMAGE_NAME $DOCKER_IMAGE_ID:latest
docker push $DOCKER_IMAGE_ID
+1 -1
View File
@@ -1,6 +1,6 @@
name: Linting name: Linting
on: [push] on: [push,pull_request]
jobs: jobs:
flake8_py3: flake8_py3:
+2
View File
@@ -9,6 +9,8 @@ cty.zip
/docker-compose.yml /docker-compose.yml
.vscode/
######################################################### #########################################################
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
+43 -1
View File
@@ -7,6 +7,43 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
## [2.4.0] - 2020-09-27
### Added
- Canadian prefix info to the `?prefixes` command.
- `?worksplit` command.
- Maps for CQ Zones, ITU Zones, ITU Regions, and Canadian prefixes.
- Attribution for all maps.
- Option to append ` | ?help` to the playing status.
- `?dbconv` command to convert voltage, power, and antenna gain values.
### Changed
- ARRL/RAC section maps to include all current ARRL/RAC sections.
### Fixed
- Issue where multiple prefixes were not handled properly.
## [2.3.2] - 2020-07-22
### Fixed
- Dependency issues
## [2.3.1] - 2020-04-02
### Fixed
- Wordlist containing innappropriate words.
## [2.3.0] - 2020-03-30
### Added
- `?phoneticweight` command, which calculates a message's length in syllables.
- `?standards` command to display [xkcd 927](https://xkcd.com/927/).
### Changed
- Python>=3.7 now required.
## [2.2.3] - 2020-03-29
### Fixed
- Commands are no longer case-sensitive.
## [2.2.2] - 2020-02-25 ## [2.2.2] - 2020-02-25
### Fixed ### Fixed
- Fixed issue where HamStudy questions with images would cause an error. - Fixed issue where HamStudy questions with images would cause an error.
@@ -87,7 +124,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 1.0.0 - 2019-07-31 [YANKED] ## 1.0.0 - 2019-07-31 [YANKED]
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.2.2...HEAD [Unreleased]: https://github.com/miaowware/qrm2/compare/v2.4.0...HEAD
[2.4.0]: https://github.com/miaowware/qrm2/releases/tag/v2.4.0
[2.3.2]: https://github.com/miaowware/qrm2/releases/tag/v2.3.2
[2.3.1]: https://github.com/miaowware/qrm2/releases/tag/v2.3.1
[2.3.0]: https://github.com/miaowware/qrm2/releases/tag/v2.3.0
[2.2.3]: https://github.com/miaowware/qrm2/releases/tag/v2.2.3
[2.2.2]: https://github.com/miaowware/qrm2/releases/tag/v2.2.2 [2.2.2]: https://github.com/miaowware/qrm2/releases/tag/v2.2.2
[2.2.1]: https://github.com/miaowware/qrm2/releases/tag/v2.2.1 [2.2.1]: https://github.com/miaowware/qrm2/releases/tag/v2.2.1
[2.2.0]: https://github.com/miaowware/qrm2/releases/tag/v2.2.0 [2.2.0]: https://github.com/miaowware/qrm2/releases/tag/v2.2.0
+77
View File
@@ -0,0 +1,77 @@
# Contributing to qrm
## Before You Start
- Make sure there's an issue for the feature, bugfix, or other improvement you want to make.
- Make sure it's something that the project maintainers want.
We can discuss it and assign the issue to you.
- Make sure work isn't already being done on the issue.
### Environment Setup
Once all of the above is done, you can get started by setting up your development envronment.
1. [Fork this repo][1] into your own GitHub namespace.
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.7 or higher.
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`.
Also add your [QRZ credentials][3] if needed.
1. In `data/options.py`, change values as needed.
Some commands require adding your Discord user ID to `owner_uids`.
1. To activate the virtual env that was created by `make`, run `source botenv/bin/activate` (or the equivelent for your shell or operating system).
## While You Develop
To run qrm, use the command `./run.sh`.
We recommend you use the `--pass-errors` flags to avoid perpetual restart loops if you break the bot.
It exists because repeatedly mashing [Ctrl+C] at high speed to break a fast loop is not fun.
Commit messages should be descriptive and mention issues that they fix ("fixes #123") or contain progress on ("progress on #123").
Make commits as needed, but try to keep it reasonable.
If there are too many, your contribution may be squashed when merged.
You may want to squash your commits locally yourself:
```sh
git reset --soft [commit before your changes]
git commit
```
Make sure to document your code as you go, in both comments and external documentation (in `/dev-notes/`) as needed.
`dev-notes` is especially important if you introduce a new json file format or to document some development process (like the command to crush the various images in the repository).
**Test your changes.**
If your code doesn't work, it's not ready for merging.
Make sure you not only test intended behaviour, but also edge cases and error cases.
Make sure to run `flake8` to ensure your code uses the proper style, and `mypy [files...]` to ensure proper typing.
If you're making a user-facing change, put a quick summary in `CHANGELOG.md` under the `[Unreleased]` heading.
Follow the [Keep a Changelog][4] format.
### A Note on Style
qrm tries to keep to PEP 8 style whenever possible.
Use the utility `flake8` to check that you follow this style.
When you start a PR or push commits, GitHub will automatically run this for you;
if that fails, you will be expected to fix those errors before merge.
Otherwise, try to follow the existing style:
double-quotes except when required to be single,
indentation of mult-line structures matching other examples in the code,
add type hints,
etc.
## When You're Ready to Merge
1. When you have finished working on your contribution, create a pull request from your fork's branch into the master branch of this repository.
1. Read through and complete the pull request template.
If the checklist is not complete, your contribution will not be merged.
1. Your pull request will get reviewed by at least one maintainer.
1. If approved, another maintainer may merge the pull request if everything looks good.
[1]: https://github.com/miaowware/qrm2/fork
[2]: https://discordpy.readthedocs.io/en/latest/discord.html
[3]: https://www.qrz.com/page/xml_data.html
[4]: https://keepachangelog.com/en/1.0.0/
+11
View File
@@ -71,6 +71,17 @@ clean:
### Dev targets ### ### Dev targets ###
.PHONY: dev-install
dev-install: $(BOTENV)/dev_req_done data/options.py data/keys.py
# Installing dev requirements
$(BOTENV)/dev_req_done: dev-requirements.txt $(BOTENV)/success
@echo "\033[34;1m--> Installing the dependencies...\033[0m"
@. $(BOTENV)/bin/activate; \
pip install ${PIP_OUTPUT} -U pip setuptools wheel; \
pip install ${PIP_OUTPUT} -U -r dev-requirements.txt
@touch $(BOTENV)/dev_req_done
### Special targets ### ### Special targets ###
+8 -5
View File
@@ -1,6 +1,6 @@
# Docker help for qrm2 # Docker help for qrm2
You have multiple ways to use docker to run an instance of qrm2 You have multiple ways to use docker to run an instance of qrm2.
- [Docker help for qrm2](#docker-help-for-qrm2) - [Docker help for qrm2](#docker-help-for-qrm2)
- [Using docker-compose and the prebuilt-image (recommended)](#using-docker-compose-and-the-prebuilt-image-recommended) - [Using docker-compose and the prebuilt-image (recommended)](#using-docker-compose-and-the-prebuilt-image-recommended)
@@ -23,13 +23,16 @@ This is the easiest method for running the bot without any modifications.
version: '3' version: '3'
services: services:
qrm2: qrm2:
image: "classabbyamp/discord-qrm2:latest" image: "classabbyamp/qrm2:latest"
# OR
# image: "docker.pkg.github.com/miaowware/qrm2/qrm2:latest"
restart: on-failure restart: on-failure
volumes: volumes:
- "./data:/app/data:rw" - "./data:/app/data:rw"
environment: environment:
- PYTHONUNBUFFERED=1 - PYTHONUNBUFFERED=1
``` ```
> Note that there are two possible sources for the image: docker's and github's registry. Github's registry requires [a few extra steps](https://docs.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages) during the initial setup.
3. Create a subdirectory named `data`. 3. Create a subdirectory named `data`.
@@ -59,7 +62,7 @@ This is the easiest method to run the bot with modifications.
services: services:
qrm2: qrm2:
build: . build: .
image: "discord-qrm2:local-latest" image: "qrm2:local-latest"
restart: on-failure restart: on-failure
volumes: volumes:
- "./data:/app/data:rw" - "./data:/app/data:rw"
@@ -75,7 +78,7 @@ This is the easiest method to run the bot with modifications.
```none ```none
$ docker-compose build --pull $ docker-compose build --pull
$ docker-compose -d $ docker-compose up -d
``` ```
> Run without "-d" to test the bot. (run in foreground) > Run without "-d" to test the bot. (run in foreground)
@@ -95,7 +98,7 @@ This methods is not very nice to use.
2. Run docker build: 2. Run docker build:
```none ```none
$ docker build -t discord-qrm2:local-latest . $ docker build -t qrm2:local-latest .
``` ```
+6
View File
@@ -14,6 +14,8 @@ See [README-DOCKER.md](./README-DOCKER.md)
### Without Docker ### Without Docker
Requires Python 3.7 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). 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).
``` ```
@@ -26,6 +28,10 @@ Run. For more information on options, see the [quick-bot-no-pain run.sh document
$ run.sh $ run.sh
``` ```
## Contributing
Check out the [contribution guidelines](/CONTRIBUTING.md) for more information about how to contribute to this project.
## Copyright ## Copyright
Copyright (C) 2019-2020 Abigail Gold, 0x5c Copyright (C) 2019-2020 Abigail Gold, 0x5c
+11
View File
@@ -63,6 +63,7 @@ emojis = SimpleNamespace(
paths = SimpleNamespace( paths = SimpleNamespace(
data=Path("./data/"), data=Path("./data/"),
resources=Path("./resources/"), resources=Path("./resources/"),
img=Path("./resources/img/"),
bandcharts=Path("./resources/img/bandcharts/"), bandcharts=Path("./resources/img/bandcharts/"),
maps=Path("./resources/img/maps/"), maps=Path("./resources/img/maps/"),
) )
@@ -70,6 +71,16 @@ paths = SimpleNamespace(
# --- Classes --- # --- Classes ---
class CallsignInfoData:
"""Represents a country's callsign info"""
def __init__(self, data: list):
self.title: str = data[0]
self.desc: str = data[1]
self.calls: str = data[2]
self.emoji: str = data[3]
class ImageMetadata: class ImageMetadata:
"""Represents the metadata of a single image.""" """Represents the metadata of a single image."""
def __init__(self, metadata: list): def __init__(self, metadata: list):
+4
View File
@@ -0,0 +1,4 @@
# Image processing instructions
For images like bandplans and maps, first resize the image to a reasonable size, then run `pngquant --quality 30-40` on the images.
Do not apply that to non-flat images like actual pictures.
+1 -1
View File
@@ -20,5 +20,5 @@ Used for grouping info such as name, description, source, and such.
| `name` | The name of the file. | `Canada`, `ITU Zones` | | `name` | The name of the file. | `Canada`, `ITU Zones` |
| `long_name` | The long name (title) of the file. | `Worldwide map of 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.` | | `description` | The description accompanying the file. | `Full radio allocations chart for all services.` |
| `source` | The source of the file. | `Instituto Federal de Telecomunicaciones (IFT)` | | `source` | The source of the file. | `Instituto Federal de Telecomunicaciones (IFT)` |
| `emoji` | A Unicode emoji associated with the file. | `📻`, `🇨🇦` | | `emoji` | A Unicode emoji associated with the file. | `📻`, `🇨🇦` |
+3
View File
@@ -0,0 +1,3 @@
-r requirements.txt
flake8
discord.py-stubs
+1 -1
View File
@@ -29,7 +29,7 @@ class AE7QCog(commands.Cog):
self.bot = bot self.bot = bot
self.session = aiohttp.ClientSession(connector=bot.qrm.connector) self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
@commands.group(name="ae7q", aliases=["ae"], category=cmn.cat.lookup) @commands.group(name="ae7q", aliases=["ae"], case_insensitive=True, category=cmn.cat.lookup)
async def _ae7q_lookup(self, ctx: commands.Context): async def _ae7q_lookup(self, ctx: commands.Context):
"""Looks up a callsign, FRN, or Licensee ID on [ae7q.com](http://ae7q.com/).""" """Looks up a callsign, FRN, or Licensee ID on [ae7q.com](http://ae7q.com/)."""
if ctx.invoked_subcommand is None: if ctx.invoked_subcommand is None:
+4 -5
View File
@@ -10,7 +10,6 @@ the GNU General Public License, version 2.
import random import random
import re import re
from collections import OrderedDict
from typing import Union from typing import Union
import discord import discord
@@ -47,9 +46,9 @@ class QrmHelpCommand(commands.HelpCommand):
if parent: if parent:
fmt = f"{parent} {fmt}" fmt = f"{parent} {fmt}"
alias = fmt alias = fmt
return f"{opt.prefix}{alias} {command.signature}\n *Aliases:* {aliases}" return f"{opt.display_prefix}{alias} {command.signature}\n *Aliases:* {aliases}"
alias = command.name if not parent else f"{parent} {command.name}" alias = command.name if not parent else f"{parent} {command.name}"
return f"{opt.prefix}{alias} {command.signature}" return f"{opt.display_prefix}{alias} {command.signature}"
async def send_error_message(self, error): async def send_error_message(self, error):
embed = cmn.embed_factory(self.context) embed = cmn.embed_factory(self.context)
@@ -61,7 +60,7 @@ class QrmHelpCommand(commands.HelpCommand):
async def send_bot_help(self, mapping): async def send_bot_help(self, mapping):
embed = cmn.embed_factory(self.context) embed = cmn.embed_factory(self.context)
embed.title = "qrm Help" embed.title = "qrm Help"
embed.description = (f"For command-specific help and usage, use `{opt.prefix}help [command name]`." embed.description = (f"For command-specific help and usage, use `{opt.display_prefix}help [command name]`."
" Many commands have shorter aliases.") " Many commands have shorter aliases.")
mapping = await mapping mapping = await mapping
@@ -189,7 +188,7 @@ class BaseCog(commands.Cog):
def parse_changelog(): def parse_changelog():
changelog = OrderedDict() changelog = {}
ver = "" ver = ""
heading = "" heading = ""
+201
View File
@@ -0,0 +1,201 @@
"""
Conversion extension for qrm
---
Copyright (C) 2020 Abigail Gold, 0x5c
This file is part of qrm2 and is released under the terms of
the GNU General Public License, version 2.
"""
import math
from enum import Enum
from typing import Optional
import discord.ext.commands as commands
import common as cmn
from data import options as opt
# not sure why but UnitConverter and Unit need to be defined before DbConvCog and convert()
class UnitConverter(commands.Converter):
async def convert(self, ctx: commands.Context, argument: str):
try:
return Unit(argument)
except ValueError as e:
raise commands.BadArgument(message=str(e))
class Unit:
def __init__(self, raw: str):
self.raw: str = raw
self.unit: str
self.type: UnitType
self.is_db: bool
self.mult: int
self._parse()
def _parse(self):
s = self.raw.lower()
if len(s) > 2 and s[:2] == "db":
self.is_db = True
if s[2:] in units:
u = units[s[2:]]
self.mult = u["mult"]
self.unit = u["log"]
self.type = u["type"]
elif s in units:
self.is_db = False
u = units[s]
self.mult = u["mult"]
self.unit = u["scalar"]
self.type = u["type"]
else:
raise ValueError(f"Invalid unit: {self.raw}")
def __str__(self):
return self.unit
class UnitType(Enum):
voltage = 1
power = 2
antenna = 3
class DbConvCog(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
@commands.command(name="dbconv", aliases=["dbc"], category=cmn.cat.ref)
async def _db_conv(self, ctx: commands.Context,
value: Optional[float] = None,
unit_from: Optional[UnitConverter] = None,
unit_to: Optional[UnitConverter] = None):
"""
Convert between decibels and scalar values for voltage, power, and antenna gain.
**Valid Units**
*Voltage:* V, mV, µV, uV, dBV, dBmV, dBµV, dBuV
*Power:* fW, mW, W, kW, dBf, dBm, dBW, dBk
*Antenna Gain:* dBi, dBd, dBq
"""
embed = cmn.embed_factory(ctx)
if value is not None and unit_from is not None and unit_to is not None:
converted = convert(value, unit_from, unit_to)
embed.title = f"{value:.3g} {unit_from} = {converted:.3g} {unit_to}"
embed.colour = cmn.colours.good
else:
embed.title = "Decibel Quick Reference"
embed.description = (
"Decibels are a great way to easily represent large quantities that are common in electronics. "
"There are a few main types that are used often in radio: voltage, power, and antenna gain. "
"Here are some commonly-used reference levels for each type:"
)
v_db_info = ("**dBV** = relative to 1 V\n"
"**dBmV** = relative to 1 mV (1e-3 V)\n"
"**dBµV** = relative to 1 µV (1e-6 V)")
embed.add_field(name="Voltage Decibels", value=v_db_info, inline=False)
p_db_info = ("**dBW** = relative to 1 W\n"
"**dBk** = relative to 1 kW (1e3 W)\n"
"**dBm** = relative to 1 mW (1e-3 W)\n"
"**dBf** = relative to 1 fW (1e-15 W)")
embed.add_field(name="Power Decibels", value=p_db_info, inline=False)
a_db_info = ("**dBi** = relative to a theoretical __i__sotropic radiator in free space "
"(equal radiation in all directions)\n"
"**dBd** = relative to a dipole in free space (0 dBd = 2.15 dBi)\n"
"**dBq** = relative to a quarter-wave antenna in free space (0 dBq = -0.85 dBi)")
embed.add_field(name="Antenna Gain Decibels", value=a_db_info, inline=False)
embed.add_field(name="Use the bot to do the conversions",
value=f"`{opt.display_prefix}dbconv [value] [unit_from] [unit_to]`",
inline=False)
await ctx.send(embed=embed)
def setup(bot: commands.Bot):
bot.add_cog(DbConvCog(bot))
def convert(initial: float, unit1: Unit, unit2: Unit):
if unit1.type == unit2.type:
# dB to dB
if unit1.is_db and unit2.is_db:
if unit1.mult == unit2.mult:
return initial
elif unit1.type == UnitType.voltage:
return _calc_volt_db(_calc_volt(initial, unit1.mult), unit2.mult)
elif unit1.type == UnitType.power:
return _calc_power_db(_calc_power(initial, unit1.mult), unit2.mult)
elif unit1.type == UnitType.antenna:
return initial + (unit1.mult - unit2.mult)
# V/W to V/W
elif not unit1.is_db and not unit2.is_db:
if unit1.mult == unit2.mult:
return initial
return initial * unit1.mult / unit2.mult
# dB to V/W
elif unit1.is_db and not unit2.is_db:
if unit1.type == UnitType.voltage:
return _calc_volt(initial, unit1.mult) / unit2.mult
elif unit1.type == UnitType.power:
return _calc_power(initial, unit1.mult) / unit2.mult
# V/W to dB
elif not unit1.is_db and unit2.is_db:
if unit1.type == UnitType.voltage:
return _calc_volt_db(initial * unit1.mult, unit2.mult)
elif unit1.type == UnitType.power:
return _calc_power_db(initial * unit1.mult, unit2.mult)
raise ValueError(f"Can't convert between {unit1} and {unit2}")
units = {
# voltage
"uv": {"mult": 1e-6, "scalar": "µV", "log": "dBµV", "type": UnitType.voltage},
"µv": {"mult": 1e-6, "scalar": "µV", "log": "dBµV", "type": UnitType.voltage},
"mv": {"mult": 1e-3, "scalar": "mV", "log": "dBmV", "type": UnitType.voltage},
"v": {"mult": 1, "scalar": "V", "log": "dBV", "type": UnitType.voltage},
# power
"fw": {"mult": 1e-15, "scalar": "fW", "log": "dBf", "type": UnitType.power},
"f": {"mult": 1e-15, "scalar": "fW", "log": "dBf", "type": UnitType.power},
"mw": {"mult": 1e-3, "scalar": "mW", "log": "dBm", "type": UnitType.power},
"m": {"mult": 1e-3, "scalar": "mW", "log": "dBm", "type": UnitType.power},
"w": {"mult": 1, "scalar": "W", "log": "dBW", "type": UnitType.power},
"kw": {"mult": 1e3, "scalar": "kW", "log": "dBk", "type": UnitType.power},
"k": {"mult": 1e3, "scalar": "kW", "log": "dBk", "type": UnitType.power},
# antenna
"q": {"mult": -0.85, "scalar": None, "log": "dBq", "type": UnitType.antenna},
"i": {"mult": 0, "scalar": None, "log": "dBi", "type": UnitType.antenna},
"d": {"mult": 2.15, "scalar": None, "log": "dBd", "type": UnitType.antenna},
}
def _calc_power_db(p: float, ref: float):
return 10 * math.log10(p / ref)
def _calc_power(db: float, ref: float):
return 10 ** (db / 10) * ref
def _calc_volt_db(v: float, ref: float):
return 20 * math.log10(v / ref)
def _calc_volt(db: float, ref: float):
return 10 ** (db / 20) * ref
# testing code
if __name__ == "__main__":
while(True):
try:
ip = input("> ").split()
initial = float(ip[0])
unit1 = Unit(ip[1])
unit2 = Unit(ip[2])
conv = convert(initial, unit1, unit2)
print(f"{initial:.2f} {unit1} = {conv:.2f} {unit2}")
except ValueError as e:
print(e)
+16
View File
@@ -10,6 +10,7 @@ the GNU General Public License, version 2.
import random import random
import discord
import discord.ext.commands as commands import discord.ext.commands as commands
import common as cmn import common as cmn
@@ -31,6 +32,21 @@ class FunCog(commands.Cog):
"""Returns xkcd: tar.""" """Returns xkcd: tar."""
await ctx.send("http://xkcd.com/1168") await ctx.send("http://xkcd.com/1168")
@commands.command(name="standards", category=cmn.cat.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)
async def _worksplit(self, ctx: commands.Context):
"""Posts "Work split you lids"."""
fn = "worksplit.jpg"
embed = cmn.embed_factory(ctx)
embed.title = "Work Split, You Lids!"
embed.set_image(url="attachment://" + fn)
img = discord.File(cmn.paths.img / fn, filename=fn)
await ctx.send(embed=embed, file=img)
@commands.command(name="xd", hidden=True, category=cmn.cat.fun) @commands.command(name="xd", hidden=True, category=cmn.cat.fun)
async def _xd(self, ctx: commands.Context): async def _xd(self, ctx: commands.Context):
"""ecks dee""" """ecks dee"""
+35 -10
View File
@@ -21,6 +21,7 @@ from resources import qcodes
class HamCog(commands.Cog): class HamCog(commands.Cog):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot self.bot = bot
self.pfxs = callsign_info.options
@commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref) @commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref)
async def _qcode_lookup(self, ctx: commands.Context, qcode: str): async def _qcode_lookup(self, ctx: commands.Context, qcode: str):
@@ -64,22 +65,26 @@ class HamCog(commands.Cog):
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref) @commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref)
async def _vanity_prefixes(self, ctx: commands.Context, country: str = None): async def _vanity_prefixes(self, ctx: commands.Context, country: str = ""):
"""Lists valid callsign prefixes for different countries.""" """Lists valid callsign prefixes for different countries."""
if country is None: country = country.lower()
await ctx.send_help(ctx.command)
return
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
if country.lower() not in callsign_info.options: if country not in self.pfxs:
embed.title = f"{country} not found!" desc = "Possible arguments are:\n"
embed.description = f"Valid countries: {', '.join(callsign_info.options.keys())}" 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 embed.colour = cmn.colours.bad
await ctx.send(embed=embed)
return
else: else:
embed.title = callsign_info.options[country.lower()][0] data = self.pfxs[country]
embed.description = callsign_info.options[country.lower()][1] embed.title = data.title + (" " + data.emoji if data.emoji else "")
embed.description = data.desc
embed.colour = cmn.colours.good embed.colour = cmn.colours.good
for name, val in callsign_info.options[country.lower()][2].items(): for name, val in data.calls.items():
embed.add_field(name=name, value=val, inline=False) embed.add_field(name=name, value=val, inline=False)
await ctx.send(embed=embed) await ctx.send(embed=embed)
@@ -92,6 +97,26 @@ class HamCog(commands.Cog):
embed.colour = cmn.colours.good embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="phoneticweight", aliases=["pw"], category=cmn.cat.ref)
async def _weight(self, ctx: commands.Context, *, msg: str):
"""Calculates the phonetic weight of a callsign or message."""
embed = cmn.embed_factory(ctx)
msg = msg.upper()
weight = 0
for char in msg:
try:
weight += phonetics.pweights[char]
except KeyError:
embed.title = "Error in calculation of phonetic weight"
embed.description = f"Unknown character `{char}` in message"
embed.colour = cmn.colours.bad
await ctx.send(embed=embed)
return
embed.title = f"Phonetic Weight of {msg}"
embed.description = f"The phonetic weight is **{weight}**"
embed.colour = cmn.colours.good
await ctx.send(embed=embed)
def setup(bot: commands.Bot): def setup(bot: commands.Bot):
bot.add_cog(HamCog(bot)) bot.add_cog(HamCog(bot))
+18 -22
View File
@@ -8,7 +8,6 @@ the GNU General Public License, version 2.
""" """
from collections import OrderedDict
from io import BytesIO from io import BytesIO
import aiohttp import aiohttp
@@ -159,27 +158,24 @@ def qrz_process_info(data: dict):
else: else:
lotw = "Unknown" lotw = "Unknown"
return OrderedDict([("Name", name), return {"Name": name,
("Country", data.get("country", None)), "Country": data.get("country", None),
("Address", address), "Address": address,
("Grid Square", data.get("grid", None)), "Grid Square": data.get("grid", None),
("County", data.get("county", None)), "County": data.get("county", None),
("CQ Zone", data.get("cqzone", None)), "CQ Zone": data.get("cqzone", None),
("ITU Zone", data.get("ituzone", None)), "ITU Zone": data.get("ituzone", None),
("IOTA Designator", data.get("iota", None)), "IOTA Designator": data.get("iota", None),
("Expires", data.get("expdate", None)), "Expires": data.get("expdate", None),
("Aliases", data.get("aliases", None)), "Aliases": data.get("aliases", None),
("Previous Callsign", data.get("p_call", None)), "Previous Callsign": data.get("p_call", None),
("License Class", data.get("class", None)), "License Class": data.get("class", None),
("Trustee", data.get("trustee", None)), "Trustee": data.get("trustee", None),
("eQSL?", eqsl), "eQSL?": eqsl,
("Paper QSL?", mqsl), "Paper QSL?": mqsl,
("LotW?", lotw), "LotW?": lotw,
("QSL Info", data.get("qslmgr", None)), "QSL Info": data.get("qslmgr", None),
("CQ Zone", data.get("cqzone", None)), "Born": data.get("born", None)}
("ITU Zone", data.get("ituzone", None)),
("IOTA Designator", data.get("iota", None)),
("Born", data.get("born", None))])
def setup(bot): def setup(bot):
+1 -1
View File
@@ -40,7 +40,7 @@ class WeatherCog(commands.Cog):
embed.set_image(url="attachment://condx.png") embed.set_image(url="attachment://condx.png")
await ctx.send(embed=embed, file=discord.File(data, "condx.png")) await ctx.send(embed=embed, file=discord.File(data, "condx.png"))
@commands.group(name="weather", aliases=["wttr"], category=cmn.cat.weather) @commands.group(name="weather", aliases=["wttr"], case_insensitive=True, category=cmn.cat.weather)
async def _weather_conditions(self, ctx: commands.Context): async def _weather_conditions(self, ctx: commands.Context):
"""Gets local weather conditions from [wttr.in](http://wttr.in/). """Gets local weather conditions from [wttr.in](http://wttr.in/).
+1 -1
View File
@@ -12,5 +12,5 @@ authors = ("@ClassAbbyAmplifier#2229", "@0x5c#0639")
description = """A bot with various useful ham radio-related functions, written in Python.""" description = """A bot with various useful ham radio-related functions, written in Python."""
license = "Released under the GNU General Public License v2" license = "Released under the GNU General Public License v2"
contributing = "Check out the source on GitHub, contributions welcome: https://github.com/miaowware/qrm2" contributing = "Check out the source on GitHub, contributions welcome: https://github.com/miaowware/qrm2"
release = "2.2.2" release = "2.4.0"
bot_server = "https://discord.gg/Ntbg3J4" bot_server = "https://discord.gg/Ntbg3J4"
+13 -4
View File
@@ -45,8 +45,8 @@ loop = asyncio.get_event_loop()
connector = loop.run_until_complete(conn.new_connector()) connector = loop.run_until_complete(conn.new_connector())
bot = commands.Bot(command_prefix=opt.prefix, bot = commands.Bot(command_prefix=opt.prefix,
description=info.description, case_insensitive=True,
help_command=commands.MinimalHelpCommand(), description=info.description, help_command=commands.MinimalHelpCommand(),
loop=loop, loop=loop,
connector=connector) connector=connector)
@@ -82,7 +82,7 @@ async def _shutdown_bot(ctx: commands.Context):
await bot.logout() await bot.logout()
@bot.group(name="extctl", aliases=["ex"], category=cmn.cat.admin) @bot.group(name="extctl", aliases=["ex"], case_insensitive=True, category=cmn.cat.admin)
@commands.check(cmn.check_if_owner) @commands.check(cmn.check_if_owner)
async def _extctl(ctx: commands.Context): async def _extctl(ctx: commands.Context):
"""Extension control commands. """Extension control commands.
@@ -193,7 +193,10 @@ async def _ensure_activity_time():
try: try:
tz = pytz.timezone(opt.status_tz) tz = pytz.timezone(opt.status_tz)
except pytz.exceptions.UnknownTimeZoneError: except pytz.exceptions.UnknownTimeZoneError:
await bot.change_presence(activity=discord.Game(name="with invalid timezones.")) status = "with invalid timezones"
if opt.show_help:
status += f" | {opt.display_prefix}help"
await bot.change_presence(activity=discord.Game(name=status))
return return
now = datetime.now(tz=tz).time() now = datetime.now(tz=tz).time()
@@ -203,6 +206,8 @@ async def _ensure_activity_time():
end_time = time(hour=sts[2][0], minute=sts[2][1], tzinfo=tz) end_time = time(hour=sts[2][0], minute=sts[2][1], tzinfo=tz)
if start_time < now <= end_time: if start_time < now <= end_time:
status = sts[0] status = sts[0]
if opt.show_help:
status += f" | {opt.display_prefix}help"
await bot.change_presence(activity=discord.Game(name=status)) await bot.change_presence(activity=discord.Game(name=status))
@@ -210,6 +215,8 @@ async def _ensure_activity_time():
@tasks.loop(minutes=5) @tasks.loop(minutes=5)
async def _ensure_activity_random(): async def _ensure_activity_random():
status = random.choice(opt.statuses) status = random.choice(opt.statuses)
if opt.show_help:
status += f" | {opt.display_prefix}help"
await bot.change_presence(activity=discord.Game(name=status)) await bot.change_presence(activity=discord.Game(name=status))
@@ -217,6 +224,8 @@ async def _ensure_activity_random():
@tasks.loop(minutes=5) @tasks.loop(minutes=5)
async def _ensure_activity_fixed(): async def _ensure_activity_fixed():
status = opt.statuses[0] status = opt.statuses[0]
if opt.show_help:
status += f" | {opt.display_prefix}help"
await bot.change_presence(activity=discord.Game(name=status)) await bot.change_presence(activity=discord.Game(name=status))
+5 -5
View File
@@ -1,5 +1,5 @@
discord.py discord.py==1.3.4
ctyparser ctyparser==2.0.0.post1
beautifulsoup4 beautifulsoup4==4.9.1
lxml lxml==4.5.2
pytz pytz==2020.1
+7 -45
View File
@@ -1,5 +1,5 @@
""" """
Information about callsigns for the vanity prefixes command in hamcog. Information about callsigns for the prefixes command in hamcog.
--- ---
Copyright (C) 2019-2020 Abigail Gold, 0x5c Copyright (C) 2019-2020 Abigail Gold, 0x5c
@@ -7,50 +7,12 @@ This file is part of discord-qrmbot and is released under the terms of
the GNU General Public License, version 2. the GNU General Public License, version 2.
""" """
from .callsigninfos import (us, ca)
from common import CallsignInfoData
from collections import OrderedDict
us_calls_title = "Valid US Vanity Callsigns"
us_calls_desc = ("#x# is the number of letters in the prefix and suffix of a callsign. "
"E.g., WY4RC would be a 2x2 callsign, with prefix WY and suffix RC.")
us_calls = OrderedDict([("**Group A** (Extra Only)", ("**Any:** K, N, W (1x2)\n"
" AA-AL, KA-KZ, NA-NZ, WA-WZ (2x1)\n"
" AA-AL (2x2)\n"
"*Except*\n"
"**Alaska:** AL, KL, NL, WL (2x1)\n"
"**Caribbean:** KP, NP, WP (2x1)\n"
"**Pacific:** AH, KH, NH, WH (2x1)")),
("**Group B** (Advanced and Extra Only)", ("**Any:** KA-KZ, NA-NZ, WA-WZ (2x2)\n"
"*Except*\n"
"**Alaska:** AL (2x2)\n"
"**Caribbean:** KP (2x2)\n"
"**Pacific:** AH (2x2)")),
("**Group C** (Technician, General, Advanced, Extra Only)", ("**Any Region:** K, N, W (1x3)\n"
"*Except*\n"
"**Alaska:** KL, NL, WL (2x2)\n"
"**Caribbean:** NP, WP (2x2)\n"
"**Pacific:** KH, NH, WH (2x2)")),
("**Group D** (Any License Class)", ("**Any Region:** KA-KZ, WA-WZ (2x3)\n"
"*Except*\n"
"**Alaska:** KL, WL (2x3)\n"
"**Caribbean:** KP, WP (2x3)\n"
"**Pacific:** KH, WH (2x3)")),
("**Unavailable**", ("- KA2AA-KA9ZZ: US Army in Japan\n"
"- KC4AAA-KC4AAF: NSF in Antartica\n"
"- KC4USA-KC4USZ: US Navy in Antartica\n"
"- KG4AA-KG4ZZ: US Navy in Guantanamo Bay\n"
"- KL9KAA-KL9KHZ: US military in Korea\n"
"- KC6AA-KC6ZZ: Former US (Eastern and Western Caroline Islands), "
"now Federated States of Micronesia (V6) and Republic of Palau (T8)\n"
"- KX6AA-KX6ZZ: Former US (Marshall Islands), "
"now Republic of the Marshall Islands (V73)\n"
"- Any suffix SOS or QRA-QUZ\n"
"- Any 2x3 with X as the first suffix letter\n"
"- Any 2x3 with AF, KF, NF, or WF prefix and suffix EMA: FEMA\n"
"- Any 2x3 with AA-AL, NA-NZ, WC, WK, WM, WR, or WT prefix: \"Group X\"\n"
"- Any 2x1, 2x2, or 2x3 with KP, NP, WP prefix and 0, 6, 7, 8, 9 number\n"
"- Any 1x1 callsign: Special Event"))])
# format: country: (title, description, text) # format: country: (title, description, text)
options = {"us": (us_calls_title, us_calls_desc, us_calls)} options = {
"us": CallsignInfoData([us.title, us.desc, us.calls, us.emoji]),
"ca": CallsignInfoData([ca.title, ca.desc, ca.calls, ca.emoji]),
}
+3
View File
@@ -0,0 +1,3 @@
"""
Callsign info for various countries
"""
+47
View File
@@ -0,0 +1,47 @@
"""
Information about callsigns for the CA prefixes command in hamcog.
---
Copyright (C) 2019-2020 Abigail Gold, 0x5c
This file is part of discord-qrmbot and is released under the terms of
the GNU General Public License, version 2.
"""
title = "Canadian Callsign Rules"
emoji = "🇨🇦"
desc = ("Canadian operators are limited to callsigns with the prefixes of their address' province/territory. "
"Initially, operators can choose a callsign with a 3-letter suffix. "
"Later on, they can apply to change or for additional callsigns. "
"Operators can only hold one 2-letter suffix callsign, but many 3-letter suffix callsigns. "
"If the number of 2-letter suffix callsigns exceeds 80% of the total available, "
"operators can only choose a 2-letter suffix after holding a license for 5 years. "
"If the operator is a family member of a deceased operator, they are not bound by this restriction. "
"Data from [ISED Canada (RIC-9)](https://www.ic.gc.ca/eic/site/smt-gst.nsf/eng/sf02102.html).")
calls = {
"Provinces": (
"**Nova Scotia:** VE1 and VA1\n"
"**Québec:** VE2 and VA2\n"
"**Ontario:** VE3 and VA3\n"
"**Manitoba:** VE4 and VA4\n"
"**Saskatchewan:** VE5 and VA5\n"
"**Alberta:** VE6 and VA6\n"
"**British Columbia:** VE7 and VA7\n"
"**New Brunswick:** VE9\n"
"**Newfoundland:** VO1\n"
"**Labrador:** VO2\n"
"**Prince Edward Island:** VY2\n"
),
"Territories": (
"**Northwest Territories:** VE8\n"
"**Nunavut:** VY0\n"
"**Yukon:** VY1\n"
),
"Other": (
"**International Waters:** VE0\n"
"**Government of Canada:** VY9\n"
"**Sable Island:** CY0\n"
"**St-Paul Island:** CY9\n"
),
"Special Event": "Various prefixes in the ranges: CF-CK, CY-CZ, VA-VG, VO, VX-VY, XJ-XO"
}
+53
View File
@@ -0,0 +1,53 @@
"""
Information about callsigns for the US prefixes command in hamcog.
---
Copyright (C) 2019-2020 Abigail Gold, 0x5c
This file is part of discord-qrmbot and is released under the terms of
the GNU General Public License, version 2.
"""
title = "US Callsign Rules"
emoji = "🇺🇸"
desc = ("#x# is the number of letters in the prefix and suffix of a callsign. "
"E.g., WY4RC would be a 2x2 callsign, with prefix WY and suffix RC.")
calls = {
"**Group A** (Extra Only)": ("**Any:** K, N, W (1x2)\n"
" AA-AL, KA-KZ, NA-NZ, WA-WZ (2x1)\n"
" AA-AL (2x2)\n"
"*Except*\n"
"**Alaska:** AL, KL, NL, WL (2x1)\n"
"**Caribbean:** KP, NP, WP (2x1)\n"
"**Pacific:** AH, KH, NH, WH (2x1)"),
"**Group B** (Advanced and Extra Only)": ("**Any:** KA-KZ, NA-NZ, WA-WZ (2x2)\n"
"*Except*\n"
"**Alaska:** AL (2x2)\n"
"**Caribbean:** KP (2x2)\n"
"**Pacific:** AH (2x2)"),
"**Group C** (Technician, General, Advanced, Extra Only)": ("**Any Region:** K, N, W (1x3)\n"
"*Except*\n"
"**Alaska:** KL, NL, WL (2x2)\n"
"**Caribbean:** NP, WP (2x2)\n"
"**Pacific:** KH, NH, WH (2x2)"),
"**Group D** (Any License Class)": ("**Any Region:** KA-KZ, WA-WZ (2x3)\n"
"*Except*\n"
"**Alaska:** KL, WL (2x3)\n"
"**Caribbean:** KP, WP (2x3)\n"
"**Pacific:** KH, WH (2x3)"),
"**Unavailable**": ("- KA2AA-KA9ZZ: US Army in Japan\n"
"- KC4AAA-KC4AAF: NSF in Antartica\n"
"- KC4USA-KC4USZ: US Navy in Antartica\n"
"- KG4AA-KG4ZZ: US Navy in Guantanamo Bay\n"
"- KL9KAA-KL9KHZ: US military in Korea\n"
"- KC6AA-KC6ZZ: Former US (Eastern and Western Caroline Islands), "
"now Federated States of Micronesia (V6) and Republic of Palau (T8)\n"
"- KX6AA-KX6ZZ: Former US (Marshall Islands), "
"now Republic of the Marshall Islands (V73)\n"
"- Any suffix SOS or QRA-QUZ\n"
"- Any 2x3 with X as the first suffix letter\n"
"- Any 2x3 with AF, KF, NF, or WF prefix and suffix EMA: FEMA\n"
"- Any 2x3 with AA-AL, NA-NZ, WC, WK, WM, WR, or WT prefix: \"Group X\"\n"
"- Any 2x1, 2x2, or 2x3 with KP, NP, WP prefix and 0, 6, 7, 8, 9 number\n"
"- Any 1x1 callsign: Special Event")
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+7 -3
View File
@@ -1,6 +1,10 @@
{ {
"arrl": ["arrl-rac.png", "ARRL Sections", "ARRL Sections", "", "", "🇺🇸"], "arrl": ["arrl-rac.png", "ARRL Sections", "ARRL Sections", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇺🇸"],
"rac": ["arrl-rac.png", "RAC Sections", "RAC Sections", "", "", "🇨🇦"], "rac": ["arrl-rac.png", "RAC Sections", "RAC Sections", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇨🇦"],
"cn": ["cn.png", "China's Prefixes", "Map of prefix regions in China", "", "CRAC", "🇨🇳"], "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)", "🇺🇸"] "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)", "🇺🇸"],
"ca": ["ca.png", "Canada's Prefixes", "Map of the prefix regions in Canada", "", "[Denelson83 (Wikimedia Commons)](https://commons.wikimedia.org/wiki/File:Amateur_radio_prefixes_in_Canada.svg)", "🇨🇦"],
"ituz": ["itu-zones.png", "ITU Zones", "ITU Zones", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇺🇳"],
"itur": ["itu-regions.png", "ITU Regions", "ITU Regions", "These are also used by the IARU for their regions.", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇺🇳"],
"cq": ["cq-zones.png", "CQ Zones", "CQ Zones", "These are used for the CQWW contest.", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🌐"]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

+40
View File
@@ -36,3 +36,43 @@ phonetics = {
"y": "yankee", "y": "yankee",
"z": "zulu" "z": "zulu"
} }
pweights = {
"A": 2,
"B": 2,
"C": 2,
"D": 2,
"E": 2,
"F": 2,
"G": 1,
"H": 2,
"I": 3,
"J": 3,
"K": 2,
"L": 2,
"M": 1,
"N": 3,
"O": 2,
"P": 2,
"Q": 2,
"R": 3,
"S": 3,
"T": 2,
"U": 3,
"V": 2,
"W": 2,
"X": 2,
"Y": 2,
"Z": 2,
"0": 2,
"1": 1,
"2": 1,
"3": 1,
"4": 1,
"5": 1,
"6": 1,
"7": 2,
"8": 1,
"9": 2,
"/": 1,
}
+119 -44225
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -15,7 +15,10 @@ Settings and options for the bot.
# The prefix for the bot (str). Define a list of stings for multiple prefixes. # The prefix for the bot (str). Define a list of stings for multiple prefixes.
# ie: `["?", "!", "pls "]` # ie: `["?", "!", "pls "]`
prefix = "?" prefix = ["? ", "?"]
# The prefix to use for display purposes (ex: status message).
display_prefix = "?"
# Whether the bot should print full stacktraces for normal exceptions: `True`, # Whether the bot should print full stacktraces for normal exceptions: `True`,
# or be nice and only print small messages: `False` (the default). # or be nice and only print small messages: `False` (the default).
@@ -27,7 +30,7 @@ debug = False
owners_uids = (200102491231092736,) owners_uids = (200102491231092736,)
# The extensions to load when running the bot. # The extensions to load when running the bot.
exts = ["ae7q", "base", "fun", "grid", "ham", "image", "lookup", "morse", "qrz", "study", "weather"] exts = ["ae7q", "base", "fun", "grid", "ham", "image", "lookup", "morse", "qrz", "study", "weather", "dbconv"]
# Either "time", "random", or "fixed" (first item in statuses) # Either "time", "random", or "fixed" (first item in statuses)
status_mode = "fixed" status_mode = "fixed"
@@ -46,6 +49,9 @@ time_statuses = [("with lids on 3.840", (00, 00), (6, 00)),
("with lids on 7.200", (18, 00), (20, 00)), ("with lids on 7.200", (18, 00), (20, 00)),
("with lids on 3.840", (20, 00), (23, 59))] ("with lids on 3.840", (20, 00), (23, 59))]
# append " | {display_prefix}help" to the Discord playing status
show_help = False
# Emoji IDs and keywords for emoji reactions # Emoji IDs and keywords for emoji reactions
# Use the format {emoji_id (int): ("tuple", "of", "lowercase", "keywords")} # Use the format {emoji_id (int): ("tuple", "of", "lowercase", "keywords")}
msg_reacts = {} msg_reacts = {}