mirror of
https://github.com/meisnate12/Plex-Meta-Manager
synced 2024-11-26 14:30:25 +00:00
[46] add letterboxd filters
This commit is contained in:
parent
4928a25b71
commit
534eda26dc
6 changed files with 74 additions and 18 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
1.16.2-develop45
|
1.16.2-develop46
|
||||||
|
|
|
@ -35,3 +35,21 @@ collections:
|
||||||
collection_order: custom
|
collection_order: custom
|
||||||
sync_mode: sync
|
sync_mode: sync
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can add 3 different filters directly to this builder.
|
||||||
|
|
||||||
|
| Filter Attribute | Description |
|
||||||
|
|:-----------------|:---------------------------------------------------------------------------------------------------|
|
||||||
|
| `rating` | **Description:** Search for the specified rating range<br>**Values:** range of int i.e. `80-100` |
|
||||||
|
| `year` | **Description:** Search for the specified year range<br>**Values:** range of int i.e. `1990-1999` |
|
||||||
|
| `note` | **Description:** Search for the specified value in the note<br>**Values:** Any String |
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
Vulture’s 101 Best Movie Endings From the 90s:
|
||||||
|
letterboxd_list_details:
|
||||||
|
url: https://letterboxd.com/brianformo/list/vultures-101-best-movie-endings/
|
||||||
|
year: 1990-1999
|
||||||
|
collection_order: custom
|
||||||
|
sync_mode: sync
|
||||||
|
```
|
|
@ -1084,11 +1084,11 @@ class CollectionBuilder:
|
||||||
|
|
||||||
def _letterboxd(self, method_name, method_data):
|
def _letterboxd(self, method_name, method_data):
|
||||||
if method_name.startswith("letterboxd_list"):
|
if method_name.startswith("letterboxd_list"):
|
||||||
letterboxd_lists = self.config.Letterboxd.validate_letterboxd_lists(method_data, self.language)
|
letterboxd_lists = self.config.Letterboxd.validate_letterboxd_lists(self.Type, method_data, self.language)
|
||||||
for letterboxd_list in letterboxd_lists:
|
for letterboxd_list in letterboxd_lists:
|
||||||
self.builders.append(("letterboxd_list", letterboxd_list))
|
self.builders.append(("letterboxd_list", letterboxd_list))
|
||||||
if method_name.endswith("_details"):
|
if method_name.endswith("_details"):
|
||||||
self.summaries[method_name] = self.config.Letterboxd.get_list_description(letterboxd_lists[0], self.language)
|
self.summaries[method_name] = self.config.Letterboxd.get_list_description(letterboxd_lists[0]["url"], self.language)
|
||||||
|
|
||||||
def _mal(self, method_name, method_data):
|
def _mal(self, method_name, method_data):
|
||||||
if method_name == "mal_id":
|
if method_name == "mal_id":
|
||||||
|
@ -2575,7 +2575,7 @@ class CollectionBuilder:
|
||||||
items = self.library.get_filter_items(search_data[2])
|
items = self.library.get_filter_items(search_data[2])
|
||||||
previous = None
|
previous = None
|
||||||
for i, item in enumerate(items, 0):
|
for i, item in enumerate(items, 0):
|
||||||
if len(self.items) <= i or item.ratingKey != self.items[i]:
|
if len(self.items) <= i or item.ratingKey != self.items[i].ratingKey:
|
||||||
text = f"after {util.item_title(previous)}" if previous else "to the beginning"
|
text = f"after {util.item_title(previous)}" if previous else "to the beginning"
|
||||||
logger.info(f"Moving {util.item_title(item)} {text}")
|
logger.info(f"Moving {util.item_title(item)} {text}")
|
||||||
self.library.moveItem(self.obj, item, previous)
|
self.library.moveItem(self.obj, item, previous)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import time
|
import re, time
|
||||||
from modules import util
|
from modules import util
|
||||||
from modules.util import Failed
|
from modules.util import Failed
|
||||||
|
|
||||||
|
@ -20,6 +20,16 @@ class Letterboxd:
|
||||||
for letterboxd_id in letterboxd_ids:
|
for letterboxd_id in letterboxd_ids:
|
||||||
slugs = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/@data-film-slug")
|
slugs = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/@data-film-slug")
|
||||||
items.append((letterboxd_id, slugs[0]))
|
items.append((letterboxd_id, slugs[0]))
|
||||||
|
slugs = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/@data-film-slug")
|
||||||
|
notes = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']/div/p/text()")
|
||||||
|
ratings = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']//span[contains(@class, 'rating')]/@class")
|
||||||
|
years = response.xpath(f"//div[@data-film-id='{letterboxd_id}']/parent::li/div[@class='film-detail-content']/h2/small/a/text()")
|
||||||
|
rating = None
|
||||||
|
if ratings:
|
||||||
|
match = re.search("rated-(\\d+)", ratings[0])
|
||||||
|
if match:
|
||||||
|
rating = int(match.group(1))
|
||||||
|
items.append((letterboxd_id, slugs[0], int(years[0]) if years else None, notes[0] if notes else None, rating))
|
||||||
next_url = response.xpath("//a[@class='next']/@href")
|
next_url = response.xpath("//a[@class='next']/@href")
|
||||||
if len(next_url) > 0:
|
if len(next_url) > 0:
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
@ -44,27 +54,50 @@ class Letterboxd:
|
||||||
descriptions = response.xpath("//meta[@property='og:description']/@content")
|
descriptions = response.xpath("//meta[@property='og:description']/@content")
|
||||||
return descriptions[0] if len(descriptions) > 0 and len(descriptions[0]) > 0 else None
|
return descriptions[0] if len(descriptions) > 0 and len(descriptions[0]) > 0 else None
|
||||||
|
|
||||||
def validate_letterboxd_lists(self, letterboxd_lists, language):
|
def validate_letterboxd_lists(self, err_type, letterboxd_lists, language):
|
||||||
valid_lists = []
|
valid_lists = []
|
||||||
for letterboxd_list in util.get_list(letterboxd_lists, split=False):
|
for letterboxd_dict in util.get_list(letterboxd_lists, split=False):
|
||||||
list_url = letterboxd_list.strip()
|
if not isinstance(letterboxd_dict, dict):
|
||||||
if not list_url.startswith(base_url):
|
letterboxd_dict = {"url": letterboxd_dict}
|
||||||
raise Failed(f"Letterboxd Error: {list_url} must begin with: {base_url}")
|
dict_methods = {dm.lower(): dm for dm in letterboxd_dict}
|
||||||
elif len(self._parse_list(list_url, language)) > 0:
|
final = {
|
||||||
valid_lists.append(list_url)
|
"url": util.parse(err_type, "url", letterboxd_dict, methods=dict_methods, parent="letterboxd_list").strip(),
|
||||||
else:
|
"note": util.parse(err_type, "note", letterboxd_dict, methods=dict_methods, parent="letterboxd_list") if "note" in dict_methods else None,
|
||||||
raise Failed(f"Letterboxd Error: {list_url} failed to parse")
|
"rating": util.parse(err_type, "rating", letterboxd_dict, methods=dict_methods, datatype="int", parent="letterboxd_list", maximum=100, range_split="-") if "rating" in dict_methods else None,
|
||||||
|
"year": util.parse(err_type, "year", letterboxd_dict, methods=dict_methods, datatype="int", parent="letterboxd_list", minimum=1000, maximum=3000, range_split="-") if "year" in dict_methods else None
|
||||||
|
}
|
||||||
|
if not final["url"].startswith(base_url):
|
||||||
|
raise Failed(f"{err_type} Error: {final['url']} must begin with: {base_url}")
|
||||||
|
elif not self._parse_list(final["url"], language):
|
||||||
|
raise Failed(f"{err_type} Error: {final['url']} failed to parse")
|
||||||
|
valid_lists.append(final)
|
||||||
return valid_lists
|
return valid_lists
|
||||||
|
|
||||||
def get_tmdb_ids(self, method, data, language):
|
def get_tmdb_ids(self, method, data, language):
|
||||||
if method == "letterboxd_list":
|
if method == "letterboxd_list":
|
||||||
logger.info(f"Processing Letterboxd List: {data}")
|
logger.info(f"Processing Letterboxd List: {data}")
|
||||||
items = self._parse_list(data, language)
|
items = self._parse_list(data["url"], language)
|
||||||
total_items = len(items)
|
total_items = len(items)
|
||||||
if total_items > 0:
|
if total_items > 0:
|
||||||
ids = []
|
ids = []
|
||||||
|
filtered_ids = []
|
||||||
for i, item in enumerate(items, 1):
|
for i, item in enumerate(items, 1):
|
||||||
letterboxd_id, slug = item
|
letterboxd_id, slug, year, note, rating = item
|
||||||
|
filtered = False
|
||||||
|
if data["year"]:
|
||||||
|
start_year, end_year = data["year"].split("-")
|
||||||
|
if not year or int(end_year) < year or year < int(start_year):
|
||||||
|
filtered = True
|
||||||
|
if data["rating"]:
|
||||||
|
start_rating, end_rating = data["rating"].split("-")
|
||||||
|
if not rating or int(end_rating) < rating or rating < int(start_rating):
|
||||||
|
filtered = True
|
||||||
|
if data["note"]:
|
||||||
|
if not note or data["note"] not in note:
|
||||||
|
filtered = True
|
||||||
|
if filtered:
|
||||||
|
filtered_ids.append(slug)
|
||||||
|
continue
|
||||||
logger.ghost(f"Finding TMDb ID {i}/{total_items}")
|
logger.ghost(f"Finding TMDb ID {i}/{total_items}")
|
||||||
tmdb_id = None
|
tmdb_id = None
|
||||||
expired = None
|
expired = None
|
||||||
|
@ -80,6 +113,8 @@ class Letterboxd:
|
||||||
self.config.Cache.update_letterboxd_map(expired, letterboxd_id, tmdb_id)
|
self.config.Cache.update_letterboxd_map(expired, letterboxd_id, tmdb_id)
|
||||||
ids.append((tmdb_id, "tmdb"))
|
ids.append((tmdb_id, "tmdb"))
|
||||||
logger.info(f"Processed {total_items} TMDb IDs")
|
logger.info(f"Processed {total_items} TMDb IDs")
|
||||||
|
if filtered_ids:
|
||||||
|
logger.info(f"Filtered: {filtered_ids}")
|
||||||
return ids
|
return ids
|
||||||
else:
|
else:
|
||||||
raise Failed(f"Letterboxd Error: No List Items found in {data}")
|
raise Failed(f"Letterboxd Error: No List Items found in {data}")
|
||||||
|
|
|
@ -521,8 +521,11 @@ class MetadataFile(DataFile):
|
||||||
"name": template_name,
|
"name": template_name,
|
||||||
"value": other_keys,
|
"value": other_keys,
|
||||||
auto_type: other_keys,
|
auto_type: other_keys,
|
||||||
"key_name": str(map_name), "key": str(map_name)
|
"key_name": other_name, "key": "other"
|
||||||
}
|
}
|
||||||
|
for k, v in template_variables.items():
|
||||||
|
if "other" in v:
|
||||||
|
template_call[k] = v["other"]
|
||||||
col = {"template": template_call, "label": str(map_name)}
|
col = {"template": template_call, "label": str(map_name)}
|
||||||
if test:
|
if test:
|
||||||
col["test"] = True
|
col["test"] = True
|
||||||
|
|
|
@ -860,7 +860,7 @@ class Plex(Library):
|
||||||
self.query_data(getattr(obj, f"remove{attr_call}"), _remove)
|
self.query_data(getattr(obj, f"remove{attr_call}"), _remove)
|
||||||
display += f"-{', -'.join(_remove)}"
|
display += f"-{', -'.join(_remove)}"
|
||||||
final = f"{obj.title[:25]:<25} | {attr_display} | {display}" if display else display
|
final = f"{obj.title[:25]:<25} | {attr_display} | {display}" if display else display
|
||||||
if do_print:
|
if do_print and final:
|
||||||
logger.info(final)
|
logger.info(final)
|
||||||
return final
|
return final
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue