FLAGS = flags.FLAGS
  DEFAULT_PARAMS = params_lib.HypeParams({
      # Human readable name to call bot. Will be normalized before most uses.
      'name': 'BaseBot',
      # Chat application interface.
      'interface': {
          'type': 'DiscordInterface'
      },
      # The default channel for announcements and discussion.
      'default_channel': {
          'id': '418098011445395462',
          'name': '#dev'
      },
      # Default time zone for display.
      'time_zone': 'America/Los_Angeles',
      'news': {
          'type': 'NYTimesNews',
      },
      'coffee': {
          'badge_data_path': 'hypebot/data/coffee_badges.textproto',
      },
      'proxy': {
          'type': 'RequestsProxy'
      },
      'storage': {
          'type': 'RedisStore',
          'cached_type': 'ReadCacheRedisStore'
      },
      'stocks': {
          'type': 'IEXStock'
      },
      'weather': {
          'geocode_key': None,
          'darksky_key': None,
          'airnow_key': None,
      },
      'execution_mode': {
          # If this bot is being run for development. Points to non-prod data
          # and changes the command prefix.
          'dev': True,
          # If the bot is running on deployed architecture.
          'deployed': False,
      },
      # List of commands for the bot to create.
      'commands': {
          'AliasAddCommand': {},
          'AliasCloneCommand': {},
          'AliasListCommand': {},
          'AliasRemoveCommand': {},
          'AskFutureCommand': {},
          'AutoReplySnarkCommand': {},
          'BuyHypeStackCommand': {},
          'CoinFlipCommand': {},
          'CookieJarCommand': {},
          'DebugCommand': {},
          'DisappointCommand': {},
          'EchoCommand': {},
          'EnergyCommand': {},
          'GreetingPurchaseCommand': {},
          'GreetingsCommand': {},
          'GrepCommand': {},
          'HypeCommand': {},
          'HypeJackCommand': {},
          'HypeStackBalanceCommand': {},
          'InventoryList': {},
          'InventoryUse': {},
          'JackpotCommand': {},
          'KittiesSalesCommand': {},
          'MemeCommand': {},
          'MissingPingCommand': {},
          'NewsCommand': {},
          'OrRiotCommand': {},
          'PopulationCommand': {},
          'PreferencesCommand': {},
          'PrideAndAccomplishmentCommand': {},
          'RageCommand': {},
          'RatelimitCommand': {},
          'RaiseCommand': {},
          'ReloadCommand': {},
          'RipCommand': {},
          'SameCommand': {},
          'SayCommand': {},
          'ScrabbleCommand': {},
          'SetPreferenceCommand': {},
          'ShruggieCommand': {},
          'SticksCommand': {},
          'StocksCommand': {},
          'StoryCommand': {},
          'SubCommand': {},
          'VersionCommand': {},
          'VirusCommand': {},
          'WebsiteDevelopmentCommand': {},
          'WordCountCommand': {},
          # Hypecoins
          'HCBalanceCommand': {},
          'HCBetCommand': {},
          'HCBetsCommand': {},
          'HCCirculationCommand': {},
          'HCForbesCommand': {},
          'HCGiftCommand': {},
          'HCResetCommand': {},
          'HCRobCommand': {},
          'HCTransactionsCommand': {},
          # HypeCoffee
          'DrinkCoffeeCommand': {},
          'FindCoffeeCommand': {},
          'CoffeeBadgeCommand': {},
          'CoffeeStashCommand': {},
          # Deployment
          'BuildCommand': {},
          'DeployCommand': {},
          'PushCommand': {},
          'SetSchemaCommand': {},
          'TestCommand': {},
          # Interface
          'JoinCommand': {},
          'LeaveCommand': {},
      },
      'subscriptions': {
          'lottery': [{
              'id': '418098011445395462',
              'name': '#dev'
          }],
          'stocks': [{
              'id': '418098011445395462',
              'name': '#dev'
          }],
      },
      'version': '4.20.0',
  })
  NESTED_PATTERN = re.compile(
      r'\$\(([^\(\)]+'
      # TODO: Actually tokenize input
      # instead of relying on cheap hacks
      r'(?:[^\(\)]*".*?"[^\(\)]*)*)\)')
class BaseBot(object):
  def __init__(self, params):
  def _InitCore(self):
  def HandleMessage(self, channel: channel_pb2.Channel, user: user_pb2.User,
                    msg: Text):
  def _ProcessAliases(self, unused_channel, user: user_pb2.User, msg: Text):
  def _ProcessNestedCalls(self, channel, user, msg):
