Skip to content
This repository has been archived by the owner on Jan 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4 from Sentir101/master
Browse files Browse the repository at this point in the history
Handle foreign characters by using unicode, option to write to output file
  • Loading branch information
Nathan Hoad committed Mar 1, 2012
2 parents 303db69 + abacfa1 commit e9638f0
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 116 deletions.
194 changes: 84 additions & 110 deletions default.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys, os
import xbmc, xbmcgui, xbmcplugin
import unicodedata
import urllib

import datetime
Expand All @@ -17,45 +18,57 @@
SECOND_SUBMENU = "Unadded TV Shows"
HELP_SUBMENU = "Help!"

def log(txt, severity=xbmc.LOGDEBUG):
try:
message = ("%s" % txt)
xbmc.log(msg=message, level=severity)
except UnicodeEncodeError:
message = ("UnicodeEncodeError")
xbmc.log(msg=message, level=xbmc.LOGWARNING)

# plugin handle
print "THESE ARE THE SYS ARGUMENTS: %s" % sys.argv
log("THESE ARE THE SYS ARGUMENTS: %s" % sys.argv)
handle = int(sys.argv[1])

FILE_EXTENSIONS = ['mpg', 'mpeg', 'avi', 'flv', 'wmv', 'mkv', '264', '3g2', '3gp', 'ifo', 'mp4', 'mov', 'iso', 'ogm']
FILE_EXTENSIONS.extend(xbmcplugin.getSetting(handle, "custom_file_extensions").split(";"))

OUTPUT_FILE = xbmcplugin.getSetting(handle, "output_file");

if not OUTPUT_FILE:
OUTPUT_FILE = '/home/xbmc/missing-movies.txt'

OUTPUT_FILE = xbmcplugin.getSetting(handle, "output_dir") + xbmcplugin.getSetting(handle, "output_file");

def remove_duplicates(files):
# converting it to a set and back drops all duplicates
return list(set(files))

def clean_name(text):
text = text.replace('%21', '!')
text = text.replace('%3a', ':')
text = text.replace('%5c', '\\')
text = text.replace('%2f', '/')
text = text.replace('%2c', ',')
text = text.replace('%5f', '_')
text = text.replace('%20', ' ')
#text = text.replace('%21', '!')
#text = text.replace('%3a', ':')
#text = text.replace('%5c', '\\')
#text = text.replace('%2f', '/')
#text = text.replace('%2c', ',')
#text = text.replace('%5f', '_')
#text = text.replace('%20', ' ')
text = unicode(text, 'utf8')

return text

def output_to_file(list):
f = open(OUTPUT_FILE, 'a')
for item in list:
f.write(item + '\n')
f.close()

def get_shares():
shares = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Files.GetSources", "params": {"media": "video"}, "id": 1}'))['result']['sources']
shares = [ s['file'] for s in shares ]
def get_sources():
sources = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "Files.GetSources", "params": {"media": "video"}, "id": 1}'))['result']['sources']
sources = [ s['file'] for s in sources ]

results = []
for s in shares:
print "FOUND SHARE: %s" % s
for s in sources:
log("FOUND SOURCE: %s" % s, xbmc.LOGINFO)
if s.startswith('addons://'):
print s + ' is an addon share, ignoring...'
shares.remove(s)
log("%s is an addon source, ignoring..." % s, xbmc.LOGINFO)
sources.remove(s)
elif s.startswith('multipath://'):
print s + ' is a multipath share, splitting and adding individuals...'
log("%s is a multipath source, splitting and adding individuals..." % s, xbmc.LOGINFO)
s = s.replace('multipath://', '')
parts = s.split('/')
parts = [ clean_name(f) for f in parts ]
Expand All @@ -64,38 +77,38 @@ def get_shares():
if b:
results.append(b)
else:
print s + ' is a straight forward share, adding...'
log("%s is a straight forward source, adding...", xbmc.LOGINFO)
results.append(s)

return results

def get_movie_sources():
result = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params":{"properties": ["file"]}, "id": 1}'))
print result
log(result, xbmc.LOGDEBUG)
movies = result['result']['movies']
print movies
log(movies, xbmc.LOGDEBUG)
files = [ item['file'] for item in movies ]
files = [ os.path.dirname(f) for f in files ]
files = remove_duplicates(files)

shares = remove_duplicates(get_shares())
sources = remove_duplicates(get_sources())

results = []
for f in files:
for s in shares:
for s in sources:
if f[-1] != os.sep:
f += os.sep

if f.startswith(s):
print s + ' was confirmed as a movie share using ' + f
log("%s was confirmed as a movie share using %s" % (s, f), xbmc.LOGINFO)
results.append(s)
shares.remove(s)
sources.remove(s)

return results

def get_tv_files(show_errors):
result = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "id": 1}'))
# NOTE:this should help me identify Yulquen's bug
print "VideoLibrary.GetTVShows results: %s" % result
log("VideoLibrary.GetTVShows results: %s" % result, xbmc.LOGDEBUG)
tv_shows = result['result']['tvshows']
files = []

Expand All @@ -107,39 +120,27 @@ def get_tv_files(show_errors):

try:
episodes = episode_result['result']['episodes']
files.extend([ e['file'] for e in episodes ])
files.extend([ unicode(e['file'], 'utf8') for e in episodes ])
except KeyError:
if show_errors:
xbmcgui.Dialog().ok("ERROR!", "Could not retrieve episodes for %s!" % show_name, "Contact the developer!")
xbmcgui.Dialog().ok("ERROR!", "Could not retrieve episodes for %s!" % show_name, "Contact the developer if there actually are episodes!")

nothing = """
seasons_result = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetSeasons", "params": {"tvshowid": %d}, "id": 1}' % show_id))
seasons = seasons_result['result']['seasons']
# will probably need tweaking to pick up special seasons and whatnot.
seasons = [ f['label'].split(' ')[1] for f in seasons if f['label'].startswith('Season')]
for season_no in seasons:
episode_result = eval(xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": %d, "season": %s}, "id": 1}' % (show_id, season_no)))
episodes = episode_result['result']['episodes']
files.extend([ e['file'] for e in episodes ])
"""
return files

def get_tv_sources():
files = get_tv_files(False)
files = [ os.path.dirname(f) for f in files ]
files = remove_duplicates(files)

shares = remove_duplicates(get_shares())
sources = remove_duplicates(get_sources())

results = []
for f in files:
for s in shares:
for s in sources:
if f.startswith(s):
print s + ' was confirmed as a tv show share using ' + f
log("%s was confirmed as a TV source using %s" % (s, f), xbmc.LOGINFO)
results.append(s)
shares.remove(s)
sources.remove(s)
return results

def file_has_extensions(filename, extensions):
Expand All @@ -156,7 +157,7 @@ def file_has_extensions(filename, extensions):

def get_files(path):
results = []
for root, sub_folders, files in os.walk(path):
for root, sub_folders, files in os.walk(unicode(path, 'utf8')):
for f in files:
if file_has_extensions(f, FILE_EXTENSIONS):
f = os.path.join(root, f)
Expand All @@ -177,7 +178,7 @@ def parameters_string_to_dict(parameters):
return paramDict

def addDirectoryItem(name, isFolder=True, parameters={}, totalItems=1):
''' Add a list item to the XBMC UI.'''
''' Add a list item to the XBMC UI. '''
li = xbmcgui.ListItem(name)

url = sys.argv[0] + '?' + urllib.urlencode(parameters)
Expand All @@ -196,9 +197,10 @@ def show_root_menu():

def show_movie_submenu():
''' Show movies missing from the library. '''
MOVIE_PATHS = remove_duplicates(get_movie_sources())
if len(MOVIE_PATHS) == 0 or len(MOVIE_PATHS[0]) == 0:
xbmcgui.Dialog().ok("ERROR!", "Could not detect movie paths! Contact developer!")
movie_sources = remove_duplicates(get_movie_sources())
if len(movie_sources) == 0 or len(movie_sources[0]) == 0:
xbmcgui.Dialog().ok("ERROR!", "Could not detect movie sources! Contact developer!")
log("No movie sources!", xbmc.LOGERROR)
xbmcplugin.endOfDirectory(handle=handle, succeeded=False)
return

Expand All @@ -208,7 +210,7 @@ def show_movie_submenu():
library_files = []
missing = []

print "SEARCHING MOVIES"
log("SEARCHING MOVIES", xbmc.LOGNOTICE)
# this magic section adds the files from trailers and sets!
for m in movies:
f = m['file']
Expand All @@ -220,11 +222,11 @@ def show_movie_submenu():
sub_trailers = []

for item in set_files['result']['files']:
sub_files.append(clean_name(item['file']))
sub_files.append(unicode(item['file'], 'utf8'))
try:
trailer = item['trailer']
if not trailer.startswith('http://'):
library_files.append(clean_name(trailer))
library_files.append(unicode(trailer, 'utf8'))
except KeyError:
pass

Expand All @@ -234,101 +236,73 @@ def show_movie_submenu():
f = f.replace('stack://', '')
parts = f.split(' , ')

parts = [ clean_name(f) for f in parts ]
parts = [ unicode(f, 'utf8') for f in parts ]

for b in parts:
library_files.append(b)
else:
library_files.append(clean_name(f))
library_files.append(unicode(f, 'utf8'))
try:
trailer = m['trailer']
if not trailer.startswith('http://'):
library_files.append(clean_name(trailer))
library_files.append(unicode(trailer, 'utf8'))
except KeyError:
pass

