-
Notifications
You must be signed in to change notification settings - Fork 7
Add cast container functionality for movies, TV shows, and episodes #9
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
base: main
Are you sure you want to change the base?
Add cast container functionality for movies, TV shows, and episodes #9
Conversation
heros-os
commented
Jan 3, 2026
- Add get_cast_items() method to ListGetItemDetails base class
- Add get_cast_directory() method for populating cast containers
- Create ListGetMovieCast, ListGetTVShowCast, and ListGetEpisodeCast classes
- Cast members populated as individual ListItems with name, role, and thumbnail
- Provides foundation for script.skinvariables to fix issue #1553
- Includes comprehensive documentation and examples
- No breaking changes, fully backward compatible
- Add get_cast_items() method to ListGetItemDetails base class - Add get_cast_directory() method for populating cast containers - Create ListGetMovieCast, ListGetTVShowCast, and ListGetEpisodeCast classes - Cast members populated as individual ListItems with name, role, and thumbnail - Provides foundation for script.skinvariables to fix issue #1553 - Includes comprehensive documentation and examples - No breaking changes, fully backward compatible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds cast container functionality to enable skinners to populate secondary containers with cast member information from movies, TV shows, and episodes. The implementation extends the existing ListGetItemDetails base class with new methods and introduces three specialized classes for handling cast data retrieval via Kodi's JSON-RPC API.
Key changes include:
- Addition of
get_cast_items()andget_cast_directory()methods to the base class for retrieving and populating cast data - Creation of three new classes (
ListGetMovieCast,ListGetTVShowCast,ListGetEpisodeCast) that provide dedicated cast container support - Comprehensive documentation and examples showing integration patterns for script.skinvariables
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| resources/modules/jurialmunkey/jrpcid.py | Adds cast retrieval methods to base class and three new cast-specific classes that fetch cast data via JSON-RPC and populate containers with actor ListItems |
| examples_cast_container.py | Provides comprehensive Python examples demonstrating usage patterns, plugin routing integration, and skin XML implementation examples |
| IMPLEMENTATION_SUMMARY.md | Documents the technical implementation details, data flow, integration steps, and usage examples for developers |
| CAST_QUICK_REFERENCE.md | Quick reference guide for both developers and skinners showing common usage patterns and troubleshooting tips |
| CAST_CONTAINER_IMPLEMENTATION.md | Detailed implementation guide covering problem statement, solution architecture, skin integration, and testing recommendations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def get_cast_items(self, dbid): | ||
| """ | ||
| Get cast members from the JSON-RPC response and create list items for each. | ||
| This creates a secondary container with cast information. | ||
| Returns a list of tuples (path, ListItem, is_folder) | ||
| """ | ||
| method = self.jrpc_method | ||
| params = { | ||
| self.jrpc_id: self.jrpc_idtype(dbid), | ||
| "properties": ["cast"] | ||
| } |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_cast_items method doesn't validate or handle the case where dbid is None or 0. The existing get_items method (lines 295-311) has a check "if dbid else []" to return an empty list for invalid dbids. Consider adding similar validation here to ensure consistent behavior and prevent unnecessary JSON-RPC calls with invalid database IDs.
| This can be used to fill Container(50) or any other container. | ||
| """ |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_cast_directory method accepts **kwargs but doesn't use them or pass them to get_cast_items. This is inconsistent with the base implementation pattern. Either remove the unused **kwargs parameter or document why it's kept for future compatibility.
| This can be used to fill Container(50) or any other container. | |
| """ | |
| This can be used to fill Container(50) or any other container. | |
| :param dbid: Database identifier for the item whose cast is being listed. | |
| :param kwargs: Accepted for API compatibility with other get_*_directory | |
| methods and reserved for future use; currently unused. | |
| """ | |
| # kwargs are intentionally unused but kept for API/interface compatibility. | |
| if kwargs: | |
| pass |
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetTVShowCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for a TV show and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['tvshowid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['tvshowid']['key'] | ||
| jrpc_id = "tvshowid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetEpisodeCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for an episode and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['episodeid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['episodeid']['key'] | ||
| jrpc_id = "episodeid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The three cast classes (ListGetMovieCast, ListGetTVShowCast, ListGetEpisodeCast) override get_directory with identical implementations. This duplicated code violates the DRY principle. Since the base class already has get_cast_directory that does exactly this, consider either removing these get_directory overrides and having users call get_cast_directory directly, or move this common implementation to the base class get_directory when dealing with cast classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@heros-os - Please address copilot comments by creating a parent class ListGetCast which the child types can inherit
| class ListGetMovieCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for a movie and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['movieid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['movieid']['key'] | ||
| jrpc_id = "movieid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetTVShowCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for a TV show and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['tvshowid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['tvshowid']['key'] | ||
| jrpc_id = "tvshowid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetEpisodeCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for an episode and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['episodeid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['episodeid']['key'] | ||
| jrpc_id = "episodeid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cast classes don't define several class attributes that are defined in the base class and other subclasses: jrpc_properties, jrpc_sublookups, item_dbtype, item_library, and container_content. While these aren't used by the overridden get_directory method, it's inconsistent with the pattern established by other subclasses (ListGetMovieDetails, ListGetTVShowDetails, etc.). Consider adding these attributes for consistency, or document why they're intentionally omitted.
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetTVShowCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for a TV show and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['tvshowid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['tvshowid']['key'] | ||
| jrpc_id = "tvshowid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') | ||
|
|
||
|
|
||
| class ListGetEpisodeCast(ListGetItemDetails): | ||
| """ | ||
| Get cast information for an episode and populate a container with cast members. | ||
| Each list item represents a cast member with name, role, and thumbnail. | ||
| """ | ||
| jrpc_method = JSON_RPC_LOOKUPS['episodeid']['method'] | ||
| jrpc_key = JSON_RPC_LOOKUPS['episodeid']['key'] | ||
| jrpc_id = "episodeid" | ||
| jrpc_idtype = int | ||
|
|
||
| def get_directory(self, dbid, **kwargs): | ||
| items = self.get_cast_items(dbid) | ||
| self.add_items(items, container_content='actors') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@heros-os - Please address copilot comments by creating a parent class ListGetCast which the child types can inherit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this file. Documentation should be done in the wiki. Too much LLM crud.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this file. Docs go in wiki
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this file. Docs go in wiki
| return [] | ||
|
|
||
| cast_items = [] | ||
| for idx, cast_member in enumerate(cast): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you enumerating. Cast is unordered in database so index position is irrelevant. Needs to be sorted by order key.
| name = cast_member.get('name', '') | ||
| role = cast_member.get('role', '') | ||
| thumbnail = cast_member.get('thumbnail', '') | ||
| order = cast_member.get('order', idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Position in database is not relevant. Order should not fallback to index.
| listitem.setProperty('thumbnail', thumbnail) | ||
|
|
||
| # Add to items list | ||
| cast_items.append(('', listitem, False)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Construction of listitem should be done in a function or class so that a list comprehension can be used.
| # Add to items list | ||
| cast_items.append(('', listitem, False)) | ||
|
|
||
| return cast_items |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
list is unordered
|
|
||
| return items | ||
|
|
||
| def get_cast_items(self, dbid): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should not be part of this class. Class is specifically a parent class for getting details about a single item. Adding another method here for cast is incorrect.
| items = self.get_items(dbid, **kwargs) | ||
| self.add_items(items, container_content=self.container_content) | ||
|
|
||
| def get_cast_directory(self, dbid, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the right place for this method. Create a separate class for getting cast instead of pinning it into the item details look up class.