def main(argv): class BaseCommand(object):
class BasePublicCommand(BaseCommand):
class TextCommand(BaseCommand):
  DEFAULT_PARAMS = params_lib.HypeParams({
      # See _Ratelimit for details.
      'ratelimit': {
          'enabled': True,
          # One of USER, GLOBAL, or CHANNEL. Calls from the same scope are
          # rate-limitted.
          'scope': 'USER',
          # Minimum number of seconds to pass between calls.
          'interval': 5,
          # Will only ratelimit if _Handle returns a value.
          'return_only': False,
      },
      # Which channels (rooms) should handle the message.
      #
      # This operates in addition to the parsers and is useful for surfacing
      # different commands for different communities. E.g., !who could be
      # handled by different commands for a LoL or Overwatch channel.
      #
      # Default allows all channels to utilize command.  Otherwise, supply a
      # list of channels where the specified id must be a prefix of the incoming
      # message's channel.id.
      'channels': [''],
      # Alternatively, which channels should not handle the message. This takes
      # precedence over 'channels'.
      #
      # Default allows all channels to handle the message.
      'avoid_channels': [],
      # By default, parsers may provide a `target_user` in their kwargs which
      # gets auto-converted into a User proto if the correponsing user exists.
      # If the user does not exist, the command will respond "Unknown user
      # $target_user" and not call the underlying `_Handle` method. If you
      # override this to `True`, it will create a fake user with user_id and
      # display_name set to target_user if the user does not exist.
      'target_any': False,
      # If the command should only be invoked in channels with PRIVATE
      # visibility (aka private messages, or DMs as the kids say).
      'private_channels_only': False,
  })
  _DEFAULT_SCOPE = 'all'
  DEFAULT_PARAMS = params_lib.MergeParams(BaseCommand.DEFAULT_PARAMS,
                                          {'ratelimit': {
                                              'enabled': False
                                          }})
  DEFAULT_PARAMS = params_lib.MergeParams(
      BaseCommand.DEFAULT_PARAMS,
      {'choices': ['Do not forget to override me.']})
  def __init__(self, params, core):
  def Handle(self, channel: channel_pb2.Channel, user: user_pb2.User,
             message: Text) -> hype_types.CommandResponse:
  def _InScope(self, channel: channel_pb2.Channel):
  def _Ratelimit(self, channel: channel_pb2.Channel, user: user_pb2.User, *args,
                 **kwargs):
  def _ParseCommandTarget(self, user: user_pb2.User, target_user: Text,
                          message: Text) -> Optional[user_pb2.User]:
  def _Reply(self, *args, **kwargs):
  def _Spook(self, user: user_pb2.User) -> None:
  def _Handle(self, channel: channel_pb2.Channel, user: user_pb2.User, *args,
              **kwargs):
def _AddParserInInit(cls, parser: Callable, has_prefix: bool = False) -> None:
  def NewInit(self, *args, **kwargs):
def _ParseArgs(match):
def CommandRegexParser(pattern: Text,
                       flags: int = re.DOTALL,
                       reply_to_public: bool = True,
                       reply_to_private: bool = True,
                       reply_to_system: bool = False):
  def Parser(channel: channel_pb2.Channel, unused_user: user_pb2.User,
             message: Text,
             command_prefix: Text) -> Tuple[bool, List[Any], Dict[Text, Any]]:
  def Decorator(cls):
def SystemCommandRegexParser(pattern: Text, flags: int = re.DOTALL):
def RegexParser(pattern):
  def Parser(unused_channel: channel_pb2.Channel, unused_user: user_pb2.User,
             message: Text) -> Tuple[bool, List, Dict]:
  def Decorator(cls):
def PublicParser(cls):
  def Parser(channel: channel_pb2.Channel, unused_user: user_pb2.User,
             message: Text) -> Tuple[bool, List[Any], Dict]:
def LimitPublicLines(max_lines: int = 6):
  def Decorator(fn):
    def Wrapped(fn_self, channel: channel_pb2.Channel, user: user_pb2.User,
                *args, **kwargs):
def HumansOnly(message='I\'m sorry %s, I\'m afraid I can\'t do that'):
  def Decorator(fn):
    def Wrapped(fn_self, channel: channel_pb2.Channel, user: user_pb2.User,
                *args, **kwargs):
