如何避免同一文件重复出现在"高级驱动器服务更改列表"中



我正在尝试通过高级服务使用驱动器API检查共享驱动器中删除的项目。然而,每次运行脚本时,我都会一次又一次地看到相同的删除文件。

我在每次运行后都会设置一个新的startPageToken,将其保存为脚本属性,并为下一次运行获取它,所以这不是问题所在。同样在同一个脚本中,我成功地检查了同一共享驱动器中的编辑,我看到编辑列表在编辑文件时会更新,所以我知道我得到了最新的修订列表。但不知怎么的,那些同样被删除的文件不断出现。

我对此的一个理论是,被删除的文件仍然在某人的计算机上打开,并且以某种方式频繁地重新加载,导致Google Drive为其记录视图,因此将其视为已更改。我从处理编辑过的文件中知道,视图确实会导致文件出现在更改列表中,即使它们没有更改。我可以通过检查modifiedDate来绕过查看的文件,看看自上次脚本运行以来文件是否真的被修改了,但对于已删除的文件,我不知道如何确定删除日期或其他任何可能帮助我过滤误报的信息。

我需要一种方法来区分自上次运行脚本以来实际删除的文件和这些奇怪的幽灵文件。显而易见的答案是找到一种方法来确定文件何时被真正删除,但我不确定如何做到这一点。当文件被删除时,modifiedDate不会被更新,由于我试图在GAS中使用高级服务作为一个绑定到容器的脚本来完成这一切,我只能访问Drive API v2,所以我无法弄清楚如何获得文件的删除日期。

以下是用于获取更改列表的函数的简化版本:

function watchDrive() {
const id = "[SHARED DRIVE ID GOES HERE]";
const driveName = "TEST";
// Script properties to store page tokens
let scriptProperties = PropertiesService.getScriptProperties();
// Set fields to fetch. Note that deleting user and timestamp are not available in Drive API v2
const fields =
"newStartPageToken,"
+"items("
+"file("
+"id,"
+"title,"
+"labels(trashed),"
+"iconLink,"
+"mimeType,"
+"createdDate,"
+"ownedByMe,"
+"modifiedDate,"
+"lastModifyingUser("
+"emailAddress,"
+"displayName,"
+"picture(url)"
+"),"
+"alternateLink,"
+"fileSize"
+")"
+")";

try {
// Get existing token if it exists, or create new one
const pageToken =
scriptProperties.getProperty(id) 
|| Drive.Changes.getStartPageToken({ driveId: id, supportsAllDrives: true    }).startPageToken;
// Get drive changes list and corresponding newStartPageToken to use on next script run
const { newStartPageToken, items = [] } = Drive.Changes.list({
fields,
pageToken,
driveId: id,
includeItemsFromAllDrives: true,
includeRemoved: true,
pageSize: 1000,
supportsAllDrives: true
});
// Save new page token for next script run
if (newStartPageToken) {
scriptProperties.setProperty(id, newStartPageToken);
}
// If changed/deleted items found, process the list to prep it for email and split into separate arrays for changes and deletions
if (items.length) {
let deletedItems = getDeleted_(items);
Logger.log(deletedItems);
} else {
Logger.log(`No changes found in ${driveName}`);
}
} catch(error) {
Logger.log("ERROR: " + error);
}
}

下面是它调用的函数,通过删除的文件进行过滤:

function getDeleted_(items) {
let deleted = items
.map(({ file }) => file)
.filter(({ id, alternateLink, title }) => id && alternateLink && title)
.filter(({ labels: { trashed = null } = {} }) => trashed === true);
return deleted;
}

请注意,此代码改编自此处的示例:https://www.labnol.org/google-drive-monitor-201026

尝试获取先前运行的累积已删除ID与当前运行的当前已删除ID之间的差异,然后使用这些ID筛选deletedItems。请参阅下面的代码。

代码:

if (items.length) {
let deletedItems = getDeleted_(items);
// get IDs of previous run of deletedItems, blank if not initialized
let prevDeletedIds = scriptProperties.getProperty("deletedIds") || "";
// get unique Ids of prevDeletedIds (in case of duplicates)
prevDeletedIds = prevDeletedIds.split(",").filter(onlyUnique);
// get unique IDs of deletedItems (in case of duplicates)
let deletedIds = deletedItems.map(item => item.id).filter(onlyUnique);
// get ids from deletedIds not present in prevDeletedIds
let differenceIds = deletedIds.filter(item => !prevDeletedIds.includes(item));
// only include items found in differenceIds
deletedItems = deletedItems.filter(item => differenceIds.includes(item.id));
// set accumulated deletedIds (including prevDeletedIds) as deletedIds
scriptProperties.setProperty("deletedIds", deletedIds.join(",").concat("," + prevDeletedIds.join(",")));
Logger.log(deletedItems);
}
// function for filtering unique values of array
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}

步骤:

  • 存储之前所有运行的累积唯一ID(例如id1id2(
  • 在下一次运行中,获取存储在变量中的deletedItems唯一ID(例如id1id2id3,假设它包含所有删除的ID,包括根据您的问题从以前的运行中删除的ID(
  • 获取当前唯一ID与属性中唯一ID之间的差异
  • 根据您从上一步获得的差异ID(id3(过滤您的deletedItems
  • 将所有累积的已删除ID(id1id2id3(再次存储在属性中,记录deletedItems并结束脚本

最新更新