Exemplo n.º 1
0
def gambling_checks(bot, trigger):
    # Set keys to None for checks
    data = {"bet": None, "msg": None, "target": None}

    # Channel Checker – perhaps make this configurable in the future
    if trigger.sender == GCHAN:
        pass
    else:
        data["msg"] = "This command can only be used in {}".format(GCHAN)
        return data

    # Target Check
    # NOTE: This is not near as "universal" as originally thought out...
    #     Could definitely use some improvement in the future.
    # PROBLEM: This code is basically useless for all of the
    #     actual gambling commands. Unfortunately, just swapping
    #     trigger.group(4) and trigger.nick comes with another set of
    #     issues to deal with.
    target = plain(trigger.group(4) or trigger.nick)
    if not target:
        data["msg"] = "If you're seeing this message...everything is horribly broken."
        return data
    if target == bot.nick:
        data["msg"] = "I just run the place; I don't participate."
        return data
    data["target"] = tools.Identifier(target)

    # "Bet" Parsing and Checking
    # We're calling everything a "bet" for simplicity.
    # Many commands below don't involve betting.
    try:
        bet = plain(trigger.group(3).replace(",", "").replace("$", ""))
        if bet.isdigit():
            data["bet"] = int(bet)
    except AttributeError:
        bet = None
    if not bet:
        data["msg"] = "I need an amount of money."
        return data
    else:
        try:
            # Checks for bets made with letters
            # Large thanks to @Nachtalb
            match = re.match("([\\d.]+)([ckmbt])", bet, re.IGNORECASE)
            # TODO: should be some logic for "all" bet
            calc = {
                "C": 1e2, "c": 1e2,
                "K": 1e3, "k": 1e3,
                "M": 1e6, "m": 1e6,
                "B": 1e9, "b": 1e9,
                "T": 1e12, "t": 1e12
            }
            num, size = match.groups()
            data["bet"] = int(float(num) * calc[size])
        except (AttributeError, ValueError):
            data["msg"] = "I need an amount of money."
            return data

    # return keys: 'msg', 'target', and 'bet'
    return data
Exemplo n.º 2
0
def test_plain_color():
    text = 'some text'
    assert plain(color(text, colors.PINK)) == text
    assert plain(color(text, colors.PINK, colors.TEAL)) == text

    tpl = 'b %s a'
    expected = tpl % text
    assert plain(tpl % color(text, colors.PINK)) == expected
    assert plain(tpl % color(text, colors.PINK, colors.TEAL)) == expected
Exemplo n.º 3
0
def test_plain_hex_color():
    text = 'some text'
    assert plain(hex_color(text, 'ff0098')) == text
    assert plain(hex_color(text, 'ff0098', '00b571')) == text

    tpl = 'b %s a'
    expected = tpl % text
    assert plain(tpl % hex_color(text, 'ff0098')) == expected
    assert plain(tpl % hex_color(text, 'ff0098', '00b571')) == expected
Exemplo n.º 4
0
def rainbow_cmd(bot, trigger):
    """Make text colored. Options are "rainbow", "usa", "commie", and "spooky"."""
    text = formatting.plain(trigger.group(2) or '')
    scheme = trigger.group(1).lower()

    if not text:
        try:
            msg = SCHEME_ERRORS[scheme]
        except KeyError:
            msg = "How did you do that?!"
        bot.reply(msg)
        return

    try:
        colors = COLOR_SCHEMES[scheme]
    except KeyError:
        # not possible to reach this at time of writing, but who knows?
        # mistakes happen when updating stuff that needs to be changed in
        # parallel
        bot.reply(
            "I don't know what color sequence to use for '{}'!".format(scheme))
        return

    color_cycle = itertools.cycle(colors)

    bot.say(''.join(char if unicodedata.category(char) ==
                    'Zs' else formatting.color(char, next(color_cycle))
                    for char in text),
            max_messages=4)