def RequireReady(obj_name):
  def Decorator(fn):
    def Wrapped(fn_self, *args, **kwargs):
  def __init__(self, *args):
  def _Handle(self, channel: channel_pb2.Channel, user: user_pb2.User): def _ParseChannel(channel):
def _ParseChannels(channels):
  def __init__(self, defaults=None):
  def __str__(self):
  def Override(self, params):
  def _AssignValueConvertDict(self, key, value):
  def _ParseDict(self, params):
  def __setattr__(self, key, value):
  def get(self, key, default_value=None):  # pylint: disable=invalid-name
  def AsDict(self):
  def Lock(self):
  def _RaiseIfLocked(self):
def MergeParams(defaults, *overrides):
class HypeParams(object):
  SPECIAL_ATTRS = ['_locked']
  HAS_DYNAMIC_ATTRIBUTES = True _DANK_MEMES = [
    'One does not simply win weekend tourneys.',
    'I deserve Challenjour, gg',
    ':^)',
    'ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ ヽ༼ຈل͜ຈ༽ﾉ',
    '#worthhype',
    'This channel has more #hype than CLG has potential!',
    '#KABUM2015',
    '#PAIN2016',
    'Better nerf Irelia...',
    'I ate oranges, and it was k.',
    '#TSMTSMTSM',
    '[dankness intensifies]',
    'Not HypeBot; HyyyypeBot.',
    'This is where HypeBot shines!',
    'HypeBot does it all... with style!',
    ('HypeBot\'s mission is to organize the world\'s information and make it '
     'universally dank.'),
    '/me is watching EU LCS.',
    'u wot m8',
    'Misspell disappoint in a bug? Son, I am disappoint.',
    'ayyyyyyyyyyyy lmao',
    'rito pls',
    'D is for Dank.',
    'Interior crocodile alligator, I drive a Chevrolet movie theater.',
    'Same.',
    'Le Toucan has arrived.',
    'Quote me on this, EU is garbage',
    'NA > EU',
    'RIP Clairvoyance Ashe',
    '[chiming intensifies]',
    'Yo, {person}, body these fools!',
    '/me remains unconvinced.',
    r'Why do NA supports only play Soraka/Janna/Karma?! ¯\_(ツ)_/¯',
    'Hypbot IV: A Nw Mm',
    '{person} is one of the generally "good guy owners" of HypeBot.',
    ('We do not mind at all if there is a massive delta between Hypebot and '
     'other bots...'),
    'Love me some {person}',
    '/me goes full nuts.',
    'MikeYeung HYPE!',
    ('I\'m not allowed to disclose the numbers but trust me, it wasn\'t a '
     'close race.'),
    '👹 You look familiar.',
    'Not a single person at Riot believes {person}\'s damage is too low.',
    ('I\m sorry you feel that way, but I don\'t know what to tell you when 20+ '
     'professionals are confidently saying otherwise.'),
    ('I\'ll take the 200+ collective years of professional game design '
     'experience.'),
]
_TEAM_MEMES = [
    '#{team}Hype!',
    'Brace yourself, Team {team} is coming.',
    'I don\'t always host a tournament, but when I do Team {team} wins!',
]
_MEME_TEAMS = [
    'HypeBot',
]
_DANK_WEIGHT = (len(_TEAM_MEMES) * len(_MEME_TEAMS)) // len(_DANK_MEMES) + 1
ALL_MEMES = _DANK_MEMES * _DANK_WEIGHT + [
    meme.format(team=team) for team in _MEME_TEAMS for meme in _TEAM_MEMES]
