Merge branch 'Develop'
# Conflicts: # MANIFEST.in # README.md # cps/helper.py # cps/static/js/archive/archive.js # cps/translations/nl/LC_MESSAGES/messages.mo # cps/translations/nl/LC_MESSAGES/messages.po # cps/ub.py # cps/updater.py # cps/web.py # cps/worker.py # optional-requirements.txt
This commit is contained in:
@@ -17,24 +17,37 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
|
||||
from flask import Response, stream_with_context
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import Column, UniqueConstraint
|
||||
from sqlalchemy import String, Integer
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
try:
|
||||
from pydrive.auth import GoogleAuth
|
||||
from pydrive.drive import GoogleDrive
|
||||
from pydrive.auth import RefreshError, InvalidConfigError
|
||||
from pydrive.auth import RefreshError
|
||||
from apiclient import errors
|
||||
gdrive_support = True
|
||||
except ImportError:
|
||||
gdrive_support = False
|
||||
|
||||
import os
|
||||
from ub import config
|
||||
import cli
|
||||
import shutil
|
||||
from flask import Response, stream_with_context
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import *
|
||||
import web
|
||||
from . import logger, cli, config
|
||||
from .constants import BASE_DIR as _BASE_DIR
|
||||
|
||||
|
||||
SETTINGS_YAML = os.path.join(_BASE_DIR, 'settings.yaml')
|
||||
CREDENTIALS = os.path.join(_BASE_DIR, 'gdrive_credentials')
|
||||
CLIENT_SECRETS = os.path.join(_BASE_DIR, 'client_secrets.json')
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
class Singleton:
|
||||
"""
|
||||
@@ -67,6 +80,9 @@ class Singleton:
|
||||
except AttributeError:
|
||||
self._instance = self._decorated()
|
||||
return self._instance
|
||||
except ImportError as e:
|
||||
log.debug(e)
|
||||
return None
|
||||
|
||||
def __call__(self):
|
||||
raise TypeError('Singletons must be accessed through `Instance()`.')
|
||||
@@ -78,7 +94,7 @@ class Singleton:
|
||||
@Singleton
|
||||
class Gauth:
|
||||
def __init__(self):
|
||||
self.auth = GoogleAuth(settings_file=os.path.join(config.get_main_dir,'settings.yaml'))
|
||||
self.auth = GoogleAuth(settings_file=SETTINGS_YAML)
|
||||
|
||||
|
||||
@Singleton
|
||||
@@ -86,6 +102,9 @@ class Gdrive:
|
||||
def __init__(self):
|
||||
self.drive = getDrive(gauth=Gauth.Instance().auth)
|
||||
|
||||
def is_gdrive_ready():
|
||||
return os.path.exists(SETTINGS_YAML) and os.path.exists(CREDENTIALS)
|
||||
|
||||
|
||||
engine = create_engine('sqlite:///{0}'.format(cli.gdpath), echo=False)
|
||||
Base = declarative_base()
|
||||
@@ -146,17 +165,17 @@ migrate()
|
||||
def getDrive(drive=None, gauth=None):
|
||||
if not drive:
|
||||
if not gauth:
|
||||
gauth = GoogleAuth(settings_file=os.path.join(config.get_main_dir,'settings.yaml'))
|
||||
gauth = GoogleAuth(settings_file=SETTINGS_YAML)
|
||||
# Try to load saved client credentials
|
||||
gauth.LoadCredentialsFile(os.path.join(config.get_main_dir,'gdrive_credentials'))
|
||||
gauth.LoadCredentialsFile(CREDENTIALS)
|
||||
if gauth.access_token_expired:
|
||||
# Refresh them if expired
|
||||
try:
|
||||
gauth.Refresh()
|
||||
except RefreshError as e:
|
||||
web.app.logger.error("Google Drive error: " + e.message)
|
||||
log.error("Google Drive error: %s", e)
|
||||
except Exception as e:
|
||||
web.app.logger.exception(e)
|
||||
log.exception(e)
|
||||
else:
|
||||
# Initialize the saved creds
|
||||
gauth.Authorize()
|
||||
@@ -166,7 +185,7 @@ def getDrive(drive=None, gauth=None):
|
||||
try:
|
||||
drive.auth.Refresh()
|
||||
except RefreshError as e:
|
||||
web.app.logger.error("Google Drive error: " + e.message)
|
||||
log.error("Google Drive error: %s", e)
|
||||
return drive
|
||||
|
||||
def listRootFolders():
|
||||
@@ -203,7 +222,7 @@ def getEbooksFolderId(drive=None):
|
||||
try:
|
||||
gDriveId.gdrive_id = getEbooksFolder(drive)['id']
|
||||
except Exception:
|
||||
web.app.logger.error('Error gDrive, root ID not found')
|
||||
log.error('Error gDrive, root ID not found')
|
||||
gDriveId.path = '/'
|
||||
session.merge(gDriveId)
|
||||
session.commit()
|
||||
@@ -443,10 +462,10 @@ def getChangeById (drive, change_id):
|
||||
change = drive.auth.service.changes().get(changeId=change_id).execute()
|
||||
return change
|
||||
except (errors.HttpError) as error:
|
||||
web.app.logger.info(error.message)
|
||||
log.error(error)
|
||||
return None
|
||||
except Exception as e:
|
||||
web.app.logger.info(e)
|
||||
log.error(e)
|
||||
return None
|
||||
|
||||
|
||||
@@ -516,6 +535,54 @@ def do_gdrive_download(df, headers):
|
||||
if resp.status == 206:
|
||||
yield content
|
||||
else:
|
||||
web.app.logger.info('An error occurred: %s' % resp)
|
||||
log.warning('An error occurred: %s', resp)
|
||||
return
|
||||
return Response(stream_with_context(stream()), headers=headers)
|
||||
|
||||
|
||||
_SETTINGS_YAML_TEMPLATE = """
|
||||
client_config_backend: settings
|
||||
client_config_file: %(client_file)s
|
||||
client_config:
|
||||
client_id: %(client_id)s
|
||||
client_secret: %(client_secret)s
|
||||
redirect_uri: %(redirect_uri)s
|
||||
|
||||
save_credentials: True
|
||||
save_credentials_backend: file
|
||||
save_credentials_file: %(credential)s
|
||||
|
||||
get_refresh_token: True
|
||||
|
||||
oauth_scope:
|
||||
- https://www.googleapis.com/auth/drive
|
||||
"""
|
||||
|
||||
def update_settings(client_id, client_secret, redirect_uri):
|
||||
if redirect_uri.endswith('/'):
|
||||
redirect_uri = redirect_uri[:-1]
|
||||
config_params = {
|
||||
'client_file': CLIENT_SECRETS,
|
||||
'client_id': client_id,
|
||||
'client_secret': client_secret,
|
||||
'redirect_uri': redirect_uri,
|
||||
'credential': CREDENTIALS
|
||||
}
|
||||
|
||||
with open(SETTINGS_YAML, 'w') as f:
|
||||
f.write(_SETTINGS_YAML_TEMPLATE % config_params)
|
||||
|
||||
|
||||
def get_error_text(client_secrets=None):
|
||||
if not gdrive_support:
|
||||
return 'Import of optional Google Drive requirements missing'
|
||||
|
||||
if not os.path.isfile(CLIENT_SECRETS):
|
||||
return 'client_secrets.json is missing or not readable'
|
||||
|
||||
with open(CLIENT_SECRETS, 'r') as settings:
|
||||
filedata = json.load(settings)
|
||||
if 'web' not in filedata:
|
||||
return 'client_secrets.json is not configured for web application'
|
||||
if client_secrets:
|
||||
client_secrets.update(filedata['web'])
|
||||
|
||||
Reference in New Issue
Block a user