Exemple #1
0
    def Reply(self,
              channel: types.Target,
              msg: MessageType,
              default_channel: Optional[Channel] = None,
              limit_lines: bool = False,
              max_public_lines: int = 6,
              user: Optional[types.User] = None,
              log: bool = False,
              log_level: int = logging.INFO) -> None:
        """Sends a message to the channel.

    Leaving Reply on the HypeCore allows replacing the interface to process
    nested commands. However, some change will be needed in order to actually
    create an OutputUtil for HBDS without a HypeCore.

    Args:
      channel: Who/where to send the message.
      msg: The message to send.
      default_channel: Who/where to send the message if no channel is specified.
      limit_lines: Whether to limit lines or not.
      max_public_lines: Maximum number of lines to send to a public channel.
      user: If specified, where to send the message if its too long.
      log: Whether to also log the message.
      log_level: How important the log is.
    """
        if not msg:
            return

        if log:
            text_msg = msg
            logging.log(log_level,
                        text_msg,
                        exc_info=log_level == logging.ERROR)

        channel = channel or default_channel
        if not channel:
            logging.info('Attempted to send message with no channel: %s', msg)
            return
        # Support legacy Reply to users as a string.
        if not isinstance(channel, Channel):
            # Send messages for sub-accounts to the real user.
            channel = Channel(id=channel.split(':')[0],
                              visibility=Channel.PRIVATE,
                              name=channel)

        if (limit_lines and channel.visibility == Channel.PUBLIC
                and isinstance(msg, list) and len(msg) > max_public_lines):
            if user:
                self.interface.SendMessage(
                    channel,
                    _MakeMessage('It\'s long so I sent it privately.'))
                self.interface.SendMessage(
                    Channel(id=user, visibility=Channel.PRIVATE, name=user),
                    _MakeMessage(msg))
            else:
                # If there is no user, just truncate and send to channel.
                self.interface.SendMessage(
                    channel, _MakeMessage(msg[:max_public_lines] + ['...']))
        else:
            self.interface.SendMessage(channel, _MakeMessage(msg))
Exemple #2
0
    def __init__(
            self,
            params: Any,  # HypeParams
            interface: interface_lib.BaseChatInterface) -> None:
        """Constructs core of hypebot.

    Args:
      params: Bot parameters.
      interface: This will always be the original interface that the bot was
        created with, and never the CaptureInterface during nested calls. For
        this reason, you should only call Join/Part and potentially Notice/Topic
        on this interface.  Don't call SendMessage or else it can send messages
        never intended for human consumption.
      hypeletter_callback: brcooley get rid of this when migrating hypeletter to
          its own command.
    """
        self.params = params
        self.nick = self.params.name.lower()
        self.interface = interface
        self.output_util = OutputUtil(self.Reply)

        self.store = storage_factory.CreateFromParams(self.params.storage)
        cached_type = self.params.storage.get(self.params.storage.type,
                                              {}).get('cached_type')
        if cached_type:
            self.cached_store = storage_factory.Create(
                cached_type, self.params.storage.get(self.params.storage.type))
        else:
            logging.info(
                'No cached_type found for storage, using default store.')
            self.cached_store = self.store

        self.user_tracker = util_lib.UserTracker()
        self.timezone = self.params.time_zone
        self.scheduler = schedule_lib.HypeScheduler(self.timezone)
        self.executor = futures.ThreadPoolExecutor(max_workers=8)
        self.runner = async_lib.AsyncRunner(self.executor)
        self.inventory = inventory_lib.InventoryManager(self.store)
        self.proxy = proxy_lib.Proxy(self.store)
        self.zombie_manager = zombie_lib.ZombieManager(self.Reply)
        self.request_tracker = RequestTracker(self.Reply)
        self.bank = coin_lib.Bank(self.store, self.nick)
        self.bets = coin_lib.Bookie(self.store, self.bank, self.inventory)
        self.stocks = stock_factory.CreateFromParams(self.params.stocks,
                                                     self.proxy)
        self.deployment_manager = deploy_lib.DeploymentManager(
            self.nick, self.bets, self.output_util, self.executor)
        self.hypestacks = hypestack_lib.HypeStacks(self.store, self.bank,
                                                   self.Reply)
        self.betting_games = []
        self.last_command = None
        self.default_channel = Channel(visibility=Channel.PUBLIC,
                                       **self.params.default_channel.AsDict())
Exemple #3
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)
     channel = Channel(
         id=message.channel.id,
         visibility=(Channel.PRIVATE
                     if message.channel.is_private else Channel.PUBLIC),
         name=message.channel.name)
     self._on_message_fn(channel, message.author.name,
                         self._CleanContent(message))
Exemple #4
0
    def __init__(self, params):
        super(HypeBot, self).__init__(params)
        api_key = (self._params.riot.api_key
                   or self._core.store.GetValue('api_key', 'key'))
        if not api_key:
            logging.fatal('api_key failed to load')

        self._core.rito = rito_lib.RitoLib(self._core.proxy,
                                           self._params.riot.api_address)
        self._core.rito.api_key = api_key
        self._core.game = game_lib.GameLib(self._core.rito)
        self._core.summoner = summoner_lib.SummonerLib(self._core.rito,
                                                       self._core.game)
        self._core.summoner_tracker = summoner_lib.SummonerTracker(
            self._core.rito)
        self._core.esports = esports_lib.EsportsLib(self._core.proxy,
                                                    self._core.executor,
                                                    self._core.game,
                                                    self._core.timezone)
        self._core.items = items_lib.ItemsLib(self._core.rito)

        # Trivia can probably be self contained once multiple parsers exist.
        self._core.trivia = trivia_lib.TriviaMaster(self._core.game,
                                                    self._OnNewTriviaQuestion,
                                                    self._OnTriviaQuestionDone,
                                                    self._OnTriviaLeaderboard)
        for chan in self._params.trivia_channels:
            channel = Channel(visibility=Channel.PUBLIC, **chan)
            self._core.trivia.MakeNewChannel(channel)

        self._core.lcs_channel = Channel(visibility=Channel.PUBLIC,
                                         **self._params.lcs_channel.AsDict())
        # Place LCS gambling first, so it beats Stock to taking the game.
        self._lcs_game = vegas_game_lib.LCSGame(self._core.esports)
        self._core.betting_games.insert(0, self._lcs_game)
        # Give _esports a chance at loading before trying to resolve LCS bets
        self._core.scheduler.FixedRate(5 * 60, 30 * 60, self._LCSGameCallback)
Exemple #5
0
    def _ProcessNestedCalls(self, channel, user, msg):
        """Evaluate nested commands within $(...)."""
        m = self.NESTED_PATTERN.search(msg)
        while m:
            backup_interface = self._core.interface
            self._core.interface = interface_factory.Create(
                'CaptureInterface', {})

            # Pretend it's Private to avoid ratelimit.
            nested_channel = Channel(id=channel.id,
                                     visibility=Channel.PRIVATE,
                                     name=channel.name)
            self.HandleMessage(nested_channel, user, m.group(1))
            response = self._core.interface.MessageLog()

            msg = msg[:m.start()] + response + msg[m.end():]
            self._core.interface = backup_interface
            m = self.NESTED_PATTERN.search(msg)
        return msg
 def _Handle(self, channel, user, channel_name):
     self._core.interface.Leave(
         Channel(id=channel_name,
                 visibility=Channel.PUBLIC,
                 name=channel_name))