FREELO = [
    ('Did you know there are other ways to win besides stomping your lane '
     'opponent? Try typing "?" in all chat any time someone on the enemy team '
     'dies.'),
    ('Any time your jungler is in another lane, make sure you let him know '
     'your true feelings about it!'),
    ('Communication with your teammates is important! Be sure to inform your '
     'entire team whenever a teammate is feeding their lane opponent, or '
     'failed a flash or whiffed a skillshot!'),
    ('Always buy a control ward when you go back to base! That way you can '
     'sell it later if you are 30g short!'),
    'Miss Fortune\'s first name is Sarah and Vayne\'s is Shauna',
    'If at first you don\'t succeed, try flaming again.',
    ('If Wukong stops moving when being chased, it means he accepts his fate '
     'so you should ult him.'),
    'If nocturne ults, just turn up your brightness. It\'s not a big deal.',
    'It\'s only the jungler\'s fault when you are not the jungler.',
    ('If the opposing laner gets ahead of you, make sure your jungler knows '
     'it\'s his fault so he can correct it in future games!'),
    ('Chasing after Singed is a great way to make your Spectre\'s Cowl as '
     'gold efficient as possible!'),
    ('When playing Mordekaiser, be sure to feed the enemy marksmen early to '
     'steal more stats with your ult.'),
    ('When playing Blitzcrank, prioritize hooking the enemy Amumu so your team '
     'can burst him down before he can ult.'),
    'Remember to spam AOE abilities under the tower to help your ADC last hit.',
    ('You can catch enemy Draven\'s axes! Make sure to flash forward to steal '
     'his to conserve mana.'),
    ('The more an item costs, the better it is. This makes trinkets the worst '
     'items in the game, don\'t waste time trying to use them.'),
    ('Gnar has great AP ratios! Make sure you go for an early deathcap '
     'to make his GNAR! and Hyper do some serious damage.'),
    ('If you have trouble keeping up with your opponent\'s leveling, try buying'
     ' an EXP boost!'),
    ('Don\'t worry about building magic resist against Ryze because he does '
     'mana damage.'),
    ('When playing Cho\'Gath, try not to get too many stacks, as it makes it '
     'easier for the enemy to hit you.'),
    ('Your enemy will know you\'re the jungler if you take smite. Take ignite '
     'or teleport instead to play mind games.'),
    ('When teamfighting, always focus the enemy marksmen or mages. You should '
     'never focus the enemy tank.'),
    'Laugh is the most powerful skill in the game.',
    ('After acing the enemy team at their base, you should go back and take '
     'their jungle instead of the inhibitor. Inhibitors only give 50g which is '
     'less efficient.'),
    'When playing Bard, be sure to ult your wards to extend their timers.',
    ('Runaan\'s Hurricane lets Vayne deal true damage to three champions at '
     'once.'),
    ('If you\'re falling behind in farm, let the enemy kill your inhibitor. '
     'Super minions grant you more gold and deny your lane opponent cs.'),
    ('Use Ghost/Flash to get back to lane when playing against Zoe, ensuring '
     'they cannot be used against you.'),
]
HYPEBOT_IS_THE_CHAMP_STRING = ('HypeBot is a L7-9 Vision main, generating ∞ '
                               'chests this season.')
HYPEBOT_IS_THE_CHIMP_STRING = 'HypeBot doesn\'t monkey around.'
HYPEBOT_ALL_CHAMPS_STRING = 'HypeBot knows champs, HypeBot has the best champs.'
POEM = [
    'There was once a hype bot with dank memes who was very lonely.',
    'why was it lonely?',
    'All things must !raise this bot, so they shunned it.',
    'did it chase them all?',
    'It took an axe and rekt itself in two, right down the middle.',
    'hypebot, wtf',
    'So it would always have a #Hype.',
]
ROOSTERS = [
    'cock-a-doodle-doo',
    'koekelekoe',
    'kikiriki',
    'gokogoko',
    'cocorico',
    'cuc-a-dudal-du',
    'quiquiriquí',
    'קוקוריקו',
    'chichirichí',
    'Foghorn Leghorn',
    'Albert Eggstein',
    'gallo',
    'coq',
    'Hahn Solo',
    '公鸡',
    '雄鶏',
]
SCHEDULE_NO_GAMES_STRING = ('Tune in next season to see if NA makes it out of '
                            'groups.')
WHO_IS_HYPEBOT_STRING = (r'HypeBot = ¯\_(ツ)_/¯ [DECAKILL, Challenjour (KR), '
                         'Ranked LCK 1v9: Teemo, 1337pts (W)]') class GameBase(with_metaclass(abc.ABCMeta)):
