Ejemplo n.º 1
0
    def __init__(self, season_year=None):
        if season_year is None:
            self.season_year = self.DEFAULT_SEASON_YEAR
        else:
            self.season_year = season_year

        self.full_schedule = get_cache(
            path=f'{self.season_year}_full_schedule',
            fn=client.season_schedule,
            season_end_year=self.season_year)

        self.player_total = get_cache(path=f'{self.season_year}_player_total',
                                      fn=client.players_season_totals,
                                      season_end_year=self.season_year)

        self.SLUG_NAME_CONVERTER = dict(
            (player['slug'], player['name'].lower())
            for player in self.player_total)
        self.NAME_SLUG_CONVERTER = dict(
            (player['name'].lower(), player['slug'])
            for player in self.player_total)
        self.game_dates = sorted(
            list(
                set(game['start_time'].astimezone(EST).date()
                    for game in self.full_schedule)))
Ejemplo n.º 2
0
async def created_date(user: str, *,
                       data: 'cache.CacheStore'=None) -> Optional[datetime]:
    if data is None:
        async with cache.get_cache() as data:
            return await created_date(user, data=data)

    if not await data.twitch_load_id(user):
        return None
    id: Optional[str] = await data.twitch_get_id(user)
    if id is None:
        return None
    with suppress(aiohttp.ClientConnectionError, aiohttp.ClientResponseError,
                  asyncio.TimeoutError):
        response: aiohttp.ClientResponse
        userData: Dict[str, Any]
        uri: str = f'/kraken/users/{id}'
        response, userData = await get_call(None, uri)
        createdDate: datetime
        try:
            createdDate = datetime.strptime(userData['created_at'],
                                            '%Y-%m-%dT%H:%M:%S.%fZ')
        except ValueError:
            createdDate = datetime.strptime(userData['created_at'],
                                            '%Y-%m-%dT%H:%M:%SZ')
        return createdDate
    return None
Ejemplo n.º 3
0
async def handle_emote_set(emoteSet: Set[int]) -> None:
    if lock.locked():
        return
    async with lock:
        cacheStore: cache.CacheStore
        async with cache.get_cache() as cacheStore:
            await cacheStore.twitch_load_emotes(emoteSet, background=True)
Ejemplo n.º 4
0
async def update(channel: str, *,
                 status: Optional[str]=None,
                 game: Optional[str]=None,
                 data: 'cache.CacheStore'=None) -> Optional[bool]:
    if data is None:
        async with cache.get_cache() as data:
            return await update(channel, status=status, game=game, data=data)

    if not await data.twitch_load_id(channel):
        return None
    id: Optional[str] = await data.twitch_get_id(channel)
    if id is None:
        return None
    postData: Dict[str, str] = {}
    if isinstance(status, str):
        postData['channel[status]'] = status or ' '
    if isinstance(game, str):
        postData['channel[game]'] = game
    if not postData:
        return None
    with suppress(aiohttp.ClientConnectionError, aiohttp.ClientResponseError,
                  asyncio.TimeoutError):
        response: aiohttp.ClientResponse
        jsonData: Optional[Dict[str, Any]]
        response, jsonData = await put_call(
            channel, f'/kraken/channels/{id}',
            headers={'Content-Type': 'application/x-www-form-urlencoded'},
            data=postData)
        return response.status == 200
    return None
Ejemplo n.º 5
0
async def active_streams(channels: Iterable[str], *,
                         data: 'cache.CacheStore'=None
                         ) -> Optional[OnlineStreams]:
    if data is None:
        async with cache.get_cache() as data:
            return await active_streams(channels, data=data)

    with suppress(aiohttp.ClientConnectionError, aiohttp.ClientResponseError,
                  asyncio.TimeoutError):
        channels = set(channels)
        if not await data.twitch_load_ids(channels):
            return None
        ids: Dict[str, Optional[str]] = await data.twitch_get_ids(channels)
        allChannels: List[str] = [id for id in ids.values() if id is not None]
        if not allChannels:
            return {}
        uri: str = '/kraken/streams?limit=100&channel=' + ','.join(allChannels)
        response: aiohttp.ClientResponse
        streamsData: Dict[str, Any]
        response, streamsData = await get_call(None, uri)
        if response.status != 200:
            return None
        online: Dict[str, TwitchStatus] = {}
        _handle_streams(streamsData['streams'], online)
        for offset in range(100, streamsData['_total'], 100):
            await asyncio.sleep(0.05)
            offsetUri: str = uri + '&offset=' + str(offset)
            response, streamsData = await get_call(None, offsetUri)
            if response.status != 200:
                break
            _handle_streams(streamsData['streams'], online)
        return online
    return None
