Compare commits

...

178 Commits

Author SHA1 Message Date
Alex Orid
f2b4e68b12 Merge branch 'master' into github-master 2021-05-13 17:10:18 -04:00
Alex Orid
0a77a7d8fb space 2021-05-13 16:46:27 -04:00
Alex Orid
b2544b9101 fix 2021-05-13 16:40:36 -04:00
2343aff13d Merge pull request 'v2 Standalone Docker Update' (#40) from v2.0 into master
Reviewed-on: #40
2021-05-13 20:36:45 +00:00
Alex Orid
db0e63c933 github prep 2021-05-13 16:33:27 -04:00
Alex Orid
18c4792b58 Update README.md 2021-05-13 15:20:51 -04:00
Alex Orid
ea1a4a4b83 updated readme 2021-05-13 15:20:04 -04:00
00aca55237 Merge pull request 'user-client' (#39) from user-client into v2.0
Reviewed-on: #39
2021-05-13 04:02:49 +00:00
Alex Orid
93c8a4fd05 prep for minimal ui commit 2021-05-13 00:01:23 -04:00
Alex Orid
581f5e9582 Added help link to about page 2021-05-12 23:59:40 -04:00
Alex Orid
88510cf5d1 Delete deleteME.py 2021-05-12 23:01:16 -04:00
Alex Orid
e735cb94c8 css improvements 2021-05-12 22:38:56 -04:00
Alex Orid
04ded59337 WORKING?!?!?!?!?!
I hate javascript
2021-05-12 21:47:44 -04:00
Alex Orid
43116bc70a Almost Working 2021-05-12 21:34:50 -04:00
Alex Orid
13dcfdcd2a typo 2021-05-12 20:37:23 -04:00
Alex Orid
788dd8e7eb Update webclient.js 2021-05-12 20:11:14 -04:00
Alex Orid
859b273fc7 Progress 2021-05-12 20:01:55 -04:00
Alex Orid
2ff76a0178 Basic Kinda Half Working 2021-05-12 18:02:42 -04:00
Alex Orid
4f3e5dcef7 Progress & bug Fix
Standalone Channel Rewards cannot use 3.10
2021-05-12 17:15:23 -04:00
Alex Orid
ecdc22ab1c progress 2021-05-12 15:40:20 -04:00
Alex Orid
c5313fe853 Progress 2021-05-12 01:04:48 -04:00
Alex Orid
99f5ee8e72 Improved CSS 2021-05-11 23:09:19 -04:00
Alex Orid
5c16536d67 Added user-client Docker stuff 2021-05-11 18:01:01 -04:00
Alex Orid
b47663a125 progress 2021-05-11 16:26:00 -04:00
Alex Orid
b1d622826f Basic Idea 2021-05-08 19:07:35 -04:00
Alex Orid
e80db3449a Progress 2021-05-07 17:06:22 -04:00
Alex Orid
d78e6bc7b4 Docker Support 2021-05-07 16:35:43 -04:00
Alex Orid
373c398306 working version 2021-05-07 16:21:10 -04:00
Alex Orid
ddec99c37b Event Log Progress 2021-05-07 16:00:11 -04:00
Alex Orid
d121753284 Event Module 2021-05-07 14:55:06 -04:00
Alex Orid
579bdcd82e removed unneeded files 2021-05-07 00:59:20 -04:00
Alex Orid
a609c4d61c initial 2021-05-07 00:54:08 -04:00
Alex Orid
fb4273416f typo 2021-05-06 00:25:22 -04:00
Alex Orid
ee237141d8 uncommented line 2021-05-06 00:19:08 -04:00
e424c7ecb6 Merge pull request 'timers-module' (#38) from timers-module into v2.0
Reviewed-on: #38
2021-05-06 04:09:33 +00:00
Alex Orid
c30decd0ef Port Changes 2021-05-06 00:07:53 -04:00
Alex Orid
8c7bc3e56b typo 2021-05-05 18:01:54 -04:00
Alex Orid
988f791a42 Working Version 2021-05-05 18:00:40 -04:00
Alex Orid
7365c2e3ee progress 2021-05-05 14:06:52 -04:00
Alex Orid
fae2cacb73 Fixes & New Rewards 2021-05-05 13:15:01 -04:00
Alex Orid
bc11d876c7 fixed comments 2021-05-04 19:08:37 -04:00
Alex Orid
a3da70bd55 Made Discord TTS Command working kinda 2021-05-04 18:57:26 -04:00
Alex Orid
72ea8f7b71 config deletion 2021-05-04 17:36:10 -04:00
Alex Orid
3d0f2b0a90 Working Version 2021-05-04 17:34:15 -04:00
Alex Orid
5d9831fc30 minor fixes 2021-05-04 16:54:45 -04:00
Alex Orid
e05183ffeb Working Version 2021-05-04 16:23:00 -04:00
Alex Orid
f0601974be working concept 2021-05-04 15:23:31 -04:00
Alex Orid
ff4b9af8b4 extra stuff 2021-05-04 14:56:57 -04:00
Alex Orid
b3667bb2fc Create timers_module.py 2021-05-03 21:10:34 -04:00
Alex Orid
572817a006 Updated Websources 2021-05-03 17:24:39 -04:00
Alex Orid
241b83076c Discord Chyron Command Fixes 2021-05-03 16:44:07 -04:00
Alex Orid
bc6a8c8bf7 credential helper function + cleaning/typo fixes 2021-05-03 04:09:53 -04:00
Alex Orid
bb002c7b0c Update rebuild_docker_and_run.bat 2021-05-03 03:52:03 -04:00
Alex Orid
7afb50d26a Docker / Editor Changes 2021-05-03 03:26:30 -04:00
Alex Orid
6b5683f615 twitch tts 2021-04-30 17:02:46 -04:00
Alex Orid
1c3d973edf Chyron Auto Fix
Improved the command in respects to the chyron command min length.
2021-04-30 15:03:22 -04:00
260d7f44f2 Merge pull request 'chyron-&-text-updater-commands' (#37) from chyron-&-text-updater-commands into v2.0
Reviewed-on: #37
2021-04-30 18:17:36 +00:00
Alex Orid
5be420a2d1 Added Text Command 2021-04-30 14:16:01 -04:00
Alex Orid
eb67d07b74 working version 2021-04-30 13:58:24 -04:00
Alex Orid
5d1c442c29 basic command 2021-04-30 11:48:29 -04:00
Alex Orid
1eee312407 Update standalone_lights.py 2021-04-30 02:18:55 -04:00
Alex Orid
2c12e40ca2 initial commit 2021-04-30 02:16:01 -04:00
Alex Orid
30bd3a9d25 typos 2021-04-30 02:14:11 -04:00
Alex Orid
f56eb4ab5e sub fix 2021-04-29 20:06:30 -04:00
Alex Orid
9028b4ae33 tts command fix 2021-04-29 19:32:36 -04:00
Alex Orid
720921b83f script updates 2021-04-29 18:19:43 -04:00
Alex Orid
f477fd1f6f typo 2021-04-29 18:01:49 -04:00
Alex Orid
a2b31868b4 Revert "Added Docker url fix to docker_utility.py"
This reverts commit 6d1c07f39b.
2021-04-29 17:53:30 -04:00
Alex Orid
6d1c07f39b Added Docker url fix to docker_utility.py 2021-04-29 17:40:52 -04:00
Alex Orid
a5429e5ce5 Discord TTS Channels 2021-04-29 17:07:41 -04:00
Alex Orid
8bd428637e Marked lines for later deletion 2021-04-29 16:45:46 -04:00
Alex Orid
d5f8d8e38d Command Restrictions 2021-04-29 16:39:22 -04:00
Alex Orid
25fee4cb5c Working Bits Pubsubs 2021-04-29 15:35:50 -04:00
834bae4773 Merge pull request 'tts-core-&-speaker' (#36) from tts-core-&-speaker into v2.0
Reviewed-on: #36
2021-04-29 15:39:22 +00:00
Alex Orid
0c12cffc53 extra 2021-04-29 11:36:10 -04:00
Alex Orid
fa376abad6 Update ChannelReward_RubiksCube.py 2021-04-28 22:49:44 -04:00
Alex Orid
56416acf77 Fixes 2021-04-28 22:45:55 -04:00
Alex Orid
2ba271c4a3 typo 2021-04-28 16:32:08 -04:00
Alex Orid
95a3189b36 initial commit 2021-04-28 15:01:24 -04:00
Alex Orid
f32f4d7fb5 volume fix 2021-04-28 06:31:42 -04:00
Alex Orid
4cabd33b70 updated readme 2021-04-28 03:39:37 -04:00
526000d99c Merge pull request 'standalone-lights & logging & more' (#35) from standalone-lights into v2.0
Reviewed-on: #35
2021-04-28 07:33:08 +00:00
Alex Orid
3fbc517e59 typo 2021-04-28 03:31:23 -04:00
Alex Orid
114d70f661 Update config.py 2021-04-28 03:30:41 -04:00
Alex Orid
53c20a2007 Delete standalone_channelrewards.py.log 2021-04-28 03:21:08 -04:00
Alex Orid
acac919f81 more logging 2021-04-28 03:20:15 -04:00
Alex Orid
2c6fd90a0e Fully Working AFAIK 2021-04-28 03:01:40 -04:00
Alex Orid
1d07fb449d Update .gitignore 2021-04-28 01:25:53 -04:00
Alex Orid
6905e211c7 logging 2021-04-28 01:25:40 -04:00
Alex Orid
8dd069f7b9 Working Docker Logging 2021-04-27 23:31:43 -04:00
Alex Orid
f34e53fe1f working without docker 2021-04-27 19:06:58 -04:00
Alex Orid
0d6e26a2a5 Revert "logging"
This reverts commit b106eaa9dd.
2021-04-27 18:55:23 -04:00
Alex Orid
b106eaa9dd logging 2021-04-27 18:47:51 -04:00
Alex Orid
87492e625a Working Version 2021-04-27 16:59:02 -04:00
Alex Orid
41afb81df0 Lights API Commands 2021-04-27 16:28:21 -04:00
Alex Orid
642c3cde5d initial script 2021-04-27 14:56:11 -04:00
49ab554494 Merge pull request 'channel rewards service' (#34) from channelpoints-service into v2.0
Reviewed-on: #34
2021-04-27 18:15:03 +00:00
Alex Orid
9c0172b021 address/api fix 2021-04-26 19:49:11 -04:00
Alex Orid
41a3362b64 working channel point rewards 2021-04-26 18:55:11 -04:00
Alex Orid
7e591e3791 is reward real 2021-04-26 18:43:54 -04:00
Alex Orid
a29f71e268 fixed type error 2021-04-26 17:23:47 -04:00
Alex Orid
df8805e5ee api stuff 2021-04-26 15:31:22 -04:00
Alex Orid
e857ea390a api typo 2021-04-26 14:49:56 -04:00
Alex Orid
d682baa864 changed api 2021-04-26 14:49:28 -04:00
Alex Orid
65a723b5df renaming and fixing parameters 2021-04-26 14:47:15 -04:00
Alex Orid
2c7a2b3ef0 Update standalone_twitch_pubsub.py 2021-04-26 13:03:27 -04:00
Alex Orid
e3a9c0bccd Channel Point Rewards 2021-04-25 20:59:28 -04:00
Alex Orid
ca48b67a01 typos 2021-04-25 11:46:35 -04:00
Alex Orid
a9641a44ab port changes 2021-04-25 01:48:37 -04:00
Alex Orid
ded62cefac initial commit 2021-04-25 00:57:22 -04:00
Alex Orid
da7defc7f2 Create twitch_generate_credentials.py 2021-04-25 00:52:46 -04:00
Alex Orid
5859a56441 Deleted Old Stuff & Added Try Blocks 2021-04-24 01:25:32 -04:00
Alex Orid
3084740238 Docker Fixes 2021-04-24 00:16:22 -04:00
Alex Orid
972738ca11 pubsub fix 2021-04-23 16:06:14 -04:00
Alex Orid
0e15d236e6 Update standalone_twitch_pubsub copy.py 2021-04-23 15:37:13 -04:00
Alex Orid
6c485d6d2c working whispers 2021-04-23 15:31:31 -04:00
Alex Orid
0602758bcb further testing 2021-04-23 14:51:13 -04:00
Alex Orid
7ab37a62b9 Update standalone_twitch_pubsub.py 2021-04-23 11:56:36 -04:00
Alex Orid
b91058660a Update standalone_twitch_pubsub.py 2021-04-23 06:40:40 -04:00
Alex Orid
a5482027f4 working token generation 2021-04-23 06:34:37 -04:00
Alex Orid
436f4a8193 Update standalone_twitch_pubsub.py 2021-04-23 05:38:01 -04:00
Alex Orid
801b0171e1 Update standalone_twitch_pubsub.py 2021-04-23 05:37:53 -04:00
Alex Orid
463014aeb8 progress 2021-04-23 05:33:46 -04:00
Alex Orid
2034e6e907 standalone twitch pubsub 2021-04-22 22:14:30 -04:00
Alex Orid
941324d637 Update standalone_twitch_pubsub.py 2021-04-22 15:19:38 -04:00
Alex Orid
9b50612f19 Docker Improvements & Simplification 2021-04-22 15:15:11 -04:00
Alex Orid
36705c8a86 Name Fix 2021-04-22 13:56:48 -04:00
7ec8dd5e0e Merge pull request 'v2-cleaned-up' (#33) from v2-cleaned-up into v2.0
Reviewed-on: #33
2021-04-22 17:50:22 +00:00
Alex Orid
294306896f Cleaning 2021-04-22 13:43:41 -04:00
Alex Orid
9c876aeee9 Merge branch 'v2.0' into v2-cleaned-up 2021-04-22 13:39:38 -04:00
93d28c0ad4 Merge pull request 'v2.0--Docker-Idea' (#32) from v2.0--Docker-Idea into v2.0
Reviewed-on: #32
2021-04-22 17:37:24 +00:00
Alex Orid
c708f57347 Update README.md 2021-04-21 21:38:22 -04:00
Alex Orid
a54686d07a docker fix 2021-04-21 21:33:30 -04:00
Alex Orid
81a51a26a1 Update README.md 2021-04-21 21:20:11 -04:00
Alex Orid
7abeeca523 Update README.md 2021-04-21 21:15:37 -04:00
Alex Orid
05e53a3cfe Idea 2021-04-21 21:05:11 -04:00
Alex Orid
5ed0e4e121 Merge branch 'v2.0' into v2-cleaned-up 2021-04-21 19:54:48 -04:00
Alex Orid
5590a21adb rename 2021-04-21 19:51:45 -04:00
Alex Orid
0e1dc8b05b Added v2 lights 2021-04-21 19:47:12 -04:00
c7c4318867 Merge pull request 'added roll command & test pull request' (#29) from v2.0 into v2-cleaned-up
Reviewed-on: #29
2021-04-21 23:35:06 +00:00
Alex Orid
44f66ae9e3 added roll command 2021-04-21 19:32:11 -04:00
Alex Orid
c3b07d7b77 Deletion & Rename 2021-04-21 19:13:58 -04:00
Alex Orid
1f21ad547c Added Bonus Data Arg 2021-04-21 17:56:08 -04:00
Alex Orid
7bb733cb6d Clean up 2021-04-21 17:49:58 -04:00
Alex Orid
7a4685da2c Update README.md 2021-04-21 17:45:04 -04:00
Alex Orid
18921b9d7d Twitch Simplification & Discord Standalone 2021-04-21 17:42:03 -04:00
Alex Orid
c400e1842b Removing Old Stuff and Blocked bad words 2021-04-21 16:40:55 -04:00
Alex Orid
6593c0fa94 readme change 2021-04-21 16:22:18 -04:00
Alex Orid
e6034fa254 Not needed? 2021-04-21 16:14:22 -04:00
Alex Orid
ffdd19f46a V2 Commands 2021-04-21 16:10:54 -04:00
dtookey
c590443de3 fixed json reply bug 2021-04-20 21:56:11 -04:00
dtookey
5fd586ead5 fixed parsing bug 2021-04-20 21:53:35 -04:00
dtookey
8b017061c0 maybe fixed the issue with the wrong annotation 2021-04-20 21:48:43 -04:00
dtookey
9a9174f687 added debugging prints 2021-04-20 21:45:48 -04:00
dtookey
d720481c26 fixed is_command shadowing 2021-04-20 21:42:27 -04:00
dtookey
6d2e6765f7 fixed flask.request 2021-04-20 21:40:29 -04:00
dtookey
c48d89c5af Merge remote-tracking branch 'origin/v2.0' into v2.0 2021-04-20 21:37:13 -04:00
dtookey
24d83f4ad9 fixed urlencode 2021-04-20 21:36:59 -04:00
Alex Orid
79902eca86 typo 2021-04-20 21:35:12 -04:00
dtookey
d55b3062e8 implemented dummy stuff this time with execution 2021-04-20 21:24:34 -04:00
dtookey
a38f99c5a0 implemented dummy stuff 2021-04-20 21:23:39 -04:00
Alex Orid
d5919aa63d Did a thing 2021-04-19 15:03:27 -04:00
Alex Orid
ba21bd2b9c forgot deletion 2021-04-19 14:59:13 -04:00
Alex Orid
3ddeb3c5d6 flask websource stuff 2021-04-19 14:57:59 -04:00
Alex Orid
97ded4d153 Added Flask Module 2021-04-16 15:09:30 -04:00
Alex Orid
4e18983c45 String Formatting 2021-04-16 14:31:20 -04:00
Alex Orid
c791f71845 typo 2021-04-16 14:16:06 -04:00
Alex Orid
b21cb25252 Added temptext Command 2021-04-16 14:15:52 -04:00
Alex Orid
1e33859f28 Added Help 2021-04-16 04:59:22 -04:00
Alex Orid
3bbd5d1611 Improved Commands 2021-04-16 04:38:07 -04:00
Alex Orid
cd5b1b0df8 Expanded Roll Command 2021-04-16 04:11:51 -04:00
Alex Orid
91c31e9646 User Flags 2021-04-16 02:59:17 -04:00
Alex Orid
5a0fd3c447 Update user_module.py 2021-04-16 02:43:18 -04:00
4f0d3892a3 Merge pull request 'Command-Management-Module & Command File Simplification/Reduction' (#27) from Command-Management-Module into master
Reviewed-on: #27
2021-04-16 05:35:50 +00:00
Alex Orid
21083b81e7 Update config.py 2021-04-16 01:31:56 -04:00
Alex Orid
07612e9989 Initial 2021-04-16 01:26:22 -04:00
6bab6d5342 Merge pull request 'master' (#25) from master into Command-Management-Module
Reviewed-on: #25
2021-04-16 02:06:44 +00:00
Alex Orid
4c1fb203b9 Initial Commit 2021-04-13 17:58:58 -04:00
103 changed files with 24626 additions and 1181 deletions

4
.gitignore vendored
View File

@ -4,3 +4,7 @@ __pycache__/
credentials/
.idea/
stream_sources/chyron.txt
stream_sources/brb.txt
*.log
timers/
event_logs/logs/

View File

@ -7,4 +7,4 @@ RUN pip3 install -r requirements.txt
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 Setup:
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)*
Helix Client ID = `https://dev.twitch.tv/console/apps`
@ -26,19 +61,40 @@ Oauth = `https://twitchapps.com/tmi/`
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)*
Engine = `"mysql+mysqlconnector://root:password@localhost:3306/DatabaseName"`
Token = `https://discord.com/developers/`<br>
<br>
### For Discord Credentials
Nickname = `Anything You Want` *(Must match ***credentialsNickname*** in config)*
## Phue Credentials:
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:
Place json credentials in the `/credentials/` folder.
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 = [" thinks its time to solve a cube "]):
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(
"WeekDays",
"► Weekdays: ",
"Daily Streams @ 12pm Noon EST")
"Daily Dev Streams starting around 12pm Noon EST")
self.addItem(
"FriSat",
"► Friday & Saturday: ",
@ -24,18 +24,18 @@ class Chyron_Module():
self.addItem(
"Commands",
"► Commands: ",
"!animal, !climateclock, !discord, !lights, !page, !roll")
self.addItem(
"Website",
"► Want to read about my various projects? visit: ",
"TheCuriousNerd.com")
"!animal, !climateclock, !discord, !lights, !roll")
#self.addItem(
# "Website",
# "► Want to read about my various projects? visit: ",
# "TheCuriousNerd.com")
self.addItem(
"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(
"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")
def chyron_stringUpdater(self):
@ -69,6 +69,18 @@ class Chyron_Module():
file.write(chyron)
file.close
def getChyronFile(self):
dir = utilities.get_dir("stream_sources")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = "stream_sources/chyron.txt"
real_file_path = os.path.join(script_dir, relative_path)
file = open(real_file_path, "rb")
text = file.read()
#print(text)
file.close
return text
class ChyronItem():
def __init__(self):
@ -82,7 +94,7 @@ class ChyronItem():
self.itemComputedString = ""
def setupItem(self, name, title, content):
print("Setting up Item {", name,"}[", title, content, "]")
print("\nSetting up Item {", name,"}[", title, content, "]")
self.itemName = name
self.itemTitle = title
self.itemContent = content

View File

@ -17,12 +17,20 @@ class AbstractCommand(metaclass=ABCMeta):
Praxis = auto()
TWITCH = auto()
DISCORD = auto()
Ver2 = auto()
def __init__(self, command: str, n_args: int = 0, command_type=CommandType.NONE, helpText:list=["No Help"]):
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):
self.command = command
self.n_args = n_args
self.command_type = command_type
self.help = helpText
self.isCommandEnabled = CommandEnabled
# no touch!
def get_args(self, text: str) -> list:
@ -32,10 +40,18 @@ class AbstractCommand(metaclass=ABCMeta):
def get_command(self) -> str:
return self.command
# no touch!
def get_commandType(self):
return self.command_type
# no touch!
def get_help(self):
return self.help
# no touch!
def is_command_enabled(self):
return self.isCommandEnabled
@abstractmethod
def do_command(self, bot, twitch_message):
pass
def do_command(self, source, user, command, rest, bonusData):
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

@ -3,93 +3,37 @@ from abc import ABCMeta
from commands.command_base import AbstractCommand
import random
import utilities_script as utility
class CommandRoll(AbstractCommand, metaclass=ABCMeta):
class Command_roll_v2(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!roll"
def __init__(self):
super().__init__(CommandRoll.command, n_args=1, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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, bot, twitch_message):
print("!roll Detected")
#twitch_message.chat.send("test acknowledged")
def do_command(self, source = AbstractCommand.CommandSource.default, user = "User", command = "", rest = "", bonusData = None):
returnString = user + " sent: [ " + command + " ] with: " + rest
diceRoll: str = ""
bot.send_message("Rolling Dice...")
print("Rolling Dice...")
if ("f") in twitch_message.text.lower():
diceRoll = self.roll(2, twitch_message)
if ("f") in rest.lower():
returnString = self.roll(2, user, command + " " +rest)
else:
diceRoll = self.roll(1, twitch_message)
returnString = self.roll(1, user, command + " " +rest)
#========================
#Old Code Below
#========================
return returnString
# temp_preParsedMessage = twitch_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 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])))
# 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]))
# if len(temp_preParsedMessage) == 2:
# diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
# roll + int(temp_preParsedMessage[1]))
# else:
# diceRoll = str(roll)
# diceRoll = "@" + twitch_message.sender + " rolled: " + diceRoll
# print(diceRoll)
#========================
#Old Code Above
#========================
bot.send_message(diceRoll)
def roll(self, roll_type, twitch_message):
def roll(self, roll_type, user, user_message):
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = twitch_message.text.split("+")
temp_preParsedMessage = user_message.split("+")
tempParsedMessage = temp_preParsedMessage[0].split(" ")
temp_dice_stmt: str = tempParsedMessage[1]
@ -103,6 +47,7 @@ class CommandRoll(AbstractCommand, metaclass=ABCMeta):
loopBool = False
if roll_type == 1:
print("-rolling...")
# If roll is in xdx+x format
if loopBool == True:
rolls: list = []
@ -129,13 +74,11 @@ class CommandRoll(AbstractCommand, metaclass=ABCMeta):
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + twitch_message.sender + " rolled: " + diceRoll
print(diceRoll)
diceRoll = user + " rolled: " + diceRoll
if roll_type == 2:
print("fate Rolling....")
print("-fate Rolling....")
# !roll 4df
# If roll is in xdx+x format
if loopBool == True:
@ -163,9 +106,7 @@ class CommandRoll(AbstractCommand, metaclass=ABCMeta):
roll + int(temp_preParsedMessage[1]))
else:
diceRoll = str(roll)
diceRoll = "@" + twitch_message.sender + " fate rolled: " + diceRoll
print(diceRoll)
diceRoll = user + " fate rolled: " + diceRoll
return diceRoll

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,47 +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\""]
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!"
bot.return_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,48 +0,0 @@
from abc import ABCMeta
import help_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandChyron(AbstractCommand, metaclass=ABCMeta):
"""
this is the help command.
"""
command = "help"
def __init__(self):
super().__init__(CommandChyron.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.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 = helper.response
bot.return_message(returnMessage)
elif i == 1:
commandsList = self.blockDecor + "Commands List:" + self.blockDecor + self.GetCommandsList(bot) + self.blockDecor
print(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,72 +0,0 @@
from abc import ABCMeta
import lights_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandLights(AbstractCommand, metaclass=ABCMeta):
"""
this is the lights command.
"""
command = "lights"
def __init__(self):
super().__init__(CommandLights.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\""]
def do_command(self, bot, user_message):
tempBool = True
if tempBool == True:
LightModule = lights_module.Lights_Module()
LightModule.main()
#print("\nRGB Command Detected!")
tempParsedMessage = user_message.message.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 = "@" + user_message.user + " changed the light's color!"
bot.return_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,72 +0,0 @@
from abc import ABCMeta
import lights_module
from commands.command_base import AbstractCommand
import random
import utilities_script as utilities
class CommandLights(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!lights"
def __init__(self):
super().__init__(CommandLights.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\""]
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!"
bot.send_message(returnMessage)
def get_help(self):
return self.help

View File

@ -1,28 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
import utilities_script as utilities
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "//restart"
def __init__(self):
super().__init__(CommandTTS.command, n_args=0, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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,22 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import utilities_script as utilities
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "!restart"
def __init__(self):
super().__init__(CommandTTS.command, n_args=0, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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

View File

@ -1,180 +0,0 @@
from abc import ABCMeta
from discord import message
from commands.command_base import AbstractCommand
import random
import discord
import discord.message
import discord.channel
class CommandRoll(AbstractCommand, metaclass=ABCMeta):
"""
this is the roll command.
"""
command = "!roll"
def __init__(self):
super().__init__(CommandRoll.command, n_args=1, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
async def do_command(self, bot, discord_message: discord.Message):
print("!roll Detected")
#twitch_message.chat.send("test acknowledged")
diceRoll: str = ""
await bot.send_message(discord_message, "Rolling Dice...")
#await discord_message.channel.send("Rolling Dice...")
print("Rolling Dice...")
if ("f") in discord_message.content.lower():
diceRoll = await self.roll(2, discord_message)
else:
diceRoll = await self.roll(1, discord_message)
#========================
#Old Code Below
#========================
# temp_preParsedMessage = discord_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 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])))
# 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]))
# if len(temp_preParsedMessage) == 2:
# diceRoll = str(roll) + " + " + temp_preParsedMessage[1] + " = " + str(
# roll + int(temp_preParsedMessage[1]))
# else:
# diceRoll = str(roll)
# diceRoll = discord_message.author.mention + " rolled: " + diceRoll
# print(diceRoll)
#========================
#Old Code Above
#========================
await bot.send_message(discord_message, diceRoll)
#await discord_message.channel.send(diceRoll)
async def roll(self, roll_type, discord_message: discord.Message):
diceRoll = ""
switch = {
1: "Standard",
2: "Fate Dice"
}
temp_preParsedMessage = discord_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 = discord_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 = discord_message.author.mention + " fate rolled: " + diceRoll
print(diceRoll)
return diceRoll
def get_help(self):
return self.help

View File

@ -1,28 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
import utilities_script as utilities
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "//shutdown"
def __init__(self):
super().__init__(CommandTTS.command, n_args=0, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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,22 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import utilities_script as utilities
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "!shutdown"
def __init__(self):
super().__init__(CommandTTS.command, n_args=0, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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

View File

@ -1,22 +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\""]
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,35 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
import discord
import discord.message
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "//tts"
def __init__(self):
super().__init__(CommandTTS.command, n_args=1, command_type=AbstractCommand.CommandType.DISCORD)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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

@ -1,27 +0,0 @@
from abc import ABCMeta
from commands.command_base import AbstractCommand
class CommandTTS(AbstractCommand, metaclass=ABCMeta):
command = "!tts"
def __init__(self):
super().__init__(CommandTTS.command, n_args=1, command_type=AbstractCommand.CommandType.TWITCH)
self.help = ["MISSING HELP ENTRY",
"\nExample:","command \"PARAM\""]
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

View File

@ -8,15 +8,14 @@ from typing import Dict
from commands.command_base import AbstractCommand
def load_commands() -> Dict[str, AbstractCommand]:
commands = compile_and_load()
#New
def load_commands(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]:
print(" -Loading ", commandType ," Commands...\n")
commands = compile_and_load(commandType)
return commands
def load_commands_new(commandType: AbstractCommand.CommandType) -> Dict[str, AbstractCommand]:
commands = compile_and_load_new(commandType)
return commands
def compile_and_load_file(path: str) -> (str, AbstractCommand):
#New
def compile_and_load_file(path: str, commandType: AbstractCommand.CommandType):
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)
@ -26,32 +25,23 @@ def compile_and_load_file(path: str) -> (str, AbstractCommand):
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
if commandType == command_inst.get_commandType():
print(" ---Successfully loaded %s: %s" % (commandType, command_inst.get_command()))
return command_inst.get_command(), command_inst
elif commandType != command_inst.get_commandType():
print(" -%s CommandType did not match: %s for: %s" % (command_inst.get_commandType(), commandType, command_inst.get_command()))
return "", None
def compile_and_load() -> Dict[str, AbstractCommand]:
#New
def compile_and_load(commandType: AbstractCommand.CommandType) -> 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
def compile_and_load_new(commandType: AbstractCommand.CommandType) -> 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)
print("compiling: %s" % name)
name, command = compile_and_load_file(name, commandType)
if command is not None and command.command_type is commandType:
dic[name] = command
break

View File

@ -3,43 +3,35 @@ import badwords as badwords
credentialsNickname = "praxis_bot"
twitch_module: bool = False
discord_module: bool = False
test_module: bool = False
user_module: bool = True
autoJoin_TwitchChannel = "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
block_TwitchChannelsMessaging = [""] # Blocks the ability to send messages to twitch channels
blockAll_TwitchChatChannelsMessaging = False # Blocks the ability to send messages to twitch channels
autoEnabled_TwitchChannelsTTS = False
block_TwitchChannelsTTS = [""] # block supersedes the tts_enabled bool
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
autoEnabled_TwitchTTS = False # Enables TTS for ALL
autoEnabled_TwitchTTS_SpeakersList_Only = False # Enables TTS for Allowed TTS List Only
#Discord Module Configs
block_DiscordChannelsMessaging = [""] # 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
autoEnabled_DiscordChannelsTTS = False
autoEnabled_DiscordChannelsTTS = True
selected_DiscordTTSChannels = ["431129571308339210"]
block_DiscordChannelsTTS = [""] # block supersedes the 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
forceAll_DiscordChatChannelsTTS = False # forceAll supersedes the blockAll bool and block list and force list
blockAll_TTS_URL_Discord = True
autoEnabled_Discord_rgbLightControl = False
#User Module Configs
blockAll_TTS_URL_UserModule = True
@ -64,15 +56,18 @@ class FileNameStrategy(Enum):
fileNameStrategy = FileNameStrategy.CONTENT_BASED
#OLD CLASS WILL DELETE
class DBStrategy(Enum):
SQLite = 1
MySQL = 2
dbStrategy = DBStrategy.SQLite
#OLD CONFIGS WILL BE DELETED SOON
#dbStrategy = DBStrategy.SQLite
#TTS Configs
is_tts_Speaker_Enabled = False
is_tts_URL_Blocked = True
class Speaker(Enum):
GOOGLE_TEXT_TO_SPEECH = 1
@ -82,6 +77,6 @@ currentSpeaker = Speaker.GOOGLE_TEXT_TO_SPEECH
#Misc Configs
slurList = badwords.slurList
praxisVersion_Alpha = "A.0 "
praxisVersion_Delta = "D.1 "
praxisVersion_Omega = "O.0 "
praxisVersion_Alpha = "0 " #Build
praxisVersion_Delta = "1 " #Minor
praxisVersion_Omega = "0.8 " #Major

View File

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

View File

@ -2,5 +2,9 @@
"username": "something",
"helix": "Helix Client ID",
"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
# Oauth = https://twitchapps.com/tmi/
# 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__()
self.username = username
self.helix = helix
self.oauth = oauth
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():

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 enum import Enum
import config as config
import db
import commands.loader as command_loader
@ -10,10 +9,10 @@ import credentials
class Help_Module():
def __init__(self):
super().__init__()
#self.dbCredential: credentials.DB_Credential
def main(self):
print("[Help Module]> help test")
self.isCommandEnabled = True
def help_command_response(self, command:AbstractCommand, responseType):
response = help_command_response()
@ -67,7 +66,4 @@ Help_Module_ = Help_Module()
if __name__ == "__main__":
testModule = Help_Module()
#credentials_manager = credentials.Credentials_Module()
#credentials_manager.load_credentials()
#testModule.dbCredential = credentials_manager.find_DB_Credential(config.credentialsNickname)
testModule.main()

View File

@ -14,7 +14,7 @@ class Lights_Module():
self.bridge_:Bridge = Bridge('192.168.191.146')
def main(self):
print("Starting up [Lights_Module]...")
print("\nStarting up [Lights_Module]...")
self.bridge_.connect()
self.bridge_.get_api()
@ -197,4 +197,4 @@ if __name__ == "__main__":
#testModule.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname)
testModule.main()
testModule.raveMode()
#testModule.raveMode()

49
main.py
View File

@ -4,8 +4,6 @@
import sys
import time
import twitch_script
import discord_script
import test_module
import user_module
@ -17,8 +15,6 @@ import credentials
import threading
twitchModule_: twitch_script.Twitch_Module
discordModule_: discord_script.Discord_Module
testModule_: test_module.Test_Module
userModule_: user_module.User_Module
@ -28,31 +24,6 @@ def main(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):
print("-init [TEST Module]")
#testModule_.dbCredential = dbCert
@ -69,15 +40,11 @@ def thread_main():
if not config.skip_splashScreen:
utility.splashScreen()
global credentials_manager
global twitchModule_
global discordModule_
global testModule_
global userModule_
credentials_manager = credentials.Credentials_Module()
twitchModule_ = twitch_script.Twitch_Module()
discordModule_ = discord_script.Discord_Module()
testModule_ = test_module.Test_Module()
userModule_ = user_module.User_Module()
@ -85,20 +52,9 @@ def thread_main():
dbCert: credentials.DB_Credential = credentials_manager.find_Credential(credentials.DB_Credential, config.credentialsNickname)
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))
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))
threads.append(thread_)
thread_.start()
if config.test_module == True:
thread_ = threading.Thread(target=test_module_init, args=(dbCert, None))
thread_.daemon = True
threads.append(thread_)
thread_.start()
@ -106,10 +62,11 @@ def thread_main():
if utility.isRunningInDocker() == False:
config.user_module = False
thread_ = threading.Thread(target=user_module_init, args=(dbCert, None))
thread_.daemon = True
threads.append(thread_)
thread_.start()
print("---Post Thread Creation Test---")
print("---Post Thread Creation Test---\n")
for t in threads:
t.join()

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
psutil
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 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.client import Client
import asyncio
import config as config
import db
import tts
import config
import commands.command_base
import commands.loader as command_loader
from commands.command_base import AbstractCommand
@ -22,6 +25,12 @@ import discord.abc
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):
def __init__(self):
super().__init__()
@ -32,12 +41,6 @@ class Discord_Module(discord.Client):
self.cooldownModule:Cooldown_Module = Cooldown_Module()
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
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))")
@ -58,34 +61,21 @@ class Discord_Module(discord.Client):
print("{" + message.guild.name + "}[ " + str(message.channel) + " ](" + message.author.display_name + ")> ")
#print(message.author.mention)
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):
# This will check for the praxis_bot-tts channel and will TTS stuff from there.
await self.eval_triggeredEvents(message)
# This will check for the praxis_bot-tts channel and will TTS stuff from there.
#await self.eval_triggeredEvents(message)
if self.cooldownModule.isCooldownActive("discordRateLimit") == False:
await self.eval_commands(message)
#await self.tts_message(message)
await self.eval_commands(message)
await self.eval_tts(message)
async def eval_triggeredEvents(self, message: discord.Message):
# 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
for channel in self.selected_ttsChannels:
@ -93,112 +83,60 @@ class Discord_Module(discord.Client):
# await self.tts_message(message)
pass
async def eval_automaticEvents(self, message: discord.Message):
pass
async def eval_tts(self, message: discord.Message):
command, rest = utility.parse_line(message.content)
try:
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):
# containsURL: bool = self.contains_url(message)
command, rest = utility.parse_line(message.content)
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
# it cant find the substring.
if message.content.find(" ") != -1:
first_space_idx = message.content.index(' ')
else:
first_space_idx = -1
async 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
command_text = ' '
if first_space_idx > -1:
command_text = message.content[0:first_space_idx]
else:
command_text = message.content
async def exec_command(self, realMessage: discord.Message, command: str, rest: str):
# todo need to url-escape command and rest
params = urlencode(
{'command_source': commands.command_base.AbstractCommand.CommandSource.Discord,
'user_name': realMessage.author.mention,
'command_name': command,
'rest': rest,
'bonus_data': realMessage})
command = self.commands[command_text]
if command is not None and command.command_type is AbstractCommand.CommandType.DISCORD:
await command.do_command(self, message)
except Exception as e:
# Undo the following for debug stuff
#print(e)
pass # we don't care
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:
await self.send_message(realMessage, msg)
else:
# todo handle failed requests
pass
async def send_message(self, message: discord.Message, response):
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:
await message.channel.send(response)
self.cooldownModule.actionTrigger("discordRateLimit")
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
if not utility.contains_slur(response):
await message.channel.send(response)
self.cooldownModule.actionTrigger("discordRateLimit")
# Checks if Sender is bot.
async def isSenderBot(self, message: discord.Message):
@ -217,12 +155,75 @@ class Discord_Module(discord.Client):
#print("isSelf: " + str(discordChannel) + " vs " + str(selectedChannel))
if discordChannel == selectedChannel:
is_Self = True
#if is_Self:
# print("Is Self")
#if not is_Self:
# print("Is Not 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.discordCredential = credentials_manager.find_Discord_Credential(config.credentialsNickname)
for ttsChannel in config.selected_discordTTSChannels:
testModule.selected_ttsChannels.append(int(ttsChannel))
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)

103
tempText_Module.py Normal file
View File

@ -0,0 +1,103 @@
import config
import utilities_script as utilities
import os
class tempText_Module():
def __init__(self):
super().__init__()
self.tempText_items = {}
def main(self):
pass
def makeItem(self, tempTextItem_):
self.addItem(tempTextItem_.itemName, tempTextItem_.itemTitle, tempTextItem_.itemContent)
self.tempText_stringUpdater()
self.update_tempTextFiles()
def addItem(self, name, title, content):
newItem:tempTextItem = tempTextItem(name=name, title=title, content=content)
newItem.setupItem(name, title, content)
self.tempText_items[name] = newItem
def getItem(self, name):
return self.tempText_items[name]
def updateItem(self, name, title, content):
newItem:tempTextItem = tempTextItem(name=name, title=title, content=content)
newItem.setupItem(name, title, content)
self.tempText_items[name] = newItem
def deleteItem(self, name):
return self.tempText_items.pop(name, None)
def tempText_stringUpdater(self):
for c in self.tempText_items:
self.tempText_items[c].item_stringUpdater()
def update_tempTextFiles(self):
dir = utilities.get_dir("stream_sources")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
for key in self.tempText_items:
item = self.tempText_items[key]
relative_path = "stream_sources/" + item.itemName + ".txt"
real_file_path = os.path.join(script_dir, relative_path)
file = open(real_file_path, "wb")
itemText_ = item.item_stringUpdater().encode("utf8")
file.write(itemText_)
file.close
def getTempTextFile(self, key):
dir = utilities.get_dir("stream_sources")
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
relative_path = "stream_sources/" + key + ".txt"
real_file_path = os.path.join(script_dir, relative_path)
file = open(real_file_path, "rb")
text = file.read()
#print(text)
file.close
return text
class tempTextItem():
def __init__(self, name = "", includeTitle = True, title = "", content = ""):
super().__init__()
self.itemName = name #This will determine the fileName
self.includeTitle = includeTitle
self.itemTitle = title
self.itemContent = content
self.itemComputedString = ""
def setupItem(self, name, title, content):
print("\nSetting up tempTextItem {", name,"}[", title, content, "]")
self.itemName = name
self.itemTitle = title
self.itemContent = content
self.item_stringUpdater()
def item_stringUpdater(self):
newString = ""
if self.includeTitle == True:
newString = newString + self.itemTitle
newString = newString + self.itemContent
self.itemComputedString = newString
return self.itemComputedString
if __name__ == "__main__":
testModule = tempText_Module()
testModule.main()
#testModule.addItem("test","title: ", "content content content")
#testModule.tempText_stringUpdater()
testItem = tempTextItem("testy","title: ", "content content content")
testModule.makeItem(testItem)
testModule.update_tempTextFiles()

View File

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

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

@ -0,0 +1,321 @@
<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);
}

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