-
-
Save dhou/51784 to your computer and use it in GitHub Desktop.
Ubiquity command to post to jiwai.de
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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: "[email protected]" | |
}, | |
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