Ejemplo n.º 6
0
async def channel_community(channel: str, *,
                            data: 'cache.CacheStore'=None
                            ) -> Optional[List[TwitchCommunity]]:
    if data is None:
        async with cache.get_cache() as data:
            return await channel_community(channel, data=data)

    if not await data.twitch_load_id(channel):
        return None
    id: Optional[str] = await data.twitch_get_id(channel)
    if id is None:
        return None
    uri: str = f'/kraken/channels/{id}/communities'
    with suppress(ConnectionError, aiohttp.ClientResponseError):
        response: aiohttp.ClientResponse
        communities: Optional[Dict[str, List[Dict[str, str]]]]
        response, communities = await get_call(None, uri)
        if response.status not in [200, 204]:
            return None
        if communities is None:
            return []
        chanCommunities: List[TwitchCommunity] = []
        community: Dict[str, str]
        for community in communities['communities']:
            chanCommunities.append(
                TwitchCommunity(community['_id'], community['name']))
        return chanCommunities
    return None
Ejemplo n.º 7
0
async def checkStreamsAndChannel(timestamp: datetime) -> None:
    if not bot.globals.channels:
        return
    dataCache: cache.CacheStore
    async with cache.get_cache() as dataCache:
        channels: Dict[str, data.Channel] = copy.copy(bot.globals.channels)
        onlineStreams: Optional[twitch.OnlineStreams]
        onlineStreams = await twitch.active_streams(channels.keys(),
                                                    data=dataCache)
        if onlineStreams is None:
            return
        communityIds: Set[str] = set()
        channel: str
        for channel in onlineStreams:
            chat: data.Channel = channels[channel]
            chat.twitchCache = timestamp
            (chat.streamingSince, chat.twitchStatus,
             chat.twitchGame, chat.community) = onlineStreams[channel]
            communityId: str
            for communityId in chat.community:
                communityIds.add(communityId)

        for channel in channels:
            if channel in onlineStreams:
                continue
            channels[channel].streamingSince = None

        await dataCache.twitch_load_community_ids(communityIds)
Ejemplo n.º 8
0
async def checkTwitchIds(timestamp: datetime) -> None:
    if not bot.globals.channels:
        return
    dataCache: cache.CacheStore
    async with cache.get_cache() as dataCache:
        channels: List[str] = list(bot.globals.channels.keys())
        await dataCache.twitch_load_ids(channels)
Ejemplo n.º 9
0
async def refreshBttvRandomBroadcasterEmotes(timestamp: datetime) -> None:
    channels: Dict[str, data.Channel] = copy.copy(bot.globals.channels)
    channel: data.Channel
    for channel in channels.values():
        if 'bttvLock' not in channel.sessionData:
            channel.sessionData['bttvLock'] = asyncio.Lock()
    dataCache: cache.CacheStore
    async with cache.get_cache() as dataCache:
        ttlChannels: Dict[str, int]
        ttlChannels = await dataCache.bttv_get_cached_broadcasters()
        toUpdate: List[data.Channel]
        toUpdate = [
            chan for chan in channels.values() if
            (chan.channel not in ttlChannels or ttlChannels[chan.channel] < 30)
            and chan.isStreaming and not chan.sessionData['bttvLock'].locked()
        ]
        if not toUpdate:
            toUpdate = [
                chan for chan in channels.values()
                if (chan.channel not in ttlChannels
                    or ttlChannels[chan.channel] < 30) and not chan.isStreaming
                and not chan.sessionData['bttvLock'].locked()
            ]
        if toUpdate:
            channel = random.choice(toUpdate)
            async with channel.sessionData['bttvLock']:
                await dataCache.bttv_load_broadcaster_emotes(channel.channel,
                                                             background=True)
Ejemplo n.º 10
0
 def per_day_game_data(self):
     for date in self.game_dates:
         data = get_cache(path=f'{self.season_year}_{date}_game_data',
                          fn=client.player_box_scores,
                          day=date.day,
                          month=date.month,
                          year=date.year)
         yield (date, data)
