コード例 #1
0
ファイル: torrent.py プロジェクト: nemec/Automaton
    def search(self, name):
        """Perform a search through each of the provided search urls for the
    given name. Return a list of .torrent files.

    """
        results = []
        for url in self.search_urls.values():
            try:
                page = urllib.urlopen(url.format(name)).read()
                soup = BeautifulSoup(page)
                table = soup.find("table").findAll("tr")
                # soup.findAll(attrs={'class':"vertTh"})
                for result in table:
                    if str(result) != "\n" and not result.attrs:
                        vals = result.findAll("td")
                        if len(vals) == 4:
                            seeders = int(vals[2].contents[0])
                            leechers = int(vals[3].contents[0])
                            info = vals[1].findNext("a")
                            # title = dict(info.attrs)['title']
                            # details = "Details for "
                            # if title.startswith(details):
                            #  title = title[len(details):]
                            link = dict(info.findNext("a").attrs)["href"]
                            results.append((seeders, link))
            except Exception as err:
                logger.log("Error performing torrent search", err)
                continue
            top = None
            try:
                top = max(results)[1]
            except ValueError:
                pass
            return top
コード例 #2
0
ファイル: torrent.py プロジェクト: SuicideSin/Automaton
    def search(self, name):
        """Perform a search through each of the provided search urls for the
    given name. Return a list of .torrent files.

    """
        results = []
        for url in self.search_urls.values():
            try:
                page = urllib.urlopen(url.format(name)).read()
                soup = BeautifulSoup(page)
                table = soup.find('table').findAll('tr')
                #soup.findAll(attrs={'class':"vertTh"})
                for result in table:
                    if str(result) != "\n" and not result.attrs:
                        vals = result.findAll('td')
                        if len(vals) == 4:
                            seeders = int(vals[2].contents[0])
                            leechers = int(vals[3].contents[0])
                            info = vals[1].findNext('a')
                            #title = dict(info.attrs)['title']
                            #details = "Details for "
                            #if title.startswith(details):
                            #  title = title[len(details):]
                            link = dict(info.findNext('a').attrs)['href']
                            results.append((seeders, link))
            except Exception as err:
                logger.log("Error performing torrent search", err)
                continue
            top = None
            try:
                top = max(results)[1]
            except ValueError:
                pass
            return top
コード例 #3
0
 def fire(self, *args, **kargs):
     """Execute all callables registered to this event."""
     for handler in self.handlers:
         try:
             handler(*args, **kargs)
         except Exception as err:  # pylint: disable-msg=W0703
             # We don't want a rogue handler to mess up everyone else
             logger.log("Exception encountered during event handling", err)
コード例 #4
0
ファイル: registrar.py プロジェクト: nemec/Automaton
 def fire(self, *args, **kargs):
   """Execute all callables registered to this event."""
   for handler in self.handlers:
     try:
       handler(*args, **kargs)
     except Exception as err:  # pylint: disable-msg=W0703
       # We don't want a rogue handler to mess up everyone else
       logger.log("Exception encountered during event handling", err)
コード例 #5
0
ファイル: weather.py プロジェクト: SuicideSin/Automaton
    def __init__(self, registrar):
        super(Weather, self).__init__(registrar)
        self.ttl = 3600  # seconds
        self.last = None  # last weather value recorded, tuple of (location, value)
        settings = ConfigParser.SafeConfigParser()
        settings.read(utils.get_plugin_settings_paths(__name__))
        try:
            self.api_key = settings.get("Settings", "wunderground_api_key")
        except ConfigParser.Error:
            raise plugin.PluginLoadError("Must provide "
                                         "wunderground_api_key in Settings.")
        self.format = 'F'
        try:
            scale = settings.get("Settings", "temp_scale").upper()
            if scale in ('F', 'C', 'K'):
                self.format = scale
        except ConfigParser.Error:
            pass

        self.max_cache_distance = 25
        try:
            self.max_cache_distance = int(
                settings.get("Settings", "max_cache_distance"))
        except (ConfigParser.Error, TypeError):
            pass
        self.CacheItem = namedtuple('CacheItem', ['expires', 'val'])

        self.locations = {}
        try:
            self.locations = dict(
                (key, value) for key, value in settings.items("Aliases"))
        except ConfigParser.NoSectionError:
            logger.log("No section 'Aliases' found in weather config file.")

        # remove spaces after commas - these would screw up lat/long searches
        for loc in self.locations:
            self.locations[loc] = re.sub(',\s*', ',', self.locations[loc])
        # dict of location:CacheItem pairs
        # if current time in sec since epoch is less than ttl, cache has expired
        # should return val if cache is still valid
        self.cache = {}

        grammar = {
            "when": ["for", "be like"],
            "where": ["at", "near", "in", 'for'],
        }

        registrar.register_service("weather",
                                   self.execute,
                                   grammar=grammar,
                                   usage="""
             USAGE: %s [location|alias]
             Returns the weather for a provided location or alias. If no
             location is provided, gets the weather data for the last
             recorded position.
            """,
                                   namespace=__name__)
