Code
Code
import os
import re
import time
import json
from colorama import Fore, Style, init
import googleapiclient.discovery
import googleapiclient.errors
import google_auth_oauthlib.flow
import google.oauth2.credentials
import pytchat
import openai
import configparser
from dotenv import load_dotenv
import argparse
import sqlite3
from sqlite3 import Error
import random
import codecs
import string
# .env variables
load_dotenv()
init(autoreset=True)
# config.ini variables
config = configparser.ConfigParser()
with codecs.open("config.ini", "r", encoding="utf-8") as f:
config.read_file(f)
# The Keys
api_key = os.environ.get("YOUTUBE_API_KEY")
openai.api_key = os.environ.get("OPENAI_API_KEY")
# Scopes
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
def connect_to_database():
global conn, c
try:
print("Connecting to the database...")
conn = sqlite3.connect("jetsbot_memory.db")
c = conn.cursor()
print("Connected to the database.")
except Exception as e:
print(f"Failed to connect to the database: {e}")
sys.exit(1)
def get_db_stats():
try:
conn = sqlite3.connect("jetsbot_memory.db")
cursor = conn.cursor()
conn.close()
return stats
except Error as e:
print(e)
def create_tables():
c.execute(
"""
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY,
role TEXT,
author_name TEXT,
content TEXT,
assistant_response TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
"""
)
conn.commit()
def truncate_table():
try:
conn = sqlite3.connect("jetsbot_memory.db")
cursor = conn.cursor()
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
# model="gpt-4",
messages=messages,
max_tokens=3000,
n=1,
stop=None,
temperature=0.7,
timeout = 3.0
)
answer = response.choices[0].message.content.strip()
return answer
except Exception as e:
print(f"Error in ask_gpt: {e}")
return "Sorry, I couldn't process your question. Please try again."
def load_credentials(credentials_file):
if os.path.exists(credentials_file):
with open(credentials_file, "r") as f:
credentials_data = json.load(f)
credentials =
google.oauth2.credentials.Credentials.from_authorized_user_info(
info=credentials_data
)
if credentials and credentials.refresh_token:
credentials = google.oauth2.credentials.Credentials(
credentials.token,
refresh_token=credentials.refresh_token,
client_id=credentials.client_id,
client_secret=credentials.client_secret,
token_uri=credentials.token_uri,
scopes=credentials.scopes,
)
return credentials
return None
def authenticate(scopes):
credentials_file = "bot_saved_token.json"
credentials = load_credentials(credentials_file)
if credentials and credentials.valid:
return credentials
else:
print("Credentials are invalid or missing. Re-authenticating.")
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
"client_secret.json", scopes
)
credentials = flow.run_local_server(port=0)
save_credentials(credentials, credentials_file)
return credentials
if not response["items"]:
print("No live stream found for the given video ID.")
return None
try:
live_chat_id =
response["items"][0]["liveStreamingDetails"]["activeLiveChatId"]
except KeyError:
print("The live stream is not active for the given video ID.")
return None
return live_chat_id
def delete_user_messages(author):
try:
c.execute("DELETE FROM messages WHERE author_name = ?", (author,))
conn.commit()
print(f"All messages from {author} have been deleted.")
return True
except Exception as e:
print(f"Error when trying to delete messages from {author}: {e}")
return False
# GG tracking
gg_mentions = {}
last_gg_message_time = 0
gg_message_cooldown = 60 * 20 # Twenty minutes in seconds
gg_mention_window = 2 * 60 # Two minutes in seconds
# Slava tracking
slava_mentions = {}
last_slava_message_time = 0
slava_message_cooldown = 60 * 20 # Twenty minutes in seconds
slava_mention_window = 2 * 60 # Two minutes in seconds
if restrict:
send_message(
youtube,
live_chat_id,
f"✈🤖 JetsBotv4 Live 🟢! Use '[!gpt] {{your text}}'. Slow mode on 🐢:
1 chat every {restrict} min. Wipe chats with '!gpt forget me' Feedback:
https://forms.gle/DWrGcBCEXofu5TNg8.",
silent,
)
else:
send_message(
youtube,
live_chat_id,
"✈🤖 JetsBotv4 Ready 🟢! Use '[!gpt] {your text}'. Reset our chat with
'!gpt forget me'. Let's talk! Feedback: https://forms.gle/DWrGcBCEXofu5TNg8",
silent,
)
prefixes = tuple(
config.get("prefixes", key) for key in config.options("prefixes")
)
if (
("safety meeting" in text.lower() or ":_safety:" in text.lower())
and time.time() - last_safety_message_time > safety_message_cooldown
):
if (
author_name not in safety_meeting_mentions
or time.time() - safety_meeting_mentions[author_name]
> safety_mention_window
):
safety_meeting_mentions[
author_name
] = time.time() # Add or update the author's mention time
if (
len(
[
user
for user, mention_time in
safety_meeting_mentions.items()
if time.time() - mention_time < safety_mention_window
]
)
>= 2
):
message = random.choice(
safety_meeting_messages
) # Choose a random safety meeting message
send_message(youtube, live_chat_id, message, silent)
last_safety_message_time = time.time()
safety_meeting_mentions = (
{}
) # Reset the dictionary after sending a message
if (
text.lower() == "gg"
and time.time() - last_gg_message_time > gg_message_cooldown
):
if (
author_name not in gg_mentions
or time.time() - gg_mentions[author_name] > gg_mention_window
):
gg_mentions[
author_name
] = time.time() # Add or update the author's mention time
if (
len(
[
user
for user, mention_time in gg_mentions.items()
if time.time() - mention_time < gg_mention_window
]
)
>= 3
):
# Select a random message
random_gg_message = random.choice(gg_messages)
send_message(youtube, live_chat_id, random_gg_message, silent)
last_gg_message_time = time.time()
gg_mentions = {} # Reset the dictionary after sending a message
if (
text.lower().startswith("!gpt restrict ")
or text.lower() == "!gpt shutdown"
or text.lower() == "!gpt stats"
or text.lower() == "!gpt look into this red light"
):
if author_name != "Jets115":
continue # Ignore commands from users other than Jets115
else:
if text.lower().startswith("!gpt restrict "):
try:
restrict = int(
text.split()[2]
) # This assumes the command is '!gpt restrict x' where
x is an integer
print(f"Restriction updated to {restrict} minutes per
user")
send_message(
youtube,
live_chat_id,
f"Restriction updated to {restrict} minutes per
user",
silent,
) # new line to send message to YouTube
except ValueError:
print(
"Invalid restriction value provided. Please provide
an integer."
)
if text.lower().startswith(prefixes):
# Check if the user is restricted from asking questions
current_time = time.time()
if (
restrict > 0
and author_name in last_question_time
and current_time - last_question_time[author_name] < restrict *
60
and author_name != "Jets115"
): # Exempt user jets115 from restrictions
print(f"Ignoring question from {author_name} due to
restriction")
continue
last_question_time[
author_name
] = current_time # Update the last question time for this user
question = text[4:].strip()
answer = ask_gpt(question, author_name)
#answer = f"GPT: @{author_name[:10]} {answer}"
# Clean up the answer first
# Process and truncate the answer
answer = re.sub(r"[^\x20-\x7E]", " ", answer)
if len(answer) > 185:
#punctuation_no_comma = string.punctuation.replace(",",
"").replace("'", "").replace("-", "")
punctuation_no_comma = string.punctuation.replace(",",
"").replace("'", "")
# Find the last punctuation mark within the first 185 characters
last_punctuation = max((answer[:185].rfind(ch) for ch in
punctuation_no_comma if answer[:185].rfind(ch) != -1), default=-1)
# Store the user message and the assistant response in the database
clean_message = re.sub("|".join(prefixes), "", text,
flags=re.IGNORECASE).strip()
store_message("user", author_name, clean_message, stored_answer)
try:
request = youtube_authenticated.liveChatMessages().insert(
part="snippet",
body={
"snippet": {
"liveChatId": live_chat_id,
"type": "textMessageEvent",
"textMessageDetails": {"messageText": message},
}
},
)
time.sleep(1)
response = request.execute()
except Exception as e:
print(f"Error sending message: {e}")
response = None
return response
def create_youtube_service(credentials=None):
if credentials:
return googleapiclient.discovery.build("youtube", "v3",
credentials=credentials)
else:
return googleapiclient.discovery.build("youtube", "v3",
developerKey=api_key)
def main():
connect_to_database()
create_tables()
args = parser.parse_args()
video_id = args.video_id
youtube_authenticated = create_youtube_service(authenticate(scopes))
youtube = create_youtube_service()
live_chat_id = get_live_chat_id(youtube, args.video_id)
if __name__ == "__main__":
main()