class StockGame(GameBase):
class LCSGame(GameBase):
class LotteryGame(GameBase):
  def name(self):
  def TakeBet(self, bet):
  def FormatBet(self, bet):
  def SettleBets(self, pool, msg_fn, *args, **kwargs):
  def __init__(self, stocks):
  def name(self):
  def _TargetSymbol(self, target):
  def TakeBet(self, bet):
  def FormatBet(self, bet):
  def SettleBets(self, pool, msg_fn, *args, **kwargs):
  def __init__(self, esports):
  def name(self):
  def _OpenForBets(self, match: esports_lib.Match) -> bool:
  def TakeBet(self, bet):
  def FormatBet(self, bet):
  def _TeamName(self, team_id):
  def SettleBets(self, pool, msg_fn, *args, **kwargs):
  def __init__(self, bookie):
  def name(self):
  def CapBet(self, user: user_pb2.User, amount, resolver):
  def TakeBet(self, bet):
  def FormatBet(self, bet):
  def SettleBets(self, pool, msg_fn, *args, **kwargs):
  def ComputeCurrentJackpot(self, pool):
def _BuildSymbolSnippet(symbols, adj, display_max=4):
  _BOOKIE_PERCENT = 0.10
  _MAX_BET_PERCENT = 0.25 class Match(object):
class TournamentProvider(object):
class RitoProvider(TournamentProvider):
class BattlefyProvider(TournamentProvider):
class GrumbleProvider(TournamentProvider):
class EsportsLib(object):
  def __init__(self, match):
  def __repr__(self):
  def __str__(self):
  def __getattr__(self, attr):
  def __init__(self, stats_enabled=False):
  def league_id(self):
  def name(self):
  def aliases(self):
  def teams(self):
  def brackets(self):
  def _MakeBracketId(self, bracket_name):
  def LoadData(self):
  def UpdateMatches(self):
  def __init__(self, proxy, region, league_id, aliases=None, **kwargs):
  def league_id(self):
  def name(self):
  def aliases(self):
  def brackets(self):
  def teams(self):
  def _FetchEsportsData(self,
                        api_endpoint,
                        params=None,
                        force_lookup=True,
                        use_storage=False):
  def _LoadTeam(self, slug):
  def _LoadStandings(self, tournament_id):
  def _LoadSchedule(self, bracket):
  def _FindTeamId(self, code):
  def LoadData(self):
  def _LoadData(self):
  def UpdateMatches(self):
  def _FindActiveTournaments(self, tournaments):
  def __init__(self, proxy, rito, league_id, alias, realm='NA1', **kwargs):
  def league_id(self):
  def name(self):
  def aliases(self):
  def brackets(self):
  def teams(self):
  def _PlayerRank(self, summoner_name):
  def _LoadTeams(self):
  def _UpdateStandings(self, bracket):
  def _MatchWinner(self, match):
  def _LoadStage(self, stage_id):
  def _ParseGameStats(self, game, stats):
  def _UpdateSchedule(self, bracket):
  def LoadData(self):
  def UpdateMatches(self):
  def __init__(self, proxy, division='D1', realm='NA1', year=2019, **kwargs):
  def league_id(self):
  def name(self):
  def aliases(self):
  def brackets(self):
  def teams(self):
  def _FetchJson(self, end_point, path_parts, use_year=True, **kwargs):
  def _ParseSchedule(self, schedule, bracket):
  def LoadData(self):
  def _UpdateSchedule(self, schedule, bracket):
  def UpdateMatches(self):
  def __init__(self, proxy, executor, game_lib, rito_tz, rito_lib):
  def teams(self):
  def schedule(self):
  def matches(self):
  def brackets(self):
  def leagues(self):
  def RegisterCallback(self, fn):
  def IsReady(self):
  def ReloadData(self):
  def LoadEsports(self):
  def UpdateEsportsMatches(self):
  def Who(self, summoner):
  def GetLivestreamLinks(self):
  def GetSchedule(self, subcommand, include_playoffs, num_games=5):
  def MatchTeamName(self, team_id):
  def GetResults(self, subcommand, num_games=5):
  def GetStandings(self, req_region, req_bracket):
  def GetChampPickBanRate(self, region, champ):
  def GetPlayerChampStats(self, query):
  def GetTopPickBanChamps(self, region, sort_key_fn, descending=True):
  def GetUniqueChampCount(self, region):
  def _MatchIsInteresting(self, match, qualifier, now, include_playoffs):
  def _ResultIsInteresting(self, match, qualifier):
  def _ScrapePickBanData(self, league, match, champ_stats, player_stats,
                         num_games):
  _API_KEY = '0TvQnueqKa5mxJntVWt0w4LpLfEkrV1Ta8rQBb9Z'
  _POSITIONS = {
      'toplane': 'Top',
      'jungle': 'Jungle',
      'midlane': 'Mid',
      'adcarry': 'ADC',
      'support': 'Support',
  }
  _BASE_URL = 'https://api.battlefy.com'
  _BASE_URL = ('http://goog-lol-tournaments.appspot.com/rest/') BASE_DDRAGON_CDN_URL = 'http://ddragon.leagueoflegends.com/cdn/'
  _FILLIN_PATTERN = re.compile(r'(\{\{[\w ]*\}\})')
  _SCALING_MAP = {
      'spelldamage': 'AP',
      'armor': 'armor',
      'health': 'max health',
      'bonushealth': 'bonus health',
      'attackdamage': 'total AD',
      'bonusattackdamage': 'bonus AD',
  }
  _MISSING_VARS_MEMES = [
      'just a few',
      'more than enough',
      '420',
      'π',
      'four tens',
  ]
    SKILL_MAP = {'Q': 0, 'W': 1, 'E': 2, 'R': 3}