library_files = set(library_files)

for movie_path in MOVIE_PATHS:
movie_files = set(get_files(movie_path))
for movie_source in movie_sources:
movie_files = set(get_files(movie_source))

if not library_files.issuperset(movie_files):
print "%s contains missing movies!" % movie_path
print "missing movies: %s" % list(movie_files.difference(library_files))
log("%s contains missing movies!" % movie_source, xbmc.LOGNOTICE)
log("library files: %s" % library_files, xbmc.LOGDEBUG)
l = list(movie_files.difference(library_files))
l.sort()
log("missing movies: %s" % l, xbmc.LOGNOTICE)
missing.extend(l)

f = None

tmp = """try:
f = open(OUTPUT_FILE, 'a')
except IOError:
f = open(OUTPUT_FILE, 'w')
now = datetime.datetime.now()
f.write('%s: search results for missing movies using the missing movies plugin:' % now.strftime('%Y-%m-%d %H:%M'))
"""

if OUTPUT_FILE:
output_to_file(missing);

for movie_file in missing:
# get the end of the filename without the extension
if os.path.splitext(movie_file.lower())[0].endswith("trailer"):
print "%s is a trailer and will be ignored!" % movie_file
log("%s is a trailer and will be ignored!" % movie_file, xbmc.LOGINFO)
else:
addDirectoryItem(movie_file, isFolder=False, totalItems=len(missing))
#f.write(tv_file)

#f.close()

xbmcplugin.endOfDirectory(handle=handle, succeeded=True)

def show_tvshow_submenu():
''' Show TV shows missing from the library. '''
TV_PATHS = remove_duplicates(get_tv_sources())
if len(TV_PATHS) == 0 or len(TV_PATHS[0]) == 0:
xbmcgui.Dialog().ok("ERROR!", "Could not detect TV paths! Contact developer!")
tv_sources = remove_duplicates(get_tv_sources())
if len(tv_sources) == 0 or len(tv_sources[0]) == 0:
xbmcgui.Dialog().ok("ERROR!", "Could not detect TV sources! Contact developer if they do exist!")
log("No TV sources!", xbmc.LOGERROR)
xbmcplugin.endOfDirectory(handle=handle, succeeded=False)
return

library_files = set(get_tv_files(True))
missing = []

for tv_path in TV_PATHS:
tv_files = set(get_files(tv_path))
log("SEARCHING TV SHOWS", xbmc.LOGNOTICE);
for tv_source in tv_sources:
tv_files = set(get_files(tv_source))

if not library_files.issuperset(tv_files):
print "%s contains missing TV shows!" % tv_path
log("%s contains missing TV shows!" % tv_source, xbmc.LOGNOTICE)
log("library files: %s" % library_files, xbmc.LOGDEBUG)
l = list(tv_files.difference(library_files))
l.sort()
log("missing episodes: %s" % l, xbmc.LOGNOTICE)
missing.extend(l)

f = None

tmp = """try:
f = open(OUTPUT_FILE, 'a')
except IOError:
f = open(OUTPUT_FILE, 'w')
now = datetime.datetime.now()
f.write('%s: search results for missing tv shows using the missing movies plugin:' % now.strftime('%Y-%m-%d %H:%M'))
"""
if OUTPUT_FILE:
output_to_file(missing)

for tv_file in missing:
addDirectoryItem(tv_file, isFolder=False)
#f.write(tv_file)

#f.close()

nothing = """
for tv_file in tv_files:
print "looking for %s in %s" % (tv_file, tv_path)
if tv_file not in files:
print "%s NOT found!" % tv_file
else:
print "%s found!" % tv_file
# it looks like it should be tv_files instead of files, but it's not.
files.remove(tv_file)
"""

xbmcplugin.endOfDirectory(handle=handle, succeeded=True)

Expand Down
7 changes: 4 additions & 3 deletions resources/language/english/strings.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<strings>
<!-- Settings -->
<string id="31000">Misc Settings (semicolon delimited)</string>
<string id="31001">Custom File Extensions</string>
<string id="31002">Search Results File</string>
<string id="30000">Output Directory</string>
<string id="30001">Output File</string>
<string id="30002">Misc Settings (semicolon delimited)</string>
<string id="30003">Custom File Extensions</string>
</strings>

7 changes: 4 additions & 3 deletions resources/settings.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<setting type="lsep" label="31000" />
<setting id="custom_file_extensions" type="text" label="31001" default="" />
<setting id="output_file" type="text" label="31002" default="" />
<setting id="output_dir" type="folder" label="30000" default="" />
<setting id="output_file" type="text" label="30001" default="" />
<setting type="lsep" label="30002" />
<setting id="custom_file_extensions" type="text" label="30003" default="" />
</settings>

0 comments on commit e9638f0

Please sign in to comment.