Skip to content

Instantly share code, notes, and snippets.

@YungSang
Last active December 26, 2015 02:19
Show Gist options
  • Save YungSang/7078179 to your computer and use it in GitHub Desktop.
Save YungSang/7078179 to your computer and use it in GitHub Desktop.
[Deprecated] Taberareloo 用パッチ: HatenaBlog model https://github.com/Constellation/taberareloo/pull/236 より。 Taberareloo v3.0.5 で対応されました。
// ==Taberareloo==
// {
// "name" : "HatenaBlog Model"
// , "description" : "Post to hatenablog.com"
// , "include" : ["background"]
// , "version" : "0.3.0"
// , "downloadURL" : "https://gist.github.com/YungSang/7078179/raw/patch.model.hatenablog.tbrl.js"
// }
// ==/Taberareloo==
(function () {
Models.register({
name : 'HatenaBlog',
ICON : 'http://hatenablog.com/images/favicon.ico',
LINK : 'http://hatenablog.com/',
LOGIN_URL : 'https://www.hatena.ne.jp/login',
CONFIG_DETAIL_URL: 'http://blog.hatena.ne.jp/my/config/detail',
ADMIN_TOP_URL: 'http://blog.hatena.ne.jp/',
BLOG_ADMIN_URL: undefined, // 個別のブログのインスタンスで定義される
is_initialized : false,
initialize : function() {
var self = this;
if (this.is_initialized) return succeed();
return this.getBlogs().addCallback(function (blogs) {
self.is_initialized = true;
return blogs.map(function(blog) {
var model = update({}, Models.HatenaBlog);
model.check = model._check;
delete model.initialize;
delete model._check;
model.LINK = blog.url;
model.name = model.name + ' - ' + blog.title;
model.ICON = blog.icon_url;
model.BLOG_ADMIN_URL = blog.admin_url;
Models.register(model);
return model;
});
});
},
getBlogs : function(){
var self = this;
return Models.Hatena.getToken().addCallback(function(set) {
return request(self.ADMIN_TOP_URL, { responseType: 'document' }).addCallback(function(res){
var doc = res.response;
var sidebarElements = $A(doc.querySelectorAll('.sidebar-index .admin-menu-blogpath'));
var blogBoxElements = $A(doc.querySelectorAll('.main-box .myblog-box'));
return $A(sidebarElements).map(function(sidebarElement){
var blogBoxElement = blogBoxElements.shift();
return {
url: blogBoxElement.querySelector('.blog-host a').href,
title: sidebarElement.textContent.replace(/^\s*/, '').replace(/\s*$/, ''),
admin_url: sidebarElement.querySelector('a').href,
icon_url: sidebarElement.querySelector('img').src
};
});
});
});
},
getUserName: function(){
return Models.Hatena.getToken().addCallback(function(set) {
return set['name'];
});
},
getApiKey : function() {
var model = Models.HatenaBlog;
if (model.token) {
return succeed(model.token);
} else {
return Models.Hatena.getToken().addCallback(function() {
return request(model.CONFIG_DETAIL_URL, { responseType: 'document' }).addCallback(function(res){
var doc = res.response;
var tokenElement = doc.querySelector('.api-key');
if (!tokenElement) {
throw new Error('HatenaBlog#getToken: failed to find ApiKey');
}
model.token = tokenElement.textContent;
return model.token;
}).addErrback(function(e) {
model.token = undefined;
throw new Error('HatenaBlog#getToken: ' +
(e.message.hasOwnProperty('status') ? '\n' + ('HTTP Status Code ' + e.message.status).indent(4) : '\n' + e.message.indent(4)));
});
});
}
},
// ここでcheckを定義すると,HatenaBlog自体が投稿可能になってしまう.
// Models.HatenaBlog自体は投稿可能ではなく,ユーザーの持っている個別のブログに投稿できる.
// ここではなく,getBlogsしたあとにcheckを定義しています.
_check : function(ps) {
return /regular|quote|link|video/.test(ps.type) || (ps.type === 'photo' && !ps.file);
},
post : function(ps){
var self = this;
var template;
if (ps.type === 'regular') {
template = '<p>%body%</p>';
} else if (ps.type === 'quote') {
template = '<blockquote>' +
'%body%' +
'<p><cite><a href="%pageUrl%">%page%</a></cite></p>' +
'</blockquote>';
} else if (ps.type === 'photo') {
template = '<p><a href="%pageUrl%"><img src="%itemUrl%"></a></p>' +
'<p><cite><a href="%pageUrl%">%page%</a></cite></p>';
} else if (ps.type === 'link') {
template = '<p><a href="%itemUrl%">%item%</a></p>';
} else if (ps.type === 'video') {
template = '<p>%itemUrl%:embed</p>' +
'<p><a href="%itemUrl%">%item%</a></p>';
}
if (ps.description) {
template += '<p>%description%</p>';
}
var data = {
body : self.paragraph(ps.body),
description : self.paragraph(ps.description),
item : escapeHTML(ps.item || ''),
itemUrl : escapeHTML(ps.itemUrl || ''),
page : escapeHTML(ps.page || ''),
pageUrl : escapeHTML(ps.pageUrl || '')
};
var body = templateExtract(template, data);
return self.getUserName().addCallback(function(userName) {
self.getApiKey().addCallback(function(apiKey){
var xml = self.generateXML({
userName : escapeHTML(userName),
title : '',
body : escapeHTML(body),
isDraft : escapeHTML('false'),
categories : ps.tags
});
return request(self.postEndpoint(), {
method : 'post',
mode : 'raw',
sendContent : xml,
username : userName,
password : apiKey
});
});
});
},
paragraph: function(text) {
if (!text) return '';
return '<p>' + text.replace(/^\n*/, '').replace(/\n*$/, '').replace(/\n+/g, '</p><p>') + '</p>';
},
postEndpoint: function() {
var self = this;
return (self.BLOG_ADMIN_URL + 'atom/entry').replace(/^http:/, 'https:');
},
// @param data { userName, title, body, isDraft, categories }
generateXML: function(data) {
var categories = (data.categories || []).map(function(name) {
return '<category term="' + escapeHTML(name) + '" />';
}).join("");
var template = '<?xml version="1.0" encoding="utf-8"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom"' +
'xmlns:app="http://www.w3.org/2007/app">' +
'<title>%title%</title>' +
'<author><name>%userName%</name></author>' +
'<content type="text/plain">%body%</content>' +
categories +
'<app:control>' +
'<app:draft>%isDraft%</app:draft>' +
'</app:control>' +
'</entry>';
return templateExtract(template, data);
}
});
setTimeout(function() {
Models.HatenaBlog.initialize();
}, 1000);
})();
@YungSang
Copy link
Author

v0.2.0 で taberareloo/taberareloo#236 と同じ実装にしました。

@hitode909
Copy link

ADMIN_URL が2重の意味で使われている

たしかに!!!いま気付きました

@hitode909
Copy link

hitode909/taberareloo@5cb25d6 でADMIN_URLに再代入するの直しました

@YungSang
Copy link
Author

update({}, Models.HatenaBlog) しているので、実質問題無いわけですが、ちょっと気になったものですから。
対応ありがとうございます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment