Skip to content

Instantly share code, notes, and snippets.

@masukomi
Created March 4, 2009 05:20
Show Gist options
  • Save masukomi/73728 to your computer and use it in GitHub Desktop.
Save masukomi/73728 to your computer and use it in GitHub Desktop.
//twtplus
//Forked from: http://sites.google.com/site/coosgadgets/2ii
//Cleared out hacks, refactored code
//Additional features:
//*Shorten all urls in a post
//*d message with friend username autocompletion
//*Post as specified user using "as" modifier
//Visit for more explanation: http://damienh.org/2009/03/02/twtplus-the-missing-twitter-command-for-ubiquity-and-firefox/
twitter_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://twitter.com/home?in_reply_to=${entry.user.screen_name}&in_reply_to_status_id=${entry.id}&status=%40${entry.user.screen_name}+\" ><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 = 140;
var store = Application.storage;
var prefs = Application.prefs;
const JWP_PREFIX = "ubiquity_twitter_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 = getTwitterIds();
if(logins.length > 0){
login = logins[0];
setCurLogin(login);
}
}
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_twitter_friends(callback) {
var curLogin = getCurLogin();
if( curLogin ){
var auth = make_basic_auth(curLogin.username, curLogin.password);
} else {
var auth = null;
}
$j.ajax({
url: "http://twitter.com/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 twitter friends');
},
});
}
var noun_twitter_friend = {
_name: "twitter friend",
friend_list: null,
callback: function(friends) {
noun_twitter_friend.friend_list = friends;
},
suggest: function(text, html) {
if (noun_twitter_friend.friend_list == null) {
get_twitter_friends(this.callback);
return [];
}
if (text.length < 2)
return [];
var suggestions = [];
for (i=0;i<noun_twitter_friend.friend_list.length;i++) {
if (noun_twitter_friend.friend_list[i].match(text, "i"))
suggestions.push(CmdUtils.makeSugg(noun_twitter_friend.friend_list[i]));
}
return suggestions.splice(0, 5);
}
};
function getTwitterIds () {
var passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
var logins = passwordManager.findLogins({}, "http://twitter.com", "", null);
return logins;
}
var noun_twitter_id = {
_name: "Twitter ID",
id_list: null,
suggest: function(text, html){
if (text.length < 2) return [];
if (noun_twitter_id.id_list == null){
noun_twitter_id.id_list = getTwitterIds();
}
var suggs = [];
for (var i = noun_twitter_id.id_list.length - 1; i >= 0; i--){
if(noun_twitter_id.id_list[i].username.match(text, "i"))
suggs.push(CmdUtils.makeSugg(noun_twitter_id.id_list[i].username));
};
return suggs.splice(0,5);
}
}
CmdUtils.CreateCommand({
name: "twtplus",
synonyms: ["twitter","tweet"],
icon: "http://assets1.twitter.com/images/favicon.ico",
author: {
name: "Damien Hou",
email: "[email protected]"
},
description: "Post message to Twitter.com with nifty features",
homepage: "http://damienh.org/category/geek-stuff/ubiquity-geek-stuff/",
license: "MIT/MPL",
takes: {
"message": noun_arb_text
},
modifiers: {
"@": noun_twitter_friend,
as: noun_twitter_id,
d: noun_twitter_friend
},
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('updating 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://twitter.com/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(/(https*:\/\/.*?)(\s|$)/gi, "<nobr><a href=\"$1\">$1</a></nobr>").replace(/@(\w+)/g, "<a href=\"http://twitter.com/$1\">@$1</a>").replace(/<a href/g, "<a style=\"color:#9999FF;\" href");
}
timeline = CmdUtils.renderTemplate(twitter_template, {
entries: data
});
store.set(JWP_TIMELINE, timeline);
store.set(JWP_TIMELINE_DATE, new Date());
$j('#timeline',p).html(store.get(JWP_TIMELINE, ''));
}
});
}
},
preview: function(p, input, mods) {
p.innerHTML = "<div id='status'></div><div id='help'></div><div id='movies'><ul></ul></div><div id='books'><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'];
$j('#status', p).html('Preview: ' + results['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);
},
_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);
};
}
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;
},
execute: function(directObj, mods) {
var statusText = this._processStatus(directObj.text, mods)['status'];
if (statusText.length < 1) {
displayMessage("Forgot something to say?");
return;
}
// detect the "as" phrase to select current twitter login user to post message
var logins = getTwitterIds();
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 = "https://twitter.com/statuses/update.json";
var updateParams = {
source: "ubiquity",
status: statusText
};
$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("Twitter error - status not updated because: " + xhr.statusText);
},
success: function() {
if(auth){
displayMessage("Twitter message posted as " + getCurLogin().username);
}else{
displayMessage("Twitter message posted");
}
}
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment