Skip to content

Commit fd6929b

Browse files
author
moedje
committed
Updates to WSOnline, show formatting, saving of shows, searching of shows, context menu items.
1 parent e012463 commit fd6929b

File tree

12 files changed

+379
-89
lines changed

12 files changed

+379
-89
lines changed

addons.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ REQUIRED [B]Script.Module.URLResolver, Simple.Downloader, YouTubeDL, and KODIswi
210210
</extension>
211211
</addon>
212212

213-
<addon id="plugin.video.wsonline" name="WatchSeries-Online" version="1.3.0" provider-name="moedje">
213+
<addon id="plugin.video.wsonline" name="WatchSeries-Online" version="1.5.0" provider-name="moedje">
214214
<requires>
215215
<import addon="xbmc.python" version="2.24.0"/>
216216
<import addon="script.module.requests" optional="false"/>
@@ -227,7 +227,7 @@ REQUIRED [B]Script.Module.URLResolver, Simple.Downloader, YouTubeDL, and KODIswi
227227
<summary>Watchseries-online TV Plugin</summary>
228228
<description>Get the latest TV episodes on Watchseries-Online(.pl/.nl/.la...) and search for a series, list all online
229229
episodes in that series, and play them from Openload.Co or VODlocker
230-
[B]V1.2.0 2018-02-14[/B]: New playback and video file resolving fixing many bugs. Source Sorting and fave sources can be set in settings. Updated to new watchseries-online host which is currently .PL and added this as a setting that can be changed in the addon so I don't have to release an update each time they move servers.
230+
[B]V1.5 2017-2-20:[/B] Parsers have been added to attempt to grab details out of the name of the show such as the date, episode number and season. Formats the listings to be standard for easy sorting and reading through including color to make date stand out. V1.2.0 2018-02-14: New playback and video file resolving fixing many bugs. Source Sorting and fave sources can be set in settings. Updated to new watchseries-online host which is currently .PL and added this as a setting that can be changed in the addon so I don't have to release an update each time they move servers.
231231
</description>
232232
</extension>
233233
</addon>

addons.xml.md5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4e4852023ba4b4b6f3208cb1b1e693a4
1+
8e0d4ba24f7883ee093e2dc3de20b003

plugin.video.wsonline/addon.py

Lines changed: 168 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def makecatitem(name, link, removelink=False):
6262
itempath = plugin.url_for(category, name=name, url=link)
6363
item = {'label': name, 'label2': link, 'icon': 'DefaultFolder.png', 'thumbnail': 'DefaultFolder.png', 'path': itempath}
6464
item.setdefault(item.keys()[0])
65-
litem = ListItem.from_dict(**item) #label=name, label2=link, icon='DefaultFolder.png', thumbnail='DefaultFolder.png', path=itempath)
65+
litem = ListItem.from_dict(**item)
6666
if removelink:
6767
litem.add_context_menu_items([('Remove Saved Show', 'RunPlugin("{0}")'.format(plugin.url_for(removeshow, name=name, link=link)),)])
6868
else:
@@ -75,9 +75,23 @@ def playurl():
7575
url = ''
7676
url = plugin.keyboard(default='', heading='Video Page URL')
7777
if url != '' and len(url) > 0:
78-
return play(url)
79-
else:
80-
return index()
78+
item = ListItem.from_dict(path=plugin.url_for(endpoint=play, url=url))
79+
item.set_is_playable(True)
80+
item.set_info(type='video', info_labels={'Title': url, 'Plot': url})
81+
item.add_stream_info(stream_type='video', stream_values={})
82+
#plugin.add_items([item])
83+
#item.select()
84+
#plugin.play_video(item.path)
85+
#play(url)
86+
#return item
87+
#plugin.play_video(item)
88+
#play(url)
89+
#
90+
#plugin.play_video(item)
91+
#return item
92+
#return plugin.redirect(item.path) #
93+
play(url)
94+
#return plugin.play_video(item)
8195

8296

8397
@plugin.route('/saved')
@@ -151,29 +165,149 @@ def DL(url):
151165

152166
def formatshow(name=""):
153167
epname = name.replace('&#8211;', '-')
154-
xname = ''
155168
epnum = ''
156-
eptit = ''
157-
nameparts = re.split(' S\d+[Ee]\d+', epname)
169+
epname = ''
170+
epdate = ''
171+
numparts = re.compile(r'[Ss]\d+[Ee]\d+').findall(name)
172+
if len(numparts) > 0:
173+
epnum = numparts.pop()
174+
datematch = re.compile(r'[12][0-9][0-9][0-9].[0-9][0-9]?.[0-9][0-9]?').findall(name)
175+
if len(datematch) > 0:
176+
epdate = datematch[0]
177+
name = name.replace(' ', ' ').strip()
178+
name = name.replace(epnum, '').strip()
179+
name = name.replace(epdate, '').strip()
180+
if epdate == '':
181+
# Let's see if we can find the date in the form of a string of Month_Abbr Daynum Year
182+
try:
183+
from calendar import month_abbr, month_name
184+
monthlist = month_name[:]
185+
monthlist.extend(month_abbr)
186+
monthlist.pop(13)
187+
monthlist.pop(0)
188+
regex = "{0}.(\d\d).(\d\d\d\d)"
189+
nummonth = 1
190+
for mon in monthlist:
191+
matches = re.compile(regex.format(mon)).findall(name)
192+
if len(matches) > 0:
193+
day, year = matches.pop()
194+
if nummonth < 10:
195+
epdate = "{0} 0{1} {2}".format(year, nummonth, day)
196+
else:
197+
epdate = "{0} {1} {2}".format(year, nummonth, day)
198+
name = name.replace(mon, '').strip()
199+
name = name.replace(year, '').strip()
200+
name = name.replace(day, '').strip()
201+
break
202+
nummonth += 1
203+
if nummonth > 12: nummonth = 1
204+
if epdate == '':
205+
year = re.split(r'\d\d\d\d', name, 1)[0]
206+
epdate = name.replace(year, '').strip()
207+
name = name.replace(epdate, '').strip()
208+
except:
209+
pass
210+
epname = name.replace('(','').replace(')','').strip()
211+
epdate = epdate.replace('(','').replace(')','').strip()
212+
epnum = epnum.replace('(','').replace(')','').strip()
213+
return epname.strip(), epdate.strip(), epnum.strip()
214+
215+
def formatlabel(epname, epdate, epnum):
216+
eplbl = ''
217+
epname = epname.replace('!', '')
218+
try:
219+
if len(epdate) == 0 and len(epnum) == 0:
220+
return epname
221+
else:
222+
if len(epdate) > 0 and len(epnum) > 0:
223+
eplbl = "{0} ([COLOR blue]{1}[/COLOR] [COLOR cyan]{2}[/COLOR])".format(epname, epdate, epnum)
224+
else:
225+
if len(epdate) > 0:
226+
eplbl = "{0} ([COLOR blue]{1}[/COLOR])".format(epname, epdate)
227+
else:
228+
eplbl = "{0} ([COLOR cyan]{1}[/COLOR])".format(epname, epnum)
229+
except:
230+
eplbl = epname + ' ' + epdate + ' ' + epnum
231+
return eplbl
232+
233+
def oldformat(name=""):
234+
epname = name.replace('&#8211;', '-')
235+
epname = ''
236+
epnum = ''
237+
eplbl = ''
238+
nameparts = re.split(r'[12][0-9][0-9][0-9].[0-9][0-9]?.[0-9][0-9]?', epname, 1)
158239
if len(nameparts) > 1:
159-
eptit = nameparts[0]
160-
epnum = epname.replace(nameparts[0], '').strip(' ')
240+
epname = nameparts[0].strip(' (')
241+
epdate = epname.replace(epname, '').strip()
242+
dateparts = epdate.split('(', 1)
243+
if len(dateparts) > 1:
244+
epdate = dateparts[0].strip()
245+
epnum = dateparts[-1].strip()
246+
else:
247+
dateparts = epdate.split(' ', 1)
248+
if len(dateparts) > 1:
249+
epdate = dateparts[0].strip()
250+
epnum = dateparts[1:-1]
161251
else:
162-
nameparts = epname.split('(',1)
252+
nameparts = epname.split('(', 1)
163253
if len(nameparts) > 1:
164-
eptit = nameparts[0].strip()
165-
epnum = nameparts[1].replace(')', '').strip(' ')
254+
epname = nameparts[0].strip()
255+
leftover = nameparts[1].split(')',1)
256+
epdate = leftover[0]
257+
if len(leftover) > 1:
258+
epnum = leftover[-1].strip()
166259
else:
167260
nameparts = re.split(r'[12][0-9][0-9][0-9].[0-9][0-9]?.[0-9]', epname, 1)
168261
if len(nameparts) > 1:
169-
eptit = nameparts[0].strip(' (')
170-
epnum = epname.replace(eptit, '').strip()
262+
epname = nameparts[0].strip(' (')
263+
epdate = epname.replace(epname, '').strip()
171264
if epnum != '':
172-
xname = "{0} [COLOR blue]{1}[/COLOR]".format(eptit, epnum)
265+
eplbl = "{0} [COLOR blue]{1}[/COLOR]".format(epname, epnum)
173266
else:
174-
xname = epname
175-
return xname, eptit, epnum
176-
267+
eplbl = epname
268+
return eplbl, epname, epnum
269+
270+
def findepseason(epnum):
271+
numseason = ''
272+
numep = ''
273+
parts = epnum.lower().split('e', 1)
274+
numseason = parts[0].replace('s', '').strip()
275+
numep = parts[-1].replace('e', '').strip()
276+
return numseason, numep
277+
278+
def episode_makeitem(episodename, episodelink):
279+
'''
280+
Will return a ListItem for the given link to an episode and it's full linked name.
281+
Name will be sent to format show to attempt to parse out a date or season from the title.
282+
Infolabels are populated with any details that can be parsed from the title as well.
283+
Should be used anytime an item needs to be created that is an item for one specific episode of a show.
284+
Latest 350, Saved Show, Category (Show listing of all episodes for that series) would all use this.
285+
'''
286+
infolbl = {}
287+
spath = plugin.url_for(episode, name=episodename, url=episodelink)
288+
img = "DefaultVideoFolder.png"
289+
seasonstr = ''
290+
try:
291+
eptitle, epdate, epnum = formatshow(episodename)
292+
eplbl = formatlabel(eptitle, epdate, epnum)
293+
plotstr = "{0} ({1}): {2} {3}".format(epdate, epnum, eptitle, episodelink)
294+
infolbl = {'Date': epdate, 'Title': eptitle, 'Plot': plotstr}
295+
if len(epnum) > 0:
296+
showS, showE = findepseason(epnum)
297+
dictshow = {'Episode': showE, 'Season': showS}
298+
infolbl.update(dictshow)
299+
snum = int(showS)
300+
epnum = int(showE)
301+
if snum > 0 and epnum > 0:
302+
epdate = "S{0}e{1}".format(snum, epnum)
303+
item = {'label': eplbl, 'label2': epdate, 'icon': img, 'thumbnail': img, 'path': spath}
304+
item.setdefault(item.keys()[0])
305+
li = ListItem.from_dict(**item)
306+
li.set_info(type='video', info_labels=infolbl)
307+
li.add_context_menu_items([('Search [B]{0}[/B]'.format(eptitle), 'RunPlugin({0})'.format(plugin.url_for(query, searchquery=eptitle)))])
308+
except:
309+
li = ListItem(label=episodename, label2=episodelink, icon=img, thumbnail=img, path=spath)
310+
return li
177311

