Compare commits

...

27 Commits

Author SHA1 Message Date
Jack b3c0710d2a
Merge 5aefcabb3c into 4b55ab49b7 2024-01-03 10:03:49 -08:00
classabbyamp 4b55ab49b7 .github/workflows/docker.yml: fix labels, again
Docker Build and Deploy / Build and push docker images (push) Has been cancelled Details
Linting / flake8 (push) Has been cancelled Details
2023-12-15 14:47:33 -05:00
classabbyamp cf378a2ef4 CHANGELOG.md: relbump 2023-12-15 14:30:59 -05:00
classabbyamp 13a8a63300 info.py: use pomelo usernames, relbump 2023-12-15 14:30:59 -05:00
classabbyamp 23619949d7 .github/workflows/docker.yml: fix tagging latest
turns out, most of this is handled automatically.
see https://github.com/docker/metadata-action#latest-tag
2023-12-15 14:20:05 -05:00
classabbyamp 444687bd12 .github/workflows/docker.yml: use metadata action, run on PRs
Docker Build and Deploy / Build and push docker images (push) Has been cancelled Details
Linting / flake8 (push) Has been cancelled Details
2023-12-11 08:21:33 -05:00
classabbyamp 86da8d135a Dockerfile: use new void container, python3.11 2023-12-11 08:21:33 -05:00
classabbyamp 67add85a7a run.sh: shellcheck 2023-12-11 08:21:33 -05:00
0x5c abdc5ebacb
Merge pull request #476 from miaowware/fix/metar
Docker Build and Deploy / Build and push docker images (push) Waiting to run Details
Linting / flake8 (push) Waiting to run Details
Fix metar + version bumps
2023-12-10 14:17:35 -05:00
0x5c a5cbb5a09a
exts/land_weather: switch to the new aviationweather.gov API
Fixes #475
2023-12-10 07:47:59 -05:00
0x5c ce99cc194e
bump pydantic to version 2 2023-12-10 07:19:45 -05:00
0x5c f8d7316071
bump pycord to pre-release v5 2023-12-10 07:16:41 -05:00
0x5c 9feeb01e42
Merge pull request #474 from cschmittiey/hamqsl-https
hamqsl.com has moved to https
2023-04-22 02:55:08 -04:00
Caleb Smith fcb682ec4a hamqsl.com has moved to https 2023-04-22 00:53:03 -06:00
Judd West c8a1128927 Add NOAA D-RAP map to propagation plugin 2023-01-30 05:25:01 -05:00
classabbyamp df08cefe25 exts/callsign: fix mail qsl display 2023-01-29 15:40:43 -05:00
0x5c cf93773a3c
Merge pull request #471 from miaowware/rel-2.9.1
rel 2.9.1
2023-01-29 00:52:48 -05:00
classabbyamp 642b49041a
bump version 2.9.1 2023-01-29 00:44:29 -05:00
classabbyamp e95f991300
bump copyright 2023-01-29 00:43:56 -05:00
0x5c 56ae14a5c3
Merge pull request #469 from miaowware/new-clt
exts/callsign: unworkaround some things solved in CLT 1.1.0
2023-01-29 00:34:04 -05:00
classabbyamp 30c6e96883
exts/callsign: unworkaround some things solved in CLT 1.1.0
fixes #466
2023-01-29 00:23:20 -05:00
0x5c 44a6905f7b
Merge pull request #468 from miaowware/embed-avatar
Embed factory/pycord fixes
2023-01-28 23:41:01 -05:00
classabbyamp d7de78e582
common.py: use tz-aware datetime for proper timestamp display
https://docs.pycord.dev/en/stable/api/data_classes.html#discord.Embed.timestamp
2023-01-28 20:11:23 -05:00
classabbyamp b000c9173e
common.py: don't error when creating embeds for users without avatars
behaviour changed in pycord 2.0:
https://docs.pycord.dev/en/stable/api/models.html#discord.User.display_avatar

fixes #467
2023-01-28 20:11:00 -05:00
licyb200 5aefcabb3c Implemented requested changes to UwUify Command & Changelog 2022-03-01 21:17:19 -08:00
licyb200 2453d20757 Cleaned up UWUify command & Updated Changelog 2022-03-01 20:31:41 -08:00
licyb200 1dc55eaff2 Added UWUify Command 2022-03-01 12:37:23 -08:00
34 changed files with 175 additions and 160 deletions

View File

@ -3,6 +3,10 @@
name: Docker Build and Deploy name: Docker Build and Deploy
on: on:
workflow_dispatch:
pull_request:
branches:
- master
push: push:
# Publish `master` as Docker `dev` image. # Publish `master` as Docker `dev` image.
branches: branches:
@ -11,29 +15,42 @@ on:
tags: tags:
- v* - v*
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
docker: docker:
name: Build and push docker images name: Build and push docker images
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
permissions: permissions:
packages: write packages: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: classabbyamp/treeless-checkout-action@v1
with:
ref: ${{ github.ref }}
- name: Write ref to file - name: Write ref to file
if: ${{ github.event_name != 'pull_request' }}
run: git rev-list -n 1 $GITHUB_REF > ./git_commit run: git rev-list -n 1 $GITHUB_REF > ./git_commit
- name: Build image - name: Docker metadata
id: build_image id: meta
run: | uses: docker/metadata-action@v4
IMAGE_ID=${GITHUB_REPOSITORY,,} with:
IMAGE_NAME=${IMAGE_ID#*/} images: |
echo "image_id=$IMAGE_ID" >> $GITHUB_ENV ghcr.io/${{ github.repository }}
echo "image_name=$IMAGE_NAME" >> $GITHUB_ENV tags: |
docker build . --file Dockerfile -t $IMAGE_NAME type=sha,prefix=
type=raw,value=dev,enable={{is_default_branch}}
type=match,pattern=v(.*),group=1
labels: |
org.opencontainers.image.authors=classabbyamp and 0x5c
org.opencontainers.image.url=https://github.com/miaowware/qrm2
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.vendor=miaowware
org.opencontainers.image.title=qrm2
org.opencontainers.image.description=Discord bot with ham radio functions
org.opencontainers.image.licenses=LiLiQ-Rplus-1.1
- name: Login to Github Container Registry - name: Login to Github Container Registry
uses: docker/login-action@v1 uses: docker/login-action@v1
@ -42,41 +59,10 @@ jobs:
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag image - name: Build and push
id: tag_image uses: docker/build-push-action@v5
run: |
IMAGE_NAME=${{ env.image_name }}
IMAGE_ID=ghcr.io/${{ env.image_id }}
echo IMAGE_ID=$IMAGE_ID
echo "image_id=$IMAGE_ID" >> $GITHUB_ENV
# 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//')
# if version is master, set version to dev
[[ "$VERSION" == "master" ]] && VERSION=dev
echo VERSION=$VERSION
echo "version=$VERSION" >> $GITHUB_ENV
# tag dev or x.x.x
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
# tag latest if not a dev release
[[ "$VERSION" != "dev" ]] && docker tag $IMAGE_NAME $IMAGE_ID:latest || true
- name: Push images to registry
run: |
VERSION=${{ env.version }}
IMAGE_ID=${{ env.image_id }}
[[ "$VERSION" != "dev" ]] && docker push $IMAGE_ID:latest || true
docker push $IMAGE_ID:$VERSION
- name: Deploy official images
id: deploy_images
uses: satak/webrequest-action@v1
with: with:
url: ${{ secrets.DEPLOY_URL }} context: .
method: POST push: ${{ github.event_name != 'pull_request' }}
headers: '{"Authentication": "Token ${{ secrets.DEPLOY_TOKEN }}"}' tags: ${{ steps.meta.outputs.tags }}
payload: '{"version": "${{ env.version }}"}' labels: ${{ steps.meta.outputs.labels }}

View File

@ -5,6 +5,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
### Added
- UwUify command
## [2.9.2] - 2023-12-15
### Added
- `?drapmap` command to display NOAA D Region Absorption Predictions map.
- Support for the new username format.
### Fixed
- Issue where `?solarweather` would not show a picture (#474).
- Issue where `?metar` and `?taf` failed to fetch data (#475).
## [2.9.1] - 2023-01-29
### Fixed
- Issue where embeds would not work for users without avatars (#467).
- Issue where embeds would show the wrong timezone.
- Several issues with `?call` caused by issues in a library (#466).
## [2.9.0] - 2023-01-13 ## [2.9.0] - 2023-01-13
@ -239,7 +257,9 @@ 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.9.0...HEAD [Unreleased]: https://github.com/miaowware/qrm2/compare/v2.9.2...HEAD
[2.9.2]: https://github.com/miaowware/qrm2/releases/tag/v2.9.2
[2.9.1]: https://github.com/miaowware/qrm2/releases/tag/v2.9.1
[2.9.0]: https://github.com/miaowware/qrm2/releases/tag/v2.9.0 [2.9.0]: https://github.com/miaowware/qrm2/releases/tag/v2.9.0
[2.8.0]: https://github.com/miaowware/qrm2/releases/tag/v2.8.0 [2.8.0]: https://github.com/miaowware/qrm2/releases/tag/v2.8.0
[2.7.6]: https://github.com/miaowware/qrm2/releases/tag/v2.7.6 [2.7.6]: https://github.com/miaowware/qrm2/releases/tag/v2.7.6

View File

@ -1,10 +1,9 @@
FROM ghcr.io/void-linux/void-linux:latest-full-x86_64-musl FROM ghcr.io/void-linux/void-musl-full
LABEL org.opencontainers.image.source https://github.com/miaowware/qrm2
COPY . /app COPY . /app
WORKDIR /app WORKDIR /app
ARG REPOSITORY=https://repo-us.voidlinux.org/current ARG REPOSITORY=https://repo-fastly.voidlinux.org/current
ARG PKGS="cairo libjpeg-turbo" ARG PKGS="cairo libjpeg-turbo"
ARG UID 1000 ARG UID 1000
ARG GID 1000 ARG GID 1000
@ -14,19 +13,19 @@ RUN \
xbps-install -Suy xbps -R ${REPOSITORY} && \ xbps-install -Suy xbps -R ${REPOSITORY} && \
xbps-install -uy -R ${REPOSITORY} && \ xbps-install -uy -R ${REPOSITORY} && \
echo "**** install system packages ****" && \ echo "**** install system packages ****" && \
xbps-install -y -R ${REPOSITORY} ${PKGS} python3 python3-pip && \ xbps-install -y -R ${REPOSITORY} ${PKGS} python3.11 && \
echo "**** install pip packages ****" && \ echo "**** install pip packages ****" && \
pip3 install -U pip setuptools wheel && \ python3.11 -m venv botenv && \
pip3 install -r requirements.txt && \ botenv/bin/pip install -U pip setuptools wheel && \
botenv/bin/pip install -r requirements.txt && \
echo "**** clean up ****" && \ echo "**** clean up ****" && \
rm -rf \ rm -rf \
/root/.cache \ /root/.cache \
/tmp/* \ /tmp/* \
/var/cache/xbps/* /var/cache/xbps/*
ENV PYTHON_BIN python3
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1
USER $UID:$GID USER $UID:$GID
CMD ["/bin/sh", "run.sh", "--pass-errors", "--no-botenv"] CMD ["/bin/sh", "run.sh", "--pass-errors"]

View File

@ -38,7 +38,7 @@ All issues and requests related to resources (including maps, band charts, data)
## Copyright ## Copyright
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
This program is released under the terms of the *Québec Free and Open-Source Licence Strong Reciprocity (LiLiQ-R+)*, version 1.1. This program is released under the terms of the *Québec Free and Open-Source Licence Strong Reciprocity (LiLiQ-R+)*, version 1.1.
See [`LICENCE`](LICENCE) for full license text (Français / English). See [`LICENCE`](LICENCE) for full license text (Français / English).

View File

@ -1,7 +1,7 @@
""" """
Common tools for the bot. Common tools for the bot.
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -12,7 +12,7 @@ import enum
import json import json
import re import re
import traceback import traceback
from datetime import datetime from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from typing import Union from typing import Union
@ -165,9 +165,9 @@ class GlobalChannelConverter(commands.IDConverter):
def embed_factory(ctx: commands.Context) -> discord.Embed: def embed_factory(ctx: commands.Context) -> discord.Embed:
"""Creates an embed with neutral colour and standard footer.""" """Creates an embed with neutral colour and standard footer."""
embed = discord.Embed(timestamp=datetime.utcnow(), colour=colours.neutral) embed = discord.Embed(timestamp=datetime.now(timezone.utc), colour=colours.neutral)
if ctx.author: if ctx.author:
embed.set_footer(text=str(ctx.author), icon_url=str(ctx.author.avatar.url)) embed.set_footer(text=str(ctx.author), icon_url=str(ctx.author.display_avatar))
return embed return embed

View File

@ -1,7 +1,7 @@
""" """
ae7q extension for qrm ae7q extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Base extension for qrm Base extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -2,7 +2,7 @@
Callsign Lookup extension for qrm Callsign Lookup extension for qrm
--- ---
Copyright (C) 2019-2020 classabbyamp, 0x5c (as qrz.py) Copyright (C) 2019-2020 classabbyamp, 0x5c (as qrz.py)
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -12,7 +12,6 @@ from typing import Dict
import aiohttp import aiohttp
from callsignlookuptools import QrzAsyncClient, CallsignLookupError, CallsignData from callsignlookuptools import QrzAsyncClient, CallsignLookupError, CallsignData
from callsignlookuptools.common.dataclasses import Trustee
from discord.ext import commands from discord.ext import commands
@ -74,7 +73,7 @@ class QRZCog(commands.Cog):
embed.title = f"QRZ Data for {data.callsign}" embed.title = f"QRZ Data for {data.callsign}"
embed.colour = cmn.colours.good embed.colour = cmn.colours.good
embed.url = data.url embed.url = data.url
if data.image is not None and data.image.url is not None: if data.image is not None:
embed.set_thumbnail(url=data.image.url) embed.set_thumbnail(url=data.image.url)
for title, val in qrz_process_info(data).items(): for title, val in qrz_process_info(data).items():
@ -101,9 +100,9 @@ def qrz_process_info(data: CallsignData) -> Dict:
qsl = dict() qsl = dict()
if data.qsl is not None: if data.qsl is not None:
qsl = { qsl = {
"eQSL?": data.qsl.eqsl.name.title(), "eQSL?": data.qsl.eqsl,
"Paper QSL?": data.qsl.mail.name.title(), "Paper QSL?": data.qsl.mail,
"LotW?": data.qsl.lotw.name.title(), "LotW?": data.qsl.lotw,
"QSL Info": data.qsl.info, "QSL Info": data.qsl.info,
} }
@ -120,7 +119,7 @@ def qrz_process_info(data: CallsignData) -> Dict:
"Aliases": ", ".join(data.aliases) if data.aliases else None, "Aliases": ", ".join(data.aliases) if data.aliases else None,
"Previous Callsign": data.prev_call, "Previous Callsign": data.prev_call,
"License Class": data.lic_class, "License Class": data.lic_class,
"Trustee": data.trustee if data.trustee is not None and data.trustee != Trustee(None, None) else None, "Trustee": data.trustee,
"Born": data.born, "Born": data.born,
} | qsl } | qsl

View File

@ -2,7 +2,7 @@
Codes extension for qrm Codes extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c (as ham.py) Copyright (C) 2019-2021 classabbyamp, 0x5c (as ham.py)
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Contest Calendar extension for qrm Contest Calendar extension for qrm
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Conversion extension for qrm Conversion extension for qrm
--- ---
Copyright (C) 2020-2021 classabbyamp, 0x5c Copyright (C) 2020-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -2,7 +2,7 @@
DXCC Prefix Lookup extension for qrm DXCC Prefix Lookup extension for qrm
--- ---
Copyright (C) 2019-2020 classabbyamp, 0x5c (as lookup.py) Copyright (C) 2019-2020 classabbyamp, 0x5c (as lookup.py)
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Fun extension for qrm Fun extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -69,6 +69,13 @@ class FunCog(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="uwuify", aliases=["uwu"], category=cmn.Cats.FUN)
async def _uwuify(self, ctx: commands.Context, *, msg: str):
"""UwUify your text"""
trans_table = msg.maketrans({"l": "w", "L": "W", "r": "w", "R": "W"})
uwuified_text = msg.replace('na', 'nya').translate(trans_table).replace("no", "yo").replace("mo", "yo")
await ctx.send(uwuified_text)
def setup(bot: commands.Bot): def setup(bot: commands.Bot):
bot.add_cog(FunCog(bot)) bot.add_cog(FunCog(bot))

View File

@ -1,7 +1,7 @@
""" """
Grid extension for qrm Grid extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Image extension for qrm Image extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -2,18 +2,16 @@
Land Weather extension for qrm Land Weather extension for qrm
--- ---
Copyright (C) 2019-2020 classabbyamp, 0x5c (as weather.py) Copyright (C) 2019-2020 classabbyamp, 0x5c (as weather.py)
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
import re import re
from typing import List
import aiohttp import aiohttp
from discord import Embed
import discord.ext.commands as commands import discord.ext.commands as commands
import common as cmn import common as cmn
@ -102,7 +100,32 @@ class WeatherCog(commands.Cog):
Airports should be given as an \ Airports should be given as an \
[ICAO code](https://en.wikipedia.org/wiki/List_of_airports_by_IATA_and_ICAO_code).""" [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))
embed = cmn.embed_factory(ctx)
airport = airport.upper()
if not re.fullmatch(r"\w(\w|\d){2,3}", airport):
embed.title = "Invalid airport given!"
embed.colour = cmn.colours.bad
await ctx.send(embed=embed)
return
url = f"https://aviationweather.gov/api/data/metar?ids={airport}&format=raw&taf=false&hours={hours}"
async with self.session.get(url) as r:
if r.status != 200:
raise cmn.BotHTTPError(r)
metar = await r.text()
if hours > 0:
embed.title = f"METAR for {airport} for the last {hours} hour{'s' if hours > 1 else ''}"
else:
embed.title = f"Current METAR for {airport}"
embed.description = "Data from [aviationweather.gov](https://www.aviationweather.gov/)."
embed.colour = cmn.colours.good
embed.description += f"\n\n```\n{metar}\n```"
await ctx.send(embed=embed)
@commands.command(name="taf", category=cmn.Cats.WEATHER) @commands.command(name="taf", category=cmn.Cats.WEATHER)
async def taf(self, ctx: commands.Context, airport: str): async def taf(self, ctx: commands.Context, airport: str):
@ -110,57 +133,28 @@ class WeatherCog(commands.Cog):
Airports should be given as an \ Airports should be given as an \
[ICAO code](https://en.wikipedia.org/wiki/List_of_airports_by_IATA_and_ICAO_code).""" [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, 0, True))
async def gen_metar_taf_embed(self, ctx: commands.Context, airport: str, hours: int, taf: bool) -> Embed:
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
airport = airport.upper() airport = airport.upper()
if re.fullmatch(r"\w(\w|\d){2,3}", airport): if not re.fullmatch(r"\w(\w|\d){2,3}", airport):
metar = await self.get_metar_taf_data(airport, hours, taf)
if taf:
embed.title = f"Current TAF for {airport}"
elif hours > 0:
embed.title = f"METAR for {airport} for the last {hours} hour{'s' if hours > 1 else ''}"
else:
embed.title = f"Current METAR for {airport}"
embed.description = "Data from [aviationweather.gov](https://www.aviationweather.gov/metar/data)."
embed.colour = cmn.colours.good
data = "\n".join(metar)
embed.description += f"\n\n```\n{data}\n```"
else:
embed.title = "Invalid airport given!" embed.title = "Invalid airport given!"
embed.colour = cmn.colours.bad embed.colour = cmn.colours.bad
return embed await ctx.send(embed=embed)
return
async def get_metar_taf_data(self, airport: str, hours: int, taf: bool) -> List[str]: url = f"https://aviationweather.gov/api/data/taf?ids={airport}&format=raw&metar=true"
url = (f"https://www.aviationweather.gov/metar/data?ids={airport}&format=raw&hours={hours}"
f"&taf={'on' if taf else 'off'}&layout=off")
async with self.session.get(url) as r: async with self.session.get(url) as r:
if r.status != 200: if r.status != 200:
raise cmn.BotHTTPError(r) raise cmn.BotHTTPError(r)
page = await r.text() taf = await r.text()
# pare down to just the data embed.title = f"Current TAF for {airport}"
page = page.split("<!-- Data starts here -->")[1].split("<!-- Data ends here -->")[0].strip() embed.description = "Data from [aviationweather.gov](https://www.aviationweather.gov/)."
# split at <hr>s embed.colour = cmn.colours.good
data = re.split(r"<hr.*>", page, maxsplit=len(airport)) embed.description += f"\n\n```\n{taf}\n```"
parsed = [] await ctx.send(embed=embed)
for sec in data:
if sec.strip():
for line in sec.split("\n"):
line = line.strip()
# remove HTML stuff
line = line.replace("<code>", "").replace("</code>", "")
line = line.replace("<strong>", "").replace("</strong>", "")
line = line.replace("<br/>", "\n").replace("&nbsp;", " ")
line = line.strip("\n")
parsed.append(line)
return parsed
def setup(bot: commands.Bot): def setup(bot: commands.Bot):

View File

@ -1,7 +1,7 @@
""" """
Morse Code extension for qrm Morse Code extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Prefixes Lookup extension for qrm Prefixes Lookup extension for qrm
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Propagation extension for qrm Propagation extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -23,7 +23,8 @@ class PropagationCog(commands.Cog):
muf_url = "https://prop.kc2g.com/renders/current/mufd-normal-now.svg" muf_url = "https://prop.kc2g.com/renders/current/mufd-normal-now.svg"
fof2_url = "https://prop.kc2g.com/renders/current/fof2-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" 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" n0nbh_sun_url = "https://www.hamqsl.com/solarsun.php"
noaa_drap_url = "https://services.swpc.noaa.gov/images/animations/d-rap/global/d-rap/latest.png"
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
@ -86,6 +87,17 @@ class PropagationCog(commands.Cog):
embed.set_image(url="attachment://solarweather.png") embed.set_image(url="attachment://solarweather.png")
await ctx.send(file=file, embed=embed) await ctx.send(file=file, embed=embed)
@commands.command(name="drapmap", aliases=["drap"], category=cmn.Cats.WEATHER)
async def drapmap(self, ctx: commands.Context):
"""Gets the current D-RAP map for radio blackouts"""
embed = cmn.embed_factory(ctx)
embed.title = "D Region Absorption Predictions (D-RAP) Map"
embed.colour = cmn.colours.good
embed.description = \
"Image from [swpc.noaa.gov](https://www.swpc.noaa.gov/products/d-region-absorption-predictions-d-rap)"
embed.set_image(url=self.noaa_drap_url)
await ctx.send(embed=embed)
def setup(bot: commands.Bot): def setup(bot: commands.Bot):
bot.add_cog(PropagationCog(bot)) bot.add_cog(PropagationCog(bot))

View File

@ -1,7 +1,7 @@
""" """
Study extension for qrm Study extension for qrm
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
TeX extension for qrm TeX extension for qrm
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Time extension for qrm Time extension for qrm
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

10
info.py
View File

@ -1,18 +1,18 @@
""" """
Static info about the bot. Static info about the bot.
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
authors = ("@ClassAbbyAmplifier#2229", "@0x5c#0639") authors = ("@classabbyamp", "@0x5c.io")
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 = "Québec Free and Open-Source Licence Strong Reciprocity (LiLiQ-R+), version 1.1" license = "Québec Free and Open-Source Licence Strong Reciprocity (LiLiQ-R+), version 1.1"
contributing = """Check out the [source on GitHub](https://github.com/miaowware/qrm2). Contributions are welcome! contributing = """Check out the [source on GitHub](https://github.com/miaowware/qrm2). Contributions are welcome!
All issues and requests related to resources (including maps, band charts, data) should be added \ 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).""" in [miaowware/qrm-resources](https://github.com/miaowware/qrm-resources)."""
release = "2.9.0" release = "2.9.2"
bot_server = "https://discord.gg/Ntbg3J4" bot_server = "https://discord.gg/Ntbg3J4"

View File

@ -2,7 +2,7 @@
""" """
qrm, a bot for Discord qrm, a bot for Discord
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,10 +1,9 @@
py-cord~=2.3.2 py-cord-dev[speed]==2.5.0rc5
aiohttp[speedups]
ctyparser~=2.0 ctyparser~=2.0
gridtools~=1.0 gridtools~=1.0
callsignlookuptools[async]~=1.0 callsignlookuptools[async]~=1.1
beautifulsoup4 beautifulsoup4
pytz pytz
cairosvg cairosvg
httpx httpx
pydantic pydantic~=2.5

View File

@ -1,7 +1,7 @@
""" """
Resource schemas generator for qrm2. Resource schemas generator for qrm2.
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Information about callsigns for the prefixes command in hamcog. Information about callsigns for the prefixes command in hamcog.
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Information about callsigns for the CA prefixes command in hamcog. Information about callsigns for the CA prefixes command in hamcog.
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Information about callsigns for the US prefixes command in hamcog. Information about callsigns for the US prefixes command in hamcog.
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
A listing of hamstudy command resources A listing of hamstudy command resources
--- ---
Copyright (C) 2019-2021 classabbyamp, 0x5c Copyright (C) 2019-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

8
run.sh
View File

@ -17,7 +17,7 @@ fi
# Argument handling # Argument handling
_PASS_ERRORS=0 _PASS_ERRORS=0
_NO_BOTENV=0 _NO_BOTENV=0
while [ ! -z "$1" ]; do while [ -n "$1" ]; do
case $1 in case $1 in
--pass-errors) --pass-errors)
_PASS_ERRORS=1 _PASS_ERRORS=1
@ -35,7 +35,7 @@ done
# If $PYTHON_BIN is not defined, default to 'python3.11' # If $PYTHON_BIN is not defined, default to 'python3.11'
if [ $_NO_BOTENV -eq 1 -a -z "$PYTHON_BIN" ]; then if [ $_NO_BOTENV -eq 1 ] && [ -z "$PYTHON_BIN" ]; then
PYTHON_BIN='python3.11' PYTHON_BIN='python3.11'
fi fi
@ -69,9 +69,9 @@ echo "$0: Starting bot..."
# The loop # The loop
while true; do while true; do
if [ $_NO_BOTENV -eq 1 ]; then if [ $_NO_BOTENV -eq 1 ]; then
"$PYTHON_BIN" main.py $@ "$PYTHON_BIN" main.py "$@"
else else
./$BOTENV/bin/python3 main.py $@ "./$BOTENV/bin/python3" main.py "$@"
fi fi
err=$? err=$?
_message="$0: The bot exited with [$err]" _message="$0: The bot exited with [$err]"

View File

@ -1,7 +1,7 @@
""" """
Wrapper to handle aiohttp connector creation. Wrapper to handle aiohttp connector creation.
--- ---
Copyright (C) 2020-2021 classabbyamp, 0x5c Copyright (C) 2020-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """

View File

@ -1,7 +1,7 @@
""" """
Resources manager for qrm2. Resources manager for qrm2.
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -23,7 +23,7 @@ class ResourcesManager:
def parse_index(self, index: str): def parse_index(self, index: str):
"""Parses the index.""" """Parses the index."""
return Index.parse_raw(index) return Index.model_validate_json(index)
def sync_fetch(self, filepath: str): def sync_fetch(self, filepath: str):
"""Fetches files in sync mode.""" """Fetches files in sync mode."""

View File

@ -1,7 +1,7 @@
""" """
Resource index models for qrm2. Resource index models for qrm2.
--- ---
Copyright (C) 2021 classabbyamp, 0x5c Copyright (C) 2021-2023 classabbyamp, 0x5c
SPDX-License-Identifier: LiLiQ-Rplus-1.1 SPDX-License-Identifier: LiLiQ-Rplus-1.1
""" """
@ -10,7 +10,7 @@ SPDX-License-Identifier: LiLiQ-Rplus-1.1
from collections.abc import Mapping from collections.abc import Mapping
from datetime import datetime from datetime import datetime
from pydantic import BaseModel from pydantic import BaseModel, RootModel
class File(BaseModel): class File(BaseModel):
@ -22,18 +22,17 @@ class File(BaseModel):
return repr(self) return repr(self)
class Resource(BaseModel, Mapping): class Resource(RootModel, Mapping):
# 'A Beautiful Hack' https://github.com/samuelcolvin/pydantic/issues/1802 root: dict[str, list[File]]
__root__: dict[str, list[File]]
def __getitem__(self, key: str) -> list[File]: def __getitem__(self, key: str) -> list[File]:
return self.__root__[key] return self.root[key]
def __iter__(self): def __iter__(self):
return iter(self.__root__) return iter(self.root)
def __len__(self) -> int: def __len__(self) -> int:
return len(self.__root__) return len(self.root)
# For some reason those were not the same??? # For some reason those were not the same???
def __str__(self) -> str: def __str__(self) -> str:
@ -41,7 +40,7 @@ class Resource(BaseModel, Mapping):
# Make the repr more logical (despite the technical inaccuracy) # Make the repr more logical (despite the technical inaccuracy)
def __repr_args__(self): def __repr_args__(self):
return self.__root__.items() return self.root.items()
class Index(BaseModel, Mapping): class Index(BaseModel, Mapping):