Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-goobook for openSUSE:Factory checked in at 2021-02-09 21:16:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-goobook (Old) and /work/SRC/openSUSE:Factory/.python-goobook.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-goobook" Tue Feb 9 21:16:38 2021 rev:3 rq:870304 version:3.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-goobook/python-goobook.changes 2020-05-28 09:16:54.100904595 +0200 +++ /work/SRC/openSUSE:Factory/.python-goobook.new.28504/python-goobook.changes 2021-02-09 21:16:40.078801338 +0100 @@ -1,0 +2,11 @@ +Mon Feb 8 14:52:57 UTC 2021 - Jan Baier <jba...@suse.com> + +Update to version 3.5.1: +- Issue 91: oauth_db_filename in config file has been broken since 3.5 +- Issue 92: AttributeError: module 'xdg' has no attribute 'XDG_CONFIG_HOME' Bumped minimum required versions for some dependencies +- Issue 87: Adjustments to how authenticate is used and documented, removed embedded client_id and secret Added documentation for getting a client_id and secret. Deprecated "client_secret_filename" in config. +- Issue 82: Feature request: Option to add phone number when creating new contact +- Issue 89: Support XDG Spec, files located in the old locations is still used if they exists but XDG locations are preferred. +- Issue 75: Added unauthenticate command. + +------------------------------------------------------------------- Old: ---- goobook-3.4.tar.gz New: ---- goobook-3.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-goobook.spec ++++++ --- /var/tmp/diff_new_pack.VV1YYD/_old 2021-02-09 21:16:40.562801888 +0100 +++ /var/tmp/diff_new_pack.VV1YYD/_new 2021-02-09 21:16:40.566801892 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-goobook # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define skip_python2 1 %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-goobook -Version: 3.4 +Version: 3.5.1 Release: 0 Summary: Search your google contacts from the command-line or mutt License: GPL-3.0-only ++++++ goobook-3.4.tar.gz -> goobook-3.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/CHANGES.rst new/goobook-3.5.1/CHANGES.rst --- old/goobook-3.4/CHANGES.rst 2019-09-10 08:21:09.000000000 +0200 +++ new/goobook-3.5.1/CHANGES.rst 2020-11-30 19:36:39.000000000 +0100 @@ -1,6 +1,31 @@ CHANGES ======= +3.5.1 2020-11-30 +---------------- + +* Issue 91: oauth_db_filename in config file has been broken since 3.5 +* Issue 92: AttributeError: module 'xdg' has no attribute 'XDG_CONFIG_HOME' + Bumped minimum required versions for some dependencies + +3.5 2020-09-07 +-------------- +* Issue 87: Adjustments to how authenticate is used and documented, removed embedded client_id and secret + Added documentation for getting a client_id and secret. + Deprecated "client_secret_filename" in config. +* Issue 82: Feature request: Option to add phone number when creating new contact +* Updated dependencies. +* Issue 89: Support XDG Spec, files located in the old locations is still used if + they exists but XDG locations are preferred. + + ex. + + - $XDG_CONFIG_HOME/goobookrc + - $XDG_CACHE_HOME/goobook_cache + - $XDG_DATA_HOME/goobook_auth.json + +* Issue 75: Added unauthenticate command. + 3.4 2019-09-10 -------------- * Issue 82: Cannot add contacts anymore diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/PKG-INFO new/goobook-3.5.1/PKG-INFO --- old/goobook-3.4/PKG-INFO 2019-09-10 08:22:26.000000000 +0200 +++ new/goobook-3.5.1/PKG-INFO 2020-11-30 19:38:07.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: goobook -Version: 3.4 +Version: 3.5.1 Summary: Search your google contacts from the command-line or mutt. Home-page: http://gitlab.com/goobook/goobook Author: Christer Sj??holm @@ -21,6 +21,8 @@ the command-line and from MUAs such as Mutt. It can be used from Mutt the same way as abook. + .. NOTE:: GooBook is looking for a new maintainer see https://gitlab.com/goobook/goobook/-/issues/90 + Installation Instructions ========================= @@ -85,32 +87,56 @@ Configuration ============= - For most users it will be enough to to run:: + First you need to authenticate yourself: - $ goobook authenticate + - Go to https://developers.google.com/people/quickstart/python + - and click "Enable the People API" + - select a name (ex. GooBook) + - select desktop app and create + - save the client_id and client_secret to be used below + + run:: + + $ goobook authenticate -- CLIENT_ID CLIENT_SECRET + + and follow the instructions, this part is web based. + + + If the procedure above to get client_id and secret stops working this is an alternative way to do it: + + - Go to the Google developer console https://console.developers.google.com/ + - Create a new project (drop down at the top of the screen) (you are free to use an existing one if you so prefer) + - Select the newly created project + - Go to OAuth consent screen from sidebar + - Select the interal user type if you can but most will only be able to select external. + - On next screen give it a name (ex. GooBook) + - select Add scope, click manually paste and write "https://www.googleapis.com/auth/contacts" inte the lower text box. + - and hit hit add and then save + - Go to Credentials from sidebar + - Click Create Credentials from top, then OAuth Client ID in the dropdown + - Choose Desktop app, enter any name you want, and hit create + - save the client_id and client_secret to be used with goobook authenticate - and follow the instructions. To get access too more settings you can create a configuration file:: - goobook config-template > ~/.goobookrc + goobook config-template > ~/.config/goobookrc It will look like this:: + # Use this template to create your ~/.goobookrc # "#" or ";" at the start of a line makes it a comment. + [DEFAULT] - # The following are optional, defaults are shown + # The following are optional, defaults are shown when not other specified. # This file is written by the oauth library, and should be kept secure, # it's like a password to your google contacts. + # default is to place it in the XDG_DATA_HOME ;oauth_db_filename: ~/.goobook_auth.json - # The client secret file is not really secret, - # usually the bundled default secret is used. - ;client_secret_filename: ~/.goobook_client_secret.json - - ;cache_filename: ~/.goobook_cache + ;cache_filename: ~/.goobook_cache # default is in the XDG_CACHE_HOME ;cache_expiry_hours: 24 ;filter_groupless_contacts: yes @@ -121,6 +147,19 @@ ;default_group: + Files + ----- + + GooBook is using three files, the optional config file that can be placed in the + XDG_CONFIG_HOME (~/.config/goobookrc) or in the home directory (~/.goobookrc). + + The authentication file that is created by running goobook authenticate + in XDG_DATA_HOME (~/.local/share/goobook_auth.json) but can also be placed + in the home directory (~/.goobook_auth.json). + + The contacts cache file that is created in XDG_CACHE_HOME (~/.cache/goobook_cache) + but can also be placed in the home directory (~/.goobook_cache). + Proxy settings -------------- @@ -182,6 +221,31 @@ CHANGES ======= + 3.5.1 2020-11-30 + ---------------- + + * Issue 91: oauth_db_filename in config file has been broken since 3.5 + * Issue 92: AttributeError: module 'xdg' has no attribute 'XDG_CONFIG_HOME' + Bumped minimum required versions for some dependencies + + 3.5 2020-09-07 + -------------- + * Issue 87: Adjustments to how authenticate is used and documented, removed embedded client_id and secret + Added documentation for getting a client_id and secret. + Deprecated "client_secret_filename" in config. + * Issue 82: Feature request: Option to add phone number when creating new contact + * Updated dependencies. + * Issue 89: Support XDG Spec, files located in the old locations is still used if + they exists but XDG locations are preferred. + + ex. + + - $XDG_CONFIG_HOME/goobookrc + - $XDG_CACHE_HOME/goobook_cache + - $XDG_DATA_HOME/goobook_auth.json + + * Issue 75: Added unauthenticate command. + 3.4 2019-09-10 -------------- * Issue 82: Cannot add contacts anymore @@ -395,7 +459,8 @@ Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Intended Audience :: End Users/Desktop -Classifier: License :: OSI Approved :: GNU General Public License (GPL) +Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Topic :: Communications :: Email :: Address Book Description-Content-Type: text/x-rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/README.rst new/goobook-3.5.1/README.rst --- old/goobook-3.4/README.rst 2018-10-29 09:34:33.000000000 +0100 +++ new/goobook-3.5.1/README.rst 2020-09-03 21:22:22.000000000 +0200 @@ -12,6 +12,8 @@ the command-line and from MUAs such as Mutt. It can be used from Mutt the same way as abook. +.. NOTE:: GooBook is looking for a new maintainer see https://gitlab.com/goobook/goobook/-/issues/90 + Installation Instructions ========================= @@ -76,32 +78,56 @@ Configuration ============= -For most users it will be enough to to run:: +First you need to authenticate yourself: - $ goobook authenticate +- Go to https://developers.google.com/people/quickstart/python +- and click "Enable the People API" +- select a name (ex. GooBook) +- select desktop app and create +- save the client_id and client_secret to be used below + +run:: + + $ goobook authenticate -- CLIENT_ID CLIENT_SECRET + +and follow the instructions, this part is web based. + + +If the procedure above to get client_id and secret stops working this is an alternative way to do it: + +- Go to the Google developer console https://console.developers.google.com/ +- Create a new project (drop down at the top of the screen) (you are free to use an existing one if you so prefer) +- Select the newly created project +- Go to OAuth consent screen from sidebar +- Select the interal user type if you can but most will only be able to select external. +- On next screen give it a name (ex. GooBook) +- select Add scope, click manually paste and write "https://www.googleapis.com/auth/contacts" inte the lower text box. +- and hit hit add and then save +- Go to Credentials from sidebar +- Click Create Credentials from top, then OAuth Client ID in the dropdown +- Choose Desktop app, enter any name you want, and hit create +- save the client_id and client_secret to be used with goobook authenticate -and follow the instructions. To get access too more settings you can create a configuration file:: - goobook config-template > ~/.goobookrc + goobook config-template > ~/.config/goobookrc It will look like this:: + # Use this template to create your ~/.goobookrc # "#" or ";" at the start of a line makes it a comment. + [DEFAULT] - # The following are optional, defaults are shown + # The following are optional, defaults are shown when not other specified. # This file is written by the oauth library, and should be kept secure, # it's like a password to your google contacts. + # default is to place it in the XDG_DATA_HOME ;oauth_db_filename: ~/.goobook_auth.json - # The client secret file is not really secret, - # usually the bundled default secret is used. - ;client_secret_filename: ~/.goobook_client_secret.json - - ;cache_filename: ~/.goobook_cache + ;cache_filename: ~/.goobook_cache # default is in the XDG_CACHE_HOME ;cache_expiry_hours: 24 ;filter_groupless_contacts: yes @@ -112,6 +138,19 @@ ;default_group: +Files +----- + +GooBook is using three files, the optional config file that can be placed in the +XDG_CONFIG_HOME (~/.config/goobookrc) or in the home directory (~/.goobookrc). + +The authentication file that is created by running goobook authenticate +in XDG_DATA_HOME (~/.local/share/goobook_auth.json) but can also be placed +in the home directory (~/.goobook_auth.json). + +The contacts cache file that is created in XDG_CACHE_HOME (~/.cache/goobook_cache) +but can also be placed in the home directory (~/.goobook_cache). + Proxy settings -------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook/application.py new/goobook-3.5.1/goobook/application.py --- old/goobook-3.4/goobook/application.py 2018-10-29 09:34:33.000000000 +0100 +++ new/goobook-3.5.1/goobook/application.py 2020-09-03 21:22:22.000000000 +0200 @@ -8,7 +8,7 @@ import datetime import locale import logging -import os +import pathlib import json import sys @@ -16,7 +16,6 @@ import oauth2client.file import oauth2client.tools import pkg_resources -from pkg_resources import resource_filename import goobook.config from goobook.goobook import GooBook, Cache, GoogleContacts, parse_groups, parse_contacts @@ -24,9 +23,29 @@ log = logging.getLogger(__name__) # pylint: disable=invalid-name -CONFIG_FILE = '~/.goobookrc' SCOPES = 'https://www.google.com/m8/feeds' # read/write access to Contacts and Contact Groups +AUTHENTICATE_HELP_STRING = '''Google OAuth authentication. + +Before running goobook authenticate you need a client_id and a client_secret, get it like this: + +Go to https://developers.google.com/people/quickstart/python +and click "Enable the People API" +select a name (ex. GooBook) +select desktop application +save the client_id and client_secret to be used below:: + + $ goobook authenticate -- CLIENT_ID CLIENT_SECRET + +and follow the instructions. + +if it doesn't open a webbrowser use + +goobook authenticate --noauth_local_webserver -- CLIENT_ID CLIENT_SECRET + +If you get the page "This app isn't verified" select Advanced and the "Go to GooBook (unsafe)" at the bottom. +''' + def main(): locale.setlocale(locale.LC_TIME, '') # Use system configured locale @@ -41,7 +60,7 @@ help="Print version and exit") parser.add_argument('-d', '--debug', dest="log_level", action='store_const', const=logging.DEBUG, help='Output debug info (stderr).') - parser.set_defaults(config=CONFIG_FILE, log_level=logging.ERROR) + parser.set_defaults(log_level=logging.ERROR) subparsers = parser.add_subparsers() @@ -52,6 +71,8 @@ help='Name to use.') parser_add.add_argument('email', nargs='?', metavar='EMAIL', help='E-mail to use.') + parser_add.add_argument('phone', nargs='?', metavar='PHONE', + help='Phone number to use.') parser_add.set_defaults(func=do_add) parser_config_template = subparsers.add_parser('config-template', @@ -86,11 +107,19 @@ parser_reload.set_defaults(func=do_reload) parser_auth = subparsers.add_parser('authenticate', - description='Google OAuth authentication.', + description=AUTHENTICATE_HELP_STRING, formatter_class=argparse.RawDescriptionHelpFormatter, parents=[oauth2client.tools.argparser]) + parser_auth.add_argument('client_id', metavar='CLIENT_ID', + help='Client ID') + parser_auth.add_argument('client_secret', metavar='CLIENT_SECRET', + help='Client secret') parser_auth.set_defaults(func=do_authenticate) + parser_unauth = subparsers.add_parser('unauthenticate', + description="Removed authentication data (logout).") + parser_unauth.set_defaults(func=do_unauthenticate) + args = parser.parse_args() logging.basicConfig(level=args.log_level) @@ -114,7 +143,7 @@ def do_add(config, args): goobk = GooBook(config) if args.name and args.email: - goobk.add_mail_contact(args.name, args.email) + goobk.add_mail_contact(args.name, args.email, args.phone) else: goobk.add_email_from(sys.stdin) goobk.cache.load(force_update=True) @@ -170,14 +199,18 @@ creds = config.creds if not creds or creds.invalid: - client_secret_filename = config.client_secret_filename - if not os.path.exists(client_secret_filename): - client_secret_filename = resource_filename(__name__, 'client_secret.json') - flow = oauth2client.client.flow_from_clientsecrets(client_secret_filename, SCOPES) + flow = oauth2client.client.OAuth2WebServerFlow(args.client_id, args.client_secret, SCOPES) creds = oauth2client.tools.run_flow(flow, store, args) else: print('You are already authenticated.') +def do_unauthenticate(config, _args): + oauth_db = pathlib.Path(config.oauth_db_filename) + if oauth_db.exists(): + oauth_db.unlink() + print("deleted", oauth_db) + + if __name__ == '__main__': main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook/client_secret.json new/goobook-3.5.1/goobook/client_secret.json --- old/goobook-3.4/goobook/client_secret.json 2015-06-02 22:21:49.000000000 +0200 +++ new/goobook-3.5.1/goobook/client_secret.json 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -{"installed":{"auth_uri":"https://accounts.google.com/o/oauth2/auth","client_secret":"iB-6KmYDQotAf2nd_fPoY86A","token_uri":"https://accounts.google.com/o/oauth2/token","client_email":"","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","oob"],"client_x509_cert_url":"","client_id":"500614897810-h9eub98go537fqplj9k59ouip21j8a1e.apps.googleusercontent.com","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"}} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook/config.py new/goobook-3.5.1/goobook/config.py --- old/goobook-3.4/goobook/config.py 2018-10-29 09:34:33.000000000 +0100 +++ new/goobook-3.5.1/goobook/config.py 2020-11-07 09:13:45.000000000 +0100 @@ -3,15 +3,21 @@ # author: Christer Sj??holm -- hcs AT furuvik DOT net import os +import pathlib +import sys from os.path import realpath, expanduser import configparser import logging import oauth2client.client +import xdg from goobook.storage import Storage log = logging.getLogger(__name__) # pylint: disable=invalid-name +LEGACY_CONFIG_FILE = pathlib.Path('~/.goobookrc').expanduser() +LEGACY_AUTH_FILE = pathlib.Path('~/.goobook_auth.json').expanduser() +LEGACY_CACHE_FILE = pathlib.Path('~/.goobook_cache').expanduser() TEMPLATE = '''\ # Use this template to create your ~/.goobookrc @@ -19,17 +25,14 @@ # "#" or ";" at the start of a line makes it a comment. [DEFAULT] -# The following are optional, defaults are shown +# The following are optional, defaults are shown when not other specified. # This file is written by the oauth library, and should be kept secure, # it's like a password to your google contacts. +# default is to place it in the XDG_DATA_HOME ;oauth_db_filename: ~/.goobook_auth.json -# The client secret file is not really secret, -# usually the bundled default secret is used. -;client_secret_filename: ~/.goobook_client_secret.json - -;cache_filename: ~/.goobook_cache +;cache_filename: ~/.goobook_cache # default is in the XDG_CACHE_HOME ;cache_expiry_hours: 24 ;filter_groupless_contacts: yes @@ -41,34 +44,88 @@ ''' -def read_config(config_file): - """Reads the ~/.goobookrc and any authentication data +def read_config(config_file=None): + """Reads the ~/.goobookrc and any authentication data. returns the configuration as a dictionary. """ config = Storage({ # Default values - 'cache_filename': '~/.goobook_cache', - 'oauth_db_filename': '~/.goobook_auth.json', - 'client_secret_filename': '~/.goobook_client_secret.json', + 'cache_filename': None, + 'oauth_db_filename': None, 'cache_expiry_hours': '24', 'filter_groupless_contacts': True, 'default_group': ''}) - config_file = os.path.expanduser(config_file) - parser = _get_config(config_file) + + # Search for config file to use + if config_file: # config file explicitly given on the commandline + config_file = os.path.expanduser(config_file) + else: # search for goobookrc in XDG dirs and homedir + config_files = [dir_ / "goobookrc" for dir_ in [xdg.XDG_CONFIG_HOME] + + xdg.XDG_CONFIG_DIRS] + [LEGACY_CONFIG_FILE] + log.debug("config file search path: %s", config_files) + for config_file_ in config_files: + if config_file_.exists(): + config_file = str(config_file_) + log.debug("found config file: %s", config_file) + break + else: + log.debug("no config file found") + config_file = None + # else: # .goobookrc in home directory + # config_file = os.path.expanduser(CONFIG_FILE) + + if config_file: + parser = _get_config(config_file) + else: + parser = None + if parser: config.get_dict().update(dict(parser.items('DEFAULT', raw=True))) # Handle not string fields if parser.has_option('DEFAULT', 'filter_groupless_contacts'): config.filter_groupless_contacts = parser.getboolean('DEFAULT', 'filter_groupless_contacts') - # Ensure paths are fully expanded - config.cache_filename = realpath(expanduser(config.cache_filename)) - config.client_secret_filename = realpath(expanduser(config.client_secret_filename)) - config.oauth_db_filename = realpath(expanduser(config.oauth_db_filename)) + if "client_secret_filename" in config: + print("WARNING: setting client_secret_filename in {} is deprecated".format(config_file), file=sys.stderr) + + # Search for cache file to use + if config.cache_filename: # If explicitly specified in config file + config.cache_filename = realpath(expanduser(config.cache_filename)) + else: # search for goobook_cache in XDG dirs and homedir + cache_files = [xdg.XDG_CACHE_HOME / "goobook_cache", LEGACY_CACHE_FILE] + log.debug("cache file search path: %s", cache_files) + for cache_file in cache_files: + cache_file = cache_file.resolve() + if cache_file.exists(): + log.debug("found cache file: %s", cache_file) + break + else: # If there is none, create in XDG_CACHE_HOME + cache_file = xdg.XDG_CACHE_HOME / "goobook_cache" + log.debug("no cache file found, will use %s", cache_file) + config.cache_filename = str(cache_file) + + # Search for auth file to use + if config.oauth_db_filename: # If explicitly specified in config file + config.oauth_db_filename = realpath(expanduser(config.oauth_db_filename)) + auth_file = pathlib.Path(config.oauth_db_filename) + else: # search for goobook_auth.json in XDG dirs and homedir + auth_files = [dir_ / "goobook_auth.json" for dir_ in [xdg.XDG_DATA_HOME] + + xdg.XDG_DATA_DIRS] + [LEGACY_AUTH_FILE] + log.debug("auth file search path: %s", auth_files) + for auth_file in auth_files: + auth_file = auth_file.resolve() + if auth_file.exists(): + log.debug("found auth file: %s", auth_file) + break + else: # If there is none, create in XDG_DATA_HOME + auth_file = xdg.XDG_DATA_HOME / "goobook_auth.json" + log.debug("no auth file found, will use %s", auth_file) + config.oauth_db_filename = str(auth_file) config.store = oauth2client.file.Storage(config.oauth_db_filename) - config.creds = config.store.get() + + config.creds = config.store.get() if auth_file.exists() else None log.debug(config) return config diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook/goobook.py new/goobook-3.5.1/goobook/goobook.py --- old/goobook-3.4/goobook/goobook.py 2019-09-10 08:03:56.000000000 +0200 +++ new/goobook-3.5.1/goobook/goobook.py 2020-08-31 21:51:40.000000000 +0200 @@ -31,7 +31,7 @@ import time import httplib2 -from apiclient.discovery import build +from googleapiclient.discovery import build from goobook.storage import Storage, storageify, unstorageify @@ -43,7 +43,7 @@ class GooBook(): - """Application logic + """Application logic. This class can't be used as a library as it looks now, it uses sys.stdin print and sys.exit(). @@ -55,7 +55,7 @@ self.cache.load() def query(self, query, simple=False): - """Do the query, and print it out in + """Do the query, and print it out in specified format. simple=False is the mutt format simple format is: @@ -180,16 +180,17 @@ if group in contact.groups: yield contact - def add_mail_contact(self, name, mailaddr): + def add_mail_contact(self, name, mailaddr, phone=None): contact = { 'names': [{'givenName': name}], 'emailAddresses': [{'value': mailaddr}], + 'phoneNumbers': [{'value': phone}], } gcont = GoogleContacts(self.__config) - log.debug('Going to create contact name: %s email: %s', name, mailaddr) + log.debug('Going to create contact name: %s email: %s phone: %s', name, mailaddr, phone) gcont.create_contact(contact) - log.info('Created contact name: %s email: %s', name, mailaddr) + log.info('Created contact name: %s email: %s %s', name, mailaddr, phone) def add_email_from(self, lines): """Add an address from From: field of a mail. @@ -197,6 +198,7 @@ This assumes a single mail file is supplied through. Args: + ---- lines: A generator of lines, usually a open file. """ @@ -232,9 +234,10 @@ self.groups = None # list of Storage def load(self, force_update=False): - """Load the cached addressbook feed, or fetch it (again) if it is old or missing or invalid or anything + """Load the cached addressbook feed, or fetch it (again) if it is old or missing or invalid or anything. Args: + ---- force_update: force update of cache """ @@ -270,7 +273,7 @@ self.save() def save(self): - """Pickle the addressbook and a timestamp""" + """Pickle the addressbook and a timestamp.""" if self.contacts: # never write a empty addressbook cache = {'contacts': unstorageify(self.contacts), 'groups': unstorageify(self.groups), @@ -387,7 +390,8 @@ x__xgafv=None, pageToken=None, sortOrder=None, - personFields='names,nicknames,emailAddresses,memberships,phoneNumbers,birthdays,imClients,organizations,addresses', + personFields=('names,nicknames,emailAddresses,memberships,' + 'phoneNumbers,birthdays,imClients,organizations,addresses'), requestSyncToken=None, syncToken=None, requestMask_includeField=None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook.1.rst new/goobook-3.5.1/goobook.1.rst --- old/goobook-3.4/goobook.1.rst 2018-10-29 09:34:33.000000000 +0100 +++ new/goobook-3.5.1/goobook.1.rst 2020-09-03 21:22:22.000000000 +0200 @@ -8,7 +8,7 @@ :Author: This manual page has been written by Dariusz Dwornikowski and Christer Sj??holm -:Date: 2018-09-22 +:Date: 2020-09-02 :Manual section: 1 :Manual group: User Manuals @@ -53,11 +53,11 @@ authenticate Allow goobook to access your Google contacts using OAuth2. -add - Read an email address from stdin and add the From: address to your Google contacts. +add [NAME] [EMAIL] [PHONE] + Add a new Google contact. If NAME and EMAIL is not specified, read an email address from stdin and add the From: address to your Google contacts. config-template - Create a config template of **~/.goobookrc**. + Display a config template of that can be written to **~/.config/goobookrc**. dump_contacts dump all your contacts to XML (stdout). @@ -82,17 +82,17 @@ ------------- | For most users it will be enough to run: | -| **goobook** authenticate +| **goobook** authenticate --help +| +| and follow the instructions | To have access to more advanced options, you can generate a config file by doing: | -| **goobook** config-template > ~/.goobookrc +| **goobook** config-template > ~/.config/goobookrc An example config can look like this:: [DEFAULT] - oauth_db_filename: ~/.goobook_auth.json - cache_filename: ~/.goobook_cache cache_expiry_hours: 24 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook.egg-info/PKG-INFO new/goobook-3.5.1/goobook.egg-info/PKG-INFO --- old/goobook-3.4/goobook.egg-info/PKG-INFO 2019-09-10 08:22:26.000000000 +0200 +++ new/goobook-3.5.1/goobook.egg-info/PKG-INFO 2020-11-30 19:38:07.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: goobook -Version: 3.4 +Version: 3.5.1 Summary: Search your google contacts from the command-line or mutt. Home-page: http://gitlab.com/goobook/goobook Author: Christer Sj??holm @@ -21,6 +21,8 @@ the command-line and from MUAs such as Mutt. It can be used from Mutt the same way as abook. + .. NOTE:: GooBook is looking for a new maintainer see https://gitlab.com/goobook/goobook/-/issues/90 + Installation Instructions ========================= @@ -85,32 +87,56 @@ Configuration ============= - For most users it will be enough to to run:: + First you need to authenticate yourself: - $ goobook authenticate + - Go to https://developers.google.com/people/quickstart/python + - and click "Enable the People API" + - select a name (ex. GooBook) + - select desktop app and create + - save the client_id and client_secret to be used below + + run:: + + $ goobook authenticate -- CLIENT_ID CLIENT_SECRET + + and follow the instructions, this part is web based. + + + If the procedure above to get client_id and secret stops working this is an alternative way to do it: + + - Go to the Google developer console https://console.developers.google.com/ + - Create a new project (drop down at the top of the screen) (you are free to use an existing one if you so prefer) + - Select the newly created project + - Go to OAuth consent screen from sidebar + - Select the interal user type if you can but most will only be able to select external. + - On next screen give it a name (ex. GooBook) + - select Add scope, click manually paste and write "https://www.googleapis.com/auth/contacts" inte the lower text box. + - and hit hit add and then save + - Go to Credentials from sidebar + - Click Create Credentials from top, then OAuth Client ID in the dropdown + - Choose Desktop app, enter any name you want, and hit create + - save the client_id and client_secret to be used with goobook authenticate - and follow the instructions. To get access too more settings you can create a configuration file:: - goobook config-template > ~/.goobookrc + goobook config-template > ~/.config/goobookrc It will look like this:: + # Use this template to create your ~/.goobookrc # "#" or ";" at the start of a line makes it a comment. + [DEFAULT] - # The following are optional, defaults are shown + # The following are optional, defaults are shown when not other specified. # This file is written by the oauth library, and should be kept secure, # it's like a password to your google contacts. + # default is to place it in the XDG_DATA_HOME ;oauth_db_filename: ~/.goobook_auth.json - # The client secret file is not really secret, - # usually the bundled default secret is used. - ;client_secret_filename: ~/.goobook_client_secret.json - - ;cache_filename: ~/.goobook_cache + ;cache_filename: ~/.goobook_cache # default is in the XDG_CACHE_HOME ;cache_expiry_hours: 24 ;filter_groupless_contacts: yes @@ -121,6 +147,19 @@ ;default_group: + Files + ----- + + GooBook is using three files, the optional config file that can be placed in the + XDG_CONFIG_HOME (~/.config/goobookrc) or in the home directory (~/.goobookrc). + + The authentication file that is created by running goobook authenticate + in XDG_DATA_HOME (~/.local/share/goobook_auth.json) but can also be placed + in the home directory (~/.goobook_auth.json). + + The contacts cache file that is created in XDG_CACHE_HOME (~/.cache/goobook_cache) + but can also be placed in the home directory (~/.goobook_cache). + Proxy settings -------------- @@ -182,6 +221,31 @@ CHANGES ======= + 3.5.1 2020-11-30 + ---------------- + + * Issue 91: oauth_db_filename in config file has been broken since 3.5 + * Issue 92: AttributeError: module 'xdg' has no attribute 'XDG_CONFIG_HOME' + Bumped minimum required versions for some dependencies + + 3.5 2020-09-07 + -------------- + * Issue 87: Adjustments to how authenticate is used and documented, removed embedded client_id and secret + Added documentation for getting a client_id and secret. + Deprecated "client_secret_filename" in config. + * Issue 82: Feature request: Option to add phone number when creating new contact + * Updated dependencies. + * Issue 89: Support XDG Spec, files located in the old locations is still used if + they exists but XDG locations are preferred. + + ex. + + - $XDG_CONFIG_HOME/goobookrc + - $XDG_CACHE_HOME/goobook_cache + - $XDG_DATA_HOME/goobook_auth.json + + * Issue 75: Added unauthenticate command. + 3.4 2019-09-10 -------------- * Issue 82: Cannot add contacts anymore @@ -395,7 +459,8 @@ Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Intended Audience :: End Users/Desktop -Classifier: License :: OSI Approved :: GNU General Public License (GPL) +Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) Classifier: Topic :: Communications :: Email :: Address Book Description-Content-Type: text/x-rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook.egg-info/SOURCES.txt new/goobook-3.5.1/goobook.egg-info/SOURCES.txt --- old/goobook-3.4/goobook.egg-info/SOURCES.txt 2019-09-10 08:22:26.000000000 +0200 +++ new/goobook-3.5.1/goobook.egg-info/SOURCES.txt 2020-11-30 19:38:07.000000000 +0100 @@ -10,7 +10,6 @@ setup.py goobook/__init__.py goobook/application.py -goobook/client_secret.json goobook/config.py goobook/goobook.py goobook/storage.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/goobook.egg-info/requires.txt new/goobook-3.5.1/goobook.egg-info/requires.txt --- old/goobook-3.4/goobook.egg-info/requires.txt 2019-09-10 08:22:26.000000000 +0200 +++ new/goobook-3.5.1/goobook.egg-info/requires.txt 2020-11-30 19:38:07.000000000 +0100 @@ -1,3 +1,4 @@ -google-api-python-client>=1.6.4 -simplejson>=2.1.0 +google-api-python-client>=1.7.12 +simplejson>=3.16.0 oauth2client<5.0.0dev,>=1.5.0 +xdg>=4.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/goobook-3.4/setup.py new/goobook-3.5.1/setup.py --- old/goobook-3.4/setup.py 2019-09-10 08:21:34.000000000 +0200 +++ new/goobook-3.5.1/setup.py 2020-11-30 19:36:00.000000000 +0100 @@ -12,7 +12,7 @@ setuptools.setup( name='goobook', - version='3.4', + version='3.5.1', description='Search your google contacts from the command-line or mutt.', long_description=README + '\n\n' + NEWS, long_description_content_type="text/x-rst", @@ -28,16 +28,18 @@ Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 Intended Audience :: End Users/Desktop - License :: OSI Approved :: GNU General Public License (GPL) + License :: OSI Approved :: GNU General Public License v3 (GPLv3) Topic :: Communications :: Email :: Address Book """.splitlines() if f.strip()], keywords='abook mutt e-mail gmail google address-book', license='GPLv3', install_requires=[ - 'google-api-python-client>=1.6.4', - 'simplejson>=2.1.0', + 'google-api-python-client>=1.7.12', + 'simplejson>=3.16.0', 'oauth2client>=1.5.0,<5.0.0dev', + 'xdg>=4.0.1' ], extras_require={ },