コード例 #6
0
ファイル: weather.py プロジェクト: nemec/Automaton
  def __init__(self, registrar):
    super(Weather, self).__init__(registrar)
    self.ttl = 3600  # seconds
    self.last = None  # last weather value recorded, tuple of (location, value)
    settings = ConfigParser.SafeConfigParser()
    settings.read(utils.get_plugin_settings_paths(__name__))
    try:
      self.api_key = settings.get("Settings", "wunderground_api_key")
    except ConfigParser.Error:
      raise plugin.PluginLoadError("Must provide "
        "wunderground_api_key in Settings.")
    self.format = 'F'
    try:
      scale = settings.get("Settings", "temp_scale").upper()
      if scale in ('F', 'C', 'K'):
        self.format = scale
    except ConfigParser.Error:
      pass

    self.max_cache_distance = 25
    try:
      self.max_cache_distance = int(settings.get("Settings",
                                                  "max_cache_distance"))
    except (ConfigParser.Error, TypeError):
      pass
    self.CacheItem = namedtuple('CacheItem', ['expires', 'val'])

    self.locations = {}
    try:
      self.locations = dict((key, value) for key, value in
        settings.items("Aliases"))
    except ConfigParser.NoSectionError:
      logger.log("No section 'Aliases' found in weather config file.")

    # remove spaces after commas - these would screw up lat/long searches
    for loc in self.locations:
      self.locations[loc] = re.sub(',\s*', ',', self.locations[loc])
    # dict of location:CacheItem pairs
    # if current time in sec since epoch is less than ttl, cache has expired
    # should return val if cache is still valid
    self.cache = {}
    
    grammar = {
      "when": ["for", "be like"],
      "where": ["at","near","in", 'for'],
    }

    registrar.register_service("weather", self.execute, grammar=grammar,
      usage="""
             USAGE: %s [location|alias]
             Returns the weather for a provided location or alias. If no
             location is provided, gets the weather data for the last
             recorded position.
            """,
      namespace=__name__)
コード例 #7
0
ファイル: torrent.py プロジェクト: nemec/Automaton
    def begin_torrent(self, movie_name):
        """Attempt to start a torrent program to begin download of the torrent."""
        filename = os.path.join(self.settings.get("Downloads", "download_dir"), os.path.basename(movie_name))
        try:
            urllib.urlretrieve(movie_name, filename)
        except IOError as err:
            logger.log("Error downloading torrent:", err)
            raise Exception("Error downloading torrent.")

        out = sp.call(["transmission-remote", "-a {0}".format(filename)])
        succ = out.lower().find("success") > 0
        if not succ:
            logger.log(out)
        return succ
コード例 #8
0
ファイル: memo.py プロジェクト: nemec/Automaton
  def execute(self, **kwargs):
    """Insert memo text as a new line in the memo file.

    Keyword arguments:
    memo -- the text to insert into the memo file

    """
    if "memo" in kwargs:
      try:
        with open(self.settings.get('Settings', 'memo_file'), "a") as fil:
          fil.write(kwargs["memo"] + "\n")
        return "Inserted into memo file."
      except IOError, err:
        logger.log("Error while writing to file", err)
        raise plugin.UnsuccessfulExecution("Error while writing to file.")
コード例 #9
0
ファイル: torrent.py プロジェクト: SuicideSin/Automaton
    def begin_torrent(self, movie_name):
        """Attempt to start a torrent program to begin download of the torrent."""
        filename = os.path.join(self.settings.get("Downloads", "download_dir"),
                                os.path.basename(movie_name))
        try:
            urllib.urlretrieve(movie_name, filename)
        except IOError as err:
            logger.log("Error downloading torrent:", err)
            raise Exception("Error downloading torrent.")

        out = sp.call(["transmission-remote", "-a {0}".format(filename)])
        succ = out.lower().find("success") > 0
        if not succ:
            logger.log(out)
        return succ
コード例 #10
0
ファイル: base.py プロジェクト: nemec/Automaton
  def registerClient(self, appname=None, publish_url=None):
    """
    Register a client service with the server. Calculate a UUID that will
    identify which plugins are loaded for each client service and return it
    to the caller.

    """
    ident = str(uuid.uuid1())
    while ident in self.client_manager.registered_clients:
      ident = str(uuid.uuid1())
    if appname is not None:
      ident = re.sub('[\W_]+', '', appname) + '-' + ident
    logger.log("Registering client {0}".format(ident))
    self.client_manager.add_client(ident, publish_url=publish_url)
    return ident
コード例 #11
0
ファイル: torrent.py プロジェクト: SuicideSin/Automaton
    def execute(self, **kwargs):
        """Download and start the provided media. Downloads the link with the
    highest seed count.

    Keyword arguments:
    file -- the .torrent file to find and download
    name -- either an IMDB link to the media or the media name to search for

    """
        if not self.settings.has_option("Downloads", "download_dir"):
            raise plugin.UnsuccessfulExecution(
                "Could not continue - "
                "no download directory in settings.")

        if "file" in kwargs:
            tfile = kwargs["file"]
            movie_name = "torrent"
        elif "name" in kwargs:
            movie_name = kwargs["name"]
            if movie_name.startswith("http://www.imdb.com/"):
                try:
                    response = urllib2.urlopen(movie_name)
                    data = response.read()
                    match = re.search("<title>(.*?)</title>", data)
                    if match:
                        title_extra = " - IMDb"
                        movie_name = match.group(1)
                        if movie_name.endswith(title_extra):
                            movie_name = movie_name[0:len(movie_name) -
                                                    len(title_extra)]
                    else:
                        return "Error finding IMDB movie title."
                except urllib2.URLError:
                    return "Error loading IMDB link."
            tfile = self.search(movie_name)
            if not tfile:
                return "Could not find any torrents."
        else:
            raise plugin.UnsuccessfulExecution("No media name provided.")

        try:
            if self.begin_torrent(tfile):
                return "Now downloading {0}".format(movie_name)
            else:
                return "Torrent downloaded, but could not be started."
        except Exception as err:
            logger.log("Error starting torrent", err)
            raise plugin.UnsuccessfulExecution("Error starting torrent.")
コード例 #12
0
ファイル: base.py プロジェクト: nemec/Automaton
  def unregisterClient(self, clientid):
    """Unregister a client service from the server. Any further use of its
    clientid will result in a ServiceNotRegisteredError.
    
    Arguments:
    clientid -- a unique id assigned to the client when registering

    Raises:
    ClientNotRegisteredError

    """
    if clientid not in self.client_manager.registered_clients:
      raise exceptions.ClientNotRegisteredError()

    logger.log("Unregistering client {0}".format(clientid))
    del self.client_manager.registered_clients[clientid]
コード例 #13
0
ファイル: schedule.py プロジェクト: nemec/Automaton
 def _executionthread(self):
   """Continually poll the queue for tasks to be run."""
   while True:
     expire, (command, namespace, args) = self.remove_task_if_past()
     if command is not None:
       val = None
       try:
         val = self.registrar.request_service(
           command, namespace=namespace, argdict=args)
       except Exception as err:
         val = "Exception encountered: {0}".format(err)
       logger.log("Scheduled command {0} has been run, with "
                  "return value: \"{1}\"".format(command, val))
     else:
       twait = max((expire - datetime.datetime.now()).total_seconds(), 0)
       self.event.wait(twait)
       self.event.clear()
コード例 #14
0
ファイル: cherry.py プロジェクト: nemec/Automaton
 def handle_error(self):
   import sys, traceback
   exc_type, exc_value, exc_traceback = sys.exc_info()
   cherrypy.response.status = 500
   logger.log(''.join(traceback.format_exception(
     exc_type, exc_value, exc_traceback)))
   cherrypy.response.headers['Content-Type'] = 'application/json'
   try:
     cherrypy.response.body = [''.join(self.make_error_dict(
       500, "Unexpected exception occurred during execution.",
       kind=exc_type.__name__))]
   except Exception as err:
     print err
     err = cherrypy._cperror.bare_error()
     status = err[0]
     message = '\n'.join(err[2])
     cherrypy.response.body = [''.join(self.make_error_dict(status, message))]
コード例 #15
0
ファイル: memo.py プロジェクト: SuicideSin/Automaton
    def execute(self, **kwargs):
        """Insert memo text as a new line in the memo file.

    Keyword arguments:
    memo -- the text to insert into the memo file

    """
        if "memo" in kwargs:
            try:
                with open(self.settings.get('Settings', 'memo_file'),
                          "a") as fil:
                    fil.write(kwargs["memo"] + "\n")
                return "Inserted into memo file."
            except IOError, err:
                logger.log("Error while writing to file", err)
                raise plugin.UnsuccessfulExecution(
                    "Error while writing to file.")
コード例 #16
0
ファイル: map.py プロジェクト: SuicideSin/Automaton
  def interpret(self, arg='', **kwargs):
    """Retrieve directions from Google Maps and format them in a
       human-readable manner.

    Keyword arguments:
    to -- the destination address
    from -- the source address (default: current location, if available)

    """
    if "to" in kwargs:
      destination = kwargs["to"]
    else:
      destination = (yield "Please provide a destination.")["_raw"]
      
    origin = kwargs.get("from", '')    
    
    if origin == '':
      try:
        origin = self.registrar.request_service(
          *self.registrar.find_best_service('location'))
      except Exception as error:
        logger.log("Could not determine location", error)
        # raise plugin.UnsuccessfulExecution("Could not determine location.")
        origin = (yield "Could not automatically determine your location. "
                    "Where are you starting from?")["_raw"]

    params = {
      'q': 'from:{0} to:{1}'.format(origin, destination),
      'output': 'json',
      'oe': 'utf8',
    }

    encoded_params = urllib.urlencode(params)
    url = 'http://maps.google.com/maps/nav?' + encoded_params
    request = urllib2.Request(url)
    resp = urllib2.urlopen(request)
    response = json.load(resp)

    status_code = response['Status']['code']
    if status_code == 200:
      yield self.format_directions_for_human(
        response['Directions']['Routes'][0]['Steps'])
      return
    elif status_code == 602:
      raise plugin.UnsuccessfulExecution('malformed query')
    raise plugin.UnsuccessfulExecution("Unknown status code: " + status_code)
コード例 #17
0
ファイル: base.py プロジェクト: nemec/Automaton
  def __init__(self, withgui=False):
    self.withgui = withgui

    self.registrar = registrar.Registrar()

    # A dictionary mapping clientids to registered plugins
    self.client_manager = clientmanager.ClientManager()

    # pylint: disable-msg=C0103
    self.LoadedPlugin = namedtuple('LoadedPlugin', ['obj', 'lock'])
    self.loaded_plugins = {}
    # Update __init__.py in the automaton package when a new plugin is added
    for plugin in automaton.plugins.__all__:
      try:
        self.enablePlugin(plugin)
      except Exception as e:  # pylint: disable-msg=W0703
        logger.log("Error loading module {0}.".format(plugin), e)
コード例 #18
0
ファイル: torrent.py プロジェクト: nemec/Automaton
    def execute(self, **kwargs):
        """Download and start the provided media. Downloads the link with the
    highest seed count.

    Keyword arguments:
    file -- the .torrent file to find and download
    name -- either an IMDB link to the media or the media name to search for

    """
        if not self.settings.has_option("Downloads", "download_dir"):
            raise plugin.UnsuccessfulExecution("Could not continue - " "no download directory in settings.")

        if "file" in kwargs:
            tfile = kwargs["file"]
            movie_name = "torrent"
        elif "name" in kwargs:
            movie_name = kwargs["name"]
            if movie_name.startswith("http://www.imdb.com/"):
                try:
                    response = urllib2.urlopen(movie_name)
                    data = response.read()
                    match = re.search("<title>(.*?)</title>", data)
                    if match:
                        title_extra = " - IMDb"
                        movie_name = match.group(1)
                        if movie_name.endswith(title_extra):
                            movie_name = movie_name[0 : len(movie_name) - len(title_extra)]
                    else:
                        return "Error finding IMDB movie title."
                except urllib2.URLError:
                    return "Error loading IMDB link."
            tfile = self.search(movie_name)
            if not tfile:
                return "Could not find any torrents."
        else:
            raise plugin.UnsuccessfulExecution("No media name provided.")

        try:
            if self.begin_torrent(tfile):
                return "Now downloading {0}".format(movie_name)
            else:
                return "Torrent downloaded, but could not be started."
        except Exception as err:
            logger.log("Error starting torrent", err)
            raise plugin.UnsuccessfulExecution("Error starting torrent.")
コード例 #19
0
ファイル: base.py プロジェクト: nemec/Automaton
  def disallowService(self, clientid, name):
    """Unregister a service from being used with a client.

    Arguments:
    clientid -- a unique id assigned to the client when registering
    name -- the name of the service to enable

    Raises:
    ClientNotRegisteredError
    ServiceNotLoadedException

    """
    name = name.lower()
    client = self.get_client(clientid)
    if name not in client.plugins:
      raise exceptions.ServiceNotRegisteredError(name)

    logger.log("Removing service {0} for client {1}".format(name, clientid))
    client.plugins.remove(name)
コード例 #20
0
ファイル: schedule.py プロジェクト: SuicideSin/Automaton
 def _executionthread(self):
     """Continually poll the queue for tasks to be run."""
     while True:
         expire, (command, namespace, args) = self.remove_task_if_past()
         if command is not None:
             val = None
             try:
                 val = self.registrar.request_service(command,
                                                      namespace=namespace,
                                                      argdict=args)
             except Exception as err:
                 val = "Exception encountered: {0}".format(err)
             logger.log("Scheduled command {0} has been run, with "
                        "return value: \"{1}\"".format(command, val))
         else:
             twait = max((expire - datetime.datetime.now()).total_seconds(),
                         0)
             self.event.wait(twait)
             self.event.clear()
コード例 #21
0
ファイル: base.py プロジェクト: nemec/Automaton
  def start(self):
    """Start the server.
    Ensures any networking is done in a separate thread from the UI.

    """
    if self.withgui:
      try:
        import gtk
        import automaton.lib.ui as ui
        ui.StatusIcon(self)
        thread = threading.Thread(target=self._start)
        thread.setDaemon(True)
        thread.start()
        gtk.gdk.threads_init()
        gtk.main()
        return
      except ImportError:
        logger.log("gtk toolkit not present, so no graphical "
                    "user interface will be available.")
    self._start()
