Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for RPDB posters & Support fallback posters via MediaFusion posters #284

Merged
merged 1 commit into from
Sep 12, 2024

Conversation

mhdzumair
Copy link
Owner

@mhdzumair mhdzumair commented Sep 12, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced catalog retrieval and caching for improved data flow and efficiency.
    • Introduced RPDB configuration options, including API key management and MediaFlow setup guidance.
  • Bug Fixes

    • Improved handling of poster URLs for series metadata, streamlining the construction process.
  • Documentation

    • Added links and descriptions for MediaFlow and RPDB setup in the configuration section.
  • User Interface

    • Implemented dynamic display of RPDB configuration options based on user interaction.
  • Performance Improvements

    • Optimized asynchronous management of movie poster URLs from the RPDB.

Copy link
Contributor

coderabbitai bot commented Sep 12, 2024

Walkthrough

The changes encompass significant updates to the catalog retrieval and caching mechanisms, the introduction of a new configuration class, enhancements to user interface elements for RPDB integration, and the addition of functionality for managing movie poster URLs from the Rating Poster Database. Key functions have been modified or added to improve data parsing, caching strategies, and metadata handling, while new HTML and JavaScript elements facilitate user configuration for RPDB services.

Changes

Files Change Summary
api/main.py Introduced functions for parsing genre and skip parameters, enhanced caching key determination, updated catalog retrieval logic, and added metadata fetching logic.
db/crud.py Refactored get_series_meta to simplify poster URL construction, removing unnecessary aggregation steps.
db/schemas.py Added RPDBConfig class for API key configuration and modified UserData to include optional RPDB configuration.
resources/html/configure.html Enhanced configuration sections for MediaFlow and RPDB, including links, checkboxes, and input fields for API key.
resources/js/config_script.js Added functionality for handling RPDB configuration options, including user input validation and dynamic display of configuration fields.
scrapers/rpdb.py Implemented asynchronous functions for managing movie poster URLs based on IMDB IDs, including checks for supported and unsupported IDs.
utils/network.py Modified get_user_data function to accept an optional secret_str parameter.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant Backend
    participant RPDB

    User->>Frontend: Interacts with RPDB configuration
    Frontend->>Backend: Sends RPDB API key
    Backend->>RPDB: Validates API key
    RPDB-->>Backend: Returns validation result
    Backend-->>Frontend: Confirms configuration
    Frontend-->>User: Displays success message
Loading

🐰 In the code we hop and play,
New features bloom, bright as day.
With posters fresh and keys in hand,
Our media flows, just as we planned!
Hooray for RPDB, our friend so dear,
Let’s celebrate with a joyful cheer! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Outside diff range and nitpick comments (3)
scrapers/rpdb.py (2)

15-25: LGTM with a minor suggestion!

The function is implemented correctly and handles errors appropriately. Consider explicitly catching httpx.TimeoutException and logging a specific message for timeouts to differentiate it from other HTTP errors.

     except httpx.HTTPError as exc:
         logging.error(f"HTTP Exception for {exc.request.url} - {exc}")
         return False
+    except httpx.TimeoutException as exc:
+        logging.error(f"Timeout for {rpdb_poster_url} - {exc}")
+        return False
     except Exception as exc:
         logging.error(f"Exception for {rpdb_poster_url} - {exc}")
         return False

28-60: Looks good with a couple of suggestions!

The function implements a caching mechanism correctly to avoid unnecessary requests. Consider the following improvements:

  1. Use a constant for the Redis key prefix to avoid duplication and improve maintainability.

  2. Use a more specific exception, such as redis.exceptions.RedisError, for the Redis operations to differentiate from other exceptions.

  3. Define a constant for the Redis key prefix:

REDIS_KEY_PREFIX = "rpdb:"
RPDB_SUPPORTED_SET = f"{REDIS_KEY_PREFIX}supported_ids"
RPDB_UNSUPPORTED_HASH = f"{REDIS_KEY_PREFIX}unsupported_ids"
  1. Catch redis.exceptions.RedisError:
from redis.exceptions import RedisError

...

try:
    if await REDIS_ASYNC_CLIENT.sismember(RPDB_SUPPORTED_SET, imdb_id):
        return rpdb_poster_url

    expiry_time = await REDIS_ASYNC_CLIENT.hget(RPDB_UNSUPPORTED_HASH, imdb_id)
    ...
except RedisError as exc:
    logging.error(f"Redis error for {imdb_id} - {exc}")
    # Handle the error, e.g., return None or raise an exception
resources/html/configure.html (1)

528-529: Remove empty <div>.

The empty <div> on lines 528-529 seems unnecessary. Please remove it to keep the markup clean and concise.

Apply this change:

-                    <div class="mb-3">
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between dedeb31 and 0f2a027.

Files selected for processing (7)
  • api/main.py (6 hunks)
  • db/crud.py (2 hunks)
  • db/schemas.py (2 hunks)
  • resources/html/configure.html (2 hunks)
  • resources/js/config_script.js (5 hunks)
  • scrapers/rpdb.py (1 hunks)
  • utils/network.py (1 hunks)
Additional comments not posted (27)
scrapers/rpdb.py (3)

63-77: LGTM!

The function correctly updates the poster URL for a single MetaItem based on the user's RPDB config and catalog type. It properly delegates the poster update logic to update_single_rpdb_poster, maintaining a good separation of concerns.


80-95: Looks good!

The function correctly updates the poster URLs for multiple MetaItems concurrently using asyncio.gather. It follows a similar pattern as update_rpdb_poster for checking the user's RPDB config and catalog type, maintaining consistency. No major issues or improvements needed.


1-13: File-level code looks good!

The imports are correctly organized and follow the standard convention. The constants for Redis keys and expiry are appropriately named and used consistently throughout the file. No issues or improvements needed at the file level.

db/schemas.py (2)

120-126: LGTM!

The RPDBConfig class follows the existing pattern of configuration classes in the file. The api_key field is appropriately aliased for consistency, and the class is configured to ignore extra fields and populate by name, which is a good practice for configuration classes.


197-197: LGTM!

The addition of the optional rpdb_config field to the UserData class enhances its structure by allowing it to hold configuration data specific to the RPDB service, thereby extending its functionality and flexibility in handling user data. The field is correctly typed, aliased for consistency, and defaults to None, which is appropriate for a configuration field.

api/main.py (14)

28-28: LGTM!

The import statement is correct and necessary for the changes made in this file.


265-265: LGTM!

The function call is correct and helps to streamline the parsing logic.


266-268: LGTM!

The function call is correct and enhances the caching mechanism by determining the cache key based on the catalog type, catalog ID, skip, genre, and user data. It also identifies if the catalog is a watchlist.


270-275: LGTM!

The code changes are correct and improve the flow of data retrieval by utilizing the cached data when available. The cached data is processed through update_rpdb_posters, ensuring that the user data and catalog type are considered.


276-277: LGTM!

The code changes are correct and ensure that the response headers are set appropriately based on the availability of the cache key.


279-281: LGTM!

The function call is correct and handles the retrieval of metadata when no cache is available. It uses the catalog type, catalog ID, genre, skip, user data, request, and watchlist catalog flag to fetch the appropriate metadata.


283-288: LGTM!

The code changes are correct and ensure that the metadata is cached for future retrieval, improving performance. The metadata is cached using the cache key, if available, with a TTL specified by settings.meta_cache_ttl.


290-290: LGTM!

The code changes are correct and ensure that the metadata is updated with the latest poster information before returning it to the user. The metadata is processed through update_rpdb_posters, considering the user data and catalog type.


293-298: LGTM!

The function is implemented correctly and streamlines the parsing of genre and skip parameters. It handles the case when genre contains a & character, indicating that skip is also provided. It extracts the skip value and converts it to an integer, defaulting to 0 if not provided or invalid.


301-323: LGTM!

The function is implemented correctly and enhances the caching mechanism by determining the appropriate cache key based on various factors. It identifies if the catalog is a watchlist based on the user's streaming provider and catalog ID. It sets the cache key to None for watchlist catalogs and events. For movie and series catalogs, it appends the user's nudity and certification filters to the cache key.


Line range hint 326-358: LGTM!

The function is implemented correctly and handles the retrieval of metadata based on the catalog type and user data. It considers various factors such as the user's IP address and watchlist catalog flag. The insertion of the special "delete all" meta item for watchlist catalogs is a nice addition.

Tools
Ruff

263-263: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


409-412: LGTM!

The code changes are correct and ensure that the search results are processed and updated with the latest poster information before returning them to the user. The search query is processed using the crud.process_search_query function based on the search query, catalog type, and user data. The resulting metadata is then updated with the latest poster information using update_rpdb_posters, considering the user data and catalog type.


445-448: LGTM!

The code changes are correct and handle the retrieval of cached metadata, ensuring that it is validated and updated with the latest poster information before returning it to the user. The cached metadata is retrieved using the cache key and validated using the MetaItem model. If the validated metadata is empty, it raises a 404 error indicating that the meta ID was not found. The validated metadata is then updated with the latest poster information using update_rpdb_poster, considering the user data and catalog type. The error handling for empty metadata is also appropriate.


471-473: LGTM!

The code changes are correct and ensure that the metadata is validated and updated with the latest poster information before returning it to the user. The metadata is validated using the MetaItem model and then updated with the latest poster information using update_rpdb_poster, considering the user data and catalog type.

resources/js/config_script.js (4)

320-326: LGTM!

