Add TOML configuration #7
1
Pipfile
1
Pipfile
|
@ -9,6 +9,7 @@ pygame = "*"
|
|||
websocket-client = "*"
|
||||
miniirc = "*"
|
||||
toml = "*"
|
||||
num2words = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
|
|
|
@ -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": {
|
||||
|
|
28
config.toml
28
config.toml
|
@ -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}"
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
from chats import AUTHOR_TYPES
|
Loading…
Reference in New Issue