Skip to content

Commit

Permalink
final touches for new release
Browse files Browse the repository at this point in the history
  • Loading branch information
keyboardmedicNL committed Nov 8, 2023
1 parent de940e7 commit 8e1d59e
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 26 deletions.
3 changes: 1 addition & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
config
Config
/config/config.json
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/config
/config/config.json
83 changes: 61 additions & 22 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,81 @@
# What it does
This is a script i wrote so i can get notifications if certain channels go live on youtube, it check their live videos to a list of keywords and if it contains said keyword it posts a link to the video to a discord webhook. it automaticly calculates the time between polls to avoid getting rate limited. however the youtube api is very restrictive on quota's and at most you can poll every 15 minutes if you only check 1 channel

the code itself is heavily commented so go ham and make it your own
![Alt text](screenshot.png)

**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 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

included are:
- a post script that sends a http post to a watchdog server of your choosing, wich wont happen if the url is left blank in the config
- a http webserver running to use for uptime monitoring by having an approachable url wich can be checked with something like uptime kuma
- remote logging capabilities with use of a discord webhook where debugging messages get posted, wich wont happen if the url is left blank in the config


# how to use
1. install python on your system from the python website https://www.python.org/downloads/
2. place all contents in a folder and make a "config" folder.
3. make a config.json and copy the text below into the file
1. install python on your system from the python website https://www.python.org/downloads/ if you plan on using the included batch files make sure to select ```intall to path``` during the installation
2. you will need a youtube data api key for the data api v3, you can get one on https://console.cloud.google.com/ it can be difficult to find the right menu's if your new to this. refer to a quick google search on how to
3. go to the config folder and copy the ```example_config.json``` or ```example_lite_config.json``` and rename it to ```config.json```.
4. adjust the appropriate config for your version
* you will need the actual channelID of the channel you want to monitor, not a handle like @youtube, plenty of tools out there that do it for you, just google ```youtube channel id finder```

lite:
```
{
"youtubeApiKey": "youtubedataAPIkey",
"webhookurl": "URL where the notification gets posted to",
"webhooklogurl": "optional URL to log output to a discord webhook",
"webhookmonitorurl": "optional URL to send simple post requests to a watchdog server in format {"name":"botname":"time":"UNIX timestamp"}",
"botname": "name to send to watchdog server OPTIONAL",
"posttimeout": "time between posts to watchdog OPTIONAL",
"wordlist": ["example1","example2","example3"],
"notificationmessage": "Example message to post to discord",
"channels": ["YoutubechannelID1","YoutubechannelID2"],
"hostname": "Adress for simple webserver",
"webport": "port for simple webserver"
"youtube_api_key": "YOUR_YOUTUBE_API_KEY",
"discord_webhook_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LINKS_TO",
"word_list": ["list", "of", "words", "to", "match"],
"ignore_list": ["list", "of", "words", "to", "ignore"],
"notification_message": "message to post with the link",
"channels": ["channelid1","channelid2"]
}
```
4. input the correct data and launch the script youtubelivebot.py
* leave optional entries blank if you do not intent to use them but do include them otherwise the script will throw an error
* you will need the actual channelID of the channel you want to monitor, not a handle like @youtube
full:
```
{
"youtube_api_key": "YOUR_YOUTUBE_API_KEY",
"discord_webhook_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LINKS_TO",
"word_list": ["list", "of", "words", "to", "match"],
"ignore_list": ["list", "of", "words", "to", "ignore"],
"notification_message": "message to post with the link",
"channels": ["channelid1","channelid2"],
"use_discord_logs": "true or false",
"discord_remote_log_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LOGS_TO",
"use_web_server": "true or false",
"web_server_url": "0.0.0.0",
"web_server_port": "8888",
"use_remote_post": "true or false",
"remote_http_server_url": "http://google.com",
"bot_name": "NAME_OF_YOUR_BOT_FOR_REMOTE_POST",
"post_interval": "time in minutes to post to remote post"
}
```
5. launch the script
on windows: with the included batch files for your version
on linux: in a terminal with ```python youtubelivebot.py``` or ```python youtubelivebotlite.py```

Optionally a dockerfile is included wich can be used to build a docker image or use the one on my repository with the following code

