-
Notifications
You must be signed in to change notification settings - Fork 0
/
cheerlights_bot.py
345 lines (257 loc) · 11.6 KB
/
cheerlights_bot.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#!/usr/bin/env python
#################################################################################
# CheerLights Discord Server Bot
# Developed by: Jeff Lehman, N8ACL
# Date: 04/18/2023
# Current Version: 6.0
# https://github.com/cheerlights/cheerlights-discord-bot
# Questions? Comments? Suggestions? Contact me one of the following ways:
# E-mail: [email protected]
# Discord: Ravendos#7364
# Mastodon: @[email protected]
# Website: https://www.qsl.net/n8acl
#############################
# Import Libraries
# import config as cfg
import os
import json
import requests
import discord # Discord library
from datetime import datetime, date, time, timedelta
import time
import sqlalchemy
from sqlalchemy import text as sqltext, select, MetaData, Table, update, insert
if os.path.exists('src'):
# Import our Custom Libraries
import src.db_functions as dbf
import src.db_conn as dbc
else:
#set the parent directory one level up and then import the src files
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.abspath(os.path.join(current_dir, ".."))
sys.path.insert(0, parent_dir)
import src.db_functions as dbf
import src.db_conn as dbc
#############################
# import config json file
config_file = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '.', 'config.json'))
with open(config_file, "r") as read_file:
config = json.load(read_file)
read_file.close()
#############################
# Create Discord Bot
TOKEN = config['discord']['bot_token']
activity = discord.Activity(type=discord.ActivityType.listening, name='/cheerlights')
bot = discord.Bot(debug_guilds=[config['discord']['server_id']], activity=activity, status=discord.Status.online)
#############################
# set database connection
try:
db_engine = dbc.db_connection()
print("Database Connection established")
except Exception as e:
print("Database Connection could not be established.", e)
metadata = sqlalchemy.MetaData()
metadata.reflect(bind=db_engine)
cheerlights_log = metadata.tables['cheerlights_logs']
#############################
# Define Variables
# DO NOT CHANGE BELOW
cheerlights_api_url = 'http://api.thingspeak.com/channels/1417/field/2/last.json'
linefeed = "\r\n"
rate_limiter = {}
button_timeout = config['button_timeout']
color_pick = {
"red" : "#FF0000",
"green" : "#008000",
"blue" : "#0000FF",
"cyan" :"#00FFFF",
"white" : "#FFFFFF",
"oldlace" : "#FDF5E6",
"purple" : "#800080",
"magenta" : "#FF00FF",
"yellow" : "#FFFF00",
"orange" : "#FFA500",
"pink" : "#FFC0CB"
}
#############################
# Define Functions
def use_api():
# Pulls latest Color from Cheerlights API
r = requests.get(cheerlights_api_url, timeout=None)
json = r.json()
return json['field2']
def hex_to_rgb(col_hex):
#Convert a hex colour to an RGB tuple.
col_hex = col_hex.lstrip('#')
return bytearray.fromhex(col_hex)
def get_key(val, my_dict):
# Return the Key from a value in a dictionary
for key, value in my_dict.items():
if val == value:
return key
def valid_colors():
# Returns list of valid colors
valid_colors = ''
for item in list(color_pick.keys()):
valid_colors = valid_colors + item + linefeed
return valid_colors
def send_to_webhook(msg,wh_url):
response = requests.post(
wh_url, data=json.dumps(msg),
headers={'Content-Type': 'application/json'},
auth = (config['wh_user'],config['wh_password'])
)
# def logging(log_message):
# today = date.today()
# bot_log_file = os.path.abspath(os.path.join(os.path.dirname( __file__ ), './log/', 'cheerlights_bot_log-' + today.strftime("%m%d%Y") + ".txt"))
# # bot_log_file = os.path.dirname(os.path.abspath(__file__)) + "/log/cheerlights_bot_log-" + today.strftime("%m%d%Y") + ".txt"
# with open(bot_log_file,"a") as f:
# f.write(log_message)
# f.close()
def logging(log_message, author, user_id, color):
sql = cheerlights_log.insert()
values_list = [{
'application': 'discord',
'username' : author,
'userid': user_id,
'message': log_message,
'color': color}]
dbf.insert_sql(db_engine,sql,values_list)
def get_block_list():
block_list = []
with open("block_list.json", "r") as read_file:
blocked_users = json.load(read_file)
for i in range(0,len(blocked_users["block_list"])):
for key, value in blocked_users["block_list"][i].items():
if key == "userid":
block_list.append(value)
return block_list
def set_color(color, author, user_id):
now = int(time.time())
block_list = get_block_list()
if user_id not in block_list:
if user_id not in rate_limiter:
rate_limiter[user_id] = 9999999
if rate_limiter[user_id] == 9999999 or (now - rate_limiter[user_id] >= config['msg_wait_time']):
rate_limiter[user_id] = now
color_code = color_pick[color.lower()]
embed = discord.Embed(title = "Setting CheerLights to Color",
description=color.lower(),
color=int(color_code.lstrip('#'), 16)
)
now = datetime.now()
timestamp = now.strftime("%m/%d/%Y %H:%M:%S")
status = "Set @CheerLights to " + color + " on " + timestamp
cl_msg = {'source': 'discord', 'colours': [color], 'username': author}
send_to_webhook(cl_msg, config['cl_wh'])
if config['logging_enabled']:
# logging(timestamp + " - " + author + "(" + user_id + ") | command: set_color | status: " + status + linefeed)
log_message = "command: set_color | status: " + status
logging(log_message, author, user_id,color.lower())
else:
response = "Slow down there sport! You are trying to send colors way too fast. Please wait "+ str(config['msg_wait_time']) + " seconds before trying again."
embed = discord.Embed(title = "Too Fast!",
description=response
)
else:
now = datetime.now()
timestamp = now.strftime("%m/%d/%Y %H:%M:%S")
if config['logging_enabled']:
# logging(timestamp + " - " + author + "(" + author + ") | User Blocked" + linefeed)
log_message = "User Blocked"
logging(log_message, author, user_id,'')
response = "Sorry, but this user has been blocked from sending colors due to spamming. If this is in error, please contact an Admin."
embed = discord.Embed(title = "User Blocked",
description=response
)
return embed
#############################
# Define CheerLights Menu Functions
class ColorSelect(discord.ui.View):
def __init__(self):
super().__init__(timeout=button_timeout, disable_on_timeout=True)
@discord.ui.button(label="Red", row=0, style=discord.ButtonStyle.primary)
async def set_color_red(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("red", user, userid),ephemeral = True)
@discord.ui.button(label="Green", row=0, style=discord.ButtonStyle.primary)
async def set_color_green(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("green", user, userid),ephemeral = True)
@discord.ui.button(label="Blue", row=0, style=discord.ButtonStyle.primary)
async def set_color_blue(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("blue", user, userid),ephemeral = True)
@discord.ui.button(label="Cyan", row=0, style=discord.ButtonStyle.primary)
async def set_color_cyan(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("cyan", user, userid),ephemeral = True)
@discord.ui.button(label="White", row=1, style=discord.ButtonStyle.primary)
async def set_color_white(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("white", user, userid),ephemeral = True)
@discord.ui.button(label="Oldlace", row=1, style=discord.ButtonStyle.primary)
async def set_color_oldlace(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("oldlace", user, userid),ephemeral = True)
@discord.ui.button(label="Purple", row=1, style=discord.ButtonStyle.primary)
async def set_color_purple(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("purple", user, userid),ephemeral = True)
@discord.ui.button(label="Magenta", row=1, style=discord.ButtonStyle.primary)
async def set_color_magenta(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("magenta", user, userid),ephemeral = True)
@discord.ui.button(label="Yellow", row=2, style=discord.ButtonStyle.primary)
async def set_color_yellow(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("yellow", user, userid),ephemeral = True)
@discord.ui.button(label="Orange", row=2, style=discord.ButtonStyle.primary)
async def set_color_orange(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("orange", user, userid),ephemeral = True)
@discord.ui.button(label="Pink", row=2, style=discord.ButtonStyle.primary)
async def set_color_pink(self, button, interaction):
user = str(interaction.user)
userid = str(interaction.user.id)
await interaction.response.send_message(embed=set_color("pink", user, userid),ephemeral = True)
class MainMenu(discord.ui.View):
def __init__(self):
super().__init__(timeout=button_timeout, disable_on_timeout=True)
@discord.ui.button(label="Get Color", style=discord.ButtonStyle.primary)
async def get_color(self, button, interaction):
color_code = use_api()
embed = discord.Embed(title = "Current CheerLights Color",
description=get_key(color_code.upper(),color_pick),
color=int(color_code.lstrip('#'), 16)
)
if config['logging_enabled']:
# logging(timestamp + " - " + author + "(" + author + ") | User Blocked" + linefeed)
log_message = "Get Color"
logging(log_message, author, user_id,'')
await interaction.response.send_message(embed=embed,ephemeral = True)
@discord.ui.button(label="Set Color", style=discord.ButtonStyle.primary)
async def set_color(self, button, interaction):
await interaction.response.send_message("Set Color", view = ColorSelect(), ephemeral = True)
#############################
# Define Discord Bot Functions
@bot.event
async def on_ready():
print(f'{bot.user.name} has connected to Discord!')
@bot.slash_command()
async def cheerlights(ctx):
await ctx.respond("CheerLight Commands", view=MainMenu(), ephemeral = True)
#############################
# Main Program
# Start Bot
bot.run(TOKEN)