Google Drive and Translation Script - html

I am using this script, but each time it fetches the RSS it creates a new HTML file.
I would like it to just rewrite the previous file instead of creating a new one and fetch only once a day. After that once i share the file is not validated in RSS Validator if there is any way to fix this changing mime or any other option. Any help with this would be appreciated.
function doGet() {
var fromLang = "en";
var toLang = "es";
var rssFeed = "http://xkcd.com/rss.xml";
var feed = parseRSS(rssFeed, fromLang, toLang);
DriveApp.createFile("rssTest", feed, MimeType.HTML);
return ContentService.createTextOutput(feed)
.setMimeType(ContentService.MimeType.RSS);
}
function parseRSS(feed, fromLang, toLang) {
var id = Utilities.base64Encode(feed + fromLang + toLang);
// Cache the RSS feeds for an hour
var cache = CacheService.getPublicCache();
var rss = cache.get(id);
if (rss != null) {
return rss;
}
var item, date, title, link, desc, guid;
var txt = UrlFetchApp.fetch(feed).getContentText();
var doc = Xml.parse(txt, false);
title = doc.getElement().getElement("channel").getElement("title").getText();
// The RSS Feed is translated using Google Translate
rss = '<rss version="2.0">';
rss += "<channel><title>";
rss += LanguageApp.translate(title, fromLang, toLang);
rss += " (" + title + ")</title>";
var items = doc.getElement().getElement("channel").getElements("item");
// Parsing single items in the RSS Feed
for (var i in items) {
try {
item = items[i];
title = item.getElement("title").getText();
link = item.getElement("link").getText();
date = item.getElement("pubDate").getText();
desc = item.getElement("description").getText();
guid = Utilities.base64Encode(link + fromLang + toLang);
title = LanguageApp.translate(title, fromLang, toLang);
desc = LanguageApp.translate(desc, fromLang, toLang,
{contentType: "html"});
rss += "<item>";
rss += " <title>" + title + "</title>";
rss += " <link>" + link + "</link>";
rss += " <pubDate>" + date + "</pubDate>";
rss += " <guid>" + guid + "</guid>";
rss += " <description><![CDATA[" + desc + "]]></description>";
rss += "</item>";
} catch (e) {
Logger.log(e);
}
}
rss += "</channel></rss>";
cache.put(id, rss, 3600);
return rss;
}

You can change the content of a file by just calling the method setContent(). And if you know the ID you can get the file through DriveApp.getFileById().
So this part of your code:
DriveApp.createFile("rssTest", feed, MimeType.HTML);
Can change to this:
var file = DriveApp.getFileById("<your file ID>");
file.setContent(feed);
I've tried to validate this RSS in the validator you sent.
There are some things that I needed to do in order to validate.
In the guid tag there is an error, basically, you need to add isPermaLink="false".
After that remember that the channel elements needs description element and link check it at w3schools.
Doing that made it a valid RSS for me. So you need to change your parseRSS to make it work.
function parseRSS(feed, fromLang, toLang) {
var id = Utilities.base64Encode(feed + fromLang + toLang);
// Cache the RSS feeds for an hour
var cache = CacheService.getPublicCache();
var rss = cache.get(id);
if (rss != null) {
return rss;
}
var item, date, title, link, desc, guid;
var txt = UrlFetchApp.fetch(feed).getContentText();
var doc = Xml.parse(txt, false);
title = doc.getElement().getElement("channel").getElement("title").getText();
// The RSS Feed is translated using Google Translate
rss = '<rss version="2.0">';
rss += "<channel><title>";
rss += LanguageApp.translate(title, fromLang, toLang);
rss += " (" + title + ")</title>";
rss += "<description>Description you need to fill</description>"; // Add this line
rss += "<link>Link you need to fill</link>"; // Add this line
var items = doc.getElement().getElement("channel").getElements("item");
// Parsing single items in the RSS Feed
for (var i in items) {
try {
item = items[i];
title = item.getElement("title").getText();
link = item.getElement("link").getText();
date = item.getElement("pubDate").getText();
desc = item.getElement("description").getText();
guid = Utilities.base64Encode(link + fromLang + toLang);
title = LanguageApp.translate(title, fromLang, toLang);
desc = LanguageApp.translate(desc, fromLang, toLang,
{contentType: "html"});
rss += "<item>";
rss += " <title>" + title + "</title>";
rss += " <link>" + link + "</link>";
rss += " <pubDate>" + date + "</pubDate>";
rss += " <guid isPermaLink="false">" + guid + "</guid>"; // Modified this line
rss += " <description><![CDATA[" + desc + "]]></description>";
rss += "</item>";
} catch (e) {
Logger.log(e);
}
}
rss += "</channel></rss>";
cache.put(id, rss, 3600);
return rss;
}

