Permalink
Browse files

can upload photo from local disk

  • Loading branch information...
1 parent 129aba9 commit 68136d4fc91fdd218a19c066abe87d0d7f0a11ce @arkxu committed Aug 9, 2012
View
@@ -1,3 +1,4 @@
+.DS_Store
lib-cov
*.seed
*.log
View
@@ -56,6 +56,22 @@ tumblr.post('/post', {type: 'text', title: 'tumblrwkstesting', body: '<h3>should
```
+### Upload a photo from local disk
+
+``` javascript
+// upload local photo can work but can not upload multiple photos in a single blog
+// most of the code for this are from ntumblr
+
+// in general, tumblr api sucks
+var photo = fs.readFileSync('./test/img/P1010486.jpg');
+
+tumblr.post('/post', {type: 'photo', data: [photo]}, function(json){
+ console.log(json);
+});
+
+```
+
+
## Tests
$ mocha
View
@@ -0,0 +1,78 @@
+// Generated by CoffeeScript 1.3.1
+(function() {
+ var CustomOAuth, OAuth, quote, replaceAfterEncode,
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+ OAuth = require('oauth').OAuth;
+
+ replaceAfterEncode = require('./encode-image').replaceAfterEncode;
+
+ quote = require('./escape-py').quote;
+
+ CustomOAuth = (function(_super) {
+
+ __extends(CustomOAuth, _super);
+
+ CustomOAuth.name = 'CustomOAuth';
+
+ function CustomOAuth() {
+ return CustomOAuth.__super__.constructor.apply(this, arguments);
+ }
+
+ CustomOAuth.prototype._createSignatureBase = function() {
+ var _remain, _signatureBase;
+ _signatureBase = CustomOAuth.__super__._createSignatureBase.apply(this, arguments);
+ if (/data%255B\d%255D/g.test(_signatureBase)) {
+ _remain = _signatureBase.split('%26').splice(1).join('%26');
+ _signatureBase = replaceAfterEncode(_signatureBase, this.originalBody);
+ return _signatureBase + "%26" + _remain;
+ } else {
+ return _signatureBase;
+ }
+ };
+
+ CustomOAuth.prototype._encodeData = function(toEncode) {
+ var result;
+ if ((!(toEncode != null)) || (toEncode === '')) {
+ return '';
+ } else {
+ if (/data(\:|%5B)/g.test(toEncode)) {
+ result = quote(toEncode.replace(/data( \:|%5B )/g, ''));
+ } else {
+ result = encodeURIComponent(toEncode);
+ }
+
+ return result.replace(/\!/g, "%21").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
+ }
+ };
+
+ CustomOAuth.prototype._createClient = function() {
+ var client, _write;
+ client = CustomOAuth.__super__._createClient.apply(this, arguments);
+ _write = client.write.bind(client);
+ client.write = function(chunk, encoding) {
+ var contentLength;
+ if (/data%3A/g.test(chunk)) {
+ chunk = replaceAfterEncode(chunk).replace("*", '%2A').replace("/", '%2F');
+ }
+ contentLength = 0;
+ if (Buffer.isBuffer(chunk) != null) {
+ contentLength = chunk.length;
+ } else {
+ contentLength = Buffer.byteLength(chunk);
+ }
+ this.setHeader("Content-Length", contentLength);
+ this.removeHeader("Connection");
+ return _write(chunk, encoding);
+ };
+ return client;
+ };
+
+ return CustomOAuth;
+
+ })(OAuth);
+
+ module.exports = CustomOAuth;
+
+}).call(this);
View
@@ -0,0 +1,42 @@
+// Generated by CoffeeScript 1.3.1
+(function() {
+ var doublequote, fs, qs, quote;
+
+ fs = require('fs');
+
+ qs = require('querystring');
+
+ quote = require('./escape-py').quote;
+
+ doublequote = require('./escape-py').doublequote;
+
+ module.exports.encodeToHex = function(buffer) {
+ return "data:" + (buffer.toString('binary'));
+ };
+
+ module.exports.replaceAfterEncode = function(str, originalBody) {
+ var pattern, _s;
+ if (originalBody == null) {
+ originalBody = null;
+ }
+ pattern = /data%3A([\w\!\'\(\)\*\-\._~%]+)/g;
+ if (originalBody != null) {
+ pattern = /data%255B(\d+)%255D%3Ddata%253A([\w\!\'\(\)\*\-\._~%]+)/g;
+ }
+ _s = str.replace(pattern, function(a, g1, g2) {
+ var data, index;
+ if (!isNaN(g1)) {
+ index = g1;
+ data = originalBody["data[" + index + "]"].replace('data:', '');
+ g1 = g2;
+ g1 = ("data%5B" + index + "%5D%3D") + doublequote(data);
+ } else {
+ g1 = quote(decodeURIComponent(g1));
+ g1 = g1.replace(/%20/g, "+");
+ }
+ return g1;
+ });
+ return _s;
+ };
+
+}).call(this);
View
@@ -0,0 +1,60 @@
+// Generated by CoffeeScript 1.3.1
+
+/*
+Python's urllib.quote
+
+escape does not escape:
+`* + - . / @ _`
+
+encodeURIComponent does not escape:
+
+! ' ( ) * - . _ ~
+*/
+
+
+(function() {
+ var doublequote, quote, replaceMismatch, unquote;
+
+ quote = function(str) {
+ str = escape(str).replace(/\%21/g, '!').replace(/\%27/g, '\'').replace(/\%28/g, '\(').replace(/\%29/g, '\)').replace(/\%7E/g, '\~');
+ return str.replace(/\+/g, '%2B').replace(/\//g, '%2F').replace(/@/g, '%40').replace(/\s/g, '%2B');
+ };
+
+ replaceMismatch = function(str) {
+ return str.replace(/\!/g, "%21").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
+ };
+
+ doublequote = function(str) {
+ return replaceMismatch(quote(str)).replace(/%/g, '%25');
+ };
+
+ unquote = function(str) {
+ return unescape(str).replace(/\%21/g, '!').replace(/\%27/g, '\'').replace(/\%28/g, '\(').replace(/\%29/g, '\)').replace(/\%7E/g, '\~').replace(/\s/g, '%2B');
+ };
+
+ (function(name, definition) {
+ var global, old, theModule;
+ if (typeof define === "function") {
+ return define(definition);
+ } else if (typeof module !== "undefined" && module.exports) {
+ return module.exports = definition();
+ } else {
+ theModule = definition();
+ global = this;
+ old = global[name];
+ theModule.noConflict = function() {
+ global[name] = old;
+ return theModule;
+ };
+ return global[name] = theModule;
+ }
+ })("escapePy", function() {
+ return {
+ quote: quote,
+ doublequote: doublequote,
+ replaceMismatch: replaceMismatch,
+ unquote: unquote
+ };
+ });
+
+}).call(this);
View
@@ -1,5 +1,6 @@
var http = require('http'),
- OAuth = require('oauth').OAuth;
+ CustomOAuth = require('./custom-oauth.js'),
+ encodeToHex = require('./encode-image').encodeToHex;
var apiHost = 'api.tumblr.com';
var apiVersion = '/v2';
@@ -13,7 +14,7 @@ function tumblr(options, hostname){
this.hostname = hostname;
if(this.consumerKey && this.consumerSecret){
- this.oa = new OAuth('http://www.tumblr.com/oauth/request_token',
+ this.oa = new CustomOAuth('http://www.tumblr.com/oauth/request_token',
'http://www.tumblr.com/oauth/access_token',
this.consumerKey, this.consumerSecret, '1.0A',
null, 'HMAC-SHA1');
@@ -110,6 +111,22 @@ tumblr.prototype.post = function (url, params, callback){
var body = "";
+ if(params.data){
+ this.oa.originalBody = {};
+ if (Array.isArray(params.data)) {
+ var _ref = params.data;
+ for (var i = 0; i < _ref.length; i++) {
+ var d = _ref[i];
+ params["data[" + i + "]"] = encodeToHex(d);
+ this.oa.originalBody["data[" + i + "]"] = encodeToHex(d);
+ }
+ delete params.data;
+ } else {
+ params['data[0]'] = encodeToHex(params.data);
+ this.oa.originalBody["data[0]"] = encodeToHex(params.data);
+ delete params.data;
+ }
+ }
if (this._isUserAPI(url)){
var req = this.oa.post(apiUrl + url, this.accessToken, this.accessSecret, params);
}else{
@@ -126,7 +143,7 @@ tumblr.prototype.post = function (url, params, callback){
var json = JSON.parse(body);
if (callback) callback(json.response);
}else{
- throw new Error(body);
+ throw new Error(body);
}
});
});
View
@@ -24,5 +24,11 @@
"engines": {
"node": ">= 0.4.0"
},
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://www.opensource.org/licenses/MIT"
+ }
+ ],
"_id": "tumblrwks@0.0.4"
}
View
@@ -1,8 +1,7 @@
var Tumblr = require('../lib/tumblrwks.js');
var assert = require('assert');
-var tumblr = new Tumblr(
- {
+var tumblr = new Tumblr({
consumerKey: 'your consumer key',
consumerSecret: 'your consumer secret',
accessToken: 'access token',
@@ -136,7 +135,7 @@ describe('POST METHOD TESTS', function (){
});
it('post one text blog', function(done){
- tumblr.post('/post', {type: 'text', title: 'tumblrwkstesting', body: '<h3>should work!! </h3>'}, function(json){
+ tumblr.post('/post', {type: 'text', title: 'tumblrwkstesting', body: '<h3>should work!! 还有中文</h3>'}, function(json){
assert(json.id);
done();
});
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -1,11 +1,9 @@
var Tumblr = require('../lib/tumblrwks.js');
var assert = require('assert');
-var tumblr = new Tumblr(
- {
- consumerKey: 'Qf6HlZz8NCBwUcMSP6PS99b2kUCqzj2J4Aecs91U25hRabgkzB'
- }
-);
+var tumblr = new Tumblr({
+ consumerKey: 'Qf6HlZz8NCBwUcMSP6PS99b2kUCqzj2J4Aecs91U25hRabgkzB'
+});
describe('SIMPLE TESTS', function (){
it('should get blog info', function(done){
@@ -0,0 +1,41 @@
+var Tumblr = require('../lib/tumblrwks.js');
+var assert = require('assert');
+var fs = require('fs');
+var querystring = require("querystring");
+
+var tumblr = new Tumblr({
+ consumerKey: 'your consumer key',
+ consumerSecret: 'your consumer secret',
+ accessToken: 'access token',
+ accessSecret: 'access secret'
+ }, "arktest.tumblr.com"
+);
+
+describe('SAMPLE POST PHOTO', function (){
+ it('should post one photo blog get form flickr ', function(done){
+ tumblr.post('/post', {
+ type: 'photo',
+ caption: 'Flickr',
+ source: 'http://farm9.staticflickr.com/8294/7733962082_11a1834801.jpg'
+ }, function(json){
+ console.log(json);
+ done();
+ });
+ });
+
+ it('should post one photo from local fs ', function(done){
+ // upload local photo can work but can not upload multiple photos in a single blog
+ // most of the code for this are from ntumblr
+
+ // in general, tumblr api sucks
+ var photo = fs.readFileSync('./test/img/P1010486.jpg');
+
+ tumblr.post('/post', {
+ type: 'photo',
+ data: [photo]
+ }, function(json){
+ console.log(json);
+ done();
+ });
+ });
+});

0 comments on commit 68136d4

Please sign in to comment.