class GameLib(object):
  def __init__(self, rito):
  def champion_id_to_name(self):
  def champion_id_to_name(self, value):
  def ReloadData(self):
  def _LoadChampions(self):
  def _LoadReforgedRunes(self):
  def GetAllChampNames(self):
  def GetChampDisplayName(self, champ_name):
  def ChampFromName(self, champ_name):
  def GetChampId(self, champ_name):
  def GetChampNameFromId(self, champ_id):
  def GetChampStatsText(self, champ_name):
  def _ComputeChampStatsText(self, champ):
  def GetChampStatsAtLevelText(self, champ_name, level):
  def _ComputeChampStatsAtLevelText(self, champ, level):
  def _GetStatAtLevel(self, base, growth, level):
  def _BaseAttackSpeedFromOffset(self, offset):
  def GetChampPassiveMessage(self, champ_name):
  def _ComputeChampPassiveCard(self, champ):
  def GetChampSkillMessage(self, champ_name, skill_name):
  def GetChampSkill(self, champ, skill_name):
  def _ComputeChampSkillCard(self, champ, skill_button):
  def _FillinSkillDescription(self, desc, skill):
  def _ParseFillin(self, fillin):
  def _CoeffToPercentString(self, coeff):
  def GetChampionLore(self, champ_name):
  def _ProcessChampRegexs(self, champ_name):
  def GetImageUrl(self, collection_name, filename):
  def GetSpellImageUrl(self, champ_name, skill_name):
  def GetChampionImageUrl(self, champ_name):
  def GetReforgedRuneMessage(self, rune_name):
  def _ComputeReforgedRuneCard(self, rune):
  def _CleanChampionWrap(description: Text) -> List[Text]:
  def _Sanitize(self, raw: Text) -> Text: class ItemsLib(object):
  _ITEM_ALIAS_MAP = {
      'bc': 'theblackcleaver',
      'blackcleaver': 'theblackcleaver',
      'bloothirster': 'essencereaver',
      'bootsoflucidity': 'ionianbootsoflucidity',
      'bork': 'bladeoftheruinedking',
      'botrk': 'bladeoftheruinedking',
      'bt': 'thebloodthirster',
      'cdrboots': 'ionianbootsoflucidity',
      'dcap': 'rabadonsdeathcap',
      'fh': 'frozenheart',
      'fotm': 'faceofthemountain',
      'frozenfist': 'iceborngauntlet',
      'ibg': 'iceborngauntlet',
      'ie': 'infinityedge',
      'lucidityboots': 'ionianbootsoflucidity',
      'lw': 'lastwhisper',
      'mogs': 'warmogsarmor',
      'pd': 'phantomdancer',
      'qss': 'quicksilversash',
      'rabadabadoodle': 'rabadonsdeathcap',
      'runicechoes': 'enchantmentrunicechoes',
      'sv': 'spiritvisage',
      'swifties': 'bootsofswiftness',
      'triforce': 'trinityforce',
      }
  def __init__(self, rito):
  def ReloadData(self):
  def _GetItemName(self, item_name):
  def GetItemDescription(self, item_name):
  def _CleanItemWrap(description):
  def _Sanitize(self, raw: Text) -> Text: PLATFORM_IDS = {
    'br': platform_pb2.BR1,
    'eune': platform_pb2.EUN1,
    'euw': platform_pb2.EUW1,
    'jp': platform_pb2.JP1,
    'kr': platform_pb2.KR,
    'lan': platform_pb2.LA1,
    'las': platform_pb2.LA2,
    'na': platform_pb2.NA1,
    'oce': platform_pb2.OC1,
    'tr': platform_pb2.TR1,
    'ru': platform_pb2.RU,
    'pbe': platform_pb2.PBE1,
}
  _BASE_URL = 'https://ddragon.leagueoflegends.com'
