Ejemplo n.º 1
0
    def status_duel(self, bot, source, **rest):
        """
        Whispers you the current status of your active duel requests/duel targets

        How to use: !duelstatus
        """

        with DBManager.create_session_scope() as db_session:
            msg = []
            if source.id in self.duel_requests:
                duelling = User.find_by_id(db_session,
                                           self.duel_requests[source.id])
                msg.append(
                    f"You have a duel request for {self.duel_request_price[source.id]} points by {duelling}"
                )

            if source.id in self.duel_targets:
                challenger = User.find_by_id(db_session,
                                             self.duel_targets[source.id])
                msg.append(
                    f"You have a pending duel request from {challenger} for {self.duel_request_price[self.duel_targets[source.id]]} points"
                )

            if len(msg) > 0:
                bot.whisper(source, ". ".join(msg))
            else:
                bot.whisper(
                    source,
                    "You have no duel request or duel target. Type !duel USERNAME POT to duel someone!"
                )
Ejemplo n.º 2
0
    def _cancel_expired_duels(self) -> None:
        if self.bot is None:
            log.warn(
                "_cancel_expired_duels of DuelModule failed because bot is None"
            )
            return

        now = utils.now()
        for source_id, started_at in self.duel_begin_time.items():
            duel_age = now - started_at
            if duel_age <= timedelta(minutes=self.settings["max_duel_age"]):
                # Duel is not too old
                continue

            with DBManager.create_session_scope() as db_session:
                source = User.find_by_id(db_session, source_id)
                if source is None:
                    continue

                target_id = self.duel_requests[source.id]

                del self.duel_targets[target_id]
                del self.duel_requests[source.id]
                del self.duel_request_price[source.id]
                del self.duel_begin_time[source.id]

                challenged = User.find_by_id(db_session, target_id)
                if challenged is None:
                    continue

                self.bot.whisper(
                    source,
                    f"{challenged} didn't accept your duel request in time, so the duel has been cancelled."
                )
Ejemplo n.º 3
0
    def end_raffle(self):
        if not self.raffle_running:
            return False

        self.raffle_running = False

        if len(self.raffle_users) == 0:
            self.bot.me("Wow, no one joined the raffle DansGame")
            return False

        with DBManager.create_session_scope() as db_session:
            winner_id = random.choice(list(self.raffle_users))
            winner = User.find_by_id(db_session, winner_id)
            if winner is None:
                return False

            self.raffle_users = set()

            if self.settings["show_on_clr"]:
                self.bot.websocket_manager.emit(
                    "notification", {
                        "message":
                        f"{winner} {format_win(self.raffle_points)} points in the raffle!"
                    })
                self.bot.me(
                    f"The raffle has finished! {winner} {format_win(self.raffle_points)} points! PogChamp"
                )

            winner.points += self.raffle_points

            HandlerManager.trigger("on_raffle_win",
                                   winner=winner,
                                   points=self.raffle_points)
Ejemplo n.º 4
0
    def decline_duel(self, bot: Bot, source: User, **options: Any) -> None:
        """
        Declines any active duel requests you've received.

        How to use: !decline
        """

        if source.id not in self.duel_targets:
            bot.whisper(source, "You are not being challenged to a duel")
            return

        with DBManager.create_session_scope() as db_session:
            requestor = User.find_by_id(db_session,
                                        self.duel_targets[source.id])

            if not requestor:
                bot.whisper(
                    source,
                    "Your challenge never existed, don't ask me what happened!"
                )
                return

            bot.whisper(source, f"You have declined the duel vs {requestor}")
            bot.whisper(requestor,
                        f"{source} declined the duel challenge with you.")

            del self.duel_targets[source.id]
            del self.duel_requests[requestor.id]
            del self.duel_request_price[requestor.id]
            del self.duel_begin_time[requestor.id]
Ejemplo n.º 5
0
    def on_clearchat(self, chatconn, event):
        tags = {tag["key"]: tag["value"] if tag["value"] is not None else "" for tag in event.tags}

        # Ignore "Chat has been cleared by a moderator" messages
        if "target-user-id" not in tags:
            return

        target_user_id = tags["target-user-id"]
        with DBManager.create_session_scope() as db_session:
            user = User.find_by_id(db_session, target_user_id)

            if user is None:
                # User is not otherwise known, we won't store their timeout (they need to type first)
                # We could theoretically also do an API call here to figure out everything about that user,
                # but that could easily overwhelm the bot when lots of unknown users are banned quickly (e.g. bots).
                return

            if "ban-duration" in tags:
                # timeout
                ban_duration = int(tags["ban-duration"])
                user.timeout_end = utils.now() + datetime.timedelta(seconds=ban_duration)
            else:
                # permaban
                # this sets timeout_end to None
                user.timed_out = False
