Пример #1
0
 def _ExtractOverrides(self, raw_message):
     """Returns nothing, or the overrides parsed for a channel, user, and msg."""
     message_regex = re.compile(r'^\[(#?\w+)(?:\|(#?\w+))?\]\s*(.+)')
     match = message_regex.match(raw_message)
     if not match:
         return
     username = self._params.default_username
     channel_name = self._params.default_channel.name
     visibility = channel_pb2.Channel.PUBLIC
     for i in range(1, 3):
         user_or_channel = match.group(i)
         if not user_or_channel:
             break
         if user_or_channel.startswith('#'):
             channel_name = user_or_channel
             if channel_name.startswith('#sys'):
                 visibility = channel_pb2.Channel.SYSTEM
         else:
             username = user_or_channel
     if username.lower() == channel_name.strip('#').lower():
         visibility = channel_pb2.Channel.PRIVATE
     message = match.group(3)
     return (channel_pb2.Channel(id=channel_name,
                                 visibility=visibility,
                                 name=channel_name),
             user_pb2.User(user_id=username,
                           display_name=username,
                           bot=username.endswith('bot')), message)
Пример #2
0
    def _Handle(self, channel: channel_pb2.Channel, user: user_pb2.User,
                message: Text) -> hype_types.CommandResponse:
        with self._lock:
            if (self._cookie and
                    time.time() - self._last_time > self._params.timeout_sec):
                self._ResetSong()

            line = self._SONG[self._line_num]
            match = re.match(line.pattern, message)
            if match:
                if line.state == 'accusation':
                    if not self._accusor:
                        # No accusor means no current song.
                        if match.groups()[0].lower() != 'who':
                            return
                        self._cookie = match.groups()[1]
                        self._accusor = user
                        self._accused = user_pb2.User(
                            user_id=self._core.name,
                            display_name=self._core.name)
                    elif user == self._accusor and match.groups(
                    )[1] == self._cookie:
                        self._accused = self._core.interface.FindUser(
                            match.groups()[0])

                if ((self._AccusorsTurn() and user == self._accusor)
                        or (self._AccusedTurn() and user == self._accused)):
                    self._NextLine(channel)
Пример #3
0
 def _Handle(
         self, channel: channel_pb2.Channel, user: user_pb2.User,
         target_user: Optional[user_pb2.User]
 ) -> hype_types.CommandResponse:
     if not target_user:
         target_user = user_pb2.User(display_name='Jensen')
     return u'Yo, %s, body these fools!' % target_user.display_name
Пример #4
0
 def WhoAll(self):
     for guild in self._client.guilds:
         for member in guild.members:
             self._user_tracker.AddUser(
                 user_pb2.User(user_id=str(member.id),
                               display_name=member.display_name,
                               bot=member.bot))
Пример #5
0
 def setUp(self):
     super(BaseCoffeeCommandTestCase, self).setUp()
     self.test_user = user_pb2.User(user_id='test-user',
                                    display_name='Tester')
     self.test_badge = coffee_pb2.Badge(
         id=0,
         name='Test Badge',
         description='This is for being a good tester.')
     self.test_data = coffee_pb2.CoffeeData(
         energy=10,
         beans=[
             coffee_pb2.Bean(variety='Robusta',
                             region='Brazil',
                             rarity='rare'),
             coffee_pb2.Bean(variety='Arabica',
                             region='Honduras',
                             rarity='common'),
             coffee_pb2.Bean(variety='Liberica',
                             region='Nicaragua',
                             rarity='legendary')
         ],
         badges=[self.test_badge.id])
     self.core.coffee._SetCoffeeData(self.test_user, self.test_data)
     # TODO: Figure out how to load badge textproto in third_party.
     self.core.coffee.badges = {self.test_badge.id: self.test_badge}
Пример #6
0
 def Loop(self):
     while True:
         channel = self._params.default_channel
         user = user_pb2.User(user_id=self._params.default_username,
                              display_name=self._params.default_username)
         message = input('> ')
         overrides = self._ExtractOverrides(message)
         if overrides:
             channel, user, message = overrides
         self._on_message_fn(channel, user, message)
Пример #7
0
 def _DistributeToPastVictims(self, msg_fn):
     """Distribute funds in scholarship account to past victims."""
     victim_scores = self._GetPDF('victim')
     scholarship_balance = self._bank.GetBalance(SCHOLARSHIP_ACCOUNT)
     self._bank.ProcessPayment(
         SCHOLARSHIP_ACCOUNT,
         [user_pb2.User(user_id=v) for v in victim_scores.keys()],
         scholarship_balance,
         'Victim scholarship fund',
         msg_fn,
         merchant_weights=victim_scores.values())
Пример #8
0
 def _ParseCommandTarget(self, user: user_pb2.User, target_user: Text,
                         message: Text) -> Optional[user_pb2.User]:
   """Processes raw target_user into a User class, resolving 'me' to user."""
   # An empty target_user defaults to the calling user
   if target_user.strip() in ('', 'me'):
     self._core.last_command = partial(self.Handle, message=message)
     return user
   real_user = self._core.interface.FindUser(target_user)
   if self._params.target_any and not real_user:
     real_user = user_pb2.User(user_id=target_user, display_name=target_user)
   return real_user
Пример #9
0
 def _RestoreUserEnergy(
         self,
         username: Text,
         tx: Optional[storage_lib.HypeTransaction] = None) -> None:
     if not tx:
         return self._store.RunInTransaction(self._RestoreUserEnergy,
                                             username)
     user = user_pb2.User(user_id=username)
     user_data = self.GetCoffeeData(user, tx)
     # Min is set such that there is a ~1% chance that a user with no beans ends
     # up at 0 energy without finding at least one bean.
     min_energy = int(math.ceil(math.log(0.01, self._params.bean_chance)))
     max_energy = min_energy * 4
     # We allow users to go over the "max" energy, but they will stop
     # regenerating energy until they fall back below the max.
     if user_data.energy < max_energy:
         user_data.energy = max(min_energy, user_data.energy + 3)
         # Ensure we don't regen over the max.
         user_data.energy = min(max_energy, user_data.energy)
     self._SetCoffeeData(user, user_data, tx)
Пример #10
0
 async def on_message(message):
     # Discord doesn't protect us from responding to ourself.
     if message.author == self._client.user:
         return
     logging.info('Message from: %s - %s#%s - %s', message.author.name,
                  message.author.display_name,
                  message.author.discriminator, message.author.id)
     user = user_pb2.User(user_id=str(message.author.id),
                          display_name=message.author.display_name)
     # Discord has DMChannel for single user interaction and GroupChannel for
     # group DMs outside of traditional TextChannels within a guild. We only
     # consider the DMChannel (single user) as private to prevent spam in Group
     # conversations.
     if isinstance(message.channel, discord.DMChannel):
         channel = channel_pb2.Channel(
             id=str(message.channel.id),
             visibility=channel_pb2.Channel.PRIVATE,
             name=message.channel.recipient.name)
     else:
         channel = channel_pb2.Channel(
             id=str(message.channel.id),
             visibility=channel_pb2.Channel.PUBLIC,
             name=message.channel.name)
     self._on_message_fn(channel, user, self._CleanContent(message))
Пример #11
0
 def FindUser(self, query):
     """Override of parent FindUser since users are faked in the terminal."""
     return user_pb2.User(display_name=query, user_id=query)
Пример #12
0
    def Rob(self, thief, victim, amount, msg_fn):
        """Attempt a robbery."""
        if amount < 0:
            msg_fn(None, 'Did you mean !hc gift?')
            return

        if victim.user_id in self._protected_peeps:
            msg_fn(None, 'The Godfather protects his family.')
            self._bank.ProcessPayment(
                thief,
                user_pb2.User(user_id=self._bot_name,
                              display_name=self._bot_name), 500,
                'In Soviet Russia, %s steals from you.' % self._bot_name,
                msg_fn)
            return

        victim_balance = self._bank.GetBalance(victim)
        if victim_balance <= 0:
            msg_fn(None, 'You cannot milk a dead cow.')
            return

        thief_alert = self._GetPDF('thief')[thief.user_id]
        victim_alert = self._GetPDF('victim')[victim.user_id]
        offset = self._BASE_BALANCE_PERCENT * (1 - thief_alert - victim_alert)
        failure_chance = self._Sigmoid(amount / victim_balance, offset)

        rob_attempt_score = random.random()

        logging.info('(%s: %0.2f, %s: %0.2f) %s of %s attempt %0.2f >? %0.2f',
                     thief, thief_alert, victim, victim_alert, amount,
                     victim_balance, rob_attempt_score, failure_chance)

        if rob_attempt_score < failure_chance:
            self._bank.ProcessPayment(
                thief, SCHOLARSHIP_ACCOUNT,
                min(self._bank.GetBalance(thief), amount),
                'Victim scholarship fund', msg_fn)
            self._DistributeToPastVictims(msg_fn)
            if (rob_attempt_score < failure_chance * thief_alert /
                (thief_alert + victim_alert + 1e-6)):
                msg_fn(
                    None,
                    '%s is a known thief and was caught.' % thief.display_name)
            else:
                msg_fn(
                    None, '%s is on high alert and caught %s.' %
                    (victim.display_name, thief.display_name))
            return

        # TODO: Fold ProcessPayment into the UpdateScores tx.
        # We don't worry about the victim having insufficient funds since there is a
        # 0% chance of stealing 100% of someone's money.
        if self._bank.ProcessPayment(victim, thief, amount, 'Highway robbery',
                                     msg_fn):
            self._store.RunInTransaction(self._UpdateScores, thief, victim,
                                         amount)
            formatted_amount = util_lib.FormatHypecoins(amount)
            msg_fn(
                None, '%s stole %s from %s' %
                (thief.display_name, formatted_amount, victim.display_name))
            # We privmsg the victim to make sure they know who stole their hypecoins.
            msg_fn(
                victim, 'You\'ve been robbed! %s stole %s' %
                (thief.display_name, formatted_amount))
Пример #13
0
from absl import logging
from hypebot.core import schedule_lib
from hypebot.core import util_lib
from hypebot.data import messages
from hypebot.protos import bank_pb2
from hypebot.protos import bet_pb2
from hypebot.protos import user_pb2
import six

# pylint: disable=line-too-long
# pylint: enable=line-too-long
from google.protobuf import json_format

# "Accounts" where various transactions end up
BOOKIE_ACCOUNT = user_pb2.User(user_id='_hypebank', display_name='HypeBank')
FEE_ACCOUNT = BOOKIE_ACCOUNT
MINT_ACCOUNT = BOOKIE_ACCOUNT
SCHOLARSHIP_ACCOUNT = user_pb2.User(user_id='_hypescholarship',
                                    display_name='HypeScholarship')
SUBSCRIPTION_ACCOUNT = BOOKIE_ACCOUNT

# pyformat: disable
HYPECENTS = frozenset([
    BOOKIE_ACCOUNT.user_id,
    FEE_ACCOUNT.user_id,
    MINT_ACCOUNT.user_id,
    SCHOLARSHIP_ACCOUNT.user_id,
    SUBSCRIPTION_ACCOUNT.user_id,
])
# pyformat: enable
Пример #14
0
from __future__ import print_function
from __future__ import unicode_literals

import unittest

from hypebot import basebot
from hypebot import hypecore
from hypebot.core import params_lib
from hypebot.interfaces import interface_factory
from hypebot.protos import channel_pb2
from hypebot.protos import user_pb2

TEST_CHANNEL = channel_pb2.Channel(id='#test',
                                   name='Test',
                                   visibility=channel_pb2.Channel.PUBLIC)
TEST_USER = user_pb2.User(user_id='_test', display_name='user')


def ForCommand(command_cls):
    """Decorator to enable setting the command for each test class."""
    def _Internal(test_cls):
        test_cls._command_cls = command_cls
        return test_cls

    return _Internal


class BaseCommandTestCase(unittest.TestCase):

    # Set the default bot params (used by core) to something sane for testing.
    BOT_PARAMS = params_lib.MergeParams(