Skip to content

Instantly share code, notes, and snippets.

@958
Last active September 27, 2015 18:48
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 958/1315917 to your computer and use it in GitHub Desktop.
Save 958/1315917 to your computer and use it in GitHub Desktop.
[keysnail]facebook plugin
// Info
let PLUGIN_INFO =
<KeySnailPlugin>
<name>faSnail</name>
<description>Yet another facebook client for KeySnail</description>
<author>958</author>
<iconURL>https://sites.google.com/site/958site/Home/files/fasnail.ks.png</iconURL>
<updateURL>https://gist.github.com/958/1315917/raw/fasnail.ks.js</updateURL>
<version>0.0.8</version>
<license>MIT</license>
<include>main</include>
<detail lang="ja"><![CDATA[
=== 使い方 ===
最初にいずれかのエクステを実行すると、認証ページが表示されます。
認証完了後、プロンプト上で Enter して下さい。
なお、この際に、認証完了後の Success と表示されたページを表示しておかないと
認証が完了しませんので、注意してください。
以下のことができます
- ニュースフィードを表示する
- 自分のウォールを表示する
- 友達のウォールを表示する
- 自分のウォールに投稿する
- 自分のウォールに表示ページのリンクを投稿する
- 友達のウォールに投稿する
- ウォールやニュースフィードで like やコメントする
- メッセージを表示する
以下のことは facebook Graph API が対応次第実装予定です
- メッセージを送る
バージョンアップ後に、うまく動作しない場合などありましたら、エクステ 'facebook-reauth' を実行して再認証してください
=== 謝辞 ===
Vimplerator facebook plugin を参考にしました
https://github.com/vimpr/vimperator-plugins/blob/master/facebook.js
Yet Another Twitter Client KeySnail を参考にしました
https://github.com/mooz/keysnail/blob/master/plugins/yet-another-twitter-client-keysnail.ks.js
Icons provided under the Creative Commons Attribution 2.5 License by FAMFAMFAM
http://www.famfamfam.com/lab/icons/silk/
]]></detail>
</KeySnailPlugin>;
// Option
let pOptions = plugins.setupOptions("fasnail", {
"hok_post_photo": {
preset: 'B',
description: M({
ja: "HoK を使って画像をポストするキー",
en: "Photo post key in HoK"
})
},
"keymap": {
preset: {
"C-z" : "prompt-toggle-edit-mode",
"SPC" : "prompt-next-page",
"b" : "prompt-previous-page",
"j" : "prompt-next-completion",
"k" : "prompt-previous-completion",
"g" : "prompt-beginning-of-candidates",
"G" : "prompt-end-of-candidates",
"q" : "prompt-cancel",
// faSnail specific actions
"l" : "like",
"L" : "unlike",
"C" : "post-comment",
"c" : "show-comments",
"o" : "open-url",
"p" : "post-text",
"P" : "post-this-page",
"D" : "delete",
"F" : "open-facebook",
"w" : "show-user-wall",
},
description: M({
ja: "キーマップ",
en: "Local keymap"
})
},
}, PLUGIN_INFO);
// Prompt
let gPrompt = {
get visible() !document.getElementById("keysnail-prompt").hidden,
forced : false,
close : function () {
if (!gPrompt.forced)
return;
gPrompt.forced = false;
if (gPrompt.visible)
prompt.finish(true);
}
};
// Main
if (!share.fasnail)
share.fasnail = {};
let fasnail = (function() {
const STATUS_ICONS = {
'status': 'data:image/png;base64,'+
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAC4SURBVCjPdZFbDsIgEEWnrsMm7oGGfZro'+
'hxvU+Iq1TyjU60Bf1pac4Yc5YS4ZAtGWBMk/drQBOVwJlZrWYkLhsB8UV9K0BUrPGy9cWbng2CtE'+
'EUmLGppPjRwpbixUKHBiZRS0p+ZGhvs4irNEvWD8heHpbsyDXznPhYFOyTjJc13olIqzZCHBouE0'+
'FRMUjA+s1gTjaRgVFpqRwC8mfoXPPEVPS7LbRaJL2y7bOifRCTEli3U7BMWgLzKlW/CuebZPAAAA'+
'AElFTkSuQmCC',
'link': 'data:image/png;base64,'+
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADpSURBVCjPY/jPgB8y0EmBHXdWaeu7ef9r'+
'HuaY50jU3J33v/VdVqkdN1SBEZtP18T/L/7f/X/wf+O96kM3f9z9f+T/xP8+XUZsYAWGfsUfrr6L'+
'2Ob9J/X/pP+V/1P/e/+J2LbiYfEHQz+ICV1N3yen+3PZf977/9z/Q//X/rf/7M81Ob3pu1EXWIFu'+
'Zvr7aSVBOx1/uf0PBEK3/46/gnZOK0l/r5sJVqCp6Xu99/2qt+v+T/9f+L8CSK77v+pt73vf65qa'+
'YAVqzPYGXvdTvmR/z/4ZHhfunP0p+3vKF6/79gZqzPQLSYoUAABKPQ+kpVV/igAAAABJRU5ErkJg'+
'gg==',
'photo' : 'data:image/png;base64,'+
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHvSURBVHjaYvr//z8DJRgggFgYgGDOnDm9'+
'//79i/7+/TvHnz9/GNABUA5MMzExgdmsrKwMbGxs87OysgoBAogFqiDGx8dHlIeHhxEIwIpBpoPY'+
'MBomBrIAhFetWpUAFCoECCCwAUCb2bm4uBiBgnAFUlJSIFvANn748IHh+vXrYD7IFbm5uQx///4F'+
'mwoQQEwgAqQBJAGzRVJSEqz469evDF++fAGz5eXlQRaB1YHUw1wFEEBMyH5lYWEBmQzW8PnzZ4af'+
'P3+CNYEM4eDgALNBapABQACxIAcUyFSQAb9//2b49esXGIP4IAyyFaQG5AJYDIAAQACBXYAcWMzM'+
'zGDbYYaBDAGxQWKcnJxgF8BiBQQAAogF5m9YNLGzszM8f/4cTIM0gKLs/fv3DC9fvmQQEREBq4GF'+
'FwgABBDcCyBDQLaDNAkICDCcOnWKARitYNtAYaGiogLmg1yF7AKAAEIx4M6dO2BJEAYZBtIEEn/8'+
'+DHDixcvwGxkzSAAEEAsyCnNxcUF7jxQiH/79g2sMSgoCGwgsmUwABBALDC/I9MgA0FeAWFhYWGM'+
'JA0LdBAACCCwAcCA+gj0G7+amho8gaDbhAxA0QzUA5YECCCYASvXrFljCYxrXWQ/IkcvirOBUQn0'+
'0kIQGyCAGHHZQiwACDAAXRg49bQg780AAAAASUVORK5CYII=',
'checkin': 'data:image/png;base64,'+
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALcSURBVBgZBcFNiFR1AADw338+dhl3Zmfd'+
'Xbf1a4NCwUSQOiREBVJhpmRoByGQbp26FJ66d4gI6iIFJRYRdQjCSiglsDIxNEgsK61tcc3WrWbm'+
'zZs3b95Hv1/Ye+jx0zNzM7ur1SoACAAAggAIyPLC7b9vn6nNzM3sfvv1d4RKkBUjAARBqRRAPIoQ'+
'lGVFWZRKuRePvrC7Vq1W5TJh9L7+F5esPR1bObpgotV09eq3fuq/aXmlo9WadGu1o1qr6/YTR/aW'+
'6rWqCkCns6qzbUw3isSnroiim6IoEoaXDAc9g7gnHUQGg0iW9IVQIKgFQLu9jnJkzfPTvHzR+MFZ'+
'c+s3aIyuGWRbtKZaxqoVtfqYKE6EMERQAYJOpyOKev6by3XXZgYf/UZeKOOzRsNI3OsbDWPDpC8d'+
'xkIoQQ2g3Z6jHJlqT+o8d4+1x1ZlD683Pju0kK6qNzdbM15VH6vrxSm6BCoEkCRD/SjW6Xb0JnL/'+
'biU5cV2ZJyrpZ07+uN+X1/fpR/8o0r4AgkoANBpTmpMz2u15reY69Wd2aizWNPI7bZi5YZinNs1u'+
'c/LaAdvn31KtFAJqAdDr9EXREH3f3/jLqSsXlI+k0u9+kWaZDdNbbZu/Xy/pe+mr97z21H4BNSEI'+
'mJya182Gfohjf6R1WZF6dPsReVnIi1yhtNxZsmPTA6J04NkP9tgRnlaDsiydX/rdpRs/azZbkiSR'+
'ZKm8LCyu/mpUZLJiZJSPdIc9Ozc/KBrFzg7eVQuIs76VfGR8rGmi0ZYMU0mWyPLMHZMLsiKXl4Wb'+
'nT9NN+ddXPrG5eUr7u0eUCMIoaJl0iDExvOGNaEpzhLHz70iLVJJlrp7drtddz3mwuLXzi+e8+rB'+
'Ez4+9qlaluXyPLdxeqeNMwQQ7NryJAghgMPH7hMqDZeXL3vj8Ic2Ti3I8k+EfYee+Hzd3Oyear2G'+
'IAACAOBM67i0LD3UP2RCS5blVm6tnPofTwlmPORvTlwAAAAASUVORK5CYII=',
};
// Header
let header = (function() {
style.register('\
#ks_fasnail_header {\
margin-left : 4px;\
margin-right : 4px;\
overflow : auto;\
}\
#ks_fasnail_user_name {\
font-weight : bold;\
margin : 4px;\
}\
#ks_fasnail_user_icon {\
border : 1px solid #828790;\
width : 46px;\
height : 46px;\
margin-left : 4px;\
margin-right : 4px;\
}\
#ks_fasnail_user_message {\
background-color: white;\
padding : 4px;\
height : 100px;\
margin : 0 4px 4px 4px;\
border : 1px solid #828790;\
overflow : auto;\
}\
#ks_fasnail_user_message .name {\
color : #3B5998;\
margin-left : 10px;\
}\
#ks_fasnail_user_message .description {\
color : #505050;\
margin-left : 10px;\
}\
#ks_fasnail_user_picture {\
border : 1px solid #828790;\
margin-left : 4px;\
margin-right : 4px;\
}\
');
let container = document.getElementById("ks_fasnail_header");
if (container) {
container.parentNode.removeChild(container);
container = null;
}
let owner = document.getElementById("keysnail-completion-list");
if (!owner) return null;
if (!container) {
let containerXML = '\
<vbox id="ks_fasnail_header">\
<hbox flex="1">\
<description id="ks_fasnail_user_name" />\
</hbox>\
<hbox flex="1">\
<vbox>\
<image id="ks_fasnail_user_icon" />\
</vbox>\
<vbox id="ks_fasnail_user_message" flex="1">\
<description />\
</vbox>\
<vbox valign="top">\
<image id="ks_fasnail_user_picture" />\
</vbox>\
</hbox>\
</vbox>';
container = util.xmlToDom(containerXML);
owner.parentNode.insertBefore(container, owner);
container = document.getElementById("ks_fasnail_header");
}
hide();
let elems = {
userName: document.getElementById("ks_fasnail_user_name"),
userIcon: document.getElementById("ks_fasnail_user_icon"),
message: document.getElementById("ks_fasnail_user_message"),
picture: document.getElementById("ks_fasnail_user_picture")
};
function showMessage(message, className) {
if (!message) return;
let messages = message.split('\n');
for (let [, val] in Iterator(messages)) {
let box = document.createElement('vbox');
if (className)
box.setAttribute('class', className);
box.appendChild(document.createTextNode(val));
elems.message.appendChild(box);
}
}
const PICTURE_SIZE = { width: 100, height: 100 };
let imageCache;
let imageOnLoad = function() {
imageCache.removeEventListener('load', arguments.callee, false);
let size = { width: PICTURE_SIZE.width, height: PICTURE_SIZE.height };
let orgSize = { width: imageCache.width, height: imageCache.height };
if (orgSize.width <= PICTURE_SIZE.width && orgSize.height <= PICTURE_SIZE.height) {
size = orgSize;
} else {
size.width = PICTURE_SIZE.width;
size.height = orgSize.height / (orgSize.width / size.width);
if (size.height > PICTURE_SIZE.height) {
size.width = size.width / (size.height / PICTURE_SIZE.height);
size.height = PICTURE_SIZE.height;
}
}
elems.picture.setAttribute('height', size.height);
elems.picture.setAttribute('width', size.width);
elems.picture.setAttribute('src', imageCache.src);
elems.picture.setAttribute('hidden', false);
imageCache = null;
};
function loadPicture(src) {
imageCache = new Image();
imageCache.src = src;
imageCache.addEventListener('load', imageOnLoad, false);
}
function show(item) {
clear(elems.message);
clear(elems.userName);
showMessage(item.message || item.story || item.caption);
if (item.name)
showMessage(item.name, 'name');
if (item.description)
showMessage(item.description, 'description');
elems.userIcon.setAttribute('src', (item.from) ? api.iconFromId(item.from.id) : '');
elems.userName.appendChild(document.createTextNode((item.from) ? item.from.name : '???'));
elems.picture.setAttribute('hidden', true);
if (imageCache)
imageCache.removeEventListener('load', imageOnLoad, false);
if (item.picture)
loadPicture(item.picture);
container.setAttribute('hidden', false);
}
function clear(elem) {
while (elem.hasChildNodes())
elem.removeChild(elem.firstChild);
}
function hide() {
if (imageCache)
imageCache.removeEventListener('load', imageOnLoad, false);
container.setAttribute('hidden', true);
}
return {
show: show,
hide: hide,
}
})();
// Pref
let settings = {
PREF_TOKEN: 'extensions.keysnail.plugins.fasnail.token',
get: function(){
return util.getUnicharPref(settings.PREF_TOKEN, "");
},
set: function(str){
util.setUnicharPref(settings.PREF_TOKEN, str);
}
};
// API
let api = (function() {
const GRAPH_API_URL = 'https://graph.facebook.com/';
share.fasnail.accessToken = settings.get();
function refreshAccessToken() {
const CLIENT_ID = '182780491804806';
const PERMISSIONS = [
'offline_access',
'publish_stream',
'read_stream',
'user_status',
'friends_status',
'user_groups',
'user_checkins',
'friends_checkins',
'publish_checkins',
'read_mailbox',
];
const redirectURL = 'https://www.facebook.com/connect/login_success.html';
let auth_url = 'https://www.facebook.com/dialog/oauth?client_id=' + CLIENT_ID
+ '&redirect_uri=' + redirectURL
+ "&scope=" + PERMISSIONS.join(',')
+ "&response_type=token";
let tab = gBrowser.loadOneTab(auth_url, null, null, null, false);
var browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("DOMContentLoaded", function loadListener(ev) {
let rootWin = browser.contentWindow;
let doc = ev.target;
if (doc !== rootWin.document) return; // only for main window
let docURL = doc.location.href;
try {
if (docURL.indexOf(redirectURL) != 0)
throw 'not url';
let token = docURL.match(/access_token=([^&]+)($|&)/)[1];
display.notify('facebook authorization success.');
settings.set(token);
share.fasnail.accessToken = token;
gBrowser.removeTab(tab);
display.notify('Authorized.');
}
catch(e)
{
display.notify('Failed to get access token.');
}
}, true);
}
function requestPost(endpoint, params, onSuccess, onError) {
let url = GRAPH_API_URL + endpoint;
for (let i in params) {
if (params[i])
params[i] = encodeURIComponent(params[i]);
else
delete params[i];
}
params['access_token'] = share.fasnail.accessToken;
util.httpPost(url, params, function(xhr) {
if (xhr.status == 200) {
if (onSuccess) onSuccess(JSON.parse(xhr.responseText));
} else {
if (onError) onError(JSON.parse(xhr.responseText));
}
});
}
function requestGet(endpoint, params, onSuccess, onError) {
let url = GRAPH_API_URL + endpoint;
params['locale'] = 'ja_JP';
for (let i in params) {
if (params[i])
params[i] = encodeURIComponent(params[i]);
else
delete params[i];
}
params['access_token'] = share.fasnail.accessToken;
url += '?' + util.paramsToString(params)
util.httpGet(url, false, function(xhr) {
if (xhr.status == 200) {
if (onSuccess) onSuccess(JSON.parse(xhr.responseText));
} else {
if (onError) onError(JSON.parse(xhr.responseText));
}
});
}
function requestDelete(endpoint, params, onSuccess, onError) {
let url = GRAPH_API_URL + endpoint;
for (let i in params) {
if (params[i])
params[i] = encodeURIComponent(params[i]);
else
delete params[i];
}
params['method'] = 'delete';
params['access_token'] = share.fasnail.accessToken;
util.httpPost(url, params, function(xhr) {
if (xhr.status == 200) {
if (onSuccess) onSuccess(JSON.parse(xhr.responseText));
} else {
if (onError) onError(JSON.parse(xhr.responseText));
}
});
}
function iconFromId(id) {
return GRAPH_API_URL + id + '/picture/';
}
return {
get isSavedAccessToken() { return ((share.fasnail.accessToken) ? true : false) },
iconFromId: iconFromId,
requestPost: requestPost,
requestGet: requestGet,
requestDelete: requestDelete,
refreshAccessToken: refreshAccessToken,
};
})();
// facebook function
let facebook = (function() {
function getWall(id, type, callback) {
display.echoStatusBar('Now loading...');
api.requestGet((id ? id : 'me') + '/' + (type ? type : 'feed'), {},
function(res) { if (callback) callback(res); },
function(res) { display.echoStatusBar('Request failed.'); if (callback) callback(res); }
);
}
function getOnce(id, callback) {
display.echoStatusBar('Now loading...');
api.requestGet(id, {},
function(res) { if (callback) callback(res); },
function(res) { display.echoStatusBar('Request failed.'); if (callback) callback(res); }
);
}
function getFriends(callback) {
display.echoStatusBar('Now loading...');
api.requestGet('me/friends', {},
function(res) { if (callback) callback(res); },
function(res) { display.echoStatusBar('Request failed.'); if (callback) callback(res); }
);
}
function postToWall(to, message, link, photo, callback) {
let endpoint = (to ? to : 'me') + "/feed";
let param = {
message: message,
link: link,
photo: photo,
};
display.echoStatusBar('Now posting...');
api.requestPost(endpoint, param,
function(res) { display.echoStatusBar('Post done.'); if (callback) callback(res); },
function(res) { display.echoStatusBar('Post failed.'); if (callback) callback(res); }
);
}
function deletePost(id, callback) {
display.echoStatusBar('Now posting...');
api.requestDelete(id, {},
function(res) { display.echoStatusBar('Post done.'); if (callback) callback(res); },
function(res) { display.echoStatusBar('Post failed.'); if (callback) callback(res); }
);
}
function like(id, callback) {
display.echoStatusBar('Now posting...');
api.requestPost(id + "/likes", {},
function(res) { display.echoStatusBar('Post done.'); if (callback) callback(res); },
function(res) { display.echoStatusBar('Post failed.'); if (callback) callback(res); }
);
}
function unLike(id, callback) {
display.echoStatusBar('Now posting...');
api.requestDelete(id + "/likes", {},
function(res) { display.echoStatusBar('Post done.'); if (callback) callback(res); },
function(res) { display.echoStatusBar('Post failed.'); if (callback) callback(res); }
);
}
function postComment(id, message, callback) {
display.echoStatusBar('Now posting...');
api.requestPost(id + "/comments", { message: message },
function(res) { display.echoStatusBar('Post done.'); if (callback) callback(res); },
function(res) { display.echoStatusBar('Post failed.'); if (callback) callback(res); }
);
}
function getInbox(callback) {
display.echoStatusBar('Now loading...');
api.requestGet('me/inbox', {},
function(res) { if (callback) callback(res); },
function(res) { display.echoStatusBar('Request failed.'); if (callback) callback(res); }
);
}
function formatTime(fbDate){
let arrDateTime = fbDate.split("T");
let arrDateCode = arrDateTime[0].split("-");
let strTimeCode = arrDateTime[1].substring(0, arrDateTime[1].indexOf("+"));
let arrTimeCode = strTimeCode.split(":");
let valid_date = new Date()
valid_date.setUTCFullYear(arrDateCode[0]);
valid_date.setUTCMonth(arrDateCode[1] - 1);
valid_date.setUTCDate(arrDateCode[2]);
valid_date.setUTCHours(arrTimeCode[0]);
valid_date.setUTCMinutes(arrTimeCode[1]);
valid_date.setUTCSeconds(arrTimeCode[2]);
return getElapsedTimeString(new Date() - valid_date);
}
function getElapsedTimeString(aMillisec) {
function format(num, str) {
return Math.floor(num) + " " + str;
}
var sec = aMillisec / 1000;
if (sec < 1.0)
return M({ja: "ついさっき", en: "just now"});
var min = sec / 60;
if (min < 1.0)
return format(sec, M({ja: "秒前", en: "seconds ago"}));
var hour = min / 60;
if (hour < 1.0)
return format(min, M({ja: "分前", en: "minutes ago"}));
var date = hour / 24;
if (date < 1.0)
return format(hour, M({ja: "時間前", en: "hours ago"}));
return format(date, M({ja: "日前", en: "days ago"}));
}
function getLinks(message) {
let strs = [message.message || '', message.description || ''].join(' ');
let urls = Array.slice(strs.match(/(?:(?:http|ftp)s?\:\/\/|www\.)[^\s]+/g) || [])
.map(function (url) url.indexOf("www") ? url : "http://" + url);
urls.push(message.link);
if (message.object_id)
urls.push('http://www.facebook.com/' + message.object_id);
let temp = {};
for (let [, val] in Iterator(urls)) {
if (val)
temp[val] = true;
}
urls = [];
for (let url in temp) {
urls.push(url);
}
return urls;
}
return {
getWall: getWall,
getOnce: getOnce,
getFriends: getFriends,
postToWall: postToWall,
deletePost: deletePost,
like: like,
unLike: unLike,
postComment: postComment,
getInbox: getInbox,
formatTime: formatTime,
getLinks: getLinks,
}
})();
function postText(to, callback) {
prompt.read(
'Post :',
function(str){
if (str != null)
facebook.postToWall(to, str, null, null, callback);
else
if (callback) callback();
}
);
}
function postLink(post_url, to, callback) {
prompt.read(
'Post link (' + post_url.split('/')[2] + ') :',
function(str){
if (str != null)
facebook.postToWall(to, str, post_url, null, callback);
else
if (callback) callback();
}
);
}
function postPhoto(post_url, image_url, to, callback) {
prompt.read(
'Post photo (' + post_url.split('/')[2] + ') :',
function(str){
if (str != null)
facebook.postToWall(to, str, post_url, image_url, callback);
else
if (callback) callback();
}
);
}
function postComment(id, callback) {
prompt.read(
'Post :',
function(str){
if (str != null)
facebook.postComment(id, str, callback);
else
if (callback) callback();
}
);
}
function showInbox() {
let threads = {}
facebook.getInbox(function(res) {
if (res.data) {
threads = res.data;
showThreads(0);
}
});
function showThreads(initialIndex) {
let collection = threads.map(function(thread) {
let from = (thread.from) ? thread.from : ((thread.to.data[1]) ? thread.to.data[1] : null);
return [
(from) ? api.iconFromId(from.id) : null,
(from) ? from.name : '',
api.iconFromId(thread.to.data[0].id),
thread.to.data[0].name,
thread.message,
facebook.formatTime(thread.created_time || thread.updated_time),
thread.unread.toString(),
thread.unseen.toString(),
];
});
prompt.selector({
message : 'Threads :',
initialIndex: initialIndex,
collection : collection,
header : ['From', 'To', 'Message', 'Date', 'Unread', 'Unseen'],
flags : [ICON|IGNORE, 0, ICON|IGNORE, 0, 0, 0, 0],
width : [15, 15, 50, 10, 5, 5],
beforeSelection : function (arg) header.show(threads[arg.i]),
onFinish : header.hide,
keymap : pOptions['keymap'],
actions : [
[ function(index) {
gPrompt.forced = true;
gPrompt.close();
showComment(index);
},
'Show comment', 'show-comments' ],
[ function(index) {
facebook.getLinks(threads[index]).forEach(function(url)
gBrowser.loadOneTab(url, null, null, null, false));
},
'Open link url', 'open-url,c' ],
/*
[ function() {
comment(threads[index].id, function() display.echoStatusBar('Post done.'));
},
'Post comment', 'post-comment' ],
*/
]
});
}
function showComment(threadIndex) {
let collection = threads[threadIndex].comments.data.map(function(comment) {
return [
api.iconFromId(comment.from.id),
comment.from.name,
comment.message,
facebook.formatTime(comment.created_time),
];
});
header.show(threads[threadIndex]);
prompt.selector({
message : 'Comments :',
initialIndex: collection.length - 1,
collection : collection,
header : ['User', 'Message', 'Date'],
flags : [ICON|IGNORE, 0, 0, 0],
width : [15, 75, 10],
onFinish : header.hide,
keymap : pOptions['keymap'],
actions : [
[ function(index) {
facebook.getLinks(threads[threadIndex].comments.data[index]).forEach(function(url)
gBrowser.loadOneTab(url, null, null, null, false));
},
'Open link url', 'open-url,c' ],
/*
[ function() {
postComment(threads[threadIndex].id);
},
'Post comment', 'post-comment' ],
*/
]
});
}
}
function showWall(type, id) {
let feeds = {}
facebook.getWall(id, type, function(res) {
if (res.data) {
feeds = res.data;
showFeeds(0);
}
});
function updateFeed(index, callback) {
facebook.getOnce(feeds[index].id, function(res) {
feeds[index] = res;
if (callback) callback(res);
});
}
function showFeeds(initialIndex) {
let postAction = false;
prompt.selector({
message : 'Feed :',
initialIndex: initialIndex,
collection : makeFeedsCollection(),
header : ['User', 'Message', 'Date', 'Like', 'Comment'],
flags : [ICON|IGNORE, 0, ICON|IGNORE, 0, 0, 0, 0],
width : [15, 64, 10, 5, 5],
beforeSelection : function (arg) header.show(feeds[arg.i]),
onFinish : header.hide,
keymap : pOptions['keymap'],
actions : [
[ function(index) {
gBrowser.loadOneTab('http://www.facebook.com/profile.php?id=' + feeds[index].from.id, null, null, null, false);
},
'Open selected user on facebook', 'open-facebook,c' ],
[ function(index, rows) {
facebook.like(feeds[index].id, function(res) {
if (res)
updateFeed(index, function() {
rows[index] = feedToSelectorRow(feeds[index]);
prompt.refresh(index);
});
});
},
'Like', 'like,c' ],
[ function(index, rows) {
facebook.unLike(feeds[index].id, function(res) {
if (res)
updateFeed(index, function() {
rows[index] = feedToSelectorRow(feeds[index]);
prompt.refresh(index);
});
});
},
'Un like', 'unlike,c' ],
[ function(index) {
if (feeds[index].likes && feeds[index].likes.count > 0) {
updateFeed(index, function() {
gPrompt.forced = true;
gPrompt.close();
showLikes(index);
});
}
},
'Show likes', 'show-likes,c' ],
[ function(index, rows) {
facebook.deletePost(feeds[index].id, function(res) {
if (res) {
feeds.splice(index, 1);
rows.splice(index, 1);
prompt.refresh(index);
}
});
},
'Delete', 'delete,c' ],
[ function(index, rows) {
postAction = true;
postComment(feeds[index].id, function(res) {
if (res)
updateFeed(index, function() {
showFeeds(index);
});
});
},
'Post comment', 'post-comment' ],
[ function(index) {
if (feeds[index].comments && feeds[index].comments.data.length > 0) {
updateFeed(index, function() {
gPrompt.forced = true;
gPrompt.close();
showComment(index);
});
}
},
'Show comments', 'show-comments,c' ],
[ function(index) {
facebook.getLinks(feeds[index]).forEach(function(url)
gBrowser.loadOneTab(url, null, null, null, false));
},
'Open link url', 'open-url,c' ],
[ function(index) {
postText(id);
},
'Post text', 'post-text' ],
[ function(index) {
postLink(content.location.href, id);
},
'Post this page', 'post-this-page' ],
[ function(index) {
showWall('feed', feeds[index].from.id);
},
'Show selected user\'s wall', 'show-user-wall' ],
]
});
function feedToSelectorRow(item) {
return [
api.iconFromId(item.from.id),
item.from.name,
item.icon || STATUS_ICONS[item.type],
(item.message || item.story || item.caption || '') +
(item.name ? (' ' + item.name) : '') + (item.description ? (' ' + item.description) : ''),
facebook.formatTime(item.created_time),
item.likes ? item.likes.count.toString() : '0',
item.comments ? item.comments.data.length.toString() : '0'
];
}
function makeFeedsCollection() {
return feeds.map(feedToSelectorRow);
}
}
function showComment(feedIndex, initialIndex) {
let feed = feeds[feedIndex];
let postAction = false;
header.show(feeds[feedIndex]);
prompt.selector({
message : 'Comments :',
initialIndex: initialIndex,
collection : makeCommentCollection(),
header : ['User', 'Message', 'Date', 'Like'],
flags : [ICON|IGNORE, 0, 0, 0],
width : [15, 70, 10, 5],
beforeSelection : function (arg) header.show(feed.comments.data[arg.i]),
onFinish : function() {
header.hide();
if (!postAction)
setTimeout(function() { showFeeds(feedIndex) }, 1);
},
keymap : pOptions['keymap'],
actions : [
[ function(index) {
gBrowser.loadOneTab('http://www.facebook.com/profile.php?id=' +
feed.comments.data[index].from.id, null, null, null, false);
},
'Open selected user on facebook', 'open-facebook,c' ],
[ function(index) {
postAction = true;
postComment(feed.id, function(res) {
if (res)
updateFeed(feedIndex, function(newFeed) {
feed = newFeed;
showComment(feedIndex);
});
});
},
'Post comment', 'post-comment' ],
[ function(index, rows) {
facebook.like(feed.comments.data[index].id, function(res) {
if (res)
updateFeed(feedIndex, function(newFeed) {
feed = newFeed;
rows[index] = commentToSelectorRow(feed.comments.data[index]);
prompt.refresh(index);
});
});
},
'Like', 'like,c' ],
[ function(index, rows) {
facebook.unLike(feed.comments.data[index].id, function(res) {
if (res)
updateFeed(feedIndex, function(newFeed) {
feed = newFeed;
rows[index] = commentToSelectorRow(feed.comments.data[index]);
prompt.refresh(index);
});
});
},
'Un like', 'unlike,c' ],
[ function(index, rows) {
facebook.deletePost(feeds[index].id, function(res) {
if (res) {
feeds.splice(index, 1);
rows.splice(index, 1);
prompt.refresh();
}
});
},
'Delete', 'delete,c' ],
[ function(index) {
facebook.getLinks(feed.comments.data[index]).forEach(function(url)
gBrowser.loadOneTab(url, null, null, null, false));
},
'Open link url', 'open-url,c' ],
[ function(index) {
showWall('feed', feed.comments.data[index].from.id);
},
'Show selected user\'s wall', 'show-user-wall' ],
]
});
function commentToSelectorRow(item) {
return [
api.iconFromId(item.from.id),
item.from.name,
item.message,
facebook.formatTime(item.created_time),
item.likes ? item.likes.toString() : '0',
];
}
function makeCommentCollection() {
return feed.comments.data.map(commentToSelectorRow);
}
}
function showLikes(feedIndex) {
let feed = feeds[feedIndex];
header.show(feeds[feedIndex]);
prompt.selector({
message : 'Comments :',
collection : makeLikesCollection(),
header : ['User'],
flags : [ICON|IGNORE, 0],
onFinish : function() {
setTimeout(function() showFeeds(feedIndex), 1);
},
keymap : pOptions['keymap'],
actions : [
[ function(index) {
gBrowser.loadOneTab('http://www.facebook.com/profile.php?id=' + feed.comments.data[index].from.id, null, null, null, false);
},
'Open selected user on facebook', 'open-facebook,c' ],
[ function(index) {
showWall('feed', feed.comments.data[index].from.id);
},
'Show selected user\'s wall', 'show-user-wall' ],
]
});
function likeToSelectorRow(item) {
return [
api.iconFromId(item.id),
item.name,
];
}
function makeLikesCollection() {
return feed.likes.data.map(likeToSelectorRow);
}
}
}
function showFriends(actions) {
actions.push([
function(index, rows) {
gBrowser.loadOneTab('http://www.facebook.com/profile.php?id=' + rows[index][2], null, null, null, false);
},
'Open selected user on facebook', 'open-facebook'
]);
facebook.getFriends(function(res) {
if (res.data) {
let friends = res.data;
let collection = friends.map(function(friend) [ api.iconFromId(friend.id), friend.name, friend.id ]);
prompt.selector({
message : 'Select friend :',
collection : collection,
flags : [ICON|IGNORE, 0, HIDDEN|IGNORE],
actions : actions
});
}
});
}
function extHook(fn) {
if (!api.isSavedAccessToken)
api.refreshAccessToken();
else
fn()
}
let self = {
showWall: function(type) {
extHook(function() showWall(type));
},
showFriendWall: function() {
extHook(function() {
showFriends([
[ function(index, rows) showWall('feed', rows[index][2]), 'Show friend wall', 'show-wall' ],
])
});
},
postText: function() {
extHook(function() postText('me'))
},
postLink: function(link_url) {
extHook(function() postLink(link_url, 'me'))
},
postPhoto: function(link_url, image_url) {
extHook(function() postPhoto(link_url, image_url, 'me'))
},
postToFriendWall: function() {
extHook(function() {
showFriends([
[ function(index, rows) postText('feed', rows[index][2]), 'Post text to this friend wall', 'post-text' ],
[ function(index, rows) postText('feed', rows[index][2]), 'Post this page to this friend wall', 'post-this-page' ],
]);
});
},
showInbox: function()
extHook(showInbox),
reAuth: function(){
extHook(function() {
settings.set('');
delete share.fasnail.accessToken;
api.refreshAccessToken();
});
}
};
return self;
})();
plugins.fasnail = fasnail;
// Add Hok
hook.addToHook('PluginLoaded', function () {
if (!plugins.hok)
return;
plugins.hok.addActions([
[pOptions["hok_post_photo"],
M({ja: "画像を facebook に投稿", en: "Photo post to facebook"}),
function (elem) {
if (elem.src)
fasnail.postPhoto(content.location.href, elem.src);
}, false, false, 'img']
]);
});
// Add ext
plugins.withProvides(function (provide) {
provide("facebook-reauth",
function (ev, arg) {
fasnail.reAuth(arg);
},
M({en:'facebook - Reauthorize', ja:'facebook - 再認証'}));
provide("facebook-show-my-wall",
function (ev, arg) {
fasnail.showWall('feed');
},
M({en:'facebook - Show my wall', ja:'facebook - 自分のウォール'}));
provide("facebook-show-news-feed",
function (ev, arg) {
fasnail.showWall('home');
},
M({en:'facebook - Show news feed', ja:'facebook - ニュースフィード'}));
provide("facebook-show-friends-wall",
function (ev, arg) {
fasnail.showFriendWall();
},
M({en:'facebook - Show friend wall', ja:'facebook - 友達のウォール'}));
provide("facebook-post-text",
function (ev, arg) {
fasnail.postText();
},
M({en:'facebook - Post text to my wall', ja:'facebook - 自分のウォールにポスト'}));
provide("facebook-post-to-friend-wall",
function (ev, arg) {
fasnail.postToFriendWall();
},
M({en:'facebook - Post to friend wall', ja:'facebook - 友達のウォールにポスト'}));
provide("facebook-post-this-page",
function (ev, arg) {
fasnail.postLink(content.location.href);
},
M({en:'facebook - Post this page to my wall', ja:'facebook - 自分のウォールに表示中のページをポスト'}));
provide("facebook-show-inbox",
function (ev, arg) {
fasnail.showInbox();
},
M({en:'facebook - Show message inbox', ja:'facebook - メッセージを表示'}));
}, PLUGIN_INFO);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment