def getStreamerInfo(self, streamername, serverChannelString=None):
        """
		Get info on the provided streamer, if they're live
		:param streamername: The name of the streamer to get info on
		:param serverChannelString: The server-channel pair where the request originated from. Needed to determine whether we need to use a nickname
		:return: A tuple, first entry is a success boolean, second one is the result string with either the error message or the currently live streamers
		"""
        # Check if we happen to have the streamer's ID on file, saves retrieving it
        if streamername in self.watchedStreamersData:
            streamerId = self.watchedStreamersData[streamername]['clientId']
            displayName = self.getStreamerNickname(streamername,
                                                   serverChannelString)
        else:
            isSuccess, result = self.retrieveChannelInfo(streamername)
            if not isSuccess:
                return (False, result)
            streamerId = result['id']
            displayName = result['display_name']

        # Get stream info
        isSuccess, result = self.retrieveStreamDataForIds([streamerId], True)
        if not isSuccess:
            return (False, result)
        if len(result) == 0:
            return (
                True,
                u"{0} doesn't appear to be streaming at the moment. Maybe they've got some old streams you can watch though, here: https://twitch.tv/{0}/videos/all"
                .format(streamername))
        #Streamer is live, return info on them
        url = "https://twitch.tv/" + streamername
        return (True,
                StringUtil.removeNewlines(u"{}: {} [{}] ({})".format(
                    displayName, result[streamerId]['title'],
                    result[streamerId]['game_name'], url)))
    def getCurrentlyLiveStreamers(self, serverChannelString):
        """
		Get a string with all the currently live streamers that the provided channel follows. If there's only a few streamers live, more expansive info is shown per streamer
		:param serverChannelString: The server name followed by the channel name, separated by a space
		:return: A tuple, first entry is a success boolean, second one is the result string with either the error message or the currently live streamers
		"""
        streamerIdsToCheck = {}
        for streamername, streamerdata in self.watchedStreamersData.iteritems(
        ):
            if serverChannelString in streamerdata[
                    'followChannels'] or serverChannelString in streamerdata[
                        'reportChannels']:
                streamerIdsToCheck[streamerdata['clientId']] = streamername
        isSuccess, result = self.retrieveStreamDataForIds(streamerIdsToCheck)
        if not isSuccess:
            self.logError(
                u"[TwitchWatch] An error occurred during a manual live check. "
                + result)
            return (
                False,
                "I'm sorry, I wasn't able to retrieve data from Twitch. It's probably entirely their fault, not mine though. Try again in a little while"
            )
        if len(result) == 0:
            return (
                True,
                "Nobody's live, it seems. Time for videogames and/or random streams, I guess!"
            )
        #One or more streamers are live, show info on each of them
        reportStrings = []
        shouldUseShortReportString = len(
            result
        ) >= 4  # Use shorter report strings if there's 4 or more people live
        for streamerId, streamerdata in result.iteritems():
            streamername = streamerIdsToCheck[streamerId]
            displayname = streamername
            if self.doesStreamerHaveNickname(streamername,
                                             serverChannelString):
                displayname = self.watchedStreamersData[streamername][
                    'nicknames'][serverChannelString]
            url = u"https://twitch.tv/{}".format(streamername)
            if shouldUseShortReportString:
                reportStrings.append(u"{} ({})".format(displayname, url))
            else:
                reportStrings.append(
                    StringUtil.removeNewlines(u"{}: {} [{}] ({})".format(
                        IrcFormattingUtil.makeTextBold(displayname),
                        streamerdata['title'], streamerdata['game_name'],
                        url)))
        return (True, StringUtil.joinWithSeparator(reportStrings))
    def executeScheduledFunction(self):
        #Go through all our stored streamers, and see if we need to report online status somewhere
        #  If we do, check if they're actually online
        streamerIdsToCheck = {
        }  #Store as a clientId-to-streamername dict to facilitate reverse lookup in self.streamerdata later
        for streamername, data in self.watchedStreamersData.iteritems():
            if len(data['reportChannels']) > 0:
                #Ok, store that we need to check whether this stream is online or not
                # Because doing the check one time for all streamers at once is far more efficient
                streamerIdsToCheck[data['clientId']] = streamername

        if len(streamerIdsToCheck) == 0:
            #Nothing to do! Let's stop now
            return

        isSuccess, liveStreamDataById = self.retrieveStreamDataForIds(
            streamerIdsToCheck.keys())
        if not isSuccess:
            self.logError(
                u"[TwitchWatch] An error occurred during the scheduled live check. "
                + liveStreamDataById)
            #Still update the last checked time, so we do get results when the connection works again
            self.lastLiveCheckTime = time.time()
            return

        #If the last time we checked for updates was (far) longer ago than the time between update checks, we've probably been offline for a while
        # Any data we retrieve could be old, so don't report it, but just log who's streaming and who isn't
        if self.lastLiveCheckTime:
            shouldReport = time.time(
            ) - self.lastLiveCheckTime <= self.scheduledFunctionTime * 6
        else:
            shouldReport = True

        if not shouldReport:
            self.logDebug(
                "[TwitchWatcher] Skipping reporting on live streams, since our last check was {} seconds ago, which is too long"
                .format(time.time() - self.lastLiveCheckTime))

        self.lastLiveCheckTime = time.time()

        channelMessages = {
        }  #key is string with server-channel, separated by a space. Value is a list of tuples with data on streams that are live

        #Go through all the required IDs and check if the API returned info info on that stream. If so, store that data for display later
        for streamerId, streamername in streamerIdsToCheck.iteritems():
            #Check if the requested ID exists in the API reply. If it didn't, the stream is offline
            if streamerId not in liveStreamDataById:
                self.watchedStreamersData[streamername][
                    'hasBeenReportedLive'] = False
            #If we have already reported the stream is live, skip over it now. Otherwise report that it has gone live
            elif not self.watchedStreamersData[streamername][
                    'hasBeenReportedLive']:
                self.watchedStreamersData[streamername][
                    'hasBeenReportedLive'] = True
                if shouldReport:
                    #Stream is live, store some info to display later
                    for serverChannelString in self.watchedStreamersData[
                            streamername]['reportChannels']:
                        #Add this stream's data to the channel's reporting output
                        if serverChannelString not in channelMessages:
                            channelMessages[serverChannelString] = []
                        channelMessages[serverChannelString].append({
                            'streamername':
                            streamername,
                            'gameName':
                            liveStreamDataById[streamerId]['game_name'],
                            'title':
                            liveStreamDataById[streamerId]['title']
                        })

        #Save live status of all the streams
        self.saveWatchedStreamerData()

        if shouldReport:
            #And now report each online stream to each channel that wants it
            for serverChannelString, streamdatalist in channelMessages.iteritems(
            ):
                server, channel = serverChannelString.rsplit(" ", 1)
                #First check if we're even in the server and channel we need to report to
                if server not in GlobalStore.bothandler.bots or channel not in GlobalStore.bothandler.bots[
                        server].channelsUserList:
                    continue

                reportStrings = []
                #If we have a lot of live streamers to report, keep it short. Otherwise, we can be a bit more verbose
                useShortReportString = len(streamdatalist) >= 4
                for streamdata in streamdatalist:
                    displayname = self.getStreamerNickname(
                        streamdata['streamername'], serverChannelString)
                    url = "https://twitch.tv/" + streamdata['streamername']
                    #A lot of live streamers to report, keep it short. Just the streamer name and the URL
                    if useShortReportString:
                        reportStrings.append(u"{} ({})".format(
                            displayname, url))
                    # Only a few streamers live, we can be a bit more verbose
                    else:
                        reportStrings.append(
                            StringUtil.removeNewlines(
                                u"{}: {} [{}] ({})".format(
                                    IrcFormattingUtil.makeTextBold(
                                        displayname), streamdata['title'],
                                    streamdata['gameName'], url)))
                #Now make the bot say it
                GlobalStore.bothandler.bots[server].sendMessage(
                    channel.encode("utf8"), u"Streamer{} went live: ".format(
                        u's' if len(reportStrings) > 1 else u'') +
                    StringUtil.joinWithSeparator(reportStrings), "say")