The code segment correctly introduces the rpdbConfig object to store the RPDB API key. The object creation is properly conditioned on the state of the enable_rpdb checkbox, and the API key is validated to ensure it's not an empty string.


378-378: LGTM!

The addition of rpdbConfig to the data returned by getUserData is consistent with the introduction of the rpdbConfig object earlier in the code.


468-471: LGTM!

The event listener correctly toggles the display of the rpdb_config section based on the state of the enable_rpdb checkbox. The setElementDisplay function is used appropriately to show or hide the section.


561-561: LGTM!

The password toggle setup for the rpdb_api_key input field is correctly implemented using the setupPasswordToggle function. This change is consistent with the password toggle setup for other sensitive input fields in the code.

db/crud.py (1)

464-465: LGTM!

The changes to the get_series_meta function improve the handling of the poster field for series metadata. By introducing the poster_path variable and using it directly in the final output, the code becomes more readable and maintainable. The removal of the poster field from the aggregation stages streamlines the data processing by eliminating unnecessary steps.

Also applies to: 600-600

resources/html/configure.html (3)

480-484: LGTM!

Adding a link to the MediaFlow setup guide is helpful for users to configure MediaFlow correctly. The code changes look good.


527-562: Looks good!

The new RPDB configuration section is implemented correctly:

  • The checkbox, description, and links provide clear context about the optional RPDB service for enhanced posters.
  • The API key input is appropriately password-protected.
  • The code is structured well and matches the existing conventions.

Great work on adding this optional feature!


545-547: LGTM!

The description of the RPDB service is clear and helpful. It provides good context about how RPDB enhances the default MediaFusion poster behavior. The text looks good.

@@ -235,7 +235,7 @@ def get_request_namespace(request: Request) -> str:
return namespace


def get_user_data(request: Request) -> UserData:
def get_user_data(request: Request, secret_str: str | None = None) -> UserData:
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Remove the unused secret_str parameter from get_user_data.

The secret_str parameter is not used within the get_user_data function, nor is it passed in any function calls throughout the codebase. Removing this unused parameter will simplify the function signature and avoid confusion.

  • File: utils/network.py
    • Line: 238
-def get_user_data(request: Request, secret_str: str | None = None) -> UserData:
+def get_user_data(request: Request) -> UserData:
     return request.user
Analysis chain

Verify the purpose and usage of the secret_str parameter.

I noticed that the function signature has been updated to accept an optional secret_str parameter, but the function body is not using this parameter. It's unclear why this parameter was added.

If the secret_str parameter is not needed, consider removing it to keep the function signature clean and avoid confusion.

To verify the purpose and usage of the secret_str parameter, run the following script:

If the secret_str parameter is not being used anywhere, consider applying this diff to remove it:

-def get_user_data(request: Request, secret_str: str | None = None) -> UserData:
+def get_user_data(request: Request) -> UserData:
     return request.user
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for the usage of the `secret_str` parameter.

# Test 1: Search for the usage of the `secret_str` parameter in the `get_user_data` function.
# Expect: No occurrences of `secret_str` within the function body.
ast-grep --lang python --pattern $'def get_user_data($_, secret_str):
  $$$
  secret_str
  $$$
'

# Test 2: Search for the invocations of the `get_user_data` function with the `secret_str` argument.
# Expect: Occurrences of `get_user_data` calls with the `secret_str` argument if the parameter is being used.
rg --type python -A 5 $'get_user_data\([^)]*secret_str'

Length of output: 185


Script:

#!/bin/bash
# Description: Search for the usage of the `secret_str` parameter.

# Test 1: Search for the usage of the `secret_str` parameter in the `get_user_data` function.
# Expect: No occurrences of `secret_str` within the function body.
ast-grep --lang python --pattern $'def get_user_data($_, secret_str):
  $$$
  secret_str
  $$$
'

# Test 2: Correct the rg command to search for invocations of the `get_user_data` function with the `secret_str` argument.
# Expect: Occurrences of `get_user_data` calls with the `secret_str` argument if the parameter is being used.
rg -t py -A 5 'get_user_data\([^)]*secret_str'

Length of output: 416

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for annotating the open API config.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhdzumair Thank you for providing that clarification. I apologize for my incorrect suggestion earlier. You're absolutely right that the secret_str parameter is important for annotating the OpenAPI config, even though it's not directly used within the function body.

I retract my previous suggestion to remove the parameter. It's crucial to keep it for proper API documentation. Thank you for catching this and explaining its purpose.

🐰💭
(A thoughtful rabbit, considering the new information)


Learnings added
Learnt from: mhdzumair
PR: mhdzumair/MediaFusion#284
File: utils/network.py:238-238
Timestamp: 2024-09-12T06:35:58.934Z
Learning: The `secret_str` parameter in the `get_user_data` function in `utils/network.py` is needed for annotating the OpenAPI config, even if it's not used within the function body itself.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant