diff --git a/.env.template b/.env.template index f4b7f21e76d7c4f1356dbf05904a1731a4221cb6..2d486a434e9b579c2b830581eb4c98dffbad7809 100644 --- a/.env.template +++ b/.env.template @@ -1,34 +1,36 @@ # Template .env File -# General +######################################################################################################################## +# Django # +######################################################################################################################## +#General +DJANGO_SECRET=<Secrect used by Django> +DJANGO_ALLOWED_HOST1=<First allowed host> +DJANGO_ALLOWED_HOST2=<Second allowed host> +DJANGO_DEBUG=True + +######################################################################################################################## +# Twitch Bot # +######################################################################################################################## +#General IRC_TOKEN=oauth:<OAuth Token to be used for login. Can be generated by using https://twitchapps.com/tmi/> +CLIENT_ID=<Client ID> +CLIENT_SECRET=<Client Secret> NICK=<Nick of the user the OAuth Token was generated for> CHANNEL=<Channel that should be entered> PREFIX=! +BROADCASTER_ID=<Twitch Channel ID> +REDIRECT_URI=<Redirect URI used for Twitch API> -# Pipi Bot -PIPI_DELAY=15 -PIPI_THRESHOLD_1=1 -PIPI_THRESHOLD_2=3 -PIPIMETER_LOOP=10 -PIPI_RESET_THRESHOLD=30 -PIPI_COLOR_0=YellowGreen -PIPI_COLOR_1=Green -PIPI_COLOR_2=GoldenRod -PIPI_COLOR_3=Red # Vote Bot VOTE_DELAY_END=5 VOTE_DELAY_INTERIM=20 VOTE_MIN_VOTES=10 -VOTE_COLOR=OrangeRed VOTE_PLUS=haugePlus VOTE_MINUS=haugeMinus VOTE_NEUTRAL=haugeNeutral -# Giveaway Bot -GIVEAWAY_COLOR=OrangeRed - # Redis Server REDIS_HOST=127.0.0.1 REDIS_PORT=6379 diff --git a/.idea/haugebot.iml b/.idea/haugebot.iml index 13a13f0c737ba7ff61d8852f8067f26013f14c88..bdc380bb6652d1d0f2ee01cb0be3903bcd200fef 100644 --- a/.idea/haugebot.iml +++ b/.idea/haugebot.iml @@ -16,7 +16,7 @@ <content url="file://$MODULE_DIR$"> <excludeFolder url="file://$MODULE_DIR$/venv" /> </content> - <orderEntry type="jdk" jdkName="Python 3.9 (haugebot) (2)" jdkType="Python SDK" /> + <orderEntry type="jdk" jdkName="Python 3.9 (haugebot)" jdkType="Python SDK" /> <orderEntry type="sourceFolder" forTests="false" /> </component> <component name="TemplatesService"> diff --git a/.idea/misc.xml b/.idea/misc.xml index 60d2706085f962f449dd51dbdbe8a74bb537b286..4b622f007e3e806f8d1f7aa09146a254420d92d4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ <component name="JavaScriptSettings"> <option name="languageLevel" value="ES6" /> </component> - <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (haugebot) (2)" project-jdk-type="Python SDK" /> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (haugebot)" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/README.md b/README.md index 5a5aee3b164a78f97e97bce8d931733e4eff5f9b..2a12e759ac12a9aede67cfa6d50e5829d61b7da0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ A Twitch Bot for channel DerHauge. ### Vote Bot - Checks every chat message for the following beginnings: results in | trigger @@ -16,29 +15,6 @@ Posts an interim result every 20 seconds and an end result after 5 seconds of no Checks if more than 10 votes have been added before posting any result. -### Pipi Bot - -Offers commands to count the number of chat users who need to go to the toilet. - - !pipi -> To mention, that you need to go to the toilet - !warpipi -> To mention, that you have been to the toilet before a break was announced - !zuspät -> Mention, that is now too late, and you had an accident - !pipimeter [mod-only] -> Get the current count of users that need to go to toilet - !pause [mod-only] -> Announce a break and reset the counter - !reset [mod-only] -> Resets all pipi-votes - -### Giveaway Bot - -Offers some commands to control a giveaway: - - !giveaway-open [mod-only] -> Resets the entry-list and open the giveaway - !giveaway-close [mod-only] -> Close the giveaway - from now nobody can enter - !giveaway-reopen [mod-only] -> Open the giveaway without resetting the entrylist - !giveaway-draw [mod-only] -> Draw a winner and remove them from the list of participants - !giveaway-reset [mod-only] -> Clear the entry-list - !giveaway -> take part at the giveaway - - ### Installation Clone this repository, create a venv and install dependencies using `pip` and the `requirements.txt` @@ -46,47 +22,4 @@ Clone this repository, create a venv and install dependencies using `pip` and th ### Configuration -Configuration of this bot is done by a `.env` file that is placed in the same directory -as the `hausgeist.py` file. This file must look like this: - - # General - IRC_TOKEN=<OAuth Token to be used for login. Can be generated by using https://twitchapps.com/tmi/> - CLIENT_ID=<Client ID that can be created by creating a twitch app at https://dev.twitch.tv/console/apps/create> - CLIENT_SECRET=<Client Secret that can be created by creating a twitch app at https://dev.twitch.tv/console/apps/create> - NICK=<Nick of the user the OAuth Token was generated for> - CHANNEL=<Channel that should be entered> - PREFIX=<Prefix for commands. In this case it is !> - - # Info Bot - INFO_JSON=<Path to json file that contains info array> - INFO_LOOP=<Number of minutes, when an information is dropped into the chat (only of the stream is live> - INFO_COLOR=<Color, info messages should be shown at> - - # Pipi Bot - PIPI_DELAY=<Delay in seconds as spam protection. This is the number of seconds between two chat announcements> - PIPI_THRESHOLD_1=<First Threshold. Used to change color and show, it is a bit more urgent> - PIPI_THRESHOLD_2=<Second Threshold. Used to change color and show, that it is really urgent> - PIPIMETER_LOOP=<Number of minutes, when the current pipi count should get sent into the chat, when the stream is life> - PIPI_RESET_THRESHOLD=<Number of minutes, the stream had to be offline, when it turns live, to reset the pipi count> - PIPI_COLOR_0=<Neutral color used for !pause command, and if pipi vote counter is 0> - PIPI_COLOR_1=<Color used when pipi vote is at least one, and less than PIPI_THRESHOLD_1> - PIPI_COLOR_2=<Color used when pipi vote is at least PIPI_THRESHOLD_1, and less than PIPI_THRESHOLD_2> - PIPI_COLOR_3=<Color used when pipi vote is above PIPI_THRESHOLD_3> - - # Vote Bot - VOTE_DELAY_END=<Number of seconds withoug a vote getting count. If this delay is reached, the vote is closed.> - VOTE_DELAY_INTERIM=<Number of seconds between two announcements of the current vote count. Also used as delay between two votes.> - VOTE_MIN_VOTES=<Number of votes to be announced at all. A vote with less users votings will not be announced at all.> - VOTE_COLOR=<Chat Color that is used to announce voting results> - VOTE_PLUS=<Positive Chate Emote> - VOTE_MINUS=<Negative Chat Emote> - VOTE_NEUTRAL=<Neutral Chat Emote> - - # Giveaway Bot - GIVEAWAY_BOT=<Chat Color that is used to send giveaway messages> - - # Redis Server - REDIS_HOST=<IP of the Redis-Server> - REDIS_PORT=<Port of the Redis-Server> - REDIS_DB=<Index of the Database> - REDIS_PW=<Password for the Redis-Server> +Configuration of this bot is done by a `.env` use `.env.template` for reference \ No newline at end of file diff --git a/haugebot_twitch/giveaway_cog.py b/haugebot_twitch/giveaway_cog.py deleted file mode 100644 index 31941bb8422a9f1e6a19a05fe7a98bb0acfed699..0000000000000000000000000000000000000000 --- a/haugebot_twitch/giveaway_cog.py +++ /dev/null @@ -1,74 +0,0 @@ -import os -import random - -from twitchio.ext import commands - - -@commands.core.cog(name="GiveawayCog") -class GiveawayCog: - def __init__(self, bot): - self.bot = bot - self.giveaway_enabled = False - self.giveaway_entries = {} - self.COLOR = os.getenv("GIVEAWAY_COLOR") - - @commands.command(name="giveaway") - async def cmd_giveaway(self, ctx): - """ take part at the giveaway """ - - if self.giveaway_enabled: - self.giveaway_entries[ctx.author.name] = 1 - - @commands.command(name="giveaway-open") - async def cmd_giveaway_open(self, ctx): - """ Reset and Open the giveaway """ - - if ctx.author.is_mod: - self.giveaway_enabled = True - self.giveaway_entries = {} - await self.bot.send_me(ctx, - "Das Giveaway wurde gestartet. Schreibe !giveaway in den Chat um daran teilzunehmen.", - self.COLOR) - - @commands.command(name="giveaway-reopen") - async def cmd_giveaway_reopen(self, ctx): - """ Reopen the giveaway after closing it (so reset) """ - - if ctx.author.is_mod: - self.giveaway_enabled = True - await self.bot.send_me(ctx, - "Das Giveaway wurde wieder geöffnet. Schreibe !giveaway in den Chat um daran teilzunehmen.", - self.COLOR) - - @commands.command(name="giveaway-close") - async def cmd_giveaway_close(self, ctx): - """ Close the giveaway """ - - if ctx.author.is_mod: - self.giveaway_enabled = False - await self.bot.send_me(ctx, "Das Giveaway wurde geschlossen. Es kann niemand mehr teilnehmen.", self.COLOR) - - @commands.command(name="giveaway-draw") - async def cmd_giveaway_draw(self, ctx): - """ Draw a giveaway winner """ - - if ctx.author.is_mod: - if len(self.giveaway_entries) > 0: - winner = random.choice(list(self.giveaway_entries)) - entry_count = len(self.giveaway_entries) - del self.giveaway_entries[winner] - await self.bot.send_me(ctx, - f"Es wurde aus {entry_count} Einträgen ausgelost. Und der Gewinner ist... @{winner}", - self.COLOR) - else: - await self.bot.send_me(ctx, "Es muss Einträge geben, damit ein Gewinner gezogen werden kann.", - self.COLOR) - - @commands.command(name="giveaway-reset") - async def cmd_giveaway_reset(self, ctx): - """ Reset giveaway entrys """ - - if ctx.author.is_mod: - self.giveaway_enabled = False - self.giveaway_entries = {} - await self.bot.send_me(ctx, "Das Giveaway wurde geschlossen und alle Einträge entfernt.", self.COLOR) diff --git a/haugebot_twitch/haugebot.py b/haugebot_twitch/haugebot.py index b3f71dd732d474e7f1f2ada1f9588c175a3bb895..26b59e1f43ccd9ea26de41174392e36095e605e4 100644 --- a/haugebot_twitch/haugebot.py +++ b/haugebot_twitch/haugebot.py @@ -1,29 +1,16 @@ -import asyncio -import logging import os import sqlite3 from abc import ABC from dotenv import load_dotenv -from giveaway_cog import GiveawayCog -from info_cog import InfoCog -from pipi_cog import PipiCog -from twitchio.dataclasses import Context, Message, Channel -from twitchio.ext import commands -from vote_cog import VoteCog - -logging.basicConfig(level=logging.INFO, filename='hausgeist.log') +from twitchio.ext.commands import Context, Bot +from twitchio import Channel, Message -load_dotenv() -IRC_TOKEN = os.getenv("IRC_TOKEN") -CLIENT_ID = os.getenv("CLIENT_ID") -CLIENT_SECRET = os.getenv("CLIENT_SECRET") -NICK = os.getenv("NICK") -CHANNEL = os.getenv("CHANNEL") -PREFIX = os.getenv("PREFIX") +from vote_cog import VoteCog +from wusstest_du_schon import WusstestDuSchon -class HaugeBot(commands.Bot, ABC): +class HaugeBot(Bot, ABC): def __init__(self): self.IRC_TOKEN = os.getenv("IRC_TOKEN") self.CLIENT_ID = os.getenv("CLIENT_ID") @@ -31,32 +18,28 @@ class HaugeBot(commands.Bot, ABC): self.NICK = os.getenv("NICK") self.CHANNEL = os.getenv("CHANNEL") self.PREFIX = os.getenv("PREFIX") - super().__init__(irc_token=IRC_TOKEN, prefix=PREFIX, nick=NICK, initial_channels=[CHANNEL], client_id=CLIENT_ID, - client_secret=CLIENT_SECRET) - self.info_cog = InfoCog(self) - # self.pipi_cog = PipiCog(self) - self.add_cog(GiveawayCog(self)) + super().__init__(token=self.IRC_TOKEN, prefix=self.PREFIX, nick=self.NICK, initial_channels=[self.CHANNEL], + client_id=self.CLIENT_ID, + client_secret=self.CLIENT_SECRET) self.add_cog(VoteCog(self)) - self.add_cog(self.info_cog) - # self.add_cog(self.pipi_cog) + self.add_cog(WusstestDuSchon(self)) @staticmethod - async def send_me(ctx, content, color): + async def send_me(ctx, content): """ Change Text color to color and send content as message """ if type(ctx) is Context or type(ctx) is Channel: - await ctx.color(color) - await ctx.send_me(content) + await ctx.send(f".me {content}") elif type(ctx) is Message: - await ctx.channel.color(color) - await ctx.channel.send_me(content) + await ctx.channel.send(f".me {content}") async def event_ready(self): print('Logged in') - self.info_cog.start_info_loop() - asyncio.create_task(self.info_cog.info_loop()) - # asyncio.create_task(self.pipi_cog.pipimeter_loop()) + if wusstest_du_schon := self.cogs.get("WusstestDuSchon"): + wusstest_du_schon.loop.start(wusstest_du_schon) + if vote_cog := self.cogs.get("VoteCog"): + vote_cog.manage_vote.start(vote_cog) @staticmethod def get_percentage(part, total): @@ -73,7 +56,7 @@ class HaugeBot(commands.Bot, ABC): return await self.get_chatters(self.CHANNEL) async def stream(self): - return await self.get_stream(self.CHANNEL) + return await self._http.get_streams(user_logins=[self.CHANNEL]) @staticmethod def get_setting(key): @@ -86,6 +69,7 @@ class HaugeBot(commands.Bot, ABC): return value +load_dotenv() bot = HaugeBot() diff --git a/haugebot_twitch/info_cog.py b/haugebot_twitch/info_cog.py deleted file mode 100644 index b638bbcf2fb58f0cf006c1d9d024ba43732915ae..0000000000000000000000000000000000000000 --- a/haugebot_twitch/info_cog.py +++ /dev/null @@ -1,42 +0,0 @@ -import asyncio -import random -import sqlite3 - -import config -from twitchio.ext import commands - - -@commands.core.cog() -class InfoCog: - def __init__(self, bot): - self.bot = bot - - def start_info_loop(self): - loop = asyncio.get_event_loop() - loop.create_task(self.info_loop()) - - async def info_loop(self): - while True: - sleep_duration = config.get_int("WusstestDuSchonLoop") - await asyncio.sleep(sleep_duration * 60) - - if await self.bot.stream(): - channel = self.bot.channel() - color = config.get_value("WusstestDuSchonColor") - prefix = config.get_value("WusstestDuSchonPrefix") - message = self.get_random_message(prefix) - await self.bot.send_me(channel, message, color) - - @staticmethod - def get_random_message(prefix): - conn = sqlite3.connect("db.sqlite3") - - c = conn.cursor() - c.execute('SELECT text, use_prefix from haugebot_web_wusstestduschon where active is true') - wusstestduschon = random.choice(c.fetchall()) - conn.close() - - if wusstestduschon[1] == 1: - return prefix.strip() + " " + wusstestduschon[0].strip() - else: - return wusstestduschon[0] diff --git a/haugebot_twitch/pipi_cog.py b/haugebot_twitch/pipi_cog.py deleted file mode 100644 index 61546ff6472c464bbc8b1d0079855c5895cbb1bb..0000000000000000000000000000000000000000 --- a/haugebot_twitch/pipi_cog.py +++ /dev/null @@ -1,159 +0,0 @@ -import asyncio -import logging -import sqlite3 -from datetime import datetime - -import config -from twitchio.dataclasses import Message -from twitchio.ext import commands - - -@commands.core.cog(name="PipiCog") -class PipiCog: - def __init__(self, bot): - self.bot = bot - self.pipi_task = None - - async def notify_pipi(self, ctx, use_timer=True, message=None): - """ Write a message in chat, if there hasn't been a notification since <PipiDelay> seconds. """ - - if use_timer and self.pipi_task and not self.pipi_task.done(): - return - - if self.pipi_task: - self.pipi_task.cancel() - - self.pipi_task = asyncio.create_task(self.pipi_block_notification()) - chatters = await self.bot.chatters() - - if message is not None: - await self.bot.send_me(ctx, message, config.get_value("PipiColor0")) - else: - vote_ctr = self.get_pipimeter() - - percentage = self.bot.get_percentage(vote_ctr, chatters.count) - - if vote_ctr == 0: - await self.bot.send_me(ctx, - f'Kein Druck (mehr) auf der Blase. Es kann fröhlich weiter gestreamt werden!', - config.get_value("PipiColor0")) - elif vote_ctr == 1: - await self.bot.send_me(ctx, f'{vote_ctr} ({percentage}%) Mensch müsste mal', - config.get_value("PipiColor1")) - elif percentage < config.get_int("PipiThreshold1"): - await self.bot.send_me(ctx, f'{vote_ctr} ({percentage}%) Menschen müssten mal', - config.get_value("PipiColor1")) - elif percentage < config.get_int("PipiThreshold2"): - await self.bot.send_me(ctx, f'{vote_ctr} ({percentage}%) Menschen müssten mal haugeAgree', - config.get_value("PipiColor2")) - else: - await self.bot.send_me(ctx, f'{vote_ctr} ({percentage}%) Menschen müssten mal haugeAgree haugeAgree', - config.get_value("PipiColor3")) - - async def pipi_block_notification(self): - """ Just do nothing but sleep for <PipiDelay> seconds """ - - await asyncio.sleep(config.get_int("PipiDelay")) - - async def pipimeter_loop(self): - """ Send !pipimeter into the chat every x Minutes. Also check, whether the stream was offline for x Minutes. - If this is true, reset the pipi counter, as you can assume, that the stream recently started.""" - - logging.log(logging.INFO, - f"Pipi loop started To have an offset from Info loop, wait for one minute. {datetime.now()} {self}") - offline_since = 0 - await asyncio.sleep(60) - - while True: - pipimeter_loop = config.get_int("PipimeterLoop") - logging.log(logging.INFO, - f"Inside Pipi loop. Sleep for {pipimeter_loop} minutes. {datetime.now()} {self}") - await asyncio.sleep(pipimeter_loop * 60) - logging.log(logging.INFO, f"Inside Pipi loop finished sleeping now. {datetime.now()} {self}") - - if await self.bot.stream(): - logging.log(logging.INFO, - f"Inside Pipi loop. Stream is online, so check for threshold!!! {datetime.now()} {self}") - if offline_since >= config.get_int("PipimeterResetThreshold"): - self.truncate_pipimeter() - offline_since = 0 - - if self.get_pipimeter() > 0: - channel = self.bot.channel() - message = Message(channel=channel) - await self.notify_pipi(message, use_timer=False) - else: - offline_since += pipimeter_loop - - logging.log(logging.INFO, - f"Inside Pipi loop. Ooooookay, Loop ended, let's continue with the next round!!! {datetime.now()} {self}") - - @commands.command(name="pipi", aliases=["Pipi"]) - async def cmd_pipi(self, ctx): - """ User mentioned there is a need to go to toilet. """ - - self.add_pipimeter(ctx.author.name) - await self.notify_pipi(ctx) - - @commands.command(name="warpipi", aliases=["Warpipi", "zuspät", "Zuspät"]) - async def cmd_warpipi(self, ctx): - """ User already went to toilet. """ - - if ctx.author.name: - self.remove_pipimeter(ctx.author.name) - await self.notify_pipi(ctx) - - @commands.command(name="pause", aliases=["Pause"]) - async def cmd_pause(self, ctx): - """ We will do a break now! """ - - if ctx.author.is_mod: - self.truncate_pipimeter() - await self.bot.send_me(ctx, "Jetzt geht noch mal jeder aufs Klo, und dann streamen wir weiter!", - config.get_value("PipiColor0")) - - @commands.command(name="reset", aliases=["Reset"]) - async def cmd_reset(self, ctx): - """ Reset pipi votes """ - - if ctx.author.is_mod: - self.truncate_pipimeter() - - @commands.command(name="pipimeter", aliases=["Pipimeter"]) - async def cmd_pipimeter(self, ctx): - if ctx.author.is_mod: - await self.notify_pipi(ctx, use_timer=False) - - def get_pipimeter(self): - conn = sqlite3.connect("db.sqlite3") - - c = conn.cursor() - c.execute('SELECT count(user) from haugebot_web_pipimeter') - pipimeter = c.fetchone()[0] - conn.close() - - return int(pipimeter) - - def truncate_pipimeter(self): - conn = sqlite3.connect("db.sqlite3") - - c = conn.cursor() - c.execute('DELETE from haugebot_web_pipimeter') - conn.commit() - conn.close() - - def add_pipimeter(self, user): - conn = sqlite3.connect("db.sqlite3") - - c = conn.cursor() - c.execute('INSERT OR REPLACE INTO haugebot_web_pipimeter(user) values (?)', (user,)) - conn.commit() - conn.close() - - def remove_pipimeter(self, user): - conn = sqlite3.connect("db.sqlite3") - - c = conn.cursor() - c.execute('DELETE from haugebot_web_pipimeter where user = ?', (user,)) - conn.commit() - conn.close() diff --git a/haugebot_twitch/vote_cog.py b/haugebot_twitch/vote_cog.py index 21b45f23895efc812a6766952ea39f42c7d6f8cc..ed9b9c73e90c4a5b93d5a1d93ff78593edabb0d6 100644 --- a/haugebot_twitch/vote_cog.py +++ b/haugebot_twitch/vote_cog.py @@ -1,29 +1,41 @@ import asyncio import os -import time +from datetime import datetime, timedelta import vote_redis -from twitchio.ext import commands +from twitchio.ext import commands, routines -@commands.core.cog(name="VoteCog") -class VoteCog: +class VoteCog(commands.Cog): def __init__(self, bot): self.bot = bot self.DELAY_END = int(os.getenv("VOTE_DELAY_END")) self.DELAY_INTERIM = int(os.getenv("VOTE_DELAY_INTERIM")) self.MIN_VOTES = int(os.getenv("VOTE_MIN_VOTES")) - self.COLOR = os.getenv("VOTE_COLOR") self.PLUS = os.getenv("VOTE_PLUS") self.MINUS = os.getenv("VOTE_MINUS") self.NEUTRAL = os.getenv("VOTE_NEUTRAL") - self.vote_end_task = None - self.vote_interim_task = None - self.vote_task_new = None + self.next_interim = None + self.vote_end = None + self.vote_blocked = None self.votes = {} - self.bot.add_listener(self.event_message) self.redis = vote_redis.VoteRedis() + @routines.routine(seconds=1) + async def manage_vote(self): + if len(self.votes) > 0: + if datetime.now() >= self.vote_end: + await self.notify_vote_result(self.bot.channel(), final_result=True) + self.votes.clear() + self.update_redis() + self.vote_blocked = datetime.now() + timedelta(seconds=self.DELAY_INTERIM) + return + if datetime.now() >= self.next_interim: + await self.notify_vote_result(self.bot.channel()) + self.next_interim = self.calc_next_interim() + if self.vote_blocked and datetime.now() >= self.vote_blocked: + self.vote_blocked = None + async def notify_vote_result(self, message, final_result=False): votes_list = self.get_votes() @@ -33,39 +45,7 @@ class VoteCog: output += f'Endergebnis' if final_result else f'Zwischenergebnis' output += f' mit insgesamt {len(self.votes)} abgegebenen Stimmen' - await self.bot.send_me(message, output, self.COLOR) - - async def vote_end_voting(self, channel): - """ End a currently open voting """ - - # Wait for the initial VOTE_DELAY_END seconds - await asyncio.sleep(self.DELAY_END) - - # Check every second, if the delay has finished, because since VOTE_DELAY_END seconds there was no vote, - # that extended the voting time - while int(self.vote_end_task.get_name()) + self.DELAY_END >= time.time(): - await asyncio.sleep(1) - - if len(self.votes) >= self.MIN_VOTES: - await self.notify_vote_result(channel, final_result=True) - - self.votes.clear() - self.vote_task_new = asyncio.create_task(self.vote_block_votes()) - self.update_redis() - - async def vote_interim_voting(self, channel): - """ End a currently open voting """ - - await asyncio.sleep(self.DELAY_INTERIM) - if not self.vote_end_task.done() and len(self.votes) >= self.MIN_VOTES: - await self.notify_vote_result(channel) - self.vote_interim_task = asyncio.create_task( - self.vote_interim_voting(self.bot.channel())) - - async def vote_block_votes(self): - """ Just do nothing but sleep for VOTE_DELAY_INTERIM seconds """ - - await asyncio.sleep(self.DELAY_INTERIM) + await self.bot.send_me(message, output) def get_votes(self): """analyzes the votes-dict and counts the votes""" @@ -86,9 +66,10 @@ class VoteCog: [neutral, self.bot.get_percentage(neutral, len(self.votes))], [minus, self.bot.get_percentage(minus, len(self.votes))]] + @commands.Cog.event() async def event_message(self, message): # make sure the bot ignores itself and nightbot - if message.author.name.lower() in [self.bot.NICK.lower(), 'nightbot']: + if not message.author or message.author.name.lower() in [self.bot.NICK.lower(), 'nightbot']: return # check if message is a vote @@ -105,22 +86,26 @@ class VoteCog: """adds votes to the votes-dict and sets timestamps""" # Delay between two votes is not yet finished. So votes are not counted. - if self.vote_task_new and not self.vote_task_new.done(): + if self.vote_blocked: return if len(self.votes) == 0: - self.vote_end_task = asyncio.create_task(self.vote_end_voting(self.bot.channel())) - self.vote_interim_task = asyncio.create_task( - self.vote_interim_voting(self.bot.channel())) + self.next_interim = self.calc_next_interim() # should vote extend voting? if ctx.author.name not in self.votes or self.votes[ctx.author.name] != votetype: - self.vote_end_task.set_name(int(time.time())) + self.vote_end = self.calc_vote_end() # add vote to dict self.votes[ctx.author.name] = votetype self.update_redis() + def calc_next_interim(self): + return datetime.now() + timedelta(seconds=self.DELAY_INTERIM) + + def calc_vote_end(self): + return datetime.now() + timedelta(seconds=self.DELAY_END) + def update_redis(self): """analyzes the votes-dict and counts the votes""" diff --git a/haugebot_twitch/wusstest_du_schon.py b/haugebot_twitch/wusstest_du_schon.py new file mode 100644 index 0000000000000000000000000000000000000000..5f6da17ab4820eaccfa3f1e5791e6f0893bb76b8 --- /dev/null +++ b/haugebot_twitch/wusstest_du_schon.py @@ -0,0 +1,35 @@ +import random +import sqlite3 + +import config +from twitchio.ext import commands, routines + + +class WusstestDuSchon(commands.Cog): + def __init__(self, bot): + self.bot = bot + + @routines.routine(minutes=config.get_int("WusstestDuSchonLoop")) + async def loop(self): + if await self.bot.stream(): + channel = self.bot.channel() + prefix = config.get_value("WusstestDuSchonPrefix") + message = self.get_random_message(prefix) + await self.bot.send_me(channel, message) + + @staticmethod + def get_random_message(prefix): + conn = sqlite3.connect("db.sqlite3") + + c = conn.cursor() + c.execute('SELECT text, use_prefix from haugebot_web_wusstestduschon where active is true') + wusstestduschon = random.choice(c.fetchall()) + conn.close() + + if wusstestduschon[1] == 1: + return prefix.strip() + " " + wusstestduschon[0].strip() + else: + return wusstestduschon[0] + + def change_interval(self, minutes): + pass \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c794e3df838bdceeb8d6337d0587c70838f92e62..f0ca043083295bcf1e20e97fb2a93db6ada5da07 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ pytz==2020.5 redis==3.5.3 requests==2.25.1 sqlparse==0.4.1 -twitchio==1.1.0 +twitchio==2.0.0b7 typing-extensions==3.7.4.3 urllib3==1.26.2 websockets==8.1