Add TOML configuration #7

Merged
skeh merged 3 commits from feature/config into main 2021-04-10 04:50:16 +00:00
6 changed files with 147 additions and 3 deletions
Showing only changes of commit 51ebff1bd5 - Show all commits

View File

@ -9,6 +9,7 @@ pygame = "*"
websocket-client = "*"
miniirc = "*"
toml = "*"
num2words = "*"
[requires]
python_version = "3.9"

18
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "78eab561bb582e47361961316e00224a4e606589ca122fc14f1d0c527c1c5dbe"
"sha256": "b0076c1e84753068b73b209da13dce37cef7680589c6b54b14204240b893797b"
},
"pipfile-spec": 6,
"requires": {
@ -31,6 +31,12 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==4.0.0"
},
"docopt": {
"hashes": [
"sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
],
"version": "==0.6.2"
},
"idna": {
"hashes": [
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
@ -47,6 +53,14 @@
"index": "pypi",
"version": "==1.6.3"
},
"num2words": {
"hashes": [
"sha256:0b6e5f53f11d3005787e206d9c03382f459ef048a43c544e3db3b1e05a961548",
"sha256:37cd4f60678f7e1045cdc3adf6acf93c8b41bf732da860f97d301f04e611cc57"
],
"index": "pypi",
"version": "==0.5.10"
},
"pygame": {
"hashes": [
"sha256:0571dde0277483f5060c8ee43cbfd8df5776b12505e3948eee241c8ce9b93371",
@ -107,7 +121,7 @@
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.15.0"
},
"toml": {

View File

@ -24,3 +24,31 @@ enabled = false
# # You can get this from https://twitchapps.com/tmi/
# oauth_key = "oauth:somethinglikethis"
[plugin.PhraseCounter]
# # Dumps a file with the current count of mesasges containting a phrase, to be read with OBS or similar
enabled = false
# # The phrases to detect
# phrases = ["pog"]
# # Relative path to dump to
# out_path="pogcount.txt"
# # If the plugin should remove duplicate letters. For example, if a phrase is "pog", with this we would count "pooooggg"
# detect_extentions = false
# # Count regardless of the position of spaces
# detect_spaced = false
# # Min number of seconds to wait inbetween file updates
# debounce_time = 1
# # Template of the text to dump, based on the standard python string format.
# # + {phrase} - the count as a number, ex "42"
# # + {phrase!s} - the count as a string, ex "fourty-two"
# # + {phrase!p:singular|plural} - chooses between the two strings depending on if the count is singular or plural in english
# # ex, `There's {pog} {pog!p:pog|pogs} in chat` would produce "There's 0 pogs in chat" and "There's 1 pog in chat"
# # A few special phrases are supported:
# # + "sum" - sum of all phrase counts
# # + "match" - number of messages containing any one of the phrases
# # + "nmatch" - number of messages containing NONE of the phrases
# # To make this multiline, use three quote marks and a newline, ie
# # template = """
# # multiline content
# # goes here!
# # """
# template="Pog count: {pog}"

84
plugins/PhraseCounter.py Normal file
View File

@ -0,0 +1,84 @@
from .PluginBase import PluginBase
from string import Formatter
from num2words import num2words
def remove_dups(text):
last_char = None
for char in list(text):
if last_char == char:
continue
last_char = char
yield char
class PhraseCounterFormatter(Formatter):
def convert_field(self, value, conversion):
if conversion == 's':
return num2words(value)
if conversion == 'p':
return value == 1
else:
return super().convert_field(value, conversion)
def format_field(self, value, format_spec):
if '|' in format_spec:
singular, plural = format_spec.split('|')
return singular if value else plural
else:
return super().format_field(value, format_spec)
class Plugin(PluginBase):
def __init__(self, out_path=None, phrases=None, template=None,
detect_spaced=False, detect_extentions=False, debounce_time=1):
if out_path is None or phrases is None or template is None:
raise ValueError('Missing config requirements')
self.out = out_path
self.phrases = phrases
self.template = template
self.detect_extentions = detect_extentions
self.detect_spaced = detect_spaced
self.debounce_time = debounce_time
self._counts = {phrase: 0 for phrase in phrases + ['sum', 'match', 'nmatch']}
self._timer = 0
self._dirty = True
self._formatter = PhraseCounterFormatter()
def normalize(self, text):
if self.detect_extentions:
text = ''.join(remove_dups(text.lower()))
if self.detect_spaced:
text = ''.join(text.split(' '))
return text
def tick(self, dt):
self._timer += dt
if self._timer > self.debounce_time and self._dirty:
out_string = self._formatter.format(self.template, **self._counts)
with open(self.out, 'w') as f:
f.write(out_string)
self._timer = 0
self._dirty = False
def handle_event(self, event):
pass
def on_message(self, message):
self._dirty = True
normalized = self.normalize(message.text)
has_match = False
for phrase in self.phrases:
if phrase in normalized:
self._counts[phrase] += 1
self._counts['sum'] += 1
has_match = True
if has_match:
self._counts['match'] += 1
else:
self._counts['nmatch'] += 1
return message

18
plugins/PluginBase.py Normal file
View File

@ -0,0 +1,18 @@
from abc import ABC, abstractmethod
class PluginBase(ABC):
def __init__(self):
super().__init__()
@abstractmethod
def tick(self, dt):
pass
@abstractmethod
def handle_event(self, event):
pass
@abstractmethod
def on_message(self, message):
pass

View File

@ -1 +0,0 @@
from chats import AUTHOR_TYPES