# Author: Nico Berlee http://nico.berlee.nl/ # URL: http://code.google.com/p/sickbeard/ # # This file is part of SickGear. # # SickGear 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. # # SickGear 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 SickGear. If not, see . import urllib, urllib2 import sickbeard import telnetlib import re from sickbeard import logger from sickbeard.exceptions import ex try: import xml.etree.cElementTree as etree except ImportError: import xml.etree.ElementTree as etree class NMJNotifier: def notify_settings(self, host): """ Retrieves the settings from a NMJ/Popcorn hour host: The hostname/IP of the Popcorn Hour server Returns: True if the settings were retrieved successfully, False otherwise """ # establish a terminal session to the PC terminal = False try: terminal = telnetlib.Telnet(host) except Exception: logger.log(u"Warning: unable to get a telnet session to %s" % (host), logger.WARNING) return False # tell the terminal to output the necessary info to the screen so we can search it later logger.log(u"Connected to %s via telnet" % (host), logger.DEBUG) terminal.read_until("sh-3.00# ") terminal.write("cat /tmp/source\n") terminal.write("cat /tmp/netshare\n") terminal.write("exit\n") tnoutput = terminal.read_all() database = "" device = "" match = re.search(r"(.+\.db)\r\n?(.+)(?=sh-3.00# cat /tmp/netshare)", tnoutput) # if we found the database in the terminal output then save that database to the config if match: database = match.group(1) device = match.group(2) logger.log(u"Found NMJ database %s on device %s" % (database, device), logger.DEBUG) sickbeard.NMJ_DATABASE = database else: logger.log(u"Could not get current NMJ database on %s, NMJ is probably not running!" % (host), logger.WARNING) return False # if the device is a remote host then try to parse the mounting URL and save it to the config if device.startswith("NETWORK_SHARE/"): match = re.search(".*(?=\r\n?%s)" % (re.escape(device[14:])), tnoutput) if match: mount = match.group().replace("127.0.0.1", host) logger.log(u"Found mounting url on the Popcorn Hour in configuration: %s" % (mount), logger.DEBUG) sickbeard.NMJ_MOUNT = mount else: logger.log(u"Detected a network share on the Popcorn Hour, but could not get the mounting url", logger.WARNING) return False return True def notify_snatch(self, ep_name): return False #Not implemented: Start the scanner when snatched does not make any sense def notify_download(self, ep_name): if sickbeard.USE_NMJ: self._notifyNMJ() def notify_subtitle_download(self, ep_name, lang): if sickbeard.USE_NMJ: self._notifyNMJ() def notify_git_update(self, new_version): return False # Not implemented, no reason to start scanner. def test_notify(self, host, database, mount): return self._sendNMJ(host, database, mount) def _sendNMJ(self, host, database, mount=None): """ Sends a NMJ update command to the specified machine host: The hostname/IP to send the request to (no port) database: The database to send the requst to mount: The mount URL to use (optional) Returns: True if the request succeeded, False otherwise """ # if a mount URL is provided then attempt to open a handle to that URL if mount: try: req = urllib2.Request(mount) logger.log(u"Try to mount network drive via url: %s" % (mount), logger.DEBUG) handle = urllib2.urlopen(req) except IOError, e: if hasattr(e, 'reason'): logger.log(u"NMJ: Could not contact Popcorn Hour on host %s: %s" % (host, e.reason), logger.WARNING) elif hasattr(e, 'code'): logger.log(u"NMJ: Problem with Popcorn Hour on host %s: %s" % (host, e.code), logger.WARNING) return False except Exception, e: logger.log(u"NMJ: Unknown exception: " + ex(e), logger.ERROR) return False # build up the request URL and parameters UPDATE_URL = "http://%(host)s:8008/metadata_database?%(params)s" params = { "arg0": "scanner_start", "arg1": database, "arg2": "background", "arg3": "" } params = urllib.urlencode(params) updateUrl = UPDATE_URL % {"host": host, "params": params} # send the request to the server try: req = urllib2.Request(updateUrl) logger.log(u"Sending NMJ scan update command via url: %s" % (updateUrl), logger.DEBUG) handle = urllib2.urlopen(req) response = handle.read() except IOError, e: if hasattr(e, 'reason'): logger.log(u"NMJ: Could not contact Popcorn Hour on host %s: %s" % (host, e.reason), logger.WARNING) elif hasattr(e, 'code'): logger.log(u"NMJ: Problem with Popcorn Hour on host %s: %s" % (host, e.code), logger.WARNING) return False except Exception, e: logger.log(u"NMJ: Unknown exception: " + ex(e), logger.ERROR) return False # try to parse the resulting XML try: et = etree.fromstring(response) result = et.findtext("returnValue") except SyntaxError, e: logger.log(u"Unable to parse XML returned from the Popcorn Hour: %s" % (e), logger.ERROR) return False # if the result was a number then consider that an error if int(result) > 0: logger.log(u"Popcorn Hour returned an errorcode: %s" % (result), logger.ERROR) return False else: logger.log(u"NMJ started background scan", logger.MESSAGE) return True def _notifyNMJ(self, host=None, database=None, mount=None, force=False): """ Sends a NMJ update command based on the SB config settings host: The host to send the command to (optional, defaults to the host in the config) database: The database to use (optional, defaults to the database in the config) mount: The mount URL (optional, defaults to the mount URL in the config) force: If True then the notification will be sent even if NMJ is disabled in the config """ if not sickbeard.USE_NMJ and not force: logger.log("Notification for NMJ scan update not enabled, skipping this notification", logger.DEBUG) return False # fill in omitted parameters if not host: host = sickbeard.NMJ_HOST if not database: database = sickbeard.NMJ_DATABASE if not mount: mount = sickbeard.NMJ_MOUNT logger.log(u"Sending scan command for NMJ ", logger.DEBUG) return self._sendNMJ(host, database, mount) notifier = NMJNotifier