Ejemplo n.º 11
0
async def refreshTwitchGlobalEmotes(timestamp: datetime) -> None:
    if twitchLock.locked():
        return
    dataCache: cache.CacheStore
    async with twitchLock, cache.get_cache() as dataCache:
        emoteSet: Set[int] = await dataCache.twitch_get_bot_emote_set()
        if emoteSet is None:
            return
        await dataCache.twitch_load_emotes(emoteSet, background=True)
Ejemplo n.º 12
0
async def set_channel_community(channel: str,
                                communities: List[str], *,
                                data: 'cache.CacheStore'=None
                                ) -> Optional[List[str]]:
    if data is None:
        async with cache.get_cache() as data:
            return await set_channel_community(channel, communities, data=data)

    if not await data.twitch_load_id(channel):
        return None
    id: Optional[str] = await data.twitch_get_id(channel)
    if id is None:
        return None
    uri: str
    response: aiohttp.ClientResponse
    jsonData: Optional[Dict[str, Any]]
    if communities:
        communityIds: Set[str] = set()
        for communityName in communities:
            if not await data.twitch_load_community_name(communityName):
                return None
            communityId: Optional[str]
            communityId = await data.twitch_get_community_id(communityName)
            if communityId is None:
                continue
            communityIds.add(communityId)
        if not communityIds:
            return []
        uri = f'/kraken/channels/{id}/communities'
        jsonData = {'community_ids': list(communityIds)}
        headers: Dict[str, str] = {'Content-Type': 'application/json'}
        with suppress(aiohttp.ClientConnectionError,
                      aiohttp.ClientResponseError,
                      asyncio.TimeoutError):
            response, jsonData = await put_call(channel, uri,
                                                headers=headers,
                                                data=json.dumps(jsonData))
            return list(communityIds) if response.status == 204 else None
    else:
        uri = f'/kraken/channels/{id}/community'
        with suppress(aiohttp.ClientConnectionError,
                      aiohttp.ClientResponseError,
                      asyncio.TimeoutError):
            response, jsonData = await delete_call(channel, uri)
            return [] if response.status == 204 else None
    return None
Ejemplo n.º 13
0
async def checkOfflineChannels(timestamp: datetime) -> None:
    channels: Dict[str, data.Channel] = copy.copy(bot.globals.channels)
    if not channels:
        return
    channel: data.Channel
    for channel in channels.values():
        if 'offlineLock' not in channel.sessionData:
            channel.sessionData['offlineLock'] = asyncio.Lock()
    cacheDuration: timedelta = timedelta(seconds=300)
    offlineChannels: List[data.Channel]
    offlineChannels = [ch for ch in channels.values()
                       if (not ch.isStreaming
                           and timestamp - ch.twitchCache >= cacheDuration
                           and not ch.sessionData['offlineLock'].locked())]
    if not offlineChannels:
        return
    if 'offlineCheck' not in bot.globals.globalSessionData:
        bot.globals.globalSessionData['offlineCheck'] = []
    bot.globals.globalSessionData['offlineCheck'] = [
        t for t in bot.globals.globalSessionData['offlineCheck']
        if t >= timestamp - timedelta(minutes=1)]
    if len(bot.globals.globalSessionData['offlineCheck']) >= 40:
        return
    chat: data.Channel = random.choice(offlineChannels)
    chat.twitchCache = timestamp
    dataCache: cache.CacheStore
    async with chat.sessionData['offlineLock'], cache.get_cache() as dataCache:
        current: Optional[twitch.TwitchStatus]
        current = await twitch.channel_properties(chat.channel)
        if current is None:
            chat.twitchCache = (timestamp - cacheDuration
                                + timedelta(seconds=60))
            return
        (chat.streamingSince, chat.twitchStatus,
         chat.twitchGame, shouldBeNone) = current
        communities: Optional[List[twitch.TwitchCommunity]]
        communities = await twitch.channel_community(chat.channel)
        if communities is not None:
            community: twitch.TwitchCommunity
            chat.community = [community.id for community in communities]
            await asyncio.gather(
                *[dataCache.twitch_save_community(comm.id, comm.name)
                  for comm in communities]
            )
        bot.globals.globalSessionData['offlineCheck'].append(timestamp)
