mirror of
				https://gitlab.com/gpvkt/twitchtts.git
				synced 2025-10-31 17:17:35 +01:00 
			
		
		
		
	Added !quickvote feature
This commit is contained in:
		
							parent
							
								
									b41723609a
								
							
						
					
					
						commit
						a65a2dcccb
					
				
					 4 changed files with 88 additions and 6 deletions
				
			
		
							
								
								
									
										15
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								CHANGELOG.md
									
										
									
									
									
								
							|  | @ -2,12 +2,21 @@ | ||||||
| 
 | 
 | ||||||
| All notable changes to this project will be documented in this file. | All notable changes to this project will be documented in this file. | ||||||
| 
 | 
 | ||||||
| ## [1.0.0] - 2022-08-11 | ## [1.1.0] - unreleased | ||||||
| 
 |  | ||||||
| Initial Release |  | ||||||
| 
 | 
 | ||||||
| ### Added | ### Added | ||||||
| 
 | 
 | ||||||
|  |   * `!quickvote` feature (see README.md for details) | ||||||
|  |   * `!ping` command added | ||||||
|  | 
 | ||||||
| ### Changed | ### Changed | ||||||
| 
 | 
 | ||||||
|  |   * The bot replies with a chat message when `!ton` or `!toff` is used | ||||||
|  | 
 | ||||||
| ### Fixed | ### Fixed | ||||||
|  | 
 | ||||||
|  |   * Improved error handling | ||||||
|  | 
 | ||||||
|  | ## [1.0.0] - 2022-08-11 | ||||||
|  | 
 | ||||||
|  | Initial Release | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
										
									
									
									
								
							|  | @ -57,6 +57,10 @@ messages: | ||||||
|   whitelist: "Sorry, you are not allowed to use TTS." |   whitelist: "Sorry, you are not allowed to use TTS." | ||||||
|   ready: "TTS bot alpha ready!" |   ready: "TTS bot alpha ready!" | ||||||
|   says: "says" |   says: "says" | ||||||
|  |   votestart: "Quickvote started. Send #yourchoice to participate." | ||||||
|  |   voteend: "Quickvote ended. The results are:" | ||||||
|  |   votenobody: "Nobody casted a vote. :(" | ||||||
|  |   votes: "Votes" | ||||||
| 
 | 
 | ||||||
| log: | log: | ||||||
|   level: "INFO" |   level: "INFO" | ||||||
|  | @ -100,6 +104,10 @@ whitelist: | ||||||
|   * `whitelist`: The bots reply if `whitelist` is set and user isn't on the list. |   * `whitelist`: The bots reply if `whitelist` is set and user isn't on the list. | ||||||
|   * `ready`: The bots init message |   * `ready`: The bots init message | ||||||
|   * `says`: Prefix to add between username and message |   * `says`: Prefix to add between username and message | ||||||
|  |   * `votestart`: Message when a quickvote is started. | ||||||
|  |   * `voteend`: Message if a quickvote ends. | ||||||
|  |   * `votenobody`: Message if quickvote ends, but nobody has voted. | ||||||
|  |   * `votes`: Suffix to vote count. | ||||||
| 
 | 
 | ||||||
| ##### log | ##### log | ||||||
| 
 | 
 | ||||||
|  | @ -144,6 +152,10 @@ Additional commands (broadcaster and mods only) are: | ||||||
|   * `!dtts <username>`: Disable TTS for the given user |   * `!dtts <username>`: Disable TTS for the given user | ||||||
|   * `!ptts <username>`: Allow TTS for the given user |   * `!ptts <username>`: Allow TTS for the given user | ||||||
| 
 | 
 | ||||||
|  | ### Additional features | ||||||
|  | 
 | ||||||
|  | The bot also contains a `!quickvote` feature. If a broadcaster or moderator send the `!quickvote` command a vote will be started (or a already running vote will be ended). After a quickvote has been started your community can casts votes by sending a chat message starting with `#`. You can include a message after `!quickvote` (e.g. `!quickvote Is pizza hawaii any good? #yes/#no`). If you do so, this message will be repeated every 60 seconds, so everyone keeps in mind, that a vote is still active. | ||||||
|  | 
 | ||||||
| ## 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: | ||||||
|  |  | ||||||
|  | @ -23,6 +23,10 @@ messages: | ||||||
|   modonly: "Sorry, TTS is a mod-only feature." |   modonly: "Sorry, TTS is a mod-only feature." | ||||||
|   ready: "TTS bot alpha ready!" |   ready: "TTS bot alpha ready!" | ||||||
|   says: "says" |   says: "says" | ||||||
|  |   votestart: "Quickvote started. Send #yourchoice to participate." | ||||||
|  |   voteend: "Quickvote ended. The results are:" | ||||||
|  |   votenobody: "Nobody casted a vote. :(" | ||||||
|  |   votes: "Votes" | ||||||
| 
 | 
 | ||||||
