Created
July 11, 2021 01:08
-
-
Save DavidBouw/8c23453e2cda0ead714335cab68d6e14 to your computer and use it in GitHub Desktop.
Automatically create an IMDB Top 250 or Letterboxd Top 250 collection in Plex using an existing movie library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
tt6751668 | tt0091251 | tt0068646 | tt0056058 | tt0071562 | tt0047478 | tt0050083 | tt0271383 | tt0055233 | tt0245429 | tt0057565 | tt0101985 | tt0111161 | tt0244316 | tt8613070 | tt4633694 | tt0053114 | tt0468569 | tt0099685 | tt0140888 | tt0108052 | tt0080684 | tt0044741 | tt0060196 | tt0079944 | tt0111341 | tt0469494 | tt0019254 | tt0060827 | tt0317248 | tt0167260 | tt0043014 | tt0060107 | tt0058625 | tt0169858 | tt0046438 | tt0078788 | tt0089881 | tt0118694 | tt0110912 | tt4016934 | tt0050825 | tt0053115 | tt0095327 | tt0113247 | tt0097216 | tt2582802 | tt0062622 | tt0100234 | tt0047396 | tt0083922 | tt0052572 | tt0087884 | tt0054407 | tt0119698 | tt0054215 | tt0102926 | tt6725014 | tt0056322 | tt0095765 | tt0072417 | tt0077711 | tt0053604 | tt0089603 | tt0047445 | tt0064116 | tt0156887 | tt0048473 | tt0081505 | tt0120737 | tt0112471 | tt0048452 | tt0078748 | tt0156794 | tt0084787 | tt0364569 | tt2396224 | tt0054042 | tt0381681 | tt0038650 | tt0072443 | tt0040725 | tt0021749 | tt0073486 | tt0167261 | tt0072684 | tt0249241 | tt0353969 | tt0050634 | tt0075404 | tt0050976 | tt0050783 | tt0041154 | tt0477348 | tt0056801 | tt0022100 | tt0361748 | tt0058946 | tt0045152 | tt0015324 | tt0063794 | tt1128075 | tt0058604 | tt0053198 | tt0040522 | tt0114369 | tt0049902 | tt0137523 | tt1255953 | tt0064040 | tt0042192 | tt0109424 | tt0346336 | tt0056172 | tt0075314 | tt0034583 | tt0057012 | tt3742378 | tt1832382 | tt3612616 | tt0050986 | tt0027977 | tt0037674 | tt0111495 | tt0055630 | tt0073198 | tt0018192 | tt0076759 | tt0091670 | tt0096288 | tt10272386 | tt0048424 | tt0033467 | tt0110357 | tt0058888 | tt0076085 | tt0046268 | tt0116282 | tt0032553 | tt0053779 | tt0037558 | tt0064068 | tt1087578 | tt0092048 | tt0347149 | tt0088763 | tt0054248 | tt0071315 | tt0062873 | tt0048956 | tt0041959 | tt0253474 | tt0057277 | tt0052357 | tt0206634 | tt0035446 | tt0093191 | tt0338013 | tt0075793 | tt0103064 | tt0036112 | tt0093342 | tt4975722 | tt0072890 | tt0086879 | tt0087843 | tt0054130 | tt8020896 | tt0081398 | tt0017136 | tt5311514 | tt0018455 | tt2380307 | tt0056444 | tt8075192 | tt0166924 | tt0065234 | tt0101640 | tt0070510 | tt0046478 | tt0042804 | tt0114709 | tt0086022 | tt0056512 | tt0051036 | tt0029192 | tt0038733 | tt0082971 | tt0096283 | tt0063278 | tt0094625 | tt0407887 | tt0069293 | tt2278388 | tt0042876 | tt0036775 | tt0118799 | tt0050613 | tt0040897 | tt0079672 | tt0051201 | tt0078754 | tt10633456 | tt0043313 | tt1375666 | tt3281548 | tt0073363 | tt0045274 | tt2106476 | tt0408664 | tt0048021 | tt1392190 | tt0117214 | tt0050371 | tt0062229 | tt1827487 | tt4468740 | tt0074958 | tt0105888 | tt0066921 | tt0043338 | tt0118749 | tt0120815 | tt0057358 | tt0129167 | tt0063522 | tt0119217 | tt0051093 | tt5052448 | tt0120265 | tt0055852 | tt0144782 | tt0061847 | tt0028950 | tt1954470 | tt0457430 | tt0042593 | tt0114787 | tt3153634 | tt0097223 | tt0061184 | tt0059527 | tt0061065 | tt0082912 | tt0053291 | tt0113277 | tt0243889 | tt6390668 | tt0066993 | tt8413338 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parasite | Come and See | The Godfather | Harakiri | The Godfather: Part II | Seven Samurai | 12 Angry Men | A Dog's Will | The Human Condition III: A Soldier's Prayer | Spirited Away | High and Low | A Brighter Summer Day | The Shawshank Redemption | Yi Yi | Portrait of a Lady on Fire | Spider-Man: Into the Spider-Verse | The Human Condition I: No Greater Love | The Dark Knight | GoodFellas | Central Station | Schindler's List | The Empire Strikes Back | Ikiru | The Good, the Bad and the Ugly | Stalker | Satantango | There Will Be Blood | The Passion of Joan of Arc | Persona | City of God | The Lord of the Rings: The Return of the King | Sunset Boulevard | Andrei Rublev | Woman in the Dunes | Neon Genesis Evangelion: The End of Evangelion | Tokyo Story | Apocalypse Now | Ran | In the Mood for Love | Pulp Fiction | The Handmaiden | Paths of Glory | The Human Condition II: Road to Eternity | Grave of the Fireflies | La Haine | Do the Right Thing | Whiplash | 2001: A Space Odyssey | Close-Up | Rear Window | Fanny and Alexander | The World of Apu | Paris, Texas | Le Trou | Princess Mononoke | Psycho | The Silence of the Lambs | Scenes from a Marriage | The Given Word | Cinema Paradiso | A Woman Under the Influence | Autumn Sonata | The Apartment | Mishima: A Life in Four Chapters | Sansho the Bailiff | Once Upon a Time in the West | Perfect Blue | Pather Panchali | The Shining | The Lord of the Rings: The Fellowship of the Ring | Before Sunrise | Ordet | Alien | Eternity and a Day | The Thing | Oldboy | It's Such a Beautiful Day | Macario | Before Sunset | It's a Wonderful Life | Mirror | The Red Shoes | City Lights | One Flew Over the Cuckoo's Nest | The Lord of the Rings: The Two Towers | Barry Lyndon | Werckmeister Harmonies | Memories of Murder | The Cranes Are Flying | The Ascent | The Seventh Seal | Nights of Cabiria | Late Spring | No Country for Old Men | 8½ | M | Inglourious Basterds | The Battle of Algiers | Singin' in the Rain | Sherlock, Jr. | War and Peace | Love Exposure | I Am Cuba | The 400 Blows | Bicycle Thieves | Se7en | A Man Escaped | Fight Club | Incendies | Army of Shadows | All About Eve | Chungking Express | The Best of Youth | Lawrence of Arabia | Taxi Driver | Casablanca | Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb | The Second Mother | A Separation | Mommy | Wild Strawberries | Modern Times | Children of Paradise | Three Colors: Red | Yojimbo | Jeanne Dielman, 23, Quai du Commerce 1080 Bruxelles | Napoleon | Star Wars | The Sacrifice | Landscape in the Mist | The Father | The Night of the Hunter | Citizen Kane | The Lion King | Red Beard | A Special Day | The Wages of Fear | Fargo | The Great Dictator | La Dolce Vita | Brief Encounter | Funeral Parade of Roses | Still Walking | Tampopo | Howl's Moving Castle | Back to the Future | Rocco and His Brothers | Chinatown | The Young Girls of Rochefort | Aparajito | The Third Man | The Pianist | The Big City | Vertigo | Children of Men | To Be or Not to Be | Wings of Desire | Eternal Sunshine of the Spotless Mind | We All Loved Each Other So Much | Terminator 2: Judgment Day | The Life and Death of Colonel Blimp | Where Is My Friend's House? | Moonlight | Dog Day Afternoon | Amadeus | Once Upon a Time in America | La Notte | An Elephant Sitting Still | Raging Bull | Metropolis | Your Name. | Sunrise: A Song of Two Humans | Coco | An Autumn Afternoon | Shoplifters | Mulholland Drive | Z | Raise the Red Lantern | Paper Moon | Ugetsu | The Young and the Damned | Toy Story | Nostalgia | Il Sorpasso | Sweet Smell of Success | Make Way for Tomorrow | A Matter of Life and Death | Raiders of the Lost Ark | My Neighbor Totoro | Marketa Lazarová | Akira | The Departed | Solaris | The Grand Budapest Hotel | Rashomon | Double Indemnity | Life Is Beautiful | Throne of Blood | The Treasure of the Sierra Madre | Opening Night | Witness for the Prosecution | All That Jazz | Minari | Early Summer | Inception | Little Women | Manila in the Claws of Light | Umberto D. | The Hunt | Nobody Knows | Rififi | Mad Max: Fury Road | A Moment of Innocence | A Face in the Crowd | Le Samouraï | Once Upon a Time in Anatolia | Paddington 2 | Network | Life, and Nothing More... | A Clockwork Orange | Ace in the Hole | Boogie Nights | Saving Private Ryan | Winter Light | The Iron Giant | Rosemary's Baby | Good Will Hunting | Tokyo Twilight | Get Out | Taste of Cherry | Cléo from 5 to 7 | The Red Light Bandit | Samurai Rebellion | Grand Illusion | Gangs of Wasseypur - Part 2 | Pan's Labyrinth | In a Lonely Place | Underground | Hope | Time of the Gypsies | Who's Afraid of Virginia Woolf? | The Shop on Main Street | The Face of Another | Pixote | Some Like It Hot | Heat | Eureka | Invisible Life | The Devils | Kumbalangi Nights | |
2019 | 1985 | 1972 | 1962 | 1974 | 1954 | 1957 | 2000 | 1961 | 2001 | 1963 | 1991 | 1994 | 2000 | 2019 | 2018 | 1959 | 2008 | 1990 | 1998 | 1993 | 1980 | 1952 | 1966 | 1979 | 1994 | 2007 | 1928 | 1966 | 2002 | 2003 | 1950 | 1966 | 1964 | 1997 | 1953 | 1979 | 1985 | 2000 | 1994 | 2016 | 1957 | 1959 | 1988 | 1995 | 1989 | 2014 | 1968 | 1990 | 1954 | 1982 | 1959 | 1984 | 1960 | 1997 | 1960 | 1991 | 1974 | 1962 | 1988 | 1974 | 1978 | 1960 | 1985 | 1954 | 1968 | 1997 | 1955 | 1980 | 2001 | 1995 | 1955 | 1979 | 1998 | 1982 | 2003 | 2012 | 1960 | 2004 | 1946 | 1975 | 1948 | 1931 | 1975 | 2002 | 1975 | 2000 | 2003 | 1957 | 1977 | 1957 | 1957 | 1949 | 2007 | 1963 | 1931 | 2009 | 1966 | 1952 | 1924 | 1966 | 2008 | 1964 | 1959 | 1948 | 1995 | 1956 | 1999 | 2010 | 1969 | 1950 | 1994 | 2003 | 1962 | 1976 | 1942 | 1964 | 2015 | 2011 | 2014 | 1957 | 1936 | 1945 | 1994 | 1961 | 1975 | 1927 | 1977 | 1986 | 1988 | 2020 | 1955 | 1941 | 1994 | 1965 | 1977 | 1953 | 1996 | 1940 | 1960 | 1945 | 1969 | 2008 | 1985 | 2004 | 1985 | 1960 | 1974 | 1967 | 1956 | 1949 | 2002 | 1963 | 1958 | 2006 | 1942 | 1987 | 2004 | 1974 | 1991 | 1943 | 1987 | 2016 | 1975 | 1984 | 1984 | 1961 | 2018 | 1980 | 1927 | 2016 | 1927 | 2017 | 1962 | 2018 | 2001 | 1969 | 1991 | 1973 | 1953 | 1950 | 1995 | 1983 | 1962 | 1957 | 1937 | 1946 | 1981 | 1988 | 1967 | 1988 | 2006 | 1972 | 2014 | 1950 | 1944 | 1997 | 1957 | 1948 | 1977 | 1957 | 1979 | 2020 | 1951 | 2010 | 2019 | 1975 | 1952 | 2012 | 2004 | 1955 | 2015 | 1996 | 1957 | 1967 | 2011 | 2017 | 1976 | 1992 | 1971 | 1951 | 1997 | 1998 | 1963 | 1999 | 1968 | 1997 | 1957 | 2017 | 1997 | 1962 | 1968 | 1967 | 1937 | 2012 | 2006 | 1950 | 1995 | 2013 | 1988 | 1966 | 1965 | 1966 | 1981 | 1959 | 1995 | 2000 | 2019 | 1971 | 2019 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------------------------------------ | |
# | |
# Automated IMDB Top 250 Plex collection script inspired by /u/SwiftPanda16 | |
# Set Secure Connections to Preferred or this will not work | |
# *** Use at your own risk! *** | |
# *** I am not responsible for damages to your Plex server or libraries. *** | |
# | |
#------------------------------------------------------------------------------ | |
import json | |
import requests | |
import time | |
import shutil | |
import sys | |
import csv | |
import os | |
from lxml import html | |
from plexapi.server import PlexServer | |
### Plex server details ### | |
# Make sure that under Network settings you have Secure connections set to Preferred or Disabled | |
PLEX_URL = 'http://localhost:32400' | |
PLEX_TOKEN = 'xxxxxxxxxx' | |
### Existing movie library details ### | |
MOVIE_LIBRARY_NAME = 'Movies' | |
### New IMDB Top 250 library details ### | |
IMDB_CHART_URL = 'http://www.imdb.com/chart/top' | |
LETTERBOXD_CHART_URL = 'https://letterboxd.com/dave/list/official-top-250-narrative-feature-films/' | |
LETTERBOXD_URL = 'https://letterboxd.com' | |
IMDB_COLLECTION_NAME = 'IMDB Top 250' | |
LETTERBOXD_COLLECTION_NAME = 'Letterboxd Official Top 250 Narrative Feature Films' | |
### The Movie Database details ### | |
# Enter your TMDb API key if your movie library is using "The Movie Database" agent. | |
# This will be used to convert the TMDb IDs to IMDB IDs. | |
# You can leave this blank '' if your movie library is using the "Plex Movie" agent. | |
TMDB_API_KEY = '' | |
##### CODE BELOW ##### | |
TMDB_REQUEST_COUNT = 0 # DO NOT CHANGE | |
def add_collection(library_key, rating_key, collection_name): | |
headers = {"X-Plex-Token": PLEX_TOKEN} | |
params = {"type": 1, | |
"id": rating_key, | |
"collection[0].tag.tag": collection_name, | |
"collection.locked": 1 | |
} | |
url = "{base_url}/library/sections/{library}/all".format(base_url=PLEX_URL, library=library_key) | |
r = requests.put(url, headers=headers, params=params) | |
def remove_collection(library_key, rating_key, collection_name): | |
headers = {"X-Plex-Token": PLEX_TOKEN} | |
params = {"type": 1, | |
"id": rating_key, | |
"collection[].tag.tag-": collection_name | |
} | |
url = "{base_url}/library/sections/{library}/all".format(base_url=PLEX_URL, library=library_key) | |
r = requests.put(url, headers=headers, params=params) | |
def get_imdb_id_from_tmdb(tmdb_id): | |
global TMDB_REQUEST_COUNT | |
if not TMDB_API_KEY: | |
return None | |
# Wait 10 seconds for the TMDb rate limit | |
if TMDB_REQUEST_COUNT >= 40: | |
time.sleep(10) | |
TMDB_REQUEST_COUNT = 0 | |
params = {"api_key": TMDB_API_KEY} | |
url = "https://api.themoviedb.org/3/movie/{tmdb_id}".format(tmdb_id=tmdb_id) | |
r = requests.get(url, params=params) | |
TMDB_REQUEST_COUNT += 1 | |
if r.status_code == 200: | |
movie = json.loads(r.text) | |
return movie['imdb_id'] | |
else: | |
return None | |
def get_imdb_id_from_letterboxd(url): | |
### Retrieve IMDB data from Letterboxd movie page ### | |
r = requests.get(url) | |
tree = html.fromstring(r.content) | |
movie_title = tree.xpath("//div[contains(@class, 'react-component film-poster')]/@data-film-name")[0] | |
movie_year = tree.xpath("//div[contains(@class, 'react-component film-poster')]/@data-film-release-year")[0] | |
try: | |
imdb_url = tree.xpath("//p[@class='text-link text-footer']//a[@data-track-action='IMDb']/@href") | |
imdb_id = imdb_url[0].rsplit('/', 2)[-2] | |
except: | |
# tmdb_url = tree.xpath("//p[@class='text-link text-footer']//a[@data-track-action='TMDb']/@href") | |
# tmdb_id = tmdb_url[0].rsplit('/', 2)[-2] | |
# Gangs of Wasseypur is one combined film on IMDB but is two separate on Letterboxd | |
if movie_title == "Gangs of Wasseypur - Part 2": | |
imdb_id = "tt1954470" | |
else: | |
imdb_id = 0 | |
return movie_title,movie_year,imdb_id | |
def letterboxd_top_250(library_language): | |
### Get the Letterboxd Top 250 List ### | |
print("Retrieving the Letterboxd Official Top 250 Narrative Feature Films list...") | |
os.chdir(os.path.dirname(os.path.abspath(__file__))) | |
top_250_titles,top_250_years,top_250_ids = [],[],[] | |
if os.path.isfile('top_250.csv'): | |
refresh = input("Stored Letterboxd Top 250 exists. Do you want to force a refresh? (y/n): ") | |
if refresh == 'n': | |
csv_read_data = {} | |
with open('top_250.csv', 'r') as csv_file: | |
csv_reader = csv.reader(csv_file, delimiter=',') | |
for i, row in enumerate(csv_reader): | |
csv_read_data[i] = row | |
top_250_ids = csv_read_data[0] | |
top_250_titles = csv_read_data[1] | |
top_250_years = csv_read_data[2] | |
if refresh == 'y' or not os.path.isfile('top_250.csv'): | |
print("Please be patient. This will take longer than creating the IMDB Top 250 list.") | |
print() | |
page_number = 1 | |
indicator = True | |
while indicator: | |
r = requests.get(LETTERBOXD_CHART_URL + 'page/{}'.format(page_number), headers={'Accept-Language': library_language}) | |
tree = html.fromstring(r.content) | |
# http://stackoverflow.com/questions/35101944/empty-list-is-returned-from-imdb-using-python-lxml | |
# https://www.w3schools.com/html/default.asp | |
# https://www.w3schools.com/xml/xpath_syntax.asp | |
# https://stackoverflow.com/questions/4531995/getting-attribute-using-xpath | |
top_250_letterboxd_url = tree.xpath("//ul[contains(@class, 'poster-list -p125 -grid film-list')]//div[@class='poster film-poster really-lazy-load']/@data-target-link") | |
if top_250_letterboxd_url: | |
for url in top_250_letterboxd_url: | |
# print(url) | |
title,year,imdb_id = get_imdb_id_from_letterboxd(LETTERBOXD_URL + url) | |
top_250_titles.append(title) | |
top_250_years.append(year) | |
top_250_ids.append(imdb_id) | |
page_number += 1 | |
else: | |
indicator = False | |
with open('top_250.csv', 'w') as csv_file: | |
csv_writer = csv.writer(csv_file, delimiter=',') | |
csv_writer.writerow(top_250_ids) | |
csv_writer.writerow(top_250_titles) | |
csv_writer.writerow(top_250_years) | |
return top_250_ids, top_250_titles, top_250_years | |
def imdb_top_250(library_language): | |
### Get the IMDB Top 250 List ### | |
print("Retrieving the IMDB Top 250 list...") | |
r = requests.get(IMDB_CHART_URL, headers={'Accept-Language': library_language}) | |
tree = html.fromstring(r.content) | |
# http://stackoverflow.com/questions/35101944/empty-list-is-returned-from-imdb-using-python-lxml | |
top_250_titles = tree.xpath("//table[contains(@class, 'chart')]//td[@class='titleColumn']/a/text()") | |
top_250_years = tree.xpath("//table[contains(@class, 'chart')]//td[@class='titleColumn']/span/text()") | |
top_250_ids = tree.xpath("//table[contains(@class, 'chart')]//td[@class='ratingColumn']/div//@data-titleid") | |
return top_250_ids, top_250_titles, top_250_years | |
def plex_movie_list(): | |
### Create PlexServer object and list of movies ### | |
try: | |
plex = PlexServer(PLEX_URL, PLEX_TOKEN) | |
except Exception as e: | |
# print(e) | |
print("No Plex server found at: {base_url}".format(base_url=PLEX_URL)) | |
print("Exiting script.") | |
sys.exit() | |
print("Retrieving a list of movies from the '{library}' library in Plex...".format(library=MOVIE_LIBRARY_NAME)) | |
try: | |
movie_library = plex.library.section(MOVIE_LIBRARY_NAME) | |
movie_library_key = movie_library.key | |
library_language = movie_library.language | |
all_movies = movie_library.all() | |
return movie_library, movie_library_key, library_language, all_movies | |
except: | |
print("The '{library}' library does not exist in Plex.".format(library=MOVIE_LIBRARY_NAME)) | |
print("Exiting script.") | |
sys.exit() | |
def imdb_id_mapping(all_movies): | |
### Create a dictionary consisting of {imdb_id: movie} pairs for the Plex library. ### | |
plex_library_imdb_ids = [] | |
imdb_map = {} | |
for m in all_movies: | |
if 'imdb://' in m.guid: | |
imdb_id = m.guid.split('imdb://')[1].split('?')[0] | |
elif 'themoviedb://' in m.guid: | |
tmdb_id = m.guid.split('themoviedb://')[1].split('?')[0] | |
imdb_id = get_imdb_id_from_tmdb(tmdb_id) | |
else: | |
imdb_id = None | |
if imdb_id: | |
plex_library_imdb_ids.append(imdb_id) | |
imdb_map[imdb_id] = m | |
return plex_library_imdb_ids, imdb_map | |
def set_collection(top_250_ids, imdb_map, movie_library_key, collection_name): | |
### Create the plex collection ### | |
print("Setting the collection for the '{}' library...".format(MOVIE_LIBRARY_NAME)) | |
in_library_idx = [] | |
for i, imdb_id in enumerate(top_250_ids): | |
movie = imdb_map.pop(imdb_id, None) | |
if movie: | |
add_collection(movie_library_key, movie.ratingKey, collection_name) | |
in_library_idx.append(i) | |
for movie in imdb_map.values(): | |
remove_collection(movie_library_key, movie.ratingKey, collection_name) | |
return in_library_idx | |
def get_found_missing_list(top_250_ids, top_250_titles, top_250_years, in_library_idx): | |
# Get list of missing IMDB Top 250 movies | |
missing_top_250 = [(idx, imdb) for idx, imdb in enumerate(zip(top_250_ids, top_250_titles, top_250_years)) | |
if idx not in in_library_idx] | |
# Get list of found IMDB Top 250 movies | |
found_top_250 = [(idx, imdb) for idx, imdb in enumerate(zip(top_250_ids, top_250_titles, top_250_years)) | |
if idx in in_library_idx] | |
return missing_top_250, found_top_250, len(top_250_ids) | |
def print_results(missing_top_250, found_top_250, list_count): | |
columns, _ = shutil.get_terminal_size(fallback=(80, 24)) | |
print("="*columns) | |
print("\nNumber of Top 250 movies in the library: {count}".format(count=list_count-len(missing_top_250))) | |
print("Number of missing Top 250 movies: {count}".format(count=len(missing_top_250))) | |
print("\nList of found Top 250 movies:\n") | |
for idx, (imdb_id, title, year) in found_top_250: | |
print("{idx}\t{imdb_id}\t{title} {year}".format(idx=idx+1, imdb_id=imdb_id, title=title, year=year)) | |
print("\nList of missing Top 250 movies:\n") | |
for idx, (imdb_id, title, year) in missing_top_250: | |
print("{idx}\t{imdb_id}\t{title} {year}".format(idx=idx+1, imdb_id=imdb_id, title=title, year=year)) | |
# def metacritic_score(imdb_id, session): | |
# r = session.get("https://www.imdb.com/title/{}/criticreviews".format(imdb_id)) | |
# tree = html.fromstring(r.content) | |
# metacritic_score = tree.xpath("//div[@class = 'metascore_block']//span[@itemprop = 'ratingValue']/text()") | |
# if metacritic_score: | |
# metacritic_score = int(metacritic_score[0]) | |
# else: | |
# metacritic_score = "None" | |
# return metacritic_score | |
# def run_metacritic_score(): | |
# cutoff_threshold = int(input("What score ceiling do you want? (Hint: 101 will include all scores) ")) | |
# plex_library_metacritic_scores = {} | |
# movie_library, movie_library_key, library_language, all_movies = plex_movie_list() | |
# plex_library_imdb_ids, imdb_map = imdb_id_mapping(all_movies) | |
# session = requests.Session() | |
# for imdb_id in plex_library_imdb_ids: | |
# plex_library_metacritic_scores[imdb_id] = metacritic_score(imdb_id, session) | |
# if plex_library_metacritic_scores[imdb_id] != "None" and plex_library_metacritic_scores[imdb_id] <= cutoff_threshold: | |
# print(imdb_map[imdb_id].title, plex_library_metacritic_scores[imdb_id]) | |
def run_imdb_top_250(): | |
movie_library, movie_library_key, library_language, all_movies = plex_movie_list() | |
top_250_ids, top_250_titles, top_250_years = imdb_top_250(library_language) | |
plex_library_imdb_ids, imdb_map = imdb_id_mapping(all_movies) | |
in_library_idx = set_collection(top_250_ids, imdb_map, movie_library_key, IMDB_COLLECTION_NAME) | |
missing_top_250, found_top_250, list_count = get_found_missing_list(top_250_ids, top_250_titles, top_250_years, in_library_idx) | |
print_results(missing_top_250, found_top_250, list_count) | |
def run_letterboxd_top_250(): | |
movie_library, movie_library_key, library_language, all_movies = plex_movie_list() | |
top_250_ids, top_250_titles, top_250_years = letterboxd_top_250(library_language) | |
plex_library_imdb_ids, imdb_map = imdb_id_mapping(all_movies) | |
in_library_idx = set_collection(top_250_ids, imdb_map, movie_library_key, LETTERBOXD_COLLECTION_NAME) | |
missing_top_250, found_top_250, list_count = get_found_missing_list(top_250_ids, top_250_titles, top_250_years, in_library_idx) | |
print_results(missing_top_250, found_top_250, list_count) | |
def run_crossover_top_250(): | |
movie_library, movie_library_key, library_language, all_movies = plex_movie_list() | |
top_250_ids, top_250_titles, top_250_years = imdb_top_250(library_language) | |
top_250_ids_two, top_250_titles_two, top_250_years_two = letterboxd_top_250(library_language) | |
top_250_ids_crossover = set(top_250_ids) & set(top_250_ids_two) | |
plex_library_imdb_ids, imdb_map = imdb_id_mapping(all_movies) | |
in_library_idx = set_collection(top_250_ids_crossover, imdb_map, movie_library_key, "IMDB & Letterboxd Top 250 Crossover") | |
if __name__ == "__main__": | |
columns, rows = shutil.get_terminal_size(fallback=(80, 24)) | |
print("="*columns) | |
print("Automated Plex collection script".center(columns)) | |
print("="*columns) | |
menu = {} | |
menu['1'] = ". IMDB Top 250" | |
menu['2'] = ". Letterboxd Top 250" | |
menu['3'] = ". IMDB Top 250 & Letterboxd Top 250" | |
menu['4'] = ". Quit" | |
options = menu.keys() | |
for entry in options: | |
print("{}{}".format(entry,menu[entry])) | |
selection = input("Please select an option: ") | |
if selection == '1': | |
print() | |
run_imdb_top_250() | |
elif selection == '2': | |
print() | |
run_letterboxd_top_250() | |
elif selection == '3': | |
print() | |
run_crossover_top_250() | |
else: | |
print() | |
print("Unknown Option Selected!") | |
print("="*columns) | |
print("Done".center(columns)) | |
print("="*columns) | |
input("Press Enter to finish...") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lxml | |
plexapi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment