mirror of https://gitlab.com/gpvkt/twitchtts.git
Quote function added
This commit is contained in:
parent
995738368c
commit
2751d329c3
|
@ -3,3 +3,4 @@ build
|
||||||
tts.spec
|
tts.spec
|
||||||
tts.exe
|
tts.exe
|
||||||
random*.txt
|
random*.txt
|
||||||
|
quotes.txt
|
||||||
|
|
21
README.md
21
README.md
|
@ -118,8 +118,11 @@ Please note that the `oauth_token` is valid for approximately 60 days. If it bec
|
||||||
* `votestart`: Message when a quickvote is started.
|
* `votestart`: Message when a quickvote is started.
|
||||||
* `voteend`: Message if a quickvote ends.
|
* `voteend`: Message if a quickvote ends.
|
||||||
* `votenobody`: Message if quickvote ends, but nobody has voted.
|
* `votenobody`: Message if quickvote ends, but nobody has voted.
|
||||||
* `voteresult`: Prefix for the result (will be read out)
|
* `voteresult`: Prefix for the result (will be read out).
|
||||||
* `votes`: Suffix to vote count.
|
* `votes`: Suffix to vote count.
|
||||||
|
* `quotenotfound`: Message if requests quote wasn't found.
|
||||||
|
* `quoteaddedprefix`: Prefix for `Quote <number> added` message.
|
||||||
|
* `quoteaddedsuffix`: Suffix for `Quote <number> added` message.
|
||||||
|
|
||||||
##### log
|
##### log
|
||||||
|
|
||||||
|
@ -176,6 +179,22 @@ The `!quickvote` feature implements a simple vote system. If a broadcaster or mo
|
||||||
|
|
||||||
The `!random` command will read a random line from a file called `random.txt`. You can also use multiple files, if you call `!random foo` the bot fetch the random line from a file called `random_foo.txt` instead of `random.txt`. `!random bar` will use the file `random_bar.txt` and so on. The `!random` command is restricted to the broadcaster and moderators.
|
The `!random` command will read a random line from a file called `random.txt`. You can also use multiple files, if you call `!random foo` the bot fetch the random line from a file called `random_foo.txt` instead of `random.txt`. `!random bar` will use the file `random_bar.txt` and so on. The `!random` command is restricted to the broadcaster and moderators.
|
||||||
|
|
||||||
|
#### !smartvote
|
||||||
|
|
||||||
|
The `!smartvote` command will read a line from a file called `quotes.txt`. You can add a parameter after the command. If the parameter is numeric the bot will search for a line starting with `#$number`. If the parameter is a string it will search for a line matching the parameter. If no parameter is given it will search for a completely random line.
|
||||||
|
|
||||||
|
The format of `quotes.txt` looks as follows:
|
||||||
|
|
||||||
|
``` lang=text
|
||||||
|
#1: "the quote" -username (date)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### !addquote
|
||||||
|
|
||||||
|
The `!addvote` command adds a new line to `quotes.txt`. It expects two parameters: `!addquote username quote` where `username` is the name of the user to be quoted.
|
||||||
|
|
||||||
|
Only Subs, Mods and Broadcaster are allowed to add quotes.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
If you prefer to build your own `tts.exe` instead of using the shipped one, you can do as follows:
|
If you prefer to build your own `tts.exe` instead of using the shipped one, you can do as follows:
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
fuzzywuzzy==0.18.0
|
||||||
PyYAML==6.0
|
PyYAML==6.0
|
||||||
|
|
156
tts.py
156
tts.py
|
@ -41,6 +41,8 @@ from http.server import BaseHTTPRequestHandler
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from fuzzywuzzy import process
|
||||||
|
|
||||||
class IRC:
|
class IRC:
|
||||||
""" IRC bot """
|
""" IRC bot """
|
||||||
irc = socket.socket()
|
irc = socket.socket()
|
||||||
|
@ -207,6 +209,14 @@ class IRC:
|
||||||
logging.debug("Ping check received.")
|
logging.debug("Ping check received.")
|
||||||
self.sendmsg(conf['IRC_CHANNEL'], "@"+str(user), "Pong!")
|
self.sendmsg(conf['IRC_CHANNEL'], "@"+str(user), "Pong!")
|
||||||
|
|
||||||
|
if msg.startswith('!addquote'):
|
||||||
|
logging.debug("!addquote command detected")
|
||||||
|
self.Commands.addquote(self, tags, msg)
|
||||||
|
|
||||||
|
if msg.startswith('!smartquote'):
|
||||||
|
logging.debug("!smartquote command detected")
|
||||||
|
self.Commands.quote(self, tags, msg)
|
||||||
|
|
||||||
elif msg.startswith('!dtts'):
|
elif msg.startswith('!dtts'):
|
||||||
logging.debug("!dtts command detected")
|
logging.debug("!dtts command detected")
|
||||||
self.Commands.dtts(self, msg)
|
self.Commands.dtts(self, msg)
|
||||||
|
@ -408,6 +418,146 @@ class IRC:
|
||||||
logging.info('Sending TTS message to raw_queue')
|
logging.info('Sending TTS message to raw_queue')
|
||||||
IRC.send_tts_msg(self, msg, tags)
|
IRC.send_tts_msg(self, msg, tags)
|
||||||
|
|
||||||
|
def addquote(self, tags, msg):
|
||||||
|
""" !addquote command
|
||||||
|
|
||||||
|
Adds a newline to quotes.txt
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = tags['user']
|
||||||
|
|
||||||
|
if IRC.check_user_denied(self, user):
|
||||||
|
logging.info('User is not allowed to use TTS')
|
||||||
|
elif IRC.check_subonly(self, tags):
|
||||||
|
logging.info('TTS is sub-only')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
with open("quotes.txt", "rb") as fp:
|
||||||
|
nol = len(fp.readlines())
|
||||||
|
fp.close()
|
||||||
|
except FileNotFoundError:
|
||||||
|
logging.warn("quotes.txt does not exists, will create")
|
||||||
|
nol = 0
|
||||||
|
|
||||||
|
nol = nol + 1
|
||||||
|
quote = msg.replace("!addquote ", "").strip()
|
||||||
|
quote = quote.split(" ",1)
|
||||||
|
username = quote[0]
|
||||||
|
|
||||||
|
quote = '#%s: "%s" -%s' % (nol, quote[1], username)
|
||||||
|
logging.info('Adding quote %s', quote)
|
||||||
|
|
||||||
|
with open("quotes.txt", "ab") as fp:
|
||||||
|
fp.write(quote.encode('utf-8'))
|
||||||
|
|
||||||
|
msg = "%s #%s %s" % (conf['MESSAGE']['QUOTE_ADDED_PREFIX'], nol, conf['MESSAGE']['QUOTE_ADDED_SUFFIX'])
|
||||||
|
|
||||||
|
raw_msg = {
|
||||||
|
"TTS": True,
|
||||||
|
"msg": msg,
|
||||||
|
"badges": True,
|
||||||
|
"subscriber": True,
|
||||||
|
"msgid": True,
|
||||||
|
"user": conf['IRC_USERNAME'],
|
||||||
|
"length": conf['IRC_TTS_LEN'],
|
||||||
|
"queuetime": datetime.datetime.now(),
|
||||||
|
"timestamp": str(time.time_ns())
|
||||||
|
}
|
||||||
|
msg_queue[raw_msg['timestamp']] = [raw_msg['user'], raw_msg['msg']]
|
||||||
|
IRC.sendmsg(self, conf['IRC_CHANNEL'], "@"+str(user), msg)
|
||||||
|
|
||||||
|
|
||||||
|
def quote(self, tags, msg = False):
|
||||||
|
""" !q command
|
||||||
|
|
||||||
|
Gets a line from quotes.txt. If a number if given as msg
|
||||||
|
it fetch the given line number. If a string is given
|
||||||
|
it fetch the best matching line. If nothing is given
|
||||||
|
it fetch a random line.
|
||||||
|
"""
|
||||||
|
|
||||||
|
user = tags['user']
|
||||||
|
query = msg.replace('!smartquote', '').strip()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if query.isdigit():
|
||||||
|
logging.info('Fetching quote #%s', query)
|
||||||
|
|
||||||
|
fp = open("quotes.txt", "rb")
|
||||||
|
quotes = fp.readlines()
|
||||||
|
|
||||||
|
for line in quotes:
|
||||||
|
if line.decode('utf-8').startswith("#"+str(query)+":"):
|
||||||
|
quote = line
|
||||||
|
break
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
elif query != "":
|
||||||
|
logging.info('Fetching match for %s', query)
|
||||||
|
|
||||||
|
fp = open("quotes.txt", "rb")
|
||||||
|
quotes = fp.readlines()
|
||||||
|
matches = process.extract(query, quotes, limit=20)
|
||||||
|
quotes = []
|
||||||
|
|
||||||
|
for match, score in matches:
|
||||||
|
if score >= 60:
|
||||||
|
quotes.append(match)
|
||||||
|
|
||||||
|
quote = random.choice(quotes)
|
||||||
|
|
||||||
|
else:
|
||||||
|
logging.info('Fetching random quote')
|
||||||
|
|
||||||
|
with open("quotes.txt", "rb") as file:
|
||||||
|
lines = file.read().splitlines()
|
||||||
|
quote = random.choice(lines)
|
||||||
|
except FileNotFoundError:
|
||||||
|
logging.error('"quotes.txt does not exists.')
|
||||||
|
|
||||||
|
if not 'quote' in vars():
|
||||||
|
logging.info('No quote found.')
|
||||||
|
quote = conf['MESSAGE']['QUOTE_NOT_FOUND']
|
||||||
|
IRC.sendmsg(self, conf['IRC_CHANNEL'], "", quote)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if isinstance(quote, str):
|
||||||
|
quote = quote
|
||||||
|
else:
|
||||||
|
quote = quote.decode('utf-8')
|
||||||
|
|
||||||
|
if IRC.check_tts_disabled(self, user):
|
||||||
|
logging.info('TTS is disabled')
|
||||||
|
elif IRC.check_user_denied(self, user):
|
||||||
|
logging.info('User is not allowed to use TTS')
|
||||||
|
elif IRC.check_subonly(self, tags):
|
||||||
|
logging.info('TTS is sub-only')
|
||||||
|
elif IRC.check_modonly(self, tags):
|
||||||
|
logging.info('TTS is mod-only')
|
||||||
|
elif IRC.check_whitelist(self, user):
|
||||||
|
logging.info('User is not on whitelist')
|
||||||
|
else:
|
||||||
|
logging.info('Sending quote to TTS')
|
||||||
|
logging.debug("Quote: %s", quote)
|
||||||
|
IRC.sendmsg(self, conf['IRC_CHANNEL'], "", quote)
|
||||||
|
|
||||||
|
quote = quote.rsplit('(', 1)[0]
|
||||||
|
|
||||||
|
raw_msg = {
|
||||||
|
"TTS": True,
|
||||||
|
"msg": quote,
|
||||||
|
"badges": True,
|
||||||
|
"subscriber": True,
|
||||||
|
"msgid": True,
|
||||||
|
"user": conf['IRC_USERNAME'],
|
||||||
|
"length": conf['IRC_TTS_LEN'],
|
||||||
|
"queuetime": datetime.datetime.now(),
|
||||||
|
"timestamp": str(time.time_ns())
|
||||||
|
}
|
||||||
|
msg_queue[raw_msg['timestamp']] = [raw_msg['user'], raw_msg['msg']]
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def quickvote(self, msg):
|
def quickvote(self, msg):
|
||||||
""" !quickvote command
|
""" !quickvote command
|
||||||
|
|
||||||
|
@ -760,7 +910,11 @@ def load_config():
|
||||||
conf['MESSAGE']['VOTEEND'] = cfg.get('messages', {}).get('voteend', "Quickvote ended. The results are:")
|
conf['MESSAGE']['VOTEEND'] = cfg.get('messages', {}).get('voteend', "Quickvote ended. The results are:")
|
||||||
conf['MESSAGE']['VOTENOBODY'] = cfg.get('messages', {}).get('votenobody', "Nobody casted a vote. :(")
|
conf['MESSAGE']['VOTENOBODY'] = cfg.get('messages', {}).get('votenobody', "Nobody casted a vote. :(")
|
||||||
conf['MESSAGE']['VOTERESULT'] = cfg.get('messages', {}).get('voteresult', "Voting has ended. The result is:")
|
conf['MESSAGE']['VOTERESULT'] = cfg.get('messages', {}).get('voteresult', "Voting has ended. The result is:")
|
||||||
conf['MESSAGE']['VOTES'] = cfg.get('messages', {}).get('votes', "Stimmen")
|
conf['MESSAGE']['VOTES'] = cfg.get('messages', {}).get('votes', "Votes")
|
||||||
|
|
||||||
|
conf['MESSAGE']['QUOTE_NOT_FOUND'] = cfg.get('messages', {}).get('quotenotfound', "Sorry, no quote found.")
|
||||||
|
conf['MESSAGE']['QUOTE_ADDED_PREFIX'] = cfg.get('messages', {}).get('quoteaddedprefix', "Quote:")
|
||||||
|
conf['MESSAGE']['QUOTE_ADDED_SUFFIX'] = cfg.get('messages', {}).get('quoteaddedsuffix', "added.")
|
||||||
|
|
||||||
conf['USERMAP'] = cfg.get('usermapping', [])
|
conf['USERMAP'] = cfg.get('usermapping', [])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue