mirror of
https://github.com/miaowware/qrm2.git
synced 2024-10-31 14:27:11 -04:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4b55ab49b7 | ||
|
cf378a2ef4 | ||
|
13a8a63300 | ||
|
23619949d7 | ||
|
444687bd12 | ||
|
86da8d135a | ||
|
67add85a7a | ||
|
abdc5ebacb | ||
|
a5cbb5a09a | ||
|
ce99cc194e | ||
|
f8d7316071 | ||
|
9feeb01e42 | ||
|
fcb682ec4a | ||
|
c8a1128927 | ||
|
df08cefe25 | ||
|
cf93773a3c | ||
|
642b49041a | ||
|
e95f991300 | ||
|
56ae14a5c3 | ||
|
30c6e96883 | ||
|
44a6905f7b | ||
|
d7de78e582 | ||
|
b000c9173e | ||
|
5460dd811b | ||
|
a00d613430 |
84
.github/workflows/docker.yml
vendored
84
.github/workflows/docker.yml
vendored
@ -3,6 +3,10 @@
|
||||
name: Docker Build and Deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
# Publish `master` as Docker `dev` image.
|
||||
branches:
|
||||
@ -11,29 +15,42 @@ on:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: Build and push docker images
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
uses: classabbyamp/treeless-checkout-action@v1
|
||||
|
||||
- name: Write ref to file
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
run: git rev-list -n 1 $GITHUB_REF > ./git_commit
|
||||
|
||||
- name: Build image
|
||||
id: build_image
|
||||
run: |
|
||||
IMAGE_ID=${GITHUB_REPOSITORY,,}
|
||||
IMAGE_NAME=${IMAGE_ID#*/}
|
||||
echo "image_id=$IMAGE_ID" >> $GITHUB_ENV
|
||||
echo "image_name=$IMAGE_NAME" >> $GITHUB_ENV
|
||||
docker build . --file Dockerfile -t $IMAGE_NAME
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ github.repository }}
|
||||
tags: |
|
||||
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
|
||||
uses: docker/login-action@v1
|
||||
@ -42,41 +59,10 @@ jobs:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Tag image
|
||||
id: tag_image
|
||||
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
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
url: ${{ secrets.DEPLOY_URL }}
|
||||
method: POST
|
||||
headers: '{"Authentication": "Token ${{ secrets.DEPLOY_TOKEN }}"}'
|
||||
payload: '{"version": "${{ env.version }}"}'
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -12,6 +12,8 @@ jobs:
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
@ -46,12 +48,10 @@ jobs:
|
||||
|
||||
- name: Publish Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag_name: ${{ env.tag_version }}
|
||||
release_name: ${{ env.tag_subject }}
|
||||
tag: ${{ env.tag_version }}
|
||||
name: ${{ env.tag_subject }}
|
||||
body: |
|
||||
${{ env.tag_body }}
|
||||
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -7,6 +7,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
## [Unreleased]
|
||||
|
||||
|
||||
## [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
|
||||
### Changed
|
||||
- Migrated to Pycord.
|
||||
@ -239,7 +255,9 @@ 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.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.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
|
||||
|
15
Dockerfile
15
Dockerfile
@ -1,10 +1,9 @@
|
||||
FROM ghcr.io/void-linux/void-linux:latest-full-x86_64-musl
|
||||
LABEL org.opencontainers.image.source https://github.com/miaowware/qrm2
|
||||
FROM ghcr.io/void-linux/void-musl-full
|
||||
|
||||
COPY . /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 UID 1000
|
||||
ARG GID 1000
|
||||
@ -14,19 +13,19 @@ RUN \
|
||||
xbps-install -Suy xbps -R ${REPOSITORY} && \
|
||||
xbps-install -uy -R ${REPOSITORY} && \
|
||||
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 ****" && \
|
||||
pip3 install -U pip setuptools wheel && \
|
||||
pip3 install -r requirements.txt && \
|
||||
python3.11 -m venv botenv && \
|
||||
botenv/bin/pip install -U pip setuptools wheel && \
|
||||
botenv/bin/pip install -r requirements.txt && \
|
||||
echo "**** clean up ****" && \
|
||||
rm -rf \
|
||||
/root/.cache \
|
||||
/tmp/* \
|
||||
/var/cache/xbps/*
|
||||
|
||||
ENV PYTHON_BIN python3
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
USER $UID:$GID
|
||||
|
||||
CMD ["/bin/sh", "run.sh", "--pass-errors", "--no-botenv"]
|
||||
CMD ["/bin/sh", "run.sh", "--pass-errors"]
|
||||
|
@ -38,7 +38,7 @@ All issues and requests related to resources (including maps, band charts, data)
|
||||
|
||||
## 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.
|
||||
See [`LICENCE`](LICENCE) for full license text (Français / English).
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Common tools for the bot.
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
@ -12,7 +12,7 @@ import enum
|
||||
import json
|
||||
import re
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Union
|
||||
@ -165,9 +165,9 @@ class GlobalChannelConverter(commands.IDConverter):
|
||||
|
||||
def embed_factory(ctx: commands.Context) -> discord.Embed:
|
||||
"""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:
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
ae7q extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Base extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -2,7 +2,7 @@
|
||||
Callsign Lookup extension for qrm
|
||||
---
|
||||
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
|
||||
"""
|
||||
@ -12,7 +12,6 @@ from typing import Dict
|
||||
|
||||
import aiohttp
|
||||
from callsignlookuptools import QrzAsyncClient, CallsignLookupError, CallsignData
|
||||
from callsignlookuptools.common.dataclasses import Trustee
|
||||
|
||||
from discord.ext import commands
|
||||
|
||||
@ -74,7 +73,7 @@ class QRZCog(commands.Cog):
|
||||
embed.title = f"QRZ Data for {data.callsign}"
|
||||
embed.colour = cmn.colours.good
|
||||
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)
|
||||
|
||||
for title, val in qrz_process_info(data).items():
|
||||
@ -101,9 +100,9 @@ def qrz_process_info(data: CallsignData) -> Dict:
|
||||
qsl = dict()
|
||||
if data.qsl is not None:
|
||||
qsl = {
|
||||
"eQSL?": data.qsl.eqsl.name.title(),
|
||||
"Paper QSL?": data.qsl.mail.name.title(),
|
||||
"LotW?": data.qsl.lotw.name.title(),
|
||||
"eQSL?": data.qsl.eqsl,
|
||||
"Paper QSL?": data.qsl.mail,
|
||||
"LotW?": data.qsl.lotw,
|
||||
"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,
|
||||
"Previous Callsign": data.prev_call,
|
||||
"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,
|
||||
} | qsl
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
Codes extension for qrm
|
||||
---
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Contest Calendar extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Conversion extension for qrm
|
||||
---
|
||||
Copyright (C) 2020-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2020-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -2,7 +2,7 @@
|
||||
DXCC Prefix Lookup extension for qrm
|
||||
---
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Fun extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Grid extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Image extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -2,18 +2,16 @@
|
||||
Land Weather extension for qrm
|
||||
---
|
||||
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
|
||||
"""
|
||||
|
||||
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
import aiohttp
|
||||
|
||||
from discord import Embed
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import common as cmn
|
||||
@ -102,7 +100,32 @@ class WeatherCog(commands.Cog):
|
||||
|
||||
Airports should be given as an \
|
||||
[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)
|
||||
async def taf(self, ctx: commands.Context, airport: str):
|
||||
@ -110,57 +133,28 @@ class WeatherCog(commands.Cog):
|
||||
|
||||
Airports should be given as an \
|
||||
[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)
|
||||
airport = airport.upper()
|
||||
|
||||
if 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:
|
||||
if not re.fullmatch(r"\w(\w|\d){2,3}", airport):
|
||||
embed.title = "Invalid airport given!"
|
||||
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://www.aviationweather.gov/metar/data?ids={airport}&format=raw&hours={hours}"
|
||||
f"&taf={'on' if taf else 'off'}&layout=off")
|
||||
url = f"https://aviationweather.gov/api/data/taf?ids={airport}&format=raw&metar=true"
|
||||
async with self.session.get(url) as r:
|
||||
if r.status != 200:
|
||||
raise cmn.BotHTTPError(r)
|
||||
page = await r.text()
|
||||
taf = await r.text()
|
||||
|
||||
# pare down to just the data
|
||||
page = page.split("<!-- Data starts here -->")[1].split("<!-- Data ends here -->")[0].strip()
|
||||
# split at <hr>s
|
||||
data = re.split(r"<hr.*>", page, maxsplit=len(airport))
|
||||
embed.title = f"Current TAF for {airport}"
|
||||
embed.description = "Data from [aviationweather.gov](https://www.aviationweather.gov/)."
|
||||
embed.colour = cmn.colours.good
|
||||
embed.description += f"\n\n```\n{taf}\n```"
|
||||
|
||||
parsed = []
|
||||
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(" ", " ")
|
||||
line = line.strip("\n")
|
||||
parsed.append(line)
|
||||
return parsed
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Morse Code extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Prefixes Lookup extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Propagation extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
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"
|
||||
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"
|
||||
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):
|
||||
self.bot = bot
|
||||
@ -86,6 +87,17 @@ class PropagationCog(commands.Cog):
|
||||
embed.set_image(url="attachment://solarweather.png")
|
||||
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):
|
||||
bot.add_cog(PropagationCog(bot))
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Study extension for qrm
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
TeX extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Time extension for qrm
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
6
info.py
6
info.py
@ -1,18 +1,18 @@
|
||||
"""
|
||||
Static info about the bot.
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
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."""
|
||||
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!
|
||||
|
||||
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.9.0"
|
||||
release = "2.9.2"
|
||||
bot_server = "https://discord.gg/Ntbg3J4"
|
||||
|
2
main.py
2
main.py
@ -2,7 +2,7 @@
|
||||
"""
|
||||
qrm, a bot for Discord
|
||||
---
|
||||
Copyright (C) 2019-2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2019-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,10 +1,9 @@
|
||||
py-cord~=2.3.2
|
||||
aiohttp[speedups]
|
||||
py-cord-dev[speed]==2.5.0rc5
|
||||
ctyparser~=2.0
|
||||
gridtools~=1.0
|
||||
callsignlookuptools[async]~=1.0
|
||||
callsignlookuptools[async]~=1.1
|
||||
beautifulsoup4
|
||||
pytz
|
||||
cairosvg
|
||||
httpx
|
||||
pydantic
|
||||
pydantic~=2.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resource schemas generator for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
8
run.sh
8
run.sh
@ -17,7 +17,7 @@ fi
|
||||
# Argument handling
|
||||
_PASS_ERRORS=0
|
||||
_NO_BOTENV=0
|
||||
while [ ! -z "$1" ]; do
|
||||
while [ -n "$1" ]; do
|
||||
case $1 in
|
||||
--pass-errors)
|
||||
_PASS_ERRORS=1
|
||||
@ -35,7 +35,7 @@ done
|
||||
|
||||
|
||||
# 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'
|
||||
fi
|
||||
|
||||
@ -69,9 +69,9 @@ echo "$0: Starting bot..."
|
||||
# The loop
|
||||
while true; do
|
||||
if [ $_NO_BOTENV -eq 1 ]; then
|
||||
"$PYTHON_BIN" main.py $@
|
||||
"$PYTHON_BIN" main.py "$@"
|
||||
else
|
||||
./$BOTENV/bin/python3 main.py $@
|
||||
"./$BOTENV/bin/python3" main.py "$@"
|
||||
fi
|
||||
err=$?
|
||||
_message="$0: The bot exited with [$err]"
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resources manager for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
@ -23,7 +23,7 @@ class ResourcesManager:
|
||||
|
||||
def parse_index(self, index: str):
|
||||
"""Parses the index."""
|
||||
return Index.parse_raw(index)
|
||||
return Index.model_validate_json(index)
|
||||
|
||||
def sync_fetch(self, filepath: str):
|
||||
"""Fetches files in sync mode."""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Resource index models for qrm2.
|
||||
---
|
||||
Copyright (C) 2021 classabbyamp, 0x5c
|
||||
Copyright (C) 2021-2023 classabbyamp, 0x5c
|
||||
|
||||
SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
"""
|
||||
@ -10,7 +10,7 @@ SPDX-License-Identifier: LiLiQ-Rplus-1.1
|
||||
from collections.abc import Mapping
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, RootModel
|
||||
|
||||
|
||||
class File(BaseModel):
|
||||
@ -22,18 +22,17 @@ class File(BaseModel):
|
||||
return repr(self)
|
||||
|
||||
|
||||
class Resource(BaseModel, Mapping):
|
||||
# 'A Beautiful Hack' https://github.com/samuelcolvin/pydantic/issues/1802
|
||||
__root__: dict[str, list[File]]
|
||||
class Resource(RootModel, Mapping):
|
||||
root: dict[str, list[File]]
|
||||
|
||||
def __getitem__(self, key: str) -> list[File]:
|
||||
return self.__root__[key]
|
||||
return self.root[key]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.__root__)
|
||||
return iter(self.root)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.__root__)
|
||||
return len(self.root)
|
||||
|
||||
# For some reason those were not the same???
|
||||
def __str__(self) -> str:
|
||||
@ -41,7 +40,7 @@ class Resource(BaseModel, Mapping):
|
||||
|
||||
# Make the repr more logical (despite the technical inaccuracy)
|
||||
def __repr_args__(self):
|
||||
return self.__root__.items()
|
||||
return self.root.items()
|
||||
|
||||
|
||||
class Index(BaseModel, Mapping):
|
||||
|
Loading…
Reference in New Issue
Block a user