Skip to content

Commit

Permalink
Add support for showing parental guides & Added feedback streams
Browse files Browse the repository at this point in the history
  • Loading branch information
mhdzumair committed Jan 5, 2025
1 parent 34fe086 commit d32164b
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 47 deletions.
47 changes: 20 additions & 27 deletions db/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
parse_stream_data,
parse_tv_stream_data,
calculate_max_similarity_ratio,
create_exception_stream
create_exception_stream,
create_content_warning_message,
)
from utils.validation_helper import (
validate_parent_guide_nudity,
Expand Down Expand Up @@ -525,19 +526,16 @@ async def get_movie_streams(
)
]
movie_metadata = await get_movie_data_by_id(video_id)
if not (movie_metadata and validate_parent_guide_nudity(movie_metadata, user_data)):
if movie_metadata:
return [create_exception_stream(
f"MediaFusion {user_data.streaming_provider.service.title()}",
f"🚫This item contains inappropriate content and it is advisable not to watch\n"
f"{movie_metadata.parent_guide_nudity_status} {movie_metadata.parent_guide_certificates}",
if not movie_metadata:
return []
if validate_parent_guide_nudity(movie_metadata, user_data) is False:
return [
create_exception_stream(
settings.addon_name,
create_content_warning_message(movie_metadata),
"inappropriate_content.mp4",
)]
return [create_exception_stream(
f"MediaFusion {user_data.streaming_provider.service.title()}",
"🚫Movie metadata not found",
"metadata_not_found.mp4"
)]
)
]

live_search_streams = user_data.live_search_streams and video_id.startswith("tt")
cache_key = f"torrent_streams:{video_id}"
Expand Down Expand Up @@ -577,21 +575,16 @@ async def get_series_streams(
background_tasks: BackgroundTasks,
) -> list[Stream]:
series_metadata = await get_series_data_by_id(video_id)
if not (
series_metadata and validate_parent_guide_nudity(series_metadata, user_data)
):
if series_metadata:
return [create_exception_stream(
f"MediaFusion {user_data.streaming_provider.service.title()}",
f"🚫This item contains inappropriate content.\n"
f"{series_metadata.parent_guide_nudity_status} {series_metadata.parent_guide_certificates}",
if not series_metadata:
return []
if validate_parent_guide_nudity(series_metadata, user_data) is False:
return [
create_exception_stream(
settings.addon_name,
create_content_warning_message(series_metadata),
"inappropriate_content.mp4",
)]
return [create_exception_stream(
f"MediaFusion {user_data.streaming_provider.service.title()}",
"🚫Series metadata not found",
"metadata_not_found.mp4"
)]
)
]

live_search_streams = user_data.live_search_streams and video_id.startswith("tt")
cache_key = f"torrent_streams:{video_id}:{season}:{episode}"
Expand Down
Binary file added resources/exceptions/filtered_no_streams.mp4
Binary file not shown.
Binary file added resources/exceptions/inappropriate_content.mp4
Binary file not shown.
4 changes: 2 additions & 2 deletions utils/exception_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ def create_text_video(

if __name__ == "__main__":
create_text_video(
"../resources/exceptions/update_imdb_data.mp4",
"We updated the metadata from IMDb.\nThanks for your contribution!",
"resources/exceptions/inappropriate_content.mp4",
"This content may not be suitable for your preferences",
)
106 changes: 88 additions & 18 deletions utils/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
)
from utils import const
from utils.config import config_manager
from utils.const import STREAMING_PROVIDERS_SHORT_NAMES
from utils.const import STREAMING_PROVIDERS_SHORT_NAMES, CERTIFICATION_MAPPING
from utils.network import encode_mediaflow_proxy_url
from utils.runtime_const import ADULT_CONTENT_KEYWORDS, TRACKERS, MANIFEST_TEMPLATE
from utils.validation_helper import validate_m3u8_or_mpd_url_with_cache
Expand Down Expand Up @@ -92,12 +92,7 @@ async def filter_and_sort_streams(
filtered_streams.append(stream)

if not filtered_streams:
return [
create_exception_stream(
settings.addon_name,
"🚫 Streams were found, but they were filtered due to your configuration.",
"filtered_no_streams.mp4"
)]
return []

# Step 2: Update cache status based on provider
if user_data.streaming_provider:
Expand Down Expand Up @@ -229,19 +224,15 @@ async def parse_stream_data(
user_ip: str | None = None,
is_series: bool = False,
) -> list[Stream]:
if not streams:
return []

streaming_provider_name = (
STREAMING_PROVIDERS_SHORT_NAMES.get(user_data.streaming_provider.service, "P2P")
if user_data.streaming_provider
else "P2P"
)

if not streams:
return [
create_exception_stream(
settings.addon_name,
"🚫 No results available in the system.",
"no_results.mp4")
]
addon_name = f"{settings.addon_name} {streaming_provider_name}"

stremio_video_id = (
f"{streams[0].meta_id}:{season}:{episode}" if is_series else streams[0].meta_id
Expand All @@ -250,7 +241,14 @@ async def parse_stream_data(
streams, user_data, stremio_video_id, user_ip
)

streams = await filter_and_sort_streams(streams, user_data, user_ip, streaming_provider_name)
if not streams:
return [
create_exception_stream(
settings.addon_name,
"🚫 Streams Found\nβš™οΈ Filtered by your configuration preferences",
"filtered_no_streams.mp4",
)
]

# Precompute constant values
show_full_torrent_name = user_data.show_full_torrent_name
Expand All @@ -265,7 +263,7 @@ async def parse_stream_data(
user_data.mediaflow_config
and user_data.mediaflow_config.proxy_debrid_streams
):
streaming_provider_name += " πŸ•΅πŸΌβ€β™‚οΈ"
addon_name += " πŸ•΅πŸΌβ€β™‚οΈ"

base_proxy_url_template = (
f"{settings.host_url}/streaming_provider/{secret_str}/stream/{{}}"
Expand Down Expand Up @@ -355,7 +353,7 @@ async def parse_stream_data(
)

stream_details = {
"name": f"{settings.addon_name} {streaming_provider_name} {resolution} {streaming_provider_status}",
"name": f"{addon_name} {resolution} {streaming_provider_status}",
"description": description,
"behaviorHints": {
"bingeGroup": f"{settings.addon_name.replace(' ', '-')}-{quality_detail}-{resolution}",
Expand Down Expand Up @@ -655,3 +653,75 @@ def calculate_max_similarity_ratio(
max_similarity_ratio = max([title_similarity_ratio] + aka_similarity_ratios)

return max_similarity_ratio


def get_certification_level(certificates: list) -> str:
"""
Get the highest certification level from a list of certificates.
Returns the category name (All Ages, Children, etc.) based on the highest restriction level.
"""
if not certificates:
return "Unknown"

# Order of restriction levels from lowest to highest
levels = ["All Ages", "Children", "Parental Guidance", "Teens", "Adults"]

highest_level = "Unknown"
for certificate in certificates:
for level in levels:
if certificate in CERTIFICATION_MAPPING[level]:
# If current level is more restrictive, update highest_level
if (
levels.index(level) > levels.index(highest_level)
if highest_level in levels
else -1
):
highest_level = level

return highest_level


def get_age_rating_emoji(certification_level: str) -> str:
"""
Get appropriate emoji for certification level
"""
emoji_mapping = {
"All Ages": "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦",
"Children": "πŸ‘Ά",
"Parental Guidance": "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦",
"Teens": "πŸ‘±",
"Adults": "πŸ”ž",
"Unknown": "❓",
}
return emoji_mapping.get(certification_level, "❓")


def get_nudity_status_emoji(nudity_status: str) -> str:
"""
Get appropriate emoji for nudity status
"""
emoji_mapping = {
"None": "πŸ‘•",
"Mild": "⚠️",
"Moderate": "πŸ”ž",
"Severe": "β›”",
}
return emoji_mapping.get(nudity_status, "❓")


def create_content_warning_message(metadata) -> str:
"""
Create a formatted warning message with emojis based on movie metadata
"""
cert_level = get_certification_level(metadata.parent_guide_certificates)
cert_emoji = get_age_rating_emoji(cert_level)
nudity_emoji = get_nudity_status_emoji(metadata.parent_guide_nudity_status)

message = (
f"⚠️ Content Warning ⚠️\n"
f"This content may not be suitable for your preferences:\n"
f"Certification: {cert_emoji} {cert_level}\n"
f"Nudity Status: {nudity_emoji} {metadata.parent_guide_nudity_status}"
)

return message

0 comments on commit d32164b

Please sign in to comment.