Related

Exception: Conversion from text/html to application/pdf failed - from yesterday

I was saving my emails as PDF. It was working well. It stopped working for the last few days with the error
Exception: Conversion from text/html to application/pdf failed
It is also reported by someone here :
It just stopped working - google-app-script google-drive-api createFile
function saveGmailAsPDF() {
var gmailLabels = "TESTING";
var driveFolder = "TEST2";
var threads = GmailApp.search("in:" + gmailLabels, 0, 5);
if (threads.length > 0) {
/* Google Drive folder where the Files would be saved */
var folders = DriveApp.getFoldersByName(driveFolder);
var folder = folders.hasNext() ?
folders.next() : DriveApp.createFolder(driveFolder);
/* Gmail Label that contains the queue */
var label = GmailApp.getUserLabelByName(gmailLabels) ?
GmailApp.getUserLabelByName(gmailLabels) : GmailApp.createLabel(driveFolder);
for (var t=0; t<threads.length; t++) {
//threads[t].removeLabel(label);
var msgs = threads[t].getMessages();
var html = "";
var attachments = [];
var subject = threads[t].getFirstMessageSubject();
/* Append all the threads in a message in an HTML document */
for (var m=0; m<msgs.length; m++) {
var msg = msgs[m];
html += "From: " + msg.getFrom() + "<br />";
html += "To: " + msg.getTo() + "<br />";
html += "Date: " + msg.getDate() + "<br />";
html += "Subject: " + msg.getSubject() + "<br />";
html += "<hr />";
html += msg.getBody().replace(/<img[^>]*>/g,"");
html += "<hr />";
var atts = msg.getAttachments();
for (var a=0; a<atts.length; a++) {
attachments.push(atts[a]);
}
}
/* Save the attachment files and create links in the document's footer */
if (attachments.length > 0) {
var footer = "<strong>Attachments:</strong><ul>";
for (var z=0; z<attachments.length; z++) {
var file = folder.createFile(attachments[z]);
footer += "<li><a href='" + file.getUrl() + "'>" + file.getName() + "</a></li>";
}
html += footer + "</ul>";
}
/* Convert the Email Thread into a PDF File */
//The PDF craeted is damaged by the below code
//var blob = Utilities.newBlob(html, "application/pdf").setName("mail" + ".pdf");
//var theFolderId = '{FOLDER ID}';
//var parentFolder = DriveApp.getFolderById(theFolderId);
//folder.createFile(blob);
// PDF is damaged by the below code
//var html = "<h1>Hello world</h1>";
//var blob = Utilities.newBlob(html, "application/pdf", "text.pdf");
//DriveApp.createFile(blob);
//the below code was working well.
var tempFile = DriveApp.createFile("temp.html", html, "text/html");
//the bellow line is giving the error for the last few days
//Error : Exception: Conversion from text/html to application/pdf failed
folder.createFile(tempFile.getAs("application/pdf")).setName(subject + ".pdf");
tempFile.setTrashed(true);
}
}
}
This seems to be an ongoing bug. It seems that it has already been reported to Google Issue Tracker. Go to the issue and click the white star (☆) at the top-left (just left of the issue ID) to increase its priority.

Sending gmail mail to Drive as a pdf with attachment combined