178312
@plugin.route('/latest')
179313
def latest():
@@ -184,16 +318,7 @@ def latest():
184318
epdate = ''
185319
eptitle = ''
186320
for eplink, epname in matches:
187-
epnamelbl, eptitle, epdate = formatshow(epname)
188-
infolbl = {}
189-
if len(epdate) > 0:
190-
infolbl = {'Date': epdate, 'Title': eptitle, 'Plot': '{0}: {1} ({2})'.format(eptitle, epdate, eplink)}
191-
spath = plugin.url_for(episode, name=epname, url=eplink)
192-
item = {'label' : epnamelbl, 'label2': eplink, 'icon':'DefaultVideoFolder.png', 'path':spath}
193-
item.setdefault(item.keys()[0])
194-
li = ListItem.from_dict(**item)
195-
li.set_info(type='video', info_labels=infolbl)
196-
litems.append(li)
321+
litems.append(episode_makeitem(epname, eplink))
197322
return litems
198323

199324

@@ -204,6 +329,11 @@ def search():
204329
searchtxt = plugin.keyboard(searchtxt, 'Search All Sites', False)
205330
searchquery = searchtxt.replace(' ', '+')
206331
plugin.set_setting(key='lastsearch', val=searchtxt)
332+
return query(searchquery)
333+
334+
335+
@plugin.route('/query/<searchquery>')
336+
def query(searchquery):
207337
urlsearch = __BASEURL__ + '/?s={0}&search='.format(searchquery)
208338
html = DL(urlsearch)
209339
htmlres = html.partition('<div class="ddmcc">')[2].split('</div>',1)[0]
@@ -227,12 +357,8 @@ def category(name, url):
227357
matches = re.compile(ur"href='(http.+watchseries-online.+/episode.+?[^'])'.+?</span>(.+?[^<])</a>", re.DOTALL + re.S + re.U).findall(html)
228358
litems =[]
229359
for eplink, epname in matches:
230-
epname = epname.replace('&#8211;', '-')
231-
epath = plugin.url_for(episode, name=epname, url=eplink)
232-
item = {'label' : epname, 'label2': eplink, 'icon' : banner, 'thumbnail' : banner, 'path' : epath}
233-
item.setdefault(item.keys()[0])
234-
litems.append(item)
235-
litems.sort(key=lambda litems : litems['label'])
360+
litems.append(episode_makeitem(epname, eplink))
361+
litems.sort(key=lambda litems : litems.label, reverse=True)
236362
return litems
237363

