class Streamer(object): def __init__(self, username, settings=None): self.username = username.lower().strip() self.channel_id = 0 self.settings = settings self.is_online = False self.stream_up = 0 self.online_at = 0 self.offline_at = 0 self.channel_points = 0 self.minute_watched_requests = None self.viewer_is_mod = False self.stream = Stream() self.raid = None self.history = {} self.streamer_url = f"{URL}/{self.username}" self.chat_url = f"{URL}/popout/{self.username}/chat?popout=" def __repr__(self): return f"Streamer(username={self.username}, channel_id={self.channel_id}, channel_points={_millify(self.channel_points)})" def __str__(self): return (f"{self.username} ({_millify(self.channel_points)} points)" if Settings.logger.less else self.__repr__()) def set_offline(self): if self.is_online is True: self.offline_at = time.time() self.is_online = False logger.info(f"{self} is Offline!", extra={"emoji": ":sleeping:"}) def set_online(self): if self.is_online is False: self.online_at = time.time() self.is_online = True self.stream.init_watch_streak() logger.info(f"{self} is Online!", extra={"emoji": ":partying_face:"}) def print_history(self): return ", ".join([ f"{key}({self.history[key]['counter']} times, {_millify(self.history[key]['amount'])} gained)" for key in self.history if self.history[key]["counter"] != 0 ]) def update_history(self, reason_code, earned, counter=1): if reason_code not in self.history: self.history[reason_code] = {"counter": 0, "amount": 0} self.history[reason_code]["counter"] += counter self.history[reason_code]["amount"] += earned if reason_code == "WATCH_STREAK": self.stream.watch_streak_missing = False def stream_up_elapsed(self): return self.stream_up == 0 or ((time.time() - self.stream_up) > 120)
def __init__(self, username, settings=None): self.username: str = username.lower().strip() self.channel_id: str = "" self.settings = settings self.is_online = False self.stream_up = 0 self.online_at = 0 self.offline_at = 0 self.channel_points = 0 self.minute_watched_requests = None self.viewer_is_mod = False self.stream = Stream() self.raid = None self.history = {} self.streamer_url = f"{URL}/{self.username}"
class Streamer(object): __slots__ = [ "username", "channel_id", "settings", "is_online", "stream_up", "online_at", "offline_at", "channel_points", "minute_watched_requests", "viewer_is_mod", "activeMultipliers", "irc_chat", "stream", "raid", "history", "streamer_url", "mutex", ] def __init__(self, username, settings=None): self.username: str = username.lower().strip() self.channel_id: str = "" self.settings = settings self.is_online = False self.stream_up = 0 self.online_at = 0 self.offline_at = 0 self.channel_points = 0 self.minute_watched_requests = None self.viewer_is_mod = False self.activeMultipliers = None self.irc_chat = None self.stream = Stream() self.raid = None self.history = {} self.streamer_url = f"{URL}/{self.username}" self.mutex = Lock() def __repr__(self): return f"Streamer(username={self.username}, channel_id={self.channel_id}, channel_points={_millify(self.channel_points)})" def __str__(self): return (f"{self.username} ({_millify(self.channel_points)} points)" if Settings.logger.less else self.__repr__()) def set_offline(self): if self.is_online is True: self.offline_at = time.time() self.is_online = False self.leave_chat() logger.info( f"{self} is Offline!", extra={ "emoji": ":sleeping:", "color": Settings.logger.color_palette.STREAMER_OFFLINE, }, ) def set_online(self): if self.is_online is False: self.online_at = time.time() self.is_online = True self.stream.init_watch_streak() self.join_chat() logger.info( f"{self} is Online!", extra={ "emoji": ":partying_face:", "color": Settings.logger.color_palette.STREAMER_ONLINE, }, ) def print_history(self): return ", ".join([ f"{key}({self.history[key]['counter']} times, {_millify(self.history[key]['amount'])} gained)" for key in sorted(self.history) if self.history[key]["counter"] != 0 ]) def update_history(self, reason_code, earned, counter=1): if reason_code not in self.history: self.history[reason_code] = {"counter": 0, "amount": 0} self.history[reason_code]["counter"] += counter self.history[reason_code]["amount"] += earned if reason_code == "WATCH_STREAK": self.stream.watch_streak_missing = False def stream_up_elapsed(self): return self.stream_up == 0 or ((time.time() - self.stream_up) > 120) def drops_condition(self): return (self.settings.claim_drops is True and self.is_online is True and self.stream.drops_tags is True and self.stream.campaigns_ids != []) def viewer_has_points_multiplier(self): return self.activeMultipliers is not None and len( self.activeMultipliers) > 0 def total_points_multiplier(self): return (sum(map( lambda x: x["factor"], self.activeMultipliers, ), ) if self.activeMultipliers is not None else 0) def get_prediction_window(self, prediction_window_seconds): delay_mode = self.settings.bet.delay_mode delay = self.settings.bet.delay if delay_mode == DelayMode.FROM_START: return min(delay, prediction_window_seconds) elif delay_mode == DelayMode.FROM_END: return max(prediction_window_seconds - delay, 0) elif delay_mode == DelayMode.PERCENTAGE: return prediction_window_seconds * delay else: return prediction_window_seconds # === ANALYTICS === # def persistent_annotations(self, event_type, event_text): event_type = event_type.upper() if event_type in ["WATCH_STREAK", "WIN", "PREDICTION_MADE"]: primary_color = ("#45c1ff" if event_type == "WATCH_STREAK" else ( "#ffe045" if event_type == "PREDICTION_MADE" else "#54ff45")) data = { "borderColor": primary_color, "label": { "style": { "color": "#000", "background": primary_color }, "text": event_text, }, } self.__save_json("annotations", data) def persistent_series(self, event_type="Watch"): self.__save_json("series", event_type=event_type) def __save_json(self, key, data={}, event_type="Watch"): # https://stackoverflow.com/questions/4676195/why-do-i-need-to-multiply-unix-timestamps-by-1000-in-javascript # data.update({"x": round(time.time() * 1000)}) now = datetime.now().replace(microsecond=0) data.update({"x": round(datetime.timestamp(now) * 1000)}) if key == "series": data.update({"y": self.channel_points}) if event_type is not None: data.update({"z": event_type.replace("_", " ").title()}) fname = os.path.join(Settings.analytics_path, f"{self.username}.json") with self.mutex: json_data = json.load(open(fname, "r")) if os.path.isfile(fname) else {} if key not in json_data: json_data[key] = [] json_data[key].append(data) json.dump(json_data, open(fname, "w"), indent=4) def leave_chat(self): if self.irc_chat is not None: self.irc_chat.stop() # Recreate a new thread to start again # raise RuntimeError("threads can only be started once") self.irc_chat = ThreadChat( self.irc_chat.username, self.irc_chat.token, self.username, ) def join_chat(self): if self.irc_chat is not None: self.irc_chat.start()
class Streamer(object): __slots__ = [ "username", "channel_id", "settings", "is_online", "stream_up", "online_at", "offline_at", "channel_points", "minute_watched_requests", "viewer_is_mod", "stream", "raid", "history", "streamer_url", ] def __init__(self, username, settings=None): self.username: str = username.lower().strip() self.channel_id: str = "" self.settings = settings self.is_online = False self.stream_up = 0 self.online_at = 0 self.offline_at = 0 self.channel_points = 0 self.minute_watched_requests = None self.viewer_is_mod = False self.stream = Stream() self.raid = None self.history = {} self.streamer_url = f"{URL}/{self.username}" def __repr__(self): return f"Streamer(username={self.username}, channel_id={self.channel_id}, channel_points={_millify(self.channel_points)})" def __str__(self): return (f"{self.username} ({_millify(self.channel_points)} points)" if Settings.logger.less else self.__repr__()) def set_offline(self): if self.is_online is True: self.offline_at = time.time() self.is_online = False logger.info( f"{self} is Offline!", extra={ "emoji": ":sleeping:", "color": Settings.logger.color_palette.STREAMER_OFFLINE, }, ) def set_online(self): if self.is_online is False: self.online_at = time.time() self.is_online = True self.stream.init_watch_streak() logger.info( f"{self} is Online!", extra={ "emoji": ":partying_face:", "color": Settings.logger.color_palette.STREAMER_ONLINE, }, ) def print_history(self): return ", ".join([ f"{key}({self.history[key]['counter']} times, {_millify(self.history[key]['amount'])} gained)" for key in sorted(self.history) if self.history[key]["counter"] != 0 ]) def update_history(self, reason_code, earned, counter=1): if reason_code not in self.history: self.history[reason_code] = {"counter": 0, "amount": 0} self.history[reason_code]["counter"] += counter self.history[reason_code]["amount"] += earned if reason_code == "WATCH_STREAK": self.stream.watch_streak_missing = False def stream_up_elapsed(self): return self.stream_up == 0 or ((time.time() - self.stream_up) > 120) def drops_condition(self): return (self.settings.claim_drops is True and self.is_online is True and self.stream.drops_tags is True and self.stream.campaigns_ids != [])