I currently have the following script that was working for us for a while. It was designed to take emails under a certain label, convert them to a pdf, and store them in a google drive folder. It works great. The problem now, is that it stores the email and attachments as separate files. We are trying to change it to where the attachment is combined with the message, so it is just one big pdf instead of multiple files.
The process was done manually for a while, but the load is getting too much. I have experimented with various codes but have had zero luck (I am not a great coder...).
function saveEmailasPDF() {
var gmailLabels = "Bill";
var driveFolder = "Emails";
var threads = GmailApp.search("in:" + gmailLabels, 0, 5);
if (threads.length > 0) {
// Google Drive folder
var folders = DriveApp.getFoldersByName(driveFolder);
var folder = folders.hasNext() ?
folders.next() : DriveApp.createFolder(driveFolder);
// Gmail Label
var label = GmailApp.getUserLabelByName(gmailLabels) ?
GmailApp.getUserLabelByName(gmailLabels) : GmailApp.createLabel(driveFolder);
for (var t=0; t<threads.length; t++) {
threads[t].removeLabel(label);
var msgs = threads[t].getMessages();
var html = "";
var attachments = [];
var subject = threads[t].getFirstMessageSubject();
// Combines the thread into an HTML document
for (var m=0; m<msgs.length; m++) {
var msg = msgs[m];
html += "From: " + msg.getFrom() + "<br />";
html += "To: " + msg.getTo() + "<br />";
html += "Date: " + msg.getDate() + "<br />";
html += "Subject: " + msg.getSubject() + "<br />";
html += "<hr />";
html += msg.getBody().replace(/<img[^>]*>/g,"");
html += "<hr />";
var atts = msg.getAttachments();
for (var a=0; a<atts.length; a++) {
attachments.push(atts[a]);
}
}
// Save the attachement to drive too and then add a link to the message pdf
if (attachments.length > 0) {
var footer = "<strong>Attachments:</strong><ul>";
for (var z=0; z<attachments.length; z++) {
var file = folder.createFile(attachments[z]);
footer += "<li><a href='" + file.getUrl() + "'>" + file.getName() + "</a></li>";
}
html += footer + "</ul>";
}
// Converts the email to a pdf. All the conversation will be in one pdf not seperated
var tempFile = DriveApp.createFile("temp.html", html, "text/html");
folder.createFile(tempFile.getAs("application/pdf")).setName(subject + ".pdf");
tempFile.setTrashed(true);
}
}
}

How do I make a JSON object produce HTML on the page

Here is my JSON
var gal = [
{
"folder":"nu_images",
"pic":"gd_42.jpg",
"boxclass":"pirobox_gall",
"alt":"Rand Poster 1",
"title":"Rand Poster 1",
"thfolder":"th",
"thumbpic":"th_gd_42.jpg"
},
{
"folder":"nu_images",
"pic":"gd_13.jpg",
"boxclass":"pirobox_gall",
"alt":"Explosive Pixel Design",
"title":"Explosive Pixel Design",
"thfolder":"th",
"thumbpic":"th_gd_13.jpg"
}
];
and here is my for loop
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML = "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + ""
};
I am trying to make my JSON show all of the objects in HTML one after the other. I can get it to show the first one or whatever number I put into the array but I don't know how to make it generate a list of them.
Here is a link to my jsfiddle. Any help you can offer would be greatly appreciated.
http://jsfiddle.net/o7cuxyhb/10/
It's being generated here <p id="gallery"></p> just not correctly.
You're overwriting your html with every loop iteration:
document.getElementById("gallery").innerHTML = ...
^---
Perhaps you want something more like
document.getElementById("gallery").innerHTML += ...
^---
which will concatenation the original html contents with your new stuff.
And technically, you shouldn't be doing this in a loop. Changing .innerHTML like that causes the document to be reflowed/re-rendered each time you change .innerHTML, which gets very expensive when you do it in a loop. You should be building your html as a plain string, THEN adding it to the dom.
e.g.
var str = '';
foreach(...) {
str += 'new html here';
}
document.getElementById("gallery").innerHTML += str;
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML += "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + "" };
Add a += instead of an = after innerHTML
Try this:
function displayJson(jsonArray){
var container = document.getElementById("gallery");
for (var i=0; i<jsonArray.length; i++){
var newElement = document.createElement("a").innerHTML = jsonToHtml(jsonArray[i])
container.appendChild(newElement);
}
}
function jsonToHtml(jsonObj){
//Define your dom object here
var el = document.createElement("a").innerHTML = '' // you code here
...
return el;
}
displayJson(gal);

Embed a video using Google Script

I'm trying to use Google Scripting to embed videos I have stored on my Google Drive into HTML. Here's the code I'm using to generate the HTML:
function GenerateTables() {
var folderz = DocsList.getFolder('SharedVideos');
var contents = folderz.getFiles().sort(function(a,b) {return b.getDateCreated()-a.getDateCreated()});
var file;
var name;
var date;
var url;
var dateModified;
var folder;
var textOutput = "<table>";
textOutput += "<tr><th>File Name</th><th>Create Date</th><th>Modified Date</th></tr>"
for (var i = 0; i < contents.length; i++) {
file = contents[i];
folder = file.getParents()[0];
name = file.getName();
url = "https://docs.google.com/file/d/" +file.getId()+"/preview";
date = Utilities.formatDate(file.getDateCreated(), 'GMT-6', 'MM/dd/yyyy hh:mm:ss aaa');
dateModified = Utilities.formatDate(file.getLastUpdated(), 'GMT-6', 'MM/dd/yyyy hh:mm:ss aaa');
textOutput += "<tr><td>" +name + "</td><td>" + date + "</td><td>" + dateModified + "</td></tr>";
textOutput += "<tr><td colspan='3'>";
textOutput += "<iframe src='"+url+"' height='385' width='640'></iframe>";
textOutput += "</td></tr>";
}
textOutput +="</table>";
return textOutput;
}
function doGet() {
var text = GenerateTables();
return HtmlService.createHtmlOutput(text);
}
The iframe is being converted to
<iframe data-caja-src='[the correct URL]' height="385" width="640"></iframe>
I was hoping it would be a simple process, but the more I got looking into it, the more complicated it seemed to be. Is there an easier way to do what I'm trying to do? I don't have much experience using Caja, but maybe there's a simple way to embed a video using Caja, I just couldn't get anything to work.
There is not yet a way to embed videos inside HtmlService. I think there's a feature request for it on the issue tracker, but regardless it's something we know about.

How to serialize HTML DOM to XML in IE 8?

Is there a way to do it(serialization of HTML DOM into XML) in IE 8 or any other older version of IE.
In firefox :
var xmlString = new XMLSerializer().serializeToString( doc );
does it.I haven't tried it, though.
XMLSerializer causes error in IE 8, that it is not defined.
var objSerializeDOM = {
//Variable to hold generated XML.
msg : "",
serializeDOM : function() {
dv = document.createElement('div'); // create dynamically div tag
dv.setAttribute('id', "lyr1"); // give id to it
dv.className = "top"; // set the style classname
// set the inner styling of the div tag
dv.style.position = "absolute";
// set the html content inside the div tag
dv.innerHTML = "<input type='button' value='Serialize' onClick='objSerializeDOM.createXML()'/>"
"<br>";
// finally add the div id to ur form
document.body.insertBefore(dv, document.body.firstChild);
},
/**
* XML creation takes place here.
*/
createXML : function() {
objSerializeDOM.msg += "";
objSerializeDOM.msg += "<?xml version='1.0' encoding='UTF-8'?>\n\n";
// Get all the forms in a document.
var forms = document.forms;
for ( var i = 0; i < forms.length; i++) {
// Get all the elements on per form basis.
elements = document.forms[i].elements;
objSerializeDOM.msg += "<FORM name=\"" + forms[i].name + "\" method=\""
+ forms[i].method + "\" action=\"" + forms[i].action + "\">\n\n";
for ( var j = 0; j < elements.length; j++) {
objSerializeDOM.msg += " <" + elements[j].tagName + " type=\""
+ elements[j].type + "\"" + " name=\""
+ elements[j].name + "\"" + " Value =\""
+ elements[j].value + "\" />\n";
}
alert(document.forms[i].elements[1].event);
}
objSerializeDOM.msg += "\n\n</FORM>\n\n";
alert(objSerializeDOM.msg);
objSerializeDOM.writeToFile(objSerializeDOM.msg);
},
/**
* Writes the msg to file at pre-specified location.
* #param msg
* the XML file created.
*/
writeToFile : function(msg) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.CreateTextFile("c:\\myXML.xml", true);
fh.WriteLine(msg);
fh.Close();
}
};
objSerializeDOM.serializeDOM();
I wrote this JS, I run this javascript using GreaseMonkey4IE. This simply puts a button on every page of the domain you specify in GM4IE. On click of that button it will parse the HTML document and create an XML file. It will also display the same as an alert first and will save the XML in your local drive on path specified.
There a still many improvements I am planning to do, but yes it works and may be give you guys an idea.The program is self-explanatory, I hope.
please have a look here How to get Events associated with DOM elements?Thanks