Как получить доступ к истории активности для данного идентификатора документа в Google Диске, чтобы восстановить данные с помощью API Google Drive?
Ошибка в приложении Google Drive привела к тому, что пользователь случайно осиротел тысячи документов, которые были в общей папке.
Глядя на консоль администратора, я могу получить идентификаторы этих документов, но не идентификаторы рассматриваемых папок (я получаю имена папок, но имена папок не уникальны, и я имею дело с тысячами документов и сотни папок)
Если какой-либо пользователь выполняет поиск потерянного документа, он может найти документ и, щелкнув по нему, просмотреть на панели "Действия" информацию о том, когда документ был удален из его дома и откуда он был удален.
Я думаю, что моя лучшая проблема в написании сценариев для решения этой проблемы:
For each google document ID...
-> Access the activity history and grab the "removed from folder" event
-> Get the FolderID from that event (surely that exists and there's API access, right?)
-> Reparent the folder
Вопрос в том, как получить API-доступ, который мне нужен к FolderID.
Обратите внимание, что в то же время у меня есть следующий код, который иногда, но не всегда, позволяет мне получить родительские папки (кажется, что он выходит из строя достаточно часто, чтобы быть бесполезным для моей общей проблемы)
function recoverFile (id) {
Logger.log('recoverFile called with id='+id);
try {
f = DriveApp.getFileById(id);
}
catch (exc) {
Logger.log('Error getting file '+id+'- no permission?');
return false
}
Logger.log('Successfully got file: '+f);
parents = f.getParents()
if (parents.hasNext()) {
p = parents.next();
}
else {
Logger.log('Document has no parents');
return false
}
all_parents = [p]
Logger.log('We have parents: '+p);
while (p) {
p.addFile(f)
all_parents.push(p)
Logger.log(p);
if (parents.hasNext()) {
p = parents.next()
}
else {
p = false
}
}
return {'file':f, 'parents':all_parents}
}
Обратите внимание, что другая проблема с этим кодом заключается в том, что он сильно замедляется после нескольких запусков - попытка / уловка getId() убивает меня, но я не знаю, кому принадлежит каждый файл, поэтому я должен попытаться выяснить.
1 ответ
API отчетов администратора является ключом к реальному решению: https://developers.google.com/admin-sdk/reports/v1/reference/activity-ref-appendix-a/drive-event-names
Используя этот API, можно извлекать данные из папок, которые были потеряны. Получив эти данные, довольно просто создать сценарий, который считывает идентификаторы документов и идентификаторы папок и помещает документы обратно в папку, хотя этот сценарий необходимо запускать для каждого создателя рассматриваемых документов.
Вот фрагмент скрипта, который извлекает данные из API:
function generateLoginActivityReport() {
var now = new Date();
// Assumes a one week time horizon -- modify as you see fit...
var oneWeekAgo = new Date(now.getTime() - 8 * 24 * 60 * 60 * 1000);
var startTime = oneWeekAgo.toISOString();
var endTime = now.toISOString();
var rows = [];
var pageToken, page;
do {
/*
page = AdminReports.Activities.list('all', 'login', {
startTime: startTime,
endTime: endTime,
maxResults: 500,
pageToken: pageToken
});
*/
page = AdminReports.Activities.list('name-of-user-who-accidentally-borked-drive@innovationcharter.org','drive', {
startTime:startTime,
endTime:endTime,
maxResults: 200,
eventName: 'remove_from_folder',
//name: 'remove_from_folder',
pageToken: pageToken});
var items = page.items;
if (items) {
for (var i = 0; i < items.length; i++) {
//for (var i = 0; i < 2; i++) {
var item = items[i];
// Get the parameters out of the mess of crap that is their parameters...
// Google serves them up this way [{} {} {} {}] instead of in a normal
// object like we're going to create in params
params = {}
for (var idx=0; idx < item.events[0].parameters.length; idx++) {
param = item.events[0].parameters[idx]
var val = false
if (param['multiValue']) {
var val = param['multiValue']
}
if (param['value']) {
var val = param['value']
}
if (param['boolValue']) {
var val = param['boolValue']
}
params[param['name']] = val
}
// Now go ahead and push a row to the spreadsheet with all
// the data we need
var row = [
new Date(item.id.time),
item.actor.email,
item.events[0].name,
params['doc_title'],
params['doc_id'],
params['source_folder_title'],
params['source_folder_id'],
params['owner'], // You'll need the owner because the
// owner has to recover the file
];
rows.push(row);
}
}
pageToken = page.nextPageToken;
} while (pageToken);
if (rows.length > 0) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet('Files Removed from Folder');
// Append the headers.
var headers = ['Time', 'User', 'Event','Doc Title','Doc','Folder Title','Folder','Owner'];
sheet.appendRow(headers);
// Append the results.
sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
//Logger.log('Report spreadsheet created: %s', spreadsheet.getUrl());
} else {
Logger.log('No results returned.');
}
}
Этот прекрасный сценарий генерирует электронную таблицу с данными, которые мы должны использовать для извлечения данных. Вот вторая часть программы - сценарий, позволяющий последовательно проходить через эти данные и восстанавливать файлы, которые мы можем восстановить...
function recoverSheet () {
DOCID = 5; // 1-INDEXED COL HEADERS
FOLDERID = 7;
OWNER = 8;
RECOVERED = 9;
DOC_LINK = 10;
FOLDER_LINK = 11;
EXTRA_PARENTS = 12;
sheet = SpreadsheetApp.getActiveSheet()
total_range = sheet.getDataRange();
for (var rownum=2; rownum<=total_range.getLastRow(); rownum++) {
// Iterate through each row...
var range = sheet.getRange(
'A'+rownum+':'+'I'+rownum // Where your data is...
)
docID=range.getCell(1,DOCID).getValue();
if (range.getCell(1,RECOVERED).getValue()) {
Logger.log('Skipping '+docID+' - already recovered');
}
else {
if (range.getCell(1,OWNER).getValue()==currentUser) {
folderID = range.getCell(1,FOLDERID).getValue();
try {
folder = DriveApp.getFolderById(folderID); // get folder...
file = DriveApp.getFileById(docID);
}
catch (exc) {
Logger.log('Failed to get file or folder :( for docID '+docID+' folderID '+folderID);
range.getCell(1,RECOVERED).setValue('FAILED');
file = false
}
if (file) {
folder.addFile(file);
// Add nice little links to make it handy to see what we recovered
sheet.getRange(rownum,RECOVERED,1,1).setValue('True'); // Set Recovered
sheet.getRange(rownum,DOC_LINK,1,1).setValue('https://drive.google.com/open?id='+docID);
sheet.getRange(rownum,FOLDER_LINK,1,1).setValue('https://drive.google.com/open?id='+folderID);
recovery = recoverFile(docID) // Do any extra recovery we can...
if (recovery) {
Logger.log('Successful extra recovery: '+recovery);
//range.getCell(1,4).setValue(recovery.file.getOwner().getEmail()); // set Owner of document
for (var i=0; i<recovery.parents.length; i++) {
sheet.getRange(rownum,EXTRA_PARENTS+i).setValue('https://drive.google.com/open?id='+recovery.parents[i].getId());
}
}
}
}}
}
}