Ejemplo n.º 14
0
async def num_followers(user: str, *,
                        data: 'cache.CacheStore'=None) -> Optional[int]:
    if data is None:
        async with cache.get_cache() as data:
            return await num_followers(user, data=data)

    if not await data.twitch_load_id(user):
        return None
    id: Optional[str] = await data.twitch_get_id(user)
    if id is None:
        return 0
    with suppress(aiohttp.ClientConnectionError, aiohttp.ClientResponseError,
                  asyncio.TimeoutError):
        response: aiohttp.ClientResponse
        followerData: Dict[str, Any]
        uri: str = f'/kraken/users/{id}/follows/channels?limit=1'
        response, followerData = await get_call(None, uri)
        return int(followerData['_total'])
    return None
Ejemplo n.º 15
0
async def autoRepeatMessage(timestamp: datetime) -> None:
    dataCache: cache.CacheStore
    async with lock, cache.get_cache() as dataCache:
        tasks: List[Awaitable[Any]] = []
        row: Tuple[str, str, str]
        async for row in dataCache.getAutoRepeatToSend():
            broadcaster: str
            name: str
            message: str
            broadcaster, name, message = row
            if broadcaster in bot.globals.channels:
                tasks.append(dataCache.sentAutoRepeat(broadcaster, name))
                channel: data.Channel = bot.globals.channels[broadcaster]
                channel.send(message)
                if channel.isMod:
                    tasks.append(
                        timeout.record_timeout(channel, None, message, None,
                                               'autorepeat'))
        if tasks:
            await asyncio.gather(*tasks)
Ejemplo n.º 16
0
async def channel_properties(channel: str, *,
                             data: 'cache.CacheStore'=None
                             ) -> Optional[TwitchStatus]:
    if data is None:
        async with cache.get_cache() as data:
            return await channel_properties(channel, data=data)

    if not await data.twitch_load_id(channel):
        return None
    id: Optional[str] = await data.twitch_get_id(channel)
    if id is None:
        return None
    uri: str = f'/kraken/channels/{id}'
    with suppress(aiohttp.ClientConnectionError, aiohttp.ClientResponseError,
                  asyncio.TimeoutError):
        response: aiohttp.ClientResponse
        channel_: Optional[Dict[str, str]]
        response, channel_ = await get_call(None, uri)
        if response.status != 200:
            return None
        return TwitchStatus(None, channel_['status'], channel_['game'], [])
    return None
Ejemplo n.º 17
0
async def check_domain_redirect(chat: 'data.Channel', nick: str,
                                message: Message, timestamp: datetime) -> None:
    dataCache: cache.CacheStore
    async with cache.get_cache() as dataCache:
        if await dataCache.twitch_num_followers(nick):
            return

    # Record all urls with users of no follows
    utils.logIrcMessage(f'{chat.ircChannel}#blockurl.log',
                        f'{nick}: {message}', timestamp)

    session: aiohttp.ClientSession
    async with aiohttp.ClientSession() as session:
        match: Match[str]
        for match in re.finditer(parser.twitchUrlRegex, str(message)):
            originalUrl: str = match.group(0)
            url: str = originalUrl
            if (not url.startswith('http://')
                    and not url.startswith('https://')):
                url = 'http://' + url
            headers = {'User-Agent': 'BotGotsThis/' + bot.config.botnick}
            try:
                response: aiohttp.ClientSession
                async with session.get(url, headers=headers) as response:
                    isBadRedirect: bool = compare_domains(url,
                                                          str(response.url),
                                                          chat=chat,
                                                          nick=nick,
                                                          timestamp=timestamp)
                    if isBadRedirect:
                        await handle_different_domains(chat, nick, message)
                        return
            except aiohttp.ClientConnectorError:
                pass
            except Exception:
                utils.logException(str(message), timestamp)
Ejemplo n.º 18
0
async def handle_different_domains(chat: 'data.Channel', nick: str,
                                   message: Message) -> None:
    dataCache: cache.CacheStore
    async with cache.get_cache() as dataCache:
        await timeout.timeout_user(dataCache, chat, nick, 'redirectUrl', 1,
                                   str(message), 'Blocked Redirected URL')
Ejemplo n.º 19
0
async def refreshBttvGlobalEmotes(timestamp: datetime) -> None:
    if bttvGlobalLock.locked():
        return
    dataCache: cache.CacheStore
    async with bttvGlobalLock, cache.get_cache() as dataCache:
        await dataCache.bttv_load_global_emotes(background=True)