diff --git a/.env.template b/.env.template
index e9696e9affb3210abaf01f85c4dbff84d373a11e..f4b7f21e76d7c4f1356dbf05904a1731a4221cb6 100644
--- a/.env.template
+++ b/.env.template
@@ -8,8 +8,10 @@ PREFIX=!
 
 # Pipi Bot
 PIPI_DELAY=15
-PIPI_THRESHOLD_1=10
-PIPI_THRESHOLD_2=20
+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
@@ -24,6 +26,9 @@ 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/vagrant.xml b/.idea/vagrant.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a5aa78680308cff5d34e132d6cabd2ab43745203
--- /dev/null
+++ b/.idea/vagrant.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VagrantProjectSettings">
+    <option name="instanceFolder" value="" />
+    <option name="provider" value="" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/hausgeist.py b/hausgeist.py
index a480b4cd8710f8ad6f1d7886d9cfd1af9606e2cf..e43628c7618890e938fc7afc3c827f05dcaad9ef 100644
--- a/hausgeist.py
+++ b/hausgeist.py
@@ -1,15 +1,13 @@
-import asyncio
 import os
-import time
 from abc import ABC
 
-import redis
 from dotenv import load_dotenv
 from twitchio.dataclasses import Context, Message, Channel
 from twitchio.ext import commands
 
 from giveaway_cog import GiveawayGog
 from pipi_cog import PipiCog
+from vote_cog import VoteCog
 
 load_dotenv()
 IRC_TOKEN = os.getenv("IRC_TOKEN")
@@ -19,19 +17,6 @@ NICK = os.getenv("NICK")
 CHANNEL = os.getenv("CHANNEL")
 PREFIX = os.getenv("PREFIX")
 
-# vote bot related
-VOTE_DELAY_END = int(os.getenv("VOTE_DELAY_END"))
-VOTE_DELAY_INTERIM = int(os.getenv("VOTE_DELAY_INTERIM"))
-VOTE_MIN_VOTES = int(os.getenv("VOTE_MIN_VOTES"))
-VOTE_COLOR = os.getenv("VOTE_COLOR")
-VOTE_PLUS = os.getenv("VOTE_PLUS")
-VOTE_MINUS = os.getenv("VOTE_MINUS")
-VOTE_NEUTRAL = os.getenv("VOTE_NEUTRAL")
-vote_end_task = None
-vote_interim_task = None
-vote_task_new = None
-votes = {}
-
 
 class HaugeBot(commands.Bot, ABC):
     def __init__(self):
@@ -45,8 +30,10 @@ class HaugeBot(commands.Bot, ABC):
                          client_secret=CLIENT_SECRET)
         self.pipi_cog = PipiCog(self)
         self.giveaway_cog = GiveawayGog(self)
+        self.vote_cog = VoteCog(self)
         self.add_cog(self.pipi_cog)
         self.add_cog(self.giveaway_cog)
+        self.add_cog(self.vote_cog)
 
     @staticmethod
     async def send_me(ctx, content, color):
@@ -74,50 +61,6 @@ class HaugeBot(commands.Bot, ABC):
 
 bot = HaugeBot()
 
-# redis-server related
-R_HOST = os.getenv("REDIS_HOST")
-R_PORT = os.getenv("REDIS_PORT")
-R_DB = os.getenv("REDIS_DB")
-R_PW = os.getenv("REDIS_PW")
-
-useRedis = False
-
-# try to connect
-r = None
-try:
-    r = redis.Redis(host=R_HOST, port=R_PORT, db=R_DB, password=R_PW)
-    print(r)
-    r.ping()
-    useRedis = True
-    print('Redis: Connected!')
-except Exception as ex:
-    print('A connection to the Redis server could not be established. Redis querys are avoided.')
-
-if useRedis and r:
-    # update constants in Redis-DB
-    r.set('voteMin', VOTE_MIN_VOTES)
-    r.set('voteDelayEnd', VOTE_DELAY_END)
-    r.set('voteDelayInter', VOTE_DELAY_INTERIM)
-
-    # reset DB
-    p = r.pipeline()  # start transaction
-    p.set('plus', 0)
-    p.set('neutral', 0)
-    p.set('minus', 0)
-    p.execute()  # transaction end
-
-
-async def notify_vote_result(message, final_result=False):
-    votes_list = get_votes()
-
-    output = f'{VOTE_PLUS} {votes_list[0][0]} ({votes_list[0][1]}%), ' \
-             f'{VOTE_NEUTRAL} {votes_list[1][0]} ({votes_list[1][1]}%), ' \
-             f'{VOTE_MINUS} {votes_list[2][0]} ({votes_list[2][1]}%) | '
-    output += f'Endergebnis' if final_result else f'Zwischenergebnis'
-    output += f' mit insgesamt {len(votes)} abgegebenen Stimmen'
-
-    await bot.send_me(message, output, VOTE_COLOR)
-
 
 @bot.command(name="hauge-commands", aliases=["Hauge-commands", "haugebot-commands", "Haugebot-commands"])
 async def cmd_haugebot_commands(ctx):