コード例 #22
0
ファイル: base.py プロジェクト: nemec/Automaton
  def allowService(self, clientid, name):
    """Register a service for use by a client.

    Arguments:
    clientid -- a unique id assigned to the client when registering
    name -- the name of the service to enable

    Raises:
    ClientNotRegisteredError
    ServiceNotLoadedException

    """
    name = name.lower()
    client = self.get_client(clientid)
    if name not in self.registrar.services:
      raise exceptions.ServiceNotProvidedError(name)

    if name not in client.plugins:
      logger.log("Adding service {0} for client {1}".format(name, clientid))
      client.plugins.add(name)
コード例 #23
0
ファイル: schedule.py プロジェクト: SuicideSin/Automaton
    def __init__(self, registrar):
        super(Schedule, self).__init__(registrar)
        self.settings = ConfigParser.SafeConfigParser()
        self.settings.read(utils.get_plugin_settings_paths(__name__))

        if not self.settings.has_option("Settings", "queue_file"):
            self.settings.set("Settings", "queue_file",
                              autoplatform.get_existing_file("schedule.queue"))
        else:
            if not os.access(self.settings.get("Settings", "queue_file"),
                             os.W_OK):
                self.settings.set("Settings", "queue_file", None)

        self.queue = PersistentPriorityQueue(
            storagefile=self.settings.get("Settings", "queue_file"))

        if (not self.settings.has_option("Settings", "queue_file")
                or self.settings.get("Settings", "queue_file") is None):
            logger.log(
                "Scheduler could not find an existing queue file and "
                "no write access to create a new one. Any scheduled tasks "
                "will disappear once server is stopped.")

        self.event = threading.Event()
        thread = threading.Thread(target=self._executionthread)
        thread.setDaemon(True)
        thread.start()

        self.registrar.register_service(
            "schedule",
            self.execute,
            grammar={
                "at": ["at"],
                "in": ["in"],
                "command": [],
            },
            usage=
            ("USAGE: schedule WHAT [at WHEN] | [in WHEN]\n"
             "Schedules a command to be run at a specific time, repeating if\n"
             "necessary."),
            namespace=__name__)
コード例 #24
0
 def __init__(self, registrar):
   super(Music, self).__init__(registrar)
   settings = ConfigParser.SafeConfigParser()
   settings.read(utils.get_plugin_settings_paths(__name__))
   hostname = "localhost"
   port = 6600
   try:
     hostname = settings.get("MPD", "hostname")
     port = settings.get("MPD", "port")
   except ConfigParser.NoSectionError:
     raise plugin.PluginLoadError("'MPD' section in config does not exist.")
   except ConfigParser.NoOptionError as err:
     if err.section == "hostname":
       logger.log("MPD hostname not in settings. "
                   "Using default of '{0}'".format(hostname))
     elif err.section == "port":
       logger.log("MPD port not in settings. "
                   "Using default of '{0}'".format(port))
   except TypeError:
     logger.log("Error loading settings for MPD. Using host and port "
                 "{0}:{1}.".format(hostname, port))
   self.client = mpd.MPDClient()
   self.client.connect(hostname, port)
   self.version = tuple(int(i) for i in self.client.mpd_version.split('.'))
   
   registrar.register_service("play", self.play,
     {"target": []}, namespace=__name__)
   registrar.register_service("listen", self.play,
     {"target": ["listen to"]}, namespace=__name__)
   registrar.register_service("pause", self.pause, {}, namespace=__name__)
   registrar.register_service("stop", self.stop, {}, namespace=__name__)
   registrar.register_service("song", self.song, {
     "next": ["next"],
     "previous": ["previous"],
   }, namespace=__name__)
コード例 #25
0
 def handle_error(self):
     import sys, traceback
     exc_type, exc_value, exc_traceback = sys.exc_info()
     cherrypy.response.status = 500
     logger.log(''.join(
         traceback.format_exception(exc_type, exc_value, exc_traceback)))
     cherrypy.response.headers['Content-Type'] = 'application/json'
     try:
         cherrypy.response.body = [
             ''.join(
                 self.make_error_dict(
                     500,
                     "Unexpected exception occurred during execution.",
                     kind=exc_type.__name__))
         ]
     except Exception as err:
         print err
         err = cherrypy._cperror.bare_error()
         status = err[0]
         message = '\n'.join(err[2])
         cherrypy.response.body = [
             ''.join(self.make_error_dict(status, message))
         ]
コード例 #26
0
ファイル: schedule.py プロジェクト: nemec/Automaton
  def __init__(self, registrar):
    super(Schedule, self).__init__(registrar)
    self.settings = ConfigParser.SafeConfigParser()
    self.settings.read(utils.get_plugin_settings_paths(__name__))

    if not self.settings.has_option("Settings", "queue_file"):
      self.settings.set("Settings", "queue_file",
        autoplatform.get_existing_file("schedule.queue"))
    else:
      if not os.access(self.settings.get("Settings", "queue_file"), os.W_OK):
        self.settings.set("Settings", "queue_file", None)

    self.queue = PersistentPriorityQueue(
      storagefile=self.settings.get("Settings", "queue_file"))

    if (not self.settings.has_option("Settings", "queue_file") or
        self.settings.get("Settings", "queue_file") is None):
      logger.log("Scheduler could not find an existing queue file and "
                 "no write access to create a new one. Any scheduled tasks "
                 "will disappear once server is stopped.")

    self.event = threading.Event()
    thread = threading.Thread(target=self._executionthread)
    thread.setDaemon(True)
    thread.start()

    self.registrar.register_service("schedule", self.execute,
      grammar={
        "at": ["at"],
        "in": ["in"],
        "command": [],
      },
      usage=("USAGE: schedule WHAT [at WHEN] | [in WHEN]\n"
            "Schedules a command to be run at a specific time, repeating if\n"
            "necessary."),
      namespace=__name__)
コード例 #27
0
ファイル: base.py プロジェクト: nemec/Automaton
 def reloadPlugin(self, name):
   """Disable and re-enable a plugin, reloading the code from source."""
   if name in self.loaded_plugins:
     plugin = self.loaded_plugins[name]
     plugin.lock.acquire()
     try:
       cmd = reload(__import__('automaton.plugins.{0}'.format(name),
                               fromlist=[name]))
       plugin.obj = getattr(cmd, name)()
       logger.log("Plugin {0} has been successfully reloaded.".format(name))
     except Exception as err:
       self.disablePlugin(name)
       logger.log("Exception encountered reloading {0}. "
                 "Plugin disabled.".format(name), err)
       logger.log(name)
     finally:
       plugin.lock.release()
コード例 #28
0
ファイル: rfid.py プロジェクト: nemec/Automaton
  else:
    data = None
  cursor.close()
  return data


try:
  s = serial.Serial("/dev/ttyUSB0", 2400)
except serial.serialutil.SerialException:
  s = serial.Serial("/dev/ttyUSB1", 2400)

op = {"DBHOST": "localhost", "DBUSER": "******", "DBPASS": ""}
op.update(settings_loader.load_app_settings(sys.argv[0]))

if op["DBPASS"] == "":
  logger.log("Error: no db password provided")
  sys.exit()

try:
  db = pgdb.connect(user=op["DBUSER"], password=op["DBPASS"],
                    host=op["DBHOST"], database="Automaton")
except Exception as e:
  print "Error connecting to database:", e
  sys.exit()

client = ClientWrapper.ClientWrapper(op["THRIFT_SERVER"])
client.open()

try:
  client.registerPlugin("say")
except exceptions.PluginNotLoadedException:
コード例 #29
0
ファイル: AIM.py プロジェクト: nemec/Automaton
 def gotBuddyList(self, l):
     self.activateSSI()
     self.setIdleTime(0)
     self.clientReady()
     logger.log("Client online.")
コード例 #30
0
ファイル: AIM.py プロジェクト: nemec/Automaton
 def clientConnectionFailed(self, connector, reason):
   logger.log("Connection failed: " + str(reason))
   protocol.ReconnectingClientFactory.clientConnectionFailed(self,
                                                   connector, reason)
コード例 #31
0
ファイル: AIM.py プロジェクト: nemec/Automaton
 def clientConnectionLost(self, connector, reason):
   logger.log("Lost connection: " + str(reason))
   if reason.check([exceptions.ClientError]):
     reactor.stop()
コード例 #32
0
ファイル: AIM.py プロジェクト: nemec/Automaton
      'MASTER': '',
      'THRIFT_SERVER': 'tails.local'
     }

settings = ConfigParser.SafeConfigParser()
settings.read(utils.get_app_settings_paths("AIM"))
try:
  if not settings.has_option("AIM", "oscar_host"):
    settings.set("AIM", "oscar_host", "login.oscar.aol.com")
  if not settings.has_option("AIM", "oscar_port"):
    settings.set("AIM", "oscar_port", "5190")

  if not (settings.has_option("AIM", "username") and
          settings.has_option("AIM", "password") and
          settings.has_option("AIM", "master")):
    logger.log("Missing necessary credentials to log in to AIM.")
    sys.exit()
except ConfigParser.NoSectionError as err:
  print "AIM config file has no section '{0}'".format(err.section)


class B(oscar.BOSConnection):
    capabilities = [oscar.CAP_CHAT]

    def __init__(self, s, p, f):
      self.factory = f
      oscar.BOSConnection.__init__(self, s, p)

    def initDone(self):
        self.requestSelfInfo().addCallback(self.gotSelfInfo)
        self.requestSSI().addCallback(self.gotBuddyList)
コード例 #33
0
ファイル: weather.py プロジェクト: SuicideSin/Automaton
    def execute(self, **kwargs):
        """Retrieve the latest weather for the provided location for the given time.
    
    Keyword arguments:
    last -- if True, return the last retrieved weather data
    where -- the location to get weather data for (defaults to current location)
      Can be an alias (defined in the configuration file)
    when -- one of 'today' or 'tomorrow' (default 'today')

    """
        if kwargs.get("last", None):
            if self.last:
                if time.time() < self.last[1].ttl:
                    yield "Data for {0}: {1}".format(self.last[0],
                                                     self.last[1].val)
                    return
                else:
                    self.last = None
            raise plugin.UnsuccessfulExecution("No recent data stored.")

        if "where" not in kwargs:
            try:
                # Try to call on latitude plugin to get the current location
                kwargs["where"] = re.sub(
                    "[() ]", "",
                    self.registrar.request_service('location', noreverse=True))
            except:
                #raise plugin.UnsuccessfulExecution("No current location is available.")
                kwargs["where"] = (yield
                                   "I could not find your current location, "
                                   "where do you want weather for?")["_raw"]

        forecastday = 0
        if "when" in kwargs:
            if kwargs["when"].upper() == "TODAY":
                forecastday = 0
            if kwargs["when"].upper() == "TOMORROW":
                forecastday = 1

        location = kwargs["where"]

        # Sub any aliases
        if location in self.locations:
            location = self.locations[location]

        # Look in the cache, pick item with minimum distance from location, then
        # check to see if it's within the tolerance
        if len(self.cache) > 0:
            cache_hit_distances = ((item, self.distance(location, item))
                                   for item in self.cache)

            closest_hit = min(cache_hit_distances, key=lambda x: x[1])[0]
            if closest_hit < self.max_cache_distance:
                if time.time() < self.cache[location].expires:
                    yield self.cache[location].val
                    return
                else:
                    self.cache.pop(location, None)

        url = "http://api.wunderground.com/api/{0}/forecast".format(
            self.api_key)
        query = "/q/{0}.json".format(re.sub('\s+', '_', location))

        resp = json.load(urllib2.urlopen(urllib2.Request(url + query)))
        if not resp:
            raise plugin.UnsuccessfulExecution("Parsing failed for location " +
                                               location)

        ret = None
        if 'results' in resp['response']:
            results = resp['response']['results']
            while len(results) > 1:
                ret = "Did you mean "
                states = set()
                countries = set()
                for result in results:
                    if result['state'] != '':
                        states.add(result['state'].lower())
                    elif result['country'] != '':
                        countries.add(result['country'].lower())
                if len(states) > 0:
                    ret += "the state"
                    if len(states) > 1:
                        ret += "s"
                    ret += ' ' + utils.humanize_join(
                        abbrev.states.try_long(x).capitalize() for x in states)
                if len(countries) > 0:
                    if len(states) > 0:
                        ret += " or "
                    ret += "the country"
                    if len(countries) > 1:
                        ret += "s"
                    ret += ' ' + utils.humanize_join(
                        abbrev.countries.try_long(x).capitalize()
                        for x in countries)
                ret += "?"
                # TODO better parsing of conversation arguments
                cont = (yield ret)['_raw'].split()
                old_results = results
                results = []
                for word in cont:
                    # Try to convert long name to abbrev
                    state = abbrev.states.try_short(word)
                    country = abbrev.countries.try_short(word)
                    for result in old_results:
                        if result['state'].lower() == state.lower():
                            results.append(result)
                        elif result['country'].lower() == country.lower():
                            results.append(result)
                if len(results) == 0:  # Invalid input was given, back up
                    results = old_results
            query = results[0]['l'] + '.json'
            resp = json.load(urllib2.urlopen(urllib2.Request(url + query)))
            if not resp:
                raise plugin.UnsuccessfulExecution(
                    "Parsing failed for location " + location)
        try:
            forecast = resp['forecast']['txt_forecast']['forecastday']
            ret = forecast[forecastday]['fcttext']
        except KeyError as err:
            logger.log("Error parsing forecast:", err)

        if not ret:
            raise plugin.UnsuccessfulExecution(
                "There is no weather data for this location")

        self.last = (location, self.CacheItem(time.time() + self.ttl, ret))
        self.cache[location] = self.last[1]
        yield ret
コード例 #34
0
ファイル: base.py プロジェクト: nemec/Automaton
 def disallowAllServices(self, clientid):
   """Disallow all services for the given client id."""
   logger.log("Removing all services for client {0}".format(clientid))
   self.get_client(clientid).plugins = set()
コード例 #35
0
ファイル: Textecute.py プロジェクト: SuicideSin/Automaton
      'IMAP_PORT': 993,
      'IMAP_USER': '',
      'IMAP_PASSWORD': '',
      'SMTP_SERVER': 'smtp.gmail.com',
      'SMTP_PORT': 587,
      'DBHOST": 'localhost',
      'DBUSER": '******',
      'DBPASS": ''
   }

op.update(settings_loader.load_app_settings(sys.argv[0]))

# Fail if authentication info is not present.
for operator in ('IMAP_USER', 'IMAP_PASSWORD', 'DBPASS'):
  if op[operator] == '':
    log("Missing necessary credentials to log in to Textecute.")
    sys.exit()