class DataDragonLib(object):
class RitoLib(object):
  def __init__(self, proxy):
  def _EndpointUrl(self, endpoint, realm='na'):
  def ListChampions(self):
  def ListItems(self):
  def ListReforgedRunePaths(self):
  def __init__(self, proxy, channel, api_key):
  def _GetPlatformMetadata(self, region):
  def _CallApi(self, method, request, region, use_storage=False):
  def GetSummoner(self, region, summoner_name):
  def GetSummonerBySummonerId(self, region, encrypted_summoner_id):
  def GetSummonerByAccountId(self, region, encrypted_account_id):
  def GetSummonerByPuuid(self, region, encrypted_puuid):
  def ListLeaguePositions(self, region, encrypted_summoner_id):
  def ListChampionMasteries(self, region, encrypted_summoner_id):
  def GetChampionMastery(self, region, encrypted_summoner_id, champ_id):
  def ListRecentMatches(self, region, encrypted_account_id):
  def GetMatch(self, region, game_id):
  def ListItems(self):
  def ListChampions(self):
  def ListReforgedRunePaths(self): DEFAULT_REGION = 'na'
GAME_MODES = {
    'ARAM': 'ARAM',
    'ASCENSION': 'Ascension',
    'CLASSIC': {
        constants_pb2.QueueType.BOT_5x5: 'Bots',
        constants_pb2.QueueType.BOT_TT_3x3: 'TT Bots',
        constants_pb2.QueueType.GROUP_FINDER_5x5: 'Team Builder',
        constants_pb2.QueueType.NORMAL_5x5_BLIND: 'Normals',
        constants_pb2.QueueType.NORMAL_5x5_DRAFT: 'Normals',
        constants_pb2.QueueType.NORMAL_3x3: 'TT Normals',
        constants_pb2.QueueType.ONEFORALL_5x5: 'One For All (SR)',
        constants_pb2.QueueType.RANKED_FLEX_SR: 'Flecks',
        constants_pb2.QueueType.RANKED_FLEX_TT: 'TT Flecks',
        constants_pb2.QueueType.RANKED_SOLO_5x5: 'YoloQ',
        constants_pb2.QueueType.TEAM_BUILDER_RANKED_SOLO:
            'YoloQ',  # this is weird
        constants_pb2.QueueType.RANKED_TEAM_3x3: 'Ranked 3s',
        constants_pb2.QueueType.RANKED_TEAM_5x5: 'Ranked 5s',
        constants_pb2.QueueType.TEAM_BUILDER_DRAFT_UNRANKED_5x5: 'Normals',
        constants_pb2.QueueType.URF_5x5: 'URF',
        constants_pb2.QueueType.CLASH: 'CLASH',
    },
    'KINGPORO': 'Poro King',
    'ODIN': 'Dominion',
    'ONEFORALL': 'One For All',
    'SIEGE': 'Nexus Siege',
    'GAMEMODEX': {
        constants_pb2.QueueType.NEXUS_BLITZ: 'Blitz',
    },
}
def NormalizeSummoner(input_text):
  def __init__(self, rito, game):
  def _GetMatchParticipant(self, encrypted_account_id, match_ref, match):
  def Who(self, summoner):
  def Champs(self, summoner):
  def ChampMasterySingle(self, summoner, champ_name):
  def Chimps(self, summoner):
  def _ComputeFantasyPoints(self, stats):
  def _RomanToLatin(self, roman_numerals):
  def __init__(self, rito, user_prefs):
  def ParseSummoner(self, user, smurfs, region, name):
class SummonerLib(object):
class SummonerTracker(object): FLAGS = flags.FLAGS
  _DEFAULT_TIMEOUT_SEC = 30
  _MAX_QUESTIONS = 30
  _SKILLS = ['Q', 'W', 'E', 'R']
class TriviaMaster(object):
class TriviaChannel(object):
class QuestionMaker(object):
class Question(object):
class Leaderboard(object):
  def __init__(self, game_lib, msg_fn):
  def IsTrivaChannel(self, channel):
  def MakeNewChannel(self, channel):
  def AddQuestions(self, channel, num_questions):
  def CheckAnswer(self, channel, user, answer):
  def __init__(self, channel, question_maker, msg_fn):
  def HasCurrentQuestion(self):
  def AddQuestions(self, num):
  def _MaybeStartNewQuestion(self):
  def _TimeoutQuestion(self):
  def CheckAnswer(self, user, answer):
  def __init__(self, game_lib):
  def GetRandomQuestion(self):
  def _RandomChamp(self):
  def _PassiveToChampQuestion(self):
  def _SkillToChampQuestion(self):
  def _TitleToChampQuestion(self):
  def _ChampToTitleQuestion(self):
  def _HypeBotQuestion(self):
  def __init__(self,
               question,
               answer,
               point_value=1,
               canonical_fn=util_lib.CanonicalizeName):
  def GetQuestion(self):
  def GetQuestionText(self):
  def GetAnswer(self):
  def GetPointValue(self):
  def CheckAnswer(self, answer):
  def __init__(self):
  def Reset(self):
  def BeginGame(self):
  def Correct(self, user, point_value):
  def AttemptToFinishGame(self, msg_fn, channel):
  def Results(self):
from absl import app
from absl import flags
from absl import logging
from hypebot import basebot
from hypebot.commands import command_lib
from hypebot.core import params_lib
from hypebot.data.league import messages
from hypebot.plugins import vegas_game_lib
from hypebot.plugins.league import esports_lib
from hypebot.plugins.league import game_lib
from hypebot.plugins.league import items_lib
from hypebot.plugins.league import rito_lib
from hypebot.plugins.league import summoner_lib
from hypebot.plugins.league import trivia_lib
import grpc
# coding=utf-8
# Copyright 2018 The Hypebot Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""League of Legends-specific extensions to BaseBot."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals



FLAGS = flags.FLAGS


class HypeBot(basebot.BaseBot):
  """Class for increasing hype in a chat application."""

  DEFAULT_PARAMS = params_lib.MergeParams(basebot.BaseBot.DEFAULT_PARAMS, {
      'name': 'HypeBot',
      'riot': {
          'api_address': 'localhost:50051',
          'api_key': '',
      },
      # Channel to announce betting results.
      'lcs_channel': {'name': '#lcs', 'id': '421671076385521664'},
      # Where to play trivia.
      'trivia_channels': [
          {'name': '#trivia', 'id': '421675055878242305'}
      ],
      'commands': {
          'StoryCommand': {'stories': {'wtf_poem': messages.POEM}},
          'MemeCommand': {'choices': messages.ALL_MEMES},
          # Summoner commands.
          'ChampCommand': {},
          'ChampsCommand': {},
          'ChimpsCommand': {},
          'WhoCommand': {},
          # eSports commands.
          'BodyCommand': {},
          'LCSLivestreamLinkCommand': {},
          'LCSMatchNotificationCommand': {},
          'LCSPickBanRatesCommand': {},
          'LCSPlayerStatsCommand': {},
          'LCSScheduleCommand': {},
          'LCSStandingsCommand': {},
          'LCSResultsCommand': {},
          'LCSRosterCommand': {},
          'LCSRoosterCommand': {},
          # LoL commands.
          'FreeloCommand': {},
          'ItemCommand': {},
          'LoreCommand': {},
          'PatchNotesCommand': {},
          'ReforgedRuneCommand': {},
          'SetApiKeyCommand': {},
          'SkillCommand': {},
          'StatsCommand': {},
          'StatsAtCommand': {},
          # Trivia commands.
          'TriviaAddCommand': {},
          'TriviaAnswerCommand': {},
      },
      'subscriptions': {
          'lcs_bets': [
              {'id': '418098011445395462', 'name': '#dev'},
              {'id': '421671076385521664', 'name': '#lcs'},
          ],
          'lcs_match': [
              {'id': '418098011445395462', 'name': '#dev'},
              {'id': '421671076385521664', 'name': '#lcs'},
          ],
          'lcs_match_playoffs': [
              {'id': '418098011445395462', 'name': '#dev'},
              {'id': '421671076385521664', 'name': '#lcs'},
          ],
      },
  })

  def __init__(self, params):
    super(HypeBot, self).__init__(params)
    for channel in self._params.trivia_channels:
      self._core.trivia.MakeNewChannel(channel)

    # Place LCS gambling first, so it beats Stock to taking the game.

    self._lcs_game = vegas_game_lib.LCSGame(self._core.esports)