@@ -125,143 +68,4 @@ async def cmd_haugebot_commands(ctx):
         "Eine Liste mit den Commands des HaugeBot findest du unter: https://github.com/dnns01/TwitchHausGeist/blob/master/README.md")
 
 
-@bot.event
-async def event_message(message):
-    global votes
-
-    if message.content.startswith(PREFIX):
-        await bot.handle_commands(message)
-    else:
-
-        # make sure the bot ignores itself and nightbot
-        if message.author.name.lower() in [NICK.lower(), 'nightbot']:
-            return
-
-        # check if message is a vote
-        msg = message.content
-        if msg[:2] == '+-' or msg[:2] == '-+' or msg[:3] == '-/+' or msg[:3] == '+/-' or msg[:len(
-                VOTE_NEUTRAL)] == VOTE_NEUTRAL:
-            add_vote(message, 'neutral')
-        elif msg[:1] == '+' or msg[:len(VOTE_PLUS)] == VOTE_PLUS:
-            add_vote(message, 'plus')
-        elif msg[:1] == '-' or msg[:len(VOTE_MINUS)] == VOTE_MINUS:
-            add_vote(message, 'minus')
-
-        if useRedis:
-            # update redis-database
-            update_redis()
-
-
-def add_vote(ctx, votetype):
-    """adds votes to the votes-dict and sets timestamps"""
-    global votes, vote_end_task, vote_interim_task
-
-    # Delay between two votes is not yet finished. So votes are not counted.
-    if vote_task_new and not vote_task_new.done():
-        return
-
-    if len(votes) == 0:
-        vote_end_task = asyncio.create_task(vote_end_voting(bot.get_channel(CHANNEL)))
-        vote_interim_task = asyncio.create_task(vote_interim_voting(bot.get_channel(CHANNEL)))
-
-    # should vote extend voting?
-    if ctx.author.name not in votes or votes[ctx.author.name] != votetype:
-        vote_end_task.set_name(int(time.time()))
-
-    # add vote to dict
-    votes[ctx.author.name] = votetype
-
-    if useRedis:
-        # update redis-database
-        update_redis()
-
-
-def update_redis():
-    """analyzes the votes-dict and counts the votes"""
-    plus = 0
-    minus = 0
-    neutral = 0
-
-    # count values in dict
-    for x in votes.values():
-        if x == 'neutral':
-            neutral += 1
-        elif x == 'plus':
-            plus += 1
-        elif x == 'minus':
-            minus += 1
-
-    if useRedis:
-        p = r.pipeline()  # start transaction
-        p.set('plus', plus)
-        p.set('neutral', neutral)
-        p.set('minus', minus)
-        p.execute()  # transaction end
-
-
-def get_votes():
-    """analyzes the votes-dict and counts the votes"""
-    plus = 0
-    minus = 0
-    neutral = 0
-
-    # count values in dict
-    for x in votes.values():
-        if x == 'neutral':
-            neutral += 1
-        elif x == 'plus':
-            plus += 1
-        elif x == 'minus':
-            minus += 1
-
-    return [[plus, bot.get_percentage(plus, len(votes))],
-            [neutral, bot.get_percentage(neutral, len(votes))],
-            [minus, bot.get_percentage(minus, len(votes))]]
-
-
-async def vote_end_voting(channel):
-    """ End a currently open voting """
-
-    global vote_task_new
-
-    # Wait for the initial VOTE_DELAY_END seconds
-    await asyncio.sleep(VOTE_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(vote_end_task.get_name()) + VOTE_DELAY_END >= time.time():
-        await asyncio.sleep(1)
-
-    if len(votes) >= VOTE_MIN_VOTES:
-        await notify_vote_result(channel, final_result=True)
-
-    votes.clear()
-    vote_task_new = asyncio.create_task(vote_block_votes())
-
-    if useRedis:
-        # update redis-database
-        update_redis()
-
-
-async def vote_interim_voting(channel):
-    """ End a currently open voting """
-
-    global vote_interim_task
-
-    await asyncio.sleep(VOTE_DELAY_INTERIM)
-    if not vote_end_task.done() and len(votes) >= VOTE_MIN_VOTES:
-        await notify_vote_result(channel)
-        vote_interim_task = asyncio.create_task(vote_interim_voting(bot.get_channel(CHANNEL)))
-
-    if useRedis:
-        # update redis-database
-        update_redis()
-
-
-async def vote_block_votes():
-    """ Just do nothing but sleep for VOTE_DELAY_INTERIM seconds """
-
-    await asyncio.sleep(VOTE_DELAY_INTERIM)
-
-
 bot.run()
diff --git a/vote_cog.py b/vote_cog.py
new file mode 100644
index 0000000000000000000000000000000000000000..399324d10560f803c946e345a9008a7068c08b13
--- /dev/null
+++ b/vote_cog.py
@@ -0,0 +1,134 @@
+import asyncio
+import os
+import time
+
+from twitchio.ext import commands
+
+import vote_redis
+
+
+@commands.core.cog(name="VoteCog")
+class VoteCog:
+    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.votes = {}
+        self.bot.add_listener(self.event_message)
+        self.redis = vote_redis.VoteRedis()
+
+    async def notify_vote_result(self, message, final_result=False):
+        votes_list = self.get_votes()
+
+        output = f'{self.PLUS} {votes_list[0][0]} ({votes_list[0][1]}%), ' \
+                 f'{self.NEUTRAL} {votes_list[1][0]} ({votes_list[1][1]}%), ' \
+                 f'{self.MINUS} {votes_list[2][0]} ({votes_list[2][1]}%) | '
+        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.get_channel(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)
+
+    def get_votes(self):
+        """analyzes the votes-dict and counts the votes"""
+        plus = 0
+        minus = 0
+        neutral = 0
+
+        # count values in dict
+        for x in self.votes.values():
+            if x == 'neutral':
+                neutral += 1
+            elif x == 'plus':
+                plus += 1
+            elif x == 'minus':
+                minus += 1
+
+        return [[plus, self.bot.get_percentage(plus, len(self.votes))],
+                [neutral, self.bot.get_percentage(neutral, len(self.votes))],
+                [minus, self.bot.get_percentage(minus, len(self.votes))]]
+
+    async def event_message(self, message):
+        # make sure the bot ignores itself and nightbot
+        if message.author.name.lower() in [self.NICK.lower(), 'nightbot']:
+            return
+
+        # check if message is a vote
+        msg = message.content
+        if msg[:2] == '+-' or msg[:2] == '-+' or msg[:3] == '-/+' or msg[:3] == '+/-' or msg[:len(
+                self.NEUTRAL)] == self.NEUTRAL:
+            self.add_vote(message, 'neutral')
+        elif msg[:1] == '+' or msg[:len(self.PLUS)] == self.PLUS:
+            self.add_vote(message, 'plus')
+        elif msg[:1] == '-' or msg[:len(self.MINUS)] == self.MINUS:
+            self.add_vote(message, 'minus')
+
+    def add_vote(self, ctx, votetype):
+        """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():
+            return
+
+        if len(self.votes) == 0:
+            self.vote_end_task = asyncio.create_task(self.vote_end_voting(self.bot.get_channel(self.bot.CHANNEL)))
+            self.vote_interim_task = asyncio.create_task(
+                self.vote_interim_voting(self.bot.get_channel(self.bot.CHANNEL)))
+
+        # 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()))
+
+        # add vote to dict
+        self.votes[ctx.author.name] = votetype
+        self.update_redis()
+
+    def update_redis(self):
+        """analyzes the votes-dict and counts the votes"""
+
+        if self.redis.is_connected:
+            votes = self.get_votes()
+            p = self.redis.pipeline()  # start transaction
+            p.set('plus', votes[0][0])
+            p.set('neutral', votes[1][0])
+            p.set('minus', votes[2][0])
+            p.execute()  # transaction end
diff --git a/vote_redis.py b/vote_redis.py
new file mode 100644
index 0000000000000000000000000000000000000000..13f4d7f770d02311bee5d2aea8f8aaef991232ab
--- /dev/null
+++ b/vote_redis.py
@@ -0,0 +1,34 @@
+import os
+
+import redis
+
+
+class VoteRedis(redis.Redis):
+    def __init__(self):
+        self.host = os.getenv("REDIS_HOST")
+        self.port = os.getenv("REDIS_PORT")
+        self.db = os.getenv("REDIS_DB")
+        self.password = os.getenv("REDIS_PW")
+        super().__init__(host=self.host, port=self.port, db=self.db, password=self.password)
+
+        try:
+            self.ping()
+            print('Redis: Connected!')
+            self.is_connected = True
+            self.init_db()
+        except Exception:
+            print('A connection to the Redis server could not be established. Redis querys are avoided.')
+            self.is_connected = False
+
+    def init_db(self):
+        # update constants in Redis-DB
+        self.set('voteMin', os.getenv("VOTE_MIN_VOTES"))
+        self.set('voteDelayEnd', os.getenv("VOTE_DELAY_END"))
+        self.set('voteDelayInter', os.getenv("VOTE_DELAY_INTERIM"))
+        #
+        # reset DB
+        p = self.pipeline()  # start transaction
+        p.set('plus', 0)
+        p.set('neutral', 0)
+        p.set('minus', 0)
+        p.execute()  # transaction end