"Authorization is required to perform that action" in Google Scripts with no way to give authorization - twitter

I am trying to create a sort of middleware so some legacy software I am working on can consume Twitter feeds.
Since Twitter has made API 1.0 obsolete and 1.1 requires OAuth and because for this project I only have client-side scripting available to me, I opted to use a Google script to perform the OAuth negotiation:
Source: http://www.labnol.org/internet/twitter-rss-feeds/27931/
function start() {
// Get your Twitter keys from dev.twitter.com
var CONSUMER_KEY = "-----";
var CONSUMER_SECRET = "----";
// Ignore everything after this line
initialize(CONSUMER_KEY, CONSUMER_SECRET);
}
function initialize(key, secret) {
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", key);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", secret);
var url = ScriptApp.getService().getUrl();
if (url) {
connectTwitter();
var msg = "";
msg += "Sample RSS Feeds for Twitter\n";
msg += "============================";
msg += "\n\nTwitter Timeline of user #labnol";
msg += "\n" + url + "?action=timeline&q=labnol";
msg += "\n\nTwitter Favorites of user #labnol";
msg += "\n" + url + "?action=favorites&q=labnol";
msg += "\n\nTwitter List labnol/friends-in-india";
msg += "\n" + url + "?action=list&q=labnol/friends-in-india";
msg += "\n\nTwitter Search for New York";
msg += "\n" + url + "?action=search&q=new+york";
msg += "\n\nYou should replace the value of 'q' parameter in the URLs as per requirement.";
msg += "\n\nFor help, please refer to http://www.labnol.org/?p=27931";
MailApp.sendEmail(Session.getActiveUser().getEmail(), "Twitter RSS Feeds", msg);
}
}
function doGet(e) {
var a = e.parameter.action;
var q = e.parameter.q;
var feed;
switch (a) {
case "timeline":
feed = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" + q;
break;
case "search":
feed = "https://api.twitter.com/1.1/search/tweets.json?q=" + encodeString(q);
break;
case "favorites":
feed = "https://api.twitter.com/1.1/favorites/list.json?screen_name=" + q;
break;
case "list":
var i = q.split("/");
feed = "https://api.twitter.com/1.1/lists/statuses.json?slug=" + i[1] + "&owner_screen_name=" + i[0];
break;
default:
feed = "https://api.twitter.com/1.1/statuses/user_timeline.json";
break;
}
var id = Utilities.base64Encode(feed);
var cache = CacheService.getPublicCache();
var rss = cache.get(id);
if ((!rss) || (rss == "undefined")) {
rss = JSONtoRSS(feed, a, q);
cache.put(id, rss, 3600);
}
return ContentService.createTextOutput(rss)
.setMimeType(ContentService.MimeType.RSS);
}
function JSONtoRSS(json, type, key) {
oAuth();
var options = {
"method": "get",
"oAuthServiceName": "twitter",
"oAuthUseToken": "always"
};
try {
var result = UrlFetchApp.fetch(json, options);
if (result.getResponseCode() === 200) {
var tweets = Utilities.jsonParse(result.getContentText());
if (type == "search")
tweets = tweets.statuses;
if (tweets) {
var len = tweets.length;
var rss = "";
if (len) {
rss = '<?xml version="1.0"?><rss version="2.0">';
rss += ' <channel><title>Twitter ' + type + ': ' + key + '</title>';
rss += ' <link>' + htmlentities(json) + '</link>';
rss += ' <pubDate>' + new Date() + '</pubDate>';
for (var i = 0; i < len; i++) {
var sender = tweets[i].user.screen_name;
var tweet = htmlentities(tweets[i].text);
rss += "<item><title>" + sender + ": " + tweet + "</title>";
rss += " <author>" + tweets[i].user.name + " (#" + sender + ")</author>";
rss += " <pubDate>" + tweets[i].created_at + "</pubDate>";
rss += " <guid isPermaLink='false'>" + tweets[i].id_str + "</guid>";
rss += " <link>https://twitter.com/" + sender + "/statuses/" + tweets[i].id_str + "</link>";
rss += " <description>" + tweet + "</description>";
rss += "</item>";
}
rss += "</channel></rss>";
return rss;
}
}
}
} catch (e) {
Logger.log(e.toString());
}
}
function connectTwitter() {
oAuth();
var search = "https://api.twitter.com/1.1/application/rate_limit_status.json";
var options = {
"method": "get",
"oAuthServiceName": "twitter",
"oAuthUseToken": "always"
};
try {
var result = UrlFetchApp.fetch(search, options);
} catch (e) {
Logger.log(e.toString());
}
}
function encodeString(q) {
var str = encodeURIComponent(q);
str = str.replace(/!/g, '%21');
str = str.replace(/\*/g, '%2A');
str = str.replace(/\(/g, '%28');
str = str.replace(/\)/g, '%29');
str = str.replace(/'/g, '%27');
return str;
}
function htmlentities(str) {
str = str.replace(/&/g, "&");
str = str.replace(/>/g, ">");
str = str.replace(/</g, "<");
str = str.replace(/"/g, """);
str = str.replace(/'/g, "'");
return str;
}
function oAuth() {
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
I have followed all of the instructions prescribed in the guide including running 'start' twice... and all that does is send my email account an email with the various URLs. When I try to access the URLs provided in the email (and the plan is to drop that URL into our legacy javascript that currently points to the Twitter 1.0 API), i get the error "Authorization is required to perform that action"
I have confirmed countless times that it is set up to "Execute the app as [me]" and "Anyone, even anonymous can access app"
I am not sure what I am missing or what got screwed up.

Turns out, I forgot to set up the callback URL within the Twitter app setup as specified in the source instructions. Oops!
This would explain why it wasn't working even though everything on the Google side was correct.

Related

Why is Outlook Interop opens outlook on my Pc even though some one else is accessing the link on their PC

I have created a function to share feedback with Agents who handled the Chats from Customer.
Feedback needs to be shared by Email from outlook. I tested the code and it does work great on my local PC.
Issue comes when some one else opens the WebApp on their local PC, and audit the Chat.
Some one else auditing chat on their Local PC opens Outlook to share feedback on my PC instead of opening on their own PC.
Can some one please help with the below code, and help me understand what is causing this to happen?
And, How can I resolve this?
Feedback Action method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ShareFeedback(Chat model)
{
int id = model.ChatId;
var q1yes = "30";
var q1no = "0";
var q2yes = "10";
var q2no = "0";
var q3yes = "25";
var q3no = "0";
var q4yes = "35";
var q4no = "0";
if (!ModelState.IsValid)
{
return View(model);
}
int dtoId;
using (Db db = new Db())
{
Chat dto = db.Chats.Where(x => x.ChatId == id).FirstOrDefault();
dto.Feedback = model.Feedback;
dto.FeedbackDateTime = DateTime.Now;
if(model.Question1 == "Yes")
{
dto.Question1 = q1yes;
}
else
{
dto.Question1 = q1no;
}
if (model.Question2 == "Yes")
{
dto.Question2 = q2yes;
}
else
{
dto.Question2 = q2no;
}
if (model.Question3 == "Yes")
{
dto.Question3 = q3yes;
}
else
{
dto.Question3 = q3no;
}
if (model.Question4 == "Yes")
{
dto.Question4 = q4yes;
}
else
{
dto.Question4 = q4no;
}
dto.ErrorGrade = model.ErrorGrade;
if (model.ErrorGrade == "Low")
{
float total = float.Parse(dto.Question1) + float.Parse(dto.Question2) + float.Parse(dto.Question3) + float.Parse(dto.Question4);
dto.QualityScore = total;
}
if (model.ErrorGrade == "Medium")
{
float total = float.Parse(dto.Question1) + float.Parse(dto.Question2) + float.Parse(dto.Question3) + float.Parse(dto.Question4);
float medtotal = total / 2;
dto.QualityScore = medtotal;
}
if (model.ErrorGrade == "High")
{
float total = 00;
dto.QualityScore = total;
}
if(model.ErrorGrade == null)
{
float total = float.Parse(dto.Question1) + float.Parse(dto.Question2) + float.Parse(dto.Question3) + float.Parse(dto.Question4);
dto.QualityScore = total;
}
var uName = User.Identity.Name;
User userDTO = db.Users.Where(x => x.Username == uName).FirstOrDefault();
dto.FeedbackSharedBy = userDTO.Username;
dto.AuditorEmail = userDTO.Email;
db.SaveChanges();
dtoId = dto.ChatId;
}
using (Db db = new Db())
{
Chat dto = db.Chats.Find(dtoId);
Application app = new Application();
MailItem mailItem = app.CreateItem(OlItemType.olMailItem);
if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
{
mailItem.Subject = "Feedback: Chat handled on " + dto.ChatCreateDateTime + " For Customer " + dto.CustName;
mailItem.To = dto.Email;
mailItem.CC = "saurabhwa#cybage.com;sagargo#cybage.com;anacletem#cybage.com;riyazsh#cybage.com";
mailItem.HTMLBody = "Hello " + dto.FirstName + "<br /><br />" + " <b>Res Time:</b> " + string.Format("<b>{0:hh\\:mm\\:ss}</b>", dto.ChatEndDateTime - dto.ChatStartDateTime)
+ " <b>AHT:</b> " + string.Format("<b>{0:hh\\:mm\\:ss}</b>", dto.ChatEndDateTime - dto.ChatCreateDateTime) + " <b>Promptness:</b> " + string.Format("<b>{0:hh\\:mm\\:ss}</b>", dto.ChatCreateDateTime - dto.ChatStartDateTime) + "<br/><br/>" + "Your score for this Chat audit is : " + "<b>" + dto.QualityScore + "%</b>" + "<br /><br />" + "<b>Feedback:</b>" + "<br /><br />" + dto.Feedback;
mailItem.Importance = OlImportance.olImportanceHigh;
mailItem.Display(false);
}
}
return RedirectToAction("StartQMS");
}
Help is much appreciated.
Well, of course, your code is executed on your server, not on the client machine.
Besides the fact that you are using Outlook from a Windows service (IIS), which is a big no-no, you need to run the code on the client side, e.g. from a Java script in a page served by your server to the client browser.
And you cannot use Outlook from JS, unless you are running in IE, and your site is trusted. The best you can do is provide the user with a "mailto:" link that can pop up a new email window with the pre-populated subject, body, and recipients.

status.getText() does not give proper HTML

I am using java and twitter4j.
Issue : I do not get proper response from status.getText() method, link references comes as text
I have a problem. My method is as follow:
Twitter twitter = null;
String userName = "clientname";
int numberOfTweets = 0;
StringBuilder timeLineText = new StringBuilder();
try {
twitter = new TwitterFactory(new GetAuthenticConfiguration().getConfigObject()).getInstance();
ResponseList<Status> statuses = twitter.getUserTimeline(userName);
timeLineText.append("<li>");
for (Status status : statuses) {
numberOfTweets++;
if (numberOfTweets > 12) {
break;
}
int remainder = numberOfTweets % 3;
if (remainder == 0) {
timeLineText.append("</li><li>");
} else {
StringBuilder tempText = new StringBuilder();
try {
tempText.append("<p>");
tempText.append("<span>");
tempText.append("<img alt=\"" + status.getUser().getScreenName() + "\" src=\"" + status.getUser().getMiniProfileImageURL() + "\" />");
tempText.append("<b>" + status.getUser().getName() + "</b> #" + status.getUser().getScreenName() + " " + new SimpleDateFormat("dd MMM").format(status.getCreatedAt()));
tempText.append("</span>");
tempText.append("<p>" + status.getText() + "</p>");
tempText.append("</p>");
} catch (Exception e) {
System.out.println(e);
}
timeLineText.append(tempText);
}
}
timeLineText.append("</li>");
} catch (Exception te) {
System.out.println(te);
}
The response i get is :
Can you tell us which Rolls-Royce #engine powers this aircraft? #AvGeek http://t.co/t5tNXQuMFB
instead of
Can you tell us which Rolls-Royce <a href="/hashtag/engine?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>engine</b></a> powers this aircraft? <a href="/hashtag/AvGeek?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>AvGeek</b></a> <a href="http://t.co/t5tNXQuMFB" class="twitter-timeline-link u-isHiddenVisually" data-pre-embedded="true" dir="ltr" >pic.twitter.com/t5tNXQuMFB</a>
The issue is I am not getting the proper html . Can anyone tell me the reason of it please?
After doing lot of R & D, I have found out that Status.getText() method gives only plain text.
We have to manually convert it to links,hashtags and users.
Below is the method I have written to do that.
Just pass your getText() output to this method (tweet).
I hope this will help to many beginners of Twitter4J.
private String linkifyTweet(String tweet) {
Pattern pattern;
Matcher matcher;
String regex_url = "((https?://\\S+)|(www.\\S+))";
String regex_hashtag = "#(\\w+)";
String regex_user = "#(\\w+)";
//regex to apply links to all urls in the tweet
pattern = Pattern.compile(regex_url);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_url, "<a target=\"_blank\" href=\"$1\">$1</a>");
}
//regex to apply links to all hashtags in the tweet
pattern = Pattern.compile(regex_hashtag);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_hashtag, "<a target=\"_blank\" href=\"https://www.twitter.com/hashtag/$1?src=hash\">#$1</a>");
}
//regex to apply links to all users in the tweet
pattern = Pattern.compile(regex_user);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_user, "<a target=\"_blank\" href=\"https://www.twitter.com/$1\">#$1</a>");
}
//System.out.println(tweet);
return tweet;
}

