mirror of
https://github.com/miaowware/qrm2.git
synced 2026-06-04 23:14:55 -04:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 940f45f4d4 | |||
| be7e29b387 | |||
| 518ead9ccd | |||
| 6e5acba6e9 | |||
| ad50a86f9d | |||
| 0bfa0c6e41 | |||
| ce64d882b8 | |||
| 0aac09f3bc | |||
| e3534d02d7 | |||
| cdcb0e17d2 | |||
| cd2503c953 | |||
| b4c165851c | |||
| 77a5af73bc | |||
| 4b7064cad9 | |||
| d8fe3cfa02 | |||
| ffc3be7e24 | |||
| 5dab93b7d3 | |||
| e660b1a8f5 | |||
| 3d96a43c50 | |||
| e8bb18ea8c | |||
| 19952396f2 | |||
| 1831c56f58 | |||
| 77e14a109c | |||
| 2ac13346d4 | |||
| 2eea7dce23 | |||
| f26a7af928 | |||
| 786440edcb | |||
| c47d211016 | |||
| 855935a26e | |||
| ff9d46f379 | |||
| 0f0c3bf723 | |||
| 7c818cfb34 |
@@ -57,20 +57,11 @@ jobs:
|
|||||||
- name: Push images to registry
|
- name: Push images to registry
|
||||||
run: docker push ${{ steps.tag_image.outputs.image_id }}
|
run: docker push ${{ steps.tag_image.outputs.image_id }}
|
||||||
|
|
||||||
# deploy:
|
- name: Deploy official images
|
||||||
# name: Deploy new images
|
id: deploy_images
|
||||||
# runs-on: ubuntu-20.04
|
uses: satak/webrequest-action@v1
|
||||||
# needs: docker
|
with:
|
||||||
# steps:
|
url: ${{ secrets.DEPLOY_URL }}
|
||||||
# - name: Deploy official images
|
method: POST
|
||||||
# id: deploy_images
|
headers: '{"Authentication": "Token ${{ secrets.DEPLOY_TOKEN }}"}'
|
||||||
# uses: satak/webrequest-action@v1.2.3
|
payload: '{"version": "${{ steps.tag_image.outputs.version }}"}'
|
||||||
# with:
|
|
||||||
# url: ${{ secrets.DEPLOY_URL }}
|
|
||||||
# method: POST
|
|
||||||
# headers: '{"Authentication": "Token ${{ secrets.DEPLOY_TOKEN }}"}'
|
|
||||||
# payload: |
|
|
||||||
# '{
|
|
||||||
# "repository": "${{ github.repository }}",
|
|
||||||
# "version": "${{ jobs.docker.steps.tag_image.outputs.version }}"
|
|
||||||
# }'
|
|
||||||
|
|||||||
@@ -25,18 +25,23 @@ jobs:
|
|||||||
SUBJECT=$(/usr/bin/git tag -l ${GITHUB_REF#refs/tags/} --format='%(subject)')
|
SUBJECT=$(/usr/bin/git tag -l ${GITHUB_REF#refs/tags/} --format='%(subject)')
|
||||||
BODY=$(/usr/bin/git tag -l ${GITHUB_REF#refs/tags/} --format='%(body)' | sed '/-----BEGIN PGP SIGNATURE-----/,$d')
|
BODY=$(/usr/bin/git tag -l ${GITHUB_REF#refs/tags/} --format='%(body)' | sed '/-----BEGIN PGP SIGNATURE-----/,$d')
|
||||||
|
|
||||||
echo SUBJECT=$SUBJECT
|
echo "SUBJECT=$SUBJECT"
|
||||||
echo BODY=$BODY
|
echo "BODY=$BODY"
|
||||||
|
|
||||||
echo ::set-output name=subject::${SUBJECT}
|
echo 'tag_subject<<EOS' >> $GITHUB_ENV
|
||||||
echo ::set-output name=body::${BODY}
|
echo "$SUBJECT" >> $GITHUB_ENV
|
||||||
echo ::set-output name=current_version::${GITHUB_REF#refs/tags/v}
|
echo 'EOS' >> $GITHUB_ENV
|
||||||
|
echo 'tag_body<<EOB' >> $GITHUB_ENV
|
||||||
|
echo "$BODY" >> $GITHUB_ENV
|
||||||
|
echo 'EOB' >> $GITHUB_ENV
|
||||||
|
echo "tag_version=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
echo "version_num=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Get Changelog Content
|
- name: Get Changelog Content
|
||||||
id: changelog_reader
|
id: changelog_reader
|
||||||
uses: mindsers/changelog-reader-action@v2
|
uses: mindsers/changelog-reader-action@v2
|
||||||
with:
|
with:
|
||||||
version: ${{ steps.get_tag.outputs.current_version }}
|
version: ${{ env.version_num }}
|
||||||
path: ./CHANGELOG.md
|
path: ./CHANGELOG.md
|
||||||
|
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
@@ -45,14 +50,13 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ steps.changelog_reader.outputs.version }}
|
tag_name: ${{ env.tag_version }}
|
||||||
release_name: ${{ steps.get_tag.outputs.subject }}
|
release_name: ${{ env.tag_subject }}
|
||||||
body: |
|
body: |
|
||||||
${{ steps.get_tag.outputs.body }}
|
${{ env.tag_body }}
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
${{ steps.changelog_reader.outputs.changes }}
|
${{ steps.changelog_reader.outputs.changes }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -7,6 +7,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.0] - 2020-10-31
|
||||||
|
### Added
|
||||||
|
- Italian (`it_hf`, `it_vhf`, `it_shf`), Japanese (`jp`) and Australian (`au`) band charts.
|
||||||
|
### Fixed
|
||||||
|
- Details to the Netherlands bandplan command to accurately represent VERNON (Netherlands ARRL equivalent organisation).
|
||||||
|
- eQSL, paper QSL, and Logbook of the World status in `?qrz` sometimes being shown incorrectly.
|
||||||
|
- Fixed network error in `?greyline`.
|
||||||
|
|
||||||
|
|
||||||
## [2.4.1] - 2020-10-06
|
## [2.4.1] - 2020-10-06
|
||||||
### Changed
|
### Changed
|
||||||
- Bumped discord.py to 1.5.0
|
- Bumped discord.py to 1.5.0
|
||||||
@@ -129,7 +138,8 @@ 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.4.1...HEAD
|
[Unreleased]: https://github.com/miaowware/qrm2/compare/v2.5.0...HEAD
|
||||||
|
[2.5.0]: https://github.com/miaowware/qrm2/releases/tag/v2.5.0
|
||||||
[2.4.1]: https://github.com/miaowware/qrm2/releases/tag/v2.4.1
|
[2.4.1]: https://github.com/miaowware/qrm2/releases/tag/v2.4.1
|
||||||
[2.4.0]: https://github.com/miaowware/qrm2/releases/tag/v2.4.0
|
[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.2]: https://github.com/miaowware/qrm2/releases/tag/v2.3.2
|
||||||
|
|||||||
@@ -15,11 +15,13 @@ import traceback
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
import discord.ext.commands as commands
|
import discord.ext.commands as commands
|
||||||
|
from discord import Emoji, Reaction, PartialEmoji
|
||||||
|
|
||||||
import data.options as opt
|
import data.options as opt
|
||||||
|
|
||||||
@@ -72,15 +74,6 @@ 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):
|
||||||
@@ -158,7 +151,7 @@ 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.utcnow(), colour=colours.neutral)
|
||||||
embed.set_footer(text=ctx.author, icon_url=str(ctx.author.avatar_url))
|
embed.set_footer(text=str(ctx.author), icon_url=str(ctx.author.avatar_url))
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
|
||||||
@@ -175,11 +168,12 @@ def error_embed_factory(ctx: commands.Context, exception: Exception, debug_mode:
|
|||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
|
||||||
async def add_react(msg: discord.Message, react: str):
|
async def add_react(msg: discord.Message, react: Union[Emoji, Reaction, PartialEmoji, str]):
|
||||||
try:
|
try:
|
||||||
await msg.add_reaction(react)
|
await msg.add_reaction(react)
|
||||||
except discord.Forbidden:
|
except discord.Forbidden:
|
||||||
print(f"[!!] Missing permissions to add reaction in '{msg.guild.id}/{msg.channel.id}'!")
|
idpath = (f"{msg.guild.id}/" if msg.guild else "") + str(msg.channel.id)
|
||||||
|
print(f"[!!] Missing permissions to add reaction in '{idpath}'!")
|
||||||
|
|
||||||
|
|
||||||
# --- Checks ---
|
# --- Checks ---
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ class BaseCog(commands.Cog):
|
|||||||
embed = cmn.embed_factory(ctx)
|
embed = cmn.embed_factory(ctx)
|
||||||
embed.title = "About qrm"
|
embed.title = "About qrm"
|
||||||
embed.description = info.description
|
embed.description = info.description
|
||||||
|
|
||||||
embed.add_field(name="Authors", value=", ".join(info.authors))
|
embed.add_field(name="Authors", value=", ".join(info.authors))
|
||||||
embed.add_field(name="License", value=info.license)
|
embed.add_field(name="License", value=info.license)
|
||||||
embed.add_field(name="Version", value=f"v{info.release}")
|
embed.add_field(name="Version", value=f"v{info.release}")
|
||||||
|
|||||||
+32
-33
@@ -11,6 +11,7 @@ the GNU General Public License, version 2.
|
|||||||
import math
|
import math
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import discord.ext.commands as commands
|
import discord.ext.commands as commands
|
||||||
|
|
||||||
@@ -21,49 +22,47 @@ from data import options as opt
|
|||||||
# not sure why but UnitConverter and Unit need to be defined before DbConvCog and convert()
|
# not sure why but UnitConverter and Unit need to be defined before DbConvCog and convert()
|
||||||
class UnitConverter(commands.Converter):
|
class UnitConverter(commands.Converter):
|
||||||
async def convert(self, ctx: commands.Context, argument: str):
|
async def convert(self, ctx: commands.Context, argument: str):
|
||||||
|
is_db = None
|
||||||
|
mult = None
|
||||||
|
unit = None
|
||||||
|
utype = None
|
||||||
try:
|
try:
|
||||||
return Unit(argument)
|
s = argument.lower()
|
||||||
|
if len(s) > 2 and s[:2] == "db":
|
||||||
|
is_db = True
|
||||||
|
if s[2:] in units:
|
||||||
|
u = units[s[2:]]
|
||||||
|
mult = u["mult"]
|
||||||
|
unit = u["log"]
|
||||||
|
utype = u["type"]
|
||||||
|
elif s in units:
|
||||||
|
is_db = False
|
||||||
|
u = units[s]
|
||||||
|
mult = u["mult"]
|
||||||
|
unit = u["scalar"]
|
||||||
|
utype = u["type"]
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Invalid unit: {argument}")
|
||||||
|
return Unit(argument, unit, utype, is_db, mult)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise commands.BadArgument(message=str(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):
|
class UnitType(Enum):
|
||||||
voltage = 1
|
voltage = 1
|
||||||
power = 2
|
power = 2
|
||||||
antenna = 3
|
antenna = 3
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Unit:
|
||||||
|
raw: str
|
||||||
|
unit: str
|
||||||
|
type: UnitType
|
||||||
|
is_db: bool
|
||||||
|
mult: int
|
||||||
|
|
||||||
|
|
||||||
class DbConvCog(commands.Cog):
|
class DbConvCog(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
@@ -85,7 +84,7 @@ class DbConvCog(commands.Cog):
|
|||||||
if value is not None and unit_from is not None and unit_to is not None:
|
if value is not None and unit_from is not None and unit_to is not None:
|
||||||
converted = convert(value, unit_from, unit_to)
|
converted = convert(value, unit_from, unit_to)
|
||||||
|
|
||||||
embed.title = f"{value:.3g} {unit_from} = {converted:.3g} {unit_to}"
|
embed.title = f"{value:.3g} {unit_from.unit} = {converted:.3g} {unit_to.unit}"
|
||||||
embed.colour = cmn.colours.good
|
embed.colour = cmn.colours.good
|
||||||
else:
|
else:
|
||||||
embed.title = "Decibel Quick Reference"
|
embed.title = "Decibel Quick Reference"
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ import common as cmn
|
|||||||
class FunCog(commands.Cog):
|
class FunCog(commands.Cog):
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
with open("resources/words") as words_file:
|
with open(cmn.paths.resources / "words") as words_file:
|
||||||
self.words = words_file.read().lower().splitlines()
|
self.words = words_file.read().lower().splitlines()
|
||||||
|
|
||||||
@commands.command(name="xkcd", aliases=["x"], category=cmn.cat.fun)
|
@commands.command(name="xkcd", aliases=["x"], category=cmn.cat.fun)
|
||||||
|
|||||||
+5
-12
@@ -8,8 +8,6 @@ the GNU General Public License, version 2.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import io
|
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
@@ -85,16 +83,11 @@ class ImageCog(commands.Cog):
|
|||||||
@commands.command(name="grayline", aliases=["greyline", "grey", "gray", "gl"], category=cmn.cat.maps)
|
@commands.command(name="grayline", aliases=["greyline", "grey", "gray", "gl"], category=cmn.cat.maps)
|
||||||
async def _grayline(self, ctx: commands.Context):
|
async def _grayline(self, ctx: commands.Context):
|
||||||
"""Gets a map of the current greyline, where HF propagation is the best."""
|
"""Gets a map of the current greyline, where HF propagation is the best."""
|
||||||
async with ctx.typing():
|
embed = cmn.embed_factory(ctx)
|
||||||
embed = cmn.embed_factory(ctx)
|
embed.title = "Current Greyline Conditions"
|
||||||
embed.title = "Current Greyline Conditions"
|
embed.colour = cmn.colours.good
|
||||||
embed.colour = cmn.colours.good
|
embed.set_image(url=self.gl_url)
|
||||||
async with self.session.get(self.gl_url) as resp:
|
await ctx.send(embed=embed)
|
||||||
if resp.status != 200:
|
|
||||||
raise cmn.BotHTTPError(resp)
|
|
||||||
data = io.BytesIO(await resp.read())
|
|
||||||
embed.set_image(url="attachment://greyline.jpg")
|
|
||||||
await ctx.send(embed=embed, file=discord.File(data, "greyline.jpg"))
|
|
||||||
|
|
||||||
|
|
||||||
def setup(bot: commands.Bot):
|
def setup(bot: commands.Bot):
|
||||||
|
|||||||
+6
-2
@@ -9,6 +9,7 @@ the GNU General Public License, version 2.
|
|||||||
|
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from ctyparser import BigCty
|
from ctyparser import BigCty
|
||||||
|
|
||||||
@@ -17,11 +18,14 @@ from discord.ext import commands, tasks
|
|||||||
import common as cmn
|
import common as cmn
|
||||||
|
|
||||||
|
|
||||||
|
cty_path = Path("./data/cty.json")
|
||||||
|
|
||||||
|
|
||||||
class LookupCog(commands.Cog):
|
class LookupCog(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
try:
|
try:
|
||||||
self.cty = BigCty("./data/cty.json")
|
self.cty = BigCty(cty_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
self.cty = BigCty()
|
self.cty = BigCty()
|
||||||
|
|
||||||
@@ -67,7 +71,7 @@ class LookupCog(commands.Cog):
|
|||||||
|
|
||||||
@tasks.loop(hours=24)
|
@tasks.loop(hours=24)
|
||||||
async def _update_cty(self):
|
async def _update_cty(self):
|
||||||
update = threading.Thread(target=run_update, args=(self.cty, "./data/cty.json"))
|
update = threading.Thread(target=run_update, args=(self.cty, cty_path))
|
||||||
update.start()
|
update.start()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -146,15 +146,15 @@ def qrz_process_info(data: dict):
|
|||||||
if address == "":
|
if address == "":
|
||||||
address = None
|
address = None
|
||||||
if "eqsl" in data:
|
if "eqsl" in data:
|
||||||
eqsl = "Yes" if data["eqsl"] == 1 else "No"
|
eqsl = "Yes" if data["eqsl"] == "1" else "No"
|
||||||
else:
|
else:
|
||||||
eqsl = "Unknown"
|
eqsl = "Unknown"
|
||||||
if "mqsl" in data:
|
if "mqsl" in data:
|
||||||
mqsl = "Yes" if data["mqsl"] == 1 else "No"
|
mqsl = "Yes" if data["mqsl"] == "1" else "No"
|
||||||
else:
|
else:
|
||||||
mqsl = "Unknown"
|
mqsl = "Unknown"
|
||||||
if "lotw" in data:
|
if "lotw" in data:
|
||||||
lotw = "Yes" if data["lotw"] == 1 else "No"
|
lotw = "Yes" if data["lotw"] == "1" else "No"
|
||||||
else:
|
else:
|
||||||
lotw = "Unknown"
|
lotw = "Unknown"
|
||||||
|
|
||||||
|
|||||||
+41
-58
@@ -8,12 +8,10 @@ the GNU General Public License, version 2.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import io
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
import discord
|
|
||||||
import discord.ext.commands as commands
|
import discord.ext.commands as commands
|
||||||
|
|
||||||
import common as cmn
|
import common as cmn
|
||||||
@@ -29,16 +27,11 @@ class WeatherCog(commands.Cog):
|
|||||||
@commands.command(name="bandconditions", aliases=["cond", "condx", "conditions"], category=cmn.cat.weather)
|
@commands.command(name="bandconditions", aliases=["cond", "condx", "conditions"], category=cmn.cat.weather)
|
||||||
async def _band_conditions(self, ctx: commands.Context):
|
async def _band_conditions(self, ctx: commands.Context):
|
||||||
"""Gets a solar conditions report."""
|
"""Gets a solar conditions report."""
|
||||||
async with ctx.typing():
|
embed = cmn.embed_factory(ctx)
|
||||||
embed = cmn.embed_factory(ctx)
|
embed.title = "Current Solar Conditions"
|
||||||
embed.title = "Current Solar Conditions"
|
embed.colour = cmn.colours.good
|
||||||
embed.colour = cmn.colours.good
|
embed.set_image(url="http://www.hamqsl.com/solarsun.php")
|
||||||
async with self.session.get("http://www.hamqsl.com/solarsun.php") as resp:
|
await ctx.send(embed=embed)
|
||||||
if resp.status != 200:
|
|
||||||
raise cmn.BotHTTPError(resp)
|
|
||||||
data = io.BytesIO(await resp.read())
|
|
||||||
embed.set_image(url="attachment://condx.png")
|
|
||||||
await ctx.send(embed=embed, file=discord.File(data, "condx.png"))
|
|
||||||
|
|
||||||
@commands.group(name="weather", aliases=["wttr"], case_insensitive=True, 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):
|
||||||
@@ -61,63 +54,53 @@ class WeatherCog(commands.Cog):
|
|||||||
async def _weather_conditions_forecast(self, ctx: commands.Context, *, location: str):
|
async def _weather_conditions_forecast(self, ctx: commands.Context, *, location: str):
|
||||||
"""Gets local weather forecast for the next three days from [wttr.in](http://wttr.in/).
|
"""Gets local weather forecast for the next three days from [wttr.in](http://wttr.in/).
|
||||||
See help of the `weather` command for possible location types and options."""
|
See help of the `weather` command for possible location types and options."""
|
||||||
async with ctx.typing():
|
try:
|
||||||
try:
|
units_arg = re.search(self.wttr_units_regex, location).group(1)
|
||||||
units_arg = re.search(self.wttr_units_regex, location).group(1)
|
except AttributeError:
|
||||||
except AttributeError:
|
units_arg = ""
|
||||||
units_arg = ""
|
if units_arg.lower() == "f":
|
||||||
if units_arg.lower() == "f":
|
units = "u"
|
||||||
units = "u"
|
elif units_arg.lower() == "c":
|
||||||
elif units_arg.lower() == "c":
|
units = "m"
|
||||||
units = "m"
|
else:
|
||||||
else:
|
units = ""
|
||||||
units = ""
|
|
||||||
|
|
||||||
loc = self.wttr_units_regex.sub("", location).strip()
|
loc = self.wttr_units_regex.sub("", location).strip()
|
||||||
|
|
||||||
embed = cmn.embed_factory(ctx)
|
embed = cmn.embed_factory(ctx)
|
||||||
embed.title = f"Weather Forecast for {loc}"
|
embed.title = f"Weather Forecast for {loc}"
|
||||||
embed.description = "Data from [wttr.in](http://wttr.in/)."
|
embed.description = "Data from [wttr.in](http://wttr.in/)."
|
||||||
embed.colour = cmn.colours.good
|
embed.colour = cmn.colours.good
|
||||||
|
|
||||||
loc = loc.replace(" ", "+")
|
loc = loc.replace(" ", "+")
|
||||||
async with self.session.get(f"http://wttr.in/{loc}_{units}pnFQ.png") as resp:
|
embed.set_image(url=f"http://wttr.in/{loc}_{units}pnFQ.png")
|
||||||
if resp.status != 200:
|
await ctx.send(embed=embed)
|
||||||
raise cmn.BotHTTPError(resp)
|
|
||||||
data = io.BytesIO(await resp.read())
|
|
||||||
embed.set_image(url="attachment://wttr_forecast.png")
|
|
||||||
await ctx.send(embed=embed, file=discord.File(data, "wttr_forecast.png"))
|
|
||||||
|
|
||||||
@_weather_conditions.command(name="now", aliases=["n"], category=cmn.cat.weather)
|
@_weather_conditions.command(name="now", aliases=["n"], category=cmn.cat.weather)
|
||||||
async def _weather_conditions_now(self, ctx: commands.Context, *, location: str):
|
async def _weather_conditions_now(self, ctx: commands.Context, *, location: str):
|
||||||
"""Gets current local weather conditions from [wttr.in](http://wttr.in/).
|
"""Gets current local weather conditions from [wttr.in](http://wttr.in/).
|
||||||
See help of the `weather` command for possible location types and options."""
|
See help of the `weather` command for possible location types and options."""
|
||||||
async with ctx.typing():
|
try:
|
||||||
try:
|
units_arg = re.search(self.wttr_units_regex, location).group(1)
|
||||||
units_arg = re.search(self.wttr_units_regex, location).group(1)
|
except AttributeError:
|
||||||
except AttributeError:
|
units_arg = ""
|
||||||
units_arg = ""
|
if units_arg.lower() == "f":
|
||||||
if units_arg.lower() == "f":
|
units = "u"
|
||||||
units = "u"
|
elif units_arg.lower() == "c":
|
||||||
elif units_arg.lower() == "c":
|
units = "m"
|
||||||
units = "m"
|
else:
|
||||||
else:
|
units = ""
|
||||||
units = ""
|
|
||||||
|
|
||||||
loc = self.wttr_units_regex.sub("", location).strip()
|
loc = self.wttr_units_regex.sub("", location).strip()
|
||||||
|
|
||||||
embed = cmn.embed_factory(ctx)
|
embed = cmn.embed_factory(ctx)
|
||||||
embed.title = f"Current Weather for {loc}"
|
embed.title = f"Current Weather for {loc}"
|
||||||
embed.description = "Data from [wttr.in](http://wttr.in/)."
|
embed.description = "Data from [wttr.in](http://wttr.in/)."
|
||||||
embed.colour = cmn.colours.good
|
embed.colour = cmn.colours.good
|
||||||
|
|
||||||
loc = loc.replace(" ", "+")
|
loc = loc.replace(" ", "+")
|
||||||
async with self.session.get(f"http://wttr.in/{loc}_0{units}pnFQ.png") as resp:
|
embed.set_image(url=f"http://wttr.in/{loc}_0{units}pnFQ.png")
|
||||||
if resp.status != 200:
|
await ctx.send(embed=embed)
|
||||||
raise cmn.BotHTTPError(resp)
|
|
||||||
data = io.BytesIO(await resp.read())
|
|
||||||
embed.set_image(url="attachment://wttr_now.png")
|
|
||||||
await ctx.send(embed=embed, file=discord.File(data, "wttr_now.png"))
|
|
||||||
|
|
||||||
|
|
||||||
def setup(bot: commands.Bot):
|
def setup(bot: commands.Bot):
|
||||||
|
|||||||
@@ -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.4.1"
|
release = "2.5.0"
|
||||||
bot_server = "https://discord.gg/Ntbg3J4"
|
bot_server = "https://discord.gg/Ntbg3J4"
|
||||||
|
|||||||
@@ -45,20 +45,18 @@ loop = asyncio.get_event_loop()
|
|||||||
connector = loop.run_until_complete(conn.new_connector())
|
connector = loop.run_until_complete(conn.new_connector())
|
||||||
|
|
||||||
# Defining the intents
|
# Defining the intents
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.none()
|
||||||
# We don't need those
|
intents.guilds = True
|
||||||
intents.bans = False
|
intents.guild_messages = True
|
||||||
intents.emojis = False
|
intents.dm_messages = True
|
||||||
intents.integrations = False
|
|
||||||
intents.webhooks = False
|
member_cache = discord.MemberCacheFlags.from_intents(intents)
|
||||||
intents.invites = False
|
|
||||||
intents.voice_states = False
|
|
||||||
intents.typing = False
|
|
||||||
|
|
||||||
bot = commands.Bot(command_prefix=opt.prefix,
|
bot = commands.Bot(command_prefix=opt.prefix,
|
||||||
case_insensitive=True,
|
case_insensitive=True,
|
||||||
description=info.description, help_command=commands.MinimalHelpCommand(),
|
description=info.description, help_command=commands.MinimalHelpCommand(),
|
||||||
intents=intents,
|
intents=intents,
|
||||||
|
member_cache=member_cache,
|
||||||
loop=loop,
|
loop=loop,
|
||||||
connector=connector)
|
connector=connector)
|
||||||
|
|
||||||
@@ -100,7 +98,7 @@ async def _extctl(ctx: commands.Context):
|
|||||||
"""Extension control commands.
|
"""Extension control commands.
|
||||||
Defaults to `list` if no subcommand specified"""
|
Defaults to `list` if no subcommand specified"""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
cmd = bot.get_command("extctl list")
|
cmd = _extctl_list
|
||||||
await ctx.invoke(cmd)
|
await ctx.invoke(cmd)
|
||||||
|
|
||||||
|
|
||||||
@@ -168,7 +166,7 @@ async def on_command_error(ctx: commands.Context, err: commands.CommandError):
|
|||||||
await cmn.add_react(ctx.message, cmn.emojis.warning)
|
await cmn.add_react(ctx.message, cmn.emojis.warning)
|
||||||
await ctx.send_help(ctx.command)
|
await ctx.send_help(ctx.command)
|
||||||
elif isinstance(err, commands.CommandNotFound):
|
elif isinstance(err, commands.CommandNotFound):
|
||||||
if ctx.invoked_with.startswith(("?", "!")):
|
if ctx.invoked_with and ctx.invoked_with.startswith(("?", "!")):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.question)
|
await cmn.add_react(ctx.message, cmn.emojis.question)
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
discord.py==1.5.0
|
discord.py~=1.5.0
|
||||||
ctyparser==2.0.0.post1
|
ctyparser~=2.0
|
||||||
beautifulsoup4==4.9.1
|
beautifulsoup4
|
||||||
lxml==4.5.2
|
lxml
|
||||||
pytz==2020.1
|
pytz
|
||||||
|
|||||||
@@ -7,12 +7,22 @@ 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 dataclasses import dataclass
|
||||||
|
|
||||||
from .callsigninfos import (us, ca)
|
from .callsigninfos import (us, ca)
|
||||||
from common import CallsignInfoData
|
|
||||||
|
|
||||||
|
|
||||||
# format: country: (title, description, text)
|
@dataclass
|
||||||
|
class CallsignInfoData:
|
||||||
|
"""Represents a country's callsign info"""
|
||||||
|
title: str = ""
|
||||||
|
desc: str = ""
|
||||||
|
calls: str = ""
|
||||||
|
emoji: str = ""
|
||||||
|
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
"us": CallsignInfoData([us.title, us.desc, us.calls, us.emoji]),
|
"us": CallsignInfoData(us.title, us.desc, us.calls, us.emoji),
|
||||||
"ca": CallsignInfoData([ca.title, ca.desc, ca.calls, ca.emoji]),
|
"ca": CallsignInfoData(ca.title, ca.desc, ca.calls, ca.emoji),
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 416 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 407 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 237 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 441 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -1,7 +1,12 @@
|
|||||||
{
|
{
|
||||||
|
"au": ["au.png", "Australia", "Amateur radio bands in Australia", "", "[Radio Amateur Society of Australia](https://vkradioamateurs.org/its-my-frequency-and-ill-cry-if-i-want-to/) [[PDF]](https://vkradioamateurs.org/wp-content/uploads/2018/05/VK-Band-Plan-Quick-Reference-1.pdf)", "🇦🇺"],
|
||||||
"ca": ["ca.png", "Canada", "Amateur radio bands in Canada", "**This bandplan is incomplete**; some bands, like 630m, are simply not present. It also does not cover any band above 30MHz.", "[RAC 0-30MHz Band Plan](https://www.rac.ca/wp-content/uploads/files/pdf/RAC%20Bandplan%20December%201%202015.pdf)", "🇨🇦"],
|
"ca": ["ca.png", "Canada", "Amateur radio bands in Canada", "**This bandplan is incomplete**; some bands, like 630m, are simply not present. It also does not cover any band above 30MHz.", "[RAC 0-30MHz Band Plan](https://www.rac.ca/wp-content/uploads/files/pdf/RAC%20Bandplan%20December%201%202015.pdf)", "🇨🇦"],
|
||||||
"cn": ["cn.png", "China", "Amateur radio bands in China", "", "Created by KN8U and NY7H", "🇨🇳"],
|
"cn": ["cn.png", "China", "Amateur radio bands in China", "", "Created by KN8U and NY7H", "🇨🇳"],
|
||||||
|
"it_hf": ["it_hf.png", "Italy (HF)", "HF amateur radio bands in Italy", "", "[Associazione Radioamatori Italiani](https://www.arimi.it/download/bandplan/) [[PDF]](http://www.arimi.it/wp-content/Plan/BP%20HF%202013%2032.pdf)", "🇮🇹"],
|
||||||
|
"it_vhf": ["it_vhf.png", "Italy (VHF/UHF)", "VHF/UHF amateur radio bands in Italy", "", "[Associazione Radioamatori Italiani](https://www.arimi.it/download/bandplan/) [[PDF]](https://www.arimi.it/wp-content/Plan/BP%20V_UHF%202013%2032.pdf)", "🇮🇹"],
|
||||||
|
"it_shf": ["it_shf.png", "Italy (UHF/SHF)", "UHF/SHF amateur radio bands in Italy", "", "[Associazione Radioamatori Italiani](https://www.arimi.it/download/bandplan/) [[PDF]](https://www.arimi.it/wp-content/Plan/BP%20U-SHF.pdf)", "🇮🇹"],
|
||||||
|
"jp": ["jp.png", "Japan", "Amateur radio bands in Japan", "Pending checks against the latest update from the 総務省 (MIC) of Japan, March 2020", "[JARL Amateur-Use Bandplans](https://jarl.org/Japanese/A_Shiryo/A-3_Band_Plan/bandplan20150105.pdf)", "🇯🇵"],
|
||||||
"mx": ["mx.png", "Mexico", "Radio allocations in Mexico", "Full radio allocations chart for all services. No information specific to amateur radio is shown.", "Secretaría de Comunicaciones y Transportes (SCT) / Instituto Federal de Telecomunicaciones (IFT)", "🇲🇽"],
|
"mx": ["mx.png", "Mexico", "Radio allocations in Mexico", "Full radio allocations chart for all services. No information specific to amateur radio is shown.", "Secretaría de Comunicaciones y Transportes (SCT) / Instituto Federal de Telecomunicaciones (IFT)", "🇲🇽"],
|
||||||
"nl": ["nl.png", "Netherlands", "Amateur radio bands in the Netherlands", "", "", "🇳🇱"],
|
"nl": ["nl.png", "Netherlands", "Amateur radio bands in the Netherlands", "*This version of this bandplan is no longer hosted on VERNON's website and it's accuracy cannot be guaranteed.*", "[VERNON Global Band Plan van de Telecom Agency, Ministerie van Economische Zaken en Klimaat](https://www.veron.nl/downloads/brochures/)", "🇳🇱"],
|
||||||
"us": ["us.png", "USA", "Amateur radio bands in the USA", "", "*[ARRL Frequency Chart](https://www.arrl.org/shop/ARRL-Frequency-Chart-11-17/)* [[PDF]](http://www.arrl.org/files/file/Regulatory/Band%20Chart/Band%20Chart%20-%2011X17%20Color.pdf)", "🇺🇸"]
|
"us": ["us.png", "USA", "Amateur radio bands in the USA", "", "*[ARRL Frequency Chart](https://www.arrl.org/shop/ARRL-Frequency-Chart-11-17/)* [[PDF]](http://www.arrl.org/files/file/Regulatory/Band%20Chart/Band%20Chart%20-%2011X17%20Color.pdf)", "🇺🇸"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"arrl": ["arrl-rac.png", "ARRL Sections", "ARRL Sections", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇺🇸"],
|
"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)", "🇨🇦"],
|
||||||
"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)", "🇺🇳"],
|
"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)", "🌐"]
|
"ituz": ["itu-zones.png", "ITU Zones", "ITU Zones", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇺🇳"],
|
||||||
|
"arrl": ["arrl-rac.png", "ARRL Sections", "ARRL Sections", "", "[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)", "🌐"],
|
||||||
|
"rac": ["arrl-rac.png", "RAC Sections", "RAC Sections", "", "[EI8IC](https://www.mapability.com/ei8ic/maps/maps.php)", "🇨🇦"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user