Last active
September 27, 2015 18:48
-
-
Save 958/1315917 to your computer and use it in GitHub Desktop.
[keysnail]facebook plugin
This file contains 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
// 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