1

谷歌云端硬盘应用程序中的一个错误导致用户意外地孤立了共享文件夹中的数千个文档。

通过查看管理控制台,我可以获取这些文档的 ID,但不能获取相关文件夹的 ID(我获取了文件夹的名称,但文件夹名称不是唯一的,我正在处理数千文件和数百个文件夹)

如果任何给定用户搜索孤立文档,他们可以找到该文档,并通过单击它,在“活动”窗格中查看有关文档何时从其主页中删除以及从何处删除的信息。

我认为我编写脚本解决方案的最佳方法是:

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

问题是如何获得我需要的对 FolderID 的 API 访问权限。

请注意,与此同时,我有以下代码,有时但并不总是能够让我获得父文件夹(它似乎经常失败,以至于对我的整体问题毫无用处)

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() 上的 try/catch 让我很生气,但我不知道谁拥有每个文件,所以我必须尝试查出。

4

1 回答 1

1

Admin Reports API 是实际解决方案的关键:https ://developers.google.com/admin-sdk/reports/v1/reference/activity-ref-appendix-a/drive-event-names

使用该 API,可以提取已孤立文件夹上的数据。一旦你有了这些数据,制作一个读取文档 ID 和文件夹 ID 并将文档放回文件夹中的脚本就相对简单了,尽管该脚本必须针对相关文档的创建者运行。

这是从 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.');
        }
    }

这个可爱的脚本会生成一个电子表格,其中包含我们需要用来提取数据的数据。这是程序的第 2 部分 - 一个脚本,用于逐行检查该数据并恢复我们可以恢复的文件......

    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());
                            }
                        } 
                    }
                }}
        }
    }
于 2015-09-17T04:30:13.957 回答