Sending a .zip from URL through Gmail - google-apps-script

Here's my code:
function myFunction() {
var url = "https://cdn-04.anonfile.com/t3ScWad7b9/fc36c282-1522257874/CRASH_FILES__2018.03.24.14.06.27_.zip";
var blob = UrlFetchApp.fetch(url).getBlob();
GmailApp.sendEmail("derekantrican#gmail.com", "", "", {attachments: [blob]});
}
As you can see, the function gets a file (a .zip) from the url and attaches it to an email that it then sends. The problem is that Google's servers are blocking the .zip:
"Learn more" leads here: https://support.google.com/mail/answer/6590?hl=en
This .zip (you can download from the URL yourself) only contains two .log files and a .xml file - none of which are banned on the url above.
I've also tried uploading to Google Drive first, then sending:
function myFunction(){
var url = "https://cdn-04.anonfile.com/t3ScWad7b9/fc36c282-1522257874/CRASH_FILES__2018.03.24.14.06.27_.zip";
var zipBlob = UrlFetchApp.fetch(url).getBlob();
zipBlob.setContentType("application/zip");
var file = DriveApp.createFile(zipBlob);
GmailApp.sendEmail("derekantrican#gmail.com", "", "", {attachments: [file.getBlob()]});
}
Same result. Any other suggestions?

Have you actually checked the contents of the 'zip' file that gets saved to your Google Drive? The issue is probably due to you attaching an HTML page, not the zip file. The link you provided is for the landing page, not the download itself, so the content of the page is exactly what is being served back when you call UrlFetchApp.fetch().
Here's what was saved to my Google Drive after sending a 'GET' request to your link:
The page requires a user to manually click on the button to initiate the download. There are no redirects, so you can't get the file by using this pattern:
UrlFetchApp.feth(url, {followRedirects: true});
The question is, can you get the actual link to the file? Well, kind of. In Chrome, open your downloads page by pressing Ctrl + J (Windows) or CMD + Shift + J (MacOS). The URLs displayed next to file names are the actual direct links to the files. However, these are very short-lived and expire within seconds.
You can grab the link and quickly paste it inside your code to make sure it works
var blob = UrlFetchApp.fetch(url).getBlob();
Logger.log(blob.getContentType()); //logs 'application/zip'
Logger.log(blob.getName()); // logs CRASH_FILES__2018.03.24.14.06.27_.zip
DriveApp.createFile(blob);
Result (note that it stops working after a few seconds as the new unique link is generated by the server):

Related

How to get url of web app of other spreadsheet? [duplicate]

This question already has answers here:
ScriptApp.getService().getUrl() points to dev URL. How can I get it to point to exec production URL?
(2 answers)
Closed 3 months ago.
This post was edited and submitted for review 3 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I want to get url of web app of other spreadsheet, so I can use that link to put in web app of the current spreadsheet. When open this web app we can click the link to go to other web app.
I don't want to put the link manually. I want to get web app url automatically from file that I set.
Normally we get url with
ScriptApp.getService().getUrl();
But that just get web app url from current file only. I want to get web app url from other file or spreadsheet. I also try to combine with
DriveApp.getFilesByName(name).next();
But it's can't combine together with class ScriptApp.
Let me explain more about my project.
I have a lot of spreadsheet files and each file already deployed as web app.
Each spreadsheet has its own pair. Something like file name "ss1a" will be pair with file name "ss1b", and "ss2a" pair with "ss2b", etc.
My point is I want to write some code in "ss1a" to looking for file "ss1b" and get link web app url from that file automatically, so it can use that link send to html and post in web app of "ss1a", without doing anything anymore in "ss1b".
I don't have any problem with version deployment url because I separate file html as text file and let all spreadsheet do
HtmlService.createTemplate(DriveApp.getFilesByName("index.txt").next().getBlob());
to read html from that file.
So I have only one version of deployment.
I just want to use the same code in every spreadsheet files and let it detect automatically without copy paste any ID or do anything manually.
Please help me
Thank you so much
Get Deployement URL:
function getDeploymentUrl() {
const scriptId = "your script id";
const base = "https://script.googleapis.com/v1/projects/"
const url1 = base + scriptId + "/deployments";
const options = { "method": "get", "muteHttpExceptions": true, "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } };
const r = UrlFetchApp.fetch(url1, options);
const robj = JSON.parse(r);
const deploymentId = robj.deployments[robj.deployments.length - 1].deploymentId;
const deploymenturl = robj.deployments[robj.deployments.length - 1].entryPoints[robj.deployments[robj.deployments.length - 1].entryPoints.length - 1].webApp.url;
return deploymenturl;
}
You can find the script id in the url of the editor and also in project settings. This function is using the Apps Script API

Snapchat download all memories at once

Over the years on snapchat I have saved lots of photos that I would like to retrieve now, The problem is they do not make it easy to export, but luckily if you go online you can request all the data (thats great)
I can see all my photos download link and using the local HTML file if I click download it starts downloading.
Here's where the tricky part is, I have around 15,000 downloads I need to do and manually clicking each individual one will take ages, I've tried extracting all of the links through the download button and this creates lots of Urls (Great) but the problem is, if you past the url into the browser then ("Error: HTTP method GET is not supported by this URL") appears.
I've tried a multitude of different chrome extensions and none of them show the actually download, just the HTML which is on the left-hand side.
The download button is a clickable link that just starts the download in the tab. It belongs under Href A
I'm trying to figure out what the best way of bulk downloading each of these individual files is.
So, I just watched their code by downloading my own memories. They use a custom JavaScript function to download your data (a POST request with ID's in the body).
You can replicate this request, but you can also just use their method.
Open your console and use downloadMemories(<url>)
Or if you don't have the urls you can retrieve them yourself:
var links = document.getElementsByTagName("table")[0].getElementsByTagName("a");
eval(links[0].href);
UPDATE
I made a script for this:
https://github.com/ToTheMax/Snapchat-All-Memories-Downloader
Using the .json file you can download them one by one with python:
req = requests.post(url, allow_redirects=True)
response = req.text
file = requests.get(response)
Then get the correct extension and the date:
day = date.split(" ")[0]
time = date.split(" ")[1].replace(':', '-')
filename = f'memories/{day}_{time}.mp4' if type == 'VIDEO' else f'memories/{day}_{time}.jpg'
And then write it to file:
with open(filename, 'wb') as f:
f.write(file.content)
I've made a bot to download all memories.
You can download it here
It doesn't require any additional installation, just place the memories_history.json file in the same directory and run it. It skips the files that have already been downloaded.
Short answer
Download a desktop application that automates this process.
Visit downloadmysnapchatmemories.com to download the app. You can watch this tutorial guiding you through the entire process.
In short, the app reads the memories_history.json file provided by Snapchat and downloads each of the memories to your computer.
App source code
Long answer (How the app described above works)
We can iterate over each of the memories within the memories_history.json file found in your data download from Snapchat.
For each memory, we make a POST request to the URL stored as the memories Download Link. The response will be a URL to the file itself.
Then, we can make a GET request to the returned URL to retrieve the file.
Example
Here is a simplified example of fetching and downloading a single memory using NodeJS:
Let's say we have the following memory stored in fakeMemory.json:
{
"Date": "2022-01-26 12:00:00 UTC",
"Media Type": "Image",
"Download Link": "https://app.snapchat.com/..."
}
We can do the following:
// import required libraries
const fetch = require('node-fetch'); // Needed for making fetch requests
const fs = require('fs'); // Needed for writing to filesystem
const memory = JSON.parse(fs.readFileSync('fakeMemory.json'));
const response = await fetch(memory['Download Link'], { method: 'POST' });
const url = await response.text(); // returns URL to file
// We can now use the `url` to download the file.
const download = await fetch(url, { method: 'GET' });
const fileName = 'memory.jpg'; // file name we want this saved as
const fileData = download.body; // contents of the file
// Write the contents of the file to this computer using Node's file system
const fileStream = fs.createWriteStream(fileName);
fileData.pipe(fileStream);
fileStream.on('finish', () => {
console.log('memory successfully downloaded as memory.jpg');
});

How can I get the code generated by File -> Publish to the web for a Google Doc using Google Apps Script?

Using the Google Sheets script editor, I want to get the number starting 2PACX that is in the code generated from File -> Publish to the web for a Google Doc.
Note this is different to fileId(), or the number shown in the normal URL for the doc that starts with 1. Is there another name for it? I've spent ages googling and found nothing.
This question is basically the same, but the answer accepted isn't one that actually answers the original question (i.e. getting the 2PACX number programatically). [Already explained the duplicate in this paragraph but editing as it looks like I have to to address the comment below]
I checked in the Drive API in v2 or V3 and the url is not available when you get file details : https://developers.google.com/drive/api/v2/reference/files/get
There is an alternative url which the embedLink but this one is only available with the v2 API.
To get the url you can use this code :
function urlPublishToTheWeb(){
var id = 'YOUR_SHEET_ID';
var url = 'https://www.googleapis.com/drive/v2/files/' + id ;
var options = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions:false
}
var html = UrlFetchApp.fetch(url,options).getContentText();
var json = JSON.parse(html)
Logger.log(json.embedLink)
}
Then go to log (CTRL + Enter) to view the link. If you check your link and this link it looks like pretty similar, just the tabs are at bottom and not top.
Stéphane

Edit on Google Docs without converting

I'm integrating my system with Google Drive. Everything is working so far, but one thing. I cannot edit the uploaded Word documents without converting them to Google Docs first.
I've read here it's possible using a Chrome plugin:
https://support.google.com/docs/answer/6055139?hl=en
But that's not my goal. I'm storing the file's information on my database and then I just request the proper URL for editing and previewing. Previewing is working fine, but when I try the edit URL it says the file does not exist. If I convert the file (using Google Drive's interface) and pass the new ID it works. I don't want to convert the user's documents to Google Drive because they still use Word as their main editing software.
Is there a way to accomplish this?
This is how I'm doing right now:
public static File UploadFile(FileInfo fileInfo, Stream stream, string googleAccount)
{
var mimetype = GetValidMimetype(fileInfo.MimeType);
var parentFolder = GetParentFolder(fileInfo);
var file = new File { Title = fileInfo.Title, MimeType = mimetype, Parents = parentFolder };
var uploadRequest = _service.Files.Insert(file, stream, mimetype);
uploadRequest.Upload();
file = uploadRequest.ResponseBody;
ShareFileWith(file.Id, googleAccount);
return file;
}
This is the URL for editing (where {0} is the file ID):
https://docs.google.com/document/d/{0}/edit?usp=drivesdk
I know that in order to convert the file I just need to:
uploadRequest.Convert = true;
But again, that's not what I want. Is it possible?
Thanks!
EDIT
Just an update. Convert = true should've worked but it's not. I've raised an issue for that here https://github.com/google/google-api-dotnet-client/issues/712
Bottomline, it only works if I open the file on Google Docs and then use its Id...

Download file from Google Drive to local folder from Google Apps Script

I'm trying to download a specific *.csv file from my Google Drive to a local folder on my computer. I have tried the following with no luck:
ContentService.createTextOutput().downloadAsFile(fileName);
I don't get an error, and nothing appears to happen. Any ideas on what's wrong with my attempt?
ContentService is used to serve up text content as a Web Application. The line of code you've shown does nothing on it's own. Assuming that it's a one-line body of a doGet() function that you've deployed as a Web App, then here's why you're seeing nothing:
ContentService - use Content Service, and...
.createTextOutput() - create an empty text output object, then...
.downloadAsFile(fileName) - when a browser invokes our Get service, have it download the content (named fileName) rather than displaying it.
Since we have no content, there's nothing to download, so you see, well, nothing.
CSV Downloader Script
This script will get the text content of a csv file on your Google Drive, and serve it for downloading. Once you've saved a version of the script and published it as a web app, you can direct a browser to the published URL to start a download.
Depending on your browser settings, you may be able to select a specific local folder and/or change the file name. You have no control over that from the server side, where this script runs.
/**
* This function serves content for a script deployed as a web app.
* See https://developers.google.com/apps-script/execution_web_apps
*/
function doGet() {
var fileName = "test.csv"
return ContentService
.createTextOutput() // Create textOutput Object
.append(getCsvFile(fileName)) // Append the text from our csv file
.downloadAsFile(fileName); // Have browser download, rather than display
}
/**
* Return the text contained in the given csv file.
*/
function getCsvFile(fileName) {
var files = DocsList.getFiles();
var csvFile = "No Content";
for (var i = 0; i < files.length; i++) {
if (files[i].getName() == fileName) {
csvFile = files[i].getContentAsString();
break;
}
}
return csvFile
}