Ejemplo n.º 6
0
    def get(id):
        with DBManager.create_session_scope() as db_session:
            user = User.find_by_id(db_session, id)
            if user is None:
                return {"error": "Not found"}, 404

            # the aliases like above are not needed here since this API endpoint is new since version 1.38
            return user.jsonify()
Ejemplo n.º 7
0
    def user_profile_connections_pair():
        with DBManager.create_session_scope() as db_session:
            if "user" not in session:
                return redirect(f"/login?n=/connections/")

            user = User.find_by_id(db_session, session["user"]["id"])
            if user is None:
                return render_template("no_user.html"), 404
            if user.offcd:
                discord = None
                steam = None
                if ("discord_id" in session and "discord_username" in session
                        and session["discord_id"] is not None
                        and session["discord_username"] is not None):
                    discord = {
                        "id": session["discord_id"],
                        "username": session["discord_username"]
                    }
                if "steam_id" in session and session["steam_id"] is not None:
                    steam = {"id": session["steam_id"]}

                data = {
                    "steam": steam,
                    "discord": discord,
                    "twitch": session["user"],
                    "offcd": user.offcd
                }
                try:
                    if discord is not None and steam is not None:
                        UserConnections._create(
                            db_session,
                            twitch_id=session["user"]["id"],
                            twitch_login=user.login,
                            discord_user_id=session["discord_id"],
                            discord_username=session["discord_username"],
                            steam_id=session["steam_id"],
                        )
                        user._setcd(db_session)
                        db_session.commit()
                        return redirect(f"/connections/")
                    else:
                        return render_template("connections.html",
                                               user=user,
                                               data=data,
                                               returnUrl=f"/connections",
                                               pair_failed=True)
                except Exception as e:
                    log.error(e)
                    return render_template("connections.html",
                                           user=user,
                                           data=data,
                                           returnUrl=f"/connections",
                                           pair_failed=True)
            else:
                return render_template("errors/403.html"), 403
Ejemplo n.º 8
0
    def _cancel_expired_duels(self):
        now = utils.now()
        for source_id, started_at in self.duel_begin_time.items():
            duel_age = now - started_at
            if duel_age <= timedelta(minutes=self.settings["max_duel_age"]):
                # Duel is not too old
                continue

            with DBManager.create_session_scope() as db_session:
                source = User.find_by_id(db_session, source_id)
                challenged = User.find_by_id(db_session, self.duel_requests[source.id])

                if source is not None and challenged is not None:
                    self.bot.whisper(
                        source,
                        f"{challenged} didn't accept your duel request in time, so the duel has been cancelled. Ditched pepeLaugh",
                    )

                del self.duel_targets[self.duel_requests[source.id]]
                del self.duel_requests[source.id]
                del self.duel_request_price[source.id]
                del self.duel_begin_time[source.id]
Ejemplo n.º 9
0
    def user_profile_connections():
        with DBManager.create_session_scope() as db_session:
            if "user" not in session:
                return redirect(f"/login?n=/connections/")

            user = User.find_by_id(db_session, session["user"]["id"])
            if user is None:
                return render_template("no_user.html"), 404
            user_connection = UserConnections._from_twitch_id(
                db_session, user.id)
            discord = None
            steam = None
            if ("discord_id" in session and "discord_username" in session
                    and session["discord_id"] is not None
                    and session["discord_username"] is not None):
                discord = {
                    "id": session["discord_id"],
                    "username": session["discord_username"]
                }
            if "steam_id" in session and session["steam_id"] is not None:
                steam = {"id": session["steam_id"]}

            data = {
                "steam": steam,
                "discord": discord,
                "twitch": session["user"],
                "offcd": user.offcd
            }
            user_connection = UserConnections._from_twitch_id(
                db_session, user.id)
            if user_connection:
                return render_template(
                    "connections_unlink.html",
                    user=user,
                    data=user_connection.jsonify(),
                    twitch_user=session["user"],
                    returnUrl=f"/connections",
                )
            return render_template("connections.html",
                                   user=user,
                                   data=data,
                                   returnUrl=f"/connections",
                                   pair_failed=False)
