diff options
Diffstat (limited to 'addon.py')
| -rw-r--r-- | addon.py | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/addon.py b/addon.py new file mode 100644 index 0000000..5534eaf --- /dev/null +++ b/addon.py @@ -0,0 +1,199 @@ +# Copyright © 2024 Jakob L. Kreuze <zerodaysfordays@sdf.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +""" +Video plugin for animations posted to Newgrounds. +""" + +import os +import sys +from urllib.parse import urlencode, parse_qsl + +from bs4 import BeautifulSoup +import requests +import xbmc +import xbmcgui +import xbmcplugin +from xbmcaddon import Addon +from xbmcvfs import translatePath + +URL = sys.argv[0] +HANDLE = int(sys.argv[1]) + +ADDON_PATH = translatePath(Addon().getAddonInfo('path')) +ICONS_DIR = os.path.join(ADDON_PATH, 'resources', 'images', 'icons') +FANART_DIR = os.path.join(ADDON_PATH, 'resources', 'images', 'fanart') + +def get_url(**kwargs): + """ + Create a URL for calling the plugin recursively from the given set of keyword arguments. + + :param kwargs: "argument=value" pairs + :return: plugin call URL + :rtype: str + """ + return '{}?{}'.format(URL, urlencode(kwargs)) + + +def get_genres(): + """ + Get the list of video genres + + Here you can insert some code that retrieves + the list of video sections (in this case movie genres) from some site or API. + + :return: The list of video genres + :rtype: list + """ + return VIDEOS + + +def get_videos(genre_index): + """ + Get the list of videofiles/streams. + + Here you can insert some code that retrieves + the list of video streams in the given section from some site or API. + + :param genre_index: genre index + :type genre_index: int + :return: the list of videos in the category + :rtype: list + """ + return VIDEOS[genre_index] + + +def list_genres(): + """ + Create the list of movie genres in the Kodi interface. + """ + xbmcplugin.setPluginCategory(HANDLE, 'Newgrounds') + xbmcplugin.setContent(HANDLE, 'movies') + + genres = ["Featured"] # get_genres() + + for index, name in enumerate(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') + info_tag.setTitle(name) + info_tag.setGenres([name]) + + url = get_url(action='listing', genre_index=index) + is_folder = True + + xbmcplugin.addDirectoryItem(HANDLE, url, list_item, is_folder) + xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE) + xbmcplugin.endOfDirectory(HANDLE) + + +def get_video_url(url): + """ + TODO + """ + xbmc.log('Getting info for {}'.format(url), 2) + html = requests.get(url).text + soup = BeautifulSoup(html, 'html.parser') + video_id = soup.find('meta', property='og:url')['content'] \ + .strip('https://www.newgrounds.com/portal/view/') + response = requests.get('https://www.newgrounds.com/portal/video/{}'.format(video_id), headers={ + 'X-Requested-With': 'XMLHttpRequest' + }).json() + preferences = ['1080p', '720p', '360p'] + for preference in preferences: + if preference in response['sources']: + source = next(filter(lambda x: x['type'] == 'video/mp4', response['sources'][preference])) + if source is not None: + return source['src'] + + +def get_addon_video_info(url): + """ + Scrape metadata from `url`. + """ + xbmc.log('Getting info for {}'.format(url), 2) + html = requests.get(url).text + soup = BeautifulSoup(html, 'html.parser') + return { + 'title': soup.find('div', id="embed_header").h2.string, + 'thumbnail': soup.find('meta', property="og:image")['content'], + 'url': url + } + +def list_videos(genre_index): + """ + Create the list of playable videos in the Kodi interface. + + :param genre_index: the index of genre in the list of movie genres + :type genre_index: int + """ + html = requests.get("https://www.newgrounds.com/movies").text + soup = BeautifulSoup(html, 'html.parser') + videos = [get_addon_video_info(tag["href"]) for tag in soup.find_all('a', "inline-card-portalsubmission")] + + xbmcplugin.setPluginCategory(HANDLE, "Featured") #, genre_info['genre']) + 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']) + list_item.setArt({'thumb': video['thumbnail']}) + + info_tag = list_item.getVideoInfoTag() + info_tag.setMediaType('movie') + info_tag.setTitle(video['title']) + # 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']) + is_folder = False + xbmcplugin.addDirectoryItem(HANDLE, url, list_item, is_folder) + xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE) + xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_VIDEO_YEAR) + xbmcplugin.endOfDirectory(HANDLE) + + +def play_video(path): + play_item = xbmcgui.ListItem(path=get_video_url(path)) + play_item.setProperty('IsPlayable', 'true') + xbmcplugin.setResolvedUrl(HANDLE, True, play_item) + + +def router(paramstring): + """ + Router function that calls other functions + depending on the provided paramstring + + :param paramstring: URL encoded plugin paramstring + :type paramstring: str + """ + params = dict(parse_qsl(paramstring)) + if not params: + list_genres() + elif params['action'] == 'listing': + list_videos(int(params['genre_index'])) + elif params['action'] == 'play': + play_video(params['video']) + else: + raise ValueError(f'Invalid paramstring: {paramstring}!') + + +if __name__ == '__main__': + router(sys.argv[2][1:]) |