Flickr Group Comments
By Mortimer
—
Last update May 18, 2006
—
Installed
1,021 times.
// Flickr Group Comments
// v0.8
// 2006-05-26
// Copyright (c) 2006, Pierre Andrews.
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// ==UserScript==
// @name Flickr Group Comments
// @namespace http://6v8.gamboni.org/Flickr-view-group-comments.html
// @description Display the recent comments in your groups directly in the recent change page
// @source http://6v8.gamboni.org/Flickr-view-group-comments.html
// @identifier http://6v8.gamboni.org/IMG/js/flickrgroupcomments.user.js
// @version 0.8
// @date 2006-05-26
// @creator Pierre Andrews (mortimer.pa@free.fr)
// @include http://*flickr.com/recent.gne*
// ==/UserScript==
//======================================================================
// Configuration
//number of minutes before the next automatic reload.
//if set to false or 0, then there will never be automatic reloads
var AUTO_RELOAD = 10;
//======================================================================
(function () {
var win = (unsafeWindow || window.wrappedJSObject || window);
//update information
var SCRIPT = {
name: "Flickr Group Comments",
namespace: "http://6v8.gamboni.org/Flickr-view-group-comments.html",
description: "Display the recent comments in your groups directly in the recent change page",
source: "http://6v8.gamboni.org/Flickr-view-group-comments.html", // script homepage/description URL
identifier: "http://6v8.gamboni.org/IMG/js/flickrgroupcomments.user.js",
version: "0.8", // version
date: (new Date(2006, 5, 26)) // update date
.valueOf()
};
//======================================================================
//to do the closure and get the right this.
//adapted from http://persistent.info/greasemonkey/gmail.user.js
function getObjectMethodClosure11(object, method,args3) {
return function(arg) {
return object[method](arg,args3);
}
}
function getObjectMethodClosure12(object, method,args3,arg4) {
return function(arg) {
return object[method](arg,args3,arg4);
}
}
//======================================================================
// constants
// http status constants
var OK = 200;
// xmlhttprequest readystate
var COMPLETE = 4;
var DEBUG = false;
win.FlickrGroupComments = function() {;}
win.FlickrGroupComments.prototype = {
//1
init: function() {
GM_addStyle(".EachGroup ul li.read {color: #AAAAAA; list-style-type: circle; font-size: 80%;}\
.EachGroup ul li.read a {color: #99ccff;} ");
var commentsLinks = document.evaluate("/html/body/div[@id='Main']/table[2]/tbody/tr/td[@id='Changes']/table/tbody/tr/td[2]/ul",
document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); // Get all group
for(var i = 0; i < commentsLinks.snapshotLength; i++) { // For each group...
var al = commentsLinks.snapshotItem(i);
this.prepareUL(al);
}
if(AUTO_RELOAD > 0) {
var change = document.evaluate("//td[@id='Changes']/table[1]",
document.body, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
).singleNodeValue;
if(change) {
setTimeout(function() { document.location.reload(); } , AUTO_RELOAD*60*1000);
var reload = document.createElement('p');
reload.innerHTML = "Next automatic reload in: "+AUTO_RELOAD+" min";
reload.setAttribute("style","background-image: url(../images/dotted.gif); background-repeat: repeat-x; background-position: left top;padding-top:10px;");
change.parentNode.insertBefore(reload,change.nextSibling);
var cnt = 0;
var timeout = function() {
var next = AUTO_RELOAD-(cnt++);
reload.innerHTML = "Next automatic reload in: "+
next+
' min';
setTimeout(timeout, 60*1000);
};
setTimeout(timeout, 250);
}
}
},
//2
prepareUL: function(element) {
var read = GM_getValue('flickrgroupcomments.read');
element.parentNode.parentNode.addEventListener('click',
getObjectMethodClosure11(this,"markAllAsRead",element),
true);
news = element.getElementsByTagName("li");
for(var i=0;i<news.length;i++) {
var li = news[i];
var as = li.getElementsByTagName('A');
if(as.length>0 && !/More\.\.\./.test(as[0].innerHTML)) {
var num = -1;
var re = new RegExp('<'+as[0].href+',([0-9]+)>');
var matches;
if(as.length > 1) {
matches = /\(([0-9]+) repl(ies|y)\)/.exec(li.innerHTML);
if(matches) {
num = parseInt(matches[1])+1;
}
}
if(read && (matches = re.exec(read))) {
var show = true;
// if we have already marked this one as read, but the
// stored number is different, then it's like if we did not read it.
// (see comment below)
if(num >= 0 && num != matches[1]) show = false;
if(show) {
li.className = 'read';
}
}
var showA = li.appendChild(document.createElement('A'));
showA.innerHTML = " Show...";
showA.title="Display the message(s).";
showA.setAttribute("style","font-size:85%;color:grey;text-decoration: underline;");
li.fgcShowA = showA;
showA.addEventListener('click',
getObjectMethodClosure12(this,"getGroupId",li,element),
true);
li.addEventListener('click',
getObjectMethodClosure11(this,"markAsRead",li),
true);
}
}
},
//3
markAllAsRead: function(event, ul) {
if(event.target == ul || event.target.tagName == 'TD'|| event.target.tagName == 'H2') {
var news = ul.getElementsByTagName("li");
for(var i=0;i<news.length;i++) {
this.markAsRead(null,news[i]);
}
}
},
//3
markAsRead: function(event,li) {
if(event) {
if(event.target == li.fgcShowA) return;
}
var as = li.getElementsByTagName('A');
if(as.length>0 && !/More\.\.\./.test(as[0].innerHTML)) {
li.className = 'read';
var num = 1;
if(as.length > 1) {
var matches = /\(([0-9]+) repl(ies|y)\)/.exec(li.innerHTML);
if(matches) {
num = parseInt(matches[1])+1;
}
}
var read = GM_getValue('flickrgroupcomments.read');
if(read) read += '<'+as[0].href+','+num+'>';
else read = '<'+as[0].href+','+num+'>';
GM_setValue('flickrgroupcomments.read',read);
}
},
//3
getGroupId: function(event,li,element) {
var showA = li.fgcShowA;
showA.style.display = 'none';
var newDiv = li.fgceNewDiv;
if(!newDiv) {
newDiv = document.createElement("DIV");
newDiv.innerHTML = '<img src="http://www.flickr.com/images/pulser2.gif" style="vertical-align:middle;margin-right:4px;border:0px #ffffff" />';
li.fgceNewDiv = newDiv;
}
var closeA = li.fgcCloseA;
if(!closeA) {
closeA = li.appendChild(document.createElement('A'));
closeA.addEventListener('click',function() {
newDiv.style.display='none';
showA.style.display='block';
closeA.style.display='none';
li.className = 'read';
}, true);
closeA.innerHTML = " Hide";
closeA.title="Hide the messages.";
closeA.setAttribute("style","font-size:85%;color:grey;text-decoration: underline;");
}
li.appendChild(newDiv);
if(!element.fgceGroupID) {
matches = /(flickr.com)?\/groups\/(.+?)\//.exec(element.innerHTML);
if(matches) {
var groupName = matches[2];
var details = {
method : "POST",
onload : getObjectMethodClosure12(this,"process_groupID",li,element),
url : "http://www.flickr.com/services/rest/?method=flickr.urls.lookupGroup&api_key=e8c3239ff04c102ce2d6ed885bf99005&url=" + encodeURIComponent("http://flickr.com/groups/"+groupName),
};
GM_xmlhttpRequest( details );
}
} else {
this.groupIDReceived(element.fgceGroupID,li,element);
}
},
//4
process_groupID: function(req,li,element) {
if(DEBUG) GM_log(req.responseText);
var rsp = req.responseText.replace(/<\?xml.*\?>/,'');
var rsp = new XML(rsp);
if (rsp == null) {
this.error( "Could not understand Flickr's response.", 0, req, li);
} else {
var stat = rsp.@stat;
if (stat == null) {
this.error( "Could not find status of Flickr request", 0, req,li);
} else if (stat != 'ok') {
if (stat == 'fail') {
var err_node = rsp.err[0];
var code = err_node.@code;
var err_msg = err_node.@msg;
this.error( err_msg, code, req,li);
} else {
this.error("Unknown error status: '" + stat + "'", 0, req,li)
}
} else {
element.fgceGroupID = rsp..@id[0];
this.groupIDReceived(element.fgceGroupID,li,element);
}
}
},
//5
groupIDReceived: function(id,li,element) {
if(!element.rssFeed) {
var details = {
method : "GET",
onload : getObjectMethodClosure12(this,"getGroupFeed",li,element),
url : "http://flickr.com/groups_feed.gne?id="+id+"&format=rss_200",
};
GM_xmlhttpRequest( details );
} else {
this.getGroupFeed(null,li,element);
}
},
//6
getGroupFeed: function(req,li,element) {
if(DEBUG) GM_log(req.responseText);
if(!element.rssFeed) {
var rsp = req.responseText.replace(/<\?xml.*\?>/,'');
rsp = new XML(rsp);
if (rsp == null) {
this.error( "Could not parse rss.", 0, req,li);
return;
} else {
element.rssFeed = rsp;
}
}
this.getLastMessage(li,element.rssFeed);
},
//7
getLastMessage: function(threadLi,rss) {
var links = threadLi.getElementsByTagName("a");
var newDiv = threadLi.fgceNewDiv;
newDiv.style.display = 'block';
if(links.length > 0){
var matches = /^([0-9]+) new replies$/.exec(links[0].innerHTML);
var html = '';
var href = '';
if(matches) {
var num = parseInt(matches[1]);
href = links[1].href;
} else if(links[0].innerHTML == "New reply") {
num = 1;
href = links[1].href;
} else {
var matches = /\(([0-9]+) repl(ies|y)\)/.exec(threadLi.innerHTML);
if(matches) {
num = parseInt(matches[1])+1;
} else
num = 1;
href = links[0].href;
}
//mark this one as read with X messages.
//we need to keep track of the number for the case of the "New Topic ... (X replies)"
//where the href is the same but does not always point to the same number of message
var read = GM_getValue('flickrgroupcomments.read');
if(read) read += '<'+links[0].href+','+num+'>';
else read = '<'+links[0].href+','+num+'>';
GM_setValue('flickrgroupcomments.read',read);
newDiv.innerHTML = this.findMessages(rss,href,num);
}
},
//8
findMessages: function(rss,link,num) {
var mess = '';
var messArray = new Array();
cnt = 1;
//we have to introduce the www. as the rss links always contains it,
// but you could have links in the web page without them.
link = link.replace(/^http:\/\/(www.)?/,"http://www.");
for each(item in rss..item) {
if(item.link.indexOf(link) == 0 && cnt <= num) {
//mark all the one we see here are read too.
var read = GM_getValue('flickrgroupcomments.read');
if(read) read += '<'+item.link+',1>';
else read = '<'+item.link+',1>';
//TODO: here we could only push it if it has not been read yet.
messArray.push(item.description);
cnt++;
} else if(cnt > num) {
break;
}
}
if(cnt==1) {
mess="sorry, message not found";
} else {
mess = "<ul style=\"list-style-type:none;margin: 0; padding:0;\">";
for(var i=messArray.length-1;i>=0;i--)
mess += "<li style=\"border-bottom: 1px solid black;padding-left: 1em;\">"+messArray[i]+"</li>";
mess += "</ul>";
}
return mess;
},
error: function(err_msg, code, req, li) {
if(li.fgceNewDiv) li.fgceNewDiv.innerHTML = '<b style="color:red">'+err_msg+'</b>';
}
}
//======================================================================
// launch
try {
window.addEventListener("load", function () {
try {
// update automatically (http://userscripts.org/scripts/show/2296)
win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
} catch (ex) {}
var flickrgp = new win.FlickrGroupComments();
flickrgp.init();
}, false);
} catch (ex) {}
})();