Allow deleting books (fixes #119)
This commit is contained in:
@@ -25,8 +25,9 @@ Session = sessionmaker()
|
||||
Session.configure(bind=engine)
|
||||
session = scoped_session(Session)
|
||||
|
||||
|
||||
class GdriveId(Base):
|
||||
__tablename__='gdrive_ids'
|
||||
__tablename__ = 'gdrive_ids'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
gdrive_id = Column(Integer, unique=True)
|
||||
@@ -36,8 +37,9 @@ class GdriveId(Base):
|
||||
def __repr__(self):
|
||||
return str(self.path)
|
||||
|
||||
|
||||
class PermissionAdded(Base):
|
||||
__tablename__='permissions_added'
|
||||
__tablename__ = 'permissions_added'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
gdrive_id = Column(Integer, unique=True)
|
||||
@@ -45,15 +47,16 @@ class PermissionAdded(Base):
|
||||
def __repr__(self):
|
||||
return str(self.gdrive_id)
|
||||
|
||||
|
||||
def migrate():
|
||||
if not engine.dialect.has_table(engine.connect(), "permissions_added"):
|
||||
PermissionAdded.__table__.create(bind = engine)
|
||||
for sql in session.execute("select sql from sqlite_master where type='table'"):
|
||||
if 'CREATE TABLE gdrive_ids' in sql[0]:
|
||||
currUniqueConstraint='UNIQUE (gdrive_id)'
|
||||
currUniqueConstraint = 'UNIQUE (gdrive_id)'
|
||||
if currUniqueConstraint in sql[0]:
|
||||
sql=sql[0].replace(currUniqueConstraint, 'UNIQUE (gdrive_id, path)')
|
||||
sql=sql.replace(GdriveId.__tablename__, GdriveId.__tablename__+ '2')
|
||||
sql=sql.replace(GdriveId.__tablename__, GdriveId.__tablename__ + '2')
|
||||
session.execute(sql)
|
||||
session.execute('INSERT INTO gdrive_ids2 (id, gdrive_id, path) SELECT id, gdrive_id, path FROM gdrive_ids;')
|
||||
session.commit()
|
||||
@@ -69,9 +72,10 @@ if not os.path.exists(dbpath):
|
||||
|
||||
migrate()
|
||||
|
||||
|
||||
def getDrive(gauth=None):
|
||||
if not gauth:
|
||||
gauth=GoogleAuth(settings_file='settings.yaml')
|
||||
gauth = GoogleAuth(settings_file='settings.yaml')
|
||||
# Try to load saved client credentials
|
||||
gauth.LoadCredentialsFile("gdrive_credentials")
|
||||
if gauth.access_token_expired:
|
||||
@@ -83,126 +87,134 @@ def getDrive(gauth=None):
|
||||
# Save the current credentials to a file
|
||||
return GoogleDrive(gauth)
|
||||
|
||||
|
||||
def getEbooksFolder(drive=None):
|
||||
if not drive:
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
ebooksFolder= "title = '%s' and 'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % config.config_google_drive_folder
|
||||
ebooksFolder = "title = '%s' and 'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % config.config_google_drive_folder
|
||||
|
||||
fileList = drive.ListFile({'q': ebooksFolder}).GetList()
|
||||
return fileList[0]
|
||||
|
||||
|
||||
def getEbooksFolderId(drive=None):
|
||||
storedPathName=session.query(GdriveId).filter(GdriveId.path == '/').first()
|
||||
storedPathName = session.query(GdriveId).filter(GdriveId.path == '/').first()
|
||||
if storedPathName:
|
||||
return storedPathName.gdrive_id
|
||||
else:
|
||||
gDriveId=GdriveId()
|
||||
gDriveId.gdrive_id=getEbooksFolder(drive)['id']
|
||||
gDriveId.path='/'
|
||||
gDriveId = GdriveId()
|
||||
gDriveId.gdrive_id = getEbooksFolder(drive)['id']
|
||||
gDriveId.path = '/'
|
||||
session.merge(gDriveId)
|
||||
session.commit()
|
||||
return
|
||||
|
||||
|
||||
def getFolderInFolder(parentId, folderName, drive=None):
|
||||
if not drive:
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
folder= "title = '%s' and '%s' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % (folderName.replace("'", "\\'"), parentId)
|
||||
folder = "title = '%s' and '%s' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false" % (folderName.replace("'", "\\'"), parentId)
|
||||
fileList = drive.ListFile({'q': folder}).GetList()
|
||||
return fileList[0]
|
||||
|
||||
|
||||
def getFile(pathId, fileName, drive=None):
|
||||
if not drive:
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
metaDataFile="'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'"))
|
||||
metaDataFile = "'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", "\\'"))
|
||||
|
||||
fileList = drive.ListFile({'q': metaDataFile}).GetList()
|
||||
return fileList[0]
|
||||
|
||||
|
||||
def getFolderId(path, drive=None):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
currentFolderId=getEbooksFolderId(drive)
|
||||
sqlCheckPath=path if path[-1] =='/' else path + '/'
|
||||
storedPathName=session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first()
|
||||
currentFolderId = getEbooksFolderId(drive)
|
||||
sqlCheckPath = path if path[-1] == '/' else path + '/'
|
||||
storedPathName = session.query(GdriveId).filter(GdriveId.path == sqlCheckPath).first()
|
||||
|
||||
if not storedPathName:
|
||||
dbChange=False
|
||||
s=path.split('/')
|
||||
dbChange = False
|
||||
s = path.split('/')
|
||||
for i, x in enumerate(s):
|
||||
if len(x) > 0:
|
||||
currentPath="/".join(s[:i+1])
|
||||
currentPath = "/".join(s[:i+1])
|
||||
if currentPath[-1] != '/':
|
||||
currentPath = currentPath + '/'
|
||||
storedPathName=session.query(GdriveId).filter(GdriveId.path == currentPath).first()
|
||||
storedPathName = session.query(GdriveId).filter(GdriveId.path == currentPath).first()
|
||||
if storedPathName:
|
||||
currentFolderId=storedPathName.gdrive_id
|
||||
currentFolderId = storedPathName.gdrive_id
|
||||
else:
|
||||
currentFolderId=getFolderInFolder(currentFolderId, x, drive)['id']
|
||||
gDriveId=GdriveId()
|
||||
gDriveId.gdrive_id=currentFolderId
|
||||
gDriveId.path=currentPath
|
||||
currentFolderId = getFolderInFolder(currentFolderId, x, drive)['id']
|
||||
gDriveId = GdriveId()
|
||||
gDriveId.gdrive_id = currentFolderId
|
||||
gDriveId.path = currentPath
|
||||
session.merge(gDriveId)
|
||||
dbChange=True
|
||||
dbChange = True
|
||||
if dbChange:
|
||||
session.commit()
|
||||
else:
|
||||
currentFolderId=storedPathName.gdrive_id
|
||||
currentFolderId = storedPathName.gdrive_id
|
||||
return currentFolderId
|
||||
|
||||
|
||||
def getFileFromEbooksFolder(drive, path, fileName):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
if path:
|
||||
# sqlCheckPath=path if path[-1] =='/' else path + '/'
|
||||
folderId=getFolderId(path, drive)
|
||||
folderId = getFolderId(path, drive)
|
||||
else:
|
||||
folderId=getEbooksFolderId(drive)
|
||||
folderId = getEbooksFolderId(drive)
|
||||
|
||||
return getFile(folderId, fileName, drive)
|
||||
|
||||
|
||||
def copyDriveFileRemote(drive, origin_file_id, copy_title):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
copied_file = {'title': copy_title}
|
||||
try:
|
||||
file_data = drive.auth.service.files().copy(
|
||||
fileId=origin_file_id, body=copied_file).execute()
|
||||
fileId = origin_file_id, body=copied_file).execute()
|
||||
return drive.CreateFile({'id': file_data['id']})
|
||||
except errors.HttpError as error:
|
||||
print ('An error occurred: %s' % error)
|
||||
return None
|
||||
|
||||
|
||||
def downloadFile(drive, path, filename, output):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
f=getFileFromEbooksFolder(drive, path, filename)
|
||||
f = getFileFromEbooksFolder(drive, path, filename)
|
||||
f.GetContentFile(output)
|
||||
|
||||
|
||||
def backupCalibreDbAndOptionalDownload(drive, f=None):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
metaDataFile="'%s' in parents and title = 'metadata.db' and trashed = false" % getEbooksFolderId()
|
||||
metaDataFile = "'%s' in parents and title = 'metadata.db' and trashed = false" % getEbooksFolderId()
|
||||
|
||||
fileList = drive.ListFile({'q': metaDataFile}).GetList()
|
||||
|
||||
databaseFile=fileList[0]
|
||||
databaseFile = fileList[0]
|
||||
|
||||
if f:
|
||||
databaseFile.GetContentFile(f)
|
||||
@@ -212,64 +224,65 @@ def copyToDrive(drive, uploadFile, createRoot, replaceFiles,
|
||||
ignoreFiles=[],
|
||||
parent=None, prevDir=''):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
isInitial=not bool(parent)
|
||||
isInitial = not bool(parent)
|
||||
if not parent:
|
||||
parent=getEbooksFolder(drive)
|
||||
parent = getEbooksFolder(drive)
|
||||
if os.path.isdir(os.path.join(prevDir,uploadFile)):
|
||||
existingFolder=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
|
||||
existingFolder = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
|
||||
if len(existingFolder) == 0 and (not isInitial or createRoot):
|
||||
parent = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}],
|
||||
"mimeType": "application/vnd.google-apps.folder" })
|
||||
parent = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],
|
||||
"mimeType": "application/vnd.google-apps.folder"})
|
||||
parent.Upload()
|
||||
else:
|
||||
if (not isInitial or createRoot) and len(existingFolder) > 0:
|
||||
parent=existingFolder[0]
|
||||
for f in os.listdir(os.path.join(prevDir,uploadFile)):
|
||||
parent = existingFolder[0]
|
||||
for f in os.listdir(os.path.join(prevDir, uploadFile)):
|
||||
if f not in ignoreFiles:
|
||||
copyToDrive(drive, f, True, replaceFiles, ignoreFiles, parent, os.path.join(prevDir,uploadFile))
|
||||
copyToDrive(drive, f, True, replaceFiles, ignoreFiles, parent, os.path.join(prevDir, uploadFile))
|
||||
else:
|
||||
if os.path.basename(uploadFile) not in ignoreFiles:
|
||||
existingFiles=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
|
||||
existingFiles = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (os.path.basename(uploadFile), parent['id'])}).GetList()
|
||||
if len(existingFiles) > 0:
|
||||
driveFile=existingFiles[0]
|
||||
driveFile = existingFiles[0]
|
||||
else:
|
||||
driveFile = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], })
|
||||
driveFile.SetContentFile(os.path.join(prevDir,uploadFile))
|
||||
driveFile = drive.CreateFile({'title': os.path.basename(uploadFile), 'parents': [{"kind":"drive#fileLink", 'id': parent['id']}], })
|
||||
driveFile.SetContentFile(os.path.join(prevDir, uploadFile))
|
||||
driveFile.Upload()
|
||||
|
||||
|
||||
def uploadFileToEbooksFolder(drive, destFile, f):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
parent=getEbooksFolder(drive)
|
||||
splitDir=destFile.split('/')
|
||||
parent = getEbooksFolder(drive)
|
||||
splitDir = destFile.split('/')
|
||||
for i, x in enumerate(splitDir):
|
||||
if i == len(splitDir)-1:
|
||||
existingFiles=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
|
||||
existingFiles = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
|
||||
if len(existingFiles) > 0:
|
||||
driveFile=existingFiles[0]
|
||||
driveFile = existingFiles[0]
|
||||
else:
|
||||
driveFile = drive.CreateFile({'title': x, 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}], })
|
||||
driveFile = drive.CreateFile({'title': x, 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],})
|
||||
driveFile.SetContentFile(f)
|
||||
driveFile.Upload()
|
||||
else:
|
||||
existingFolder=drive.ListFile({'q' : "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
|
||||
existingFolder = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % (x, parent['id'])}).GetList()
|
||||
if len(existingFolder) == 0:
|
||||
parent = drive.CreateFile({'title': x, 'parents' : [{"kind": "drive#fileLink", 'id' : parent['id']}],
|
||||
"mimeType": "application/vnd.google-apps.folder" })
|
||||
parent = drive.CreateFile({'title': x, 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}],
|
||||
"mimeType": "application/vnd.google-apps.folder"})
|
||||
parent.Upload()
|
||||
else:
|
||||
parent=existingFolder[0]
|
||||
parent = existingFolder[0]
|
||||
|
||||
|
||||
def watchChange(drive, channel_id, channel_type, channel_address,
|
||||
channel_token=None, expiration=None):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
# Watch for all changes to a user's Drive.
|
||||
@@ -286,15 +299,16 @@ def watchChange(drive, channel_id, channel_type, channel_address,
|
||||
# Raises:
|
||||
# apiclient.errors.HttpError: if http request to create channel fails.
|
||||
body = {
|
||||
'id': channel_id,
|
||||
'type': channel_type,
|
||||
'address': channel_address
|
||||
'id': channel_id,
|
||||
'type': channel_type,
|
||||
'address': channel_address
|
||||
}
|
||||
if channel_token:
|
||||
body['token'] = channel_token
|
||||
if expiration:
|
||||
body['expiration'] = expiration
|
||||
return drive.auth.service.changes().watch(body=body).execute()
|
||||
return drive.auth.service.changes().watch(body=body).execute()
|
||||
|
||||
|
||||
def watchFile(drive, file_id, channel_id, channel_type, channel_address,
|
||||
channel_token=None, expiration=None):
|
||||
@@ -314,7 +328,7 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
|
||||
apiclient.errors.HttpError: if http request to create channel fails.
|
||||
"""
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
|
||||
@@ -329,6 +343,7 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
|
||||
body['expiration'] = expiration
|
||||
return drive.auth.service.files().watch(fileId=file_id, body=body).execute()
|
||||
|
||||
|
||||
def stopChannel(drive, channel_id, resource_id):
|
||||
"""Stop watching to a specific channel.
|
||||
Args:
|
||||
@@ -339,19 +354,20 @@ def stopChannel(drive, channel_id, resource_id):
|
||||
apiclient.errors.HttpError: if http request to create channel fails.
|
||||
"""
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
# service=drive.auth.service
|
||||
body = {
|
||||
'id': channel_id,
|
||||
'resourceId': resource_id
|
||||
'id': channel_id,
|
||||
'resourceId': resource_id
|
||||
}
|
||||
return drive.auth.service.channels().stop(body=body).execute()
|
||||
|
||||
|
||||
def getChangeById (drive, change_id):
|
||||
if not drive:
|
||||
drive=getDrive()
|
||||
drive = getDrive()
|
||||
if drive.auth.access_token_expired:
|
||||
drive.auth.Refresh()
|
||||
# Print a single Change resource information.
|
||||
|
||||
Reference in New Issue
Block a user