In your script, how about the following modification?
Pattern 1:
In this pattern, your script is simply modified.
function RemoveEditors() {
const EDITOR = "mickey@mouse.com";
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
var editor = file.getEditors().find(e => e.getEmail() == EDITOR);
if (editor) {
file.removeEditor(EDITOR);
}
}
}
Pattern 2:
I thought that in the above modification, all files are required to be retrieved. In that case, the process cost might be high. So, in order to reduce the process cost of the script, in this pattern, the files with the editor of EDITOR are searched using the search query. And, the editor is removed.
function RemoveEditors() {
const EDITOR = "mickey@mouse.com";
var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false`);
while (files.hasNext()) {
var file = files.next();
file.removeEditor(EDITOR);
}
}
Pattern 3:
In this pattern, Drive API is used. By this, I thought that when the number of files is large, the process cost might be reduced a little. When you use this script, please enable Drive API at Advanced Google services. And also, please install a Google Apps Script library of BatchRequest. Ref
function RemoveEditors() {
const EDITOR = "mickey@mouse.com";
const q = `'${EDITOR}' in writers and trashed=false`;
let requests = [];
let pageToken = "";
do {
const obj = Drive.Files.list({ q, fields: "nextPageToken,items(permissions(emailAddress,id,role),id)", maxResults: 1000, pageToken });
if (obj.items.length > 0) {
requests = [...requests, ...obj.items.flatMap(({ permissions, id }) => {
const user = permissions.find(({ emailAddress, role }) => role == "writer" && emailAddress == EDITOR);
if (user) {
return {
method: "DELETE",
endpoint: `https://www.googleapis.com/drive/v3/files/${id}/permissions/${user.id}`,
};
}
return [];
})];
}
pageToken = obj.nextPageToken;
} while (pageToken);
if (requests.length == 0) return;
var result = BatchRequest.EDo({ batchPath: "batch/drive/v3", requests });
}
References:
Added:
For example, when the above pattern 2 is used and an error at file.removeEditor(EDITOR) is avoided, how about the following sample script?
Sample 1:
function RemoveEditors() {
const EDITOR = "mickey@mouse.com";
var yourEmail = "###your email address###"; // Please set your email address.
var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false and '${yourEmail}' in owners`);
while (files.hasNext()) {
var file = files.next();
file.removeEditor(EDITOR);
}
}
- From your reply, I'm worried that you might have no permission for removing the editors of the file. So, in this modification, the files, that you are the owner, are used.
Sample 2:
function RemoveEditors() {
const EDITOR = "mickey@mouse.com";
var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false`);
while (files.hasNext()) {
var file = files.next();
try {
file.removeEditor(EDITOR);
} catch(e) {
console.log(`Error message: ${e.message}, Error file: ${file.getId()}`);
}
}
}
- In this modification, when an error occurs at
file.removeEditor(EDITOR), the error is skipped by try-catch. And, about the file that an error occurs, the error message and the file ID are shown in the log. By this, I thought that the reason for the issue might be found.