-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
executable file
·133 lines (116 loc) · 4.27 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python
'''README
This program logs in as a discord bot and responds to defined weather data requests ('slash commands', or most often just 'commands').
Usage:
./main.py run
References:
https://typer.tiangolo.com/
https://discordpy.readthedocs.io/en/stable/api.html
'''
# stdlib
from sys import exit
# custom modules
from toolchain.commands import current_logic, forecast_logic, air_quality_logic
# 3rd party
try:
import typer
from yaml import safe_load, YAMLError
from discord import Client, Intents, File, app_commands, Object, Interaction
import discord.ext
except ModuleNotFoundError as e:
print("Error. Missing one or more 3rd-party packages (pip install).")
exit(1)
#───Globals──────────────────
app = typer.Typer()
with open('config.yml', 'r') as raw_config:
try:
config = safe_load(raw_config)
except YAMLError as e:
print("Error. YAML input invalid.\n{e}")
exit(1)
app_id = config['app_id']
public_key = config['public_key']
perms_int = config['perms_int']
token = config['token']
client_id = config['client_id']
client_secret = config['client_secret']
guild_id = config['guild_id']
channel_scope = config['channel_scope']
api_key = config['open_weather_key']
latitude = config['latitude']
longitude = config['longitude']
#───Commands─────────────────
@app.command()
def run() -> None:
'''Weather Bot
Runs Discord bot that fetches climate data from the OpenWeather API upon slash-command chat dictation.
'''
## Init
guild = discord.Object(id=guild_id)
class MyClient(discord.Client):
def __init__(self, *, intents: discord.Intents):
super().__init__(intents=intents)
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
self.tree.copy_global_to(guild=guild)
await self.tree.sync(guild=guild)
intents = Intents(messages=True, guilds=True, members=True)
client = MyClient(intents=intents)
@client.event
async def on_ready():
'''Print successful login'''
print(f'Logged in as {client.user} (ID: {client.user.id})')
print('──────')
## Commands
#───
@client.tree.command()
async def help(interaction:Interaction):
'''Explain WeatherBot usage'''
if interaction.channel.name in channel_scope:
message = f'''/forecast :: *5 day forecast*
/current :: *current climate conditions*
/airquality :: *current air quality metrics*'''
await interaction.response.send_message(message)
else:
message = f'Sorry, i only respond in {", ".join(channel_scope)}'
await interaction.response.send_message(message, ephemeral=True)
#───
@client.tree.command()
async def current(interaction: discord.Interaction):
'''Current weather conditions.'''
if interaction.channel.name in channel_scope:
message = current_logic(api_key, longitude, latitude)
await interaction.response.send_message(message)
else:
message = f'Sorry, i only respond in {", ".join(channel_scope)}'
await interaction.response.send_message(message, ephemeral=True)
#───
@client.tree.command()
async def forecast(interaction: discord.Interaction):
'''Seven day forecast.'''
if interaction.channel.name in channel_scope:
message = forecast_logic(api_key, longitude, latitude)
await interaction.response.send_message(message)
else:
message = f'Sorry, i only respond in {", ".join(channel_scope)}'
await interaction.response.send_message(message, ephemeral=True)
#───
@client.tree.command()
async def airquality(interaction: discord.Interaction):
'''Current air quality metrics'''
if interaction.channel.name in channel_scope:
message = air_quality_logic(api_key, longitude, latitude)
await interaction.response.send_message(message)
else:
message = f'Sorry, i only respond in {", ".join(channel_scope)}'
await interaction.response.send_message(message, ephemeral=True)
#───
## Login
try:
client.run(token)
except Exception as e:
print(f'Error on attempted login:\n{e}')
return None
#───Entry────────────────────
if __name__ == "__main__":
app()