```
docker run -dit --name youtubelivebot -v /path/to/config:/usr/src/app/config -p <port for webserver>:<port defined in config> keyboardmedic/youtubelivebot:latest
```
# how it works
**main script**
- loads the config.
- launches the webserver and post server in seperate threads if selected in the config.
- calculates time between polls to be as much as possible within the given rate limit quota provided by the api (for 1 channel this is every 15 minutes, for 2 channels every 30 minutes and so forth)
- loops over the channels configured and checks if they have any live streams active
- if a livestream is found it is checked against the wordlist to see if the video title contains ANY of the words provided in the word_list
- if a match is found it checks if any of the words in the ignore_list are in the title, if ANY of those words are present in the title it will ignore the livestream and not post it.
- if NONE of the ignore_list words are present it will post the video to the configured webhook with the configured message
- it then waits for the calculated time and loops over the channels again

**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
Scripts are written by an amateur, use at your own risk

17 changes: 17 additions & 0 deletions config/example_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"youtube_api_key": "YOUR_YOUTUBE_API_KEY",
"discord_webhook_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LINKS_TO",
"word_list": ["list", "of", "words", "to", "match"],
"ignore_list": ["list", "of", "words", "to", "ignore"],
"notification_message": "message to post with the link",
"channels": ["channelid1","channelid2"],
"use_discord_logs": "true or false",
"discord_remote_log_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LOGS_TO",
"use_web_server": "true or false",
"web_server_url": "0.0.0.0",
"web_server_port": "8888",
"use_remote_post": "true or false",
"remote_http_server_url": "http://google.com",
"bot_name": "NAME_OF_YOUR_BOT_FOR_REMOTE_POST",
"post_interval": "time in minutes to post to remote post"
}
8 changes: 8 additions & 0 deletions config/example_lite_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"youtube_api_key": "YOUR_YOUTUBE_API_KEY",
"discord_webhook_url": "URL_TO_YOU_DISCORD_WEBHOOK_TO_POST_LINKS_TO",
"word_list": ["list", "of", "words", "to", "match"],
"ignore_list": ["list", "of", "words", "to", "ignore"],
"notification_message": "message to post with the link",
"channels": ["channelid1","channelid2"]
}
Binary file added image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions start lite.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off
python youtubelivebotlite.py
pause
3 changes: 2 additions & 1 deletion start.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@echo off
python "youtubelivebot" youtubelivebot.py
python youtubelivebot.py
pause
61 changes: 61 additions & 0 deletions youtubelivebotlite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# imports needed libraries for code
import requests
import time
import json
import math
import threading
from os.path import exists
from subprocess import call

#variables used in script
l= []

#pulls data from config
with open("config/config.json") as config:
config_json = json.load(config)
youtube_api_key = config_json["youtube_api_key"]
discord_webhook_url = config_json["discord_webhook_url"]
word_list = config_json["word_list"]
ignore_list = config_json["ignore_list"]
notification_message = config_json["notification_message"]
channels = config_json["channels"]
print("succesfully loaded config")

# checks if name of video contains pursuit and if so posts video to webhook
while True:
try:
# calculates minimum time between api calls to avoid rate limiting
time_to_poll= math.ceil(1440 * len(channels) / 100)
time_to_sleep = time_to_poll * 60
print(f"calculated time between polls is {str(time_to_poll)} minutes")
# loop checks all channels in config and searches for video titles matching defined keywords in config
for channel in channels:
print(f"polling channel {channel}")
r = requests.get('https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=' + channel, '&eventType=live&type=video&key=' + youtube_api_key)
request = r
print(f"requested information for channel {channel} with response: {str(request)}")
# checks if get request was succesfull
if "200" in str(request):
yt_api_json = request.json()
try:
item_count = len(yt_api_json["items"])
except:
item_count = 0
if item_count > 0:
for item in yt_api_json["items"]:
# checks if videos found contain keywords and do not contain ignored words
if any(s in (item["snippet"]["title"].lower()) for s in word_list) and all(s not in (item["snippet"]["title"].lower()) for s in ignore_list):
video_id_to_send = item["id"]["videoId"]
if video_id_to_send not in l:
l.append(video_id_to_send)
print(f"found video matching criteria, posting video with id: {video_id_to_send}")
r = requests.post(discord_webhook_url, data={"content": notification_message + "https://www.youtube.com/watch?v=" + video_id_to_send,})
else:
print(f"Live video found but it did not match the criteria for {channel}")
else:
print(f"no live videos found for channel {channel}")
print(f"waiting for {str(time_to_poll)} minutes")
time.sleep(time_to_sleep)
except Exception as e:
print(f"An exception occurred in main loop: {str(e)} waiting for 1 minute")
time.sleep(60)

0 comments on commit 8e1d59e

Please sign in to comment.