Skip to content

Instantly share code, notes, and snippets.

@dhou
Created January 25, 2009 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhou/51784 to your computer and use it in GitHub Desktop.
Save dhou/51784 to your computer and use it in GitHub Desktop.
Ubiquity command to post to jiwai.de
//Based on: http://sites.google.com/site/coosgadgets/2ii
//Heavily refactored and with more features
jiwai_template = "\
<div style=\"overflow: auto; height: 450px;\"> \
{for entry in entries} \
<div style=\"margin:0;padding:2px;padding-left:4px;background-color:{if entry_index%2 == 0}#555{else}#313131{/if};border:solid 1px;border-top-color:#484848;border-left:solid 3px #ccc;border-right-color:#2c2c2c;border-bottom-color:#2b2b2b;font-size:13px;-moz-border-radius:5px;\"> \
<a href=\"http://jiwai.de/${entry.user.screen_name}/thread/${entry.id}\" ><img src=\"${entry.user.profile_image_url}\" style=\"height: 2em; float: left;margin-right:3px; margin-top:4px;border:none;\"/></a> \
<span style=\"font-weight: bold\">${entry.user.screen_name}</span> \
<span>${entry.text}</span> \
<div style=\"clear:both;\"></div> \
</div> \
{/for}</div>";
const STATUS_MAXLEN = 500;
var store = Application.storage;
var prefs = Application.prefs;
const JWP_PREFIX = "ubiquity_jiwai_plus";
const JWP_TIMELINE = JWP_PREFIX+"_timeline";
const JWP_TIMELINE_DATE = JWP_PREFIX+"_timeline_date";
const JWP_CUR_LOGIN = JWP_PREFIX+"_cur_login";
var $j = jQuery;
function setCurLogin(login){
store.set(JWP_CUR_LOGIN, login);
}
function getCurLogin(){
var login = store.get(JWP_CUR_LOGIN, '');
if(!login){
logins = getJiwaiIds();
if(logins.length > 0){
login = logins[0];
setCurLogin(login);
}
}
// CmdUtils.log('current login: ' + login.username);
return login;
}
function make_basic_auth(user, password){
var tok = user + ":" + password;
var hash = CmdUtils.getWindow().btoa(tok); //Base64 encode.
return "Basic " + hash;
}
function get_jiwai_friends(callback) {
var curLogin = getCurLogin();
if( curLogin ){
var auth = make_basic_auth(curLogin.username, curLogin.password);
} else {
var auth = null;
}
$j.ajax({
url: "http://api.jiwai.de/statuses/friends.json",
type: "GET",
dataType: "json",
beforeSend: function(req) {
if( auth ) req.setRequestHeader("Authorization", auth);
},
success: function(data) {
var friends = [];
for (var i in data) {
var friend = data[i];
friends.push(friend.screen_name);
}
callback(friends);
},
error: function() {
displayMessage('Failed to get jiwai friends');
},
});
}
var noun_jiwai_friend = {
_name: "jiwai friend",
friend_list: null,
callback: function(friends) {
noun_jiwai_friend.friend_list = friends;
},
suggest: function(text, html) {
if (noun_jiwai_friend.friend_list == null) {
get_jiwai_friends(this.callback);
return [];
}
if (text.length < 2)
return [];
var suggestions = [];
for (i=0;i<noun_jiwai_friend.friend_list.length;i++) {
if (noun_jiwai_friend.friend_list[i].match(text, "i"))
suggestions.push(CmdUtils.makeSugg(noun_jiwai_friend.friend_list[i]));
}
return suggestions.splice(0, 5);
}
};
function getJiwaiIds () {
var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
var logins = passwordManager.findLogins({}, "http://jiwai.de", "", null);
return logins;
}
var noun_jiwai_id = {
_name: "Jiwai ID",
id_list: null,
suggest: function(text, html){
if (text.length < 2) return [];
if (noun_jiwai_id.id_list == null){
noun_jiwai_id.id_list = getJiwaiIds();
}
var suggs = [];
for (var i = noun_jiwai_id.id_list.length - 1; i >= 0; i--){
if(noun_jiwai_id.id_list[i].username.match(text, "i"))
suggs.push(CmdUtils.makeSugg(noun_jiwai_id.id_list[i].username));
};
return suggs.splice(0,5);
}
}
CmdUtils.CreateCommand({
name: "jiwai",
author: {
name: "Damien Hou",
email: "houyongr@gmail.com"
},
icon:"http://asset.jiwai.de/img/favicon.ico",
description: "Post message to Jiwai.de with nifty features",
homepage: "http://damienh.org/category/geek-stuff/ubiquity-geek-stuff/",
license: "MPL",
takes: {
"message": noun_arb_text
},
modifiers: {
"@": noun_jiwai_friend,
as: noun_jiwai_id,
d: noun_jiwai_friend
},
moviesLinks: [],
getShortenedUrl: function(url){
var shortUrl = url;
$j.ajax({
type: "GET",
async: false,
url: 'http://is.gd/api.php',
data: {
'longurl': url
},
error: function() {
displayMessage("Failed to shorten URL");
},
success: function(shortened) {
shortUrl = shortened;
}
});
return shortUrl;
},
hasTimeline: function () {
return store.has(JWP_TIMELINE);
},
getTimeline: function () {
if (this.hasTimeline()) {
return store.get(JWP_TIMELINE,'');
}else{
return '';
}
},
setTimeline: function (timeline){
store.set(JWP_TIMELINE, timeline);
},
timelineExpired: function () {
var now = new Date();
var update = store.has(JWP_TIMELINE_DATE) ? store.get(JWP_TIMELINE_DATE,'') : undefined;
if (update != undefined) {
delta = now - update;
return delta > 120000;
}else{
return false;
}
},
_update_timeline: function(p) {
CmdUtils.log('update timeline');
var now = new Date();
if (this.hasTimeline() && !this.timelineExpired()) {
$j('#timeline',p).html(this.getTimeline());
} else {
var curLogin = getCurLogin();
if( curLogin ){
var auth = make_basic_auth(curLogin.username, curLogin.password);
} else {
var auth = null;
}
$j.ajax({
url:"http://api.jiwai.de/statuses/friends_timeline.json",
params:{count: 10},
type:'GET',
dataType:"json",
beforeSend: function(req) {
if( auth ) req.setRequestHeader("Authorization", auth);
},
success: function(data) {
data = data.slice(0,10);
for (var entry in data) {
data[entry]['text'] = data[entry]['text'].replace(/(http:\/\/[^s]+)/i, "<a href=\"$1\">$1</a>");
}
timeline = CmdUtils.renderTemplate(jiwai_template, {
entries: data
});
store.set(JWP_TIMELINE, timeline);
store.set(JWP_TIMELINE_DATE, new Date());
$j('#timeline',p).html(store.get(JWP_TIMELINE, ''));
}
});
}
},
_getMediaMeta: function(items, type, status, p){
function callback(q, title, link){
status = status.replace(new RegExp("#"+type+"\/"+q+"\/"), title+"("+link+")");
$j('#status', p).html('Preview: ' + status);
}
for (var i=0; i < items.length; i++) {
var m = items[i];
// CmdUtils.log('current movie: '+ m);
CmdUtils.previewGet(p,
'http://api.douban.com/'+type+'/subjects?start-index=1&max-results=1',
{'q':m},
function(data){
var title = $j('entry title',data).text();
if(title){
var href = $j('entry link[rel="alternate"]',data).attr('href');
var img = $j('entry link[rel="image"]',data).attr('href');
$j('#'+type+' ul',p).append('<li style="display:inline;float:left;overflow:hidden;margin:0 5px;text-align:center;"><p><a href="'+href+'">'+title+'</a></p><p><a href="'+href+'"><img src="'+img+'"/></a></p></li>');
var q = $j('feed > title',data).text();
callback(q.substring(3,q.length-4), title, href);
}
},
"xml"
);
};
},
preview: function(p, input, mods) {
p.innerHTML = "<div id='status'></div><div id='help'></div><div id='movie'><ul></ul></div><div id='book'><ul></ul></div><div id='music'><ul></ul></div><div style='clear:both'></div><div id='timeline'></div>";
var results = this._processStatus(input.text, mods);
var status = results['status'];
if(results['movies'] && results['movies'].length > 0){
status = "[电影]"+status;
var movies = results['movies'];
this._getMediaMeta(movies, 'movie', status, p);
}
if (results['books'] && results['books'].length>0) {
status = "[读书]" + status;
var books = results['books'];
this._getMediaMeta(books, 'book', status, p);
}
if (results['music'] && results['music'].length>0) {
status = "[音乐]" + status;
var music = results['music'];
this._getMediaMeta(music, 'music', status, p);
};
$j('#status', p).html('Preview: ' + status);
var rem = STATUS_MAXLEN - status.length;
var help = "<p style=\"font-size:smaller;\">Remaining: " + rem + " chars. Type #url for the current URL. Click avatar to reply.</p>"
$j('#help',p).html(help);
this._update_timeline(p);
},
_parseMovies: function(status){
var movies = status.match(/(?:#movie\/)([^\/]+)(?:\/)/g);
// CmdUtils.log('found movies: ' + movies);
results = [];
if(movies){
for (var i=0; i < movies.length; i++) {
var movie = movies[i].substring(7,movies[i].length-1);
results.push(movie);
// CmdUtils.log('got movie name: ' + movie);
};
}
return results;
},
_parseBooks: function(status){
var books = status.match(/(?:#book\/)([^\/]+)(?:\/)/g);
// CmdUtils.log('found books: ' + books);
results = [];
if(books){
for (var i=0; i < books.length; i++) {
var book = books[i].substring(6,books[i].length-1);
results.push(book);
// CmdUtils.log('got book name: ' + book);
};
}
return results;
},
_parseMusic: function(status){
var music = status.match(/(?:#music\/)([^\/]+)(?:\/)/g);
// CmdUtils.log('found music: ' + music);
results = [];
if(music){
for (var i=0; i < music.length; i++) {
var m = music[i].substring(7,music[i].length-1);
results.push(m);
// CmdUtils.log('got music name: ' + m);
};
}
return results;
},
_processStatus: function(status, mods) {
var elements = {};
//first, replace #url tag with actual current url
var curUrl = CmdUtils.getDocument().URL;
status = status.replace(/(^|\s)#url(\s|$)/, "$1" + curUrl + "$2");
//shorten all urls
var urls = status.match(/((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/g);
if(urls){
for (var i=0; i < urls.length; i++) {
var shortened = this.getShortenedUrl(urls[i]);
status = status.replace(urls[i], shortened);
};
}
elements.movies = this._parseMovies(status);
elements.books = this._parseBooks(status);
elements.music = this._parseMusic(status);
if(mods.d && mods.d.text){
status = 'd '+mods.d.text+' '+status;
}
if (mods["@"] && mods["@"].text) {
status = "@" + mods["@"].text + " " + status;
}
elements['status'] = status;
return elements;
},
_replaceMediaMeta: function(items, type, status){
if(items.length > 0){
switch(type){
case "movie":
status = "[电影]"+status;
break;
case "book":
status = "[读书]"+status;
break;
case "music":
status = "[音乐]"+status;
break;
}
for (var i=0; i < items.length; i++) {
var m = items[i];
$j.ajax({
type:"GET",
url:'http://api.douban.com/'+type+'/subjects?start-index=1&max-results=1',
data:{'q':m},
async:false,
success: function(data) {
var title = $j('entry title',data).text();
if(title){
var link = $j('entry link[rel="alternate"]',data).attr('href');
status = status.replace(new RegExp("#"+type+"\/"+m+"\/"), title+"( "+link+" )");
}
},
dataType:"xml"
});
};
}
return status;
},
execute: function(directObj, mods) {
var status = this._processStatus(directObj.text, mods)['status'];
if (status.length < 1) {
displayMessage("Forgot something to say?");
return;
}
//process media tags
status = this._replaceMediaMeta(this._parseMovies(status), 'movie', status);
status = this._replaceMediaMeta(this._parseBooks(status), 'book', status);
status = this._replaceMediaMeta(this._parseMusic(status), 'music', status);
// detect the "as" phrase to select current jiwai login user to post message
var logins = getJiwaiIds();
if(mods.as && mods.as.text){
var asLogin = mods.as.text;
for (var i = logins.length - 1; i >= 0; i--){
if (logins[i].username == asLogin){
setCurLogin(logins[i]);
var name = getCurLogin().username;
break;
}
}
}
var curLogin = getCurLogin();
if( curLogin ){
var auth = make_basic_auth(curLogin.username, curLogin.password);
} else {
var auth = null;
}
var updateUrl = "http://api.jiwai.de/statuses/update.json";
var updateParams = {
source: "ubiquity",
status: status
};
$j.ajax({
type: "POST",
url: updateUrl,
data: updateParams,
dataType: "json",
beforeSend: function(req) {
if( auth ) req.setRequestHeader("Authorization", auth);
},
error: function(xhr, status, error) {
displayMessage("jiwai error - status not updated because: " + xhr.statusText);
},
success: function() {
if(auth){
displayMessage("Jiwai message posted as " + getCurLogin().username);
}else{
displayMessage("Jiwai message posted");
}
}
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment