DriveApp.remove(folder) using REST API? - google-drive-api

I want to 'hide' a folder from the users Drive root, as it contains mostly junk Google Docs. I don't want to actually trash it, or use the appData storage as I can't then convert things to Google Docs.
In Apps Script, I can call DriveApp.remove(folder) and the file is given no parents at all, not even the root. I've tried calling the create method with "parents": [] but the folder is still created in the root.
Is there a way to make this happen with the REST API?

Figured it out. Supplying an empty parents list means Google will assign the folder to the root of your Drive. The only way to change this is to supply an update request indicating that you want to remove the parents of the folder that fall under the alias root.
In Python, it's as simple as this:
service.files().update(fileId=id, removeParents='root').execute()

Related

How to upload a subfolder in shared google drive using python?

Need to know how to do the same in shared drive.
I was able to create a subfolder in my drive using:
file_metadata = {
'supportsAllDrives':True,
'parents': ['twLBZwLdxfBKTEX0VUUr6'],
'name': "new folderrrrr sub",
'mimeType': 'application/vnd.google-apps.folder',
}
file = DRIVE.files().create(body=file_metadata,
fields='id', supportsAllDrives=True, supportsTeamDrives=True).execute()```
I grasp that you want to upload a folder filled with files in a shared drive. If that isn't your question, please forgive me. To accomplish that you'll need editing permission to be able to write into that shared drive. With that on mind, your operation can be divided into two steps:
First you want to create a folder inside the shared drive in a way similar as this one. As the parents[] you have to use the id property of the shared drive (you can get it by using the LIST method).
After that you'll have to upload every file, one by one, with a code akin this one. You'll need to use the identifier of the folder created on the previous step and the appropriate MIME type.
For both operation you must use the CREATE method with the supportsAllDrives parameter set to true (this requirement is only needed until the first of June of 2020 as described on the linked documentation). You can read here how to set up a working Drive API environment for Python if you don't have one already. If you have any doubt or request additional help, please don't hesitate to comment on my answer.

How can I use Google Apps Script to move files between personal Google Drives and Team Drives?

Recently, I gained access to Google Team Drive via Google's Team Drive early adopter program.
I created a Google Docs file called Hello, world!, and then wrote a short Google Apps Script function which uses an addFile() method to update which Google Drive folder the file is attached to:
function move_or_link_file() {
var source = DriveApp.getFolderById("<sourceID>");
var fileiter = source.getFilesByName("Hello, world!");
var dest = DriveApp.getFolderById("<destID>");
while (fileiter.hasNext()) {
var file = fileiter.next();
dest.addFile(file);
}
}
Typically, a Google Drive folder has a URL which matches the following pattern: https://drive.google.com/drive/folders/<alphanumericID>. Although it's perhaps a bit inelegant, I can test my code under various operating scenarios and conditions by simply opening different combinations of Google Drive folders in a web browser, selecting the <alphanumericID> portion of the folder URL, and then manually copy-and-pasting values for this string into <sourceID> and <destID>.
After testing, I am able to identify four different input conditions which result in three distinct behaviors:
Case 1: <sourceID> and <destID> are both folders in my personal Google Drive:
In this case, the script behaves in effect as if it's creating a symbolic link: the Hello, world! file now appears in both directories. Note that it really is the same file, not two identical copies: for example, if I open the document, then the document URL, like the folder URLs, also follows a pattern: https://docs.google.com/document/d/<documentID>/edit. I can tell the file is the same because when I open it, the URL for the document shares the same <documentID>, regardless of which parent folder I use to access it.
For case 1, I can also get the script to behave more like a mv command by simply appending an additional line, source.removeFile(file); to the end of the file iterator loop.
Case 2: <sourceID> is a folder in my personal Google Drive while <destID> is a folder in a Team Drive:
In this case, the script behaves like a mv command by default, rather than as a symbolic link, even without the additional call to the removeFile() method that I mentioned in case 1: i.e., the Hello, world! file simply disappears from my personal drive and reappears in the Team Drive.
Case 3: <sourceID> and <destID> are both folders in a Google Team Drive:
This results in an error message from Google Apps Script: Cannot use this operation on a Team Drive item. (line 7, file "move_or_link_file").
Case 4: <sourceID> is a folder in a Team Drive while <destID> is a folder in my personal Google Drive:
Same error as for Case 3.
Now here is the really weird part: the GSuite graphical user interface (i.e., what you are using when you access Google Drive files and folders via the web browser) offers a Move command via a popup window that appears when you right-click on a file. This GUI version of the Unix-like mv command behaves identically for all four of the above cases: it doesn't matter whether you are moving a folder back and forth between a personal drive or team drive, or internally within a drive, it works correctly and moves the file to where you would expect it to go, every time.
So, I presume it must be possible to implement a mv command via Google's API, somehow, given that they've evidently done it already for users of the GUI interface.
Thus my question: given that it's empirically possible to move files back and forth between arbitrary combinations of folders in personal drives and team drives, how would I actually do it, using only the API calls provided by Google Apps Script?
Also, a bonus question: suppose that, similar to Case 1, instead of moving a file between two different folders in the same Team Drive, I actually wanted to create a symbolic link attaching the file to both folders--how would I use the Google API to do that as well? (I.e., how can I get Case 3 to behave more like Case 1?)
The Google Team Drives only recently started allowing scripts in general. I would imagine the file move you were able to achieve in case 2 is not even intended. There are still several limitations on the team drive (for example you cannot move folders).
For Case 1 I can simply point out that your script is not actually a move command. You should actually imagine Google Drive folders as Gmail tags. A file can have no folders at all. Your script merely assigns a tag to the file and as such it can appear in many folders (just like an email can have many Gmail tags and appear in each tags "folder").
It works in case 2 because Team Drive is a seperate entity from your personal drive. In essence, when you added it to the team drive you had to give up the ownership of the file. As far as I have seen, team drive considers that adding a file to it means that it should be removed from all other parents. I would assume that is why in cases 3 and 4 you cannot move any items. The owner is the team drive itself, however the commands are being sent as a regular Gsuite user.
Drive REST api was recently (~begining of March) updated to work with team drives: https://developers.google.com/drive/v3/web/about-teamdrives so I believe that technically what you are looking for can be done, however considering there are still several limitations on team drives, I don't think it will be documented as well as it could be.

Move file from appDataFolder to user's root folder with Google drive API

Is it possible to move file from appDataFolder to user's root folder on Google Drive using drive API v2 or v3? I can't find any example how to do that. I just try to use gapi.client.drive.files.update from javascript drive v3 API and addParents parameter to change folder, it works fine with files in user's root folder, but doesn't work with files in appDataFolder.
I know that it is possible to copy file from appDataFolder to user's drive root, but I need to keep fileId, and copying generates new fileId for copied file.
I found there is a file property called "spaces" and files from appDataFolder a in spaces=appDataFolder whereas files from user's root folder are in spaces=drive. Is it possible to move file between these spaces keeping same fileId?
I found some similar posts:
Copy an exising Drive file into the appdata folder
Is it possible to share the application data on google drive
and it looks like it is not possible to do it this way. When I check my console I also get "Method not supported for appdata contents" or "Method not supported for files within the Application Data folder." message.
So is there any method to move file from appDataFolder?
Thank's for help.
No, it seems to be impossible. The current document doesn't mention about that, but the error message clearly says so. Thumb down for drive api.

Remove a file that was previously added from Shared With Me to My Drive

Google Drive has a cool feature: one can add a file or folder from Shared With Me to My Drive.
Then I can delete this file from My Drive in the same manner (note that if I delete shared file in web version it won't go to Trash)
However, I am getting 403 Forbidden error while trying to delete this file using Google Drive API (because of insufficient permissions due to that I am not owner of this file). So, as one can see, this is not a simple Delete request. How can I implement this functionality?
Add to My Drive changes the parents collection for the item in question. To change this, you will want to unparent the item rather than delete.
Use the about.get call to retrieve the My Drive ID, then remove that ID from the list of parents in the file resource for the file/folder. Update the file with the new list of parents.
A late answer, but I ran into this issue too. This happens because the file isn't actually copied, it's the same instance. If you remove it from My Drive, it will be removed from the Shared Drive too. And you may lack permission to remove it from the Shared Drive.
If you want to just remove it from My Drive: click on the file. In the right panel, under Details, there is a list of locations. At least the Shared Drive and My Drive is listed there. Click the X to remove it from My Drive, and it will disappear there while preserved on the Shared Drive.
This is what I found. After removing the parent of an item shared with me, do a sharedWithMe search still return the item, even though the item's parent list is empty.
Here is the code:
string sItemId = (this is the Id of the item shared with me);
string sParentId = driveService.About.Get().Execute().RootFolderId;
driveService.Parents.Delete(sItemId, sParentId).Execute();
var parentList = m_driveService.Parents.List(sItemId).Execute();
At this point parentList.Items.Count is 0.
Now when I search sharedWithMe the item is in the return list.

Google apps script - Folder as a script container

Is it possible to restrict the reach of a Google Apps Script to a given Google Drive folder?
I'm creating a stand alone apps script that will be hosted as a web app.
The goal of the script is to list all the sub-folders contained inside the folder (the root folder) where the stand alone script is saved and return a JSON with information about those sub-folders and the files that they contain.
notes:
The name or the id of the root folder is unknown as the script will be distributed to Google Drive users and I want to allow them to save the script inside any folder they would like to.
Although the root folder can have any name or any hierarchical position inside the user's Google Drive folders tree, I'm planning on enforcing a predefined naming structure for the sub-folders.
I thought about two approaches to solve this, but I do not know which one is possible and what Classes and Methods to use.
1)The first approach would be to restrict the script reach to it's container folder, therefore the call to DocsList.getFolders(), would return an array of folders objects just for the folders (sub-folders) contained by the root folder.
Question: Does Google Apps Script provide a Class or Method to restrict the reach of a stand alone script, as described above?
2) Get the name or id of the root folder containing the script and using it retrieve the sub-folders and their files.
Question Does Google Apps Script provide a Method to get the name or the id of the folder that contains the script?
Thanks in advance for any help or tip.
None of those are currently possible. You can write a ui to ask the user for the folder. The google picker now supports picking folders.