21 Commits

Author SHA1 Message Date
0x5c 6b0cdb6249 Merge pull request #463 from miaowware/update-changelog
Bump version to 2.9.0
2023-01-13 03:51:01 -05:00
0x5c 4eed94b55b Bump version to 2.9.0 2023-01-13 03:48:45 -05:00
0x5c 3110961a3a exts/propagation: Fix ?solarweather no image bug
Back to the ugly hack of downloading the image and uploading it to discord.

Fixes #461
2023-01-13 03:44:27 -05:00
0x5c a4c8a056ac First steps for move from aiohttp to httpx 2023-01-13 03:44:27 -05:00
classabbyamp 9368ccd9e2 exts/study: fix in DMs
fixes #442
2023-01-13 01:14:54 -05:00
0x5c 8efd958314 Merge pull request #460 from miaowware/delete-solar-aliases
exts/propagation: Remove deprecated ?solarweather aliases
2023-01-13 01:09:57 -05:00
0x5c 4803bf89b2 exts/propagation: Remove deprecated ?solarweather aliases
Fixes #332
2023-01-13 01:03:37 -05:00
classabbyamp c82216cae6 Revert "update changelog, bump release"
This reverts commit 1b0b244f99.
2023-01-13 00:48:06 -05:00
classabbyamp 1650cd50dc exts/callsign: simplify stringification, fix data validation 2023-01-12 22:24:06 -05:00
classabbyamp 1b0b244f99 update changelog, bump release 2023-01-01 16:22:42 -05:00
classabbyamp 5db77f78d9 exts/callsign: convert to callsignlookuptools (qrz only for now) 2023-01-01 16:22:42 -05:00
classabbyamp c7ea5e0998 migrate to pycord 2023-01-01 16:22:42 -05:00
classabbyamp adffd82127 utils/resources_manager.py: use httpx instead of requests 2023-01-01 16:22:42 -05:00
classabbyamp 970159e81b Makefile: update default python version to 3.11 2023-01-01 16:22:42 -05:00
0x5c f5aeefc934 Merge pull request #454 from miaowware/token-perms
.github/workflows/docker.yml: add package write perms
2022-10-12 01:08:29 -04:00
classabbyamp aac9262469 .github/workflows/docker.yml: add package write perms 2022-10-12 00:56:56 -04:00
0x5c b472cdfa25 Merge pull request #453 from miaowware/xbps-update
Dockerfile: ensure system update works
2022-10-11 19:57:13 -04:00
classabbyamp 585cae8b97 Dockerfile: ensure system update works 2022-10-11 18:17:53 -04:00
0x5c c3fbd3e719 Merge pull request #452 from miaowware/set-output
.github/workflows/docker.yml: remove deprecated set-output
2022-10-11 18:14:12 -04:00
classabbyamp 7eadb50b96 exts/dbconv: fix lint 2022-10-11 18:12:55 -04:00
classabbyamp 98642c099d .github/workflows/docker.yml: remove deprecated set-output
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-10-11 14:24:03 -04:00
16 changed files with 158 additions and 121 deletions
+11 -9
View File
@@ -15,6 +15,8 @@ jobs:
docker:
name: Build and push docker images
runs-on: ubuntu-20.04
permissions:
packages: write
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -29,8 +31,8 @@ jobs:
run: |
IMAGE_ID=${GITHUB_REPOSITORY,,}
IMAGE_NAME=${IMAGE_ID#*/}
echo ::set-output name=image_id::$IMAGE_ID
echo ::set-output name=image_name::$IMAGE_NAME
echo "image_id=$IMAGE_ID" >> $GITHUB_ENV
echo "image_name=$IMAGE_NAME" >> $GITHUB_ENV
docker build . --file Dockerfile -t $IMAGE_NAME
- name: Login to Github Container Registry
@@ -43,10 +45,10 @@ jobs:
- name: Tag image
id: tag_image
run: |
IMAGE_NAME=${{ steps.build_image.outputs.image_name }}
IMAGE_ID=ghcr.io/${{ steps.build_image.outputs.image_id }}
IMAGE_NAME=${{ env.image_name }}
IMAGE_ID=ghcr.io/${{ env.image_id }}
echo IMAGE_ID=$IMAGE_ID
echo ::set-output name=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,')
@@ -55,7 +57,7 @@ jobs:
# if version is master, set version to dev
[[ "$VERSION" == "master" ]] && VERSION=dev
echo VERSION=$VERSION
echo ::set-output name=version::$VERSION
echo "version=$VERSION" >> $GITHUB_ENV
# tag dev or x.x.x
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
@@ -64,8 +66,8 @@ jobs:
- name: Push images to registry
run: |
VERSION=${{ steps.tag_image.outputs.version }}
IMAGE_ID=${{ steps.tag_image.outputs.image_id }}
VERSION=${{ env.version }}
IMAGE_ID=${{ env.image_id }}
[[ "$VERSION" != "dev" ]] && docker push $IMAGE_ID:latest || true
docker push $IMAGE_ID:$VERSION
@@ -77,4 +79,4 @@ jobs:
url: ${{ secrets.DEPLOY_URL }}
method: POST
headers: '{"Authentication": "Token ${{ secrets.DEPLOY_TOKEN }}"}'
payload: '{"version": "${{ steps.tag_image.outputs.version }}"}'
payload: '{"version": "${{ env.version }}"}'
+12 -1
View File
@@ -7,6 +7,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
## [2.9.0] - 2023-01-13
### Changed
- Migrated to Pycord.
### Removed
- Long-deprecated aliases for `?solarweather`.
### Fixed
- Issue where ?hamstudy would not work in direct messages (#442).
- Issue where `?solarweather` would not show a picture (#461).
## [2.8.0] - 2022-06-24
### Removed
- `?ae7q` command (#448).
@@ -229,7 +239,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 1.0.0 - 2019-07-31 [YANKED]
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.8.0...HEAD
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.9.0...HEAD
[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
[2.7.5]: https://github.com/miaowware/qrm2/releases/tag/v2.7.5
+4 -3
View File
@@ -1,4 +1,4 @@
FROM ghcr.io/void-linux/void-linux:latest-mini-x86_64
FROM ghcr.io/void-linux/void-linux:latest-full-x86_64-musl
LABEL org.opencontainers.image.source https://github.com/miaowware/qrm2
COPY . /app
@@ -11,9 +11,10 @@ ARG GID 1000
RUN \
echo "**** update system ****" && \
xbps-install -SuyM -R ${REPOSITORY} && \
xbps-install -Suy xbps -R ${REPOSITORY} && \
xbps-install -uy -R ${REPOSITORY} && \
echo "**** install system packages ****" && \
xbps-install -yM -R ${REPOSITORY} ${PKGS} python3 python3-pip && \
xbps-install -y -R ${REPOSITORY} ${PKGS} python3 python3-pip && \
echo "**** install pip packages ****" && \
pip3 install -U pip setuptools wheel && \
pip3 install -r requirements.txt && \
+1 -1
View File
@@ -12,7 +12,7 @@
# Those are the defaults; they can be over-ridden if specified
# at en environment level or as 'make' arguments.
BOTENV ?= botenv
PYTHON_BIN ?= python3.9
PYTHON_BIN ?= python3.11
PIP_OUTPUT ?= -q
+13 -7
View File
@@ -18,10 +18,11 @@ from types import SimpleNamespace
from typing import Union
import aiohttp
import httpx
import discord
import discord.ext.commands as commands
from discord import Emoji, Reaction, PartialEmoji
from discord import Emoji, PartialEmoji
import data.options as opt
@@ -125,12 +126,16 @@ class ImagesGroup(collections.abc.Mapping):
class BotHTTPError(Exception):
"""Raised whan a requests fails (status != 200) in a command."""
def __init__(self, response: aiohttp.ClientResponse):
msg = f"Request failed: {response.status} {response.reason}"
def __init__(self, response: aiohttp.ClientResponse | httpx.Response):
if isinstance(response, aiohttp.ClientResponse):
self.status = response.status
self.reason = response.reason
else:
self.status = response.status_code
self.reason = response.reason_phrase
msg = f"Request failed: {self.status} {self.reason}"
super().__init__(msg)
self.response = response
self.status = response.status
self.reason = response.reason
# --- Converters ---
@@ -161,7 +166,8 @@ 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.set_footer(text=str(ctx.author), icon_url=str(ctx.author.avatar_url))
if ctx.author:
embed.set_footer(text=str(ctx.author), icon_url=str(ctx.author.avatar.url))
return embed
@@ -178,7 +184,7 @@ def error_embed_factory(ctx: commands.Context, exception: Exception, debug_mode:
return embed
async def add_react(msg: discord.Message, react: Union[Emoji, Reaction, PartialEmoji, str]):
async def add_react(msg: discord.Message, react: Union[Emoji, PartialEmoji, str]):
try:
await msg.add_reaction(react)
except discord.Forbidden:
+1 -1
View File
@@ -1,3 +1,3 @@
-r requirements.txt
flake8
discord.py-stubs==1.7.3
mypy
+5 -3
View File
@@ -141,7 +141,8 @@ class QrmHelpCommand(commands.HelpCommand):
embed.title = await self.get_command_signature(group)
embed.description = group.help
for cmd in await self.filter_commands(group.commands, sort=True):
embed.add_field(name=await self.get_command_signature(cmd), value=cmd.help, inline=False)
embed.add_field(name=await self.get_command_signature(cmd), value=cmd.help if cmd.help else "",
inline=False)
await self.context.send(embed=embed)
@@ -177,7 +178,7 @@ class BaseCog(commands.Cog):
@commands.Cog.listener()
async def on_ready(self):
if not self.bot_invite:
if not self.bot_invite and self.bot.user:
self.bot_invite = (f"https://discordapp.com/oauth2/authorize?client_id={self.bot.user.id}"
f"&scope=bot&permissions={opt.invite_perms}")
@@ -196,7 +197,8 @@ class BaseCog(commands.Cog):
inline=False)
if opt.enable_invite_cmd and (await self.bot.application_info()).bot_public:
embed.add_field(name="Invite qrm to Your Server", value=self.bot_invite, inline=False)
embed.set_thumbnail(url=str(self.bot.user.avatar_url))
if self.bot.user and self.bot.user.avatar:
embed.set_thumbnail(url=str(self.bot.user.avatar.url))
await ctx.send(embed=embed)
@commands.command(name="ping", aliases=["beep"], category=cmn.BoltCats.INFO)
+41 -44
View File
@@ -9,11 +9,10 @@ SPDX-License-Identifier: LiLiQ-Rplus-1.1
from typing import Dict
from datetime import datetime
import aiohttp
from qrztools import qrztools, QrzAsync, QrzError
from gridtools import Grid, LatLong
from callsignlookuptools import QrzAsyncClient, CallsignLookupError, CallsignData
from callsignlookuptools.common.dataclasses import Trustee
from discord.ext import commands
@@ -29,14 +28,16 @@ class QRZCog(commands.Cog):
self.qrz = None
try:
if keys.qrz_user and keys.qrz_pass:
self.qrz = QrzAsync(keys.qrz_user, keys.qrz_pass, useragent="discord-qrm2",
session=aiohttp.ClientSession(connector=bot.qrm.connector))
# seed the qrz object with the previous session key, in case it already works
session_key = ""
try:
with open("data/qrz_session") as qrz_file:
self.qrz.session_key = qrz_file.readline().strip()
session_key = qrz_file.readline().strip()
except FileNotFoundError:
pass
self.qrz = QrzAsyncClient(username=keys.qrz_user, password=keys.qrz_pass, useragent="discord-qrm2",
session_key=session_key,
session=aiohttp.ClientSession(connector=bot.qrm.connector))
except AttributeError:
pass
@@ -63,69 +64,65 @@ class QRZCog(commands.Cog):
async with ctx.typing():
try:
data = await self.qrz.get_callsign(callsign)
except QrzError as e:
data = await self.qrz.search(callsign)
except CallsignLookupError as e:
embed.colour = cmn.colours.bad
embed.description = str(e)
await ctx.send(embed=embed)
return
embed.title = f"QRZ Data for {data.call}"
embed.title = f"QRZ Data for {data.callsign}"
embed.colour = cmn.colours.good
embed.url = data.url
if data.image != qrztools.QrzImage():
if data.image is not None and data.image.url is not None:
embed.set_thumbnail(url=data.image.url)
for title, val in qrz_process_info(data).items():
if val:
if val is not None and (val := str(val)):
embed.add_field(name=title, value=val, inline=True)
await ctx.send(embed=embed)
def qrz_process_info(data: qrztools.QrzCallsignData) -> Dict:
if data.name != qrztools.Name():
def qrz_process_info(data: CallsignData) -> Dict:
if data.name is not None:
if opt.qrz_only_nickname:
if data.name.nickname:
name = data.name.nickname + " " + data.name.name
nm = data.name.name if data.name.name is not None else ""
if data.name.nickname is not None:
name = data.name.nickname + " " + nm
elif data.name.first:
name = data.name.first + " " + data.name.name
name = data.name.first + " " + nm
else:
name = data.name.name
name = nm
else:
name = data.name.formatted_name
name = data.name
else:
name = None
if data.address != qrztools.Address():
state = ", " + data.address.state + " " if data.address.state else ""
address = "\n".join(
[x for x
in [data.address.attn, data.address.line1, data.address.line2 + state, data.address.zip]
if x]
)
else:
address = None
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(),
"QSL Info": data.qsl.info,
}
return {
"Name": name,
"Country": data.address.country,
"Address": address,
"Grid Square": data.grid if data.grid != Grid(LatLong(0, 0)) else None,
"County": data.county if data.county else None,
"CQ Zone": data.cq_zone if data.cq_zone else None,
"ITU Zone": data.itu_zone if data.itu_zone else None,
"IOTA Designator": data.iota if data.iota else None,
"Expires": f"{data.expire_date:%Y-%m-%d}" if data.expire_date != datetime.min else None,
"Country": data.address.country if data.address is not None else None,
"Address": data.address,
"Grid Square": data.grid,
"County": data.county,
"CQ Zone": data.cq_zone,
"ITU Zone": data.itu_zone,
"IOTA Designator": data.iota,
"Expires": f"{data.expire_date:%Y-%m-%d}" if data.expire_date is not None else None,
"Aliases": ", ".join(data.aliases) if data.aliases else None,
"Previous Callsign": data.prev_call if data.prev_call else None,
"License Class": data.lic_class if data.lic_class else None,
"Trustee": data.trustee if data.trustee else None,
"eQSL?": "Yes" if data.eqsl else "No",
"Paper QSL?": "Yes" if data.mail_qsl else "No",
"LotW?": "Yes" if data.lotw_qsl else "No",
"QSL Info": data.qsl_manager if data.qsl_manager else None,
"Born": f"{data.born:%Y-%m-%d}" if data.born != datetime.min 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,
"Born": data.born,
} | qsl
def setup(bot):
+1 -1
View File
@@ -187,7 +187,7 @@ def _calc_volt(db: float, ref: float):
# testing code
if __name__ == "__main__":
while(True):
while True:
try:
ip = input("> ").split()
initial = float(ip[0])
+22 -17
View File
@@ -7,11 +7,11 @@ SPDX-License-Identifier: LiLiQ-Rplus-1.1
"""
from datetime import datetime
from io import BytesIO
import aiohttp
import cairosvg
from datetime import datetime
import httpx
import discord
import discord.ext.commands as commands
@@ -27,15 +27,17 @@ class PropagationCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.session = aiohttp.ClientSession(connector=bot.qrm.connector)
self.httpx_client: httpx.AsyncClient = bot.qrm.httpx_client
@commands.command(name="mufmap", aliases=["muf"], category=cmn.Cats.WEATHER)
async def mufmap(self, ctx: commands.Context):
"""Shows a world map of the Maximum Usable Frequency (MUF)."""
async with ctx.typing():
async with self.session.get(self.muf_url, headers={"Connection": "Upgrade", "Upgrade": "http/1.1"}) as r:
svg = await r.read()
out = BytesIO(cairosvg.svg2png(bytestring=svg))
resp = await self.httpx_client.get(self.muf_url)
await resp.aclose()
if resp.status_code != 200:
raise cmn.BotHTTPError(resp)
out = BytesIO(cairosvg.svg2png(bytestring=await resp.aread()))
file = discord.File(out, "muf_map.png")
embed = cmn.embed_factory(ctx)
embed.title = "Maximum Usable Frequency Map"
@@ -47,9 +49,11 @@ class PropagationCog(commands.Cog):
async def fof2map(self, ctx: commands.Context):
"""Shows a world map of the Critical Frequency (foF2)."""
async with ctx.typing():
async with self.session.get(self.fof2_url, headers={"Connection": "Upgrade", "Upgrade": "http/1.1"}) as r:
svg = await r.read()
out = BytesIO(cairosvg.svg2png(bytestring=svg))
resp = await self.httpx_client.get(self.fof2_url)
await resp.aclose()
if resp.status_code != 200:
raise cmn.BotHTTPError(resp)
out = BytesIO(cairosvg.svg2png(bytestring=await resp.aread()))
file = discord.File(out, "fof2_map.png")
embed = cmn.embed_factory(ctx)
embed.title = "Critical Frequency (foF2) Map"
@@ -67,19 +71,20 @@ class PropagationCog(commands.Cog):
embed.set_image(url=self.gl_baseurl + date_params)
await ctx.send(embed=embed)
@commands.command(name="solarweather", aliases=["solar", "bandconditions", "cond", "condx", "conditions"],
category=cmn.Cats.WEATHER)
@commands.command(name="solarweather", aliases=["solar"], category=cmn.Cats.WEATHER)
async def solarweather(self, ctx: commands.Context):
"""Gets a solar weather report."""
resp = await self.httpx_client.get(self.n0nbh_sun_url)
await resp.aclose()
if resp.status_code != 200:
raise cmn.BotHTTPError(resp)
img = BytesIO(await resp.aread())
file = discord.File(img, "solarweather.png")
embed = cmn.embed_factory(ctx)
embed.title = "☀️ Current Solar Weather"
if ctx.invoked_with in ["bandconditions", "cond", "condx", "conditions"]:
embed.add_field(name="⚠️ Deprecated Command Alias",
value=(f"This command has been renamed to `{ctx.prefix}solar`!\n"
"The alias you used will be removed in the next version."))
embed.colour = cmn.colours.good
embed.set_image(url=self.n0nbh_sun_url)
await ctx.send(embed=embed)
embed.set_image(url="attachment://solarweather.png")
await ctx.send(file=file, embed=embed)
def setup(bot: commands.Bot):
+19 -13
View File
@@ -159,13 +159,13 @@ class StudyCog(commands.Cog):
await cmn.add_react(q_msg, list(self.choices.values())[i])
await cmn.add_react(q_msg, cmn.emojis.question)
def check(reaction, user):
return (user.id != self.bot.user.id
and reaction.message.id == q_msg.id
and (str(reaction.emoji) in self.choices.values() or str(reaction.emoji) == cmn.emojis.question))
def check(ev):
return (ev.user_id != self.bot.user.id
and ev.message_id == q_msg.id
and (str(ev.emoji) in self.choices.values() or str(ev.emoji) == cmn.emojis.question))
try:
reaction, user = await self.bot.wait_for("reaction_add", timeout=300.0, check=check)
ev = await self.bot.wait_for("raw_reaction_add", timeout=300.0, check=check)
except asyncio.TimeoutError:
embed.set_field_at(1, name="Answers", value=answers_str_bolded, inline=False)
embed.set_field_at(2, name="Answer",
@@ -174,16 +174,18 @@ class StudyCog(commands.Cog):
embed.colour = cmn.colours.timeout
await q_msg.edit(embed=embed)
else:
if str(reaction.emoji) == cmn.emojis.question:
if str(ev.emoji) == cmn.emojis.question:
embed.set_field_at(1, name="Answers", value=answers_str_bolded, inline=False)
embed.set_field_at(2, name="Answer",
value=f"The correct answer was {self.choices[question['answer']]}", inline=False)
embed.add_field(name="Answer Requested By", value=str(user), inline=False)
# only available in guilds, but it only makes sense there
if ev.member:
embed.add_field(name="Answer Requested By", value=str(ev.member), inline=False)
embed.colour = cmn.colours.timeout
await q_msg.edit(embed=embed)
else:
answers_str_checked = ""
chosen_ans = self.choices_inv[str(reaction.emoji)]
chosen_ans = self.choices_inv[str(ev.emoji)]
for letter, ans in answers.items():
answers_str_checked += f"{self.choices[letter]}"
if letter == question["answer"] == chosen_ans:
@@ -195,19 +197,23 @@ class StudyCog(commands.Cog):
else:
answers_str_checked += f" {ans}\n"
if self.choices[question["answer"]] == str(reaction.emoji):
if self.choices[question["answer"]] == str(ev.emoji):
embed.set_field_at(1, name="Answers", value=answers_str_checked, inline=False)
embed.set_field_at(2, name="Answer", value=(f"{cmn.emojis.check_mark} "
f"**Correct!** The answer was {reaction.emoji}"))
embed.add_field(name="Answered By", value=str(user), inline=False)
f"**Correct!** The answer was {ev.emoji}"))
# only available in guilds, but it only makes sense there
if ev.member:
embed.add_field(name="Answered By", value=str(ev.member), inline=False)
embed.colour = cmn.colours.good
await q_msg.edit(embed=embed)
else:
embed.set_field_at(1, name="Answers", value=answers_str_checked, inline=False)
embed.set_field_at(2, name="Answer",
value=(f"{cmn.emojis.x} **Incorrect!** The correct answer was "
f"{self.choices[question['answer']]}, not {reaction.emoji}"))
embed.add_field(name="Answered By", value=str(user), inline=False)
f"{self.choices[question['answer']]}, not {ev.emoji}"))
# only available in guilds, but it only makes sense there
if ev.member:
embed.add_field(name="Answered By", value=str(ev.member), inline=False)
embed.colour = cmn.colours.bad
await q_msg.edit(embed=embed)
+1 -1
View File
@@ -14,5 +14,5 @@ contributing = """Check out the [source on GitHub](https://github.com/miaowware/
All issues and requests related to resources (including maps, band charts, data) should be added \
in [miaowware/qrm-resources](https://github.com/miaowware/qrm-resources)."""
release = "2.8.0"
release = "2.9.0"
bot_server = "https://discord.gg/Ntbg3J4"
+13 -10
View File
@@ -16,6 +16,7 @@ from datetime import datetime, time
from types import SimpleNamespace
from pathlib import Path
import httpx
import pytz
import discord
@@ -49,9 +50,9 @@ connector = loop.run_until_complete(conn.new_connector())
# Defining the intents
intents = discord.Intents.none()
intents.guilds = True
intents.guild_messages = True
intents.dm_messages = True
intents.messages = True
intents.reactions = True
intents.message_content = True
member_cache = discord.MemberCacheFlags.from_intents(intents)
@@ -69,6 +70,8 @@ bot.qrm = SimpleNamespace()
# Let's store stuff here.
bot.qrm.connector = connector
bot.qrm.debug_mode = debug_mode
# TODO: Add code to close the client
bot.qrm.httpx_client = httpx.AsyncClient()
# --- Commands ---
@@ -81,7 +84,7 @@ async def _restart_bot(ctx: commands.Context):
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
print(f"[**] Restarting! Requested by {ctx.author}.")
exit_code = 42 # Signals to the wrapper script that the bot needs to be restarted.
await bot.logout()
await bot.close()
@bot.command(name="shutdown", aliases=["shut"], category=cmn.BoltCats.ADMIN)
@@ -92,7 +95,7 @@ async def _shutdown_bot(ctx: commands.Context):
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
print(f"[**] Shutting down! Requested by {ctx.author}.")
exit_code = 0 # Signals to the wrapper script that the bot should not be restarted.
await bot.logout()
await bot.close()
@bot.group(name="extctl", aliases=["ex"], case_insensitive=True, category=cmn.BoltCats.ADMIN)
@@ -123,10 +126,10 @@ async def _extctl_load(ctx: commands.Context, extension: str):
"""Loads an extension."""
try:
bot.load_extension(ext_dir + "." + extension)
except commands.ExtensionNotFound as e:
except discord.errors.ExtensionNotFound as e:
try:
bot.load_extension(plugin_dir + "." + extension)
except commands.ExtensionNotFound:
except discord.errors.ExtensionNotFound:
raise e
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
@@ -140,10 +143,10 @@ async def _extctl_reload(ctx: commands.Context, extension: str):
await cmn.add_react(ctx.message, pika)
try:
bot.reload_extension(ext_dir + "." + extension)
except commands.ExtensionNotLoaded as e:
except discord.errors.ExtensionNotLoaded as e:
try:
bot.reload_extension(plugin_dir + "." + extension)
except commands.ExtensionNotLoaded:
except discord.errors.ExtensionNotLoaded:
raise e
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
@@ -153,10 +156,10 @@ async def _extctl_unload(ctx: commands.Context, extension: str):
"""Unloads an extension."""
try:
bot.unload_extension(ext_dir + "." + extension)
except commands.ExtensionNotLoaded as e:
except discord.errors.ExtensionNotLoaded as e:
try:
bot.unload_extension(plugin_dir + "." + extension)
except commands.ExtensionNotLoaded:
except discord.errors.ExtensionNotLoaded:
raise e
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
+4 -3
View File
@@ -1,9 +1,10 @@
discord.py~=1.7.3
py-cord~=2.3.2
aiohttp[speedups]
ctyparser~=2.0
gridtools~=1.0
qrztools[async]~=1.0
callsignlookuptools[async]~=1.0
beautifulsoup4
pytz
cairosvg
requests
httpx
pydantic
+2 -2
View File
@@ -34,9 +34,9 @@ while [ ! -z "$1" ]; do
done
# If $PYTHON_BIN is not defined, default to 'python3.9'
# If $PYTHON_BIN is not defined, default to 'python3.11'
if [ $_NO_BOTENV -eq 1 -a -z "$PYTHON_BIN" ]; then
PYTHON_BIN='python3.9'
PYTHON_BIN='python3.11'
fi
+8 -5
View File
@@ -9,7 +9,7 @@ SPDX-License-Identifier: LiLiQ-Rplus-1.1
from pathlib import Path
import requests
import httpx
from utils.resources_models import Index
@@ -28,8 +28,11 @@ class ResourcesManager:
def sync_fetch(self, filepath: str):
"""Fetches files in sync mode."""
self.print_msg(f"Fetching {filepath}", "sync")
with requests.get(self.url + filepath) as resp:
return resp.content
resp = httpx.get(self.url + filepath)
resp.raise_for_status()
r = resp.content
resp.close()
return r
def sync_start(self, basedir: Path) -> Index:
"""Takes cares of constructing the local resources repository and initialising the RM."""
@@ -40,7 +43,7 @@ class ResourcesManager:
new_index: Index = self.parse_index(raw)
with (basedir / "index.json").open("wb") as file:
file.write(raw)
except (requests.RequestException, OSError) as ex:
except (httpx.RequestError, OSError) as ex:
self.print_msg(f"There was an issue fetching the index: {ex.__class__.__name__}: {ex}", "sync")
if (basedir / "index.json").exists():
self.print_msg("Old file exist, using old resources", "fallback")
@@ -58,7 +61,7 @@ class ResourcesManager:
try:
with (basedir / file.filename).open("wb") as f:
f.write(self.sync_fetch(file.filename))
except (requests.RequestException, OSError) as ex:
except (httpx.RequestError, OSError) as ex:
ex_cls = ex.__class__.__name__
self.print_msg(f"There was an issue fetching {file.filename}: {ex_cls}: {ex}", "sync")
if not (basedir / file.filename).exists():