Merge pull request 'v2 Standalone Docker Update' (#40) from v2.0 into master

Reviewed-on: #40
This commit is contained in:
alex_orid 2021-05-13 20:36:45 +00:00
commit 2343aff13d
103 changed files with 24512 additions and 1481 deletions

3
.gitignore vendored
View File

@ -5,3 +5,6 @@ credentials/
.idea/ .idea/
stream_sources/chyron.txt stream_sources/chyron.txt
stream_sources/brb.txt stream_sources/brb.txt
*.log
timers/
event_logs/logs/

View File

@ -1,46 +0,0 @@
from main import user_module_init
import config as config
import db
import user_module
import commands.loader as command_loader
from commands.command_base import AbstractCommand
import credentials
class Command_Management_Module():
def __init__(self):
super().__init__()
self.dbCredential: credentials.DB_Credential
def main_test(self):
print("[TEST Module]> test")
tempModule = user_module.User_Module()
#tempModule.commands = command_loader.load_commands_new(AbstractCommand.CommandType.Praxis)
print(self.getCommandsList(tempModule.commands))
def getCommandsList(self, targetModuleCommands):
print(type(targetModuleCommands))
commandsList = "\n"
for cmd in targetModuleCommands:
targetCommand = targetModuleCommands[cmd]
print(targetCommand.command)
print(targetCommand.isCommandEnabled)
return commandsList
def getUserPermission():
pass
if __name__ == "__main__":
testModule = Command_Management_Module()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
testModule.main_test()

View File

@ -7,4 +7,4 @@ RUN pip3 install -r requirements.txt
COPY . . COPY . .
CMD [ "python3", "main.py"] #Uncomment to start with the Docker Container CMD [ "python3", "main.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_discord.txt requirements_sa_discord.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_discord.txt
COPY . .
CMD [ "python3", "standalone_discord_script.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_twitch.txt requirements_sa_twitch.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_twitch.txt
COPY . .
CMD [ "python3", "standalone_twitch_script.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.7.10-alpine3.12
WORKDIR /Praxis
COPY requirements_sa_twitch_pubsub.txt requirements_sa_twitch_pubsub.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_twitch_pubsub.txt
COPY . .
CMD [ "python3", "standalone_twitch_pubsub.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.7.10-alpine3.12
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_channelrewards.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_command.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.7.10-alpine3.12
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_eventLog.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.7.10-alpine3.12
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_lights.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_tts_core.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_user_client.py"]

View File

@ -0,0 +1,11 @@
FROM python:3.10.0a7-alpine3.13
WORKDIR /Praxis
COPY requirements_sa_command.txt requirements_sa_command.txt
RUN apk add --update gcc libc-dev linux-headers && rm -rf /var/cache/apk/*
RUN pip3 install -r requirements_sa_command.txt
COPY . .
CMD [ "python3", "standalone_websource.py"]

View File

@ -1,23 +1,58 @@
A chatbot to help with live stream production and effects. An evolving chatbot to help users primarily with live stream production and effects.
___ ___
# Docker: # Praxis Bot
## Docker Info: ## Docker:
Currently to build the container run the following command. This bot primarily uses docker to run various services.
### Image Setup:
`docker create -p 2501:2501 -e ISDOCKER=cat --name praxis praxis` Use the following command to setup all the images.
Windows: `makedockerimages.bat`<br>
Linux: `makedockerimages.sh`
### Docker-Compose Info:
To Start:
`docker-compose up -d`<br>
To Stop:
`docker-compose down`<br>
<br>
___
### User TTS Speaker:
To receive audio from standalone_tt_core.py launch standalone_tts_speaker.py.
`python standalone_tts_speaker.py`
or
windows: `praxis-tts-speaker.bat` Modify this to match the correct directory! Or no work for YOU!!!<br>
linux: `praxis-tts-speaker.sh`<br>
<br>
___
### User Web Client:
To access the User Client visit `index.html` from `\user_client\v1\` in your browser.<br>
<br>
___
# Credentials: # Credentials:
## Credentials Setup: ## Credentials Setup:
Create a json based on the templates and put them into the `/credentials/` folder. Create a json based on the templates and put them into the `/credentials/` folder.
Refer to the `/credential_templates/` folder for examples. Refer to the `/credential_templates/` folder for examples.<br>
<br>
### For Twitch Credentials ## For Twitch Credentials:
### Twitch IRC Chat Credentials:
Username = `TwitchUsername` *(Must match ***credentialsNickname*** in config)* Username = `TwitchUsername` *(Must match ***credentialsNickname*** in config)*
Helix Client ID = `https://dev.twitch.tv/console/apps` Helix Client ID = `https://dev.twitch.tv/console/apps`
@ -26,19 +61,40 @@ Oauth = `https://twitchapps.com/tmi/`
V5 Client ID = `https://twitchtokengenerator.com/` V5 Client ID = `https://twitchtokengenerator.com/`
### For Database Credentials ### Twitch PubSub Credentials:
pubsub_client_id = `https://dev.twitch.tv/console/apps` Set url to `http://localhost:17563`
pubsub_secret = `^Look at Instructions Above^`
pubsub_AccessToken = Generate by using: `python twitch_generate_credentials.py`
pubsub_RefreshToken = `^Look at Instructions Above^`<br>
<br>
## For Database Credentials:
Will be replaced soon.<br>The current `db.py` file is not being used for now.<br>
~~Nickname = `Anything You Want` *(Must match ***credentialsNickname*** in config)*~~
~~Engine = `"mysql+mysqlconnector://root:password@localhost:3306/DatabaseName"`~~<br>
<br>
## For Discord Credentials:
Nickname = `Anything You Want` *(Must match ***credentialsNickname*** in config)* Nickname = `Anything You Want` *(Must match ***credentialsNickname*** in config)*
Engine = `"mysql+mysqlconnector://root:password@localhost:3306/DatabaseName"` Token = `https://discord.com/developers/`<br>
<br>
### For Discord Credentials ## Phue Credentials:
Nickname = `Anything You Want` *(Must match ***credentialsNickname*** in config)* The lights module will only be able to establish and generate credentials if the button on the bridge is pressed prior to running the script via:
`python lights_module.py`<br>
Token = `https://discord.com/developers/` After running a credential file will be created in the user's home directory on their operating system called `.python_hue` this can then be moved into the credentials folder.<br>
<br>
## Credential Usage: ## Credential Usage:
Place json credentials in the `/credentials/` folder. Place json credentials in the `/credentials/` folder.
To load them, run `load_credentials()` from `Credentials_Module` in the `credentials.py` script. To load them, run `load_credentials()` from `Credentials_Module` in the `credentials.py` script.
</br>
___ ___

View File

@ -1 +1 @@
slurList = ("fag", "faggot", "niga", "nigga", "nigger", "retard", "tard", "rtard", "coon") slurList = ("fag", "faggot", "niga", "nigga", "nigger", "retard", "tard", "rtard", "coon", "dghdtrhrsy65eu665")

View File

@ -0,0 +1,56 @@
from abc import ABCMeta, abstractmethod
from enum import Enum, auto
class AbstractChannelRewards(metaclass=ABCMeta):
"""
This is the base class for channel points. In order to load a channel point redemption a few conditions must be met:
1) The class name MUST begin with 'ChannelPoint' i.e. CommandTTS, CommandBan, etc...
2) the class MUST extend AbstractCommand
Generally, it would be advisable to define the ChannelPointPrize redemption name as a variable of the
class and to then call super().__init__(command)
"""
class ChannelRewardsType(Enum):
NONE = auto()
channelPoints = auto()
twitch_bits = auto()
twitch_subs = auto()
class ChannelRewardsSource(Enum):
default = 0
Praxis = 1
Twitch = 2
Discord = 3
def __init__(self, ChannelRewardName: str, n_args: int = 0, ChannelRewardType=ChannelRewardsType.NONE, helpText:list=["No Help"], isChannelRewardEnabled = True):
self.ChannelRewardName = ChannelRewardName
self.n_args = n_args
self.ChannelRewardType = ChannelRewardType
self.help = helpText
self.isChannelRewardEnabled = isChannelRewardEnabled
# no touch!
def get_args(self, text: str) -> list:
return text.split(" ")[0:self.n_args + 1]
# no touch!
def get_ChannelRewardName(self) -> str:
return self.ChannelRewardName
# no touch!
def get_ChannelRewardType(self):
return self.ChannelRewardType
# no touch!
def get_help(self):
return self.help
# no touch!
def is_ChannelReward_enabled(self):
return self.isChannelRewardEnabled
@abstractmethod
def do_ChannelReward(self, source, user, command, rewardPrompt, userInput, bonusData):
pass

View File

@ -0,0 +1,79 @@
import importlib
import importlib.util
import inspect
import os
import sys
from typing import Dict
from channel_rewards.channelRewards_base import AbstractChannelRewards
#New
def load_rewards(channelRewardsType: AbstractChannelRewards.ChannelRewardsType) -> Dict[str, AbstractChannelRewards]:
print(" -Loading ", channelRewardsType ," ChannelRewards...\n")
ChannelRewards = compile_and_load(channelRewardsType)
return ChannelRewards
#New
def compile_and_load_file(path: str, channelRewardsType: AbstractChannelRewards.ChannelRewardsType):
module_name = os.path.split(path)[1].replace(".py", "")
spec = importlib.util.spec_from_file_location(module_name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.load_module(module_name)
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and name.startswith("ChannelReward"):
ChannelReward_inst = obj()
if channelRewardsType == ChannelReward_inst.get_ChannelRewardType():
print(" ---Successfully loaded %s: %s" % (channelRewardsType, ChannelReward_inst.get_ChannelRewardName()))
return ChannelReward_inst.get_ChannelRewardName(), ChannelReward_inst
elif channelRewardsType != ChannelReward_inst.get_ChannelRewardType():
print(" -%s ChannelRewardsType did not match: %s for: %s" % (ChannelReward_inst.get_ChannelRewardType(), channelRewardsType, ChannelReward_inst.get_ChannelRewardName()))
return "", None
#New
def compile_and_load(ChannelRewardType: AbstractChannelRewards.ChannelRewardsType) -> Dict[str, AbstractChannelRewards]:
dic = {}
implementations = get_implementations_dir()
for dirName, subdirList, fileList in os.walk(implementations):
for file in fileList:
name = os.path.join(dirName, file)
print("compiling: %s" % name)
name, reward = compile_and_load_file(name, ChannelRewardType)
if reward is not None and reward.ChannelRewardType is ChannelRewardType:
dic[name] = reward
break
return dic
def get_base_dir() -> str:
cwd = os.getcwd()
split = os.path.split(cwd)
current = split[len(split) - 1]
if current == 'channel_rewards':
return check_dir(cwd)
elif current == 'Praxis_Bot' or current == 'Praxis':
return check_dir(os.path.join(cwd, "channel_rewards"))
else:
print("could not find working directory for Praxis_Bot/channel_rewards")
raise Exception
def get_implementations_dir() -> str:
return check_dir(os.path.join(get_base_dir(), "implemented"))
def get_compiled_dir() -> str:
return check_dir(os.path.join(get_base_dir(), "compiled"))
def check_dir(path: str) -> str:
if not os.path.exists(path):
os.mkdir(path, 0x777)
return path
if __name__ == "__main__":
rewards = load_rewards()

View File

@ -0,0 +1,97 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_Hydration(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the hydration reward.
"""
ChannelRewardName = "Hydrate"
def __init__(self):
super().__init__(ChannelReward_Hydration.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a hydration channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
try:
if self.is_ChannelReward_enabled:
thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
if self.is_ChannelReward_enabled:
thread_ = threading.Thread(target=self.send_TTS, args=("", "Silly Nerd Fix The Lights Module"))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
try:
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(rewardPrompt)
thread_ = threading.Thread(target=self.send_TTS, args=(user, prompt_))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = ["I demand you drink at once!", "I reccomend you drink some water oowu!", "Get a bucket and a mop cuz you need hydration!", "Hi, I think you look dehydrated, so go get some water!", "Thirsty streamer needs some water!"]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,88 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_RubiksCube(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the hydration reward.
"""
ChannelRewardName = "Solve a Rubiks Cube"
def __init__(self):
super().__init__(ChannelReward_RubiksCube.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a rubiks cube reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#self.send_Lights_Command(user, 16, "!lights rubikscube", "")
try:
if self.is_ChannelReward_enabled:
thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights rubikscube", ""))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(rewardPrompt)
thread_ = threading.Thread(target=self.send_TTS, args=(user, prompt_))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = [""]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_Suggest_Poll(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the Suggest a Poll reward.
"""
ChannelRewardName = "Suggest a Poll"
def __init__(self):
super().__init__(ChannelReward_Suggest_Poll.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a TTS channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
# thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
# thread_.daemon = True
# self.threads.append(thread_)
# thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase("wants to run a poll about,")
thread_ = threading.Thread(target=self.send_TTS, args=("",user + prompt_ + userInput))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = ["wants to know other people's thoughts on,", "wants to gauge the room on the topic of,"]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_TTS_Message(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the TTS Message reward.
"""
ChannelRewardName = "Send a TTS Message"
def __init__(self):
super().__init__(ChannelReward_TTS_Message.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a TTS channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
# thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
# thread_.daemon = True
# self.threads.append(thread_)
# thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(rewardPrompt)
thread_ = threading.Thread(target=self.send_TTS, args=(user, userInput))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = [""]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_Workout_Pushups(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the Do 20 push-ups reward.
"""
ChannelRewardName = "Do 20 push-ups"
def __init__(self):
super().__init__(ChannelReward_Workout_Pushups.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a Do 20 push-ups channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
# thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
# thread_.daemon = True
# self.threads.append(thread_)
# thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(" wants The Curious Nerd, to do 20 pushups")
thread_ = threading.Thread(target=self.send_TTS, args=("", user + prompt_))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = [" demands that The Curious Nerd, to do 20 pushups "]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_Workout_Situps(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the Do 20 sit-ups reward.
"""
ChannelRewardName = "Do 20 sit-ups"
def __init__(self):
super().__init__(ChannelReward_Workout_Situps.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a Do 20 sit-ups channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
# thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
# thread_.daemon = True
# self.threads.append(thread_)
# thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(" wants The Curious Nerd, to do 20 sit-ups")
thread_ = threading.Thread(target=self.send_TTS, args=("", user + prompt_))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = [" demands that The Curious Nerd, to do 20 sit-ups "]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_Workout_Squats(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the Do 20 squats reward.
"""
ChannelRewardName = "Do 20 squats"
def __init__(self):
super().__init__(ChannelReward_Workout_Squats.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.channelPoints)
self.help = ["This is a Do 20 squats channel point reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
# thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
# thread_.daemon = True
# self.threads.append(thread_)
# thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase(" wants The Curious Nerd, to do 20 squats")
thread_ = threading.Thread(target=self.send_TTS, args=("", user + prompt_))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = [" demands that The Curious Nerd, to do 20 squats "]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,99 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_TwitchBits(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the hydration reward.
"""
ChannelRewardName = "TwitchBits"
def __init__(self):
super().__init__(ChannelReward_TwitchBits.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.twitch_bits)
self.help = ["This is a TwitchBits reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
#if self.is_ChannelReward_enabled:
#thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights hydration", ""))
#thread_.daemon = True
#self.threads.append(thread_)
#thread_.start()
if self.is_ChannelReward_enabled:
thread_ = threading.Thread(target=self.send_TTS, args=("", user + " showered the stream with " + userInput + " bits and says: " + rewardPrompt))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_bitsAmount(self, dataToParse:dict):
try:
getData = str(dataToParse['data']['message']['data']['bits_used'])
except:
getData = "Error"
return getData
def get_bitsMessage(self, dataToParse:dict):
try:
getData = str(dataToParse['data']['message']['data']['chat_message'])
except:
getData = "Error"
return getData
def get_Phrase(self, defaultRewardPrompt,
phrases = [""]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -0,0 +1,87 @@
from abc import ABCMeta
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import threading
import random
class ChannelReward_TwitchSubs(AbstractChannelRewards, metaclass=ABCMeta):
"""
this is the TwitchSubs reward.
"""
ChannelRewardName = "TwitchSub"
def __init__(self):
super().__init__(ChannelReward_TwitchSubs.ChannelRewardName, n_args=1, ChannelRewardType=AbstractChannelRewards.ChannelRewardsType.twitch_subs)
self.help = ["This is a TwitchSub reward."]
self.isChannelRewardEnabled = True
self.threads = []
def do_ChannelReward(self, source = AbstractChannelRewards.ChannelRewardsSource.default, user = "User", rewardName = "", rewardPrompt = "", userInput = "", bonusData = None):
#print("sending:",user, 16, "!lights hydration")
try:
if self.is_ChannelReward_enabled:
thread_ = threading.Thread(target=self.send_Lights_Command, args=(user, 16, "!lights ravemode", ""))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
if self.is_ChannelReward_enabled:
prompt_ = self.get_Phrase("a funny")
thread_ = threading.Thread(target=self.send_TTS, args=("", user + " is " + prompt_ + " nerd! Thank you for your support!"))
thread_.daemon = True
self.threads.append(thread_)
thread_.start()
except:
pass
return None
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def get_Phrase(self, defaultRewardPrompt,
phrases = ["an amazing", "a special", "an inquisitive", "a thoughtful", "a curious", "a hyper focusing", "a trend setting", "an artistic"]):
phrases.append(defaultRewardPrompt)
totalPhrases = len(phrases) - 1
targetPhrase = phrases[random.randint(0,totalPhrases)]
return targetPhrase
def get_help(self):
return self.help

View File

@ -16,7 +16,7 @@ class Chyron_Module():
self.addItem( self.addItem(
"WeekDays", "WeekDays",
"► Weekdays: ", "► Weekdays: ",
"Daily Streams @ 12pm Noon EST") "Daily Dev Streams starting around 12pm Noon EST")
self.addItem( self.addItem(
"FriSat", "FriSat",
"► Friday & Saturday: ", "► Friday & Saturday: ",
@ -24,18 +24,18 @@ class Chyron_Module():
self.addItem( self.addItem(
"Commands", "Commands",
"► Commands: ", "► Commands: ",
"!animal, !climateclock, !discord, !lights, !page, !roll") "!animal, !climateclock, !discord, !lights, !roll")
self.addItem( #self.addItem(
"Website", # "Website",
"► Want to read about my various projects? visit: ", # "► Want to read about my various projects? visit: ",
"TheCuriousNerd.com") # "TheCuriousNerd.com")
self.addItem( self.addItem(
"Follow", "Follow",
"", "",
"If you like what you see, hit that follow button to see more!") "If you like what you see and want more, hit the follow button to see more!")
self.addItem( self.addItem(
"Discord", "Discord",
"Want to join our discord? type \" !d \" in chat to get the link or visit: ", "Need help with Praxis Bot or one of our other projects? (or for memes) Join our discord! Type: \" !d \" in chat to get the link or visit: ",
"discord.io/thecuriousnerd") "discord.io/thecuriousnerd")
def chyron_stringUpdater(self): def chyron_stringUpdater(self):

View File

@ -17,6 +17,13 @@ class AbstractCommand(metaclass=ABCMeta):
Praxis = auto() Praxis = auto()
TWITCH = auto() TWITCH = auto()
DISCORD = auto() DISCORD = auto()
Ver2 = auto()
class CommandSource(Enum):
default = 0
Praxis = 1
Twitch = 2
Discord = 3
def __init__(self, command: str, n_args: int = 0, command_type=CommandType.NONE, helpText:list=["No Help"], CommandEnabled = True): def __init__(self, command: str, n_args: int = 0, command_type=CommandType.NONE, helpText:list=["No Help"], CommandEnabled = True):
self.command = command self.command = command
@ -46,5 +53,5 @@ class AbstractCommand(metaclass=ABCMeta):
return self.isCommandEnabled return self.isCommandEnabled
@abstractmethod @abstractmethod
def do_command(self, bot, twitch_message): def do_command(self, source, user, command, rest, bonusData):
pass pass

View File

@ -0,0 +1,74 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
from json import loads
from urllib.parse import urlencode
import requests
import config
import chyron_module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Command_chyron_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the test command.
"""
command = "!chyron"
def __init__(self):
super().__init__(Command_chyron_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["The chyron string can be generated and updated with this command.",
"\nExample:","chyron update \"RIGHTNOW\""]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = "trying to update chyron..."
praxis_logger_obj.log("\n [" + user + "] Command>: " + command + " " + rest)
for name in config.adminUsers_List:
print(name)
tempName = user.lower()
if name == tempName:
try:
returnString = user + " has updated the chyron!"
chyron_ = chyron_module.Chyron_Module()
chyron_.main(rest)
chyron_.chyron_stringUpdater()
chyron_.updateChyronFile()
except:
returnString = user + " has attempted to update the chyron but an error may have occurred!"
#returnString = chyron_.chyron_computedString
else:
returnString = user + " has attempted to update the chyron but an error may have occurred further on!!!"
return returnString
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return None
def get_help(self):
return self.help

View File

@ -0,0 +1,64 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
from json import loads
from urllib.parse import urlencode
import requests
import config
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Command_lights_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the lights command.
"""
command = "!lights"
def __init__(self):
super().__init__(Command_lights_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["This command allows you to modify the lights via the Lights_Module.",
"\nExample:","lights \"SCENE\"","lights \"COLOR\"","lights \"R\" \"G\" \"B\"","lights \"1\" \"0.5\" \"0\""]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = ""
praxis_logger_obj.log("\n Command>: " + command + rest)
isTwitch = False
if "Twitch_ZZZ" in source: #temp changed for steam change back later
for name in config.allowedCommandsList_TwitchPowerUsers:
print(name)
tempName = user.lower()
if name == tempName:
returnString = self.send_Lights_Command(user, 16, command, rest)
else:
returnString = self.send_Lights_Command(user, 16, command, rest)
return returnString
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return None
def get_help(self):
return self.help

View File

@ -0,0 +1,114 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import random
import utilities_script as utility
class Command_roll_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!roll"
def __init__(self):
super().__init__(Command_roll_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["This will roll dice, based on your inputs.",
"\nExample:","roll \"d20\"", "roll \"1D20+5\"", "roll \"10df\"", "roll \"10Df+3\""]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = user + " sent: [ " + command + " ] with: " + rest
if ("f") in rest.lower():
returnString = self.roll(2, user, command + " " +rest)
else:
returnString = self.roll(1, user, command + " " +rest)
return returnString
def roll(self, roll_type, user, user_message):
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = user_message.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt: str = tempParsedMessage[1]
parsedMessage = temp_dice_stmt.lower().split("d")
loopBool: bool = False
if parsedMessage[0] != "":
loopBool = True
if loopBool == True:
if int(parsedMessage[0]) == 1:
loopBool = False
if roll_type == 1:
print("-rolling...")
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(1, int(parsedMessage[1]))) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(1, int(parsedMessage[1])) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = user + " rolled: " + diceRoll
if roll_type == 2:
print("-fate Rolling....")
# !roll 4df
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(-1, 1)) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(-1, 1) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = user + " fate rolled: " + diceRoll
return diceRoll
def get_help(self):
return self.help

View File

@ -0,0 +1,25 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import utilities_script as utility
class Command_test_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the test command.
"""
command = "testerino"
def __init__(self):
super().__init__(Command_test_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["This is a test command.",
"\nExample:","testerino"]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = user + " sent: [ " + command + " ] with: " + rest
#print(returnString)
return returnString
def get_help(self):
return self.help

View File

@ -0,0 +1,124 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
from json import loads
from urllib.parse import urlencode
import requests
import config
import tempText_Module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Command_Text_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the text command.
"""
command = "!text"
def __init__(self):
super().__init__(Command_Text_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["The temptext string can be generated and updated with this command.",
"\nExample:","temptext update \"Name\" \"Title\" \"Content\""]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = "trying to update text..."
praxis_logger_obj.log("\n Command>: " + command + " " + rest)
returnString = user + " has attempted to update the text but an error may have occurred!"
for name in config.adminUsers_List:
print(name)
tempName = user.lower()
if name == tempName:
#try:
# returnString = user + " has updated the text!"
# tempText_ = tempText_Module.tempText_Module()
# tempText_.main()
# testItem = tempText_Module.tempTextItem("testy","► ", rest)
# tempText_.makeItem(testItem)
# tempText_.update_tempTextFiles()
#except:
# returnString = user + " has attempted to update the text but an error may have occurred!"
#returnString = chyron_.chyron_computedString
bandaid_string:str = command + " " + rest
tempParsedMessage = bandaid_string.split(" ")
i = len(tempParsedMessage)
if i > 2:
if "update" in tempParsedMessage[1]:
tempTextModule:tempText_Module.tempText_Module = tempText_Module.tempText_Module()
tempText:tempText_Module.tempTextItem = tempText_Module.tempTextItem()
if i > 2:
newText = ""
counter = 0
for word in tempParsedMessage:
if counter > 2:
newText = newText + word + " "
counter = counter + 1
newText = newText[:-1] # Gets rid of last space
#print(tempParsedMessage[2], newText)
tempText.itemName = tempParsedMessage[2]
tempText.itemContent = newText
tempTextModule.makeItem(tempText)
returnString = user + " has updated the text!"
else:
returnString = user + " has attempted to update the text but an error may have occurred!"
#tempTextModule.update_tempTextFiles()
if "chyron" in tempParsedMessage[1]:
tempTextModule:tempText_Module.tempText_Module = tempText_Module.tempText_Module()
tempText:tempText_Module.tempTextItem = tempText_Module.tempTextItem()
if i > 1:
newText = ""
counter = 0
for word in tempParsedMessage:
if counter > 1:
newText = newText + word + " "
counter = counter + 1
newText = newText[:-1] # Gets rid of last space
#print(tempParsedMessage[2], newText)
tempText.itemName = tempParsedMessage[1]
if len(newText) < 180:
#for x in range(120 - len(newText)):
# newText = newText + " "
while len(newText) < 180:
newText = newText + " "
tempText.itemContent = newText
tempTextModule.makeItem(tempText)
returnString = user + " has updated the chyron text!"
else:
returnString = user + " has attempted to update the text but an error may have occurred!"
#tempTextModule.update_tempTextFiles()
return returnString
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return None
def get_help(self):
return self.help

View File

@ -0,0 +1,104 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
from json import loads
from urllib.parse import urlencode
from urllib.parse import parse_qs
import requests
import re
import config
import discord
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Command_tts_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the tts command.
"""
command = "!tts"
def __init__(self):
super().__init__(Command_tts_v2.command, n_args=1, command_type=AbstractCommand.CommandType.Ver2)
self.help = ["This command allows you to do tts.",
"\nExample:","tts \"TEXT\""]
self.isCommandEnabled = True
def do_command(self, source = AbstractCommand.CommandSource.default, user:str = "User", command = "", rest = "", bonusData = None):
returnString = user + " sent a tts command!"
praxis_logger_obj.log("\n Command>: " + command + rest)
if "Twitch" in source:
for name in config.allowedTTS_List:
print(name)
tempName = user.lower()
if name == tempName:
self.send_TTS(user, rest)
elif "Discord" in source:
for name in config.allowedTTS_List:
print(name)
tempNick = self.contains_value("(?<=nick=')[^']+", bonusData)
tempName = user.lower()
if name == tempName:
self.send_TTS(tempNick, rest)
else:
returnString = self.send_TTS(user, rest)
#for name in config.allowedCommandsList_TwitchPowerUsers:
#print(name)
#tempName = user.lower()
#if name == tempName:
#self.send_TTS(user, rest)
return returnString
def send_Lights_Command(self, username, light_group, command, rest):
# todo need to url-escape command and rest
params = urlencode({'user_name': username, 'light_group': light_group, 'command': command, 'rest':rest})
#standalone_lights
url = "http://standalone_lights:42042/api/v1/exec_lights?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return None
def send_TTS(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
#data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def contains_value(self, search: str, data:str):
contains = re.search(search, data)
return contains.group(0)
def get_help(self):
return self.help

View File

@ -1,48 +0,0 @@
from abc import ABCMeta
import chyron_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandChyron(AbstractCommand, metaclass=ABCMeta):
"""
this is the chyron command.
"""
command = "chyron"
def __init__(self):
super().__init__(CommandChyron.command, n_args=5, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["The chyron string can be generated and updated with this command.",
"\nExample:","chyron update \"RIGHTNOW\""]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
tempBool = True
if tempBool == True:
tempParsedMessage = user_message.message.split(" ")
i = len(tempParsedMessage)
if i > 2:
if "update" in tempParsedMessage[1]:
chyron = chyron_module.Chyron_Module()
if i > 2:
rightNow = ""
counter = 0
for word in tempParsedMessage:
if counter > 1:
rightNow = rightNow + word + " "
counter = counter + 1
rightNow = rightNow[:-1]
chyron.main(rightNow)
else:
chyron.main()
chyron.updateChyronFile()
returnMessage = "@" + user_message.user + " updated the chyron!\n"
bot.return_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,23 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import utilities_script as utility
class Command_Clear(AbstractCommand, metaclass=ABCMeta):
"""
this is the clear command.
"""
command = "clear"
def __init__(self):
super().__init__(Command_Clear.command, n_args=1, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["This is a command to clear the screen.",
"\nExample:","clear"]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
utility.clearScreen()
def get_help(self):
return self.help

View File

@ -1,25 +0,0 @@
from abc import ABCMeta
import time
from commands.command_base import AbstractCommand
class Command_Exit(AbstractCommand, metaclass=ABCMeta):
"""
this is the exit command.
"""
command = "exit"
def __init__(self):
super().__init__(Command_Exit.command, n_args=1, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["This is a command to exit [User Module].",
"\nExample:","exit"]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
bot.return_message("\nQuitting [User Module] Interface...")
time.sleep(0.2)
bot.inputLoop = False
def get_help(self):
return self.help

View File

@ -1,49 +0,0 @@
from abc import ABCMeta
import help_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class Command_Help(AbstractCommand, metaclass=ABCMeta):
"""
this is the help command.
"""
command = "help"
def __init__(self):
super().__init__(Command_Help.command, n_args=5, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["This is a command to learn more about other commands.",
"\nExample:","help \"COMMAND\""]
self.isCommandEnabled = True
self.blockDecor = "\n================================================================\n"
def do_command(self, bot, user_message):
tempBool = True
if tempBool == True:
tempParsedMessage = user_message.message.split(" ")
i = len(tempParsedMessage)
if i > 1:
targetCommand = bot.commands[tempParsedMessage[1]]
helper = help_module.Help_Module_.help_command_response(targetCommand, help_module.help_command_responseType.fancy)
returnMessage = "\n" + helper.response
bot.return_message(returnMessage)
elif i == 1:
commandsList = "\n" + self.blockDecor + "Commands List:" + self.blockDecor + self.GetCommandsList(bot) + self.blockDecor
bot.return_message(commandsList)
def GetCommandsList(self, bot):
commandsList = ""
i = 0
for cmd in bot.commands:
commandsList = commandsList + cmd + "\n"
return commandsList
def get_help(self):
return self.help

View File

@ -1,139 +0,0 @@
from abc import ABCMeta
import lights_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandLights_Praxis(AbstractCommand, metaclass=ABCMeta):
"""
this is the lights command.
"""
command = "lights"
def __init__(self):
super().__init__(CommandLights_Praxis.command, n_args=3, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["This command allows you to modify the lights via the Lights_Module.",
"\nExample:","lights \"SCENE\"","lights \"COLOR\"","lights \"R\" \"G\" \"B\"","lights \"1\" \"0.5\" \"0\""]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
tempBool = True
if tempBool == True:
LightModule = lights_module.Lights_Module()
LightModule.main()
#bot.return_message("\nRGB Command Detected!")
tempParsedMessage = user_message.message.split(" ")
sceneCommand = False
if (len(tempParsedMessage)) > 2:
bot.return_message("RGB Command!")
rgb_r = float(tempParsedMessage[1])
rgb_g = float(tempParsedMessage[2])
rgb_b = float(tempParsedMessage[3])
xy_result = LightModule.rgb_to_xy(rgb_r, rgb_g, rgb_b)
#bot.return_message("got XY")
LightModule.bridge_.set_group(16, "xy", xy_result)
bot.return_message("sent color to [Lights_Module]")
else:
if "stream" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "Stream")
elif "normal" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "Bright")
elif "haxor" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "hacker vibes")
elif "off" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.set_group("Downstairs", "on", False)
elif "on" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.set_group("Downstairs", "on", True)
elif "ravemode" in tempParsedMessage:
sceneCommand = True
LightModule.raveMode()
else:
bot.return_message("Color Command!")
xy_result = LightModule.color_string_parser(tempParsedMessage)
#bot.return_message("got XY")
LightModule.bridge_.set_group(16, "xy", xy_result)
bot.return_message("sent color to [Lights_Module]")
if sceneCommand == True:
bot.return_message("Scene Command!")
returnMessage = "@" + user_message.user.name + " changed the light's color!\n"
bot.return_message(returnMessage)
def get_help(self):
return self.help
class CommandLights_Twitch(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!lights"
def __init__(self):
super().__init__(CommandLights_Twitch.command, n_args=3, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["This command allows you to modify the lights via the Lights_Module.",
"\nExample:","!lights \"SCENE\"","!lights \"COLOR\"","!lights \"R\" \"G\" \"B\"","!lights \"1\" \"0.5\" \"0\""]
self.isCommandEnabled = True
def do_command(self, bot, twitch_message):
if bot.allow_rgbLightControl == True:
LightModule = lights_module.Lights_Module()
LightModule.main()
#print("\nRGB Command Detected!")
tempParsedMessage = twitch_message.text.split(" ")
sceneCommand = False
if (len(tempParsedMessage)) > 2:
print("RGB Command!")
rgb_r = float(tempParsedMessage[1])
rgb_g = float(tempParsedMessage[2])
rgb_b = float(tempParsedMessage[3])
xy_result = LightModule.rgb_to_xy(rgb_r, rgb_g, rgb_b)
#print("got XY")
LightModule.bridge_.set_group(16, "xy", xy_result)
print("sent color to [Lights_Module]")
else:
if "stream" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "Stream")
elif "normal" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "Bright")
elif "haxor" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.run_scene("Downstairs", "hacker vibes")
elif "off" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.set_group("Downstairs", "on", False)
elif "on" in tempParsedMessage:
sceneCommand = True
LightModule.bridge_.set_group("Downstairs", "on", True)
elif "ravemode" in tempParsedMessage:
sceneCommand = True
LightModule.raveMode()
else:
print("Color Command!")
xy_result = LightModule.color_string_parser(tempParsedMessage)
#print("got XY")
LightModule.bridge_.set_group(16, "xy", xy_result)
print("sent color to [Lights_Module]")
if sceneCommand == True:
print("Scene Command!")
returnMessage = "@" + twitch_message.sender + " changed the light's color!\n"
bot.send_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,47 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
import utilities_script as utilities
class CommandTTS_Twitch(AbstractCommand, metaclass=ABCMeta):
command = "!restart"
def __init__(self):
super().__init__(CommandTTS_Twitch.command, n_args=0, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
def do_command(self, bot, twitch_message):
args = self.get_args(twitch_message.text)
if twitch_message.sender.lower() == twitch_message.channel:
bot.send_message("Bot restarting...")
utilities.restart_self()
def get_help(self):
return self.help
class CommandTTS_Discord(AbstractCommand, metaclass=ABCMeta):
command = "//restart"
def __init__(self):
super().__init__(CommandTTS_Discord.command, n_args=0, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
async def do_command(self, bot, discord_message: discord.message):
if str(discord_message.author.top_role) == "Admin":
print("Admin Check")
#response = str("Bot restarting... on %s" % discord_message.guild.name)
response = str("Bot restarting...")
await bot.send_message(discord_message, response)
utilities.restart_self()
def get_help(self):
return self.help

View File

@ -1,359 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import random
from discord import message
import discord
import discord.message
import discord.channel
class CommandRoll_Praxis(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "roll"
def __init__(self):
super().__init__(CommandRoll_Praxis.command, n_args=1, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["This will roll dice, based on your inputs.",
"\nExample:","roll \"d20\"", "roll \"1D20+5\"", "roll \"10df\"", "roll \"10Df+3\""]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
#print("roll Detected")
#message.chat.send("test acknowledged")
diceRoll: str = ""
bot.return_message("\nRolling Dice...")
#print("Rolling Dice...")
if ("f") in user_message.message.lower():
diceRoll = self.roll(2, user_message)
else:
diceRoll = self.roll(1, user_message)
bot.return_message(diceRoll)
def roll(self, roll_type, user_message):
user = str(user_message.user.name)
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = user_message.message.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt: str = tempParsedMessage[1]
parsedMessage = temp_dice_stmt.lower().split("d")
loopBool: bool = False
if parsedMessage[0] != "":
loopBool = True
if loopBool == True:
if int(parsedMessage[0]) == 1:
loopBool = False
if roll_type == 1:
print("-rolling...")
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(1, int(parsedMessage[1]))) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(1, int(parsedMessage[1])) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + user + " rolled: " + diceRoll
if roll_type == 2:
print("-fate Rolling....")
# !roll 4df
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(-1, 1)) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(-1, 1) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + user + " fate rolled: " + diceRoll
return diceRoll + "\n"
def get_help(self):
return self.help
class CommandRoll_Twitch(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!roll"
def __init__(self):
super().__init__(CommandRoll_Twitch.command, n_args=1, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
def do_command(self, bot, message):
print("!roll Detected")
#message.chat.send("test acknowledged")
diceRoll: str = ""
bot.send_message("Rolling Dice...")
print("Rolling Dice...")
if ("f") in message.text.lower():
diceRoll = self.roll(2, message)
else:
diceRoll = self.roll(1, message)
bot.send_message(diceRoll)
def roll(self, roll_type, message):
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = message.text.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt: str = tempParsedMessage[1]
parsedMessage = temp_dice_stmt.lower().split("d")
loopBool: bool = False
if parsedMessage[0] != "":
loopBool = True
if loopBool == True:
if int(parsedMessage[0]) == 1:
loopBool = False
if roll_type == 1:
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(1, int(parsedMessage[1]))) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(1, int(parsedMessage[1])) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + message.sender + " rolled: " + diceRoll
print(diceRoll)
if roll_type == 2:
print("fate Rolling....")
# !roll 4df
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(-1, 1)) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(-1, 1) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + message.sender + " fate rolled: " + diceRoll
print(diceRoll)
return diceRoll
def get_help(self):
return self.help
class CommandRoll_Discord(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!roll"
def __init__(self):
super().__init__(CommandRoll_Discord.command, n_args=1, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
async def do_command(self, bot, message: discord.Message):
print("!roll Detected")
#message.chat.send("test acknowledged")
diceRoll: str = ""
await bot.send_message(message, "Rolling Dice...")
#await message.channel.send("Rolling Dice...")
print("Rolling Dice...")
if ("f") in message.content.lower():
diceRoll = await self.roll(2, message)
else:
diceRoll = await self.roll(1, message)
await bot.send_message(message, diceRoll)
#await message.channel.send(diceRoll)
async def roll(self, roll_type, message: discord.Message):
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = message.content.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt: str = tempParsedMessage[1]
parsedMessage = temp_dice_stmt.lower().split("d")
loopBool: bool = False
if parsedMessage[0] != "":
loopBool = True
if loopBool == True:
if int(parsedMessage[0]) == 1:
loopBool = False
if roll_type == 1:
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(1, int(parsedMessage[1]))) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(1, int(parsedMessage[1])) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = message.author.mention + " rolled: " + diceRoll
print(diceRoll)
if roll_type == 2:
print("fate Rolling....")
# !roll 4df
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
for x in range(int(parsedMessage[0])):
rolls.append(random.randint(-1, 1)) # This is the roller
rollTotal = 0
for roll in rolls:
rollTotal = rollTotal + roll
diceRoll = diceRoll + str(roll) + ", "
diceRoll = diceRoll[:-2] # This removes the last two characters in the string
if len(temp_preParsedMessage) == 2:
diceRoll = diceRoll + " + " + temp_preParsedMessage[1] + " = " + str(
rollTotal + int(temp_preParsedMessage[1]))
else:
diceRoll = diceRoll + " = " + str(rollTotal)
# If roll is in dx+x format
if loopBool == False:
roll: int = random.randint(-1, 1) # This is the roller
if len(temp_preParsedMessage) == 2:
diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = message.author.mention + " fate rolled: " + diceRoll
print(diceRoll)
return diceRoll
def get_help(self):
return self.help

View File

@ -1,47 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
import utilities_script as utilities
class ShutdownCommand_Twitch(AbstractCommand, metaclass=ABCMeta):
command = "!shutdown"
def __init__(self):
super().__init__(ShutdownCommand_Twitch.command, n_args=0, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
def do_command(self, bot, twitch_message):
args = self.get_args(twitch_message.text)
if twitch_message.sender.lower() == twitch_message.channel:
bot.send_message("Bot shutting down...")
utilities.hard_shutdown()
def get_help(self):
return self.help
class ShutdownCommand_Discord(AbstractCommand, metaclass=ABCMeta):
command = "//shutdown"
def __init__(self):
super().__init__(ShutdownCommand_Discord.command, n_args=0, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
async def do_command(self, bot, discord_message: discord.message):
if str(discord_message.author.top_role) == "Admin":
print("Admin Check")
#response = str("Bot restarting... on %s" % discord_message.guild.name)
response = str("Bot shutting down...")
await bot.send_message(discord_message, response)
utilities.hard_shutdown()
def get_help(self):
return self.help

View File

@ -1,52 +0,0 @@
from abc import ABCMeta
import tempText_Module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandChyron(AbstractCommand, metaclass=ABCMeta):
"""
this is the temptext command.
"""
command = "temptext"
def __init__(self):
super().__init__(CommandChyron.command, n_args=5, command_type=AbstractCommand.CommandType.Praxis)
self.help = ["The temptext string can be generated and updated with this command.",
"\nExample:","temptext update \"Name\" \"Title\" \"Content\""]
self.isCommandEnabled = True
def do_command(self, bot, user_message):
tempBool = True
if tempBool == True:
tempParsedMessage = user_message.message.split(" ")
i = len(tempParsedMessage)
if i > 2:
if "update" in tempParsedMessage[1]:
tempTextModule = tempText_Module.tempText_Module()
tempText = tempText_Module.tempTextItem()
if i > 2:
newText = ""
counter = 0
for word in tempParsedMessage:
if counter > 2:
newText = newText + word + " "
counter = counter + 1
newText = newText[:-1] # Gets rid of last space
#print(tempParsedMessage[2], newText)
tempText.itemName = tempParsedMessage[2]
tempText.itemContent = newText
tempTextModule.makeItem(tempText)
else:
tempText.main()
#tempTextModule.update_tempTextFiles()
returnMessage = "@" + user_message.user.name + " updated the temptextFiles!\n"
bot.return_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,23 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
class CommandTest(AbstractCommand, metaclass=ABCMeta):
"""
this is a test command. and a poor excuse for a git commit.
"""
command = "!test"
def __init__(self):
super().__init__(CommandTest.command, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
def do_command(self, bot, twitch_message):
print("!test Detected")
bot.send_message("testing acknowledged")
def get_help(self):
return self.help

View File

@ -1,59 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
class CommandTTS_Twitch(AbstractCommand, metaclass=ABCMeta):
command = "!tts"
def __init__(self):
super().__init__(CommandTTS_Twitch.command, n_args=1, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
def do_command(self, bot, twitch_message):
args = self.get_args(twitch_message.text)
if args[1] == "start":
if twitch_message.sender.lower() == twitch_message.channel:
bot.send_message("tts activated on #%s" % twitch_message.channel)
bot.tts_enabled = True
elif args[1] == "stop":
if twitch_message.sender.lower() == twitch_message.channel:
bot.send_message("tts deactivated on #%s" % twitch_message.channel)
bot.tts_enabled = False
def get_help(self):
return self.help
class CommandTTS_Discord(AbstractCommand, metaclass=ABCMeta):
command = "//tts"
def __init__(self):
super().__init__(CommandTTS_Discord.command, n_args=1, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
self.isCommandEnabled = True
async def do_command(self, bot, discord_message: discord.message):
args = self.get_args(discord_message.content)
if args[1] == "start":
print(discord_message.author.top_role)
print("start detected")
if str(discord_message.author.top_role) == "Admin":
print("Admin Check")
response = str("tts activated on %s" % discord_message.guild.name)
await bot.send_message(discord_message, response)
bot.tts_enabled = True
elif args[1] == "stop":
print("stop detected")
if str(discord_message.author.top_role) == "Admin":
print("Admin Check")
response = str("tts deactivated on %s" % discord_message.guild.name)
await bot.send_message(discord_message, response)
bot.tts_enabled = False
def get_help(self):
return self.help

View File

@ -8,32 +8,14 @@ from typing import Dict
from commands.command_base import AbstractCommand from commands.command_base import AbstractCommand
def load_commands() -> Dict[str, AbstractCommand]:
commands = compile_and_load()
return commands
#New #New
def load_commands_new(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]: def load_commands(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]:
print(" -Loading ", commandType ," Commands...\n") print(" -Loading ", commandType ," Commands...\n")
commands = compile_and_load_new(commandType) commands = compile_and_load(commandType)
return commands return commands
def compile_and_load_file(path: str) -> (str, AbstractCommand):
module_name = os.path.split(path)[1].replace(".py", "")
spec = importlib.util.spec_from_file_location(module_name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.load_module(module_name)
for name, obj in inspect.getmembers(module):
if inspect.isclass(obj) and name.startswith("Command"):
command_inst = obj()
print("Successfully loaded %s: %s" % (name, command_inst.get_command()))
return command_inst.get_command(), command_inst
return "", None
#New #New
def compile_and_load_file_new(path: str, commandType: AbstractCommand.CommandType) -> (str, AbstractCommand): def compile_and_load_file(path: str, commandType: AbstractCommand.CommandType):
module_name = os.path.split(path)[1].replace(".py", "") module_name = os.path.split(path)[1].replace(".py", "")
spec = importlib.util.spec_from_file_location(module_name, path) spec = importlib.util.spec_from_file_location(module_name, path)
module = importlib.util.module_from_spec(spec) module = importlib.util.module_from_spec(spec)
@ -50,28 +32,16 @@ def compile_and_load_file_new(path: str, commandType: AbstractCommand.CommandTyp
print(" -%s CommandType did not match: %s for: %s" % (command_inst.get_commandType(), commandType, command_inst.get_command())) print(" -%s CommandType did not match: %s for: %s" % (command_inst.get_commandType(), commandType, command_inst.get_command()))
return "", None return "", None
def compile_and_load() -> Dict[str, AbstractCommand]:
dic = {}
implementations = get_implementations_dir()
for dirName, subdirList, fileList in os.walk(implementations):
for file in fileList:
name = os.path.join(dirName, file)
print("compiling: %s" % name)
name, command = compile_and_load_file(name)
if command is not None:
dic[name] = command
break
return dic
#New #New
def compile_and_load_new(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]: def compile_and_load(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]:
dic = {} dic = {}
implementations = get_implementations_dir() implementations = get_implementations_dir()
for dirName, subdirList, fileList in os.walk(implementations): for dirName, subdirList, fileList in os.walk(implementations):
for file in fileList: for file in fileList:
name = os.path.join(dirName, file) name = os.path.join(dirName, file)
print("compiling: %s" % name) print("compiling: %s" % name)
name, command = compile_and_load_file_new(name, commandType) name, command = compile_and_load_file(name, commandType)
if command is not None and command.command_type is commandType: if command is not None and command.command_type is commandType:
dic[name] = command dic[name] = command
break break

View File

@ -3,49 +3,35 @@ import badwords as badwords
credentialsNickname = "praxis_bot" credentialsNickname = "praxis_bot"
twitch_module: bool = False
discord_module: bool = False
test_module: bool = False test_module: bool = False
user_module: bool = True user_module: bool = True
autoJoin_TwitchChannel = "thecuriousnerd"
autoJoin_TwitchChannels = ["thecuriousnerd"] autoJoin_TwitchChannels = ["thecuriousnerd"]
whitelisted_TwitchPowerUsers = ["thecuriousnerd"] allowedCommandsList_TwitchPowerUsers = ["thecuriousnerd", "lakotor", "blastofcynicism", "theredpoint"]
allowedTTS_List = ["thecuriousnerd", "lakotor", "blastofcynicism", "theredpoint", "<@76078763984551936>", "<@!76078763984551936>"]
adminUsers_List = ["thecuriousnerd", "<@!76078763984551936>"]
#Twitch Module Configs #Twitch Module Configs
block_TwitchChannelsMessaging = [""] # Blocks the ability to send messages to twitch channels block_TwitchChannelsMessaging = [""] # Blocks the ability to send messages to twitch channels
blockAll_TwitchChatChannelsMessaging = False # Blocks the ability to send messages to twitch channels blockAll_TwitchChatChannelsMessaging = False # Blocks the ability to send messages to twitch channels
autoEnabled_TwitchChannelsTTS = False autoEnabled_TwitchTTS = False # Enables TTS for ALL
block_TwitchChannelsTTS = [""] # block supersedes the tts_enabled bool autoEnabled_TwitchTTS_SpeakersList_Only = False # Enables TTS for Allowed TTS List Only
blockAll_TwitchChatChannelsTTS = False # blockAll supersedes the force bool and force list and tts_enabled bool
force_TwitchChannelsTTS = [""] # force supersedes the block list
forceAll_TwitchChatChannelsTTS = False # forceAll supersedes the blockAll bool and block list and force list
blockAll_TTS_URL_Twitch = True
autoEnabled_Twitch_rgbLightControl = False
twitch_defaultCommandEnabledState = True
#twitch_defaultCommandEnabledState_liveStreamOnly = True # If true this will make commands only available during live streams.
#Discord Module Configs #Discord Module Configs
block_DiscordChannelsMessaging = [""] # Blocks the ability to send messages to Discord channels block_DiscordChannelsMessaging = [""] # Blocks the ability to send messages to Discord channels
blockAll_DiscordChannelsMessaging = False # Blocks the ability to send messages to Discord channels blockAll_DiscordChannelsMessaging = False # Blocks the ability to send messages to Discord channels
blockAll_DiscordPrivateMessaging = False # Private Messaging not yet implemented blockAll_DiscordPrivateMessaging = False # Private Messaging not yet implemented
autoEnabled_DiscordChannelsTTS = False
autoEnabled_DiscordChannelsTTS = True
selected_DiscordTTSChannels = ["431129571308339210"] selected_DiscordTTSChannels = ["431129571308339210"]
block_DiscordChannelsTTS = [""] # block supersedes the tts_enabled bool block_DiscordChannelsTTS = [""] # block supersedes the tts_enabled bool
blockAll_DiscordChannelsTTS = False # blockAll supersedes the force bool and force list and tts_enabled bool blockAll_DiscordChannelsTTS = False # blockAll supersedes the force bool and force list and tts_enabled bool
force_DiscordChannelsTTS = [""] # force supersedes the block list force_DiscordChannelsTTS = [""] # force supersedes the block list
forceAll_DiscordChatChannelsTTS = False # forceAll supersedes the blockAll bool and block list and force list forceAll_DiscordChatChannelsTTS = False # forceAll supersedes the blockAll bool and block list and force list
blockAll_TTS_URL_Discord = True
autoEnabled_Discord_rgbLightControl = False
#discord_defaultCommandEnabledState = True
#discord_defaultCommandEnabledState_liveStreamOnly = True # If true this will make commands only available during live streams.
#User Module Configs #User Module Configs
blockAll_TTS_URL_UserModule = True blockAll_TTS_URL_UserModule = True
@ -70,15 +56,18 @@ class FileNameStrategy(Enum):
fileNameStrategy = FileNameStrategy.CONTENT_BASED fileNameStrategy = FileNameStrategy.CONTENT_BASED
#OLD CLASS WILL DELETE
class DBStrategy(Enum): class DBStrategy(Enum):
SQLite = 1 SQLite = 1
MySQL = 2 MySQL = 2
#OLD CONFIGS WILL BE DELETED SOON
dbStrategy = DBStrategy.SQLite #dbStrategy = DBStrategy.SQLite
#TTS Configs #TTS Configs
is_tts_Speaker_Enabled = False
is_tts_URL_Blocked = True
class Speaker(Enum): class Speaker(Enum):
GOOGLE_TEXT_TO_SPEECH = 1 GOOGLE_TEXT_TO_SPEECH = 1
STREAMLABS_API = 2 STREAMLABS_API = 2
@ -153,6 +142,6 @@ PollyVoice = PollyVoices.Justin
#Misc Configs #Misc Configs
slurList = badwords.slurList slurList = badwords.slurList
praxisVersion_Alpha = "A.0 " praxisVersion_Alpha = "0 " #Build
praxisVersion_Delta = "D.1 " praxisVersion_Delta = "1 " #Minor
praxisVersion_Omega = "O.0 " praxisVersion_Omega = "0.8 " #Major

View File

@ -77,7 +77,7 @@ class Cooldown_Module:
targetCD.actionList.append(newAction) targetCD.actionList.append(newAction)
if __name__ == "__main__": if __name__ == "__main__":
testCD = Cooldowns_Module() testCD = Cooldown_Module()
cdName = "test" cdName = "test"
testCD.setupCooldown(cdName, 20, 2) testCD.setupCooldown(cdName, 20, 2)

View File

@ -2,5 +2,9 @@
"username": "something", "username": "something",
"helix": "Helix Client ID", "helix": "Helix Client ID",
"oauth": "token", "oauth": "token",
"v5_client": "Client ID" "v5_client": "Client ID",
"pubsub_client_id": "",
"pubsub_secret": "",
"pubsub_AccessToken": "",
"pubsub_RefreshToken": ""
} }

View File

@ -14,12 +14,16 @@ class Twitch_Credential():
# Helix ID = https://dev.twitch.tv/console/apps # Helix ID = https://dev.twitch.tv/console/apps
# Oauth = https://twitchapps.com/tmi/ # Oauth = https://twitchapps.com/tmi/
# V5 Client ID = https://twitchtokengenerator.com/ # V5 Client ID = https://twitchtokengenerator.com/
def __init__(self, username, helix, oauth, v5_client): def __init__(self, username, helix, oauth, v5_client, pubsub_client_id, pubsub_secret, pubsub_AccessToken, pubsub_RefreshToken):
# super().__init__() # super().__init__()
self.username = username self.username = username
self.helix = helix self.helix = helix
self.oauth = oauth self.oauth = oauth
self.v5_client = v5_client self.v5_client = v5_client
self.pubsub_client_id = pubsub_client_id
self.pubsub_secret = pubsub_secret
self.pubsub_AccessToken = pubsub_AccessToken
self.pubsub_RefreshToken = pubsub_RefreshToken
class Discord_Credential(): class Discord_Credential():

76
docker-compose.yaml Normal file
View File

@ -0,0 +1,76 @@
version: '3.7'
services:
standalone_user_client:
image: standalone_user_client
volumes:
- "./:/Praxis/"
ports:
- 42055:42055
environment:
- ISDOCKER=cat
standalone_eventlog:
image: standalone_eventlog
volumes:
- "./:/Praxis/"
ports:
- 42008:42008
environment:
- ISDOCKER=cat
standalone_command:
image: standalone_command
volumes:
- "./:/Praxis/"
ports:
- 42010:42010
environment:
- ISDOCKER=cat
standalone_channelrewards:
image: standalone_channelrewards
volumes:
- "./:/Praxis/"
ports:
- 42069:42069
environment:
- ISDOCKER=cat
standalone_lights:
image: standalone_lights
volumes:
- "./:/Praxis/"
ports:
- 42042:42042
environment:
- ISDOCKER=cat
standalone_tts_core:
image: standalone_tts_core
volumes:
- "./:/Praxis/"
ports:
- 42064:42064
environment:
- ISDOCKER=cat
standalone_websource:
image: standalone_websource
volumes:
- "./:/Praxis/"
ports:
- 42088:42088
environment:
- ISDOCKER=cat
standalone_twitchscript:
image: standalone_twitchscript
volumes:
- "./:/Praxis/"
environment:
- ISDOCKER=cat
standalone_twitch_pubsub:
image: standalone_twitch_pubsub
volumes:
- "./:/Praxis/"
environment:
- ISDOCKER=cat
standalone_discordscript:
image: standalone_discordscript
volumes:
- "./:/Praxis/"
environment:
- ISDOCKER=cat

View File

@ -0,0 +1,135 @@
from datetime import datetime
import random
import os
import json
import utilities_script as utility
from os import listdir
from os.path import isfile, join
class event_log():
def __init__(self, eventName, eventTime, eventType, eventSender, eventData):
super().__init__()
self.eventName = eventName
self.eventTime = eventTime
self.eventType = eventType
self.eventSender = eventSender
self.eventData = eventData
class Event_Log_Module():
def __init__(self):
super().__init__()
self.Event_Log_List = []
self.Event_Log_FileName_Bonus = "%s_%s_%s-%s_%s_%s_event_log" % (str(datetime.now().year), str(datetime.now().month), str(datetime.now().day),str(datetime.now().hour), str(datetime.now().minute), str(datetime.now().second))
self.Event_Log_FileName = "COMPLETE_event_log"
def main(self):
self.load_HistoricLogs()
def makeFile(self, fileName):
dir = utility.get_dir("event_logs/logs")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = fileName + ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
# with open(real_file_path, 'w') as cred_w:
# #data = json.load(event_log_obj)
# dic = {}
# dic['eventName'] = event_log_obj.eventName
# dic['eventTime'] = str(event_log_obj.eventTime)
# dic['eventType'] = str(event_log_obj.eventType)
# dic['eventData'] = str(event_log_obj.eventData)
# json.dump(dic, cred_w, indent=2)
newList = []
for event in self.Event_Log_List:
newDic = {}
newDic['eventName'] = event.eventName
newDic['eventTime'] = str(event.eventTime)
newDic['eventType'] = str(event.eventType)
newDic['eventSender'] = str(event.eventSender)
newDic['eventData'] = str(event.eventData)
newList.append(newDic)
with open(real_file_path, 'w') as logFile:
json.dump(newList, logFile, indent=2)
def readFile(self, fileName):
dir = utility.get_dir("event_logs/logs")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = fileName + ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
newList = []
with open(real_file_path, 'r') as eventlog_:
data = json.load(eventlog_)
for d in data:
eventName = d['eventName']
eventTime = d['eventTime']
eventType = d['eventType']
eventSender = d['eventSender']
eventData = d['eventData']
foundLog = event_log(eventName, eventTime, eventType, eventSender, eventData)
newList.append(foundLog)
return newList
def deleteFile(self, fileName):
dir = utility.get_dir("event_logs/logs")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = fileName + ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
os.remove(real_file_path)
def get_base_dir(self) -> str:
cwd = os.getcwd()
split = os.path.split(cwd)
current = split[len(split) - 1]
if current == 'event_logs/logs':
return self.check_dir(cwd)
elif current == 'Praxis_Bot' or current == 'Praxis':
return self.check_dir(os.path.join(cwd, "event_logs/logs"))
else:
print("could not find working directory for Praxis_Bot/event_logs/logs")
raise Exception
def get_implementations_dir(self) -> str:
return self.check_dir(os.path.join(self.get_base_dir()))
def check_dir(self, path: str) -> str:
if not os.path.exists(path):
os.mkdir(path, 0x777)
return path
def make_event(self, eventName, eventTime, eventType, eventSender, eventData):
newLog = event_log(eventName, eventTime, eventType, eventSender, eventData)
self.Event_Log_List.append(newLog)
self.makeFile(self.Event_Log_FileName)
self.makeFile(self.Event_Log_FileName_Bonus)
return newLog
def get_recent_logs(self, howFarBack):
newList = []
try:
for event in self.Event_Log_List:
#recentLog = self.Event_Log_List[-x]
newDic = {}
newDic['eventName'] = event.eventName
newDic['eventTime'] = str(event.eventTime)
newDic['eventType'] = str(event.eventType)
newDic['eventSender'] = str(event.eventSender)
newDic['eventData'] = str(event.eventData)
newList.append(newDic)
except:
return newList
return newList
def load_HistoricLogs(self):
try:
self.Event_Log_List = self.readFile(self.Event_Log_FileName)
self.makeFile(self.Event_Log_FileName)
except:
pass

View File

@ -1,7 +1,6 @@
from commands.command_base import AbstractCommand from commands.command_base import AbstractCommand
from enum import Enum from enum import Enum
import config as config import config as config
import db
import commands.loader as command_loader import commands.loader as command_loader
@ -10,7 +9,6 @@ import credentials
class Help_Module(): class Help_Module():
def __init__(self): def __init__(self):
super().__init__() super().__init__()
#self.dbCredential: credentials.DB_Credential
def main(self): def main(self):
print("[Help Module]> help test") print("[Help Module]> help test")
@ -68,7 +66,4 @@ Help_Module_ = Help_Module()
if __name__ == "__main__": if __name__ == "__main__":
testModule = Help_Module() testModule = Help_Module()
#credentials_manager = credentials.Credentials_Module()
#credentials_manager.load_credentials()
#testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
testModule.main() testModule.main()

View File

@ -197,4 +197,4 @@ if __name__ == "__main__":
#testModule.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname) #testModule.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname)
testModule.main() testModule.main()
testModule.raveMode() #testModule.raveMode()

47
main.py
View File

@ -4,8 +4,6 @@
import sys import sys
import time import time
import twitch_script
import discord_script
import test_module import test_module
import user_module import user_module
@ -17,8 +15,6 @@ import credentials
import threading import threading
twitchModule_: twitch_script.Twitch_Module
discordModule_: discord_script.Discord_Module
testModule_: test_module.Test_Module testModule_: test_module.Test_Module
userModule_: user_module.User_Module userModule_: user_module.User_Module
@ -28,31 +24,6 @@ def main(inputArg):
args = utility.get_args(inputArg) args = utility.get_args(inputArg)
def twitch_module_init(dbCert, twitchCert):
print("-init [TWITCH Module]")
twitchModule_.db_manager.setup_engine(dbCert)
twitchModule_.twitchCredential = twitchCert
twitchModule_.tts_enabled = config.autoEnabled_TwitchChannelsTTS
twitchModule_.whitelisted_users = config.whitelisted_TwitchPowerUsers
print("[TWITCH Module]>", "Loading Channels...")
for twitchChannel in config.autoJoin_TwitchChannels:
print("joining twitch channel:", twitchChannel)
twitchModule_.join_channel(None, twitchChannel)
def discord_module_init(dbCert, discordCert):
print("-init [DISCORD Module]")
discordModule_.dbCredential = dbCert
discordModule_.discordCredential = discordCert
discordModule_.tts_enabled = config.autoEnabled_DiscordChannelsTTS
for ttsChannel in config.selected_DiscordTTSChannels:
discordModule_.selected_ttsChannels.append(int(ttsChannel))
discordModule_.main()
def test_module_init(dbCert, Empty): def test_module_init(dbCert, Empty):
print("-init [TEST Module]") print("-init [TEST Module]")
#testModule_.dbCredential = dbCert #testModule_.dbCredential = dbCert
@ -69,15 +40,11 @@ def thread_main():
if not config.skip_splashScreen: if not config.skip_splashScreen:
utility.splashScreen() utility.splashScreen()
global credentials_manager global credentials_manager
global twitchModule_
global discordModule_
global testModule_ global testModule_
global userModule_ global userModule_
credentials_manager = credentials.Credentials_Module() credentials_manager = credentials.Credentials_Module()
twitchModule_ = twitch_script.Twitch_Module()
discordModule_ = discord_script.Discord_Module()
testModule_ = test_module.Test_Module() testModule_ = test_module.Test_Module()
userModule_ = user_module.User_Module() userModule_ = user_module.User_Module()
@ -85,20 +52,6 @@ def thread_main():
dbCert: credentials.DB_Credential = credentials_manager.find_Credential(credentials.DB_Credential, config.credentialsNickname) dbCert: credentials.DB_Credential = credentials_manager.find_Credential(credentials.DB_Credential, config.credentialsNickname)
threads = [] threads = []
if config.twitch_module == True:
twitchCert: credentials.Twitch_Credential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
thread_ = threading.Thread(target=twitch_module_init, args=(dbCert, twitchCert))
thread_.daemon = True
threads.append(thread_)
thread_.start()
if config.discord_module == True:
discordCert: credentials.Discord_Credential = credentials_manager.find_Discord_Credential(config.credentialsNickname)
thread_ = threading.Thread(target=discord_module_init, args=(dbCert, discordCert))
thread_.daemon = True
threads.append(thread_)
thread_.start()
if config.test_module == True: if config.test_module == True:
thread_ = threading.Thread(target=test_module_init, args=(dbCert, None)) thread_ = threading.Thread(target=test_module_init, args=(dbCert, None))
thread_.daemon = True thread_.daemon = True

10
makedockerimages.bat Normal file
View File

@ -0,0 +1,10 @@
docker build --file Dockerfile_standalone_user_client.Dockerfile --tag standalone_user_client .
docker build --file Dockerfile_standalone_eventlog.Dockerfile --tag standalone_eventlog .
docker build --file Dockerfile_standalone_command.Dockerfile --tag standalone_command .
docker build --file Dockerfile_standalone_channelRewards.Dockerfile --tag standalone_channelrewards .
docker build --file Dockerfile_standalone_lights.Dockerfile --tag standalone_lights .
docker build --file Dockerfile_standalone_tts_core.Dockerfile --tag standalone_tts_core .
docker build --file Dockerfile_standalone_websource.Dockerfile --tag standalone_websource .
docker build --file Dockerfile_standalone_DiscordScript.Dockerfile --tag standalone_discordscript .
docker build --file Dockerfile_standalone_TwitchScript.Dockerfile --tag standalone_twitchscript .
docker build --file Dockerfile_standalone_Twitch_Pubsub.Dockerfile --tag standalone_twitch_pubsub .

11
makedockerimages.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
docker build --file Dockerfile_standalone_user_client.Dockerfile --tag standalone_user_client .
docker build --file Dockerfile_standalone_eventlog.Dockerfile --tag standalone_eventlog .
docker build --file Dockerfile_standalone_command.Dockerfile --tag standalone_command .
docker build --file Dockerfile_standalone_channelRewards.Dockerfile --tag standalone_channelrewards .
docker build --file Dockerfile_standalone_lights.Dockerfile --tag standalone_lights .
docker build --file Dockerfile_standalone_tts_core.Dockerfile --tag standalone_tts_core .
docker build --file Dockerfile_standalone_websource.Dockerfile --tag standalone_websource .
docker build --file Dockerfile_standalone_DiscordScript.Dockerfile --tag standalone_discordscript .
docker build --file Dockerfile_standalone_TwitchScript.Dockerfile --tag standalone_twitchscript .
docker build --file Dockerfile_standalone_Twitch_Pubsub.Dockerfile --tag standalone_twitch_pubsub .

70
obsWebSocket.py Normal file
View File

@ -0,0 +1,70 @@
import asyncio
import simpleobsws
import json
loop = asyncio.get_event_loop()
ws = simpleobsws.obsws(host='127.0.0.1', port=4444, password='MYSecurePassword', loop=loop) # Every possible argument has been passed, but none are required. See lib code for defaults.
async def default_request():
await ws.connect() # Make the connection to OBS-Websocket
result = await ws.call('GetVersion') # We get the current OBS version. More request data is not required
print(result) # Print the raw json output of the GetVersion request
await asyncio.sleep(1)
requests = result['available-requests'].split(',')
#data = {'source':'test_source', 'volume':0.5}
#result = await ws.call('SetVolume', data) # Make a request with the given data
#print(result)
await ws.disconnect() # Clean things up by disconnecting. Only really required in a few specific situations, but good practice if you are done making requests or listening to events.
return requests
async def make_custom_request(request, data=None):
await ws.connect() # Make the connection to OBS-Websocket
#result = await ws.call(request) # We get the current OBS version. More request data is not required
#print(result) # Print the raw json output of the GetVersion request
await asyncio.sleep(1)
if not data==None:
#data = {'source':'tinycam', 'volume':0.5}
result = await ws.call(request, data=data) # Make a request with the given data
print(result)
await ws.disconnect() # Clean things up by disconnecting. Only really required in a few specific situations, but good practice if you are done making requests or listening to events.
async def on_event(data):
print('New event! Type: {} | Raw Data: {}'.format(data['update-type'], data)) # Print the event data. Note that `update-type` is also provided in the data
async def on_switchscenes(data):
print("\n===========================================\n\n")
print('Scene switched to "{}". It has these sources: {}'.format(data['scene-name'], data['sources']))
def getRequests():
return loop.run_until_complete(default_request())
def makeRequest(request, data):
loop.run_until_complete(make_custom_request(request, data))
def listenForData():
print("\n\nListener:")
loop = asyncio.get_event_loop()
ws = simpleobsws.obsws(host='127.0.0.1', port=4444, password='MYSecurePassword', loop=loop) # Every possible argument has been passed, but none are required. See lib code for defaults.
loop.run_until_complete(ws.connect())
ws.register(on_event) # By not specifying an event to listen to, all events are sent to this callback.
ws.register(on_switchscenes, 'SwitchScenes')
loop.run_forever()
if __name__ == "__main__":
#print("\n\nRequests:")
#loop.run_until_complete(get_requests())
#makeRequest("ToggleStudioMode")
#listenForData()
pass

12
praxis bot.code-workspace Normal file
View File

@ -0,0 +1,12 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"cSpell.words": [
"unlisten"
]
}
}

2
praxis-main-start.bat Normal file
View File

@ -0,0 +1,2 @@
cd "c:\praxis"
docker-compose up -d

2
praxis-main-stop.bat Normal file
View File

@ -0,0 +1,2 @@
cd "c:\praxis"
docker-compose down

View File

@ -1,2 +0,0 @@
cd "c:\praxis"
python "c:/Praxis/main.py"

2
praxis-tts-speaker.bat Normal file
View File

@ -0,0 +1,2 @@
cd "c:\praxis"
python "c:\praxis\standalone_tts_speaker.py"

2
praxis-tts-speaker.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/bash
python "c:\praxis\standalone_tts_speaker.py"

View File

@ -1,2 +0,0 @@
cd "c:\praxis"
python "c:\praxis\user_module.py"

14
praxis_logging.py Normal file
View File

@ -0,0 +1,14 @@
import logging
import utilities_script
class praxis_logger():
def init(self, name):
super().__init__()
self.logName = "logs/" + name + ".log"
utilities_script.get_dir("logs")
logging.basicConfig(filename=self.logName, level=logging.DEBUG)
logging.info('Application running!')
def log(self, msg):
print(self.logName, msg)
logging.info(msg)

View File

@ -1,8 +0,0 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

View File

@ -0,0 +1,10 @@
cd "c:\praxis"
docker-compose down
docker build --file Dockerfile_standalone_command.Dockerfile --tag standalone_command .
docker build --file Dockerfile_standalone_channelRewards.Dockerfile --tag standalone_channelrewards .
docker build --file Dockerfile_standalone_lights.Dockerfile --tag standalone_lights .
docker build --file Dockerfile_standalone_tts_core.Dockerfile --tag standalone_tts_core .
docker build --file Dockerfile_standalone_DiscordScript.Dockerfile --tag standalone_discordscript .
docker build --file Dockerfile_standalone_TwitchScript.Dockerfile --tag standalone_twitchscript .
docker build --file Dockerfile_standalone_Twitch_Pubsub.Dockerfile --tag standalone_twitch_pubsub .
docker-compose up -d

View File

@ -9,4 +9,5 @@ playsound
discord.py discord.py
psutil psutil
art art
phue phue
flask

View File

@ -0,0 +1,7 @@
twitch-python
discord.py
flask
psutil
phue
art
requests

View File

@ -0,0 +1,4 @@
discord.py
psutil
art
requests

View File

@ -0,0 +1,4 @@
twitch-python
psutil
art
requests

View File

@ -0,0 +1,4 @@
twitchAPI
psutil
art
requests

View File

@ -0,0 +1,161 @@
import flask
from flask import Flask, request, after_this_request
import channel_rewards.channelRewards_loader as rewards_loader
from channel_rewards.channelRewards_base import AbstractChannelRewards
from json import loads
from urllib.parse import urlencode
import requests
import json
import base64
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
loadedRewards = {}
def init():
# todo load entire reward library and cache it here
praxis_logger_obj.log("init stuff")
loadedRewards[AbstractChannelRewards.ChannelRewardsType.channelPoints] = rewards_loader.load_rewards(AbstractChannelRewards.ChannelRewardsType.channelPoints)
loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_bits] = rewards_loader.load_rewards(AbstractChannelRewards.ChannelRewardsType.twitch_bits)
loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_subs] = rewards_loader.load_rewards(AbstractChannelRewards.ChannelRewardsType.twitch_subs)
def is_reward(reward_name, reward_type) -> bool:
#global loadedRewards
tempType = reward_type.replace('ChannelRewardsType.', '')
realTempType = AbstractChannelRewards.ChannelRewardsType.__dict__[tempType]
#praxis_logger_obj.log(loadedRewards[realTempType])
for reward in loadedRewards[realTempType]:
#praxis_logger_obj.log("found: ", reward, "type: ", type(reward))
if reward_name == reward:
praxis_logger_obj.log("Equal")
return True
if reward_name == "!echo":
return True
else:
return False
def handle_reward(source, username, reward_name, reward_type, rewardPrompt, userInput, bonusData):
#reward:AbstractChannelRewards = loadedRewards[reward_name]
praxis_logger_obj.log("\n trying to handle reward: " + reward_name)
try:
tempType = reward_type.replace('ChannelRewardsType.', '')
realTempType = AbstractChannelRewards.ChannelRewardsType.__dict__[tempType]
tempSource = source.replace('ChannelRewardsSource.', '')
realSource = AbstractChannelRewards.ChannelRewardsSource.__dict__[tempSource]
reward:AbstractChannelRewards = loadedRewards[realTempType][reward_name]
if reward is not None:
reward_response = reward.do_ChannelReward(realSource, username, reward_name, rewardPrompt, userInput, bonusData)
return flask.make_response("{\"message\":\"%s\"}" % reward_response, 200, {"Content-Type": "application/json"})
except:
return flask.make_response("{\"message\":\"%s\"}" % "Something Went horribly wrong", 500)
#praxis_logger_obj.log("Doing a reward")
def handle_get_list():
tempDict = {}
returnedDict = {}
for cmd in loadedRewards[AbstractChannelRewards.ChannelRewardsType.channelPoints]:
tempCmd:AbstractChannelRewards = loadedRewards[AbstractChannelRewards.ChannelRewardsType.channelPoints][cmd]
tempDict['channelRewardName'] = tempCmd.ChannelRewardName
tempDict['isRewardEnabled'] = str(tempCmd.isChannelRewardEnabled).lower()
returnedDict[tempCmd.ChannelRewardName] = tempDict
tempDict = {}
for cmd in loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_bits]:
tempCmd:AbstractChannelRewards = loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_bits][cmd]
tempDict['channelRewardName'] = tempCmd.ChannelRewardName
tempDict['isRewardEnabled'] = str(tempCmd.isChannelRewardEnabled).lower()
returnedDict[tempCmd.ChannelRewardName] = tempDict
tempDict = {}
for cmd in loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_subs]:
tempCmd:AbstractChannelRewards = loadedRewards[AbstractChannelRewards.ChannelRewardsType.twitch_subs][cmd]
tempDict['channelRewardName'] = tempCmd.ChannelRewardName
tempDict['isRewardEnabled'] = str(tempCmd.isChannelRewardEnabled).lower()
returnedDict[tempCmd.ChannelRewardName] = tempDict
tempDict = {}
payload = json.dumps(returnedDict)
praxis_logger_obj.log("dumped")
praxis_logger_obj.log(payload)
payload = base64.b64encode(str.encode(payload))
print("encoded")
praxis_logger_obj.log("encoded")
praxis_logger_obj.log(payload)
return flask.make_response("{\"message\":\"%s\"}" % payload.decode(), 200, {"Content-Type": "application/json"})
@api.route('/api/v1/reward', methods=['GET'])
def reward_check():
if 'reward_name' in request.args and 'reward_type' in request.args:
#praxis_logger_obj.log("reward_name: "+ request.args['reward_name']+"reward_type: "+ request.args['reward_type'])
if is_reward(request.args['reward_name'], request.args['reward_type']):
praxis_logger_obj.log("about to send")
return flask.make_response('', 200)
else:
return flask.make_response('', 404)
@api.route('/api/v1/exec_reward', methods=['GET'])
def exec_reward():
if 'reward_name' not in request.args:
return flask.make_response('{\"text\":"Argument \'reward_name\' not in request"}', 400)
if 'reward_type' not in request.args:
return flask.make_response('{\"text\":"Argument \'reward_type\' not in request"}', 400)
if 'reward_prompt' not in request.args:
return flask.make_response('{\"text\":"Argument \'reward_prompt\' not in request"}', 400)
if 'user_input' not in request.args:
return flask.make_response('{\"text\":"Argument \'user_input\' not in request"}', 400)
if 'reward_source' not in request.args:
return flask.make_response('{\"text\":"Argument \'reward_source\' not in request"}', 400)
if 'user_name' not in request.args:
username = "User"
else:
username = request.args['user_name']
praxis_logger_obj.log("\n About to try a reward")
praxis_logger_obj.log(request.args['reward_source'])
praxis_logger_obj.log(request.args['reward_name'])
praxis_logger_obj.log(request.args['reward_type'])
praxis_logger_obj.log(request.args['reward_prompt'])
praxis_logger_obj.log(request.args['user_input'])
praxis_logger_obj.log(request.args['bonus_data'])
return handle_reward(
request.args['reward_source'],
username,
request.args['reward_name'],
request.args['reward_type'],
request.args['reward_prompt'],
request.args['user_input'],
request.args['bonus_data'])
@api.route('/api/v1/get_list/all', methods=['GET'])
def get_list():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return handle_get_list()
if __name__ == '__main__':
init()
api.run(host='0.0.0.0', port=42069)

121
standalone_command.py Normal file
View File

@ -0,0 +1,121 @@
import json
import flask
from flask import Flask, request, after_this_request
import commands.loader as command_loader
from commands.command_base import AbstractCommand
from json import loads
from urllib.parse import urlencode
import requests
import base64
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
loadedCommands = {}
def init():
# todo load entire command library and cache it here
load_commands()
def load_commands():
global loadedCommands
loadedCommands = command_loader.load_commands(AbstractCommand.CommandType.Ver2)
def is_command(command: str) -> bool:
#print(command)
for cmd in loadedCommands:
#print(cmd)
if command == cmd:
return True
if command == "!echo":
return True
else:
return False
def handle_command(source, username, command, rest, bonusData):
if command == "!echo":
message = "Got payload [%s]" % rest
#print(message)
return flask.make_response("{\"message\":\"%s\"}" % message, 200, {"Content-Type": "application/json"})
tempSource = source.replace('CommandSource.', '')
realSource = AbstractCommand.CommandSource.__dict__[tempSource]
cmd:AbstractCommand = loadedCommands[command]
if cmd is not None:
cmd_response = cmd.do_command(source, username, command, rest, bonusData)
return flask.make_response("{\"message\":\"%s\"}" % cmd_response, 200, {"Content-Type": "application/json"})
#print("Doing a command")
def handle_get_list():
tempDict = {}
returnedDict = {}
for cmd in loadedCommands:
tempCmd:AbstractCommand = loadedCommands[cmd]
tempDict['command'] = tempCmd.command
tempDict['isCommandEnabled'] = str(tempCmd.isCommandEnabled).lower()
returnedDict[tempCmd.command] = tempDict
tempDict = {}
payload = json.dumps(returnedDict)
praxis_logger_obj.log("dumped")
praxis_logger_obj.log(payload)
payload = base64.b64encode(str.encode(payload))
print("encoded")
praxis_logger_obj.log("encoded")
praxis_logger_obj.log(payload)
return flask.make_response("{\"message\":\"%s\"}" % payload.decode(), 200, {"Content-Type": "application/json"})
@api.route('/api/v1/command', methods=['GET'])
def command_check():
if 'name' in request.args:
if is_command(request.args['name']):
return flask.make_response('', 200)
else:
return flask.make_response('', 404)
@api.route('/api/v1/exec_command', methods=['GET'])
def exec_command():
if 'command_name' not in request.args:
return flask.make_response('{\"text\":"Argument \'command_name\' not in request"}', 400)
if 'rest' not in request.args:
return flask.make_response('{\"text\":"Argument \'rest\' not in request"}', 400)
if 'command_source' not in request.args:
return flask.make_response('{\"text\":"Argument \'command_source\' not in request"}', 400)
if 'user_name' not in request.args:
username = "User"
else:
username = request.args['user_name']
return handle_command(request.args['command_source'], username, request.args['command_name'], request.args['rest'], request.args['bonus_data'])
@api.route('/api/v1/get_list/all', methods=['GET'])
def get_list():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return handle_get_list()
if __name__ == '__main__':
init()
api.run(host='0.0.0.0', port=42010)

View File

@ -1,15 +1,18 @@
import random import random
import re import re
import utilities_script as utilities import utilities_script as utility
from json import loads
from urllib.parse import urlencode
import requests
from discord import message from discord import message
from discord.client import Client from discord.client import Client
import asyncio import asyncio
import config as config import config
import db
import tts
import commands.command_base
import commands.loader as command_loader import commands.loader as command_loader
from commands.command_base import AbstractCommand from commands.command_base import AbstractCommand
@ -22,6 +25,12 @@ import discord.abc
from cooldowns import Cooldown_Module from cooldowns import Cooldown_Module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Discord_Module(discord.Client): class Discord_Module(discord.Client):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -32,12 +41,6 @@ class Discord_Module(discord.Client):
self.cooldownModule:Cooldown_Module = Cooldown_Module() self.cooldownModule:Cooldown_Module = Cooldown_Module()
self.cooldownModule.setupCooldown("discordRateLimit", 10, 1) self.cooldownModule.setupCooldown("discordRateLimit", 10, 1)
self.commands = command_loader.load_commands_new(AbstractCommand.CommandType.DISCORD)
self.tts_enabled: bool = False
self.selected_ttsChannels:list = []
self.block_tts_url: bool = False
# don't freak out, this is *merely* a regex for matching urls that will hit just about everything # don't freak out, this is *merely* a regex for matching urls that will hit just about everything
self._urlMatcher = re.compile( self._urlMatcher = re.compile(
"(https?:(/{1,3}|[a-z0-9%])|[a-z0-9.-]+[.](com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw))") "(https?:(/{1,3}|[a-z0-9%])|[a-z0-9.-]+[.](com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw))")
@ -58,34 +61,21 @@ class Discord_Module(discord.Client):
print("{" + message.guild.name + "}[ " + str(message.channel) + " ](" + message.author.display_name + ")> ") print("{" + message.guild.name + "}[ " + str(message.channel) + " ](" + message.author.display_name + ")> ")
#print(message.author.mention) #print(message.author.mention)
print(message.content) print(message.content)
#print(message.channel.id)
#Message ID
#print(str(message.id))
#print(str(message.channel.id))
if message.content == "//test":
#pass
await message.channel.send('test response')
#test = self.get_channel(431129571308339210)
#await test.send("testerino")
temp = message.channel.last_message
delayTime:float = 3
await message.delete(delay=delayTime)
await temp.delete(delay=delayTime)
debugLogString= "\n\n{" + message.guild.name + "}[ " + str(message.channel) + " ](" + message.author.display_name +")> " + message.content + "\n"
praxis_logger_obj.log(debugLogString)
if not await self.isSenderBot(message): if not await self.isSenderBot(message):
# This will check for the praxis_bot-tts channel and will TTS stuff from there. # This will check for the praxis_bot-tts channel and will TTS stuff from there.
await self.eval_triggeredEvents(message) #await self.eval_triggeredEvents(message)
if self.cooldownModule.isCooldownActive("discordRateLimit") == False: await self.eval_commands(message)
await self.eval_commands(message) await self.eval_tts(message)
#await self.tts_message(message)
async def eval_triggeredEvents(self, message: discord.Message): async def eval_triggeredEvents(self, message: discord.Message):
# This will check for the selected channels and will TTS stuff from there. # This will check for the selected channels and will TTS stuff from there.
await self.tts_message(message) #await self.tts_message(message)
foundChannel = False foundChannel = False
for channel in self.selected_ttsChannels: for channel in self.selected_ttsChannels:
@ -93,112 +83,60 @@ class Discord_Module(discord.Client):
# await self.tts_message(message) # await self.tts_message(message)
pass pass
async def eval_tts(self, message: discord.Message):
command, rest = utility.parse_line(message.content)
async def eval_automaticEvents(self, message: discord.Message): try:
pass is_actionable = await self.is_command(command)
if not is_actionable:
await self.exec_tts(message)
except:
print("something went wrong with tts")
async def eval_commands(self, message: discord.Message): async def eval_commands(self, message: discord.Message):
# containsURL: bool = self.contains_url(message) command, rest = utility.parse_line(message.content)
try: try:
#first_space_idx = message.text.index(' ') is_actionable = await self.is_command(command)
if is_actionable:
if self.cooldownModule.isCooldownActive("discordRateLimit") == False:
await self.exec_command(message, command, rest)
except:
print("something went wrong with a command")
# This fixes a error where if you send a command without arguments it fails because async def is_command(self, word: str) -> bool:
# it cant find the substring. # todo need to url-escape word
if message.content.find(" ") != -1: clean_param = urlencode({'name': word})
first_space_idx = message.content.index(' ') url = "http://standalone_command:42010/api/v1/command?%s" % clean_param
else: resp = requests.get(url)
first_space_idx = -1 return resp.status_code == 200
command_text = ' ' async def exec_command(self, realMessage: discord.Message, command: str, rest: str):
if first_space_idx > -1: # todo need to url-escape command and rest
command_text = message.content[0:first_space_idx] params = urlencode(
else: {'command_source': commands.command_base.AbstractCommand.CommandSource.Discord,
command_text = message.content 'user_name': realMessage.author.mention,
'command_name': command,
'rest': rest,
'bonus_data': realMessage})
command = self.commands[command_text] url = "http://standalone_command:42010/api/v1/exec_command?%s" % params
if command is not None and command.command_type is AbstractCommand.CommandType.DISCORD: resp = requests.get(url)
await command.do_command(self, message) if resp.status_code == 200:
except Exception as e: print("Got the following message: %s" % resp.text)
# Undo the following for debug stuff data = loads(resp.text)
#print(e) msg = data['message']
pass # we don't care if msg is not None:
await self.send_message(realMessage, msg)
else:
# todo handle failed requests
pass
async def send_message(self, message: discord.Message, response): async def send_message(self, message: discord.Message, response):
isBlocked = await self.isChannel_inConfigList(str(message.channel.id), config.block_DiscordChannelsMessaging) isBlocked = await self.isChannel_inConfigList(str(message.channel.id), config.block_DiscordChannelsMessaging)
if self.cooldownModule.isCooldownActive("discordRateLimit") == False and not isBlocked and not config.blockAll_DiscordChannelsMessaging: if self.cooldownModule.isCooldownActive("discordRateLimit") == False and not isBlocked and not config.blockAll_DiscordChannelsMessaging:
await message.channel.send(response) if not utility.contains_slur(response):
self.cooldownModule.actionTrigger("discordRateLimit") await message.channel.send(response)
async def tts_message(self, message: discord.Message):
isBlocked = await self.isChannel_inConfigList(str(message.channel.id), config.block_DiscordChannelsTTS)
isForced = (await self.isChannel_inConfigList(str(message.channel.id), config.force_DiscordChannelsTTS) and not config.blockAll_DiscordChannelsTTS)
#print("isBlocked: " + str(isBlocked))
#print("isForced: " + str(isForced))
if (not await self.contains_slur(message)) and (await self.isTTS_URL_Enabled(message)):
print(message.channel.id, message.channel.id, message.channel.id)
isMessageChannelInList = False
for TTS_C_id in config.selected_DiscordTTSChannels:
print(TTS_C_id)
if int(TTS_C_id) == int(message.channel.id):
isMessageChannelInList = True
if self.tts_enabled and (isMessageChannelInList) and not isBlocked and not config.blockAll_DiscordChannelsTTS or isForced or config.forceAll_DiscordChatChannelsTTS:
if not message.content.startswith('!'):
text_to_say: str = "%s says, %s" % (message.author.display_name, message.content)
channel_text = "%s user msg" % message.channel
tts.tts(text_to_say)
if not await self.contains_slur(message):
if self.tts_enabled:
if not message.content.startswith('!'):
pass
#text_to_say: str = "%s says, %s" % (message.author.display_name, message.content)
#channel_text = "%s user msg" % message.channel
#tts.tts(text_to_say)
# Checks for basic slurs.
async def contains_slur(self, message: discord.Message):
containsSlur: bool = False
if await self.slur_check(message.content) or await self.slur_check(message.author.display_name):
containsSlur = True
return containsSlur
async def slur_check(self, text):
containsSlur: bool = False
parsedMessage = text.split(" ")
for word in parsedMessage:
for slur in config.slurList:
if word.lower() == slur:
containsSlur = True
break # we want to immediately escape if we found a slur
if containsSlur:
break
if containsSlur:
print("<{ slur detected! }>")
#print("<{ slur detected! }> " + " [#" + message.channel + "](" + message.author.display_name + ") used a slur in chat")
return containsSlur
async def contains_url(self, message: discord.Message):
containsURL = re.search(self._urlMatcher, message.content.lower()) is not None
if containsURL:
print("<{ link detected! }> " + " [#" + str(message.channel) + "](" + message.author.display_name + ") sent a link in chat")
return containsURL
async def isTTS_URL_Enabled(self, message: discord.Message):
is_ttsEnabled = False
if not config.blockAll_TTS_URL_Discord or not self.block_tts_url:
if not await self.contains_url(message):
is_ttsEnabled = True
return is_ttsEnabled
self.cooldownModule.actionTrigger("discordRateLimit")
# Checks if Sender is bot. # Checks if Sender is bot.
async def isSenderBot(self, message: discord.Message): async def isSenderBot(self, message: discord.Message):
@ -217,12 +155,75 @@ class Discord_Module(discord.Client):
#print("isSelf: " + str(discordChannel) + " vs " + str(selectedChannel)) #print("isSelf: " + str(discordChannel) + " vs " + str(selectedChannel))
if discordChannel == selectedChannel: if discordChannel == selectedChannel:
is_Self = True is_Self = True
#if is_Self:
# print("Is Self")
#if not is_Self:
# print("Is Not Self")
return is_Self return is_Self
async def exec_tts(self, message: discord.Message):
isBlocked = await self.isChannel_inConfigList(str(message.channel.id), config.block_DiscordChannelsTTS)
isForced = (await self.isChannel_inConfigList(str(message.channel.id), config.force_DiscordChannelsTTS) and not config.blockAll_DiscordChannelsTTS)
#print("isBlocked: " + str(isBlocked))
#print("isForced: " + str(isForced))
print(message.channel.id, message.channel.id, message.channel.id)
isMessageChannelInList = False
for TTS_C_id in config.selected_DiscordTTSChannels:
print(TTS_C_id)
if int(TTS_C_id) == int(message.channel.id):
isMessageChannelInList = True
if config.autoEnabled_DiscordChannelsTTS and (isMessageChannelInList) and not isBlocked and not config.blockAll_DiscordChannelsTTS or isForced or config.forceAll_DiscordChatChannelsTTS:
if not message.content.startswith('!'):
text_to_say: str = "%s says, %s" % (message.author.display_name, message.content)
channel_text = "%s user msg" % message.channel
await self.exec_tts_sender("", text_to_say)
async def exec_tts_sender(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://standalone_tts_core:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
if not await self.contains_slur(message):
if self.tts_enabled:
if not message.content.startswith('!'):
pass
#text_to_say: str = "%s says, %s" % (message.author.display_name, message.content)
#channel_text = "%s user msg" % message.channel
#tts.tts(text_to_say)
#FINISH THIS EVENT LOG
async def send_EventLog(self, eventName, eventTime, eventType, eventData):
params = urlencode(
{'event_name': eventName,
'event_time': eventTime,
'event_type': eventType,
'event_data': eventData})
url = "http://standalone_eventlog:42008/api/v1/event_log/add_event?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
@ -234,7 +235,4 @@ if __name__ == "__main__":
testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname) testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
testModule.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname) testModule.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname)
for ttsChannel in config.selected_discordTTSChannels:
testModule.selected_ttsChannels.append(int(ttsChannel))
testModule.main() testModule.main()

198
standalone_eventLog.py Normal file
View File

@ -0,0 +1,198 @@
from datetime import datetime
from enum import Enum
from os import F_OK
import tempText_Module
import time
import config as config
import flask
from flask import Flask, request, after_this_request
import credentials
import commands.loader as command_loader
from commands.command_base import AbstractCommand
from cooldowns import Cooldown_Module
import utilities_script as utility
import chyron_module
import timers_module
import random
import json
import base64
import event_logs.event_log_Module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api:Flask = Flask(__name__)
api.config["DEBUG"] = True
logging_module = event_logs.event_log_Module.Event_Log_Module()
def init():
print("starting up... ",)
logging_module.main()
def add_event(eventName, eventTime, eventType, eventSender, eventData):
logging_module.make_event(eventName, eventTime, eventType, eventSender, eventData)
return flask.make_response("{\"message\":\"%s\"}" % None, 200, {"Content-Type": "application/json"})
def get_events():
#returnedData = logging_module.get_recent_logs(50)
try:
masterDic = {}
newDic = {}
counter = 0
for event in logging_module.Event_Log_List:
#praxis_logger_obj.log("get event history debug thing: "+ str(event))
#recentLog = self.Event_Log_List[-x]
newDic['eventName'] = str(event.eventName)
newDic['eventTime'] = str(event.eventTime)
newDic['eventType'] = str(event.eventType)
newDic['eventSender'] = str(event.eventSender)
newDic['eventData'] = str(event.eventData)
masterDic[str(counter)] = newDic
counter = counter + 1
newDic = {}
except:
masterDic = {}
#returnedData = [""]
#praxis_logger_obj.log("\nGotten Events" + str(masterDic))
#print("\nGotten Events" + masterDic)
payload = json.dumps(masterDic)
payload = base64.b64encode(str.encode(payload))
return flask.make_response("{\"message\":\"%s\"}" % payload.decode(), 200, {"Content-Type": "application/json"})
def reRunEvent_handler(eventName, eventTime, eventType, eventSender, eventData):
attempt_Event_Rerun(eventName, eventTime, eventType, eventSender, eventData)
return flask.make_response("{\"message\":\"%s\"}" % 'rerunning event....', 200, {"Content-Type": "application/json"})
def attempt_Event_Rerun(eventName, eventTime, eventType, eventSender, eventData):
returnString = ""
try:
return flask.make_response("{\"message\":\"%s\"}" % returnString, 200, {"Content-Type": "application/json"})
except:
returnString = "Something Went Wrong!"
return flask.make_response("{\"message\":\"%s\"}" % returnString, 200, {"Content-Type": "application/json"})
@api.route('/')
def bot_StatusIcon():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return flask.make_response('Hello There', 200)
@api.route('/api/v1/event_log/status')
def bot_status():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return flask.make_response('EventLog Service: OK', 200)
@api.route('/api/v1/event_log/add_event')
def add_event_log():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'event_name' not in request.args:
return flask.make_response('{\"text\":"Argument \'event_name\' not in request"}', 400)
if 'event_time' not in request.args:
return flask.make_response('{\"text\":"Argument \'event_time\' not in request"}', 400)
if 'event_type' not in request.args:
return flask.make_response('{\"text\":"Argument \'event_type\' not in request"}', 400)
if 'eventSender' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventSender\' not in request"}', 400)
if 'event_data' not in request.args:
return flask.make_response('{\"text\":"Argument \'event_data\' not in request"}', 400)
return add_event(request.args['event_name'], request.args['event_time'], request.args['event_type'], request.args['eventSender'], request.args['event_data'],)
@api.route('/api/v1/event_log/get_events')
def get_event_log():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'request_data' not in request.args:
requestData = 50
return get_events()
@api.route('/api/v1/event_log/reRunEvent')
def reRunEvent():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'eventName' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventName\' not in request"}', 400)
if 'eventTime' not in request.args:
sentTime = request.args('eventTime')
else:
sentTime = None
if 'eventType' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventType\' not in request"}', 400)
if 'eventSender' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventSender\' not in request"}', 400)
if 'eventData' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventData\' not in request"}', 400)
return reRunEvent_handler(request.args['eventName'], sentTime, request.args['eventType'], request.args['eventSender'], request.args['eventData'])
# @api.route('/api/v1/event_log/chyron/get')
# def get_chyron():
# @after_this_request
# def add_header(response):
# response.headers.add('Access-Control-Allow-Origin', '*')
# return response
# return flask.make_response('Client Service: OK', 200)
# @api.route('/api/v1/event_log/commands/get')
# def get_commands():
# @after_this_request
# def add_header(response):
# response.headers.add('Access-Control-Allow-Origin', '*')
# return response
# return flask.make_response('Client Service: OK', 200)
# @api.route('/api/v1/event_log/rewards/get')
# def get_rewards():
# @after_this_request
# def add_header(response):
# response.headers.add('Access-Control-Allow-Origin', '*')
# return response
# return flask.make_response('Client Service: OK', 200)
# @api.route('/api/v1/event_log/timers/get')
# def get_timers():
# @after_this_request
# def add_header(response):
# response.headers.add('Access-Control-Allow-Origin', '*')
# return response
# return flask.make_response('Client Service: OK', 200)
# @api.route('/api/v1/event_log/text_sources/get')
# def get_text_sources():
# @after_this_request
# def add_header(response):
# response.headers.add('Access-Control-Allow-Origin', '*')
# return response
# return flask.make_response('Client Service: OK', 200)
if __name__ == "__main__":
init()
api.run(host="0.0.0.0", port = 42008)

306
standalone_lights.py Normal file
View File

@ -0,0 +1,306 @@
from time import sleep
import phue
from phue import Bridge
import random
import utilities_script as utilities
import credentials
import config
import flask
from flask import request
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
class Lights_Module():
def __init__(self):
super().__init__()
# The .python_hue is generated in the home directory by default.
self.bridge_:Bridge = Bridge('192.168.191.42', config_file_path='credentials/.python_hue')
def main(self):
praxis_logger_obj.log("\nStarting up [Lights_Module]...")
self.bridge_.connect()
self.bridge_.get_api()
light_list = self.bridge_.lights
group_list:list = []
groups = self.bridge_.get_group()
groupCount = 0
#praxis_logger_obj.log("\n -Listing Lights...")
for l in light_list:
pass
#praxis_logger_obj.log(l.name)
#praxis_logger_obj.log("\n -Counting Groups...")
for g in groups:
#praxis_logger_obj.log(g)
groupCount = int(g)
for gc in range(groupCount):
try:
#praxis_logger_obj.log("group n:" + str(gc))
group = self.bridge_.get_group(gc ,'name')
#praxis_logger_obj.log(group)
group_list.append(group)
#praxis_logger_obj.log(" --done adding")
except:
pass
#praxis_logger_obj.log(" --adding failed")
#self.bridge_.set_group(18, "bri", 254) #This is max Brightness
#self.bridge_.set_group(18, "on", True) #This is will turn ON
#xy_result = self.rgb_to_xy(0,0,1) #This will take an rgb value and make it xy
#self.bridge_.set_group(16, "xy", xy_result) #This will make the lights in the group turn blue
# The Following will make a rave
#for rave in range(10):
#rgb_r = random.random()
#rgb_g = random.random()
#rgb_b = random.random()
#xy_result = self.rgb_to_xy(rgb_r, rgb_g, rgb_b) #This will take an rgb value and make it xy
#self.bridge_.set_group(16, "xy", xy_result)
#sleep(0.1)
#for stuffz in self.bridge_.scenes:
#praxis_logger_obj.log(stuffz)
# This will set the group Downstairs to the Stream scene
#self.bridge_.run_scene("Downstairs", "Stream")
#self.bridge_.run_scene("Downstairs", "Stream")
praxis_logger_obj.log("-[Lights_Module] Setup Complete")
def setLight():
pass
def setLights():
pass
def setGroup():
pass
def setGroups():
pass
def rubiksCube(self):
for rave in range(10):
rgb_r = random.random()
rgb_g = random.random()
rgb_b = random.random()
xy_result = self.rgb_to_xy(rgb_r, rgb_g, rgb_b) #This will take an rgb value and make it xy
self.bridge_.set_group(16, "xy", xy_result, transitiontime=0.2)
sleep(0.25)
self.bridge_.run_scene("Downstairs", "Stream")
def hydration(self):
self.bridge_.run_scene("Downstairs", "hydration")
sleep(4)
self.bridge_.run_scene("Downstairs", "Stream")
def raveMode(self):
for rave in range(30):
rgb_r = random.random()
rgb_g = random.random()
rgb_b = random.random()
xy_result = self.rgb_to_xy(rgb_r, rgb_g, rgb_b) #This will take an rgb value and make it xy
self.bridge_.set_group(16, "xy", xy_result)
sleep(0.3)
self.bridge_.run_scene("Downstairs", "Stream")
def rgb_to_xy(self, red, green, blue):
""" conversion of RGB colors to CIE1931 XY colors
Formulas implemented from: https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
Args:
red (float): a number between 0.0 and 1.0 representing red in the RGB space
green (float): a number between 0.0 and 1.0 representing green in the RGB space
blue (float): a number between 0.0 and 1.0 representing blue in the RGB space
Returns:
xy (list): x and y
"""
# gamma correction
red = pow((red + 0.055) / (1.0 + 0.055), 2.4) if red > 0.04045 else (red / 12.92)
green = pow((green + 0.055) / (1.0 + 0.055), 2.4) if green > 0.04045 else (green / 12.92)
blue = pow((blue + 0.055) / (1.0 + 0.055), 2.4) if blue > 0.04045 else (blue / 12.92)
# convert rgb to xyz
x = red * 0.649926 + green * 0.103455 + blue * 0.197109
y = red * 0.234327 + green * 0.743075 + blue * 0.022598
z = green * 0.053077 + blue * 1.035763
# convert xyz to xy
x = x / (x + y + z)
y = y / (x + y + z)
# TODO check color gamut if known
return [x, y]
def color_string_parser(self, message):
maxDigits = config.colorParse_maxDigits
praxis_logger_obj.log("Searching for color...")
xy_color = [0, 0]
for text in message:
#praxis_logger_obj.log("testing word")
if "red" in text.lower():
xy_color = self.rgb_to_xy(1,0,0)
praxis_logger_obj.log("-found: red")
if "blue" in text.lower():
praxis_logger_obj.log("-found: blue")
xy_color = self.rgb_to_xy(0,0,1)
if "green" in text.lower():
praxis_logger_obj.log("-found: green")
xy_color = self.rgb_to_xy(0,1,0)
if "yellow" in text.lower():
praxis_logger_obj.log("-found: yellow")
xy_color = self.rgb_to_xy(
0.7,
0.64,
0)
if "cyan" in text.lower():
praxis_logger_obj.log("-found: cyan")
xy_color = self.rgb_to_xy(0,1,1)
if "aquamarine" in text.lower():
praxis_logger_obj.log("-found: aquamarine")
xy_color = self.rgb_to_xy(
round(utilities.rescale_value(111,0,254),maxDigits),
round(utilities.rescale_value(218,0,254),maxDigits),
round(utilities.rescale_value(146,0,254),maxDigits))
if "turquoise" in text.lower():
praxis_logger_obj.log("-found: turquoise")
xy_color = self.rgb_to_xy(
round(utilities.rescale_value(172,0,254),maxDigits),
round(utilities.rescale_value(233,0,254),maxDigits),
round(utilities.rescale_value(232,0,254),maxDigits))
if "orange" in text.lower():
praxis_logger_obj.log("-found: orange")
xy_color = self.rgb_to_xy(
1,
round(utilities.rescale_value(126,0,254),maxDigits),
0)
if "magenta" in text.lower():
praxis_logger_obj.log("-found: magenta")
xy_color = self.rgb_to_xy(
1,
0,
1)
if "purple" in text.lower():
praxis_logger_obj.log("-found: purple")
xy_color = self.rgb_to_xy(
round(utilities.rescale_value(159,0,254),maxDigits),
round(utilities.rescale_value(32,0,254),maxDigits),
round(utilities.rescale_value(239,0,254),maxDigits))
if "violet" in text.lower():
praxis_logger_obj.log("-found: violet")
xy_color = self.rgb_to_xy(
round(utilities.rescale_value(237,0,254),maxDigits),
round(utilities.rescale_value(129,0,254),maxDigits),
round(utilities.rescale_value(237,0,254),maxDigits))
return xy_color
RGB_Lights = Lights_Module()
def init():
RGB_Lights.main()
def do_lights_command(user="", lightGroup="all", command = "", rest = ""):
returnString = "None"
praxis_logger_obj.log("about to do something ......")
praxis_logger_obj.log("about to do something with: " + command + " " + rest)
#bot.return_message("\nRGB Command Detected!")
if rest is not "":
tempFix = command + " " + rest
else:
tempFix = command
tempParsedMessage = tempFix.split(" ")
sceneCommand = False
if (len(tempParsedMessage)) > 2:
praxis_logger_obj.log("RGB Command!")
rgb_r = float(tempParsedMessage[1])
rgb_g = float(tempParsedMessage[2])
rgb_b = float(tempParsedMessage[3])
xy_result = RGB_Lights.rgb_to_xy(rgb_r, rgb_g, rgb_b)
praxis_logger_obj.log("got XY")
RGB_Lights.bridge_.set_group(16, "xy", xy_result)
#bot.return_message("sent color to [Lights_Module]")
else:
if "stream" in tempParsedMessage:
sceneCommand = True
RGB_Lights.bridge_.run_scene("Downstairs", "Stream")
elif "normal" in tempParsedMessage:
sceneCommand = True
RGB_Lights.bridge_.run_scene("Downstairs", "Bright")
elif "haxor" in tempParsedMessage:
sceneCommand = True
RGB_Lights.bridge_.run_scene("Downstairs", "hacker vibes")
elif "off" in tempParsedMessage:
sceneCommand = True
RGB_Lights.bridge_.set_group("Downstairs", "on", False)
elif "on" in tempParsedMessage:
sceneCommand = True
RGB_Lights.bridge_.set_group("Downstairs", "on", True)
elif "rubikscube" in tempParsedMessage:
sceneCommand = True
RGB_Lights.rubiksCube()
elif "hydration" in tempParsedMessage:
sceneCommand = True
RGB_Lights.hydration()
elif "ravemode" in tempParsedMessage:
sceneCommand = True
RGB_Lights.raveMode()
else:
#bot.return_message("Color Command!")
xy_result = RGB_Lights.color_string_parser(tempParsedMessage)
#bot.return_message("got XY")
RGB_Lights.bridge_.set_group(16, "xy", xy_result)
#bot.return_message("sent color to [Lights_Module]")
if sceneCommand == True:
praxis_logger_obj.log("Scene Command!")
returnString = user + " changed the light's color!"
return flask.make_response("{\"message\":\"%s\"}" % returnString, 200, {"Content-Type": "application/json"})
@api.route('/api/v1/exec_lights', methods=['GET'])
def exec_lights():
if 'user_name' not in request.args:
user_name="User"
else:
user_name=request.args['user_name']
if 'light_group' not in request.args:
return flask.make_response('{\"text\":"Argument \'light_group\' not in request"}', 400)
if 'command' not in request.args:
return flask.make_response('{\"text\":"Argument \'scene_name\' not in request"}', 400)
praxis_logger_obj.log("about to do something ......")
RGB_Lights.main()
return do_lights_command(user_name, request.args['light_group'], request.args['command'], request.args['rest'])
if __name__ == "__main__":
init()
api.run(host='0.0.0.0', port=42042)
#testModule.raveMode()

View File

@ -0,0 +1,45 @@
import flask
from flask import request
import obsWebSocket
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
possibleRequests = []
def init():
possibleRequests = obsWebSocket.getRequests()
for r in possibleRequests:
print("requestname: "+r)
#obsWebSocket.makeRequest("ToggleStudioMode", {'source':'tinycam', 'render':'True'})
#obsWebSocket.makeRequest("SetSourceRender", data={'source':"tinycam", 'render': False, 'scene-name':"Cam feed (main) INFOBOX"})
#obsWebSocket.makeRequest("SetSourceRender", data={'source':"tinycam", 'render': True, 'scene-name':"Cam feed (main) INFOBOX"})
#obsWebSocket.listenForData()
def do_request(requestName, data):
if requestName in possibleRequests:
obsWebSocket.makeRequest(requestName, data)
@api.route('/api/v1/obs/websocket/makeRequest', methods=['GET'])
def makeRequest():
if 'request_name' not in request.args:
return flask.make_response('{\"text\":"Argument \'request_name\' not in request"}', 400)
if 'request_data' not in request.args:
data = None
else:
data = request.args['request_data']
#possibleRequests = obsWebSocket.getRequests()
do_request(request.args['request_name'], data)
if __name__ == "__main__":
init()
api.run(host='0.0.0.0', port=42010)

54
standalone_tts_core.py Normal file
View File

@ -0,0 +1,54 @@
import flask
from flask import request
from json import loads
from urllib.parse import urlencode
import requests
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
def init():
praxis_logger_obj.log("init stuff")
def send_text(tts_sender, tts_text):
#Play Text
params = urlencode({'tts_sender': tts_sender, 'tts_text': tts_text})
url = "http://192.168.191.208:40085/api/v1/tts/speech?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
#data = loads(resp.text)
#msg = data['message']
#if msg is not None:
#pass
#else:
# todo handle failed requests
#pass
#return None
return flask.make_response('', 200)
@api.route('/api/v1/tts/send_text', methods=['GET'])
def tts_send_text():
if 'tts_sender' not in request.args:
tts_sender = ""
if 'tts_text' not in request.args:
return flask.make_response('{\"text\":"Argument \'tts_text\' not in request"}', 400)
return send_text(request.args['tts_sender'], request.args['tts_text'])
if __name__ == '__main__':
#send_text("","Blah Blah Blah")
#init()
api.run(host='0.0.0.0', port=42064)

68
standalone_tts_speaker.py Normal file
View File

@ -0,0 +1,68 @@
import flask
from flask import request
import tts
import config
import utilities_script as utility
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api = flask.Flask(__name__)
# enable/disable this to get web pages of crashes returned
api.config["DEBUG"] = False
def init():
praxis_logger_obj.log("init stuff")
def isTTS_URL_Check(message):
isNotBlocked = True
is_ttsEnabled = config.is_tts_Speaker_Enabled
is_tts_URL_Allowed = not config.is_tts_URL_Blocked
has_URL = False
if utility.contains_url(message):
has_URL = True
if is_tts_URL_Allowed:
if has_URL:
has_URL = False
if has_URL:
isNotBlocked = False
if not is_ttsEnabled:
isNotBlocked = False
return not isNotBlocked
def try_TTS(tts_sender, tts_text):
text_to_say: str = "%s says, %s" % (tts_sender, tts_text)
#tts.tts(str(text_to_say))
#tts.tts(str(tts_text))
if tts_sender == "":
text_to_say = tts_text
if isTTS_URL_Check(tts_text):
if not utility.contains_slur(tts_sender):
if not utility.contains_slur(text_to_say):
tts.tts(str(text_to_say))
return flask.make_response('', 200)
@api.route('/api/v1/tts/speech', methods=['GET'])
def tts_speech():
if 'tts_sender' not in request.args:
tts_sender = ""
else:
tts_sender = request.args['tts_sender']
if 'tts_text' not in request.args:
return flask.make_response('{\"text\":"Argument \'tts_text\' not in request"}', 400)
return try_TTS(tts_sender, request.args['tts_text'])
if __name__ == '__main__':
#init()
api.run(host='0.0.0.0', port=40085)

237
standalone_twitch_pubsub.py Normal file
View File

@ -0,0 +1,237 @@
import re
from json import loads
from urllib.parse import urlencode
import requests
import credentials
import config
from channel_rewards.channelRewards_base import AbstractChannelRewards
import channel_rewards.channelRewards_base
import twitchAPI
from twitchAPI.pubsub import PubSub
from twitchAPI.twitch import Twitch
from twitchAPI.types import AuthScope
from twitchAPI.oauth import UserAuthenticator
from pprint import pprint
from uuid import UUID
from cooldowns import Cooldown_Module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Twitch_Pubsub():
def __init__(self):
super().__init__()
self.credential : credentials.Twitch_Credential()
self.twitch : Twitch()
self.pubsub: PubSub()
self.target_scope = [AuthScope.WHISPERS_READ, AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.BITS_READ, AuthScope.CHANNEL_READ_SUBSCRIPTIONS]
self.uuid_whisper = None
self.uuid_channelPoints = None
self.uuid_bits = None
self.uuid_subs = None
self.cooldownModule: Cooldown_Module = Cooldown_Module()
self.cooldownModule.setupCooldown("twitchpubsub", 20, 32)
def setup(self):
self.twitch.authenticate_app(self.target_scope)
self.twitch.set_user_authentication(self.credential.pubsub_AccessToken, self.target_scope, self.credential.pubsub_RefreshToken)
def get_tokens(self):
self.twitch.authenticate_app(self.target_scope)
for scope_ in self.target_scope:
print(scope_)
auth = UserAuthenticator(self.twitch, self.target_scope, force_verify=True)
token, refresh_token = auth.authenticate()
if token is not None: print("found token")
if refresh_token is not None: print("found refresh_token")
print(token)
print(refresh_token)
self.twitch.set_user_authentication(token, self.target_scope, refresh_token)
def start(self):
self.pubsub = PubSub(self.twitch)
#self.pubsub.ping_frequency = 30
self.pubsub.start()
print("started")
def next(self):
user_id = self.twitch.get_users(logins=[config.autoJoin_TwitchChannel])['data'][0]['id']
if user_id is not None: print("found user_id")
print(user_id)
self.uuid_whisper = self.pubsub.listen_whispers(user_id, self.callback_whisper)
self.uuid_channelPoints = self.pubsub.listen_channel_points(user_id, self.callback_channelPoints)
self.uuid_bits = self.pubsub.listen_bits(user_id, self.callback_bits)
self.uuid_subs = self.pubsub.listen_channel_subscriptions(user_id, self.callback_subs)
#input('press ENTER to close...')
def stop(self):
self.pubsub.unlisten(self.uuid_whisper)
self.pubsub.unlisten(self.uuid_channelPoints)
self.pubsub.unlisten(self.uuid_bits)
self.pubsub.unlisten(self.uuid_subs)
self.pubsub.stop()
def callback_whisper(self, uuid: UUID, data: dict) -> None:
print('got callback for UUID ' + str(uuid))
pprint(data)
def callback_channelPoints(self, uuid: UUID, data: dict) -> None:
print("Channel Point Redemption")
print('got callback for UUID ' + str(uuid))
pprint(data)
#print("attempting to get data: ")
#print(data['data']['redemption']['user']['display_name'])
#print(data['data']['redemption']['reward']['title'])
#print(data['data']['redemption']['reward']['prompt'])
try:
userinput = data['data']['redemption']['user_input']
except:
userinput = ""
praxis_logger_obj.log("\n\n")
praxis_logger_obj.log(data['data']['redemption']['user']['display_name'])
praxis_logger_obj.log(data['data']['redemption']['reward']['title'])
praxis_logger_obj.log(AbstractChannelRewards.ChannelRewardsType.channelPoints)
praxis_logger_obj.log(data['data']['redemption']['reward']['prompt'])
praxis_logger_obj.log(userinput)
praxis_logger_obj.log(data)
self.callback_EXEC(
data['data']['redemption']['user']['display_name'],
data['data']['redemption']['reward']['title'],
AbstractChannelRewards.ChannelRewardsType.channelPoints,
data['data']['redemption']['reward']['prompt'],
userinput,
data)
def callback_bits(self, uuid: UUID, data: dict) -> None:
print("Bits Redemption")
print('got callback for UUID ' + str(uuid))
pprint(data)
praxis_logger_obj.log(data['data']['user_name'])
try:
userinput = data['data']['chat_message']
praxis_logger_obj.log(data['data']['chat_message'])
except:
userinput = ""
praxis_logger_obj.log(data)
self.callback_EXEC(
data['data']['user_name'],
"TwitchBits",
AbstractChannelRewards.ChannelRewardsType.twitch_bits,
userinput,
data['data']['bits_used'],
data)
def callback_subs(self, uuid: UUID, data: dict) -> None:
print("Subs Redemption")
print('got callback for UUID ' + str(uuid))
pprint(data)
try:
userinput = data['message']['sub_message']['message']
except:
userinput = ""
self.callback_EXEC(
data['message']['display_name'],
"TwitchSub",
AbstractChannelRewards.ChannelRewardsType.twitch_subs,
userinput,
"",
data)
def callback_EXEC(self, sender, rewardName:str, rewardType, rewardPrompt, userInput, raw_data):
try:
is_actionable = self.is_reward(rewardName, rewardType)
if is_actionable:
praxis_logger_obj.log("Trying to do the thing")
#if self.cooldownModule.isCooldownActive("twitchpubsub") == False:
self.exec_reward(sender, rewardName, rewardType, rewardPrompt, userInput, raw_data)
except:
print("something went wrong with a reward")
def is_reward(self, rewardName, rewardType):
# todo need to url-escape word
clean_param = urlencode({'reward_name': rewardName, 'reward_type':rewardType})
print(rewardName, rewardType)
#standalone_channelrewards
url = "http://standalone_channelrewards:42069/api/v1/reward?%s" % clean_param
resp = requests.get(url)
return resp.status_code == 200
def exec_reward(self, sender, rewardName, rewardType, rewardPrompt, userInput, realMessage):
params = urlencode(
{'reward_source': channel_rewards.channelRewards_base.AbstractChannelRewards.ChannelRewardsSource.Twitch,
'user_name': sender,
'reward_name': rewardName,
'reward_type': rewardType,
'reward_prompt': rewardPrompt,
'user_input' : userInput,
'bonus_data': realMessage})
#standalone_channelrewards
url = "http://standalone_channelrewards:42069/api/v1/exec_reward?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
#self.send_message(msg) #Cant Send messages with this pubsub library afaik
pass
else:
# todo handle failed requests
pass
#FINISH THIS EVENT LOG
def send_EventLog(self, eventName, eventTime, eventType, eventSender, eventData):
params = urlencode(
{'event_name': eventName,
'event_time': eventTime,
'event_type': eventType,
'eventSender': eventSender,
'event_data': eventData})
url = "http://standalone_eventlog:42008/api/v1/event_log/add_event?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
if __name__ == "__main__":
testModule = Twitch_Pubsub()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.credential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
testModule.twitch = Twitch(testModule.credential.pubsub_client_id, testModule.credential.pubsub_secret)
#pprint(testModule.twitch.get_users(logins=['thecuriousnerd']))
#testModule.get_tokens()
testModule.setup()
testModule.start()
testModule.next()
#testModule.stop()

221
standalone_twitch_script.py Normal file
View File

@ -0,0 +1,221 @@
from datetime import datetime
import re
from json import loads
from urllib.parse import urlencode
import requests
import twitch
import twitch.chat
import config as config
import credentials
from cooldowns import Cooldown_Module
import commands.command_base
import utilities_script as utility
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
class Twitch_Module():
def __init__(self):
super().__init__()
self.twitchCredential: credentials.Twitch_Credential
self.chat: twitch.Chat
self.block_chat_url: bool = True
self.whitelisted_users: list = ["thecuriousnerd"]
# don't freak out, this is *merely* a regex for matching urls that will hit just about everything
self._urlMatcher = re.compile(
"(https?:(/{1,3}|[a-z0-9%])|[a-z0-9.-]+[.](com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw))")
# Default Twitch Chat limit is 20 per 30 seconds
# If Mod or Op, Twitch Chat limit is 100 per 30 seconds
self.cooldownModule: Cooldown_Module = Cooldown_Module()
self.cooldownModule.setupCooldown("twitchChat", 20, 32)
def join_channel(self, credential: credentials.Twitch_Credential, channel_name: str):
channel_name = "#" + channel_name
print("Connecting to Channel: " + channel_name + "...")
if credential is None:
credential = self.twitchCredential
self.chat = twitch.Chat(
channel=channel_name,
nickname=credential.username,
oauth=credential.oauth,
# LIBRARY UPDATE BROKE THE FOLLOWING LINE [FIX THIS]
# helix = twitch.Helix(credential.helix, use_cache=True)
)
self.chat.subscribe(self.twitch_chat)
print("Connected to Channel: ", channel_name)
def leave_channel(self):
print("Leaving Channel", self.chat.channel)
self.chat.irc.leave_channel(self.chat.channel)
self.chat.irc.socket.close()
def send_message(self, message):
isBlocked = self.isChannel_inConfigList(self.chat.channel, config.block_TwitchChannelsMessaging)
# print("isBlocked: " + str(isBlocked) + " for: " + self.chat.channel)
#if self.
if utility.contains_slur(message): isBlocked = True
if self.cooldownModule.isCooldownActive(
"twitchChat") == False and not isBlocked and not config.blockAll_TwitchChatChannelsMessaging:
self.chat.send(message)
# print("Sent ChatMSG")
self.cooldownModule.actionTrigger("twitchChat")
def eval_command(self, message):
command, rest = utility.parse_line(message.text)
try:
is_actionable = self.is_command(command)
if is_actionable:
self.send_EventLog(command, str(datetime.now()), "command.twitch", message.sender, rest)
praxis_logger_obj.log("Sent a thing")
except:
praxis_logger_obj.log("something went wrong with Event LOG")
try:
is_actionable = self.is_command(command)
if is_actionable:
if self.cooldownModule.isCooldownActive("twitchChat") == False:
self.exec_command(message ,command, rest)
except:
praxis_logger_obj.log("something went wrong with a command")
def is_command(self, word: str) -> bool:
# todo need to url-escape word
clean_param = urlencode({'name': word})
url = "http://standalone_command:42010/api/v1/command?%s" % clean_param
resp = requests.get(url)
return resp.status_code == 200
def exec_command(self, realMessage: twitch.chat.Message, command: str, rest: str):
# todo need to url-escape command and rest
params = urlencode(
{'command_source': commands.command_base.AbstractCommand.CommandSource.Twitch,
'user_name': realMessage.sender,
'command_name': command,
'rest': rest,
'bonus_data': realMessage})
#standalone_command
url = "http://standalone_command:42010/api/v1/exec_command?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
self.send_message(msg)
else:
# todo handle failed requests
pass
def eval_tts(self, message: twitch.chat.Message):
command, rest = utility.parse_line(message.text)
try:
is_actionable = self.is_command(command)
if not is_actionable:
self.exec_tts(message)
except:
print("something went wrong with tts")
def exec_tts(self, message: twitch.chat.Message):
if config.autoEnabled_TwitchTTS:
if config.autoEnabled_TwitchTTS_SpeakersList_Only:
tempName = message.sender.lower()
if tempName in config.allowedTTS_List:
text_to_say: str = "%s says, %s" % (message.sender, message.text)
self.exec_tts_sender("", text_to_say)
else:
text_to_say: str = "%s says, %s" % (message.sender, message.text)
self.exec_tts_sender("", text_to_say)
def send_EventLog(self, command, eventTime, eventType, eventSender, rest):
params = urlencode(
{'event_name': command,
'event_time': eventTime,
'event_type': eventType,
'eventSender': eventSender,
'event_data': rest})
url = "http://standalone_eventlog:42008/api/v1/event_log/add_event?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def exec_tts_sender(self, username, message):
params = urlencode({'tts_sender': username, 'tts_text': message})
#standalone_tts_core
url = "http://localhost:42064/api/v1/tts/send_text?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
pass
def send_whisper(self, user, message):
pass
# This reacts to messages
def twitch_chat(self, message: twitch.chat.Message) -> None:
print("[#" + message.channel + "](" + message.sender + ")> " + message.text)
command, rest = utility.parse_line(message.text)
praxis_logger_obj.log("\n[#" + message.channel + "](" + message.sender + ")> " + message.text)
self.eval_command(message)
self.eval_tts(message)
#try:
# is_actionable = self.is_command(command)
# if is_actionable:
# if self.cooldownModule.isCooldownActive("twitchChat") == False:
# self.exec_command(message ,command, rest)
#except:
# print("something went wrong with a command")
def isChannel_inConfigList(self, selectedChannel, selectedList):
# print(channel)
# print(selectedList)
is_Self = False
for twitchChannel in selectedList:
if twitchChannel == selectedChannel:
is_Self = True
# if is_Self:
# print("Is Self")
# if not is_Self:
# print("Is Not Self")
return is_Self
if __name__ == "__main__":
testModule = Twitch_Module()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.twitchCredential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
#testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
for twitchChannel in config.autoJoin_TwitchChannels:
testModule.join_channel(None, twitchChannel)

205
standalone_user_client.py Normal file
View File

@ -0,0 +1,205 @@
from enum import Enum
from os import F_OK
import tempText_Module
import time
import config as config
from datetime import datetime
import re
from json import loads
from urllib.parse import urlencode
import requests
import flask
from flask import Flask, request, after_this_request
import credentials
import commands.loader as command_loader
from commands.command_base import AbstractCommand
from cooldowns import Cooldown_Module
import utilities_script as utility
import chyron_module
import timers_module
import random
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api:Flask = Flask(__name__)
api.config["DEBUG"] = True
def init():
print("starting up... ",)
def handle_request_get(requestName, requestType, requestData):
if requestType == "list":
if requestName == "Chyron":
response = request_get_list("XXXXXXXXX", "42010")
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
if requestName == "Commands":
response = request_get_list("standalone_command", "42010")
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
if requestName == "Rewards":
response = request_get_list("standalone_channelrewards", "42069")
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
if requestName == "Timers":
response = request_get_list("XXXXXXXXX", "42010")
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
if requestName == "TextSources":
response = request_get_list("XXXXXXXXX", "42010")
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
if requestName == "EventHistory":
params = urlencode(
{'request_name': requestName,
'request_type': requestType,
'request_data': requestData})
response = request_get_eventlist(params)
return flask.make_response("{\"message\": \"%s\"}" % response, 200, {"Content-Type": "application/json"})
else:
return flask.make_response("{\"message\": \"%s\"}" % "Invalid Request Name", 400, {"Content-Type": "application/json"})
def request_get_list(serviceName, servicePort):
try:
url = "http://"+ serviceName + ":"+ servicePort + "/api/v1/get_list/all"
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
praxis_logger_obj.log(msg)
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return flask.make_response("{\"message\": \"%s\"}" % "Minor Mess up on get list", 200, {"Content-Type": "application/json"})
except:
return flask.make_response("{\"message\": \"%s\"}" % "Major Mess up on get list", 200, {"Content-Type": "application/json"})
def request_get_eventlist(params):
try:
url = "http://standalone_eventlog:42008/api/v1/event_log/get_events?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return msg
# todo send to logger and other relevent services
else:
# todo handle failed requests
return flask.make_response("{\"message\": \"%s\"}" % "Minor Mess up on get eventlist", 200, {"Content-Type": "application/json"})
except:
return flask.make_response("{\"message\": \"%s\"}" % "Major Mess up on get eventlist", 200, {"Content-Type": "application/json"})
def request_reRunEvent(eventName, eventTime, eventType, eventSender, eventData):
try:
params = urlencode(
{'eventName': eventName,
'eventTime': eventTime,
'eventType': eventType,
'eventSender': eventSender,
'eventData': eventData})
url = "http://standalone_eventlog:42008/api/v1/event_log/reRunEvent?%s" % params
resp = requests.get(url)
if resp.status_code == 200:
print("Got the following message: %s" % resp.text)
data = loads(resp.text)
msg = data['message']
if msg is not None:
return flask.make_response("{\"message\": \"%s\"}" % msg, 200, {"Content-Type": "application/json"})
# todo send to logger and other relevent services
else:
# todo handle failed requests
return flask.make_response('Something Went a little bit Wrong rerunning an event', 400)
except:
return flask.make_response('Something Went Wrong rerunning an event', 400)
def handle_request_set(requestName, requestType, requestData):
if requestType == "update":
if requestName == "Chyron":
pass
if requestName == "Commands":
pass
elif requestType == "delete":
if requestName == "Chyron":
pass
if requestName == "Commands":
pass
@api.route('/')
def bot_StatusIcon():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return flask.make_response('Client Service: OK', 200)
@api.route('/api/v1/user_client/get', methods=['GET'])
def get_data():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'request_name' not in request.args:
return flask.make_response('{\"text\":"Argument \'request_name\' not in request"}', 400)
if 'request_type' not in request.args:
return flask.make_response('{\"text\":"Argument \'request_type\' not in request"}', 400)
if 'request_data' not in request.args:
requestData = None
else:
requestData = request.args['request_data']
return handle_request_get(request.args['request_name'], request.args['request_type'], requestData)
@api.route('/api/v1/user_client/set', methods=['GET'])
def set_data():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'request_type' not in request.args:
return flask.make_response('{\"text\":"Argument \'request_type\' not in request"}', 400)
@api.route('/api/v1/user_client/event_log/reRunEvent', methods=['GET'])
def EventLog_reRunEvent():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
if 'eventName' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventName\' not in request"}', 400)
if 'eventTime' not in request.args:
sentTime = request.args('eventTime')
else:
sentTime = None
if 'eventType' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventType\' not in request"}', 400)
if 'eventSender' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventSender\' not in request"}', 400)
if 'eventData' not in request.args:
return flask.make_response('{\"text\":"Argument \'eventData\' not in request"}', 400)
#return flask.make_response("test", 200)
return request_reRunEvent(request.args['eventName'], sentTime, request.args['eventType'], request.args['eventSender'], request.args['eventData'])
if __name__ == "__main__":
init()
api.run(host="0.0.0.0", port = 42055)

66
standalone_webSource.py Normal file
View File

@ -0,0 +1,66 @@
from enum import Enum
from os import F_OK
import tempText_Module
import time
import config as config
from flask import Flask
import credentials
import commands.loader as command_loader
from commands.command_base import AbstractCommand
from cooldowns import Cooldown_Module
import utilities_script as utility
import chyron_module
import timers_module
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api:Flask = Flask(__name__)
api.config["DEBUG"] = True
def init():
print("starting up... ",)
@api.route('/')
def hello_world():
return 'I can see your Ghost!'
@api.route('/chyron')
def textSource_chyron():
tempModule = chyron_module.Chyron_Module()
return tempModule.getChyronFile()
@api.route('/text/<file_name>/')
def textSource_tempText(file_name):
print("trying file: ", file_name)
tempModule = tempText_Module.tempText_Module()
return tempModule.getTempTextFile(file_name)
@api.route('/timer/status/<timer_name>/')
def textSource_timerStatus(timer_name):
tempModule = timers_module.Timers_Module()
result = tempModule.checkTimerStatus_fromFiles(timer_name)
returnString = "Timer %s is %s" % (timer_name, result)
return returnString
@api.route('/timer/time/<timer_name>/')
def textSource_timerTime(timer_name):
tempModule = timers_module.Timers_Module()
result = tempModule.checkTime_fromFiles(timer_name)
if result is None: result = ""
returnString = result
return returnString
if __name__ == "__main__":
init()
api.run(host="0.0.0.0", port = 42088)

View File

@ -1,12 +1,11 @@
import config as config import config as config
import db
import credentials import credentials
class Test_Module(): class Test_Module():
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.dbCredential: credentials.DB_Credential
def main(self): def main(self):
print("[TEST Module]> test") print("[TEST Module]> test")
@ -15,7 +14,4 @@ class Test_Module():
if __name__ == "__main__": if __name__ == "__main__":
testModule = Test_Module() testModule = Test_Module()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
testModule.main() testModule.main()

205
timers_module.py Normal file
View File

@ -0,0 +1,205 @@
import os
import json
from praxis_logging import praxis_logger
import time
import datetime
import utilities_script as utility
import importlib
import importlib.util
import sys
import inspect
class timer():
def __init__(self,
name,
startTime = datetime.datetime.now,
endTime = datetime.datetime.now,
trigger = "",
trigger_exec = "",
timerFormat = "%Y-%m-%d %H:%M:%S.%f",
tempTimer = True):
self.name = name
self.startTime = startTime
self.endTime = endTime
self.trigger = trigger
self.trigger_exec = trigger_exec
self.timerFormat = timerFormat
self.tempTimer = tempTimer # If enabled this will cause the Timer to be deleted upon shutdown or startup
class Timers_Module():
def __init__(self):
super().__init__()
self.timersList = {}
def main(self):
self.createTimer("test_timer", seconds=15)
#self.createTimer("mega_test_timer", hours=20, seconds=10)
#self.updateTimersList()
#for t in self.timersList:
#print(t)
#while True:
#for t in self.timersList:
#print(t)
#print(self.checkTimerStatus_fromFiles("test_timer"))
#print(self.checkTimerStatus_fromFiles("test_timer_2"))
#time.sleep(0.5)
def updateTimersList(self):
dic = {}
implementations = self.get_implementations_dir()
for dirName, subdirList, fileList in os.walk(implementations):
for file in fileList:
print(file)
name, startTime, endTime, trigger, trigger_exec, timerFormat, tempTimer = self.readFile(file)
newTimer = timer(
name,
datetime.datetime.strptime(startTime, timerFormat),
datetime.datetime.strptime(endTime, timerFormat),
trigger,
trigger_exec,
utility.strToBool(tempTimer))
self.timersList[newTimer.name] = newTimer
return dic
def get_base_dir(self) -> str:
cwd = os.getcwd()
split = os.path.split(cwd)
current = split[len(split) - 1]
if current == 'timers':
return self.check_dir(cwd)
elif current == 'Praxis_Bot' or current == 'Praxis':
return self.check_dir(os.path.join(cwd, "timers"))
else:
print("could not find working directory for Praxis_Bot/timers")
raise Exception
def get_implementations_dir(self) -> str:
return self.check_dir(os.path.join(self.get_base_dir()))
def check_dir(self, path: str) -> str:
if not os.path.exists(path):
os.mkdir(path, 0x777)
return path
def createTimer(self, name, days=0, hours=0, minutes=0, seconds=0, microseconds=0, trigger="", trigger_exec="", timerFormat='%Y-%m-%d %H:%M:%S.%f', tempTimer=True):
startTime = datetime.datetime.now()
targetTime = startTime + datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds, microseconds=microseconds)
newTimer= timer(name, startTime, targetTime, trigger, trigger_exec, timerFormat, tempTimer)
self.timersList[newTimer.name] = newTimer
self.makeFile(newTimer)
def checkTimerStatus_fromFiles(self, name):
try:
if name is not None:
name, startTime, endTime, trigger, trigger_exec, timerFormat, tempTimer = self.readFile(name+".json")
if datetime.datetime.strptime(endTime, timerFormat) < datetime.datetime.now():
#print("do timer thing")
#self.TIMER_EXEC(name, datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S.%f'), datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S.%f'), trigger, trigger_exec, utility.strToBool(tempTimer))
return True
else:
return False
else:
return False
except:
return None
def checkTime_fromFiles(self, name):
try:
name, startTime, endTime, trigger, trigger_exec, timerFormat, tempTimer = self.readFile(name+".json")
if name is not None:
endT = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S.%f')
if endT.timestamp() < datetime.datetime.now().timestamp():
print("do timer thing")
endT = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S.%f')
curTime = datetime.datetime.now()
#curTime = datetime.datetime.strptime(curTime, '%Y-%m-%d %H:%M:%S.%f')
result = endT - datetime.timedelta(days=curTime.day, hours=curTime.hour, minutes=curTime.minute, seconds=curTime.second, microseconds=curTime.microsecond)
print(type(result))
self.TIMER_EXEC(name, datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S.%f'), datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S.%f'), trigger, trigger_exec, utility.strToBool(tempTimer))
fixedEndTime = datetime.datetime.strftime(result, timerFormat)
return str("Timer Done")
else:
endT = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S.%f')
curTime = str(datetime.datetime.now())
curTime = datetime.datetime.strptime(curTime, '%Y-%m-%d %H:%M:%S.%f')
result = endT - datetime.timedelta(days=curTime.day, hours=curTime.hour, minutes=curTime.minute, seconds=curTime.second, microseconds=curTime.microsecond)
fixedEndTime = datetime.datetime.strftime(result, timerFormat)
#fixedTimeDelta = fixedEndTime - fixedCurTime
#praxis_logger.log(str(timeDelta))
return str(fixedEndTime)
else:
return None
except:
return None
def deleteTimer(self, name):
try:
self.deleteFile(name+".json")
except:
print("Deletion Error")
self.timersList.pop(name)
def TIMER_EXEC(self, name, startTime, endTime, trigger, trigger_exec, tempTimer):
print(trigger, trigger_exec, "at", endTime)
if tempTimer == True:
print("deleting " + name)
self.deleteTimer(name)
def makeFile(self, timer_obj:timer):
dir = utility.get_dir("timers")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = timer_obj.name + ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
with open(real_file_path, 'w') as cred_w:
#data = json.load(timer_obj)
dic = {}
dic['name'] = timer_obj.name
dic['startTime'] = str(timer_obj.startTime)
dic['endTime'] = str(timer_obj.endTime)
dic['trigger'] = timer_obj.trigger
dic['trigger_exec'] = timer_obj.trigger_exec
dic['timerFormat'] = timer_obj.timerFormat
dic['tempTimer'] = str(timer_obj.tempTimer)
json.dump(dic, cred_w, indent=2)
def readFile(self, name):
dir = utility.get_dir("timers")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = name #+ ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
with open(real_file_path, 'r') as cred_r:
data = json.load(cred_r)
name = data['name']
startTime = data['startTime']
endTime = data['endTime']
trigger = data['trigger']
trigger_exec = data['trigger_exec']
timerFormat = data['timerFormat']
tempTimer = data['tempTimer']
return name, startTime, endTime, trigger, trigger_exec, timerFormat, tempTimer
def deleteFile(self, name):
dir = utility.get_dir("timers")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = name #+ ".json"
real_file_path = os.path.join(script_dir, dir, relative_path)
os.remove(real_file_path)
if __name__ == "__main__":
testModule = Timers_Module()
testModule.main()

View File

@ -0,0 +1,71 @@
import credentials
import config
import twitchAPI
from twitchAPI.pubsub import PubSub
from twitchAPI.twitch import Twitch
from twitchAPI.types import AuthScope
from twitchAPI.oauth import UserAuthenticator
from pprint import pprint
from uuid import UUID
import json
import utilities_script as utility
import os
class Twitch_Credential_Maker():
def __init__(self):
super().__init__()
self.credential : credentials.Twitch_Credential()
self.twitch : Twitch()
self.target_scope = [AuthScope.WHISPERS_READ, AuthScope.CHANNEL_READ_REDEMPTIONS, AuthScope.BITS_READ, AuthScope.CHANNEL_READ_SUBSCRIPTIONS]
def get_tokens(self):
self.twitch.authenticate_app(self.target_scope)
for scope_ in self.target_scope:
print(scope_)
auth = UserAuthenticator(self.twitch, self.target_scope, force_verify=True)
token, refresh_token = auth.authenticate()
if token is not None: print("found token")
if refresh_token is not None: print("found refresh_token\n")
print("token: ", token)
print("refresh_token: ", refresh_token)
print("")
return token, refresh_token
def updateCredentialsFile(self, token, refreshToken):
dir = utility.get_dir("credentials")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = "credentials/twitch.json"
real_file_path = os.path.join(script_dir, relative_path)
with open(real_file_path, 'r') as cred_r:
data = json.load(cred_r)
data['pubsub_AccessToken'] = token
data['pubsub_RefreshToken'] = refreshToken
os.remove(real_file_path)
with open(real_file_path, 'w') as cred_w:
json.dump(data, cred_w, indent=2)
if __name__ == "__main__":
testModule = Twitch_Credential_Maker()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.credential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
testModule.twitch = Twitch(testModule.credential.pubsub_client_id, testModule.credential.pubsub_secret)
#pprint(testModule.twitch.get_users(logins=['thecuriousnerd']))
token, refreshToken = testModule.get_tokens()
print("Update credentials file? (y/n)")
response = input()
if "y" in response.lower():
testModule.updateCredentialsFile(token, refreshToken)
print("Ready to close")
input()

View File

@ -1,201 +0,0 @@
from typing import Sequence
import random
import re
import utilities_script as utilities
import twitch
import twitch.chat
import config as config
import db
import tts
import commands.loader as command_loader
import credentials
from commands.command_base import AbstractCommand
from cooldowns import Cooldown_Module
class Twitch_Module():
def __init__(self):
super().__init__()
self.twitchCredential: credentials.Twitch_Credential
self.dbCredential: credentials.DB_Credential
self.db_manager: db.db_module = db.db_module()
self.chat: twitch.Chat
self.commands = command_loader.load_commands_new(AbstractCommand.CommandType.TWITCH)
self.tts_enabled: bool = False
self.block_tts_url: bool = False
self.tts_whitelist_enabled: bool = False
self.block_chat_url: bool = True
self.whitelisted_users: list = ["thecuriousnerd"]
# don't freak out, this is *merely* a regex for matching urls that will hit just about everything
self._urlMatcher = re.compile(
"(https?:(/{1,3}|[a-z0-9%])|[a-z0-9.-]+[.](com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw))")
# Default Twitch Chat limit is 20 per 30 seconds
# If Mod or Op, Twitch Chat limit is 100 per 30 seconds
self.cooldownModule:Cooldown_Module = Cooldown_Module()
self.cooldownModule.setupCooldown("twitchChat", 20, 32)
self.allow_rgbLightControl = config.autoEnabled_Twitch_rgbLightControl
def join_channel(self, credential: credentials.Twitch_Credential, channel_name:str):
channel_name = "#" + channel_name
print("Connecting to Channel: " + channel_name + "...")
if credential is None:
credential = self.twitchCredential
self.chat = twitch.Chat(
channel = channel_name,
nickname = credential.username,
oauth = credential.oauth,
# LIBRARY UPDATE BROKE THE FOLLOWING LINE [FIX THIS]
#helix = twitch.Helix(credential.helix, use_cache=True)
)
self.chat.subscribe(self.twitch_chat)
print("Connected to Channel: ", channel_name)
def leave_channel(self):
print("Leaving Channel", self.chat.channel)
self.chat.irc.leave_channel(self.chat.channel)
self.chat.irc.socket.close()
def send_message(self, message):
isBlocked = self.isChannel_inConfigList(self.chat.channel, config.block_TwitchChannelsMessaging)
#print("isBlocked: " + str(isBlocked) + " for: " + self.chat.channel)
if self.cooldownModule.isCooldownActive("twitchChat") == False and not isBlocked and not config.blockAll_TwitchChatChannelsMessaging:
self.chat.send(message)
#print("Sent ChatMSG")
self.cooldownModule.actionTrigger("twitchChat")
def send_whisper(self, user, message):
pass
# This reacts to messages
def twitch_chat(self, message: twitch.chat.Message) -> None:
print("[#" + message.channel + "](" + message.sender + ")> " + message.text)
if not self.isSenderBot(message):
if self.cooldownModule.isCooldownActive("twitchChat") == False:
print("Pre Eval")
self.eval_commands(message)
self.tts_message(message)
def eval_commands(self, message: twitch.chat.Message):
print("evaling command")
# containsURL: bool = self.contains_url(message)
try:
#first_space_idx = message.text.index(' ')
# This fixes a error where if you send a command without arguments it fails because
# it cant find the substring.
if message.text.find(" ") != -1:
first_space_idx = message.text.index(' ')
else:
first_space_idx = -1
command_text = ' '
if first_space_idx > -1:
command_text = message.text[0:first_space_idx]
else:
command_text = message.text
command = self.commands[command_text]
if command is not None and command.command_type is AbstractCommand.CommandType.TWITCH:
print("running command")
command.do_command(self, message)
except Exception as e:
# Undo the following for debug stuff
#print(e)
print("failed command")
pass # we don't care
def tts_message(self, message: twitch.chat.Message):
isBlocked = self.isChannel_inConfigList(self.chat.channel, config.block_TwitchChannelsTTS)
isForced = (self.isChannel_inConfigList(self.chat.channel, config.force_TwitchChannelsTTS) and not config.blockAll_TwitchChatChannelsTTS)
if (not self.contains_slur(message)) and (self.isTTS_URL_Enabled(message)):
if self.tts_enabled and not isBlocked and not config.blockAll_TwitchChatChannelsTTS or isForced or config.forceAll_TwitchChatChannelsTTS:
if not message.text.startswith('!'):
text_to_say: str = "%s says, %s" % (message.sender, message.text)
channel_text = "%s user msg" % message.channel
tts.tts(text_to_say)
def contains_url(self, message: twitch.chat.Message):
containsURL = re.search(self._urlMatcher, message.text.lower()) is not None
if containsURL:
print("<{ link detected! }> " + " [#" + message.channel + "](" + message.sender + ") sent a link in chat")
return containsURL
# Checks if Sender is bot.
def isSenderBot(self, message: twitch.chat.Message):
isBot = False
for bot in config.botList:
if message.sender.lower() == bot.lower():
isBot = True
print("<{ bot detected! }> " + " [#" + message.channel + "](" + message.sender + ") is a bot")
return isBot
# Checks for basic slurs.
def contains_slur(self, message: twitch.chat.Message):
containsSlur: bool = False
parsedMessage = message.text.split(" ")
for word in parsedMessage:
for slur in config.slurList:
if word.lower() == slur:
containsSlur = True
break # we want to immediately escape if we found a slur
if containsSlur:
break
if containsSlur:
print("<{ slur detected! }> " + " [#" + message.channel + "](" + message.sender + ") used a slur in chat")
return containsSlur
def isTTS_URL_Enabled(self, message: twitch.chat.Message):
is_ttsEnabled = False
if not config.blockAll_TTS_URL_Twitch or not self.block_tts_url:
if not self.contains_url(message):
is_ttsEnabled = True
return is_ttsEnabled
def isChannel_inConfigList(self, selectedChannel, selectedList):
#print(channel)
#print(selectedList)
is_Self = False
for twitchChannel in selectedList:
if twitchChannel == selectedChannel:
is_Self = True
#if is_Self:
# print("Is Self")
#if not is_Self:
# print("Is Not Self")
return is_Self
# This is a old function used prior to the creation of the Twitch_Module class above.
# I need to make a new one for the class.
def main_chat_commands_check(channel, sender, text):
response = db.basic_command_trigger(channel, sender, text)
if response == "$$None$$":
pass
else:
print("Curious Nerd Response Function:")
print(response)
if __name__ == "__main__":
testModule = Twitch_Module()
credentials_manager = credentials.Credentials_Module()
credentials_manager.load_credentials()
testModule.twitchCredential = credentials_manager.find_Twitch_Credential(config.credentialsNickname)
testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
for twitchChannel in config.autojoinTwitchChannels:
testModule.join_channel(None, twitchChannel)

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2017 Materialize
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,90 @@
<p align="center">
<a href="http://materializecss.com/">
<img src="http://materializecss.com/res/materialize.svg" width="150">
</a>
<h3 align="center">MaterializeCSS</h3>
<p align="center">
Materialize, a CSS Framework based on material design.
<br>
<a href="http://materializecss.com/"><strong>-- Browse the docs --</strong></a>
<br>
<br>
<a href="https://travis-ci.org/Dogfalo/materialize">
<img src="https://travis-ci.org/Dogfalo/materialize.svg?branch=master" alt="Travis CI badge">
</a>
<a href="https://badge.fury.io/js/materialize-css">
<img src="https://badge.fury.io/js/materialize-css.svg" alt="npm version badge">
</a>
<a href="https://cdnjs.com/libraries/materialize">
<img src="https://img.shields.io/cdnjs/v/materialize.svg" alt="CDNJS version badge">
</a>
<a href="https://david-dm.org/Dogfalo/materialize">
<img src="https://david-dm.org/Dogfalo/materialize/status.svg" alt="dependencies Status badge">
</a>
<a href="https://david-dm.org/Dogfalo/materialize#info=devDependencies">
<img src="https://david-dm.org/Dogfalo/materialize/dev-status.svg" alt="devDependency Status badge">
</a>
<a href="https://gitter.im/Dogfalo/materialize">
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter badge">
</a>
</p>
## Table of Contents
- [Quickstart](#quickstart)
- [Documentation](#documentation)
- [Supported Browsers](#supported-browsers)
- [Changelog](#changelog)
- [Testing](#testing)
- [Contributing](#contributing)
- [Copyright and license](#copyright-and-license)
## Quickstart:
Read the [getting started guide](http://materializecss.com/getting-started.html) for more information on how to use materialize.
- [Download the latest release](https://github.com/Dogfalo/materialize/releases/latest) of materialize directly from GitHub.
- Clone the repo: `git clone https://github.com/Dogfalo/materialize.git`
- Include the files via [cdnjs](https://cdnjs.com/libraries/materialize). More [here](http://materializecss.com/getting-started.html).
- Install with [npm](https://www.npmjs.com): `npm install materialize-css`
- Install with [Bower](https://bower.io): `bower install materialize`
- Install with [Atmosphere](https://atmospherejs.com): `meteor add materialize:materialize`
## Documentation
The documentation can be found at <http://materializecss.com>. To run the documentation locally on your machine, you need [Node.js](https://nodejs.org/en/) installed on your computer.
### Running documentation locally
Run these commands to set up the documentation:
```bash
git clone https://github.com/Dogfalo/materialize
cd materialize
npm install
```
Then run `grunt monitor` to compile the documentation. When it finishes, open a new browser window and navigate to `localhost:8000`. We use [BrowserSync](https://www.browsersync.io/) to display the documentation.
### Documentation for previous releases
Previous releases and their documentation are available for [download](https://github.com/Dogfalo/materialize/releases).
## Supported Browsers:
Materialize is compatible with:
- Chrome 35+
- Firefox 31+
- Safari 7+
- Opera
- Edge
- IE 10+
## Changelog
For changelogs, check out [the Releases section of materialize](https://github.com/Dogfalo/materialize/releases) or the [CHANGELOG.md](CHANGELOG.md).
## Testing
We use Jasmine as our testing framework and we're trying to write a robust test suite for our components. If you want to help, [here's a starting guide on how to write tests in Jasmine](CONTRIBUTING.md#jasmine-testing-guide).
## Contributing
Check out the [CONTRIBUTING document](CONTRIBUTING.md) in the root of the repository to learn how you can contribute. You can also browse the [help-wanted](https://github.com/Dogfalo/materialize/labels/help-wanted) tag in our issue tracker to find things to do.
## Copyright and license
Code copyright 2017 Materialize. Code released under the MIT license.

9389
user_client/v1/css/materialize.css vendored Normal file

File diff suppressed because it is too large Load Diff

16
user_client/v1/css/materialize.min.css vendored Normal file

File diff suppressed because one or more lines are too long

307
user_client/v1/index.html Normal file
View File

@ -0,0 +1,307 @@
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Praxis Bot Control Panel</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!--Import materialize.css-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="css/materialize.css" media="screen,projection"/>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
</head>
<body>
<div class="row">
<div class="col s12 blue sticky ontop">
<ul class="tabs blue">
<li class="tab col s3"><a class="active" href="#Home" style="color: white;">Home</a></li>
<li class="tab col s3 hide"><a href="#Settings" style="color: white;">Settings</a></li>
<li class="tab col s3 "><a href="#About" style="color: white;">About</a></li>
</ul>
</div>
</div>
<div id="Home">
<div id="" class="row bodyarea" style="">
<div id="sidebar_area" class="col s12 m3 hide-on-small-and-down card" style="position: fixed;">
<div style="" onclick="BotStatus()"><p id="BotStatus" class="card noselect" style="padding-left: 3px;padding-right: 3px;">Bot Status: ??</p></div>
<div class="row" style="padding-left: 3px;" style="">
<a href="index.html"><div class="s12 card waves-effect waves-light btn-large colsInSideBar" style="background-color: #42A5F5;">
<i class="material-icons">arrow_upward</i>
</div></a>
<div class="lineSeperator blue"></div>
<a href="#Chyron"><div class="s12 card waves-effect waves-light btn-large colsInSideBar hide" style="background-color: #42A5F5;">
<p>Chyron</p>
</div></a>
<a href="#Commands"><div class="s12 card waves-effect waves-light btn-large colsInSideBar" style="background-color: #42A5F5;">
<p>Commands</p>
</div></a>
<a href="#Rewards"><div class="s12 card colsInSideBar waves-effect waves-light btn-large" style="background-color: #42A5F5;">
<p>Rewards</p>
</div></a>
<a href="#Timers"><div class="s12 card colsInSideBar waves-effect waves-light btn-large hide" style="background-color: #42A5F5;">
<p>Timers</p>
</div></a>
<a href="#TextSources"><div class="s12 card colsInSideBar waves-effect waves-light btn-large hide" style="background-color: #42A5F5;">
<p>Text Sources</p>
</div></a>
<a href="#EventHistory"><div class="lineSeperator blue"></div>
<div class="s12 card colsInSideBar waves-effect waves-light btn-large" style="background-color: #42A5F5;">
<p>Event History</p>
</div></a>
<a href="#Services"><div class="s12 card colsInSideBar waves-effect waves-light btn-large hide" style="background-color: #42A5F5;">
<p>Services</p>
</div></a>
</div>
</div>
<div id="main_area" class="col s12 m9 right card">
<div id="Chyron" style="padding-top: 20px;"><div class="rowsInMain center card hide">
<a class="btn-floating btn-large waves-effect waves-light blue right" style="margin-right: 10px;">
<i class="material-icons">refresh</i>
</a>
<a class="btn-floating btn-large waves-effect waves-light green right" style="margin-right: 10px;">
<i class="material-icons">add</i>
</a>
<h3>Chyron:</h3></div>
<div class="rowsInMain row card hide" style="margin-right: 20px;margin-left: 20px;margin-top: 30px;margin-bottom: 30px;">
<div class="col s12 switch hide" style="top: -20px;position: relative;padding-left: 10px;"><label>Enabled:<input type="checkbox"><span class="lever"></span></label></div>
<div class="col s4"><p>Section Name:</p>
<div class="input-field inline" style="width: 80%;">
<input id="section_name_inline" type="text" class="validate">
<label for="section_name_inline">Section Name</label>
</div>
</div>
<div class="col s4"><p>Title:</p>
<div class="input-field inline" style="width: 80%;">
<input id="title_inline" type="text" class="validate">
<label for="title_inline">Title</label>
</div>
</div>
<div class="col s4"><p>Content:</p>
<div class="input-field inline" style="width: 80%;">
<input id="content_inline" type="text" class="validate">
<label for="content_inline">Text</label>
</div>
</div>
<div style="position: absolute; right: 0; top: 0; width: 3em;" class="col s1 btn red waves-effect"><i class="material-icons">delete</i></div>
</div>
<div id="Commands" style="padding-top: 20px;"><div class="rowsInMain center card">
<a onclick="updateCommandList()" class="btn-floating btn-large waves-effect waves-light blue right" style="margin-right: 10px;">
<i class="material-icons">refresh</i>
</a>
<h3>Commands:</h3></div>
<div id="CommandRowWrapper">
</div>
</div>
<div id="Rewards" style="padding-top: 20px;"><div class="rowsInMain center card">
<a onclick="updateRewardList()" class="btn-floating btn-large waves-effect waves-light blue right" style="margin-right: 10px;">
<i class="material-icons">refresh</i>
</a>
<h3>Rewards:</h3></div>
<div id="RewardRowWrapper">
</div>
</div>
<div id="Timers" style="padding-top: 20px;"></div><div class="rowsInMain center card hide">
<a class="btn-floating btn-large waves-effect waves-light red right hide-on-small-and-down" style="margin-right: 10px;">
<i class="material-icons">add</i>
</a><h3>Timers:</h3></div>
<div class="rowsInMain row card hide" style="margin-right: 20px;margin-left: 20px;margin-top: 30px;margin-bottom: 30px;">
<div class="col s3"><p>Timer Name:</p></div>
<div class="col s3"><p>Trigger:</p></div>
<div class="col s3"><p>Trigger_EXEC:</p></div>
<div class="col s "><p>O</p></div>
</div>
<div id="TextSources" style="padding-top: 20px;"></div><div class="rowsInMain center card hide">
<a class="btn-floating btn-large waves-effect waves-light blue right" style="margin-right: 10px;">
<i class="material-icons">refresh</i>
</a>
<h3>Text Sources:</h3></div>
<div class="rowsInMain row card hide" style="margin-right: 20px;margin-left: 20px;margin-top: 30px;margin-bottom: 30px;">
<div class="col s4"><p>File Name:</p>
<div class="input-field inline" style="width: 80%;">
<input id="filename_inline" type="text" class="validate">
<label for="filename_inline">Text</label>
</div>
</div>
<div class="col s4"><p>Title:</p>
<div class="input-field inline" style="width: 80%;">
<input id="title_inline" type="text" class="validate">
<label for="title_inline">Text</label>
</div>
</div>
<div class="col s4"><p>Text:</p>
<div class="input-field inline" style="width: 80%;">
<input id="text_inline" type="text" class="validate">
<label for="text_inline">Text</label>
</div>
</div>
<div style="position: absolute; right: 0; top: 0; width: 3em;" class="col s1 btn red waves-effect"><i class="material-icons">delete</i></div>
</div>
<div id="EventHistory" style="padding-top: 20px;"></div><div class="rowsInMain center card">
<a onclick="updateEventList()" class="btn-floating btn-large waves-effect waves-light blue right" style="margin-right: 10px;">
<i class="material-icons">refresh</i>
</a>
<h3>Event History:</h3></div>
<div id="EventHistoryWrapper" class="EventHistoryWrapper">
</div>
<div id="Services" style="padding-top: 20px;"></div><div class="rowsInMain center card hide"><h3>Services:</h3></div>
<div class="row hide">
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">Commands</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">Rewards</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">RGB Lights</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">Text Sources</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">TTS</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
<div class="col s6 m3">
<div class="card modulesCard">
<div class="modulesCardWrap">
<h6 style="padding-top: 15px;">OBS Web Socket</h6>
<a class="waves-effect waves-light btn modulesCardWrapButton">Enable</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="Settings"style="padding-top: 20px;">
<div class="card" >
<div class=""style="padding-top: 20px;">
<div class="row bodyarea container" style="background-color: rgb(221, 221, 221);">
<div class="rowsInMain center card">
<a class="btn-floating btn-large waves-effect waves-light blue right" style="position: absolute; right: 5px;">
<i class="material-icons">refresh</i>
</a>
<h1>Settings</h1>
</div>
<div class="">
<div class="col s12">
<div class="card center" style="margin-top: 15px;margin-bottom: 15px; min-height: 3em; padding-top: 5px;padding-bottom: 5px;">
<h3>Config</h3>
</div>
</div>
</div>
<div class="container">
<div class="col s12">
<div class="card center" style="margin-top: 15px;margin-bottom: 15px; min-height: 3em; padding-top: 15px;padding-bottom: 15px;">
<p>test</p>
</div>
</div>
</div>
<div class="">
<div class="col s12">
<div class="card center" style="margin-top: 15px;margin-bottom: 15px; min-height: 3em; padding-top: 5px;padding-bottom: 5px;">
<h3>Credentials</h3>
</div>
</div>
</div>
<div class="container">
<div class="col s12">
<div class="card center" style="margin-top: 15px;margin-bottom: 15px; min-height: 3em; padding-top: 15px;padding-bottom: 15px;">
<p>test</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="About" class="">
<div class="row bodyarea">
<div class="col s12 center">
<h1>Made by Alex Orid,<br> The Curious Nerd</h1>
<h5>Need Help? Want to help out?<br><a href="https://discord.com/invite/sNTXWn4" target="_blank">Come visit my Discord</a></h5>
<p>Version:<br> A:0 D:1 O:0.8</p>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="js/materialize.js"></script>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<!--<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>-->
<!--<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>-->
<script src="webclient.js"></script>
</body>
</html>

4
user_client/v1/index.js Normal file
View File

@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.fixed-action-btn');
var instances = M.FloatingActionButton.init(elems, options);
});

10021
user_client/v1/js/materialize.js vendored Normal file

File diff suppressed because it is too large Load Diff

6
user_client/v1/js/materialize.min.js vendored Normal file

File diff suppressed because one or more lines are too long

157
user_client/v1/style.css Normal file
View File

@ -0,0 +1,157 @@
body {
background-color: rgb(250, 250, 250);
padding: 0;
margin: 0;
}
div {
padding: 0;
margin: 0;
}
p {
padding: 0;
margin: 0;
}
#header{
background-color: cadetblue;
width: 100%;
display: flex;
}
.bodyarea{
background-color: rgb(250, 250, 250);
padding: 0;
padding-top: 3em;
margin: 0;
min-height: 90%;
}
#sidebar_area{
background-color: rgb(235, 235, 235);;
min-height: 100%;
}
#main_area{
background-color: rgb(221, 221, 221);
min-height: 100%;
}
.main_area{
background-color: rgb(221, 221, 221);
min-height: 100%;
}
.lineSeperator{
margin-top: 15px;
margin-bottom: 15px;
width: 100%;
height: 5px;
background-color: white;
}
.noPadding{
padding: 0;
margin: 0;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
}
.sticky_btm {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
}
.ontop {
z-index: 1000;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.headerItem{
padding: 1em;
background-color: steelblue;
}
.headerItem:hover{
background-color: gray;
}
.headerText{
text-align: center;
color: white;
padding-left: 1em;
padding-right: 1em;
}
.colsInSideBar{
min-width: 100%;
}
.colsInSideBar:hover{
color: white;
font-weight: bold;
background-color: black;
}
.modulesCard{
min-height: 5em;
background-color: red;
}
.modulesCardWrap{
margin-left: 15px;
min-height: 10em;
}
.modulesCardWrapButton{
margin-top: 100px;
}
.rowsInMain{
padding-top: 30px;
padding-bottom: 30px;
}
.EventHistoryWrapper{
overflow-y: scroll;
max-height: 60vh;
background-color: rgb(175, 213, 214);
margin-right: 20px;
margin-left: 20px;
margin-top: 30px;
margin-bottom: 30px;
}
/* width */
::-webkit-scrollbar {
width: 20px;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: rgb(105, 105, 105);
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: rgb(49, 49, 49);
}

279
user_client/v1/webclient.js Normal file
View File

@ -0,0 +1,279 @@
refresh = () => response = fetch('http://127.0.0.1:42055/')
.then((response) => {
return response.text();
})
ConnectionTest = async () => {
var a = await refresh();
console.log(a)
return a
}
async function BotStatus() {
var connectionStatus = await ConnectionTest();
document.getElementById("BotStatus").innerHTML = connectionStatus;
}
BotStatus();
async function setValue(request_type, command, isEnabled) {
let newCommandState = {
'request_type': request_type,
'command_name': command,
'is_enabled': isEnabled
}
let params = "?command_name="+encodeURIComponent(newCommandState.command_name)+"&"+"is_enabled="+encodeURIComponent(newCommandState.is_enabled);
let targetURL = "http://127.0.0.1:42055/api/v1/user_client/set"+params;
//console.log(targetURL)
let a = await fetch_GetList(targetURL);
//console.log("return: "+a);
}
fetch_GetList = (fetchURL) => response = fetch(fetchURL)
.then((response) => {
return response.text();
})
GetList = async (listType) => {
if (true) {
let ListRequestOBJ = {
'request_name': listType,
'request_type': "list"
}
let params = "?request_name="+encodeURIComponent(ListRequestOBJ.request_name)+"&"+"request_type="+encodeURIComponent(ListRequestOBJ.request_type);
let targetURL = "http://127.0.0.1:42055/api/v1/user_client/get"+params;
//console.log(targetURL)
let a = await fetch_GetList(targetURL);
//console.log("return: "+a);
return a
}
else {
return None
}
}
async function GetList_OBJ(ListName) {
let returnedList = await GetList(ListName);
let obj_main = JSON.parse(returnedList);
//console.log(returnedList);
//console.log(obj_main);
//console.log(typeof obj_main['message'])
//console.log(obj_main.message);
//var obj_temp = JSON.parse(obj_main.message['!lights']);
let data = atob(obj_main.message);
console.log(ListName, data);
let notDictionary = JSON.parse(data);
//let notDictionary = true
return notDictionary
}
async function updateCommandList() {
$("#CommandRowWrapper").empty();
let returnedCommands = await GetList_OBJ("Commands");
for (var x in returnedCommands){
//console.log(x)
var commandName = returnedCommands[x].command
var isCommandEnabled = ""
if (returnedCommands[x].isCommandEnabled == "true") {
isCommandEnabled = "checked"
}
var template = ""+
"<div class=\"rowsInMain row card\" style=\"margin-right: 20px;margin-left: 20px;margin-top: 30px;margin-bottom: 30px;\">" +
"<div class=\"col s12 switch\" style=\"top: -20px;position: relative;padding-left: 10px;\"><label>Enabled:<input "+ isCommandEnabled +" disabled type=\"checkbox\"><span class=\"lever\"></span></label></div>" +
"<div class=\"col s4\"><p>Command Name:</p>" +
"<div class=\"input-field inline\" style=\"width: 80%;\">" +
"<p style =\"color:grey;\">Command</p>" +
"<input disabled id=\"\" type=\"text\" value=\""+ commandName +"\" class=\"validate\">" +
"</div></div></div></div>"
$("#CommandRowWrapper").append(template);
}
//var commandName = "!testerino"
//var isCommandEnabled = "" // if == "checked" will start off with the isEnabled bool enabled
}
updateCommandList();
async function updateRewardList() {
$("#RewardRowWrapper").empty();
console.log("about to update the rewards list");
let returnedRewards = await GetList_OBJ("Rewards");
for (var x in returnedRewards){
//console.log(x)
let rewardName = returnedRewards[x].channelRewardName
var isRewardEnabled = ""
if (returnedRewards[x].isRewardEnabled == "true") {
isRewardEnabled = "checked"
}
let template = ""+
"<div class=\"rowsInMain row card\" style=\"margin-right: 20px;margin-left: 20px;margin-top: 30px;margin-bottom: 30px;\">" +
"<div class=\"col s12 switch\" style=\"top: -20px;position: relative;padding-left: 10px;\"><label>Enabled:<input "+ isRewardEnabled +" disabled type=\"checkbox\"><span class=\"lever\"></span></label></div>" +
"<div class=\"col s4\"><p>Reward Name:</p>" +
"<div class=\"input-field inline\" style=\"width: 80%;\">" +
"<p style =\"color:grey;\">Reward</p>" +
"<input disabled id=\"\" type=\"text\" value=\""+ rewardName +"\" class=\"validate\">" +
"</div></div></div></div>"
$("#RewardRowWrapper").append(template);
}
//var commandName = "!testerino"
//var isCommandEnabled = "" // if == "checked" will start off with the isEnabled bool enabled
}
updateRewardList();
GetEventList = async () => {
if (true) {
let ListRequestOBJ = {
'request_name': "EventHistory",
'request_type': "list",
'request_data': "50"
}
let params = "?request_name="+encodeURIComponent(ListRequestOBJ.request_name)
+"&"+"request_type="+encodeURIComponent(ListRequestOBJ.request_type)
+"&"+"request_data="+encodeURIComponent(ListRequestOBJ.request_data);
let targetURL = "http://127.0.0.1:42055/api/v1/user_client/get"+params;
//console.log(targetURL)
let a = await fetch_GetList(targetURL);
//console.log("return: "+a);
return a
}
else {
return None
}
}
async function GetEventList_OBJ() {
let returnedList = await GetEventList();
let obj_main = JSON.parse(returnedList);
//console.log(returnedList);
console.log(obj_main);
//console.log(typeof obj_main['message'])
//console.log(obj_main.message);
//var obj_temp = JSON.parse(obj_main.message['!lights']);
let data = atob(obj_main.message);
console.log("Event List OBJ: ", data);
let notDictionary = JSON.parse(data);
//let notDictionary = true
return notDictionary
}
async function updateEventList() {
$("#EventHistoryWrapper").empty();
let returnedEvents = await GetEventList_OBJ();
// let template = ""+
// "<div class=\"rowsInMain row card\">"+
// "<div class=\"col s3\"><p>Event:"+ "eventName" +"</p></div>"+
// "<div class=\"col s3\"><p>User:"+ "eventSender" +"</p></div>"+
// "<div class=\"col s3\"><p>Message:"+ "eventData" +"</p></div>"+
// "<a onclick=\"reRunEvent()\" class=\"btn waves-effect waves-light green right col s1\" style=\"position: absolute; right: 0; top: 0; width: 3em;\">"+
// "<i class=\"material-icons\">refresh</i>"+
// "</a></div>"
// $("#EventHistoryWrapper").append(template);
// $("#EventHistoryWrapper").append(template);
// $("#EventHistoryWrapper").append(template);
// $("#EventHistoryWrapper").append(template);
// $("#EventHistoryWrapper").append(template);
// $("#EventHistoryWrapper").append(template);
console.log(returnedEvents)
try {
for (var x in returnedEvents){
console.log(x)
let eventName = returnedEvents[x].eventName
let eventTime = returnedEvents[x].eventTime
let eventType = returnedEvents[x].eventType
let eventSender = returnedEvents[x].eventSender
let eventData = returnedEvents[x].eventData
//console.log(eventName)
//console.log(eventTime)
//console.log(eventType)
//console.log(eventSender)
//let reRunEvent_Params = String("reRunEvent(\"" + eventName + "\", \"" + eventTime + "\", \"" + eventType + "\", \"" + eventSender + "\", \"" + eventData+"\")")
let reRunEvent_Params = `reRunEvent(&quot;${eventName}&quot;, &quot;${eventTime}&quot;, &quot;${eventType}&quot;, &quot;${eventSender}&quot;, &quot;${eventData}&quot;)`
//let reRunEvent_Params = `reRunEvent('${eventName}', '${eventTime}', '${eventType}', '${eventSender}', '${eventData}')`
console.log(reRunEvent_Params)
//let reRunEvent_Params = String("reRunEvent()")
let template = ""+
"<div class=\"rowsInMain row card\">"+
"<div class=\"col s12\" style=\"position:absolute;top:0;color:grey;\">Time: "+ eventTime +"</div>"+
"<div class=\"col s12 m3\"><p>Event: <br>"+ eventName +"</p><br></div>"+
"<div class=\"col s12 m3\"><p>User: <br>"+ eventSender +"</p><br></div>"+
"<div class=\"col s12 m3\"><p>Message: <br>"+ eventData +"</p><br></div>"+
'<a onclick="'+ reRunEvent_Params +'" class="hide btn waves-effect waves-light green right col s1" style="position: absolute; right: 0; top: 0; width: 3em;">'+
"<i class=\"material-icons\">refresh</i>"+
"</a></div>"
$("#EventHistoryWrapper").prepend(template);
}
}finally {
}
}
updateEventList();
fetch_RerunEvent = (fetchURL) => response = fetch(fetchURL)
.then((response) => {
return response.text();
})
RerunEvent_OBJ = async (eventToRun) => {
if (true) {
let exampleEvent = {
'eventName': "",
'eventTime': "",
'eventType': "",
'eventSender': "",
'eventData': ""
}
let params = ""+
"?eventName="+encodeURIComponent(eventToRun['eventName'])+
"&"+"eventTime="+encodeURIComponent(eventToRun['eventTime'])+
"&"+"eventType="+encodeURIComponent(eventToRun['eventType'])+
"&"+"eventSender="+encodeURIComponent(eventToRun['eventSender'])+
"&"+"eventData="+encodeURIComponent(eventToRun['eventData']);
let targetURL = "http://127.0.0.1:42055/api/v1/user_client/event_log/reRunEvent"+params;
//console.log(targetURL)
let a = await fetch_RerunEvent(targetURL);
//console.log("return: "+a);
return a
}
else {
return None
}
}
async function reRunEvent(eventName, eventTime, eventType, eventSender, eventData) {
var newEvent = {
'eventName': eventName,
'eventTime': eventTime,
'eventType': eventType,
'eventSender': eventSender,
'eventData': eventData
}
let response = await RerunEvent_OBJ(newEvent);
console.log(response)
let main = JSON.parse(response);
let data = main.message
console.log("response: ", data);
}

View File

@ -0,0 +1,51 @@
from enum import Enum
from os import F_OK
import tempText_Module
import time
import config as config
import flask
from flask import Flask, request, after_this_request
import credentials
import commands.loader as command_loader
from commands.command_base import AbstractCommand
from cooldowns import Cooldown_Module
import utilities_script as utility
import chyron_module
import timers_module
import random
import os
import praxis_logging
praxis_logger_obj = praxis_logging.praxis_logger()
praxis_logger_obj.init(os.path.basename(__file__))
praxis_logger_obj.log("\n -Starting Logs: " + os.path.basename(__file__))
api:Flask = Flask(__name__)
api.config["DEBUG"] = True
class Module_InfoLookup():
def __init__(self):
super().__init__()
def init():
print("starting up... ",)
@api.route('/')
def bot_StatusIcon():
@after_this_request
def add_header(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response
return flask.make_response('Client Service: OK', 200)
if __name__ == "__main__":
init()
api.run(host="0.0.0.0", port = 42063)

Some files were not shown because too many files have changed in this diff Show More