firefox extension working on page load

I'm trying to create my first extension.
I've found this sample: http://blog.mozilla.org/addons/2009/01/28/how-to-develop-a-firefox-extension/
I need to get some html content on a specific page and write something in the same page, so I modified it and got what I needed (with javascript I added content in the table I want). But to view my content I have to launch the extension from the button on the status bar, while I would like to have it already active in the page as I load/reload it (with a check on the url so to have it working only on that page) but I can't have it automatically.
I tried to add linkTargetFinder.run(); on init area, but... nothing. Moreover the extension as an "autorun" but eve if active, I don0t see any change.
any working sample?
Thanks
Nadia
Here it is the code (I edited just the .js file), I commented a couple of test not working...
var linkTargetFinder = function () {
var prefManager = Components.classes["#mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
return {
init : function () {
gBrowser.addEventListener("load", function () {
var autoRun = prefManager.getBoolPref("extensions.linktargetfinder.autorun");
if (autoRun) {
linkTargetFinder.run();
}
//linkTargetFinder.run(); // doesn't work
}, false);
//linkTargetFinder.run(); // doesn't work
alert("ZZZZZZZZZZZZZZZZZZ"); // doesn't work
},
run : function () {
var head = content.document.getElementsByTagName("head")[0],
style = content.document.getElementById("link-target-finder-style"),
allLinks = content.document.getElementsByTagName("a"),
foundLinks = 0;
if (!style) {
style = content.document.createElement("link");
style.id = "link-target-finder-style";
style.type = "text/css";
style.rel = "stylesheet";
style.href = "chrome://linktargetfinder/skin/skin.css";
head.appendChild(style);
}
for (var i=0, il=allLinks.length; i<il; i++) {
elm = allLinks[i];
if (elm.getAttribute("target")) {
elm.className += ((elm.className.length > 0)? " " : "") + "link-target-finder-selected";
foundLinks++;
}
}
if (foundLinks === 0) {
alert("No links found with a target attribute");
}
else {
//alert("Found " + foundLinks + " links with a target attribute");
}
t = content.document.getElementById("ERSContainer"), // ID of the table
d = t.getElementsByTagName("tr")[1],
r = d.getElementsByTagName("td")[1];
var myMail = "mail: "+r.textContent; //ok scrive nella td
var myName = content.document.getElementById("buyercontactname").value;
var myAddr1 = content.document.getElementById("buyeraddress1").value;
var myAddr2 = content.document.getElementById("buyeraddress2").value;
var myCity = content.document.getElementById("buyercity").value;
var myProv = content.document.getElementById("buyerstateprovince").value;
var myCAP = content.document.getElementById("buyerzip").value;
var elt = content.document.getElementById("buyercountry");
var myCountry = elt.options[elt.selectedIndex].text;
var myTel = content.document.getElementById("dayphone1").value;
var myTag1 = "<tr><td colspan='2'>OK!!!<br />";
var myTag2 = "</td></tr>";
z= t.innerHTML;
t.innerHTML = myTag1 + myMail +
" - "+myName+
myAddr1 + "<br />" +
myAddr2 + "<br />" +
myCity + "<br />" +
myProv + "<br />" +
myCAP + "<br />" +
myCountry + "<br />" +
myTel + "<br />" +
myFlash+
myTag2+z;
}
};
}();
window.addEventListener("load", linkTargetFinder.init, false);
If what you are doing is running a bit of JavaScript on a specific web page, like adding content into a table, maybe you should consider doing a userscript for the Greasemonkey addon instead of a full addon. With this you write your JS for the page and it gets executed each time you browse this specific page.
edit:
Try with this :
init: function () {
gBrowser.addEventListener("load", linkTargetFinder.run, true);
},
...
I bet that the extensions.linktargetfinder.autorun does not exist. So getBoolPref throws an exception and the rest is history.
Change your code to the following
var autoRun;
try {
autoRun = prefManager.getBoolPref("extensions.linktargetfinder.autorun");
} catch(e){
autoRun = false;
}

Refresh tweets frequently in my site homepage without reaching to the rate limit

I am working on the site which needs real time tweets to be displayed to users. I have used Tweet Sharp library to fetch tweets.
My site needs tweets to be refreshed frequently, but sometimes I get {"The remote server returned an error: (429) Too Many Requests."} error.
As my site needs real time information, I have to fetch tweets frequently. How can I achieve this? How to get newest tweets without hitting to the Rate Limits?
TwitterService service=new TwitterService(AppSetting.objTwitterClientInfo.ConsumerKey, AppSetting.objTwitterClientInfo.ConsumerSecret, AppSetting.objTwitterModerateInfo.ModerateAccessToken, AppSetting.objTwitterModerateInfo.ModerateAccessTokenSecret);
var options = new ListTweetsOnHomeTimelineOptions();
options.ExcludeReplies = false;
options.Count = intTotalRec;
var lstTwitterStatus = service.ListTweetsOnHomeTimeline(options);
You can use the streaming api like this:-
public void Can_stream_from_user_stream() {
const int maxStreamEvents = 5;
var block = new AutoResetEvent(false);
var count = 0;
service.StreamUser((streamEvent, response) =>
{
if (streamEvent is TwitterUserStreamEnd)
{
block.Set();
}
if (response.StatusCode == 0)
{
if (streamEvent is TwitterUserStreamFriends)
{
var friends = (TwitterUserStreamFriends)streamEvent;
Assert.IsNotNull(friends);
Assert.IsNotNull(friends.RawSource);
Assert.IsTrue(friends.Ids.Any());
}
if (streamEvent is TwitterUserStreamEvent)
{
var #event = (TwitterUserStreamEvent)streamEvent;
Assert.IsNotNull(#event);
Assert.IsNotNull(#event.TargetObject);
Assert.IsNotNull(#event.RawSource);
Console.Write(#event.Event + "\n" + #event.Source + "\n" + #event.Target);
}
if (streamEvent is TwitterUserStreamStatus)
{
var tweet = ((TwitterUserStreamStatus)streamEvent).Status;
Assert.IsNotNull(tweet);
Assert.IsNotNull(tweet.Id);
Assert.IsNotNull(tweet.User);
Assert.IsNotNull(tweet.RawSource);
Assert.IsNotNull(tweet.User.ScreenName);
Console.WriteLine(tweet.User.ScreenName + "\n" + tweet.Text);
}
if (streamEvent is TwitterUserStreamDirectMessage)
{
var dm = ((TwitterUserStreamDirectMessage)streamEvent).DirectMessage;
Assert.IsNotNull(dm);
Assert.IsNotNull(dm.Id);
Assert.IsNotNull(dm.Sender);
Assert.IsNotNull(dm.Recipient);
Assert.IsNotNull(dm.RawSource);
Console.WriteLine(dm.SenderScreenName + "\n" + dm.RecipientScreenName + "\n" + dm.Text);
}
if (streamEvent is TwitterUserStreamDeleteStatus)
{
var deleted = (TwitterUserStreamDeleteStatus)streamEvent;
Assert.IsNotNull(deleted);
Assert.IsTrue(deleted.StatusId > 0);
Assert.IsTrue(deleted.UserId > 0);
}
if (streamEvent is TwitterUserStreamDeleteDirectMessage)
{
var deleted = (TwitterUserStreamDeleteDirectMessage)streamEvent;
Assert.IsNotNull(deleted);
Assert.IsTrue(deleted.DirectMessageId > 0);
Assert.IsTrue(deleted.UserId > 0);
}
count++;
if (count == maxStreamEvents)
{
block.Set();
}
}
else
{
Assert.Ignore("Stream responsed with status code: {0}", response.StatusCode);
}
});
block.WaitOne();
service.CancelStreaming();
}

Google Calendar not displaying correct time

I have a Google Calendar for a school website I'm working on and am using the Google API to display the next five calendar events. One problem is that the time displays on a 24 hour clock instead of AM and PM, but that's not my main problem. The main problem is that while the events display the correct time on the website, when you click on the event to view it in the calendar event view, it will only display GMT time instead of Eastern Time. While logged into the Google account, the events display the right time zone, but whenever you view it while not logged in, it defaults to GMT.
I have tried changing it to another time zone and change it back, didn't fix it.
I also made sure all settings in both the calendar and the account were set to Eastern time zone, at least everywhere I could find it.
I've seen a lot of people with similar problems on Google sites using the ical or other feeds, but I haven't seen anyone with the problem using a code similar to mine.
The website is live: http://fletcheracademy.com. And here is the main javascript code that pulls it.
There's probably some details I'm missing, let me know if there's anything else you need to know. Thanks so much!
<script type="text/javascript">
google.load("gdata", "2.x");
function init() {
google.gdata.client.init(handleGDError);
loadDeveloperCalendar();
}
function loadDeveloperCalendar() {
loadCalendarByAddress('fletcheracademycalendar#gmail.com');
}
function padNumber(num) {
if (num <= 9) {
return "0" + num;
}
return num;
}
function loadCalendarByAddress(calendarAddress) {
var calendarUrl = 'https://www.google.com/calendar/feeds/' +
calendarAddress + '/public/full';
loadCalendar(calendarUrl);
}
function loadCalendar(calendarUrl) {
var service = new
google.gdata.calendar.CalendarService('gdata-js-client-samples-simple');
var query = new google.gdata.calendar.CalendarEventQuery(calendarUrl);
query.setOrderBy('starttime');
query.setSortOrder('ascending');
query.setFutureEvents(true);
query.setSingleEvents(true);
query.setMaxResults(5);
service.getEventsFeed(query, listEvents, handleGDError);
}
function handleGDError(e) {
document.getElementById('jsSourceFinal').setAttribute('style', 'display:none');
if (e instanceof Error) {
alert('Error at line ' + e.lineNumber + ' in ' + e.fileName + '\n' + 'Message: ' + e.message);
if (e.cause) {
var status = e.cause.status;
var statusText = e.cause.statusText;
alert('Root cause: HTTP error ' + status + ' with status text of: ' + statusText);
}
} else {
alert(e.toString());
}
}
function listEvents(feedRoot) {
var entries = feedRoot.feed.getEntries();
var eventDiv = document.getElementById('events');
if (eventDiv.childNodes.length > 0) {
eventDiv.removeChild(eventDiv.childNodes[0]);
}
var ul = document.createElement('ul');
//document.getElementById('calendarTitle').innerHTML =
// "Calendar: " + feedRoot.feed.title.$t;
var len = entries.length;
for (var i = 0; i < len; i++) {
var entry = entries[i];
var title = entry.getTitle().getText();
var startDateTime = null;
var startJSDate = null;
var times = entry.getTimes();
if (times.length > 0) {
startDateTime = times[0].getStartTime();
startJSDate = startDateTime.getDate();
}
var entryLinkHref = null;
if (entry.getHtmlLink() != null) {
entryLinkHref = entry.getHtmlLink().getHref();
}
var dateString = (startJSDate.getMonth() + 1) + "/" + startJSDate.getDate();
if (!startDateTime.isDateOnly()) {
dateString += " " + startJSDate.getHours() + ":" +
padNumber(startJSDate.getMinutes());
}
var li = document.createElement('li');
if (entryLinkHref != null) {
entryLink = document.createElement('a');
entryLink.setAttribute('href', entryLinkHref);
entryLink.appendChild(document.createTextNode(title));
li.appendChild(entryLink);
li.appendChild(document.createTextNode(' - ' + dateString));
} else {
li.appendChild(document.createTextNode(title + ' - ' + dateString));
}
ul.appendChild(li);
}
eventDiv.appendChild(ul);
}
google.setOnLoadCallback(init);
</script>
Try this!
Where you have:
var calendarUrl = 'https://www.google.com/calendar/feeds/' + calendarAddress + '/public/full';
you should add something like:
&ctz=Europe/Lisbon
Check here for the correct name of your timezone.

Resources