diff options
| author | Jakob L. Kreuze <zerodaysfordays@sdf.org> | 2024-06-19 09:34:34 -0400 |
|---|---|---|
| committer | Jakob L. Kreuze <zerodaysfordays@sdf.org> | 2024-06-19 09:34:34 -0400 |
| commit | 3b704f0d7f42959a2c9dca4756da53cd62ed3d96 (patch) | |
| tree | 67e4a9c15bdfed8e6979bdf48a7e34fd7784f572 | |
| parent | 07ce254cae2528ed6f5118cc1ea5b834db8f3400 (diff) | |
Refactoring
| -rw-r--r-- | addon.py | 161 |
1 files changed, 102 insertions, 59 deletions
@@ -50,9 +50,9 @@ def get_url(**kwargs): return "{}?{}".format(URL, urlencode(kwargs)) -def list_genres(): +def list_top_level(): """ - Create the list of movie genres in the Kodi interface. + Create the list of entrypoints in the Kodi interface. """ xbmcplugin.setPluginCategory(HANDLE, "Newgrounds") xbmcplugin.setContent(HANDLE, "movies") @@ -70,7 +70,6 @@ def list_genres(): for name in genres: list_item = xbmcgui.ListItem(label=name) - # list_item.setArt({'icon': genre_info['icon'], 'fanart': genre_info['fanart']}) info_tag = list_item.getVideoInfoTag() info_tag.setMediaType("video") @@ -92,7 +91,7 @@ def list_categories(genre="Featured"): xbmcplugin.setPluginCategory(HANDLE, "Newgrounds") xbmcplugin.setContent(HANDLE, "movies") - CATEGORIES = { + categories = { "All": 0, "Action": 45, "Comedy - Original": 60, @@ -105,18 +104,14 @@ def list_categories(genre="Featured"): "Spam": 55, } - for name in CATEGORIES.keys(): + for name in categories.keys(): list_item = xbmcgui.ListItem(label=name) - # list_item.setArt({'icon': genre_info['icon'], 'fanart': genre_info['fanart']}) - info_tag = list_item.getVideoInfoTag() info_tag.setMediaType("video") info_tag.setTitle(name) info_tag.setGenres([name]) - - url = get_url(action="listing", genre=genre, category=CATEGORIES[name]) + url = get_url(action="listing", genre=genre, category=categories[name]) is_folder = True - xbmcplugin.addDirectoryItem(HANDLE, url, list_item, is_folder) xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE) xbmcplugin.endOfDirectory(HANDLE) @@ -124,7 +119,11 @@ def list_categories(genre="Featured"): def get_video_url(url): """ - TODO + Return the location of the stream for a movie. + + :param url: URL of Newgrounds movie page + :return: stream URL + :rtype: str """ html = requests.get(url).text soup = BeautifulSoup(html, "html.parser") @@ -150,6 +149,10 @@ def get_video_url(url): def get_addon_video_info(url): """ Scrape metadata from `url`. + + :param url: URL of Newgrounds movie page + :return: dictionary of video metadata + :rtype: dict """ html = requests.get(url).text soup = BeautifulSoup(html, "html.parser") @@ -158,7 +161,7 @@ def get_addon_video_info(url): thumbnail = soup.find("meta", property="og:image") if thumbnail is not None: thumbnail = thumbnail["content"] - sidestats_popularity = soup.find_all('dl', 'sidestats')[0].find_all('dd') + sidestats_popularity = soup.find_all("dl", "sidestats")[0].find_all("dd") views = sidestats_popularity[0].string faves = sidestats_popularity[1].a if faves is not None: @@ -172,7 +175,7 @@ def get_addon_video_info(url): score = sidestats_popularity[3].span.string except IndexError: score = 0 - sidestats_date_and_genre = soup.find_all('dl', 'sidestats')[1].find_all('dd') + sidestats_date_and_genre = soup.find_all("dl", "sidestats")[1].find_all("dd") upload_date = sidestats_date_and_genre[0].string upload_time = sidestats_date_and_genre[1].string try: @@ -180,22 +183,28 @@ def get_addon_video_info(url): except IndexError as e: genre = "Unknown" try: - tags = [tag.string for tag in soup.find('dd', 'tags').find_all('a')] + tags = [tag.string for tag in soup.find("dd", "tags").find_all("a")] except AttributeError as e: tags = [] - author_comments = ''.join([s for s in soup.find('div', id='author_comments').strings]).strip() + author_comments = "".join( + [s for s in soup.find("div", id="author_comments").strings] + ).strip() try: - authors = [author.string for author in soup.find('ul', 'authorlinks').find_all('a') if author.get("class") is None] + authors = [ + author.string + for author in soup.find("ul", "authorlinks").find_all("a") + if author.get("class") is None + ] except AttributeError: authors = [] - if len(soup.find_all('h2', 'rated-a')) != 0: - rating = 'a' - elif len(soup.find_all('h2', 'rated-m')) != 0: - rating = 'm' - elif len(soup.find_all('h2', 'rated-t')) != 0: - rating = 't' + if len(soup.find_all("h2", "rated-a")) != 0: + rating = "a" + elif len(soup.find_all("h2", "rated-m")) != 0: + rating = "m" + elif len(soup.find_all("h2", "rated-t")) != 0: + rating = "t" else: - rating = 'e' + rating = "e" return { "title": title, @@ -215,9 +224,20 @@ def get_addon_video_info(url): } -def get_video_urls( - genre="Featured", interval="today", sort="date", category=0, offset=0 +def get_frontpage_video_urls( + grouping="Featured", interval="today", sort_by="date", category=0, offset=0 ): + """ + Return a list of movies from the Newgrounds frontpage. + + :param grouping: one of "Featured", "Latest", or "Popular" + :param interval: one of "today", "yesterday", "week", "month", "year", "all" + :param sort_by: one of "date", score", "views" + :param category: numeric identifier for video category + :param offset: pagination offset + :return: list of video URLs + :rtype: list + """ URLS = { "Featured": "https://www.newgrounds.com/movies/featured", "Latest": "https://www.newgrounds.com/movies/browse", @@ -225,15 +245,16 @@ def get_video_urls( } assert interval in ["today", "yesterday", "week", "month", "year", "all"] - assert sort in ["date"] - assert isinstance(genre, int) + assert sort_by in ["date", "score", "views"] + assert isinstance(category, int) + assert isinstance(offset, int) - url = URLS[genre] + url = URLS[grouping] response = requests.get( url, params={ "interval": interval, - "sort": sort, + "sort": sort_by, "genre": category, "isAjaxRequest": True, "offset": offset, @@ -248,11 +269,33 @@ def get_video_urls( return [tag["href"] for tag in soup.find_all("a", "inline-card-portalsubmission")] -def search(term, offset=0): +def search(term, sort_by="relevance", offset=1): + """ + Return a list of movies matching a given search term. + + :param term: Term to search for + :param sort_by: one of "relevance", "date-asc", "date-desc", "score-asc", "score-desc", "views-asc", "views-desc" + :param offset: pagination offset + :return: list of video URLs + :rtype: list + """ + assert isinstance(term, str) + assert sort_by in [ + "relevance", + "date-asc", + "date-desc", + "score-asc", + "score-desc", + "views-asc", + "views-desc", + ] + assert isinstance(offset, int) + response = requests.get( "https://www.newgrounds.com/search/conduct/movies", params={ "suitabilities": "etm", + "sort": sort_by, "terms": term, "page": offset, "inner": 1, @@ -276,16 +319,16 @@ def list_videos(video_urls, title=None, next_page=None): """ videos = [] with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor: - # Start the load operations and mark each future with its URL - future_to_url = {executor.submit(get_addon_video_info, url): url for url in video_urls} - for future in concurrent.futures.as_completed(future_to_url): - url = future_to_url[future] - videos.append(future.result()) + # Start the load operations and mark each future with its URL + future_to_url = { + executor.submit(get_addon_video_info, url): url for url in video_urls + } + for future in concurrent.futures.as_completed(future_to_url): + url = future_to_url[future] + videos.append(future.result()) xbmcplugin.setPluginCategory(HANDLE, title) xbmcplugin.setContent(HANDLE, "movies") - # Get the list of videos in the category. - # videos = genre_info['movies'] - # Iterate through videos. + for video in videos: list_item = xbmcgui.ListItem(label=video["title"]) if video["thumbnail"] is not None: @@ -294,14 +337,15 @@ def list_videos(video_urls, title=None, next_page=None): info_tag = list_item.getVideoInfoTag() info_tag.setMediaType("movie") info_tag.setTitle(video["title"]) - info_tag.setYear(int(video["upload_date"][-4:])) - info_tag.setRating(float(video["score"]), int(video["votes"].replace(',', ''))) - info_tag.setPlaycount(int(video["views"].replace(',', ''))) + info_tag.setRating(float(video["score"]), int(video["votes"].replace(",", ""))) + info_tag.setPlaycount(int(video["views"].replace(",", ""))) info_tag.setPlot(video["description"]) info_tag.setGenres([video["genre"]]) info_tag.setDirectors(video["authors"]) - info_tag.setPremiered(dateutil.parser.parse(video["upload_date"]).strftime("%Y-%m-%d")) + info_tag.setPremiered( + dateutil.parser.parse(video["upload_date"]).strftime("%Y-%m-%d") + ) info_tag.setTags(video["tags"]) if video["rating"] == "a": @@ -313,9 +357,6 @@ def list_videos(video_urls, title=None, next_page=None): else: info_tag.setMpaa("PG") - # info_tag.setGenres([genre_info['genre']]) - # info_tag.setPlot(video['plot']) - # info_tag.setYear(video['year']) list_item.setProperty("IsPlayable", "true") url = get_url(action="play", video=video["url"]) @@ -323,7 +364,7 @@ def list_videos(video_urls, title=None, next_page=None): xbmcplugin.addDirectoryItem(HANDLE, url, list_item, is_folder) # Add a "continue" folder. - if next_page is not None: + if next_page is not None and len(video_urls) > 0: list_item = xbmcgui.ListItem(label="Next Page") info_tag = list_item.getVideoInfoTag() info_tag.setMediaType("video") @@ -352,16 +393,22 @@ def router(paramstring): """ params = dict(parse_qsl(paramstring)) if not params: - list_genres() + list_top_level() elif params["action"] == "listing" and "category" in params: offset = int(params.get("offset", 0)) - video_urls = get_video_urls(category=params["category"], interval="all", offset=offset) - next_page = get_url(action="listing", genre=params["genre"], category=params["category"], offset=offset + 20) - list_videos( - video_urls, - params["genre"], - next_page + video_urls = get_frontpage_video_urls( + grouping=params["genre"], + interval="all", + category=params["category"], + offset=offset, + ) + next_page = get_url( + action="listing", + genre=params["genre"], + category=params["category"], + offset=offset + 20, ) + list_videos(video_urls, params["genre"], next_page) elif params["action"] == "listing": list_categories(params["genre"]) elif params["action"] == "searchprompt": @@ -371,14 +418,10 @@ def router(paramstring): xbmc.executebuiltin("Container.Update(%s)" % url) elif params["action"] == "search": term = params["term"] - offset = int(params.get("offset", 0)) + offset = int(params.get("offset", 1)) video_urls = search(term, offset=offset) next_page = get_url(action="search", term=term, offset=offset + 1) - list_videos( - video_urls, - "Search Results: {}".format(term), - next_page - ) + list_videos(video_urls, "Search Results: {}".format(term), next_page) elif params["action"] == "play": play_video(params["video"]) else: |