238364

@@ -349,14 +475,15 @@ def play(url):
349475
if len(resolved) > 1:
350476
plugin.set_resolved_url(resolved)
351477
item = ListItem.from_dict(path=resolved)
478+
return item
352479
else:
353-
plugin.set_resolved_url(url)
354-
plugurl = 'plugin://plugin.video.live.streamspro/?url={0}'.format(urllib.quote_plus(url))
355-
item = ListItem.from_dict(path=plugurl)
356-
item.add_stream_info('video', stream_values={})
357-
item.set_is_playable(True)
358-
plugin.notify(msg="RESOLVE FAIL: {0}".format(url.split('.',1)[-1]), title="Trying {0}".format(item.path.split('.',1)[-1]), delay=2000)
359-
return item
480+
plugin.set_resolved_url() #url)
481+
#plugurl = 'plugin://plugin.video.live.streamspro/?url={0}'.format(urllib.quote_plus(url))
482+
#item = ListItem.from_dict(path=plugurl)
483+
#item.add_stream_info('video', stream_values={})
484+
#item.set_is_playable(True)
485+
#plugin.notify(msg="RESOLVE FAIL: {0}".format(url.split('.', 1)[-1]),title="Trying {0}".format(item.path.split('.', 1)[-1]), delay=2000)
486+
return None
360487

361488

362489
if __name__ == '__main__':

plugin.video.wsonline/addon.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<addon id="plugin.video.wsonline" name="WatchSeries-Online" version="1.3.0" provider-name="moedje">
2+
<addon id="plugin.video.wsonline" name="WatchSeries-Online" version="1.5.0" provider-name="moedje">
33
<requires>
44
<import addon="xbmc.python" version="2.24.0"/>
55
<import addon="script.module.requests" optional="false"/>
@@ -16,7 +16,7 @@
1616
<summary>Watchseries-online TV Plugin</summary>
1717
<description>Get the latest TV episodes on Watchseries-Online(.pl/.nl/.la...) and search for a series, list all online
1818
episodes in that series, and play them from Openload.Co or VODlocker
19-
[B]V1.2.0 2018-02-14[/B]: New playback and video file resolving fixing many bugs. Source Sorting and fave sources can be set in settings. Updated to new watchseries-online host which is currently .PL and added this as a setting that can be changed in the addon so I don't have to release an update each time they move servers.
19+
[B]V1.5 2017-2-20:[/B] Parsers have been added to attempt to grab details out of the name of the show such as the date, episode number and season. Formats the listings to be standard for easy sorting and reading through including color to make date stand out. V1.2.0 2018-02-14: New playback and video file resolving fixing many bugs. Source Sorting and fave sources can be set in settings. Updated to new watchseries-online host which is currently .PL and added this as a setting that can be changed in the addon so I don't have to release an update each time they move servers.
2020
</description>
2121
</extension>
2222
</addon>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
V 1.5.0 (2017-02-20)
2+
- Added parser to get details from the linked show
3+
- Added formatter to label the show name with color for details parser has found
4+
- Parser tries to find a date in a few formats and Season and Episode Number.
5+
6+
V 1.2.0 (2017-02-15)
7+
- Added setting for favourite file sources
8+
- Uses sources in settings to sort them to top of list
9+
- Fixed problem with url request getting access denied from new .PL server by using REQUESTS module
10+
11+
V 1.1.0 (2017-02-14)
12+
- Hostname changed to watchseries-online.pl
13+
- Added setting for addon to specify the current hostname

plugin.video.wsonline/changelog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
V 1.5.0 (2017-02-20)
2+
- Added parser to get details from the linked show
3+
- Added formatter to label the show name with color for details parser has found
4+
- Parser tries to find a date in a few formats and Season and Episode Number.
5+
16
V 1.2.0 (2017-02-15)
27
- Added setting for favourite file sources
38
- Uses sources in settings to sort them to top of list

0 commit comments

Comments
 (0)