Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b222b2342e | ||
|
|
a0d5c63aee | ||
|
|
0976c2c9e3 | ||
|
|
82647b2597 | ||
|
|
e20ac2c849 | ||
|
|
37a689e58e | ||
|
|
79043feb91 | ||
|
|
c2f905229f | ||
|
|
114e6aeb9b | ||
|
|
83f7270d6b | ||
|
|
63602bc19c | ||
|
|
65a608395b | ||
|
|
f11c076258 | ||
|
|
7b7f57f4c0 | ||
|
|
e2c100c5bb | ||
|
|
57e5c37f1a | ||
|
|
d53cc3b3f6 | ||
|
|
fc7ef5eb69 | ||
|
|
ccba129bb2 | ||
|
|
d9f52bdafd | ||
|
|
f0615c51e8 | ||
|
|
6deb4455ed | ||
|
|
86d7e414c2 | ||
|
|
19304b5d27 | ||
|
|
f87a07f6bd | ||
|
|
6b3490557c | ||
|
|
006468bd35 | ||
|
|
2cf516dd1f | ||
|
|
0467fde122 | ||
|
|
d9362fb819 | ||
|
|
b165e67676 | ||
|
|
1dc54fa5f2 | ||
|
|
91063db833 | ||
|
|
c9f2d07f4b | ||
|
|
290bdc3903 | ||
|
|
93734ec773 | ||
|
|
37a6b08fe2 | ||
|
|
f1e35bae27 | ||
|
|
5c2b426748 | ||
|
|
ed6606f8ac | ||
|
|
be4b46a81d | ||
|
|
f0c65454d3 | ||
|
|
646081286f | ||
|
|
e36d8727c5 | ||
|
|
e8cf0f2c24 | ||
|
|
cd4b3bbb38 | ||
|
|
2a5ced954b | ||
|
|
ea2a76bf81 | ||
|
|
1be2590f43 | ||
|
|
f37fc95ddc | ||
|
|
2515eb83a5 | ||
|
|
47e5c364a9 | ||
|
|
a03efbd2a9 | ||
|
|
d49d368895 | ||
|
|
ba792ff1f5 | ||
|
|
faad238f8c | ||
|
|
cc1368258c | ||
|
|
7c1b3c207d | ||
|
|
8f9af7d10c | ||
|
|
4ec07fdf77 | ||
|
|
7e9be22734 | ||
|
|
d85149e5f1 | ||
|
|
0e393b089f | ||
|
|
c16fb46b78 | ||
|
|
f051fe0087 | ||
|
|
bf2ac43a88 | ||
|
|
87f82af697 | ||
|
|
9036557154 | ||
|
|
c9c67f32c9 | ||
|
|
cc90375376 | ||
|
|
6df3f8a55f | ||
|
|
0bf0134a86 | ||
|
|
576f21b6fc | ||
|
|
824c952ad9 | ||
|
|
eeae88595d | ||
|
|
a709f25ea3 | ||
|
|
4c43ab0e8e | ||
|
|
d97a2d1fe3 | ||
|
|
10baa139a1 | ||
|
|
be04db6237 | ||
|
|
ce319f8696 | ||
|
|
b26139fdac | ||
|
|
98cf67381b | ||
|
|
132267f5d4 | ||
|
|
1a204d303b | ||
|
|
f82227ea0d | ||
|
|
238bb9f5ea | ||
|
|
f026c88817 | ||
|
|
fa2fb34e41 | ||
|
|
85cf5f5ce5 | ||
|
|
1e62920925 | ||
|
|
d58c7245e7 | ||
|
|
861397b455 | ||
|
|
a265de4a62 | ||
|
|
d9883b6f97 | ||
|
|
64d80c79ac | ||
|
|
91def4cd4d | ||
|
|
6a46983293 | ||
|
|
0544d870e7 | ||
|
|
e1327961b6 | ||
|
|
153bc39e63 | ||
|
|
f94f69aa59 | ||
|
|
9dfae705e5 | ||
|
|
32144c5657 | ||
|
|
5235df2259 | ||
|
|
eca6fae897 | ||
|
|
1e58d5017d | ||
|
|
75121c5a79 | ||
|
|
71231d3a9b | ||
|
|
3b6c82d6f5 | ||
|
|
1fc96f6b3a | ||
|
|
c7216563e6 | ||
|
|
4a27acb4ac | ||
|
|
e0d77bf82d | ||
|
|
84e6f8ed6d | ||
|
|
67309f5925 | ||
|
|
8480215db9 | ||
|
|
7bab9a1238 | ||
|
|
e08621d317 | ||
|
|
204acac19c | ||
|
|
077e82bda2 | ||
|
|
9af4a52927 | ||
|
|
2970adc634 | ||
|
|
a95b88d99f | ||
|
|
3832d13200 | ||
|
|
ca06fea13f | ||
|
|
5575dbb054 | ||
|
|
8d02152697 | ||
|
|
ae601c45f5 | ||
|
|
7391e68778 | ||
|
|
0f607f67ee | ||
|
|
142a7fcf48 | ||
|
|
2ef6cf6053 | ||
|
|
dd0dbb0f27 | ||
|
|
f85a637566 | ||
|
|
bb711b8167 | ||
|
|
9f4ee76bb7 | ||
|
|
4464d589d9 | ||
|
|
de815af682 | ||
|
|
46dc4190a0 | ||
|
|
c8414ba000 | ||
|
|
9eaf1d8029 | ||
|
|
b26af574ae | ||
|
|
51692a17db | ||
|
|
b90b5fc8f4 | ||
|
|
6e0642a11b | ||
|
|
fba8cc680c | ||
|
|
1547784a40 | ||
|
|
3b65435899 | ||
|
|
bd98d1bdcb | ||
|
|
d946067bd4 | ||
|
|
d15267ea53 | ||
|
|
05b7520a3f | ||
|
|
f8e04ea086 | ||
|
|
e594d27beb | ||
|
|
427937e8d5 | ||
|
|
ff189b7357 | ||
|
|
92542b4405 | ||
|
|
351fb9c090 | ||
|
|
af6862dfe5 | ||
|
|
4e562c5c66 | ||
|
|
25d0aad3cb | ||
|
|
82743a0d66 | ||
|
|
ce51483344 | ||
|
|
40806125a5 | ||
|
|
bb33e9f82b | ||
|
|
7fdbcdf951 | ||
|
|
369b3bf867 | ||
|
|
b62f864167 | ||
|
|
5b748dc207 | ||
|
|
cbf96086d3 | ||
|
|
29b7cd93da | ||
|
|
7987fe186a | ||
|
|
3fd8c5de0e | ||
|
|
82fda0be94 | ||
|
|
3f9cbf8964 | ||
|
|
d86f634827 | ||
|
|
82b08ce80b | ||
|
|
7015ac4f7e | ||
|
|
bf8a306870 | ||
|
|
2a3fc39da6 | ||
|
|
079770da7b | ||
|
|
cabf2d3ba8 | ||
|
|
9f8864683d | ||
|
|
56685916f0 | ||
|
|
991e0f2429 | ||
|
|
89235209e1 | ||
|
|
66ff3375ff | ||
|
|
993adfc196 | ||
|
|
fdbe058c2a | ||
|
|
4471e5930d | ||
|
|
1c7c739942 | ||
|
|
0a7eec666d | ||
|
|
41c640ca10 | ||
|
|
2e961db66f | ||
|
|
c0d817fb69 | ||
|
|
6d1b82d3c3 | ||
|
|
8805587576 |
No files matched your search
@@ -2,11 +2,19 @@
|
||||
|
||||
[](http://gitlab.rickelobe.com/Bots/r0b3BOT/commits/master)
|
||||
|
||||
# Screenshot
|
||||

|
||||
|
||||
# Description
|
||||
This is R0b3's Discord Bot. It's creation was basically a challenge posed a coworker who said "Hey, you can write Discord Bots in Python... Make one to display your 3D printer status!".
|
||||
This is R0b3's Discord Bot. It's creation was basically a challenge posed a coworker who said "Hey, you can write Discord Bots in Python... Make one to display your 3D printer status!". But as time went on, a few more features were added. Aside from being able to query and monitor your 3D printer, it can also fetch the current status of a service monitroed by your [StatPing](https://github.com/statping/statping) instance. In addition to just fetching the current status of a service, you can subscribe to receive alerts for any StatPing service state change. All subscriptions are persistent and will remain even after the bot is restarted.
|
||||
|
||||
# Features
|
||||
* Query & Monitor 3D Printer Status using `$printstat` command(Requires that your printer is connected to [Octoprint](https://octoprint.org/))<br>
|
||||

|
||||
* Query serivces states on StatPing using the `$spstatus`
|
||||
* Use `$spsub` to "Subscribe" to service change alerts for StatPing services. Subscribed alerts are persistent and are not lost on bot restart.<br>
|
||||

|
||||
* Play a selection of sound clips to voice channel members using the various commands (`$torololo`, `$oops`, `$promoted`, etc)
|
||||
|
||||
# Commands
|
||||

|
||||
|
||||
# Requirements
|
||||
1. discord.py version 1.2.4 or greater<br>
|
||||
@@ -14,6 +22,6 @@ This is R0b3's Discord Bot. It's creation was basically a challenge posed a cow
|
||||
|
||||
# Configuration
|
||||
1. Create a Discord Bot via Developer tools<br>
|
||||
2. Enter various configuration parameters in bot_config.conf.example<br>
|
||||
2. Enter configuration parameters in bot_config.conf.example<br>
|
||||
3. Enter OctoPrint config parameters in octoapi.conf.example<br>
|
||||
4. Rename *.example files as *.conf<br>
|
||||
@@ -3,14 +3,19 @@
|
||||
# Replace the placeholders with your information. Do not use quotes.
|
||||
#
|
||||
# discord_auth_token - this is the bot token generated via the Discord development console.
|
||||
# bot_command_prefix - The prefix used identify commands for this bot
|
||||
# hass_url - URL to your home assistant instance. This is used to turn on the light by your 3d printer
|
||||
# hass_token - Long Lived Access Token used to authenticate with the REST API for your Home assistant instance
|
||||
# hass_light - Entity name of the light you want to control
|
||||
# octoprint_ip_address - IP Address of you OctoPrint (or OctoPi) host. Used to get 3D printer stats.
|
||||
# statping_url - Server hostname of the StatPing instance we will be querying w/ the REST API
|
||||
# statping_api_key - API Key for Statping to query for service status
|
||||
#
|
||||
discord_auth_token = <Discord Auth Token>
|
||||
bot_command_prefix = <!/$/#/etc>
|
||||
hass_url = <URL to HomeAssistant>
|
||||
hass_token = <HomeAssistant Long Lived Access Token>
|
||||
hass_light = <Entity_ID of the light @ your printer>
|
||||
octoprint_ip_address = <OctoPrint IP Address>
|
||||
|
||||
statping_url = <Statping URL>
|
||||
statping_api_key = <Statping API Key>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 316 KiB |
+435
-39
@@ -16,24 +16,30 @@ from discord.utils import get
|
||||
from discord.voice_client import VoiceClient
|
||||
import requests
|
||||
import asyncio
|
||||
#from aiofile import AIOFile
|
||||
import aiofiles as aiof
|
||||
import pickle
|
||||
|
||||
bot = commands.Bot(command_prefix='$', description='A derpy derp of a bot.')
|
||||
|
||||
#Record the time the bot started
|
||||
start_time = time.time()
|
||||
start_time = time.time()
|
||||
|
||||
config = configparser.RawConfigParser()
|
||||
configFilePath = r'bot_config.conf'
|
||||
|
||||
# Last error message variable used by $last_error command to display in discord
|
||||
global last_error
|
||||
last_error = "No errors been recorded."
|
||||
last_error = "No errors have been recorded."
|
||||
|
||||
try:
|
||||
config.read(configFilePath)
|
||||
except:
|
||||
print("Error loading config! Please check config file 'bot-config.conf'")
|
||||
|
||||
#
|
||||
# Read in bot configurations
|
||||
#
|
||||
|
||||
# Setup HomeAssistant URL and Headers
|
||||
HASS_TOKEN = config.get('bot-config', 'hass_token')
|
||||
HASS_URL = config.get('bot-config', 'hass_url')
|
||||
@@ -45,14 +51,27 @@ hassHEADERS = {
|
||||
}
|
||||
|
||||
OCTOPRINT_IP_ADDRESS = config.get('bot-config', 'octoprint_ip_address')
|
||||
|
||||
DISCORD_AUTH_TOKEN = config.get('bot-config', 'discord_auth_token')
|
||||
BOT_COMMAND_PREFIX = config.get('bot-config', 'bot_command_prefix')
|
||||
STATPING_URL = config.get('bot-config', 'statping_url')
|
||||
STATPING_API_KEY = config.get('bot-config', 'statping_api_key')
|
||||
statpingURL = STATPING_URL + "/api/services"
|
||||
statpingHEADERS = {
|
||||
'Authorization': f"Bearer {STATPING_API_KEY}",
|
||||
'content-type': 'application/json',
|
||||
}
|
||||
|
||||
# Configure bot
|
||||
bot = commands.Bot(command_prefix=BOT_COMMAND_PREFIX, description='A derpy derp of a bot.')
|
||||
|
||||
# Printing configuration details to console
|
||||
print(f"HomeAssistant URL: {hassURL}")
|
||||
print(f"HomeAssistant URL HEADERS: {hassHEADERS}")
|
||||
print(f"HomeAssistant Light: {HASS_LIGHT}")
|
||||
print(f"OctoPrint IP Address: {OCTOPRINT_IP_ADDRESS}")
|
||||
print(f"StatPing Server: {STATPING_URL}")
|
||||
print(f"StatPing API Key: {STATPING_API_KEY}")
|
||||
print(f"StatPing URL Headers: {statpingHEADERS}")
|
||||
|
||||
# On Ready
|
||||
@bot.event
|
||||
@@ -61,10 +80,21 @@ async def on_ready():
|
||||
print(bot.user.name)
|
||||
print(bot.user.id)
|
||||
print('------')
|
||||
print("Setting activity to 'Listenting to your commands")
|
||||
activity = discord.Activity(name="your commands",type=discord.ActivityType.listening)
|
||||
print("Setting activity to 'Listenting to your commands'")
|
||||
activity = discord.Activity(name="your $commands",type=discord.ActivityType.listening)
|
||||
await bot.change_presence(activity=activity)
|
||||
|
||||
|
||||
# If 15 seconds or less have passed since the program was started, start the monitor.
|
||||
runtime = time.time() - start_time
|
||||
if runtime <= 15:
|
||||
#Run StatPing_Monitor
|
||||
print("Starting StatPing Monitor.")
|
||||
await StatPing_Monitor()
|
||||
else:
|
||||
print(f">> Bot has been running for more than {int(runtime)} seconds. Not restarting monitor.")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def greetings(ctx):
|
||||
await ctx.send(":smiley: :wave: Hello there!")
|
||||
@@ -72,6 +102,7 @@ async def greetings(ctx):
|
||||
|
||||
@bot.event
|
||||
async def on_command_error(ctx, error):
|
||||
global last_error
|
||||
if isinstance(error, commands.CommandOnCooldown):
|
||||
seconds = round(error.retry_after,1)
|
||||
print(f" - Error, user tried to use command while in cooldown (wait is: {seconds}")
|
||||
@@ -93,21 +124,6 @@ async def on_command_error(ctx, error):
|
||||
async def last_error(ctx):
|
||||
await ctx.send(f"Last error recorded: {last_error}")
|
||||
|
||||
@bot.command()
|
||||
async def uptime(ctx):
|
||||
# Displays how long the bot has been online
|
||||
second = time.time() - start_time
|
||||
minute, second = divmod(second, 60)
|
||||
hour, minute = divmod(minute, 60)
|
||||
day, hour = divmod(hour, 24)
|
||||
week, day = divmod(day, 7)
|
||||
week = int(week)
|
||||
day = int(day)
|
||||
hour = int(hour)
|
||||
minute = int(minute)
|
||||
second = int(second)
|
||||
await ctx.send(f"Uptime [WW:DD:HH:MM:SS]: {week:02d}:{day:02d}:{hour:02d}:{minute:02d}:{second:02d}")
|
||||
|
||||
#
|
||||
# Giphy Commands
|
||||
#
|
||||
@@ -200,6 +216,16 @@ async def aww(ctx, member : discord.Member="NONE"):
|
||||
async def eia(ctx, member : discord.Member="NONE"):
|
||||
await play_sound(ctx, member, "./sounds/awesome.mp3", "$eia", 11)
|
||||
|
||||
@bot.command()
|
||||
@commands.cooldown(rate=1, per=10.0, type=commands.BucketType.user)
|
||||
async def yaw(ctx, member : discord.Member="NONE"):
|
||||
await play_sound(ctx, member, "./sounds/yaw.mp3", "$yaw", 6)
|
||||
|
||||
@bot.command()
|
||||
@commands.cooldown(rate=1, per=10.0, type=commands.BucketType.user)
|
||||
async def heavy(ctx, member : discord.Member="NONE"):
|
||||
await play_sound(ctx, member, "./sounds/heavy.mp3", "$heavy", 6)
|
||||
|
||||
@bot.command()
|
||||
@commands.cooldown(rate=1, per=10.0, type=commands.BucketType.user)
|
||||
async def rs(ctx, member : discord.Member="NONE"):
|
||||
@@ -511,34 +537,404 @@ async def info(ctx):
|
||||
# give users a link to invite thsi bot to their server
|
||||
embed.add_field(name="Invite", value="[Invite link](https://discordapp.com/api/oauth2/authorize?client_id=416312716677087233&permissions=51264&scope=bot)")
|
||||
|
||||
# Bot Uptime
|
||||
second = time.time() - start_time
|
||||
minute, second = divmod(second, 60)
|
||||
hour, minute = divmod(minute, 60)
|
||||
day, hour = divmod(hour, 24)
|
||||
week, day = divmod(day, 7)
|
||||
week = int(week)
|
||||
day = int(day)
|
||||
hour = int(hour)
|
||||
minute = int(minute)
|
||||
second = int(second)
|
||||
embed.add_field(name="Uptime [WW:DD:HH:MM:SS]:", value=f"{week:02d}:{day:02d}:{hour:02d}:{minute:02d}:{second:02d}", inline=False)
|
||||
|
||||
print("Getting git describe data to display as version in info embed")
|
||||
bot_version = await run('git describe')
|
||||
embed.add_field(name="Version:", value=f"{bot_version}", inline=False)
|
||||
|
||||
# Gitlab link to source
|
||||
embed.add_field(name="Source Code:", value="[R0b3Bot on Gitlab](https://gitlab.rickelobe.com/Bots/r0b3BOT)", inline=False)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
bot.remove_command('help')
|
||||
|
||||
@bot.command()
|
||||
async def spstatus(ctx, service = "NONE"):
|
||||
#async def spalert(ctx, cmd = "NONE", arg = "NONE"):
|
||||
|
||||
# if cmd != "NONE":
|
||||
# if cmd == "add":
|
||||
# spalert +=
|
||||
if service != "NONE":
|
||||
|
||||
#await get_stp_status(ctx, service.lower())
|
||||
result = await get_stp_status(service.lower())
|
||||
|
||||
if result == "service not found":
|
||||
await ctx.send(f"'{service}' was not found")
|
||||
elif result['online']:
|
||||
await ctx.send(f"{result['name']} is Online")
|
||||
elif not result['online']:
|
||||
await ctx.send(f"{result['name']} is Offline")
|
||||
else:
|
||||
await ctx.send(f"Received an unexpected result '{result}' querying '{service}'")
|
||||
|
||||
else:
|
||||
await ctx.send("Please speficy a service name to query.")
|
||||
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def spsub(ctx, service = "NONE"):
|
||||
|
||||
spsublist = {} # Statping Subscription list to be read in from file
|
||||
# Structure of spsublist nested dictionary
|
||||
# spsublist[service name][list of channel ids][a state value]
|
||||
# dict = {'Plex': {'state' : 'online', 'channels' : ['1232', '43234']}
|
||||
# 'Space Eingineers' : {'state' : online', 'channels' : ['2343', '54563']}}
|
||||
#
|
||||
currentsub_request = [] # list of elements detailing the current sub request
|
||||
datestring = datetime.now()
|
||||
datestring = datestring.strftime("%m/%d/%Y-%H:%M:%S")
|
||||
|
||||
# replace _ with sapces
|
||||
service = service.replace("_"," ")
|
||||
|
||||
print(f"[{datestring}]: {ctx.message.author.display_name} called '$spsub '{service}'''")
|
||||
|
||||
# Only work on this if the user has supplied a service name to monitor, a value of NONE
|
||||
# means nothing was specified
|
||||
if service != "NONE" and service != "-list" and not service.startswith('-del '):
|
||||
|
||||
print(f">> Querying status of '{service}' to see if it exists")
|
||||
service_state = await get_stp_status(service)
|
||||
|
||||
if service != "NONE":
|
||||
|
||||
if service == "-list":
|
||||
# List the serivces that this channel is subscribed to
|
||||
# Read in spsublist
|
||||
sublist = ''
|
||||
async with aiof.open('spsublist.dat', 'rb') as datafile:
|
||||
pickled_spsublist = await datafile.read()
|
||||
spsublist = pickle.loads(pickled_spsublist)
|
||||
|
||||
for service in spsublist.keys():
|
||||
|
||||
for channel in spsublist[service]['channels']:
|
||||
if channel == ctx.channel.id:
|
||||
sublist += f"'{service}' "
|
||||
|
||||
await ctx.send(f"This channel is subscribed to: {sublist}")
|
||||
|
||||
elif service.startswith('-del:'):
|
||||
# Delete the service from this channels subscriptions
|
||||
service_toremove = service[5:]
|
||||
print(f"{service_toremove}")
|
||||
|
||||
# Open the data file for read in
|
||||
async with aiof.open('spsublist.dat', 'rb') as datafile:
|
||||
pickled_spsublist = await datafile.read()
|
||||
spsublist = pickle.loads(pickled_spsublist)
|
||||
|
||||
# We haven't found either the channel or servic; mark as false
|
||||
found_service = False
|
||||
found_channel = False
|
||||
|
||||
# Iterate through the service names in the data
|
||||
for service in spsublist.keys():
|
||||
|
||||
# If the service we want to unsub from is the same as the service in the data, we need to search for the channel
|
||||
if service.lower() == service_toremove.lower():
|
||||
|
||||
# We've found the service match, mark as true
|
||||
found_service = True
|
||||
|
||||
# Iterate through the channels that are subbed to this service
|
||||
for channel in spsublist[service]['channels']:
|
||||
|
||||
# If a channel listed in the service matches the current users channel id, we've found our match
|
||||
if channel == ctx.channel.id:
|
||||
|
||||
# Marking channel as found
|
||||
found_channel = True
|
||||
# Get the proper name of the service
|
||||
service_toremove = service
|
||||
#Remove the current users channel from this service
|
||||
spsublist[service]['channels'].remove(ctx.channel.id)
|
||||
# Break since we're done.
|
||||
break
|
||||
|
||||
# If we got to the point of finding the channel, we're done.
|
||||
if found_channel:
|
||||
break
|
||||
|
||||
if found_service and found_channel:
|
||||
print(">> Saving dictionary to spsublist.dat")
|
||||
async with aiof.open('spsublist.dat', 'wb') as datafile:
|
||||
pickled_spsublist = pickle.dumps(spsublist, protocol=4)
|
||||
await datafile.write(pickled_spsublist)
|
||||
#await datafile.fsync()
|
||||
await datafile.flush()
|
||||
await ctx.send(f"This channel is unsubscribed from '{service}' alerts.")
|
||||
else:
|
||||
await ctx.send(f"This channel is not subscribed to alerts for '{service_toremove}''")
|
||||
|
||||
# If the service exists, proceed with adding it to the list.
|
||||
elif service_state != "service not found":
|
||||
|
||||
print(f">> '{service}' is a valid service on StatPing.")
|
||||
print(f">> Checking if it has already been subscribed to")
|
||||
#await ctx.send(f"'{service_state['name']}' added to monitored services")
|
||||
currentsub_request.append(ctx.channel.id)
|
||||
currentsub_request.append(service_state['name'])
|
||||
currentsub_request.append("online")
|
||||
print(f">> Channel ID: {currentsub_request[0]}")
|
||||
print(f">> Service Name: {currentsub_request[1]}")
|
||||
print(f">> Initial State to set: {currentsub_request[2]}")
|
||||
|
||||
# read in data file containing dict of subscriptions
|
||||
print(">> Checking for spsublist.dat")
|
||||
if os.path.exists('spsublist.dat'):
|
||||
|
||||
print(">> Data file exists, reading it in.")
|
||||
# Read in spsublist
|
||||
async with aiof.open('spsublist.dat', 'rb') as datafile:
|
||||
pickled_spsublist = await datafile.read()
|
||||
spsublist = pickle.loads(pickled_spsublist)
|
||||
|
||||
print(f">> Checking if serivce is already in datafile")
|
||||
found_service = False
|
||||
found_channel = False
|
||||
for service in spsublist.keys():
|
||||
print(f">> Does {service.lower()} == {currentsub_request[1].lower()}")
|
||||
|
||||
if service.lower() == currentsub_request[1].lower():
|
||||
found_service = True
|
||||
# This service matched what the user is trying to subscribe to
|
||||
# Now we need to check if this is for the same channel
|
||||
print(f">> Found {service} in data file, checking for channel")
|
||||
|
||||
for channel in spsublist[service]['channels']:
|
||||
if channel == currentsub_request[0]:
|
||||
print(f">> This channel is already subscribed to {service}")
|
||||
await ctx.send(f"This channel is already subscribed to {service} alerts")
|
||||
found_channel = True
|
||||
break
|
||||
if not found_channel:
|
||||
# Append the current channel id to the list for this service
|
||||
print(f">> Adding serivce '{currentsub_request[1]}' to {ctx.channel.id}")
|
||||
await ctx.send(f"{service} has been added to monitored services for this channel")
|
||||
spsublist[service]['channels'].append(currentsub_request[0])
|
||||
break
|
||||
|
||||
if not found_service:
|
||||
# Append the current channel id to the list for this service
|
||||
print(f">> Adding serivce '{currentsub_request[1]}' to {ctx.channel.id}")
|
||||
await ctx.send(f"{currentsub_request[1]} has been added to monitored services for this channel")
|
||||
#newsub = {}
|
||||
#newsub[currentsub_request[1]] = {'state' : 'online', 'channels' : [currentsub_request[0]]}
|
||||
spsublist[currentsub_request[1]] = {'state' : 'online', 'channels' : [currentsub_request[0]]}
|
||||
|
||||
else:
|
||||
|
||||
print(">> spsublist.dat does not exist, new file will be created")
|
||||
|
||||
# append new subscription to dict
|
||||
print(">> Creating new dictionary")
|
||||
spsublist[currentsub_request[1]] = {'state' : 'online', 'channels' : [currentsub_request[0]]}
|
||||
print(f">> {service} subscription has been saved")
|
||||
await ctx.send(f"{service} has been added to monitored services for this channel")
|
||||
|
||||
#Write updated array to data file
|
||||
print(">> Saving dictionary to spsublist.dat")
|
||||
async with aiof.open('spsublist.dat', 'wb') as datafile:
|
||||
pickled_spsublist = pickle.dumps(spsublist, protocol=4)
|
||||
await datafile.write(pickled_spsublist)
|
||||
#await datafile.fsync()
|
||||
await datafile.flush()
|
||||
|
||||
print(">> Done")
|
||||
#await ctx.send(f"'{service_state['name']}' added to monitored services")
|
||||
|
||||
else:
|
||||
print(f">> '{service}' does not exist, cancelling subscription")
|
||||
await ctx.send(f"{service} was not found")
|
||||
|
||||
async def StatPing_Monitor():
|
||||
|
||||
# reads in "spsublist.dat" every 60 seconds then iterates
|
||||
# through to check for service status changes. This function will need to check
|
||||
# that "spsublist.dat" exists and is not empty. This function should be called
|
||||
# in bot.on_ready
|
||||
|
||||
#new_spsublist = {}
|
||||
|
||||
# read in data file containing list of subscriptions
|
||||
while True:
|
||||
print("Statping Monitor: Reading in spsublist.dat")
|
||||
if os.path.exists('spsublist.dat'):
|
||||
async with aiof.open('spsublist.dat', 'rb') as datafile:
|
||||
pickled_spsublist = await datafile.read()
|
||||
spsublist = pickle.loads(pickled_spsublist)
|
||||
|
||||
for service in spsublist.keys():
|
||||
# service used to be subscription
|
||||
status = await get_stp_status(service)
|
||||
print(f">> {service} Online: {status['online']} | Previous state: {spsublist[service]['state']}")
|
||||
if status != 'status not found':
|
||||
if status['online'] and spsublist[service]['state'] == 'online':
|
||||
|
||||
# nothing has changed, no alert needed
|
||||
await asyncio.sleep(1)
|
||||
elif not status['online'] and spsublist[service]['state'] == "offline":
|
||||
|
||||
# again, nothing has changed no alert needed
|
||||
await asyncio.sleep(1)
|
||||
else:
|
||||
|
||||
print(f">> Status of '{service}' has changed, notifying subscribed channels")
|
||||
|
||||
if status['online']:
|
||||
spsublist[service]['state'] = 'online'
|
||||
for channel in spsublist[service]['channels']:
|
||||
ctx = bot.get_channel(channel)
|
||||
print(f">> Alerting {ctx} that {service} is Online")
|
||||
embed = discord.Embed(title=f"Service Alert", description=f"{service} is Online!", color=0x00ff40)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
elif not status['online']:
|
||||
spsublist[service]['state'] = 'offline'
|
||||
for channel in spsublist[service]['channels']:
|
||||
ctx = bot.get_channel(channel)
|
||||
print(f">> Alerting {ctx} that {service} is Offline")
|
||||
embed = discord.Embed(title=f"Service Alert", description=f"{service} is Offline!", color=0xff2200)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
else:
|
||||
for channel in spsublist[service]['channels']:
|
||||
ctx = bot.get_channel(channel)
|
||||
print(f">> Alerting {ctx} that {service} is an Unknown state")
|
||||
embed = discord.Embed(title=f"Service Alert", description=f"{service} is in an unknown state!", color=0xffff00)
|
||||
await ctx.send(embed=embed)
|
||||
print(">> Done")
|
||||
|
||||
#new_spsublist.append(subscription)
|
||||
|
||||
# Write status changes to spsublist.dat
|
||||
async with aiof.open('spsublist.dat', 'wb') as datafile:
|
||||
pickled_spsublist = pickle.dumps(spsublist)
|
||||
await datafile.write(pickled_spsublist)
|
||||
#await datafile.fsync()
|
||||
await datafile.flush()
|
||||
|
||||
else:
|
||||
print(">> spsublist.dat does not exist, nothing to do.")
|
||||
|
||||
await asyncio.sleep(60)
|
||||
|
||||
|
||||
async def sp_monitor(sublist):
|
||||
|
||||
# Checks the services listed in spsublist for status change
|
||||
# Sublist is a list of 3 items:
|
||||
# - ctx (used to send alert to channel)
|
||||
# - service (the name of the service to check)
|
||||
# - status string (last status of the service, either 'online' or 'offline')
|
||||
|
||||
ctx = sublist[0]
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
status = await get_stp_status(spsublist[1])
|
||||
if status['online'] and spsublist[2] == "online":
|
||||
# nothing has changed, no alert needed
|
||||
await asyncio.sleep(1)
|
||||
elif not status['online'] and spsublist[2] == "offline":
|
||||
# again, nothing has changed no alert needed
|
||||
await asyncio.sleep(1)
|
||||
else:
|
||||
print(f"Status of {status['name']}' has changed")
|
||||
if status['online']:
|
||||
embed = discord.Embed(title=f"{status['name']} Service Alert", description=f"{spsublist[1]} is Online!", color=0x00ff40)
|
||||
await ctx.send(embed=embed)
|
||||
#await ctx.send(f"{spsublist[1]} is Online!")
|
||||
spsublist[2] = "online"
|
||||
elif not status['online']:
|
||||
embed = discord.Embed(title=f"{status['name']} Service Alert", description=f"{spsublist[1]} is Offline!", color=0xff2200)
|
||||
await ctx.send(embed=embed)
|
||||
#await ctx.send(f"{spsublist[1]} is Offline!")
|
||||
spsublist[2] = "offline"
|
||||
else:
|
||||
embed = discord.Embed(title=f"{status['name']} Service Alert", description=f"{spsublist[1]} is in an unknown state!", color=0xffff00)
|
||||
await ctx.send(embed=embed)
|
||||
#await ctx.send(f"Unknown state for service {spsublist[1]}")
|
||||
await asyncio.sleep(60)
|
||||
|
||||
async def get_stp_status(service):
|
||||
|
||||
# Get StatPing status via REST API
|
||||
spservice_array = requests.get(statpingURL, headers=statpingHEADERS)
|
||||
found = False
|
||||
|
||||
# spservice_array is json data, need to treat it as such
|
||||
for spservice in spservice_array.json():
|
||||
|
||||
# using lower() to eliminate any case mismatch problems
|
||||
if spservice['name'].lower() == service.lower():
|
||||
|
||||
found = True
|
||||
return spservice
|
||||
|
||||
# Want to alert user if the service was not found
|
||||
if not found:
|
||||
return "service not found"
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def help(ctx):
|
||||
embed = discord.Embed(title="R0b3BOT", description="List of commands are:", color=0xeee657)
|
||||
embed.add_field(name="$printstat", value="Uploads a snapshot of Rich's 3D printer and current stats", inline=False)
|
||||
embed.add_field(name="$explain", value="Displays Dalek EXPLAIN gif", inline=False)
|
||||
embed.add_field(name="$holyshit", value="Displays Marty McFly HOLY SHIT gif", inline=False)
|
||||
embed.add_field(name="$greetings", value="Gives a nice greet message", inline=False)
|
||||
embed.add_field(name="$cat", value="Gives a cute cat gif to lighten up the mood.", inline=False)
|
||||
embed.add_field(name="$bitch @member", value="Plays clip of BigEric420 saying 'maybe you shouldn't be such a bitch.mp3'", inline=False)
|
||||
embed.add_field(name="$boom @member", value="Plays 'Boom Bitch' sound clip", inline=False)
|
||||
embed.add_field(name="$cowbell @member", value="Plays 'SNL More Cowbell' sound clip", inline=False)
|
||||
embed.add_field(name="$oops @member", value="Plays 'Oops.mp3'", inline=False)
|
||||
embed.add_field(name="$promoted @member", value="Plays Battlefield Friends 'PROMOTED!' sound clip", inline=False)
|
||||
embed.add_field(name="$trololo @member", value="Plays a clip of Trololo song", inline=False)
|
||||
embed.add_field(name="$leeroy @member", value="Plays Leeeerrroooyyy Jenkins clip", inline=False)
|
||||
embed.add_field(name="$eia @member", value="Plays 'Everything is Awesome' song clip")
|
||||
embed.add_field(name="$info", value="Gives a little info about the bot", inline=False)
|
||||
embed.add_field(name="$help", value="Gives this message", inline=False)
|
||||
embed.add_field(name="$last_error", value="Will display the real error message the bot has last encountered for additional debugging info")
|
||||
embed.add_field(name="$uptime", value="Displays how long the bot has been up since last service restart")
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}printstat", value="Uploads a snapshot of Rich's 3D printer and current stats", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}explain", value="Displays Dalek EXPLAIN gif", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}holyshit", value="Displays Marty McFly HOLY SHIT gif", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}greetings", value="Gives a nice greet message", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}cat", value="Gives a cute cat gif to lighten up the mood.", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}bitch @member", value="Plays clip of BigEric420 saying 'maybe you shouldn't be such a bitch.mp3'", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}boom @member", value="Plays 'Boom Bitch' sound clip", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}cowbell @member", value="Plays 'SNL More Cowbell' sound clip", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}oops @member", value="Plays 'Oops.mp3'", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}promoted @member", value="Plays Battlefield Friends 'PROMOTED!' sound clip", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}trololo @member", value="Plays a clip of Trololo song", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}leeroy @member", value="Plays Leeeerrroooyyy Jenkins clip", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}eia @member", value="Plays 'Everything is Awesome' song clip")
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}info", value="Gives a little info about the bot", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}help", value="Gives this message", inline=False)
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}last_error", value="Will display the real error message the bot has last encountered for additional debugging info")
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}spstatus servicename", value="Retrieves status of service from StatPing")
|
||||
embed.add_field(name=f"{BOT_COMMAND_PREFIX}spsub service", value="Allows user to subscribe to service status change alerts for the channel. Can replace <service> with -list and -del:service to manage alerts. NOTICE:Replace spaces in service names w/ '_'!")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
embed = discord.Embed(title="A note about sound clips:", description="Sound clips are only played voice channels. If no user is specified when calling the command, the sound will played in the channel the user is currently joined to. When a username is specified, the bot will play the sound in the channel that user is currently in.")
|
||||
embed = discord.Embed(title="A note about sound clips:", description="Sound clips are only played in voice channels. If a user is not specified when calling the command, the sound will played in the channel of that issuing user is currently joined to. When a username is specified, the bot will play the sound in the channel that user is currently in.")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
# Function to run shell command and return stdout or sterr
|
||||
async def run(cmd):
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE)
|
||||
|
||||
stdout, stderr = await proc.communicate()
|
||||
|
||||
print(f'[{cmd!r} exited with {proc.returncode}]')
|
||||
if stdout:
|
||||
#print(f'[stdout]\n{stdout.decode()}')
|
||||
return stdout.decode()
|
||||
if stderr:
|
||||
#print(f'[stderr]\n{stderr.decode()}')
|
||||
return stderr.decode()
|
||||
|
||||
bot.run(DISCORD_AUTH_TOKEN)
|
||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user