| log: | log: | ||||||
|   level: "INFO" |   level: "INFO" | ||||||
|  |  | ||||||
							
								
								
									
										63
									
								
								tts.py
									
										
									
									
									
								
							
							
						
						
									
										63
									
								
								tts.py
									
										
									
									
									
								
							|  | @ -31,6 +31,7 @@ import socketserver | ||||||
| from threading import Thread | from threading import Thread | ||||||
| from http.server import BaseHTTPRequestHandler | from http.server import BaseHTTPRequestHandler | ||||||
| from urllib.parse import parse_qs | from urllib.parse import parse_qs | ||||||
|  | from collections import Counter | ||||||
| 
 | 
 | ||||||
| class IRC: | class IRC: | ||||||
|     irc = socket.socket() |     irc = socket.socket() | ||||||
|  | @ -40,6 +41,10 @@ class IRC: | ||||||
|         self.tts_denied = [] |         self.tts_denied = [] | ||||||
|         self.tts_allowed = [] |         self.tts_allowed = [] | ||||||
|         self.tts_status = True |         self.tts_status = True | ||||||
|  |         self.quickvote = False | ||||||
|  |         self.votemsg = False | ||||||
|  |         self.poll = {} | ||||||
|  |         self.pollcount = 0 | ||||||
| 
 | 
 | ||||||
|         if 'WHITELIST_USER' in conf: |         if 'WHITELIST_USER' in conf: | ||||||
|             self.tts_allowed = conf['WHITELIST_USER'] |             self.tts_allowed = conf['WHITELIST_USER'] | ||||||
|  | @ -63,9 +68,9 @@ class IRC: | ||||||
|         try: |         try: | ||||||
|             self.irc.send(bytes("JOIN " + channel + "\r\n", "UTF-8")) |             self.irc.send(bytes("JOIN " + channel + "\r\n", "UTF-8")) | ||||||
|         except ConnectionResetError: |         except ConnectionResetError: | ||||||
|             logging.warn('JOIN was refused, will try again in 5 seconds.') |             logging.warning('JOIN was refused, will try again in 5 seconds.') | ||||||
|             time.sleep(5) |             time.sleep(5) | ||||||
|             logging.warn('Please check your credentials, if this error persists.') |             logging.warning('Please check your credentials, if this error persists.') | ||||||
|             self.irc.send(bytes("JOIN " + channel + "\r\n", "UTF-8")) |             self.irc.send(bytes("JOIN " + channel + "\r\n", "UTF-8")) | ||||||
| 
 | 
 | ||||||
|     def sendpriv(self, channel, user, msg): |     def sendpriv(self, channel, user, msg): | ||||||
|  | @ -171,11 +176,48 @@ class IRC: | ||||||
|                     return True |                     return True | ||||||
| 
 | 
 | ||||||
|                 if msg.startswith('!ping'): |                 if msg.startswith('!ping'): | ||||||
|                     logging.debug('Ping check received.') |                     logging.debug("Ping check received.") | ||||||
|                     self.sendpriv(conf['IRC_CHANNEL'], "@"+str(user), "Pong!") |                     self.sendpriv(conf['IRC_CHANNEL'], "@"+str(user), "Pong!") | ||||||
| 
 | 
 | ||||||
|                     return True |                     return True | ||||||
| 
 | 
 | ||||||
|  |                 if msg.startswith('!quickvote'): | ||||||
|  |                     logging.info("!quickvote command detected") | ||||||
|  |                     if self.quickvote: | ||||||
|  |                         logging.debug('Quickvote stopped') | ||||||
|  | 
 | ||||||
|  |                         if self.pollcount == 0: | ||||||
|  |                             logging.info("Nobody voted") | ||||||
|  |                             self.sendpriv(conf['IRC_CHANNEL'], "@chat", conf['MESSAGE']['VOTEEND']) | ||||||
|  |                             self.sendpriv(conf['IRC_CHANNEL'], "*", conf['MESSAGE']['VOTENOBODY']) | ||||||
|  |                             self.quickvote = False | ||||||
|  |                             self.poll = {} | ||||||
|  |                             return False | ||||||
|  | 
 | ||||||
|  |                         logging.info("Counting votes") | ||||||
|  |                         count = 0 | ||||||
|  |                         count = Counter(self.poll.values()).most_common(5) | ||||||
|  |                         self.sendpriv(conf['IRC_CHANNEL'], "@chat", conf['MESSAGE']['VOTEEND']) | ||||||
|  | 
 | ||||||
|  |                         logging.debug(count) | ||||||
|  | 
 | ||||||
