1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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:])
|