我正尝试使用here中所述的Google Drive File API列出我的所有Google脚本文件。但是,我总是返回一个空的[]列表。我认为我的令牌和范围都不错,因为我正在从Google OAuth2找回它:
{ "access_token": "xxxxx", "expires_in": 3600, "refresh_token": "yyyyy",
"scope": "https://www.googleapis.com/auth/drive.scripts https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive",
"token_type": "Bearer"
}
但是当我使用mimeType过滤发出查询时(我只想获取Google应用脚本列表):
mimeType = 'application/vnd.google-apps.script'
即使我刚刚在Google表格中创建了Google脚本,我也只返回一个空项目列表([]):
{ "kind": "drive#fileList", "etag": "....", "selfLink": "https://www.googleapis.com/drive/v2/files?q=mimeType+%3D+'application/vnd.google-apps.script'", "incompleteSearch": false, "items": []}
我猜想app-script意味着除Google脚本代码(属于Google表格的一部分)以外的其他含义...感激任何帮助:)
答案 0 :(得分:3)
一个“变通办法”拼凑而成的被子,以获取独立和绑定项目ID的列表
我在此发布了此信息,是因为在过去的几天中我多次浏览了此页面,以防万一有人真的想获得他们项目的完整列表,并且不介意跳过几圈就可以了,那么这对他们可能有用。
我找到了一种获取所有我的Apps脚本项目文件ID的方法。它虽然不漂亮,但我将所有1393个装订成独立的。我进入Google Developer Hub后,发现可以在属性名称data-script-id="project id"
中找到我的项目ID,并继续向下移到列表的底部,我得以使该页面继续搜索更多页面,直到出现该页面为止。一无所有。然后,我进入Chrome开发人员工具,发现包含所有具有上述属性的div的div,对我来说,这个名字叫做<div class="uBvHbd"
,我复制了整个div并尝试将其粘贴到Google的ascii文件中帐户,但是我发现这是一个问题,因此我打开了UltraEdit的副本并将其粘贴到了那里。我玩了一段时间正则表达式,花了一整天的时间对UltraEdit文档模型及其Javascript Engine版本进行了培训,并开发了以下例程,使我可以构建完整的projectids列表。
UltraEdits脚本语言:
function getDocumentPaths() {
UltraEdit.outputWindow.write('File Paths:');
for(var i=0;i<UltraEdit.document.length;i++) {
UltraEdit.outputWindow.write('[' + i + ']: ' + UltraEdit.document[i].path);
}
}
function getFileNames() {
var nA=[];
var fnToIdx={fnA:[]};
for(var i=0;i<UltraEdit.document.length;i++) {
var p=UltraEdit.document[i].path;
var pA=p.split(/\\/);
var fn=pA[pA.length-1].split('.')[0];
fnToIdx.fnA.push(fn);
fnToIdx[fn]=i;
}
UltraEdit.outputWindow.write('FileNames: \r\n' + fnToIdx.fnA.join('\r\n'));
return fnToIdx;
}
function getScriptIdsIndex() {
for(var i=0;i<UltraEdit.document.length;i++) {
if(UltraEdit.document[i].isName('ScriptIds')) {
return i;
}
}
}
function getFileIndexByName(name) {
var name=name||'ScriptIds';
if(name) {
for(var i=0;i<UltraEdit.document.length;i++) {
if(UltraEdit.document[i].isName(name)) {
return i;
}
}
}else{
UltraEdit.messageBox("Invalid or Missing Inputs at getFileIndexByName().","Alert")
}
}
function getAllFileIndices(obj) {
UltraEdit.outputWindow.write('File Indices:');
var fnIndicesA=[]
for(var j=0;j<obj.fnA.length;j++) {
fnIndicesA.push({name:obj.fnA[j] , index:obj[obj.fnA[j]]})
}
var_dump(fnIndicesA);
}
function updateWorkingTabs(index) {
UltraEdit.outputWindow.write('Index: ' + index);
UltraEdit.document[index].selectAll();
UltraEdit.document[index].copy();
var workingTabsA=[];
for(var i=0;i<UltraEdit.document.length;i++) {
if(UltraEdit.document[i].path.slice(0,-1)=='Edit') {
UltraEdit.document[i].paste();
workingTabsA.push(i);
}
}
return workingTabsA;
}
function findAllIds() {
var fnToIndex=getFileNames();
UltraEdit.document[fnToIndex['ScriptIds']].selectAll();
UltraEdit.document[fnToIndex['ScriptIds']].copy();
var s=UltraEdit.clipboardContent;
var re=/data-script-id="[^"]+"/g;
var matchA=s.match(re);
UltraEdit.document[fnToIndex['FileIds']].selectAll();
UltraEdit.document[fnToIndex['FileIds']].cut();
for(var i=0;i<matchA.length;i++) {
UltraEdit.document[fnToIndex['FileIds']].write(matchA[i].slice(16,-1) + '\r\n');
}
}
function removeDuplicates() {
var fnToIndex=getFileNames();
UltraEdit.document[fnToIndex['FileIds']].selectAll();
UltraEdit.document[fnToIndex['FileIds']].copy();
var fnA=UltraEdit.clipboardContent.split('\r\n');
if(!fnA[fnA.length-1]) {
fnA.pop();
}
var uA=[];
for(var i=0;i<fnA.length;i++) {
if(uA.indexOf(fnA[i])==-1) {
uA.push(fnA[i]);
}
}
var s='';
for(var i=0;i<uA.length;i++) {
if(i>0){
s+='\r\n';
}
s+=uA[i];
}
UltraEdit.document[fnToIndex['FileIds']].selectAll();
UltraEdit.document[fnToIndex['FileIds']].cut();
UltraEdit.document[fnToIndex['FileIds']].write(s);
}
UltraEdit.outputWindow.clear();
//UltraEdit.open('E:\\Projects\\ScriptIds\\ScriptIds.txt');
//var ScriptIds_idx=getScriptIdsIndex();
//var wtA=updateWorkingTabs(ScriptIds_idx);
//findAllIds()
removeDuplicates();
输入文件为24 MB,输出列表为81KB,花了我不到5秒钟的时间在我的笔记本电脑上运行了脚本,以删除ID并删除重复项(找不到任何重复项)。
我在Google Apps脚本中运行了这两个例程,以从Google Apps Script API获取脚本信息,以便我可以确定哪些是独立的,哪些是容器绑定的。对于容器绑定,我可以获取容器文件名和ID。
function getInfo(projectId) {
var projectId=projectId||pid;
var rObj={'ProjectId':projectId};
var params = {muteHttpExceptions:true,headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
try {
var url=Utilities.formatString('https://script.googleapis.com/v1/projects/%s',projectId);
}
catch(e) {
return rObj['Error']=e;
}
var resp=UrlFetchApp.fetch(url,params);
var data=JSON.parse(resp.getContentText());
if(data.hasOwnProperty('parentId')) {
var pFile=DriveApp.getFileById(data.parentId)
var parentName=pFile.getName();
var pfldrA=[];
var pFolders=pFile.getParents();
while(pFolders.hasNext()) {
var folder=pFolders.next();
pfldrA.push({id:folder.getId(),name:folder.getName()});
}
rObj['ProjectName']=data.title;
rObj['ParentName']=parentName;
rObj['ParentId']=data.parentId;
rObj['ParentFolders']='';
rObj['ParentFolderIds']='';
//var html=Utilities.formatString('<br /><b>Project Name:</b>%s<br /><b>ParentName:</b> %s<br /><b>ParentId:</b> %s',data.title,parentName,data.parentId);
//html+=Utilities.formatString('<br /><b>Parent Folders:</b>');
for(var i=0;i<pfldrA.length;i++) {
if(i>0) {
rObj.ParentFolders+=', ';
rObj.ParentFolderIds+=', ';
}
//html+=Utilities.formatString('<br /><b>Name:</b> %s <b>Id:</b> %s',pfldrA[i].name,pfldrA[i].id);
rObj.ParentFolders+=pfldrA[i].name;
rObj.ParentFolderIds+=pfldrA[i].id;
}
}else{
rObj['ProjectName']=data.title;
//var html=Utilities.formatString('<br /><b>StandAlone Project</b><br /><b>Project Name:</b>%s<br /><b>ProjectId:</b>%s',data.title,projectId);
}
//Logger.log(data);
//var userInterface=HtmlService.createHtmlOutput(html);
//SpreadsheetApp.getUi().showModelessDialog(userInterface, "Project Info");
return rObj;
}
function updateProjects() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Projects');
var idx={hA:[],hr:1}
idx.hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];
idx.hA.forEach(function(e,i){idx[e]=i;});
var lr=sh.getLastRow();
var sr=getColumnHeight(1,sh,ss) + 1;
var cnt=25;
setGlobal('count',cnt);
if(lr-sr+1<cnt) {
cnt=lr-sr+1;
}
if(sr>=lr) {
setGlobal('count',0);
return;
}
//Item ProjectId ProjectName ParentId ParentName ParentFolders ParentFolderIds
var rg=sh.getRange(sr,1,cnt,sh.getLastColumn());
var vA=rg.getValues();
for(var i=0;i<vA.length;i++) {
if(!vA[i][idx.Item] && vA[i][idx.ProjectId]) {
var pObj=getInfo(vA[i][idx.ProjectId]);
if(!pObj.hasOwnProperty('Error') && pObj.hasOwnProperty('ParentId')) {
vA[i][idx.Item]=i+sr;
vA[i][idx.ProjectName]=pObj.ProjectName;
vA[i][idx.ParentId]=pObj.ParentId;
vA[i][idx.ParentName]=pObj.ParentName;
vA[i][idx.ParentFolders]=pObj.ParentFolders;
vA[i][idx.ParentFolderIds]=pObj.ParentFolderIds;
}else if(!pObj.hasOwnProperty('Error') && !pObj.hasOwnProperty('ParentId')){
vA[i][idx.Item]=i+sr;
vA[i][idx.ProjectName]=pObj.ProjectName;
vA[i][idx.ParentName]='Standalone Project';
}else{
vA[i][idxItem]=i+sr;
vA[i][idx.ProjectName]=(pObj.hasOwnProperty('Error'))?pObj.Error:"Unknown Problem";
}
Utilities.sleep(1000);
}
}
rg.setValues(vA);
}
我稍后再回来,在代码中添加一些注释。它不是很漂亮,但是我现在列出了我所有项目的列表,以及在哪里可以找到它们的列表以及它们所在的容器的名称。我必须感谢@Tanaike提供的Apps脚本库。它确实帮助我弄清楚了如何访问Apps Script API,事实证明,它比我想象的要难得多。
瞥见最终名单的一部分:
答案 1 :(得分:2)
关于检索容器绑定脚本类型的项目的文件列表并从项目中导出每个脚本,请检查以下答案。