Exemplo n.º 5
0
def plex_search(bot, trigger):
    """Search Plex for a movie or show."""
    search = formatting.plain(trigger.group(2) or '')

    if not search:
        try:
            msg = "I need something to search..."
        except KeyError:
            msg = "How did you do that?!"
        bot.reply(msg)
        return

    plex = plex_test(bot, trigger)

    if plex is None:
        return

    search_results = []

    # Search and add Movies to search_results
    for video in plex.search(search, mediatype="movie", limit=3):
        search_results.append("[{}] {} ({})".format(video.TYPE.title(),
                                                    video.title, video.year))

    # Search and add TV Shows to search_results
    for video in plex.search(search, mediatype="show", limit=3):
        search_results.append("[{}] {} ({})".format(video.TYPE.title(),
                                                    video.title, video.year))

    # verify there's results
    if not search_results:
        bot.reply("No results for your query.")
    else:
        bot.reply(", ".join(search_results))
Exemplo n.º 6
0
def check_money(bot, trigger):
    """Check how much money you or another user has."""
    # We're not using gambling_checks() because it's
    # tuned for most other commands in this plugin.
    # Channel Check
    if trigger.sender == GCHAN:
        pass
    else:
        return bot.reply("This command can only be used in {}".format(GCHAN))

    # Target Check
    target = plain(trigger.group(3) or trigger.nick)
    if not target:
        return bot.reply(
            "If you're seeing this message...everything is horribly broken.")

    target = tools.Identifier(target)

    if target == bot.nick:
        return bot.reply("I just run the place; I don't participate.")
    if target not in bot.channels[trigger.sender].users:
        return bot.reply("Please provide a valid user.")

    # Actual Currency Check
    currency_amount = bot.db.get_nick_value(target, "currency_amount")
    if currency_amount is not None:
        balance = "${:,}".format(currency_amount)
        bot.say("{} has {}".format(target, bold(balance)))
    else:
        bot.say("{} needs to run `.iwantmoney` first.".format(target))
Exemplo n.º 7
0
def antonyms(bot, trigger):
    word = formatting.plain(trigger.group(3))

    url = "https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{}".format(
        word)
    key = {"key": bot.config.thesaurus.api_key}

    try:
        antonyms = requests.get(url, params=key).json()[0]["meta"]["ants"][0]
        bot.say(", ".join(antonyms), max_messages=2)
    except IndexError:
        bot.reply("No results.")
