def get_unlisted_livestreams_by_username(username: str) -> Dict[str, Any]: """Get a user's unlisted livestreams from their username. Args: username (str): The user's username. Returns: Dict[str, Any]: The unlisted livestream. """ items = "user_snowflake, start_date, title, description, category, unique_id" res = query_one("SELECT snowflake FROM user WHERE username = ?", [username]) stream = query_one( f"SELECT {items} FROM stream WHERE user_snowflake = ? AND unlisted = 1 AND end_date IS NULL AND start_date IS NOT NULL", # noqa: E501 [res["snowflake"]], ) if stream: stream["username"] = username return stream
def get_livestreams_by_username(username: str) -> Dict[str, Any]: """Get a user's current livestreams via their username. Args: username (str): The username you want to check for. Returns: Dict[str, Any]: The livestream's details. """ items = "user_snowflake, start_date, title, description, category, unique_id" user_id = query_one("SELECT snowflake FROM user WHERE username = ?", [username]) stream = query_one( f"SELECT {items} FROM stream WHERE user_snowflake = ? AND unlisted = 0 AND end_date IS NULL AND start_date IS NOT NULL", # noqa: E501 [user_id["snowflake"]], ) if stream: stream["username"] = username return stream
def get_unique_stream_id_from_stream_key(stream_key: str) -> str: """Get a stream's unique ID from its key. Args: stream_key (str): The stream's key Returns: str: The unique ID. """ res = query_one("SELECT unique_id FROM stream WHERE stream_key = ?", [stream_key]) return res["unique_id"]
def get_stream_key_from_unique_id(unique_id: str) -> str: """Get a stream's stream key from its unique ID. Args: unique_id (str): The stream's unique ID. Returns: str: The stream key. """ res = query_one("SELECT stream_key FROM stream WHERE unique_id = ?", [unique_id]) return res["stream_key"]
def end_stream(stream_key: str) -> None: """Sets the stream's end date in the database. Args: stream_key (str): The stream key to update. """ db = get_db() current_app.logger.info(f"Ending stream {stream_key}") res = query_one("SELECT * FROM stream WHERE stream_key = ?", [stream_key]) db.execute( "UPDATE stream SET end_date = ? WHERE id = ?", (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), res["id"]), ) db.commit()
def get_username_from_snowflake(snowflake: int) -> str: """Get a user's username from a user ID. Args: snowflake (int): The user's ID. Returns: str: The user's username. """ user = query_one( "SELECT username FROM user WHERE snowflake = ?", [snowflake], ) return user["username"]
def manage_stream(unique_id: str) -> Any: """Manage a stream's properties via its unique ID. Args: unique_id (str): The stream's unique ID. Returns: Any: A static page rendered by Flask. """ user = discord.fetch_user() form = StreamGenerationForm() stream = query_one( "SELECT title, description, category, archivable, unlisted, user_snowflake FROM stream WHERE unique_id = ?", [unique_id], ) if not stream: return render_template("alert.html", error="Invalid stream ID."), 404 # Populate the stream editing form. form.title.data = stream["title"] form.description.data = stream["description"] form.category.data = stream["category"] form.archivable.data = stream["archivable"] form.unlisted.data = stream["unlisted"] if stream["user_snowflake"] == user.id: if request.method == "GET": return render_template("manage_stream.html", form=form, unique_id=unique_id) if request.method == "POST": form = StreamGenerationForm(request.form) if form.validate(): keys_to_change = {} for key, value in form.data.items(): if stream[key] != value: keys_to_change[key] = value update_db_fields(unique_id, **keys_to_change) return render_template("manage_stream.html", form=form, unique_id=unique_id, update=True) else: # User does not have access to manage this stream ID. return abort(403)
def done() -> Any: """Mark the stream as done and archive the stream. Returns: Any: Returns 200 when the function has completed. """ stream_key = request.form["name"] end_stream(stream_key) stream = query_one("SELECT * FROM stream WHERE stream_key = ?", [stream_key]) if bool(stream["archivable"]): current_app.logger.info("Stream is archivable.") else: current_app.logger.info("Stream is going to be archived privately.") archive_stream(stream_key) return jsonify({"message": "Stream has successfully ended"}), 200
def verify_stream_key(stream_key: str) -> bool: """Validate that the stream key exists in the database Args: stream_key (str): The stream key to validate. Returns: bool: True if the key exists. """ valid = False res = query_one( "SELECT * from stream WHERE stream_key = ? AND end_date IS NULL", [stream_key]) try: if res["stream_key"]: current_app.logger.info(f"Accepting stream: {stream_key}") valid = True except TypeError: current_app.logger.info(f"Invalid stream key: {stream_key}") return valid
def me() -> Text: """Render a page to manage stream properties Returns: Text: Static page rendered by Flask. """ discord_user = discord.fetch_user() user = query_one("SELECT * FROM user WHERE snowflake = ?", [discord_user.id]) streams = query_many( "SELECT * FROM stream WHERE user_snowflake = ?", [discord_user.id] ) if streams: for stream in streams: try: duration = stream["end_date"] - stream["start_date"] stream["duration"] = str(duration) except TypeError: continue stream["username"] = user["username"] return render_template("manage_user.html", user=user, streams=streams) return render_template("manage_user.html", user=user)
def serve_stream(unique_id: str, file: str) -> Any: """Serve stream via its unique ID Example: A stream uses the following IDs and keys: Stream key = 1451fgsa Unique ID = klzfls156 GET /watch/klzfls156/index.m3u8 < HLS_DIR/1451fgsa-index.m3u8 GET /watch/klzfls156/1.ts < HLS_DIR/1451fgsa-1.ts Args: unique_id (str): The stream's unique ID file (str): The requested file Returns: Any: Serves file from HLS path if exists. """ stream_key = get_stream_key_from_unique_id(unique_id) stream = query_one("SELECT end_date FROM stream WHERE stream_key = ?", [stream_key]) if stream_key and not stream["end_date"]: if file == "index.m3u8": try: rewrite_stream_playlist(stream_key) return send_from_directory( environ.get("HLS_PATH"), f"{stream_key}-index.m3u8" ) except FileNotFoundError: return abort(404) else: return send_from_directory(environ.get("HLS_PATH"), f"{stream_key}-{file}") return abort(404)
def serve_archive(unique_id: str) -> Response: """Serves stream from the archive. Args: unique_id (str): The stream's unique ID. Returns: Response: File being served by Flask's Response class. """ user = discord.fetch_user() stream = query_one( "SELECT * FROM stream WHERE archived_file IS NOT NULL AND unique_id = ?", [unique_id], ) if user.id == stream["user_snowflake"]: # The user requesting the stream created it. # Therefore they shall always have access to the file. return serve_file(stream) elif bool(stream["archivable"]): # The stream is publically archived. return serve_file(stream) else: # The stream does not exist. return abort(404)