def uptime(self): """ Returns a TimeDelta for how long the stream was online, or is online. """ if self.ended is False: return utils.now() - self.stream_start return self.stream_end - self.stream_start
def refresh_stream_status_stage2(self, status: Optional[UserStream]): redis = RedisManager.get() key_prefix = self.bot.streamer + ":" # Default data we want to update in case the stream is offline stream_data = { f"{key_prefix}online": "False", f"{key_prefix}viewers": 0, } self.num_viewers = 0 if status: # Update stream_data with fresh online data stream_data[f"{key_prefix}online"] = "True" stream_data[f"{key_prefix}viewers"] = status.viewer_count game_info: Optional[ TwitchGame] = self.bot.twitch_helix_api.get_game_by_game_id( status.game_id) game_name: str = "" if game_info is not None: game_name = game_info.name stream_data[f"{key_prefix}game"] = game_name self.num_viewers = status.viewer_count self.game = game_name self.title = status.title self.num_offlines = 0 self.first_offline = None # Update stream chunk data if self.current_stream is None: self.create_stream(status) if self.current_stream_chunk is None: self.create_stream_chunk(status) if self.current_stream_chunk is not None: if self.current_stream_chunk.broadcast_id != status.id: log.debug( f"Detected a new chunk! {self.current_stream_chunk.broadcast_id} != {status.id}" ) self.create_stream_chunk(status) else: # stream reported as offline if self.online is True: # but we have stream marked as online.. begin the countdown self.num_offlines += 1 log.info(f"Offline. {self.num_offlines}") if self.first_offline is None: self.first_offline = utils.now() if self.num_offlines >= self.NUM_OFFLINES_REQUIRED: log.info("Switching to offline state!") self.go_offline() redis.hmset("stream_data", stream_data)
def roulette(self, **options): if self.settings["only_roulette_after_sub"]: if self.last_sub is None: return False if utils.now() - self.last_sub > datetime.timedelta( seconds=self.settings["after_sub_roulette_time"]): return False message = options["message"] user = options["source"] bot = options["bot"] if message: bot.whisper( user.username, "The command is only !roulette and it wagers all your points SmileyFace" ) return False try: bet = pajbot.utils.parse_points_amount(user, "all") except pajbot.exc.InvalidPointAmount as e: bot.whisper(user.username, str(e)) return False if bet < 500: bot.whisper(user.username, "You can only roulette for 500+ points FeelsWeirdMan") return False # Calculating the result result = self.rigged_random_result() points = bet if result else -bet user.points += points with DBManager.create_session_scope() as db_session: r = Roulette(user.id, points) db_session.add(r) arguments = { "bet": bet, "user": user.username_raw, "points": user.points_available() } if points > 0: out_message = self.get_phrase("message_won", **arguments) else: out_message = self.get_phrase("message_lost", **arguments) if user.subscriber: bot.me(out_message) else: bot.whisper(user.username, out_message) HandlerManager.trigger("on_roulette_finish", user=user, points=points)
def _filter_time_until_dt(var: Any, args: List[str]) -> Any: try: ts = utils.time_since(var.timestamp(), utils.now().timestamp()) if ts: return ts return "0 seconds" except: return "never FeelsBadMan ?"
def execute_now(method, args=[], kwargs={}, scheduler=None): if scheduler is None: scheduler = ScheduleManager.base_scheduler if scheduler is None: raise ValueError("No scheduler available") job = scheduler.add_job(method, "date", run_date=utils.now(), args=args, kwargs=kwargs) return ScheduledJob(job)
def _filter_time_since_dt(var, args): try: ts = utils.time_since(utils.now().timestamp(), var.timestamp()) if ts: return ts return "0 seconds" except: return "never FeelsBadMan ?"
def _seek(self, _time, current_song_webjsonify): self.bot.songrequest_websocket_manager.emit( "play", { "current_song": current_song_webjsonify, "current_timestamp": str(utils.now().timestamp()) }) self.bot.websocket_manager.emit("songrequest_seek", WIDGET_ID, {"seek_time": _time}) self.module_state["paused"] = True self._module_state()
def on_tick(self, **rest): if self.output_buffer == "": return if self.last_add is None: return diff = utils.now() - self.last_add if diff.seconds > 3: self.flush_output_buffer()
def execute_delayed(delay, method, args=[], kwargs={}, scheduler=None): if scheduler is None: scheduler = ScheduleManager.base_scheduler if scheduler is None: raise ValueError("No scheduler available") job = scheduler.add_job( method, "date", run_date=utils.now() + datetime.timedelta(seconds=delay), args=args, kwargs=kwargs ) return ScheduledJob(job)
def on_message(self, source, message, whisper, **rest): sendMessage = "" if message is None or whisper or source.ignored: return if self.question: right_answer = self.question["answer"].lower() user_answer = message.lower() if len(right_answer) <= 5: correct = right_answer == user_answer else: ratio = Levenshtein.ratio(right_answer, user_answer) correct = ratio >= 0.86 if correct: if self.point_bounty > 0: sendMessage = "{} got the answer right! The answer was {} FeelsGoodMan They get {} points! PogChamp".format( source.username_raw, self.question["answer"], self.point_bounty) source.points += self.point_bounty else: sendMessage = "{} got the answer right! The answer was {} FeelsGoodMan".format( source.username_raw, self.question["answer"]) self.question = None self.step = 0 self.last_question = utils.now() self.correct_dict[source.username_raw] = self.correct_dict.get( source.username_raw, 0) + 1 if "strep" in source.username_raw: self.streptocuckus += 1 if self.streptocuckus == 6: self.bot.say( "streptocarcus you gotta stop. you've been answering trivia almost every hour for the past " "few weeks. i know it's hard waiting for the next question but this trivia addiction is going " "to destroy you. please, streptocarcus. its for your own good." ) self.streptocuckus = 0 # record winstreak of correct answers for user if source.username_raw != self.winstreak[0]: self.winstreak = [source.username_raw, 1] else: self.winstreak[1] += 1 if self.winstreak[1] >= 7: sendMessage += " {} is on a {} question streak. Get a life FeelsWeirdMan".format( *self.winstreak) elif self.winstreak[1] >= self.min_streak: sendMessage += " {} is on a streak of {} correct answers Pog".format( *self.winstreak) self.bot.safe_me(sendMessage)
def lost(self, points_lost): self.duels_total += 1 self.points_lost += points_lost self.last_duel = utils.now() if self.current_streak < 0: self.current_streak -= 1 else: self.current_streak = -1 if abs(self.current_streak) > self.longest_losestreak: self.longest_losestreak = self.current_streak
def shared_end_predict(bot, source, type): with DBManager.create_session_scope() as db_session: # Check if there is a non-ended, but closed prediction run we can end predictions = db_session.query(PredictionRun).filter_by(ended=None, open=False, type=type).all() if len(predictions) == 0: bot.say(f"{source}, There is no closed prediction runs we can end right now.") return True for prediction in predictions: prediction.ended = utils.now() bot.say(f"Closed predictions with IDs {', '.join([str(p.id) for p in predictions])}")
def request(self, method, endpoint, params, headers, authorization=None, json=None): try: return super().request(method, endpoint, params, headers, authorization, json) except HTTPError as e: if e.response.status_code == 429: # retry once after rate limit resets... rate_limit_reset = datetime.fromtimestamp(int(e.response.headers["Ratelimit-Reset"]), tz=timezone.utc) time_to_wait = rate_limit_reset - utils.now() time.sleep(math.ceil(time_to_wait.total_seconds())) return super().request(method, endpoint, params, headers, authorization, json) else: raise e
def step_end(self): if self.question is not None: self.winstreak = [None, None] self.bot.safe_me( 'MingLee No one could answer the trivia! The answer was "{}" MingLee Since you\'re all useless, DatGuy gets one point.' .format(self.question["answer"])) self.question = None self.step = 0 self.last_question = utils.now() with DBManager.create_session_scope() as db_session: user = self.bot.users.find("datguy1", db_session=db_session) user.points += 1
def won(self, points_won): self.duels_won += 1 self.duels_total += 1 self.points_won += points_won self.last_duel = utils.now() if self.current_streak > 0: self.current_streak += 1 else: self.current_streak = 1 if self.current_streak > self.longest_winstreak: self.longest_winstreak = self.current_streak
def _create(db_session, stream_id, video_id, requested_by_id, skipped_by_id, skip_after): songrequesthistory = SongrequestHistory( stream_id=stream_id, video_id=video_id, date_finished=utils.now(), requested_by_id=requested_by_id, skipped_by_id=skipped_by_id, skip_after=skip_after, ) db_session.add(songrequesthistory) return songrequesthistory
def __init__(self, stream_id, youtube_id, **options): self.id = None self.stream_id = stream_id self.user_id = options.get("user_id", None) self.youtube_id = youtube_id self.date_added = utils.now() self.date_played = None self.skip_after = options.get("skip_after", None) if self.skip_after is not None and self.skip_after < 0: # Make sure skip_after cannot be a negative number self.skip_after = None
def _play(self, video_id, current_song_webjsonify): self.bot.songrequest_websocket_manager.emit( "play", { "current_song": current_song_webjsonify, "current_timestamp": str(utils.now().timestamp()) }) self.bot.websocket_manager.emit("songrequest_play", WIDGET_ID, {"video_id": video_id}) self.module_state["paused"] = True self._module_state() if self.module_state["video_showing"]: self._show()
def step_end(self): if self.question is not None: self.winstreak = 0 self.bot.safe_me( f'MingLee No one could answer the trivia! The answer was "{self.question["answer"]}" MingLee' ) self.question = None self.step = 0 self.last_question = utils.now() with DBManager.create_session_scope() as db_session: user = User.find_by_user_input(db_session, "datguy1") user.points = user.points + 1
def __init__( self, user_id, timeout_start, timeout_end, timeout_author, timeout_recent_end=(utils.now() + datetime.timedelta(days=14)), ): self.user_id = user_id self.timeout_start = timeout_start self.timeout_recent_end = timeout_recent_end self.timeout_end = timeout_end self.timeout_author = timeout_author
def execute_now(method, args=[], kwargs={}, scheduler=None): if scheduler is None: scheduler = ScheduleManager.base_scheduler if scheduler is None: return ScheduledJob(None) job = scheduler.add_job(method, "date", run_date=utils.now(), args=args, kwargs=kwargs) return ScheduledJob(job)
def command_close(self, **options): bot = options["bot"] self.last_game_start = utils.now() - datetime.timedelta(seconds=10) for username in self.bets: _, points = self.bets[username] user = self.bot.users[username] user.remove_debt(points) bot.whisper( username, "Your HS bet of {} points has been refunded because the bet has been cancelled.".format(points), ) self.bets = {}
def refresh_video_url_stage2(self, data): if self.online is False: return if self.current_stream_chunk is None or self.current_stream is None: return log.info( f"Attempting to fetch video url for broadcast {self.current_stream_chunk.broadcast_id}" ) video_url, video_preview_image_url, video_recorded_at = self.fetch_video_url_stage2( data) if video_url is None: log.info("No video for broadcast found") return log.info(f"Successfully fetched a video url: {video_url}") if self.current_stream_chunk is None or self.current_stream_chunk.video_url is None: with DBManager.create_session_scope( expire_on_commit=False) as db_session: self.current_stream_chunk.video_url = video_url self.current_stream_chunk.video_preview_image_url = video_preview_image_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info("Successfully commited video url data.") elif self.current_stream_chunk.video_url != video_url: # End current stream chunk self.current_stream_chunk.chunk_end = utils.now() DBManager.session_add_expunge(self.current_stream_chunk) with DBManager.create_session_scope( expire_on_commit=False) as db_session: stream_chunk = StreamChunk( self.current_stream, self.current_stream_chunk.broadcast_id, video_recorded_at) self.current_stream_chunk = stream_chunk self.current_stream_chunk.video_url = video_url self.current_stream_chunk.video_preview_image_url = video_preview_image_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info("Successfully commited video url data in a new chunk.")
def on_user_sub_or_resub(self, **rest): now = utils.now() # True if we already announced the alert_message_after_sub within the last 5 seconds. Prevents # spam after bulk sub gifts. skip_message = self.last_sub is not None and now - self.last_sub < datetime.timedelta( seconds=5) self.last_sub = now if (self.settings["only_roulette_after_sub"] and self.settings["alert_message_after_sub"] != "" and not skip_message): self.bot.say(self.settings["alert_message_after_sub"].format( seconds=self.settings["after_sub_roulette_time"]))
def poll_trivia(self): if self.question is None and (self.last_question is None or utils.now() - self.last_question >= datetime.timedelta(seconds=12)): url = "http://jservice.io/api/random" r = requests.get(url) self.question = r.json()[0] self.question["answer"] = (self.question["answer"].replace( "<i>", "").replace("</i>", "").replace("\\", "").replace( "(", "").replace(")", "").strip('"').strip(".")) if (len(self.question["answer"]) == 0 or len(self.question["question"]) <= 1 or "href=" in self.question["answer"]): self.question = None return self.step = 0 self.last_step = None # Is it time for the next step? condition = self.last_question is None or utils.now( ) - self.last_question >= datetime.timedelta( seconds=self.settings["question_delay"]) if (self.last_step is None and condition) or ( self.last_step is not None and utils.now() - self.last_step >= datetime.timedelta(seconds=self.settings["step_delay"])): self.last_step = utils.now() self.step += 1 if self.step == 1: self.step_announce() elif self.step < self.settings["hint_count"] + 2: self.step_hint() else: self.step_end()
def _create(db_session, video_id, skip_after, requested_by_id, queue=None, backup=False): songrequestqueue = SongrequestQueue(video_id=video_id, date_added=utils.now(), skip_after=skip_after, requested_by_id=requested_by_id) db_session.add(songrequestqueue) db_session.commit() SongRequestQueueManager.inset_song( songrequestqueue.id, "backup-song-queue" if backup else "song-queue", queue) return songrequestqueue
def check_follow_age(self, bot, source, username, streamer, event): streamer = bot.streamer if streamer is None else streamer.lower() age = bot.twitchapi.get_follow_relationship(username, streamer) is_self = source.username == username message = "" streamer = streamer.replace('admiralbulldog', 'Buldog') if age: # Following human_age = time_since(utils.now().timestamp() - age.timestamp(), 0) message = "{} has been following {} for {}".format(username, streamer, human_age) else: # Not following message = "{} is not following {}".format(username, streamer) bot.send_message_to_user(source, message, event, method=self.settings["action_followage"])
def pause_function(self): if not self.module_state["enabled"] or not self.current_song_id: return False if not self.module_state["paused"]: self.module_state["paused"] = True self._module_state() self._pause() self.remove_schedule() with DBManager.create_session_scope() as db_session: song = SongrequestQueue._from_id(db_session, self.current_song_id) song.played_for = (utils.now() - song.date_resumed).total_seconds() song.date_resumed = None return True return False
def command_restart(self, bot, message, **rest): reason = message if message else "No reason given EleGiggle" with DBManager.create_session_scope() as db_session: current_game = self.get_current_game(db_session, with_bets=True, with_users=True) for bet in current_game.bets: bet.user.points = User.points + bet.points bot.whisper( bet.user, f"Your {bet.points} points bet has been refunded. The reason given is: '{reason}'" ) db_session.delete(bet) current_game.timestamp = utils.now() self.spectating = False bot.me("All your bets have been refunded and betting has been restarted.")
def refresh_video_url_stage2(self, data) -> None: if self.online is False: return if self.current_stream_chunk is None or self.current_stream is None: return video: Optional[TwitchVideo] = self.fetch_video_url_stage2(data) if video is None: return log.info(f"Successfully fetched a video url: {video.url}") if self.current_stream_chunk is None or self.current_stream_chunk.video_url is None: with DBManager.create_session_scope( expire_on_commit=False) as db_session: self.current_stream_chunk.video_url = video.url self.current_stream_chunk.video_preview_image_url = video.thumbnail_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info("Successfully commited video url data.") elif self.current_stream_chunk.video_url != video.url: # End current stream chunk self.current_stream_chunk.chunk_end = utils.now() DBManager.session_add_expunge(self.current_stream_chunk) with DBManager.create_session_scope( expire_on_commit=False) as db_session: stream_chunk = StreamChunk( self.current_stream, self.current_stream_chunk.broadcast_id, video.created_at) self.current_stream_chunk = stream_chunk self.current_stream_chunk.video_url = video.url self.current_stream_chunk.video_preview_image_url = video.thumbnail_url db_session.add(self.current_stream_chunk) db_session.commit() db_session.expunge_all() log.info("Successfully commited video url data in a new chunk.")