Exemplo n.º 8
0
    def __init__(self, own_nick, line, url_schemes=None):
        line = line.strip('\r\n')
        self.line = line
        self.urls = tuple()
        self.plain = ''

        # Break off IRCv3 message tags, if present
        self.tags = {}
        if line.startswith('@'):
            tagstring, line = line.split(' ', 1)
            for tag in tagstring[1:].split(';'):
                tag = tag.split('=', 1)
                if len(tag) > 1:
                    self.tags[tag[0]] = tag[1]
                else:
                    self.tags[tag[0]] = None

        self.time = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc)
        if 'time' in self.tags:
            try:
                self.time = datetime.datetime.strptime(
                    self.tags['time'],
                    "%Y-%m-%dT%H:%M:%S.%fZ",
                ).replace(tzinfo=datetime.timezone.utc)
            except ValueError:
                pass  # Server isn't conforming to spec, ignore the server-time

        # Grabs hostmask from line.
        # Example: line = ':Sopel!foo@bar PRIVMSG #sopel :foobar!'
        #          print(hostmask)  # Sopel!foo@bar
        # All lines start with ":" except PING.
        if line.startswith(':'):
            self.hostmask, line = line[1:].split(' ', 1)
        else:
            self.hostmask = None

        # Parses the line into a list of arguments.
        # Some events like MODE don't have a secondary string argument, i.e. no ' :' inside the line.
        # Example 1:  line = ':nick!ident@domain PRIVMSG #sopel :foo bar!'
        #             print(text)    # 'foo bar!'
        #             print(argstr)  # ':nick!ident@domain PRIVMSG #sopel'
        #             print(args)    # [':nick!ident@domain', 'PRIVMSG', '#sopel', 'foo bar!']
        # Example 2:  line = 'irc.libera.chat MODE Sopel +i'
        #             print(text)    # '+i'
        #             print(args)    # ['irc.libera.chat', 'MODE', 'Sopel', '+i']
        if ' :' in line:
            argstr, self.text = line.split(' :', 1)
            self.args = argstr.split(' ')
            self.args.append(self.text)
        else:
            self.args = line.split(' ')
            self.text = self.args[-1]

        self.event = self.args[0]
        self.args = self.args[1:]
        components = PreTrigger.component_regex.match(self.hostmask
                                                      or '').groups()
        self.nick, self.user, self.host = components
        self.nick = tools.Identifier(self.nick)

        # If we have arguments, the first one is the sender
        # Unless it's a QUIT event
        if self.args and self.event != 'QUIT':
            target = tools.Identifier(self.args[0])
        else:
            target = None

        # Unless we're messaging the bot directly, in which case that second
        # arg will be our bot's name.
        if target and target.lower() == own_nick.lower():
            target = self.nick
        self.sender = target

        # Parse CTCP into a form consistent with IRCv3 intents
        if self.event == 'PRIVMSG' or self.event == 'NOTICE':
            intent_match = PreTrigger.intent_regex.match(self.args[-1])
            if intent_match:
                intent, message = intent_match.groups()
                self.tags['intent'] = intent
                self.args[-1] = message or ''

            # Search URLs after CTCP parsing
            self.urls = tuple(
                web.search_urls(self.args[-1], schemes=url_schemes))

        # Populate account from extended-join messages
        if self.event == 'JOIN' and len(self.args) == 3:
            # Account is the second arg `...JOIN #Sopel account :realname`
            self.tags['account'] = self.args[1]

        # get plain text message
        if self.args:
            self.plain = formatting.plain(self.args[-1])
Exemplo n.º 9
0
def gamble_oddsevens(bot, trigger):
    """Wager X amount of money on (o)dds or (e)vens. Winning will net you double your bet."""
    try:
        data = gambling_checks(bot, trigger)
    except Exception as msg:
        return bot.reply(msg)

    bet = data["bet"]
    msg = data["msg"]
    gambler = trigger.nick

    if not bet:
        return bot.reply(msg)

    # Check if user has enough money to make the gamble...
    bet_check = bot.db.get_nick_value(gambler, "currency_amount")
    if bet_check is None:
        return bot.reply(
            "You can't gamble yet! Please run the `.iwantmoney` command.")
    if bet > bet_check:
        return bot.reply(
            "You don't have enough money to make this bet. Try a smaller bet.")

    # Check if user has actually bet (o)dds or (e)vens.
    user_choice = plain(trigger.group(4) or '')
    if not user_choice:
        return bot.reply("You need to bet on (o)dds or (e)vens.")
    if user_choice in ["o", "e", "odd", "even", "odds", "evens"]:
        pass
    else:
        return bot.reply("You need to bet on (o)dds or (e)vens.")

    # Take the user's money before continuing
    spend_on_bet = bet_check - bet
    bot.db.set_nick_value(gambler, "currency_amount", spend_on_bet)

    # Set odds or evens
    if user_choice in ("odd", "even"):
        pass
    elif user_choice in ("o", "odds"):
        user_choice = "odd"
    elif user_choice in ("e", "evens"):
        user_choice = "even"

    # Roll and complete transaction
    roll_num = secrets.randbelow(101)
    if (roll_num % 2) == 0:
        roll = "even"
    else:
        roll = "odd"

    if roll == user_choice:
        winnings = bet * 2
        new_balance = spend_on_bet + winnings
        bot.db.set_nick_value(gambler, "currency_amount", new_balance)
        balance = "${:,}".format(new_balance)
        msg = "I rolled {}. That's {}. You bet on {}. You won ${:,}! Your new balance is {}.".format(
            roll_num, roll, user_choice, winnings, bold(balance))
    else:
        balance = "${:,}".format(spend_on_bet)
        msg = "I rolled {}. That's {}. You bet on {}. You lost ${:,}. Your new balance is {}.".format(
            roll_num, roll, user_choice, bet, bold(balance))

    # Stress user with delay
    bot.action("rolls a bunch of dice or something...")
    time.sleep(1.5)
    bot.reply(msg)