Ejemplo n.º 10
0
    def cancel_duel(self, bot, source, **rest):
        """
        Cancel any duel requests you've sent.

        How to use: !cancelduel
        """

        if source.id not in self.duel_requests:
            bot.whisper(source, "You have not sent any duel requests")
            return

        with DBManager.create_session_scope() as db_session:
            challenged = User.find_by_id(db_session,
                                         self.duel_requests[source.id])
            bot.whisper(source, f"You have cancelled the duel vs {challenged}")
            del self.duel_targets[challenged.id]
            del self.duel_request_price[source.id]
            del self.duel_begin_time[source.id]
            del self.duel_requests[source.id]
Ejemplo n.º 11
0
 def on_message(self, ws, message):
     msg = json.loads(message)
     if msg["type"].lower() == "pong":
         self.sent_ping = False
     elif msg["type"].lower() == "reconnect":
         ScheduleManager.execute_now(self.reset)
     elif msg["type"].lower() == "message":
         if msg["data"][
                 "topic"] == "channel-bits-events-v2." + self.bot.streamer_user_id:
             messageR = json.loads(msg["data"]["message"])
             user_id_of_cheer = str(messageR["data"]["user_id"])
             bits_cheered = str(messageR["data"]["bits_used"])
             with DBManager.create_session_scope() as db_session:
                 user = User.find_by_id(db_session, user_id_of_cheer)
                 if user is not None:
                     HandlerManager.trigger("on_cheer",
                                            True,
                                            user=user,
                                            bits_cheered=bits_cheered)
Ejemplo n.º 12
0
 def on_message(self, message):
     msg = json.loads(message)
     if msg["type"].lower() == "pong":
         self.sent_ping = False
         return
     elif msg["type"].lower() == "reconnect":
         self.reset()
         return
     elif msg["type"].lower() == "message":
         if msg["data"][
                 "topic"] == "channel-bits-events-v2." + self.bot.streamer_user_id:
             messageR = json.loads(msg["data"]["message"])
             user_id_of_cheer = str(messageR["data"]["user_id"])
             bits_cheered = str(messageR["data"]["bits_used"])
             with DBManager.create_session_scope() as db_session:
                 user = User.find_by_id(db_session, user_id_of_cheer)
                 if user is not None:
                     HandlerManager.trigger("on_cheer",
                                            True,
                                            user=user,
                                            bits_cheered=bits_cheered)
             return
         try:
             message_message = json.loads(msg["data"]["message"])
             if message_message["type"] == "reward-redeemed":
                 userDict = message_message["data"]["redemption"]["user"]
                 HandlerManager.trigger(
                     "on_redeem",
                     redeemer=UserBasics(userDict["id"], userDict["login"],
                                         userDict["display_name"]),
                     redeemed_id=message_message["data"]["redemption"]
                     ["reward"]["id"],
                     user_input=message_message["data"]["redemption"].get(
                         "user_input", ""),
                 )
         except Exception as e:
             log.error(e)
     elif msg["type"].lower() == "response":
         if not msg["error"]:
             return
     log.warning(msg)
Ejemplo n.º 13
0
    def decline_duel(self, bot, source, **options):
        """
        Declines any active duel requests you've received.

        How to use: !decline
        """

        if source.id not in self.duel_targets:
            bot.whisper(source, "You are not being challenged to a duel")
            return False

        with DBManager.create_session_scope() as db_session:
            requestor = User.find_by_id(db_session, self.duel_targets[source.id])

            bot.whisper(source, f"You have declined the duel vs {requestor}")
            bot.whisper(requestor, f"{source} declined the duel challenge with you.")

            del self.duel_targets[source.id]
            del self.duel_requests[requestor.id]
            del self.duel_request_price[requestor.id]
            del self.duel_begin_time[requestor.id]
Ejemplo n.º 14
0
 def user_profile_connections_unpair():
     with DBManager.create_session_scope() as db_session:
         if "user" not in session:
             return redirect(f"/login?n=/connections/")
         user = User.find_by_id(db_session, session["user"]["id"])
         if user is None:
             return render_template("no_user.html"), 404
         saved_data = db_session.query(UserConnections).filter_by(
             twitch_id=session["user"]["id"]).one_or_none()
         if not saved_data:
             return render_template("errors/403.html"), 403
         redis = RedisManager.get()
         unlinked_accounts = redis.get("unlinks-subs-discord")
         if unlinked_accounts is None:
             unlinked_accounts = {}
         else:
             unlinked_accounts = json.loads(unlinked_accounts)
         unlinked_accounts[saved_data.twitch_id] = saved_data.jsonify()
         unlinked_accounts = redis.set("unlinks-subs-discord",
                                       json.dumps(unlinked_accounts))
         saved_data._remove(db_session)
         db_session.commit()
         return redirect(f"/connections/")
