Example #1
0
def makeNFO(mediaelement):
	nfopath = os.path.splitext(mediaelement["thepath"])[0] + ".nfo"
	doc = Document()
	synodlnatrakt = doc.createElement("SynoDLNAtrakt")
	doc.appendChild(synodlnatrakt)
	#the id
	id = doc.createElement("id")
	idtext = doc.createTextNode(mediaelement["imdb_id"])
	id.appendChild(idtext)
	#the title of the movie
	title = doc.createElement("title")
	titletext = doc.createTextNode(mediaelement["name"])
	title.append(titletext)

	year = doc.createElement("year")
	yeartext = doc.createTextNode(mediaelement["year"])
	year.append(yeartext)

	synodlnatrakt.append(id)
	synodlnatrakt.append(title)
	synodlnatrakt.append(year)
	try:
		f = open(nfopath,"w")
		f.write(doc.toprettyxml(indent="  "))
		f.close()
		logger.info(u"nfo file for {0} created".format(mediaelement["name"]))
	except:
		logger.error(u"unable to create nfo for {0}".format(mediaelement["name"]))
Example #2
0
def processWatched(mediaelement):
	'''INFO: synoindex -N doesn't seem to work here, i wasnt able to figure out why, but it seems like
		-N is just a shortcut for -d and -a.
		So the id in the database gets updated to, and this is kinda useless... may just delete it and re add it manually?'''
	if config.delete_from_index:
		check = subprocess.call(['synoindex','-d', '{0}'.format(mediaelement["thepath"])])
		if check == 0:
			logger.info(u"Deleted {0} from the synoindex database".format(mediaelement["thepath"]))
		else:
			logger.error(u"Cant delete from synoindex... exit code: {0}".format(check))
	if mediaelement["type"] == "movie" and config.move_watched_movies and mediaelement["process"] > 80:
		dirname = os.path.dirname(mediaelement["thepath"])
		path, filename = os.path.split(dirname)
		#newpath = os.path.join(config.move_movies_to_dir, foldername)
		#os.rename(dirname, newpath)
		newfullpath = os.path.join(config.move_movies_to_dir, filename)
		if os.path.exists(mediaelement["thepath"]) and not os.path.exists(newfullpath):
			shutil.move(dirname, config.move_movies_to_dir)
			logger.info(u"Moved {0} to {1}".format(mediaelement["thepath"], newfullpath))
			if config.update_synoindex:
				try:
					subprocess.call(['synoindex','-N', '{0}', '{1}'.format(newfullpath, mediaelement["thepath"])])
				except:
					subprocess.call(['synoindex','-d', '{0}'.format(mediaelement["thepath"])])
				logger.info(u"Updated synoindex for {0} with {1}".format(mediaelement["thepath"], newfullpath))
		else:
			logger.info(u"Directory already exists")

	if mediaelement["type"] == "series" and config.move_watched_series:
		pass
Example #3
0
def tmdbsearch(searchstring):
	logger.debug(u"searchstring: {0}".format(searchstring))
	if searchstring[:2] == "tt":
		movieinfo = tmdb.getMovieInfo('{0}'.format(searchstring))
	else:
		results = tmdb.search(searchstring)
		if results:
			firstresult = results[0]
			movieinfo = firstresult.info()
		else:
			#search again for movie without the year
			searchstring = re.sub(" \([0-9]{4}\)", "", searchstring)
			results = tmdb.search(searchstring)
			if results:
				firstresult = results[0]
				movieinfo = firstresult.info()
			else:
				logger.error(u"Can't find any matches for {0}: {1}".format(nfotype, searchstring))
	imdb_id = movieinfo["imdb_id"]
	title = movieinfo["original_name"]
	logger.info(u"Found result for {0} -> Fullname: {1} imdb_id: {2}".format(searchstring, title, imdb_id))
	return title, imdb_id
Example #4
0
	def action(self, query, args=None):
		with db_lock:
	
			if query == None:
				return
	
			sqlResult = None
			attempt = 0
	
			while attempt < 5:
				try:
					if args == None:
						logger.debug("{0}: {1}".format(self.filename, query))
						#print query
						sqlResult = self.connection.execute(query)
					else:
						logger.debug("{0}: {1} with args {2}".format(self.filename, query, args))
						#print query, args
						sqlResult = self.connection.execute(query, args)
					self.connection.commit()
					# get out of the connection attempt loop since we were successful
					break
				except sqlite3.OperationalError, e:
					if "unable to open database file" in e.message or "database is locked" in e.message:
						logger.warning(u"DB error: ".format(ex(e)))
						#print "error(e)"
						attempt += 1
						time.sleep(1)
					else:
						logger.error(u"DB error: ".format(ex(e)))
						#print "error(e)"
						raise
				except sqlite3.DatabaseError, e:
					logger.error(u"Fatal error executing query: ".format(ex(e)))
					#print "error(e)"
					raise
Example #5
0
    def _sendBoxcar(self, msg, title, email, subscribe=False):
        msg = msg.strip()
        curUrl = API_URL
        data = urllib.urlencode({
                'email': email,
                'notification[from_screen_name]': title,
                'notification[message]': msg.encode('utf-8'),
                'notification[from_remote_service_id]': int(time.time())
                })
        if subscribe: # subscription notification
            data = urllib.urlencode({'email': email})
            curUrl = curUrl + "/subscribe"

        req = urllib2.Request(curUrl)
        try:
            handle = urllib2.urlopen(req, data)
            handle.close()
        except urllib2.URLError, e:
            if not hasattr(e, 'code'):
                logger.error("Boxcar notification failed. {0}".format(ex(e)))
                return False
            else:
                logger.warning("Boxcar notification failed. Error code: {0}".format(str(e.code)))

            if e.code == 404: #HTTP status 404 if the provided email address isn't a Boxcar user.
                logger.warning("Username is wrong/not a boxcar email. Boxcar will send an email to it")
                return False
            elif e.code == 401: #For HTTP status code 401's, it is because you are passing in either an invalid token, or the user has not added your service.
                if subscribe: #If the user has already added your service, we'll return an HTTP status code of 401.
                    logger.error("Already subscribed to service")
                    # i dont know if this is true or false ... its neither but i also dont know how we got here in the first place
                    return False
                else: #HTTP status 401 if the user doesn't have the service added
                    subscribeNote = self._sendBoxcar(msg, title, email, True)
                    if subscribeNote:
                        logger.debug("Subscription send")
                        return True
                    else:
                        logger.error("Subscription could not be send")
                        return False
            elif e.code == 400: #If you receive an HTTP status code of 400, it is because you failed to send the proper parameters
                logger.error("Wrong data send to boxcar")
                return False
def buildMediaElement(mediaelement, theid):
	#check if given id is already in Database and get the lastviewed value to compare if its the same entry.
	if mediaelement:
		logger.info(u"processing file: {0}".format(mediaelement["thepath"]))
		logger.debug(u"mediatype: {0}, directory: {1}".format(mediaelement["type"], mediaelement["directory"]))
		mediaelement["id"] = theid
		mediaelement["duration"] = helper.getVideoDuration(theid)
		mediaelement["viewed"], mediaelement["lastviewed"] = getDurationFromLog(theid)
		mediaelement["process"] = helper.getProcess(mediaelement["duration"], mediaelement["viewed"])
		#quit here if process is not enough... (saves time)
		# if int(mediaelement["process"]) < int(config.min_progress):
		# 	logger.error(u"File with the ID: {0}, has been viewed {1}% we need at least {2}%... skipping it".format(mediaelement["id"], mediaelement["process"], config.min_progress))
		# 	return None
		# else:
			#currently only used for movies... idk if its possible to scrobble this for series.
			#mediaelement["lastviewedstamp"] = calendar.timegm(mediaelement["lastviewed"].timetuple())
		mediaelement["lastviewedstamp"] = time.mktime(mediaelement["lastviewed"].timetuple())
			#generate timestamp from lastviewed (datetime obj)
			#d = datetime.datetime.now()
			#calendar.timegm(d.timetuple())
	
			#timestamp is needed for scrobbling last viewed date and to save it in database...
	
			#generate datetime from timestamp
			#datetime.datetime.utcfromtimestamp(1341237828)
			
			#handling for mediatype series
		if mediaelement["type"] == "series":
			try:
				mediaelement["tvdb_id"], mediaelement["name"] = helper.checkNFO(mediaelement["thepath"], "series")
				mediaelement["season"], mediaelement["episode"] = helper.checkNFO(mediaelement["thepath"], "episode")
			except:
				logger.error(u"Could not create {0} MediaElement".format(mediaelement["type"]))
				return None
		#handling for mediatype movies
		if mediaelement["type"] == "movie":
			try:
				mediaelement["name"], mediaelement["imdb_id"], mediaelement["year"], mediaelement["hasnfo"] = helper.checkNFO(mediaelement["thepath"], "movie")
			except:
				logger.error(u"Could not create {0} MediaElement".format(mediaelement["type"]))
				return None
		#log the created mediaobject in debug mode
		logger.debug(u"MediaElement successfully created: {0}".format(mediaelement))
		
		#insert created infos in database if activated
		if config.use_database:
			helper.mediaelementToDatabase(mediaelement)
			
		return mediaelement
	else:
		logger.error(u"File with the ID: {0} seems not to be a media file that i currently support")
		return None
Example #7
0
def checkNFO(filepath, nfotype):
	hasnfo = False
	#check the nfo for the needed id stuff...
	#check if there is an nfo file... if not, f**k it and try to get infos from tvdb...
	if nfotype == "series":
		directory = os.path.dirname(filepath)
		directory = re.sub(r'Staffel \d{2}|Season \d{2}', '', directory)
		nfofile = os.path.join(directory, "tvshow.nfo")
		try:
			dom = parse(nfofile)
			seriesidTag = dom.getElementsByTagName('id')[0].toxml()
			seriesid=seriesidTag.replace('<id>','').replace('</id>','')
			try:
				nameTag = dom.getElementsByTagName('showtitle')[0].toxml()
				name=nameTag.replace('<showtitle>','').replace('</showtitle>','')
			except:
				nameTag = dom.getElementsByTagName('title')[0].toxml()
				name=nameTag.replace('<title>','').replace('</title>','')
			logger.debug(u"SeriesID for {0} is: {1}".format(name, seriesid))
			return seriesid, name
		except:
			#TODO: fix some unicode errors here...
			logger.error(u"cant find/open file: {0}".format(nfofile))
			if config.try_guessing:
				logger.info(u"Trying to guess infos from Filename...")
				seriesname = os.path.basename(filepath)
				p = re.match(seriesregex, seriesname)
				name = p.group("name").replace(".", " ").strip()
				season = p.group("season")
				episode = p.group("episode")
				logger.debug(u"Type: {3}, Name: {0}, Season: {1}, Episode: {2}".format(name, season, episode, nfotype))
				t = tvdb_api.Tvdb()
				showinfo = t[name]	
				tvdb_id = showinfo["id"]
				realname = showinfo["seriesname"]
				year = showinfo["firstaired"]
				#logger.debug("tvdb gave the following keys: {0}".format(showinfo.data.keys()))
				logger.info(u"Found result for {0} -> Fullname: {1}, tvdb_id: {2}, Year: {3}".format(seriesname, realname, tvdb_id, year))
				return tvdb_id, realname
			else:
				logger.error(u"Please enable try_guessing in settings or create an tvshow.nfo for: {0}".format(directory))
			return 0

		

	if nfotype == "episode":
		filename, extension = os.path.splitext(filepath)
		nfofile = filename + ".nfo"
		try:
			dom = parse(nfofile)
			episodeTag = dom.getElementsByTagName('episode')[0].toxml()
			episode=episodeTag.replace('<episode>','').replace('</episode>','')
			seasonTag = dom.getElementsByTagName('season')[0].toxml()
			season=seasonTag.replace('<season>','').replace('</season>','')
			episodeTag = dom.getElementsByTagName('episode')[0].toxml()
			episode=episodeTag.replace('<episode>','').replace('</episode>','')
			logger.info(u'TVSHOW info -> Season: {0}, Episode: {1}'.format(season, episode))
			return season, episode
		except:
			logger.error(u"Cant find/open/parse file: {0}".format(nfofile))
			if config.try_guessing:
				logger.info(u"try to guess infos from Filename...")
				seriesname = os.path.basename(filepath)
				p = re.match(seriesregex, seriesname)
				name = p.group("name").replace(".", " ").strip()
				season = p.group("season")
				episode = p.group("episode")
				logger.debug(u"Type: {3}, Series: {0}, Season: {1}, Episode: {2}".format(seriesname, season, episode, nfotype)) 
				return season, episode
			else:
				logger.error(u"Please enable try_guessing in settings or create an .nfo for: {0}".format(directory))
			return 0

	if nfotype == "movie":
		#order of use: .nfo, .imdb, try_guessing
		filename, extension = os.path.splitext(filepath)
		nfofile = filename + ".nfo"
		if os.path.exists(nfofile):
			hasnfo = True
		try:
			dom = parse(nfofile)
			tvdb_idtag = dom.getElementsByTagName('id')[0].toxml()
			tvdb_id=tvdb_idtag.replace('<id>','').replace('</id>','')
			nametag = dom.getElementsByTagName('title')[0].toxml()
			name=nametag.replace('<title>','').replace('</title>','')
			if name[:4].lower() in config.the_srings:
				name = name[4:] + ', ' + name[:4].strip()
			yeartag = dom.getElementsByTagName('year')[0].toxml()
			year=yeartag.replace('<year>','').replace('</year>','')
			logger.info(u'Movie info -> Name: {0}, Year: {1}, imdb_id: {2}'.format(name, year, tvdb_id))
			return name, tvdb_id, year
		except:
			logger.error(u"Cant find/open file: {0}".format(nfofile))
			imdbcheck = checkIMDB(filename)
			if imdbcheck:
				searchstring = imdbcheck
			else:
				searchstring = None

			#only use try_guessing if there was no imdb file...
			if config.try_guessing and not searchstring:
				logger.info(u"try to guess infos from Filename...")
				try:
					moviename = os.path.basename(filepath)
					for junk in config.removejunk:
						moviename = moviename.replace(junk,'')
					p = re.match(movieregex, moviename)
					name = p.group("name").replace("."," ").replace("-"," ").strip()
					if name[:4].lower() in config.the_srings:
						name = name[4:] + ', ' + name[:4].strip()
					year = p.group("year")
					searchstring = "{0} ({1})".format(name, year)
				except:
					moviename = os.path.dirname(filepath)
					for junk in config.removejunk:
						moviename = moviename.replace(junk,'')
					directory, moviename = os.path.split(moviename)
					p = re.match(movieregex, moviename)
					name = p.group("name").replace("."," ").strip()
					year = p.group("year")
					searchstring = "{0} ({1})".format(name, year)

				logger.debug(u"Type: {3}, Name: {0}, Year: {1}, Searchstring: {2}".format(name, year, searchstring, nfotype))
				#we need imdb id for scrobbleing to trakt, so lets make a moviedb lookup here to get these infos (especially if there is no year in the name....)
				#this ALWAYS uses the first resault that comes from tmdb...
			else:
				logger.error(u"Please enable try_guessing in settings or create an .nfo for: {0}".format(filepath))
				return 0

			if searchstring:
				title, imdb_id = tmdbsearch(searchstring)
				return title, imdb_id, year, hasnfo
			else:
				logger.error(u"Something went terrible wrong here...")
				return 0
# Root path
path = os.path.dirname(os.path.abspath( __file__ ))

# Insert local directories into path
sys.path.insert(0, os.path.join(path, 'lib'))

#TODO: cleanup!

#check if debugmode is acitvated
try:
	debugfile = open('/var/packages/MediaServer/etc/dmsinfo.conf')
	filelines = debugfile.readlines()
	debugfile.close()
	value = filelines[-1].replace("loglevel_mediaservice=\"","").replace("\"\n","")
	if int(value) < 3:
		logger.error(u"MediaServer not running in Debugmode!")
		sys.exit(u"Please enable Debugmode for MediaServer first!")
	else:
		logger.debug(u"MediaServer running in Debugmode")
except:
	logger.error(u"Can't check if your MeidaServer runs in Debugmode or not...")

def getDurationFromLog(theid):
	dates = idtimes[theid]
	
	startdate = dates[0]
	try:
		enddate = dates[-1]
	except:
		enddate = startdate