|  |                         for key, value in count: | ||||||
|  |                             self.sendpriv(conf['IRC_CHANNEL'], "*", str(key)+" ("+str(value)+ " "+ conf['MESSAGE']['VOTES'] + ")") | ||||||
|  | 
 | ||||||
|  |                         self.quickvote = False | ||||||
|  |                         self.poll = {} | ||||||
|  |                         self.pollcount = 0 | ||||||
|  |                         return True | ||||||
|  |                     else: | ||||||
|  |                         logging.debug('Quickvote started') | ||||||
|  |                         self.quickvote = True | ||||||
|  |                         self.votemsg = resp.split('!quickvote', 1)[1].strip() | ||||||
|  |                         if self.votemsg: | ||||||
|  |                             self.sendpriv(conf['IRC_CHANNEL'], "@chat", conf['MESSAGE']['VOTESTART'] + " (" + str(self.votemsg) + ")") | ||||||
|  |                         else: | ||||||
|  |                             self.sendpriv(conf['IRC_CHANNEL'], "@chat", conf['MESSAGE']['VOTESTART']) | ||||||
|  |                     return True | ||||||
|  | 
 | ||||||
|                 if msg.startswith('!ptts'): |                 if msg.startswith('!ptts'): | ||||||
|                     logging.debug("!ptts command detected") |                     logging.debug("!ptts command detected") | ||||||
|                     user = msg.replace('!ptts', '').strip().lower() |                     user = msg.replace('!ptts', '').strip().lower() | ||||||
|  | @ -193,6 +235,12 @@ class IRC: | ||||||
| 
 | 
 | ||||||
|                     return True |                     return True | ||||||
| 
 | 
 | ||||||
|  |                 if msg.startswith('#') and self.quickvote == True: | ||||||
|  |                     logging.info('Quickvote: Cast detected') | ||||||
|  |                     self.pollcount += 1 | ||||||
|  |                     self.poll[user] = msg.lower() | ||||||
|  |                     logging.debug(self.poll) | ||||||
|  | 
 | ||||||
|                 if msg.startswith('!toff'): |                 if msg.startswith('!toff'): | ||||||
|                     logging.info('TTS is now turned off') |                     logging.info('TTS is now turned off') | ||||||
|                     msg_queue.clear() |                     msg_queue.clear() | ||||||
|  | @ -398,6 +446,11 @@ def load_config(): | ||||||
|             conf['MESSAGE']['WHITELISTONLY'] = cfg['messages']['whitelist'] or False |             conf['MESSAGE']['WHITELISTONLY'] = cfg['messages']['whitelist'] or False | ||||||
|             conf['MESSAGE']['SAYS'] = cfg['messages']['says'] or "says" |             conf['MESSAGE']['SAYS'] = cfg['messages']['says'] or "says" | ||||||
| 
 | 
 | ||||||
|  |             conf['MESSAGE']['VOTESTART'] = cfg['messages']['votestart'] or "Quickvote started. Send #yourchoice to participate." | ||||||
|  |             conf['MESSAGE']['VOTEEND'] = cfg['messages']['voteend'] or "Quickvote ended. The results are:" | ||||||
|  |             conf['MESSAGE']['VOTENOBODY']  = cfg['messages']['votenobody'] or "Nobody casted a vote. :(" | ||||||
|  |             conf['MESSAGE']['VOTES']  = cfg['messages']['votes'] or "Stimmen" | ||||||
|  | 
 | ||||||
|             conf['USERMAP'] = cfg['usermapping'] or [] |             conf['USERMAP'] = cfg['usermapping'] or [] | ||||||
| 
 | 
 | ||||||
|             if 'whitelist' in cfg: |             if 'whitelist' in cfg: | ||||||
|  | @ -473,6 +526,10 @@ def main(): | ||||||
|             if confreload - lastreload > datetime.timedelta(seconds=60): |             if confreload - lastreload > datetime.timedelta(seconds=60): | ||||||
|                 conf = load_config() |                 conf = load_config() | ||||||
|                 lastreload = datetime.datetime.now() |                 lastreload = datetime.datetime.now() | ||||||
|  |                  | ||||||
|  |                 if irc.quickvote and irc.votemsg: | ||||||
|  |                     logging.info('Quickvote is active') | ||||||
|  |                     irc.sendpriv(conf['IRC_CHANNEL'], "@chat", conf['MESSAGE']['VOTESTART'] + " (" + str(irc.votemsg) + ")") | ||||||
| 
 | 
 | ||||||
|             logging.debug('Raw message queue:') |             logging.debug('Raw message queue:') | ||||||
|             logging.debug(msg_queue_raw) |             logging.debug(msg_queue_raw) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue