diff options
| author | Vasil Zlatanov <vasil.zlatanov@gmail.com> | 2014-04-23 23:16:10 +0200 | 
|---|---|---|
| committer | Vasil Zlatanov <vasil.zlatanov@gmail.com> | 2014-04-23 23:16:10 +0200 | 
| commit | 50abfa786ea2986dda508f080476284b4bad7da3 (patch) | |
| tree | 0e968a2a39516f67f6248c7e8f7413f69e561924 /mutt/goobook/build | |
| parent | 00d0dfb24d415af4e9eb7d7fa1cb4ac34be7e6c5 (diff) | |
| download | dotfiles-50abfa786ea2986dda508f080476284b4bad7da3.tar.gz dotfiles-50abfa786ea2986dda508f080476284b4bad7da3.tar.bz2 dotfiles-50abfa786ea2986dda508f080476284b4bad7da3.zip | |
Removed unneeded gunk.
Diffstat (limited to 'mutt/goobook/build')
3 files changed, 0 insertions, 400 deletions
| diff --git a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/__init__.py b/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/__init__.py deleted file mode 100644 index 27c5034..0000000 --- a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: UTF-8 -*- -# vim: fileencoding=UTF-8 filetype=python ff=unix et ts=4 sw=4 sts=4 tw=120 -# author: Christer Sjöholm -- hcs AT furuvik DOT net - - diff --git a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/goobook.py b/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/goobook.py deleted file mode 100644 index f0f5edf..0000000 --- a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/goobook.py +++ /dev/null @@ -1,352 +0,0 @@ -#!/usr/bin/env python2 -# vim: fileencoding=UTF-8 filetype=python ff=unix expandtab sw=4 sts=4 tw=120 -# maintainer: Christer Sjöholm -- goobook AT furuvik DOT net -# -# Copyright (C) 2009  Carlos José Barroso -# Copyright (C) 2010  Christer Sjöholm -# -# This program 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. -# -# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>. - -'''\ -The idea is make an interface to google contacts that mimics the behaviour of -abook for mutt. It's developed in python and uses the fine -google data api (gdata). -''' - -import email.header -import locale -import logging -import optparse -import getpass -import sys -import os -import subprocess -import re -import time -import ConfigParser -from netrc import netrc -from os.path import realpath, expanduser -from storage import Storage - -try: -    import simplejson -    json = simplejson # this hushes pyflakes -except ImportError: -    import json - -import gdata -from gdata.contacts.client import ContactsClient, ContactsQuery -from gdata.contacts.data import ContactEntry -from gdata.data import Email, Name, FullName - -log = logging.getLogger('goobook') - -CONFIG_FILE = '~/.goobookrc' -CONFIG_TEMPLATE = '''\ -# "#" or ";" at the start of a line makes it a comment. -[DEFAULT] -# If not given here, email and password is taken from .netrc using -# machine google.com -;email: user@gmail.com -;password: top secret -# The following are optional, defaults are shown -;max_results: 9999 -;cache_filename: ~/.goobook_cache -;cache_expiry_hours: 24 -''' - -ENCODING = locale.getpreferredencoding() - -class GooBook(object): -    '''This class can't be used as a library as it looks now, it uses sys.stdin -       print, sys.exit() and getpass().''' -    def __init__ (self, config): -        self.config = config -        self.__client = None -        self.contacts = {} -        ''' This is where all the contacts is stored -        {'contacts': {contact_id: <contact>} -         'groups': {'group': [contact_id] ] -        } -        <contact> is a {'name':'', 'email':''} -        ''' - -    @property -    def password(self): -        if not self.config.password: -            self.config.password = getpass.getpass() -        return self.config.password - -    def __get_client(self): -        '''Login to Google and return a ContactsClient object. - -        ''' -        if not self.__client: -            if not self.config.email or not self.password: -                print >> sys.stderr, "ERROR: Missing email or password" -                sys.exit(1) -            client = ContactsClient() -            client.ssl = True -            client.ClientLogin(email=self.config.email, password=self.password, service='cp', source='goobook') -            self.__client = client -        return self.__client - -    def __query_contacts(self, query): -        match = re.compile(query, re.I).search -        for contact in self.contacts['contacts'].itervalues(): -            for field in ('name', 'nick', 'emails'): -                value = contact.get(field, None) -                if not value: -                    pass -                elif isinstance(value, basestring): -                    if value and match(value): -                        yield contact -                        break -                else: #value is list -                    found_one = False -                    for value2 in value: -                        if value2 and match(value2): -                            yield contact -                            found_one = True -                            break -                    if found_one: -                        break - -    def __query_groups(self, query): -        match = re.compile(query, re.I).search -        for (group_id, group_name) in self.contacts['groups'].iteritems(): -            if match(group_name): -                yield (group_name, list(self.__get_group_contacts(group_id))) - -    def query(self, query): -        """Do the query, and print it out in - -        """ -        self.load() -        #query contacts -        matching_contacts = sorted(self.__query_contacts(query), key=lambda c: c['name']) -        #query groups -        matching_groups = sorted(self.__query_groups(query), key=lambda g: g[0]) -        # mutt's query_command expects the first line to be a message, -        # which it discards. -        print "\n", -        for contact in matching_contacts: -            if 'emails' in contact and contact['emails']: -                emailaddrs = sorted(contact['emails']) -                for emailaddr in emailaddrs: -                    print (u'%s\t%s' % (emailaddr, contact['name'])).encode(ENCODING) -        for group_name, contacts in matching_groups: -            emails = ['%s <%s>' % (c['name'], c['emails'][0]) for c in contacts if c['emails']] -            emails = ', '.join(emails) -            if not emails: -                continue -            print (u'%s\t%s (group)' % (emails, group_name)).encode(ENCODING) - -    def __get_group_contacts(self, group_id): -        for contact in self.contacts['contacts'].itervalues(): -            if group_id in contact['groups']: -                yield contact - -    def load(self): -        """Load the cached addressbook feed, or fetch it (again) if it is -        old or missing or invalid or anyting - -        """ -        contacts = None - -        # if cache older than cache_expiry_hours -        if (not os.path.exists(self.config.cache_filename) or -                ((time.time() - os.path.getmtime(self.config.cache_filename)) > -                    (self.config.cache_expiry_hours * 60 *60))): -            contacts = self.fetch() -            self.store(contacts) -        if not contacts: -            try: -                contacts = json.load(open(self.config.cache_filename)) -                if contacts.get('goobook_cache') != '1.1': -                    contacts = None # Old cache format -            except ValueError: -                pass # Failed to read JSON file. -        if not contacts: -            contacts = self.fetch() -            self.store(contacts) -        if not contacts: -            raise Exception('Failed to find any contacts') # TODO -        self.contacts = contacts - - -    def fetch_contacts(self): -        client = self.__get_client() -        query = ContactsQuery(max_results=self.config.max_results) -        entries = client.get_contacts(query=query).entry -        return dict([self.__parse_contact(ent) for ent in entries]) - -    @staticmethod -    def __parse_contact(ent): -        '''takes a gdata contact entry and returns a parsed contact. -        on the form (contact_id, {fieldname:content}) - -        ''' -        contact = {} -        contact['name'] = ent.title.text -        contact['emails'] = [emailent.address for emailent in ent.email] -        if ent.nickname: -            contact['nick'] = ent.nickname.text -        contact['groups'] = [g.href for g in ent.group_membership_info] -        return (ent.id.text, contact) - -    def fetch_contact_groups(self): -        client = self.__get_client() -        return dict([(g.id.text, g.title.text) for g in client.get_groups().entry]) - -    def fetch(self): -        """Actually go out on the wire and fetch the addressbook. -        Returns the contacts data structure. - -        """ -        contacts = self.fetch_contacts() -        groups = self.fetch_contact_groups() -        return {'contacts':contacts, 'groups':groups, 'goobook_cache': '1.1'} - -    def store(self, contacts): -        """Pickle the addressbook and a timestamp - -        """ -        if contacts: # never write a empty addressbook -            json.dump(contacts, open(self.config.cache_filename, 'w'), indent=2) - -    def add(self): -        """Add an address from From: field of a mail. -        This assumes a single mail file is supplied through stdin. - -        """ -        from_line = "" -        for line in sys.stdin: -            if line.startswith("From: "): -                from_line = line -                break -        if from_line == "": -            print "Not a valid mail file!" -            sys.exit(2) -        #Parse From: line -        #Take care of non ascii header -        from_line = unicode(email.header.make_header(email.header.decode_header(from_line))) -        #Parse the From line -        (name, mailaddr) = email.utils.parseaddr(from_line) -        if not name: -            name = mailaddr -        #save to contacts -        client = self.__get_client() -        new_contact = ContactEntry(name=Name(full_name=FullName(text=name))) -        new_contact.email.append(Email(address=mailaddr, rel='http://schemas.google.com/g/2005#home', primary='true')) -        client.create_contact(new_contact) -        print 'Created contact:', name.encode(ENCODING), mailaddr.encode(ENCODING) - -def read_config(config_file): -    '''Reads the ~/.goobookrc and ~/.netrc. -    returns the configuration as a dictionary. - -    ''' -    config = Storage({ # Default values -        'email': '', -        'password': '', -        'max_results': '9999', -        'cache_filename': '~/.goobook_cache', -        'cache_expiry_hours': '24', -        }) -    config_file = os.path.expanduser(config_file) -    if os.path.lexists(config_file) or os.path.lexists(config_file + '.gpg'): -        try: -            parser = ConfigParser.SafeConfigParser() -            if os.path.lexists(config_file): -                log.info('Reading config: %s', config_file) -                f = open(config_file) -            else: -                log.info('Reading config: %s', config_file + '.gpg') -                sp = subprocess.Popen(['gpg', '--no-tty', '-q', '-d', config_file + ".gpg"], stdout=subprocess.PIPE) -                f = sp.stdout -            parser.readfp(f) -            config.update(dict(parser.items('DEFAULT', raw=True))) -        except (IOError, ConfigParser.ParsingError), e: -            print >> sys.stderr, "Failed to read configuration %s\n%s" % (config_file, e) -            sys.exit(1) -    if not config.get('email') or not config.get('password'): -        log.info('email or password missing from config, checking .netrc') -        auth = netrc().authenticators('google.com') -        if auth: -            login = auth[0] -            password = auth[2] -            if not config.get('email'): -                config['email'] = login -            if not config.get('password'): -                config['password'] = password -        else: -            log.info('No match in .netrc') - -        config.cache_filename = realpath(expanduser(config.cache_filename)) - -        log.debug(config) -    return config - -def main(): -    class MyParser(optparse.OptionParser): -        def format_epilog(self, formatter): -            return self.epilog -    usage = 'usage: %prog [options] <command> [<arg>]' -    description = 'Search you Google contacts from mutt or the command-line.' -    epilog = '''\ -Commands: -  add              Add the senders address to contacts, reads a mail from STDIN. -  reload           Force reload of the cache. -  query <query>    Search contacts using query (regex). -  config-template  Prints a template for .goobookrc to STDOUT - -''' -    parser = MyParser(usage=usage, description=description, epilog=epilog) -    parser.set_defaults(config_file=CONFIG_FILE) -    parser.add_option("-c", "--config", dest="config_file", -                    help="Specify alternative configuration file.", metavar="FILE") -    parser.add_option("-v", "--verbose", dest="logging_level", default=logging.ERROR, -                    help="Specify alternative configuration file.", -                    action='store_const', const=logging.INFO) -    parser.add_option("-d", "--debug", dest="logging_level", -                    help="Specify alternative configuration file.", -                    action='store_const', const=logging.DEBUG) -    (options, args) = parser.parse_args() -    if len(args) == 0: -        parser.print_help() -        sys.exit(1) -    logging.basicConfig(level=options.logging_level) -    config = read_config(options.config_file) -    goobk = GooBook(config) -    try: -        cmd = args.pop(0) -        if cmd == "query": -            if len(args) != 1: -                parser.error("incorrect number of arguments") -            goobk.query(args[0].decode(ENCODING)) -        elif cmd == "add": -            goobk.add() -        elif cmd == "reload": -            goobk.store(goobk.fetch()) -        elif cmd == "config-template": -            print CONFIG_TEMPLATE -        else: -            parser.error('Command not recognized: %s' % cmd) -    except gdata.client.BadAuthentication, e: -        print >> sys.stderr, e # Incorrect username or password -        sys.exit(1) - -if __name__ == '__main__': -    main() diff --git a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/storage.py b/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/storage.py deleted file mode 100644 index 3314327..0000000 --- a/mutt/goobook/build/lib.linux-x86_64-2.7/goobook/storage.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: UTF-8 -*- -# vim: fileencoding=UTF-8 filetype=python ff=unix et ts=4 sw=4 sts=4 tw=120 -# author: Christer Sjöholm -- hcs AT furuvik DOT net - -class Storage(dict): -    """ -    A Storage object is like a dictionary except `obj.foo` can be used -    in addition to `obj['foo']`. - -        >>> o = storage(a=1) -        >>> o.a -        1 -        >>> o['a'] -        1 -        >>> o.a = 2 -        >>> o['a'] -        2 -        >>> del o.a -        >>> o.a -        Traceback (most recent call last): -            ... -        AttributeError: 'a' - -        Storage comes from web.py (public domain) -    """ -    def __getattr__(self, key): -        try: -            return self[key] -        except KeyError, k: -            raise AttributeError, k - -    def __setattr__(self, key, value): -        self[key] = value - -    def __delattr__(self, key): -        try: -            del self[key] -        except KeyError, k: -            raise AttributeError, k - -    def __repr__(self): -        return '<Storage ' + dict.__repr__(self) + '>' - | 