# Set SMTP authentication to the same as IMAP
# if none has been provided.
if not 'SMTP_USER' in op:
  op['SMTP_USER'] = op['IMAP_USER']
if not'SMTP_PASSWORD' in op:
  op['SMTP_PASSWORD'] = op['IMAP_PASSWORD']

try:
  db = pgdb.connect(user=op["DBUSER"], password=op["DBPASS"],
                    host=op["DBHOST"], database="Automaton")
except Exception as e:
  log("Error connecting to database: %s" % e)
  sys.exit()
コード例 #36
0
ファイル: weather.py プロジェクト: nemec/Automaton
  def execute(self, **kwargs):
    """Retrieve the latest weather for the provided location for the given time.
    
    Keyword arguments:
    last -- if True, return the last retrieved weather data
    where -- the location to get weather data for (defaults to current location)
      Can be an alias (defined in the configuration file)
    when -- one of 'today' or 'tomorrow' (default 'today')

    """
    if kwargs.get("last", None):
      if self.last:
        if time.time() < self.last[1].ttl:
          yield "Data for {0}: {1}".format(self.last[0], self.last[1].val)
          return
        else:
          self.last = None
      raise plugin.UnsuccessfulExecution("No recent data stored.")

    if "where" not in kwargs:
      try:
        # Try to call on latitude plugin to get the current location
        kwargs["where"] = re.sub("[() ]", "",
                self.registrar.request_service('location', noreverse=True))
      except:
        #raise plugin.UnsuccessfulExecution("No current location is available.")
        kwargs["where"] = (yield "I could not find your current location, "
          "where do you want weather for?")["_raw"]

    forecastday = 0
    if "when" in kwargs:
      if kwargs["when"].upper() == "TODAY":
        forecastday = 0
      if kwargs["when"].upper() == "TOMORROW":
        forecastday = 1

    location = kwargs["where"]

    # Sub any aliases
    if location in self.locations:
      location = self.locations[location]

    # Look in the cache, pick item with minimum distance from location, then
    # check to see if it's within the tolerance
    if len(self.cache) > 0:
      cache_hit_distances = ((item, self.distance(location, item))
                              for item in self.cache)
                              
      closest_hit = min(cache_hit_distances, key=lambda x: x[1])[0]
      if closest_hit < self.max_cache_distance:
        if time.time() < self.cache[location].expires:
          yield self.cache[location].val
          return
        else:
          self.cache.pop(location, None)

    url = "http://api.wunderground.com/api/{0}/forecast".format(self.api_key)
    query = "/q/{0}.json".format(re.sub('\s+', '_', location))

    resp = json.load(urllib2.urlopen(urllib2.Request(url + query)))
    if not resp:
      raise plugin.UnsuccessfulExecution(
                      "Parsing failed for location " + location)

    ret = None
    if 'results' in resp['response']:
      results = resp['response']['results']
      while len(results) > 1:
        ret = "Did you mean "
        states = set()
        countries = set()
        for result in results:
          if result['state'] != '':
            states.add(result['state'].lower())
          elif result['country'] != '':
            countries.add(result['country'].lower())
        if len(states) > 0:
          ret += "the state"
          if len(states) > 1:
            ret += "s"
          ret += ' ' + utils.humanize_join(
              abbrev.states.try_long(x).capitalize() for x in states)
        if len(countries) > 0:
          if len(states) > 0:
            ret += " or "
          ret += "the country"
          if len(countries) > 1:
            ret += "s"
          ret += ' ' + utils.humanize_join(
              abbrev.countries.try_long(x).capitalize() for x in countries)
        ret += "?"
        # TODO better parsing of conversation arguments
        cont = (yield ret)['_raw'].split()
        old_results = results
        results = []
        for word in cont:
          # Try to convert long name to abbrev
          state = abbrev.states.try_short(word)
          country = abbrev.countries.try_short(word)
          for result in old_results:
            if result['state'].lower() == state.lower():
              results.append(result)
            elif result['country'].lower() == country.lower():
              results.append(result)
        if len(results) == 0:  # Invalid input was given, back up
          results = old_results
      query = results[0]['l'] + '.json'
      resp = json.load(urllib2.urlopen(urllib2.Request(url + query)))
      if not resp:
        raise plugin.UnsuccessfulExecution(
                        "Parsing failed for location " + location)
    try:
      forecast = resp['forecast']['txt_forecast']['forecastday']
      ret = forecast[forecastday]['fcttext']
    except KeyError as err:
      logger.log("Error parsing forecast:", err)

    if not ret:
      raise plugin.UnsuccessfulExecution(
                      "There is no weather data for this location")

    self.last = (location, self.CacheItem(time.time() + self.ttl, ret))
    self.cache[location] = self.last[1]
    yield ret
コード例 #37
0
ファイル: base.py プロジェクト: nemec/Automaton
 def allowAllServices(self, clientid):
   """Allow all services for the given clientid."""
   logger.log("Allowing all services for client {0}".format(clientid))
   self.get_client(clientid).plugins = set(self.registrar.services.keys())