Skip to content

Commit

Permalink
rewrite continued to make logs more readable
Browse files Browse the repository at this point in the history
  • Loading branch information
keyboardmedicNL committed Nov 8, 2023
1 parent 25f348a commit d7541a4
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 49 deletions.
23 changes: 21 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ a simple script that polls a list of twitch channels and posts a message to a di

**the script currently comes with 2 versions:**
- the lite version, wich just contains the script to check for livestreams and posts them to discord aswell.
- the full version, wich contains the script, the option to send log messages to a discord webhook for easy remote monitoring and a simple webserver that can be pinged to monitor uptime, aswell as simple service that will send a http post to an adress of your chosing with a configurable timer with the json ```{'name': "bot_name", 'time': "unix timestamp of current time in utc"}``` all of this can be toggled on or off in the config
- the full version, wich contains the script, the option to send log messages to a discord webhook for easy remote monitoring and a simple webserver that can be pinged to monitor uptime, aswell as simple remote post service that will send a http post to an adress of your chosing with a configurable timer with the json ```{'name': "bot_name", 'time': "unix timestamp of current time in utc"}``` all of this can be toggled on or off in the config


# how to use
Expand All @@ -35,7 +35,7 @@ full:
"discord_webhook_url": "webhook to post main messages to",
"poll_interval": "time in minutes between polls",
"use_web_server": "true or false",
"webs_erver_url": "adress for local webserver OPTIONAL",
"web_server_url": "adress for local webserver OPTIONAL",
"web_server_port": "port for local webserver OPTIONAL",
"use_discord_logs": "true or false",
"discord_remote_log_url": "webhook to post log messages to OPTIONAL",
Expand All @@ -59,6 +59,25 @@ on linux: in a terminal with ```python goinglive.py``` or ```python goinglivelit
```
docker run -it -d --name twitchgoinglive -v /path/to/config:/usr/src/app/config keyboardmedic/twitchgoinglive:latest
```
# how it works
**main script**
- loads the config.
- launches the webserver and post server in seperate threads if selected in the config.
- checks if token.txt is present in the config folder and reads it to load the auth token for twitch api calls, if not it runs the get_token function to request an auth token from twitch and saves it to token.txt
- it gets the list of streamers to poll with the get_streamers function and checks if any txt files exsist in the config folder with streamer names with a saved messageid, if it finds any it will attempt to delete the messages on discord with the corresponding message id, it does this to avoid leaving old messages up between restarts
- it then loops trough all the streamers and gets the stream information from the twitch api to see if they are live and to retrieve the needed data for the message
- if a streamer is live it checks if a txt file with the streamers name exsists, if it does not exsist it posts a message to discord and creates a txt file with the name of the streamer wich holds the messageid of the message posted to discord, if the txt does exsist it reads it for the messageid and then updates the message on discord with that id
- if a streamer is not live it checks if a txt file exsists with the streamers name and if it does it will read it for the message id and delete that message on discord.
- it then waits for the preconfigured time and loops back to looping trough the streamers.

**webserver**
- loads the config
- serves a website on the defined adress with the defined port with just a plain text message that says "hello i am a webserver"

**remote post**
- loads the config
- sends a http post to the configured adress with the following json ```{'name': "bot_name as configured", 'time': "unix timestamp of current time in utc"}```
- waits for the configured timeout and then sends a post again

# disclaimer
these scripts are written by an amateur... use at your own risk
85 changes: 59 additions & 26 deletions goinglive.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ def webhook_send(rr):
rl = requests.post(webhook_url, json=data_for_hook, params={'wait': 'true'})
rl_json = rl.json()
message_id = rl_json["id"]
print(f"discord webhook response for method post is {rl} ({message_id} posted)")
discord_remote_log("Goinglivebot",14081792,f"discord webhook response for method post is {rl} ({message_id} posted)")
if "200" in str(rl):
print(f"posting message to discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","green",f"posting message to discord with discord id: {message_id} for {streamer}, response is {rl}")
else:
print(f"attempted to post message to discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","red",f"attempted to post message to discord with discord id: {message_id} for {streamer}, response is {rl}")
return(message_id)

# edits discord webhook message
Expand Down Expand Up @@ -105,36 +109,54 @@ def webhook_edit(rr,message_id):
}
]}
rl = requests.patch(f"{webhook_url}/messages/{message_id}", json=data_for_hook, params={'wait': 'true'})
print(f"discord webhook response for method patch is {rl} ({message_id} updated)")
discord_remote_log("Goinglivebot",14081792,f"discord webhook response for method patch is {rl} ({message_id} updated)")
if "200" in str(rl):
print(f"updating message to discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","green",f"updating message to discord with discord id: {message_id} for {streamer}, response is {rl}")
else:
print(f"attempted to update message to discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","red",f"attempted to update message to discord with discord id: {message_id} for {streamer}, response is {rl}")

# deletes discord webhook message
def webhook_delete(message_id):
rl = requests.delete(f"{webhook_url}/messages/{message_id}", params={'wait': 'true'})
print(f"discord webhook response for method delete is {rl} ({message_id} removed)")
discord_remote_log("Goinglivebot",14081792,f"discord webhook response for method delete is {rl} ({message_id} removed)")
if "204" in str(rl):
print(f"deleting message om discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","green",f"deleting message om discord with id: {message_id} for {streamer}, response is {rl}")
else:
print(f"attempted to delete message on discord with id: {message_id} for {streamer}, response is {rl}")
discord_remote_log("Goinglivebot","red",f"attempted to delete message on discord with id: {message_id} for {streamer}, response is {rl}")

# ===== twitch functions =====
# renews token used for twitch api calls
def get_token():
print("Requesting new token from twitch")
response=requests.post("https://id.twitch.tv/oauth2/token", json_data={"client_id" : str(twitch_api_id), "client_secret" : str(twitch_api_secret), "grant_type":"client_credentials"})
tokenJson = response.json()
token = tokenJson["access_token"]
print(f"new token is: {token}")
discord_remote_log("Goinglivebot",14081792,f"new auth token requested")
with open(r'config/token.txt', 'w') as tokenFile:
tokenFile.write("%s\n" % token)
discord_remote_log("Goinglivebot","yellow",f"Requesting new token from twitch")
response=requests.post("https://id.twitch.tv/oauth2/token", json={"client_id" : str(twitch_api_id), "client_secret" : str(twitch_api_secret), "grant_type":"client_credentials"})
if "200" in str(response):
token_json = response.json()
token = token_json["access_token"]
print(f"new token is: {token}")
discord_remote_log("Goinglivebot","green",f"new auth token recieved")
with open(r'config/token.txt', 'w') as tokenFile:
tokenFile.write("%s\n" % token)
else:
print(f"unable to request new token with response: {response}")
discord_remote_log("Goinglivebot","red",f"unable to request new token with response: {response}")
token = "empty"
return(token)

# gets stream information from twitch api
def get_stream(streamer):
response=requests.get(f"https://api.twitch.tv/helix/streams?&user_login={streamer}", headers={'Authorization':f"Bearer {token}", 'Client-Id':twitch_api_id})
print(f"response for get_stream with name {streamer} is {response}")
discord_remote_log("Goinglivebot",14081792,f"response for get_stream with name {streamer} is {response}")
print(f"tried to get streamer information with function get_stream for {streamer} with response: {response}")
if "200" in str(response):
discord_remote_log("Goinglivebot","green",f"got streamer information with function get_stream for {streamer} with response: {response}")
else:
discord_remote_log("Goinglivebot","red",f"tried to get streamer information with function get_stream for {streamer} with response: {response}")
responsejson = response.json()
try:
is_live = responsejson["data"][0]["type"]
discord_remote_log("Goinglivebot","green",f"{streamer} is live!")
except:
is_live = ""
return(response, responsejson, is_live)
Expand All @@ -143,6 +165,16 @@ def get_stream(streamer):
# simple discord webhook send for remote logging
def discord_remote_log(title,color,description):
if use_discord_logs.lower() == "true":
if color == "blue":
color = 1523940
elif color == "yellow":
color = 14081792
elif color == "red":
color = 10159108
elif color == "green":
color = 703235
elif color == "purple":
color = 10622948
data_for_log_hook = {"embeds": [
{
"title": title,
Expand All @@ -159,22 +191,22 @@ def save_message_id(name,message_id):
with open(fileName, 'w') as File:
File.write(message_id)
print(f"{message_id} saved in file {name}.txt")
discord_remote_log("Goinglivebot",14081792,f"{message_id} saved in file {name}.txt")
discord_remote_log("Goinglivebot","green",f"message id: {message_id} saved in file {name}.txt")

# reads streamid from file
def read_message_id(name):
fileName = f"config/{name}.txt"
with open(fileName, 'r') as File:
message_id = str(File.readline())
print(f"{message_id} read from {name}.txt")
discord_remote_log("Goinglivebot",14081792,f"{message_id} read from {name}.txt")
discord_remote_log("Goinglivebot","green",f"message id: {message_id} read from {name}.txt")
return(message_id)

# remove file
def remove_message_id_file(name):
os.remove(f"config/{name}.txt")
print(f"removed file {name}.txt")
discord_remote_log("Goinglivebot",14081792,f"removed file {name}.txt")
discord_remote_log("Goinglivebot","green",f"removed file {name}.txt")

# gets list of streamers to poll
def get_streamers():
Expand All @@ -183,6 +215,7 @@ def get_streamers():
if "http" in streamers[0]:
response = requests.get(streamers[0])
streamers = response.text.splitlines()
discord_remote_log("Goinglivebot","yellow",f"list of streamers to poll from: {streamers}")
return(streamers)

# ===== end of functions =====
Expand All @@ -200,7 +233,7 @@ def get_streamers():
use_discord_logs = str(config_json["use_discord_logs"])
if use_discord_logs.lower() == "true":
discord_remote_log_url = str(config_json["discord_remote_log_url"])
discord_remote_log("Goinglivebot",14081792,"succesfully loaded config")
discord_remote_log("Goinglivebot","blue","succesfully loaded config")
print("succesfully loaded config")

# webserver for local monitoring
Expand All @@ -210,7 +243,7 @@ def thread_second(): # start webserver.py as a second threat to allow it to run
process_thread = threading.Thread(target=thread_second)
process_thread.start()
print("starting webserver for local monitoring")
discord_remote_log("Goinglivebot",14081792,"starting webserver for local monitoring")
discord_remote_log("Goinglivebot","blue","starting webserver for local monitoring")

#post process to talk to remote monitor
if use_remote_post.lower() == "true":
Expand All @@ -219,15 +252,15 @@ def thread_third(): # start post.py as a third threat to allow it to run paralle
process_thread = threading.Thread(target=thread_third)
process_thread.start()
print("starting post server for remote monitoring")
discord_remote_log("Goinglivebot",14081792,"starting post server for remote monitoring")
discord_remote_log("Goinglivebot","blue","starting post server for remote monitoring")

#opens file to get auth token
if exists(f"config/token.txt"):
with open("config/token.txt", 'r') as file2:
tokenRaw = str(file2.readline())
token = tokenRaw.strip()
print ("Token to use for auth: " + token)
discord_remote_log("Goinglivebot",14081792,"auth token loaded succesfully")
discord_remote_log("Goinglivebot","blue","auth token loaded succesfully")
else:
token = get_token()

Expand All @@ -240,15 +273,14 @@ def thread_third(): # start post.py as a third threat to allow it to run paralle
webhook_delete(message_id_from_file)
remove_message_id_file(streamer)
print("removed old messages posted to webhook")
discord_remote_log("Goinglivebot",14081792,"removed old messages posted to webhook")
discord_remote_log("Goinglivebot","blue","removed old messages posted to webhook")

# main loop
while True:
try:
streamers = get_streamers()
for streamer in streamers:
rresponse,r,is_live = get_stream(streamer)
if "401" in str(rresponse):
if not "200" in str(rresponse):
token = get_token()
rresponse,r,is_live = get_stream(streamer)
if is_live == "live":
Expand All @@ -264,9 +296,10 @@ def thread_third(): # start post.py as a third threat to allow it to run paralle
webhook_delete(message_id_from_file)
remove_message_id_file(streamer)
print(f"waiting for {poll_interval} minutes")
discord_remote_log("Goinglivebot",14081792,f"waiting for {poll_interval} minutes")
discord_remote_log("Goinglivebot","yellow",f"waiting for {poll_interval} minutes")
except Exception as e:
print("An exception occurred: ", str(e))
discord_remote_log("Goinglivebot","red",f"An exception occurred: {str(e)}")
print()
time.sleep(poll_interval*60)

Expand Down
19 changes: 15 additions & 4 deletions post.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
from datetime import datetime, timezone, timedelta

# formats embed for discord webhook and posts to url
def discord_remote_log(title,color,description):
def discord_remote_log(title,color,description):
if use_discord_logs.lower() == "true":
if color == "blue":
color = 1523940
elif color == "yellow":
color = 14081792
elif color == "red":
color = 10159108
elif color == "green":
color = 703235
elif color == "purple":
color = 10622948
data_for_log_hook = {"embeds": [
{
"title": title,
Expand All @@ -15,6 +25,7 @@ def discord_remote_log(title,color,description):
}
]}
rl = requests.post(discord_remote_log_url, json=data_for_log_hook)
time.sleep(1)

# loads needed data from config to variables
with open("config/config.json") as config: # opens config and stores data in variables
Expand All @@ -26,7 +37,7 @@ def discord_remote_log(title,color,description):
if use_discord_logs.lower() == "true":
discord_remote_log_url = str(config_json["discord_remote_log_url"])
print("<POST> Succesfully loaded config")
discord_remote_log("Goinglivebot/post",14081792,"succesfully loaded config")
discord_remote_log("Goinglivebot/post","blue","succesfully loaded config")

# main loop
while True:
Expand All @@ -36,8 +47,8 @@ def discord_remote_log(title,color,description):
try:
x = requests.post( remote_http_server_url, json = myobj) # sends post request
print("<POST> webhook response is: " + x.text) # log message
discord_remote_log("Goinglivebot/post",14081792,f"webhook response is: {x.text}")
discord_remote_log("Goinglivebot/post","purple",f"webhook response is: {x.text}")
except Exception as e: # catches exception
print(f"An exception occurred in main loop: {str(e)}")
discord_remote_log("Goinglivebot/post",10159108,f"An exception occurred in main loop: {str(e)}")
discord_remote_log("Goinglivebot/post","red",f"An exception occurred in main loop: {str(e)}")
time.sleep(post_interval)
Loading

0 comments on commit d7541a4

Please sign in to comment.