예제 #1
0
    def execute(self, **kwargs):
        """Retrieve mail from a GMail account through curl."""

        # Load command settings from a configuration file
        settings = ConfigParser.SafeConfigParser()
        settings.read(utils.get_plugin_settings_paths(__name__))
        try:
            username = settings.get("Credentials", "username")
            password = settings.get("Credentials", "password")
        except ConfigParser.NoOptionError:
            raise plugin.UnsuccessfulExecution(
                "Error: username/password "
                "not provided in settings file.")
        cmd = ("curl -u {0}:{1} --silent \"https://mail.google.com/mail/"
               "feed/atom\" | tr -d '\n' | awk -F '<entry>' '{"
               "for (i=2; i<=NF; i++) {print $i}}' | "
               "sed -n \"s/<title>\\(.*\)<\\/title.*name>\\(.*\\)"
               "<\\/name>.*/\\2 - \\1/p\"".format(username, password))
        proc = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)
        out, err = proc.communicate()
        if out == "":
            out = "No mail."
        if len(out) == 0:
            raise plugin.UnsuccessfulExecution(err)
        return out
예제 #2
0
  def execute(self, **kwargs):
    """Search Google and return the first result.

    Keyword arguments:
    query -- the query to search for

    """
    if "query" not in kwargs:
      raise plugin.UnsuccessfulExecution('Error: No search string.')
    query = urllib.urlencode({'q': kwargs["query"]})
    url = ('http://ajax.googleapis.com/ajax/services/'
            'search/web?v=1.0&' + query)
    search_results = urllib.urlopen(url)
    response = json.loads(search_results.read())
    results = response['responseData']['results']
    try:
      # Strips HTML formatting
      ret = re.sub(r'<[^>]*?>', '', results[0]['content'])
    except:
      raise plugin.UnsuccessfulExecution("There was an error parsing data. "
                                          "Please try again.")

    # Strips HTML special characters (ie. &quot; )
    ret = re.sub(r'&[^ ]*?;', '', ret)

    return unicodedata.normalize('NFKD', ret).encode('ascii', 'ignore')
예제 #3
0
    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.")
예제 #4
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)
예제 #5
0
  def execute(self, **kwargs):
    """Log into Google Latitude and retrieve the user's current location.
    
    Keyword arguments:
    noreverse -- Return the latitude and longitude pair rather than turn it
      into a human-readable location. (default False)

    """
    settings = ConfigParser.SafeConfigParser()
    settings.read(utils.get_plugin_settings_paths(__name__))

    try:
      auth = open(settings.get('Settings', 'AUTHPATH'), "r")
      credentials = pickle.loads(auth.read())
      auth.close()
    except ConfigParser.NoSectionError:
      raise plugin.UnsuccessfulExecution("'Settings' section missing from "
                                          "config file.")
    except ConfigParser.NoOptionError:
      raise plugin.UnsuccessfulExecution("Server not authenticated "
                                "with Google Latitude.")
    except IOError:
      raise plugin.UnsuccessfulExecution("Error opening authentication file.")

    http = httplib2.Http()
    http = credentials.authorize(http)

    lat = build("latitude", "v1", http=http)

    data = lat.currentLocation().get(granularity="best").execute()

    if all(k in data for k in ('latitude', 'longitude')):
      if kwargs.get("noreverse", False):
        return "({0}, {1})".format(data['latitude'], data['longitude'])
      else:
        ret = self.lookup(data['latitude'], data['longitude'])
        if ret == None:
          return "({0}, {1})".format(data['latitude'], data['longitude'])
        else:
          return ret
    else:
      if 'kind' in data:
        raise plugin.UnsuccessfulExecution("No latitude data available.")
      else:
        raise plugin.UnsuccessfulExecution("Error in Latitude response.")
예제 #6
0
    def execute(self, **kwargs):
        """Schedule a command to be run at a later time.

    Keyword arguments:
    command -- the command (in natural language) to be run
    in -- a relative time offset (hours, minutes, and/or seconds)
    at -- an absolute time to run the command

    """
        expire = 0
        if "command" not in kwargs:
            raise plugin.UnsuccessfulExecution("No command provided.")

        if "in" in kwargs:
            try:
                idx = kwargs["in"].rfind(" ")
                wait = kwargs["in"][:idx]
                scale = kwargs["in"][idx + 1:]
            except ValueError:
                raise plugin.UnsuccessfulExecution("Error parsing time.")
            try:
                expire = int(wait)
            except ValueError:
                try:
                    expire = utils.text_to_int(wait)
                except:
                    raise plugin.UnsuccessfulExecution("Error parsing time.")
            if scale.startswith("h"):
                expire = datetime.datetime.now() + datetime.timedelta(
                    hours=expire)
            elif scale.startswith("m"):
                expire = datetime.datetime.now() + datetime.timedelta(
                    minutes=expire)
            elif scale.startswith("s"):
                expire = datetime.datetime.now() + datetime.timedelta(
                    seconds=expire)
            else:
                raise plugin.UnsuccessfulExecution(
                    "Could not determine time scale (h/m/s).")
        elif "at" in kwargs:
            expire = utils.text_to_absolute_time(wait)
            if not expire:
                raise plugin.UnsuccessfulExecution("Error parsing time.")
        else:
            raise plugin.UnsuccessfulExecution(
                'Command could not be scheduled. Must specify "in" or "at"')

        cmd, namespace, args = self.registrar.find_best_service(
            kwargs["command"])
        if cmd is None:
            raise plugin.UnsuccessfulExecution("Provided text could not be "
                                               "converted into a command.")
        self.queue.put((expire, (cmd, namespace, args)))
        self.event.set()
        return 'Command scheduled.'
예제 #7
0
    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.")
예제 #8
0
    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
예제 #9
0
        registrar.register_service("remember",
                                   self.execute,
                                   grammar={"memo": []},
                                   usage=usage,
                                   namespace=__name__)

    def disable(self):
        """Disable all of Memo's services."""
        self.registrar.unregister_service("memo", namespace=__name__)
        self.registrar.unregister_service("remember", namespace=__name__)

    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.")
        else:
            raise plugin.UnsuccessfulExecution("Must provide data to insert.")