Skip to content

Commit

Permalink
feat: add theme completion report
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher committed Aug 2, 2023
1 parent acad48e commit 3c9ab72
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 13 deletions.
15 changes: 7 additions & 8 deletions Contents/Code/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@
# local imports
if sys.version_info.major < 3:
from default_prefs import default_prefs
from constants import issue_url_games, issue_url_movies
from constants import contributes_to, issue_url_games, issue_url_movies
from plex_api_helper import add_themes, get_plex_item, plex_listener
from youtube_dl_helper import process_youtube
else:
from .default_prefs import default_prefs
from .constants import issue_url_games, issue_url_movies
from .constants import contributes_to, issue_url_games, issue_url_movies
from .plex_api_helper import add_themes, get_plex_item, plex_listener
from .youtube_dl_helper import process_youtube
import completion_report


def ValidatePrefs():
Expand Down Expand Up @@ -130,6 +131,9 @@ def Start():
plex_listener()
Log.Debug('plex_listener started, watching for activity from new Plex Movie agent.')

# generate report
completion_report.generate_report()


@handler(prefix='/music/themerr-plex', name='Themerr-plex', thumb='attribution.png')
def main():
Expand Down Expand Up @@ -194,12 +198,7 @@ class Themerr(Agent.Movies):
primary_provider = False
fallback_agent = False
accepts_from = []
contributes_to = [
'com.plexapp.agents.imdb',
'com.plexapp.agents.themoviedb',
# 'com.plexapp.agents.thetvdb', # not available as movie agent
'dev.lizardbyte.retroarcher-plex'
]
contributes_to = contributes_to

@staticmethod
def search(results, media, lang, manual):
Expand Down
222 changes: 222 additions & 0 deletions Contents/Code/completion_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# -*- coding: utf-8 -*-

# future imports
from __future__ import division

# standard imports
import os
import sys

# plex debugging
try:
import plexhints # noqa: F401
except ImportError:
pass
else: # the code is running outside of Plex
from plexhints.core_kit import Core # core kit
from plexhints.log_kit import Log # log kit

# imports from Libraries\Shared
from typing import Optional, Tuple

# local imports
import plex_api_helper
if sys.version_info.major < 3:
from constants import contributes_to, guid_map, issue_url_games, issue_url_movies, themerr_data_directory
from plex_api_helper import get_database_id
else:
from .constants import contributes_to, guid_map, issue_url_games, issue_url_movies, themerr_data_directory
from .plex_api_helper import get_database_id


def build_modify_button(item, database_info, btn_text):
# type: (any, Tuple[str, str], str) -> str
"""
Create the modification button for the plex item.
"""
item_agent = database_info[0]
database_id = database_info[1]

if item_agent == 'dev.lizardbyte.retroarcher-plex':
issue_url = issue_url_games
elif item_agent in contributes_to:
issue_url = issue_url_movies
else:
issue_url = None

modify_button = ""

if issue_url:
issue_title = '%s (%s)' % (item.title, item.year)
item_issue_url = issue_url % (issue_title, database_id)

if database_id:
modify_button = '<a href="{0}" class="btn btn-info" role="button">{1}</a>'.format(item_issue_url, btn_text)

return modify_button


def generate_report():
"""
Generate a report with the theme song completion status of all items in the library.
"""
# get all Plex items from supported metadata agents
plex_server = plex_api_helper.setup_plexapi()
plex_library = plex_server.library
Log.Debug('plex_library: %s' % plex_library)

sections = plex_library.sections()
Log.Debug('sections: %s' % sections)

html = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Themerr-plex completion report</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://app.lizardbyte.dev/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://app.lizardbyte.dev/css/custom.css">
</head>
<body>
<!-- Bootstrap JS -->
<script src="https://app.lizardbyte.dev/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<div class="container">
"""
for section in sections:
if section.agent not in contributes_to:
# todo - there is a small chance that a library with an unsupported agent could still have
# a individual items that was matched with a supported agent...
continue # skip unsupported metadata agents

# get all items in the section
all_items = section.all()
Log.Debug('section count items: %s' % len(all_items))

# get all items in the section with theme songs
items_with_themes = section.all(theme__exists=True)
Log.Debug('section count items with themes: %s' % len(items_with_themes))

# add each section to a html report
# todo - fix me up ... maybe add this to the attribution text?
html += """
<div class="row">
<div class="col-12">
<h1>{0}</h1>
</div>
</div>
""".format(section.title)

# add a percent completion gauge to the report
percent_complete = int(len(items_with_themes) / len(all_items) * 100) if len(items_with_themes) else 0
if percent_complete == 100:
progress_color = 'bg-success'
btn_color = 'btn-success'
elif percent_complete > 50:
progress_color = 'bg-warning'
btn_color = 'btn-warning'
else:
progress_color = 'bg-danger'
btn_color = 'btn-warning'
html += """
<div class="row">
<div class="col-12">
<div class="progress">
<div class="progress-bar {0}" role="progressbar" style="width: {1}%" aria-valuenow="{1}"
aria-valuemin="0" aria-valuemax="100">{1}%</div>
</div>
</div>
</div>
""".format(progress_color, percent_complete)

if items_with_themes:
html += """
<div class="row">
<div class="col-12">
<button class="btn {0}" type="button" data-bs-toggle="collapse" data-bs-target="#{1}_complete_collapse"
aria-expanded="false" aria-controls="{1}_complete_collapse">
Completed
</button>
<div class="collapse" id="{1}_complete_collapse">
<table class="table table-bordered caption-top">
<caption>Items with theme songs</caption>
<tr>
<th>Item Name</th>
<th>Year</th>
<th>Edit in ThemerrDB</th>
</tr>
""".format('btn-success', section.title)

for item in items_with_themes:
database_info = get_database_id(item=item)
modify_button = build_modify_button(item=item, database_info=database_info, btn_text='Edit')
html += """
<tr>
<td>{0}</td>
<td>{1}</td>
<td>{2}</td>
</tr>
""".format(item.title, item.year, modify_button)

html += """
</table>
</div>
</div>
</div>
"""

# use list comprehension to get all items without theme songs
items_without_themes = [item for item in all_items if item not in items_with_themes]

if items_without_themes:
html += """
<div class="row">
<div class="col-12">
<button class="btn {0}" type="button" data-bs-toggle="collapse" data-bs-target="#{1}_missing_collapse"
aria-expanded="false" aria-controls="{1}_missing_collapse">
Missing
</button>
<div class="collapse show" id="{1}_missing_collapse">
<table class="table table-bordered caption-top">
<caption>Items missing theme songs</caption>
<tr>
<th>Item Name</th>
<th>Year</th>
<th>Add to ThemerrDB</th>
</tr>
""".format(btn_color, section.title)

for item in items_without_themes:
database_info = get_database_id(item=item)
modify_button = build_modify_button(item=item, database_info=database_info, btn_text='Add')
html += """
<tr>
<td>{0}</td>
<td>{1}</td>
<td>{2}</td>
</tr>
""".format(item.title, item.year, modify_button)

html += """
</table>
</div>
</div>
</div>
"""

# complete html
html += """
</div>
</body>
</html>
"""

# write the report to a file
report_file = os.path.join(themerr_data_directory, 'themerr-completion-report.html')
Core.storage.save(filename=report_file, data=html, binary=False)
27 changes: 27 additions & 0 deletions Contents/Code/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
# -*- coding: utf-8 -*-

# standard imports
import os

# plex debugging
try:
import plexhints # noqa: F401
except ImportError:
pass
else: # the code is running outside of Plex
from plexhints.core_kit import Core # core kit

app_support_directory = Core.app_support_path
plugin_identifier = 'dev.lizardbyte.themerr-plex'
plugin_support_directory = os.path.join(app_support_directory, 'Plug-in Support')
plugin_support_data_directory = os.path.join(plugin_support_directory, 'Data')
themerr_data_directory = os.path.join(plugin_support_data_directory, plugin_identifier, 'DataItems')

contributes_to = [
'tv.plex.agents.movie',
'com.plexapp.agents.imdb',
'com.plexapp.agents.themoviedb',
# 'com.plexapp.agents.thetvdb', # not available as movie agent
'dev.lizardbyte.retroarcher-plex'
]

guid_map = dict(
imdb='imdb',
tmdb='themoviedb',
Expand Down
51 changes: 47 additions & 4 deletions Contents/Code/plex_api_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# imports from Libraries\Shared
from future.moves import queue
import requests
from typing import Optional
from typing import Optional, Tuple
import urllib3
from urllib3.exceptions import InsecureRequestWarning
from plexapi.alert import AlertListener
Expand All @@ -32,10 +32,10 @@

# local imports
if sys.version_info.major < 3:
from constants import guid_map, issue_url_movies
from constants import app_support_directory, guid_map, issue_url_movies
from youtube_dl_helper import process_youtube
else:
from .constants import guid_map, issue_url_movies
from .constants import app_support_directory, guid_map, issue_url_movies
from .youtube_dl_helper import process_youtube

plex = None
Expand All @@ -45,7 +45,6 @@
processing_completed = []

# constants
app_support_directory = Core.app_support_path
metadata_movie_directory = os.path.join(app_support_directory, 'Metadata', 'Movies')


Expand Down Expand Up @@ -234,6 +233,50 @@ def upload_theme(plex_item, filepath=None, url=None):
return False


def get_database_id(item):
# type: (any) -> Tuple[Optional[str], Optional[str]]
agent = None
database_id = None
imdb_id = None # if this gets set we need to do additional processing

if item.guids: # guids is a blank list for items from legacy agents, only available for new agent items
agent = 'tv.plex.agents.movie'
for guid in item.guids:
split_guid = guid.id.split('://')
database = guid_map[split_guid[0]]
database_id = split_guid[1]

if database == 'igdb':
imdb_id = database_id
database_id = None

if database == 'themoviedb':
imdb_id = None # reset this as we won't need to process it
break
elif item.guid:
split_guid = item.guid.split('://')
agent = split_guid[0]
if agent == 'dev.lizardbyte.retroarcher-plex':
# dev.lizardbyte.retroarcher-plex://{igdb-1638}{platform-4}{(USA)}?lang=en
database_id = item.guid.split('igdb-')[1].split('}')[0]
elif agent == 'com.plexapp.agents.themoviedb':
# com.plexapp.agents.themoviedb://363088?lang=en
database_id = item.guid.split('://')[1].split('?')[0]
elif agent == 'com.plexapp.agents.imdb':
# com.plexapp.agents.imdb://tt0113189?lang=en
imdb_id = item.guid.split('://')[1].split('?')[0]

if imdb_id:
themerr_url = 'https://app.lizardbyte.dev/ThemerrDB/%s/%s/%s.json' % ('movies', 'imdb', imdb_id)
themerr_response = requests.get(url=themerr_url)

if themerr_response.status_code == requests.codes.ok:
themerr_json = themerr_response.json()
database_id = themerr_json['id']

return agent, database_id


def get_plex_item(rating_key):
# type: (int) -> any
"""
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Themerr-plex is a metadata agent plug-in for Plex Media Player. The plug-in adds

This plugin contributes to the following metadata agents.

- Plex Movie
- Plex Movie - `tv.plex.agents.movie`
- Plex Movie (Legacy) - `com.plexapp.agents.imdb`
- The Movie Database - `com.plexapp.agents.themoviedb`
- `RetroArcher <https://github.com/LizardByte/RetroArcher-plex>`_ - `dev.lizardbyte.retroarcher-plex`
Expand Down

0 comments on commit 3c9ab72

Please sign in to comment.