Ejemplo n.º 15
0
    async def check_discord_roles(self):
        if not self.guild:
            return

        tier2_role = self.guild.get_role(int(self.settings["tier2_role"]))
        tier3_role = self.guild.get_role(int(self.settings["tier3_role"]))
        notify_role = self.guild.get_role(int(self.settings["notify_role"]))
        ignore_role = self.guild.get_role(int(self.settings["ignore_role"]))

        roles_allocated = {
            "tier2_role": tier2_role,
            "tier3_role": tier3_role,
            "notify_role": notify_role,
            "ignore_role": ignore_role,
        }

        quick_dict_twitch = {}
        quick_dict_discord = {}
        subs_to_return = {}

        queued_subs = json.loads(self.redis.get("queued-subs-discord"))
        unlinkinfo = json.loads(self.redis.get("unlinks-subs-discord"))

        messages_add = []
        messages_remove = []
        messages_other = []

        with DBManager.create_session_scope() as db_session:
            for twitch_id in unlinkinfo:
                unlinks = unlinkinfo[twitch_id]
                member = self.guild.get_member(int(unlinks["discord_user_id"]))
                if member:
                    if tier3_role is not None and tier3_role in member.roles:
                        await self.remove_role(member, tier3_role)
                    if tier2_role is not None and tier2_role in member.roles:
                        await self.remove_role(member, tier2_role)
                user = User.find_by_id(db_session, twitch_id)
                steam_id = unlinks["steam_id"]
                tier = unlinks["discord_tier"]
                if self.settings["notify_on_unsub"] and tier > 1 and self.settings[f"notify_on_tier{tier}"]:
                    discord = await self.get_discord_string(unlinks["discord_user_id"])
                    messages_other.append(
                        f"\n\nAccount Data Unlinked: Tier {tier} sub removal notification:\nTwitch: {user} (<https://twitch.tv/{user.login}>){discord}\nSteam: <https://steamcommunity.com/profiles/{steam_id}>"
                    )

            self.redis.set("unlinks-subs-discord", json.dumps({}))

            all_connections = db_session.query(UserConnections).all()

            for connection in all_connections:
                user = connection.twitch_user
                member = self.guild.get_member(int(connection.discord_user_id))
                discord = await self.get_discord_string(connection.discord_user_id)
                steam_id = connection.steam_id

                if (
                    not user or discord == ""
                ):  # Discord doesnt exist or Somehow the twitch doesnt exist in our database so we prune
                    connection._remove(db_session)
                    continue

                quick_dict_twitch[connection.twitch_id] = connection
                quick_dict_discord[connection.discord_user_id] = connection

                if not connection.twitch_login:
                    connection._update_twitch_login(db_session, user.login)
                if connection.twitch_login != user.login:
                    if connection.tier > 1:
                        if self.settings["notify_on_name_change"] and self.settings[f"notify_on_tier{connection.tier}"]:
                            messages_other.append(
                                f"\n\nTwitch login changed for a tier {connection.tier} sub\nSteam: <https://steamcommunity.com/profiles/{connection.steam_id}>\nOld Twitch: {connection.twitch_login}\nNew Twitch: {user.login}"
                            )
                    connection._update_twitch_login(db_session, user.login)

                if member and member.display_name + "#" + member.discriminator != connection.discord_username:
                    connection._update_discord_username(db_session, member.display_name + "#" + member.discriminator)

                db_session.commit()

                if not ignore_role or member and ignore_role not in member.roles:
                    role = roles_allocated[f"tier{user.tier}_role"] if user.tier and user.tier > 1 else None
                    if user.tier == connection.tier:
                        if role and role not in member.roles:
                            await self.add_role(member, role)
                    else:
                        if user.tier and user.tier > 1:
                            if (
                                self.settings["notify_on_unsub"]
                                and connection.tier > 1
                                and self.settings[f"notify_on_tier{connection.tier}"]
                            ):
                                messages_remove.append(
                                    f"\n\nTier {connection.tier} sub removal notification:\nTwitch: {user} (<https://twitch.tv/{user.login}>){discord}\nSteam: <https://steamcommunity.com/profiles/{steam_id}>"
                                )
                            connection._update_tier(db_session, user.tier)
                        if role:
                            if (
                                self.settings["notify_on_new_sub"]
                                and user.tier > 1
                                and self.settings[f"notify_on_tier{user.tier}"]
                            ):
                                messages_add.append(
                                    f"\n\nTier {user.tier} sub notification:\nTwitch: {user} (<https://twitch.tv/{user.login}>){discord}\nSteam: <https://steamcommunity.com/profiles/{steam_id}>"
                                )
                            await self.add_role(member, role)
                            connection._update_tier(db_session, user.tier)
                db_session.commit()

                if not self.settings["pause_bot"]:
                    if connection.twitch_id not in subs_to_return and not self.settings["pause_bot"]:
                        if connection.tier != user.tier:
                            if connection.tier != 0 and (not user.tier or user.tier == 0):
                                subs_to_return[connection.twitch_id] = str(
                                    utils.now() + timedelta(days=int(self.settings["grace_time"]))
                                )
                            else:
                                subs_to_return[connection.twitch_id] = str(utils.now())

            if not self.settings["pause_bot"]:
                for sub in queued_subs:  # sub "twitch_id" : date_to_be_removed
                    connection = quick_dict_twitch[sub]
                    time = queued_subs[sub]
                    user = connection.twitch_user
                    if user.tier == connection.tier or (
                        not user.tier and connection.tier == 0
                    ):  # they resubbed before grace ended
                        continue
                    if ":" in time[-5:]:
                        time = f"{time[:-5]}{time[-5:-3]}{time[-2:]}"
                    if datetime.strptime(time, "%Y-%m-%d %H:%M:%S.%f%z") < utils.now():  # must be run now
                        member = self.guild.get_member(int(connection.discord_user_id))
                        if connection.tier > 1:
                            role = roles_allocated[f"tier{connection.tier}_role"]
                            if member and role and role in member.roles:
                                await self.remove_role(member, role)
                            if self.settings["notify_on_unsub"] and self.settings[f"notify_on_tier{connection.tier}"]:
                                discord = await self.get_discord_string(connection.discord_user_id)
                                messages_remove.append(
                                    f"\n\nTier {connection.tier} sub removal notification:\nTwitch: {user} (<https://twitch.tv/{user.login}>){discord}\nSteam: <https://steamcommunity.com/profiles/{connection.steam_id}>"
                                )
                        connection._update_tier(db_session, user.tier)
                    else:
                        subs_to_return[sub] = queued_subs[sub]
                db_session.commit()

            for tier in [2, 3]:
                role = roles_allocated[f"tier{tier}_role"]
                if not role:
                    continue
                for member in role.members:
                    if ignore_role is None or ignore_role not in member.roles:
                        if str(member.id) not in quick_dict_discord:
                            if not self.settings["pause_bot"]:
                                await self.remove_role(member, role)
                        else:
                            connection = quick_dict_discord[str(member.id)]
                            if connection.tier != tier:
                                await self.remove_role(member, role)

        if notify_role:
            for member in notify_role.members:
                return_message = ""
                for message in messages_other:
                    if len(return_message) + len(message) > 1300:
                        await self.private_message(member, return_message)
                        return_message = ""
                    return_message += message
                if return_message != "":
                    await self.private_message(member, return_message)
                    return_message = ""
                for message in messages_remove:
                    if len(return_message) + len(message) > 1300:
                        await self.private_message(member, return_message)
                        return_message = ""
                    return_message += message
                if return_message != "":
                    await self.private_message(member, return_message)
                    return_message = ""
                for message in messages_add:
                    if len(return_message) + len(message) > 1300:
                        await self.private_message(member, return_message)
                        return_message = ""
                    return_message += message
                if return_message != "":
                    await self.private_message(member, return_message)
                    return_message = ""
        self.redis.set("queued-subs-discord", json.dumps(subs_to_return))
Ejemplo n.º 16
0
    def initiate_duel(self, bot, source, message, **rest):
        """
        Initiate a duel with a user.
        You can also bet points on the winner.
        By default, the maximum amount of points you can spend is 420.

        How to use: !duel USERNAME POINTS_TO_BET
        """

        if message is None:
            bot.whisper(source, f"Invalid Usage !duel USERNAME POINTS_TO_BET")
            return False

        msg_split = message.split()
        input = msg_split[0]

        with DBManager.create_session_scope() as db_session:
            user = User.find_by_user_input(db_session, input)
            if user is None:
                # No user was found with this username
                bot.whisper(
                    source,
                    f"The user, {input}, has never typed in chat before FailFish"
                )
                return False
            if user == source:
                bot.whisper(source, f"You cannot duel yourself")
                return False
            duel_price = 0
            if len(msg_split) > 1:
                try:
                    duel_price = int(msg_split[1])
                    if duel_price < 0:
                        return False
                except ValueError:
                    pass

            if source.id in self.duel_requests:
                currently_duelling = User.find_by_id(
                    db_session, self.duel_requests[source.id])
                if currently_duelling is None:
                    del self.duel_requests[source.id]
                    return False
                bot.whisper(
                    source,
                    f"You already have a duel request active with {currently_duelling}. Type !cancelduel to cancel your duel request.",
                )
                return False
            if user.last_active is None or (
                    utils.now() - user.last_active) > timedelta(minutes=5):
                bot.whisper(
                    source,
                    "This user has not been active in chat within the last 5 minutes. Get them to type in chat before sending another challenge",
                )
                return False

            if not user.can_afford(duel_price) or not source.can_afford(
                    duel_price):
                bot.whisper(
                    source,
                    f"You or your target do not have more than {duel_price} points, therefore you cannot duel for that amount.",
                )
                return False

            if user.id in self.duel_targets:
                challenged_by = User.find_by_id(db_session,
                                                self.duel_requests[user.id])
                bot.whisper(
                    source,
                    f"This person is already being challenged by {challenged_by}. Ask them to answer the offer by typing !deny or !accept",
                )
                return False

            self.duel_targets[user.id] = source.id
            self.duel_requests[source.id] = user.id
            self.duel_request_price[source.id] = duel_price
            self.duel_begin_time[source.id] = utils.now()
            bot.whisper(
                user,
                f"You have been challenged to a duel by {source} for {duel_price} points. You can either !accept or !deny this challenge.",
            )
            bot.whisper(source,
                        f"You have challenged {user} for {duel_price} points")
Ejemplo n.º 17
0
    def accept_duel(self, bot, source, **rest):
        """
        Accepts any active duel requests you've received.

        How to use: !accept
        """

        if source.id not in self.duel_targets:
            bot.whisper(source,
                        "You are not being challenged to a duel by anyone.")
            return

        with DBManager.create_session_scope() as db_session:
            requestor = User.find_by_id(db_session,
                                        self.duel_targets[source.id])
            duel_price = self.duel_request_price[self.duel_targets[source.id]]
            if not source.can_afford(duel_price) or not requestor.can_afford(
                    duel_price):
                bot.whisper(
                    source,
                    f"Your duel request with {requestor} was cancelled due to one of you not having enough points.",
                )
                bot.whisper(
                    requestor,
                    f"Your duel request with {source} was cancelled due to one of you not having enough points.",
                )

                del self.duel_requests[requestor.id]
                del self.duel_request_price[requestor.id]
                del self.duel_begin_time[requestor.id]
                del self.duel_targets[source.id]

                return False

            source.points -= duel_price
            requestor.points -= duel_price
            participants = [source, requestor]
            winner = random.choice(participants)
            participants.remove(winner)
            loser = participants.pop()

            winner.points += duel_price * 2

            # Persist duel statistics
            winner.duel_stats.won(duel_price)
            loser.duel_stats.lost(duel_price)
            arguments = {
                "winner": winner.name,
                "loser": loser.name,
                "total_pot": duel_price,
                "extra_points": duel_price,
            }

            if duel_price > 0:
                message = self.get_phrase("message_won_points", **arguments)
                if duel_price >= 500 and self.settings["show_on_clr"]:
                    bot.websocket_manager.emit(
                        "notification",
                        {"message": f"{winner} won the duel vs {loser}"})
            else:
                message = self.get_phrase("message_won", **arguments)
            bot.say(message)

            del self.duel_requests[requestor.id]
            del self.duel_request_price[requestor.id]
            del self.duel_begin_time[requestor.id]
            del self.duel_targets[source.id]

            HandlerManager.trigger("on_duel_complete",
                                   winner=winner,
                                   loser=loser,
                                   points_won=duel_price,
                                   points_bet=duel_price)