Example #1
0
    def parse_all_emotes(self, message, twitch_emotes_tag=None):
        # Twitch Emotes
        twitch_emote_instances = self.parse_twitch_emotes_tag(
            twitch_emotes_tag, message)
        twitch_emote_start_indices = {
            instance.start
            for instance in twitch_emote_instances
        }

        # for the other providers, split the message by spaces
        # and then, if word is not a twitch emote, consider ffz channel -> bttv channel ->
        # ffz global -> bttv global in that order.
        third_party_emote_instances = []

        for current_word_index, word in iterate_split_with_index(
                message.split(" ")):
            # ignore twitch emotes
            is_twitch_emote = current_word_index in twitch_emote_start_indices
            if is_twitch_emote:
                continue

            emote = self.match_word_to_emote(word)
            if emote is None:
                # this word is not an emote
                continue

            third_party_emote_instances.append(
                EmoteInstance(start=current_word_index,
                              end=current_word_index + len(word),
                              emote=emote))

        all_instances = twitch_emote_instances + third_party_emote_instances
        all_instances.sort(key=lambda instance: instance.start)

        return all_instances, compute_emote_counts(all_instances)
def test_iterates_correctly() -> None:
    # a bcd ef
    generator = iterate_split_with_index(["a", "bcd", "ef"])
    assert next(generator) == (0, "a")
    assert next(generator) == (2, "bcd")
    assert next(generator) == (6, "ef")
    with pytest.raises(StopIteration):
        next(generator)
def test_empty_item() -> None:
    # a bcd ef
    generator = iterate_split_with_index(["a", "", "ef"])
    assert next(generator) == (0, "a")
    assert next(generator) == (2, "")
    assert next(generator) == (3, "ef")
    with pytest.raises(StopIteration):
        next(generator)
def test_zero_items() -> None:
    generator = iterate_split_with_index([])
    with pytest.raises(StopIteration):
        next(generator)
Example #5
0
    def bingo_start(self, bot, source, message, event, args):
        if self.bingo_running:
            bot.say(f"{source}, a bingo is already running FailFish")
            return False

        emote_instances = args["emote_instances"]
        known_sets = self.make_known_sets_dict()

        selected_sets = set()
        points_reward = None
        unparsed_options = []

        words_in_message = [s for s in message.split(" ") if len(s) > 0]
        if len(words_in_message) <= 0:
            bot.say(
                f"{source}, You must at least give me some emote sets or emotes to choose from! FailFish"
            )
            return False

        emote_index_offset = len("!bingo start ")

        # we can't iterate using words_in_message here because that would mess up the accompanying index
        for index, word in iterate_split_with_index(message.split(" ")):
            if len(word) <= 0:
                continue

            # Is the current word an emote?
            potential_emote_instance = next(
                (e for e in emote_instances
                 if e.start == index + emote_index_offset), None)
            if potential_emote_instance is not None:
                # single-emote set with the name of the emote
                new_set = (potential_emote_instance.emote.code,
                           (potential_emote_instance.emote, ), True)
                selected_sets.add(new_set)
                continue

            # Is the current word a number?
            try:
                parsed_int = int(word)
            except ValueError:
                parsed_int = None

            if parsed_int is not None:
                # if points_reward is already set this is the second number in the message
                if points_reward is not None:
                    unparsed_options.append(word)
                    continue
                points_reward = parsed_int
                continue

            # Is the current word a known set?
            cleaned_key = remove_emotes_suffix(word).lower()
            if cleaned_key in known_sets:
                selected_sets.add(known_sets[cleaned_key])
                continue

            unparsed_options.append(word)

        if len(unparsed_options) > 0:
            bot.say(
                "{}, I don't know what to do with the argument{} {} BabyRage".
                format(
                    source,
                    "" if len(unparsed_options) == 1 else "s",  # pluralization
                    join_to_sentence(['"' + s + '"'
                                      for s in unparsed_options]),
                ))
            return False

        default_points = self.settings["default_points"]
        if points_reward is None:
            points_reward = default_points

        max_points = self.settings["max_points"]
        if points_reward > max_points:
            bot.say(
                f"{source}, You can't start a bingo with that many points. FailFish {max_points} are allowed at most."
            )
            return False

        allow_negative_bingo = self.settings["allow_negative_bingo"]
        if points_reward < 0 and not allow_negative_bingo:
            bot.say(
                f"{source}, You can't start a bingo with negative points. FailFish"
            )
            return False

        min_points = -self.settings["max_negative_points"]
        if points_reward < min_points:
            bot.say(
                f"{source}, You can't start a bingo with that many negative points. FailFish {min_points} are allowed at most."
            )
            return False

        if len(selected_sets) <= 0:
            bot.say(
                f"{source}, You must at least give me some emotes or emote sets to choose from! FailFish"
            )
            return False

        selected_set_names = []
        selected_discrete_emote_codes = []
        selected_emotes = set()
        for set_name, set_emotes, is_discrete_emote in selected_sets:
            if is_discrete_emote:
                selected_discrete_emote_codes.append(set_name)
            else:
                selected_set_names.append(set_name)
            selected_emotes.update(set_emotes)

        correct_emote = random.choice(list(selected_emotes))

        user_messages = []
        if len(selected_set_names) > 0:
            user_messages.append(join_to_sentence(selected_set_names))

        if len(selected_discrete_emote_codes) > 0:
            # the space at the end is so the ! from the below message doesn't stop the last emote from showing up in chat
            user_messages.append(
                f"these emotes: {' '.join(selected_discrete_emote_codes)} ")

        bot.me(
            f"A bingo has started! ThunBeast Guess the right emote to win {points_reward} points! B) Only one emote per message! Select from {' and '.join(user_messages)}!"
        )

        log.info(
            f"A Bingo game has begun for {points_reward} points, correct emote is {correct_emote}"
        )
        self.active_game = BingoGame(correct_emote, points_reward)