Exemplo n.º 10
0
def gamble_betflip(bot, trigger):
    """Wager X amount of money on (h)eads or (t)ails. Winning will net you double your bet."""
    try:
        data = gambling_checks(bot, trigger)
    except Exception as msg:
        return bot.reply(msg)

    bet = data["bet"]
    msg = data["msg"]
    gambler = trigger.nick

    if not bet:
        return bot.reply(msg)

    # Check if user has enough money to make the gamble...
    bet_check = bot.db.get_nick_value(gambler, "currency_amount")
    if bet_check is None:
        return bot.reply(
            "You can't gamble yet! Please run the `.iwantmoney` command.")
    if bet > bet_check:
        return bot.reply(
            "You don't have enough money to make this bet. Try a smaller bet.")

    # Check if user has actually bet (H)eads or (T)ails.
    user_choice = plain(trigger.group(4) or '')
    if not user_choice:
        return bot.reply("You need to bet on (h)eads or (t)ails.")
    if user_choice in ["h", "t", "heads", "tails"]:
        pass
    else:
        return bot.reply("You need to bet on (h)eads or (t)ails.")

    # Take the user's money before continuing
    spend_on_bet = bet_check - bet
    bot.db.set_nick_value(gambler, "currency_amount", spend_on_bet)

    # Set heads or tails
    if user_choice == "h":
        user_choice = "heads"
    if user_choice == "t":
        user_choice = "tails"

    # Flip coin and complete transaction
    heads_or_tails = ["heads", "tails"]
    flip_result = secrets.choice(heads_or_tails)

    if flip_result == user_choice:
        winnings = bet * 2
        new_balance = spend_on_bet + winnings
        bot.db.set_nick_value(gambler, "currency_amount", new_balance)
        balance = "${:,}".format(new_balance)
        msg = "Congrats; the coin landed on {}. You won ${:,}! Your new balance is {}.".format(
            flip_result, winnings, bold(balance))
    else:
        balance = "${:,}".format(spend_on_bet)
        msg = "Sorry, the coin landed on {}. You lost ${:,}. Your new balance is {}.".format(
            flip_result, bet, bold(balance))

    # Stress user with delay
    bot.action("flips a coin...")
    time.sleep(1.5)
    bot.reply(msg)
Exemplo n.º 11
0
def test_plain_italic():
    text = 'some text'
    assert plain(italic(text)) == text
Exemplo n.º 12
0
def test_plain_monospace():
    text = 'some text'
    assert plain(monospace(text)) == text
Exemplo n.º 13
0
    def __init__(
        self,
        own_nick: identifiers.Identifier,
        line: str,
        url_schemes: Optional[Sequence] = None,
        identifier_factory: IdentifierFactory = identifiers.Identifier,
    ):
        self.make_identifier = identifier_factory
        line = line.strip('\r\n')
        self.line: str = line
        self.urls: Tuple[str, ...] = tuple()
        self.plain: str = ''
        self.ctcp: Optional[str] = None

        # Break off IRCv3 message tags, if present
        self.tags: Dict[str, Optional[str]] = {}
        if line.startswith('@'):
            tagstring, line = line.split(' ', 1)
            for raw_tag in tagstring[1:].split(';'):
                tag = raw_tag.split('=', 1)
                if len(tag) > 1:
                    self.tags[tag[0]] = tag[1]
                else:
                    self.tags[tag[0]] = None

        # Client time or server time
        self.time = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc
        )
        if 'time' in self.tags:
            # ensure "time" is a string (typecheck)
            tag_time = self.tags['time'] or ''
            try:
                self.time = datetime.datetime.strptime(
                    tag_time,
                    "%Y-%m-%dT%H:%M:%S.%fZ",
                ).replace(tzinfo=datetime.timezone.utc)
            except ValueError:
                pass  # Server isn't conforming to spec, ignore the server-time

        # Grabs hostmask from line.
        # Example: line = ':Sopel!foo@bar PRIVMSG #sopel :foobar!'
        #          print(hostmask)  # Sopel!foo@bar
        # All lines start with ":" except PING.
        self.hostmask: Optional[str]
        if line.startswith(':'):
            self.hostmask, line = line[1:].split(' ', 1)
        else:
            self.hostmask = None

        # Parses the line into a list of arguments.
        # Some events like MODE don't have a secondary string argument, i.e. no ' :' inside the line.
        # Example 1:  line = ':nick!ident@domain PRIVMSG #sopel :foo bar!'
        #             print(text)    # 'foo bar!'
        #             print(argstr)  # ':nick!ident@domain PRIVMSG #sopel'
        #             print(args)    # [':nick!ident@domain', 'PRIVMSG', '#sopel', 'foo bar!']
        # Example 2:  line = 'irc.libera.chat MODE Sopel +i'
        #             print(text)    # '+i'
        #             print(args)    # ['irc.libera.chat', 'MODE', 'Sopel', '+i']
        if ' :' in line:
            argstr, self.text = line.split(' :', 1)
            self.args = argstr.split(' ')
            self.args.append(self.text)
        else:
            self.args = line.split(' ')
            self.text = self.args[-1]

        self.event = self.args[0]
        self.args = self.args[1:]

        # The regex will always match any string, even an empty one
        components_match = cast(
            Match, PreTrigger.component_regex.match(self.hostmask or ''))
        nick, self.user, self.host = components_match.groups()
        self.nick: identifiers.Identifier = self.make_identifier(nick)

        # If we have arguments, the first one is the sender
        # Unless it's a QUIT event
        target: Optional[identifiers.Identifier] = None

        if self.args and self.event != 'QUIT':
            target = self.make_identifier(self.args[0])

            # Unless we're messaging the bot directly, in which case that
            # second arg will be our bot's name.
            if target.lower() == own_nick.lower():
                target = self.nick

        self.sender = target

        # Parse CTCP
        if self.event == 'PRIVMSG' or self.event == 'NOTICE':
            ctcp_match = PreTrigger.ctcp_regex.match(self.args[-1])
            if ctcp_match is not None:
                ctcp, message = ctcp_match.groups()
                self.ctcp = ctcp
                self.args[-1] = message or ''

            # Search URLs after CTCP parsing
            self.urls = tuple(
                web.search_urls(self.args[-1], schemes=url_schemes))

        # Populate account from extended-join messages
        if self.event == 'JOIN' and len(self.args) == 3:
            # Account is the second arg `...JOIN #Sopel account :realname`
            self.tags['account'] = self.args[1]

        # get plain text message
        if self.args:
            self.plain = formatting.plain(self.args[-1])
Exemplo n.º 14
0
def test_plain_strikethrough():
    text = 'some text'
    assert plain(strikethrough(text)) == text
Exemplo n.º 15
0
def test_plain_reverse():
    text = 'some text'
    assert plain(reverse(text)) == text
Exemplo n.º 16
0
def test_plain_emoji():
    text = 'some emoji 💪 in here'
    assert plain(text) == text
Exemplo n.º 17
0
def test_plain_unknown():
    text = 'some \x99text'
    assert plain(text) == text, 'An unknown control code must not be stripped'
Exemplo n.º 18
0
def test_plain_non_printing(code):
    text = 'some%s text' % code
    assert plain(text) == 'some text'
Exemplo n.º 19
0
def test_plain_reset():
    text = 'some%s text' % CONTROL_NORMAL
    assert plain(text) == 'some text'
Exemplo n.º 20
0
def test_plain_bold():
    text = 'some text'
    assert plain(bold(text)) == text
Exemplo n.º 21
0
def test_plain_underline():
    text = 'some text'
    assert plain(underline(text)) == text