summaryrefslogtreecommitdiff
path: root/addon.py
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2024-06-15 13:51:53 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2024-06-15 13:51:53 -0400
commitb3df7ba04275e1368cfa385c663b7730b18cb866 (patch)
tree93eeb47ebc4dbf22e8fe87c781e8e6fb656a3cdb /addon.py
Initial commit
Diffstat (limited to 'addon.py')
-rw-r--r--addon.py199
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:])