Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add repost test cases;

  • Loading branch information...
commit 7e036e8b7a940d397d7b587948ed3196974614d6 1 parent 98c474e
@fengmk2 fengmk2 authored
View
2  .gitignore
@@ -1,3 +1,5 @@
.project
.settings
node_modules/
+lib-cov
+coverage.html
View
5 .npmignore
@@ -4,3 +4,8 @@ support/
.settings/
.project
mkdoc.sh
+Makefile
+gtap
+node_modules
+.travis.yml
+coverage.html
View
40 README.md
@@ -30,44 +30,52 @@ $ npm install weibo
## How to use
-### Browser
+### Browser: `Phonegap` or `Chrome extension`
-```javascript
-// Include the `weibo.js` javascript files:
+* require `jQuery`
-<script type="text/javascript" src="/weibo/weibo.js"></script>
+```javascript
+// Include the javascript files:
+
+<script src="lib/weibo/lib/eventproxy.js"></script>
+<script src="lib/weibo/lib/base64.js"></script>
+<script src="lib/weibo/lib/sha1.js"></script>
+<script src="lib/weibo/lib/utils.js"></script>
+<script src="lib/weibo/lib/oauth.js"></script>
+<script src="lib/weibo/lib/urllib.js"></script>
+<script src="lib/weibo/lib/tsina.js"></script>
+<script src="lib/weibo/lib/tapi.js"></script>
<script type="text/javascript">
-// load all the lib scripts with urlprefix where the `weibo` directory you put into
-weibo.load('/weibo/');
-
var tapi = weibo.TAPI;
var appkey = 'your appkey', secret = 'your app secret';
var oauth_callback_url = 'your callback url' || 'oob';
tapi.init('tsina', appkey, secret, oauth_callback_url);
-tapi.public_timeline({}, function (error, data, xhr) {
- if (error) {
+tapi.public_timeline({ user: { blogType: 'tsina' } }, function (err, statuses) {
+ if (err) {
console.error(error);
} else {
- console.log(data);
+ console.log(statuses);
}
});
-
</script>
```
### Server
```javascript
-var tapi = require('weibo').tapi;
+
+var tapi = require('weibo');
+
// change appkey to yours
var appkey = 'your appkey', secret = 'your app secret';
var oauth_callback_url = 'your callback url' || 'oob';
tapi.init('tsina', appkey, secret, oauth_callback_url);
-tapi.public_timeline({}, function (error, data, response) {
- if (error) {
- console.error(error);
+
+tapi.public_timeline({ user: { blogType: 'tsina' } }, function (err, statuses) {
+ if (err) {
+ console.error(err);
} else {
- console.log(data);
+ console.log(statuses);
}
});
```
View
0  testMiddleWare.js → examples/testMiddleWare.js
File renamed without changes
View
2  index.js
@@ -8,5 +8,5 @@
* Module dependencies.
*/
-var libpath = process.env.URLLIB_COV ? './lib-cov' : './lib';
+var libpath = process.env.WEIBO_COV ? './lib-cov' : './lib';
module.exports = require(libpath + '/tapi');
View
17 lib/oauth.js
@@ -168,17 +168,17 @@ OAuth.setProperties(OAuth, {
var parameters = message.parameters;
if (parameters instanceof Array) {
for (var p = 0; p < parameters.length; ++p) {
- if (parameters[p][0] === name) {
- if (value === undefined) {
- parameters.splice(p, 1);
- } else {
- parameters[p][1] = value;
- value = undefined;
- }
+ if (parameters[p][0] === name) {
+ if (value === undefined) {
+ parameters.splice(p, 1);
+ } else {
+ parameters[p][1] = value;
+ value = undefined;
}
+ }
}
if (value !== undefined) {
- parameters.push([name, value]);
+ parameters.push([name, value]);
}
} else {
parameters = OAuth.getParameterMap(parameters);
@@ -273,6 +273,7 @@ OAuth.setProperties(OAuth.SignatureMethod.prototype, {
sign: function sign(message) {
var baseString = OAuth.SignatureMethod.getBaseString(message);
var signature = this.getSignature(baseString);
+ // console.log(baseString, this.key, signature)
OAuth.setParameter(message, "oauth_signature", signature);
return signature; // just in case someone's interested
},
View
6 lib/sha1.js
@@ -32,17 +32,17 @@ var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s) {
- return binb2hex(core_sha1(str2binb(s),s.length * chrsz));
+ return binb2hex(core_sha1(str2binb(s), s.length * chrsz));
}
exports.hex_sha1 = hex_sha1;
function b64_sha1(s) {
- return binb2b64(core_sha1(str2binb(s),s.length * chrsz));
+ return binb2b64(core_sha1(str2binb(s), s.length * chrsz));
}
exports.b64_sha1 = b64_sha1;
function str_sha1(s) {
- return binb2str(core_sha1(str2binb(s),s.length * chrsz));
+ return binb2str(core_sha1(str2binb(s), s.length * chrsz));
}
exports.str_sha1 = str_sha1;
View
100 lib/tapi.js
@@ -1,12 +1,14 @@
(function () {
var TAPI = {};
-
+var utils;
var root = this; // window on browser
if (typeof module === 'undefined') {
root.weibo.TAPI = TAPI;
+ utils = root.weibo.utils;
} else {
module.exports = TAPI;
+ utils = require('./utils');
}
var TSinaAPI;
@@ -27,7 +29,7 @@ if (typeof require !== 'undefined') {
}
// 封装兼容所有微博的api,自动判断微博类型
-Object.extend(TAPI, {
+utils.extend(TAPI, {
TYPES: {
tsina: TSinaAPI,
@@ -95,8 +97,8 @@ Object.extend(TAPI, {
return this.api_dispatch(user).get_authorization_url(user, callback, context);
},
- /* 获取access token
- *
+ /**
+ * 获取access token
*/
get_access_token: function (user, callback, context) {
return this.api_dispatch(user).get_access_token(user, callback, context);
@@ -106,13 +108,13 @@ Object.extend(TAPI, {
* 验证用户是否已经开通微博服务。并返回用户信息和最新的一条微博
*/
verify_credentials: function (user, callback, context) {
- return this.api_dispatch(user).verify_credentials(user, callback, context);
+ return this.api_dispatch(user).verify_credentials(user, callback, context);
},
/* 获取API的访问频率限制。返回当前小时内还能访问的次数。
*/
- rate_limit_status: function (data, callback, context) {
- return this.api_dispatch(data).rate_limit_status(data, callback, context);
+ rate_limit_status: function (data, callback, context) {
+ return this.api_dispatch(data).rate_limit_status(data, callback, context);
},
// count, base_app: 0 all, 1 current app
@@ -122,8 +124,24 @@ Object.extend(TAPI, {
// since_id, max_id, count, page
// home_timeline in twitter
- friends_timeline: function(data, callback, context) {
- return this.api_dispatch(data).friends_timeline(data, callback, context);
+ friends_timeline: function (data, callback, context) {
+ var max_id = data.max_id;
+ return this.api_dispatch(data).friends_timeline(data, function (err, statuses) {
+ if (err || !max_id) {
+ return callback.call(context, err, statuses);
+ }
+ max_id = String(max_id);
+ // ignore the max_id status
+ var needs = [];
+ for (var i = 0, l = statuses.length; i < l; i++) {
+ var status = statuses[i];
+ if (String(status.id) === max_id) {
+ continue;
+ }
+ needs.push(status);
+ }
+ callback.call(context, null, needs);
+ }, this);
},
/*
@@ -145,7 +163,7 @@ Object.extend(TAPI, {
* count false int,默认值20,最大值200。 单页返回的记录条数。
* page false int,默认值1。 返回结果的页码。注意:有分页限制。
*/
- comments_timeline: function(data, callback, context) {
+ comments_timeline: function (data, callback, context) {
return this.api_dispatch(data).comments_timeline(data, callback, context);
},
@@ -156,7 +174,7 @@ Object.extend(TAPI, {
* count false int,默认值20,最大值200。 单页返回的记录条数。
* page false int,默认值1。 返回结果的页码。
*/
- repost_timeline: function(data, callback, context) {
+ repost_timeline: function (data, callback, context) {
return this.api_dispatch(data).repost_timeline(data, callback, context);
},
@@ -166,7 +184,7 @@ Object.extend(TAPI, {
* count false int,默认值20,最大值200。 单页返回的记录条数。
* page false int,默认值1。 返回结果的页码。注意:有分页限制。
*/
- mentions: function(data, callback, context) {
+ mentions: function (data, callback, context) {
return this.api_dispatch(data).mentions(data, callback, context);
},
@@ -179,47 +197,47 @@ Object.extend(TAPI, {
* cursor false int 用于分页请求,请求第1页cursor传-1,在返回的结果中会得到next_cursor字段,表示下一页的cursor。next_cursor为0表示已经到记录末尾。
* count false int,默认20,最大200 每页返回的最大记录数,最大不能超过200,默认为20。
*/
- friends: function(data, callback, context) {
+ friends: function (data, callback, context) {
return this.api_dispatch(data).friends(data, callback, context);
},
// 同friends
- followers: function(data, callback, context) {
+ followers: function (data, callback, context) {
return this.api_dispatch(data).followers(data, callback, context);
},
// page
- favorites: function(data, callback, context) {
+ favorites: function (data, callback, context) {
return this.api_dispatch(data).favorites(data, callback, context);
},
// id
- favorites_create: function(data, callback, context) {
+ favorites_create: function (data, callback, context) {
return this.api_dispatch(data).favorites_create(data, callback, context);
},
// id
- favorites_destroy: function(data, callback, context) {
+ favorites_destroy: function (data, callback, context) {
return this.api_dispatch(data).favorites_destroy(data, callback, context);
},
// ids: 要获取评论数和转发数的微博消息ID列表,用逗号隔开
- counts: function(data, callback, context) {
+ counts: function (data, callback, context) {
return this.api_dispatch(data).counts(data, callback, context);
},
// id
- user_show: function(data, callback, context) {
+ user_show: function (data, callback, context) {
return this.api_dispatch(data).user_show(data, callback, context);
},
// since_id, max_id, count, page
- direct_messages: function(data, callback, context) {
+ direct_messages: function (data, callback, context) {
return this.api_dispatch(data).direct_messages(data, callback, context);
},
// id
- destroy_msg: function(data, callback, context) {
+ destroy_msg: function (data, callback, context) {
return this.api_dispatch(data).destroy_msg(data, callback, context);
},
@@ -232,7 +250,7 @@ Object.extend(TAPI, {
* 私信的接收方必须是发送方的粉丝。否则无法成功发送私信
* 系统返回400错误,提示:40017:Error: can't send direct message to user who is not your follower!
*/
- new_message: function(data, callback, context) {
+ new_message: function (data, callback, context) {
return this.api_dispatch(data).new_message(data, callback, context);
},
@@ -241,7 +259,7 @@ Object.extend(TAPI, {
* lat, long: lat和long参数需配合使用,用于标记发表微博消息时所在的地理位置,只有用户设置中geo_enabled=true时候地理位置信息才有效。
* annotations: 元数据,主要是为了方便第三方应用记录一些适合于自己使用的信息。每条微博可以包含一个或者多个元数据。请以json字串的形式提交,字串长度不超过512个字符,具体内容可以自定。
*/
- update: function(data, callback, context) {
+ update: function (data, callback, context) {
if (!data.pic) {
return this.api_dispatch(data).update(data, callback, context);
}
@@ -255,18 +273,18 @@ Object.extend(TAPI, {
* status
* pic: {keyname: 'pic', file: filepath} 要上传的图片。仅支持JPEG,GIF,PNG图片,为空返回400错误。目前上传图片大小限制为<5M。
*/
- upload: function(data, pic, callback, context) {
+ upload: function (data, pic, callback, context) {
return this.api_dispatch(data).upload(data, pic, callback, context);
},
- upload_pic_url: function(data, pic, callback, context) {
+ upload_pic_url: function (data, pic, callback, context) {
return this.api_dispatch(data).upload_pic_url(data, pic, callback, context);
},
/*
* id, status, is_comment
*/
- repost: function(data, callback, context) {
+ repost: function (data, callback, context) {
return this.api_dispatch(data).repost(data, callback, context);
},
@@ -274,7 +292,7 @@ Object.extend(TAPI, {
* id, comment, cid
* without_mention: 1:回复中不自动加入“回复@用户名”,0:回复中自动加入“回复@用户名”. 默认为0.
*/
- comment: function(data, callback, context) {
+ comment: function (data, callback, context) {
return this.api_dispatch(data).comment(data, callback, context);
},
@@ -283,31 +301,31 @@ Object.extend(TAPI, {
* id: 要评论的微博消息ID
* without_mention: 1:回复中不自动加入“回复@用户名”,0:回复中自动加入“回复@用户名”.默认为0.
*/
- reply: function(data, callback, context) {
+ reply: function (data, callback, context) {
return this.api_dispatch(data).reply(data, callback, context);
},
/*
* id, count, page
*/
- comments: function(data, callback, context) {
+ comments: function (data, callback, context) {
return this.api_dispatch(data).comments(data, callback, context);
},
// id
- comment_destroy: function(data, callback, context) {
+ comment_destroy: function (data, callback, context) {
return this.api_dispatch(data).comment_destroy(data, callback, context);
},
/*
* id, user_id, screen_name 这三个参数必填其一。
*/
- friendships_create: function(data, callback, context) {
+ friendships_create: function (data, callback, context) {
return this.api_dispatch(data).friendships_create(data, callback, context);
},
// id
- friendships_destroy: function(data, callback, context) {
+ friendships_destroy: function (data, callback, context) {
return this.api_dispatch(data).friendships_destroy(data, callback, context);
},
@@ -315,47 +333,47 @@ Object.extend(TAPI, {
* target_id, target_screen_name: 参数必选其一
* source_id, source_screen_name: 参数可不填,如果不填,则默认取当前登录用户
*/
- friendships_show: function(data, callback, context) {
+ friendships_show: function (data, callback, context) {
return this.api_dispatch(data).friendships_show(data, callback, context);
},
// type: 需要清零的计数类别,值为下列四个之一:1. 评论数,2. @me数,3. 私信数,4. 关注数
- reset_count: function(data, callback, context) {
+ reset_count: function (data, callback, context) {
return this.api_dispatch(data).reset_count(data, callback, context);
},
// id 瑞推
- retweet: function(data, callback, context) {
+ retweet: function (data, callback, context) {
return this.api_dispatch(data).retweet(data, callback, context);
},
// id
- destroy: function(data, callback, context) {
+ destroy: function (data, callback, context) {
return this.api_dispatch(data).destroy(data, callback, context);
},
// user_id, count, page
- tags: function(data, callback, context) {
+ tags: function (data, callback, context) {
return this.api_dispatch(data).tags(data, callback, context);
},
// count, page
- tags_suggestions: function(data, callback, context) {
+ tags_suggestions: function (data, callback, context) {
return this.api_dispatch(data).tags_suggestions(data, callback, context);
},
// tags
- create_tag: function(data, callback, context) {
+ create_tag: function (data, callback, context) {
return this.api_dispatch(data).create_tag(data, callback, context);
},
// tag_id
- destroy_tag: function(data, callback, context) {
+ destroy_tag: function (data, callback, context) {
return this.api_dispatch(data).destroy_tag(data, callback, context);
},
// id
- status_show: function(data, callback, context) {
+ status_show: function (data, callback, context) {
return this.api_dispatch(data).status_show(data, callback, context);
},
View
1,098 lib/tsina.js
@@ -4,6 +4,7 @@
var utils;
var OAuth;
var EventProxy;
+var urllib;
var root = this; // window on browser
@@ -11,26 +12,24 @@ if (typeof require !== 'undefined') {
var fs = require('fs');
var path = require('path');
OAuth = require('./oauth');
- var urllib = require('./urllib');
+ urllib = require('./urllib');
utils = require('./utils');
- EventProxy = require('./eventproxy').EventProxy;
+ EventProxy = require('../lib/eventproxy').EventProxy; // no need to coverage
} else {
OAuth = weibo.OAuth;
- var urllib = weibo.urllib;
+ urllib = weibo.urllib;
utils = weibo.utils;
EventProxy = root.EventProxy;
}
var TSinaAPI = {
- combo: function (callback) {
- return new utils.Combo(callback);
- },
config: {
host: 'http://api.t.sina.com.cn',
user_home_url: 'http://weibo.com/n/',
search_url: 'http://weibo.com/k/',
result_format: '.json',
source: '',
+ need_source: true,
oauth_key: '',
oauth_secret: '',
oauth_callback: '',
@@ -82,6 +81,7 @@ var TSinaAPI = {
update: '/statuses/update',
upload: '/statuses/upload',
repost: '/statuses/repost',
+ // repost: '/statuses/retweet/{{id}}',
repost_timeline: '/statuses/repost_timeline',
comment: '/statuses/comment',
reply: '/statuses/reply',
@@ -164,6 +164,7 @@ var TSinaAPI = {
for (var k in params) {
args[k] = params[k];
}
+ args.type = (args.type || 'GET').toUpperCase();
args.data = args.data || {};
if (!args.data.source) {
if (args.need_source === false || this.config.need_source === false) {
@@ -198,6 +199,7 @@ var TSinaAPI = {
args.url.replace(utils.STRING_FORMAT_REGEX, function (match, key) {
delete args.data[key];
});
+ // console.log(url, args, user)
// 设置认证头部
this.apply_auth(url, args, user);
var callmethod = user.uniqueKey + ': ' + args.type + ' ' + args.url;
@@ -247,13 +249,13 @@ var TSinaAPI = {
}
var parameters = {};
- for (var k in args.data) {
+ for (var k in args.data) {
parameters[k] = args.data[k];
if (k.substring(0, 6) === 'oauth_') { // 删除oauth_verifier相关参数
delete args.data[k];
}
}
-
+
var message = {
action: url,
method: args.type,
@@ -269,9 +271,8 @@ var TSinaAPI = {
// 设置时间戳
OAuth.setTimestampAndNonce(message);
// 签名参数
- //console.log(message.parameters);
+ // console.log(message.parameters);
OAuth.SignatureMethod.sign(message, accessor);
-
// oauth参数通过get方式传递
if (this.config.oauth_params_by_get) {
args.data = message.parameters;
@@ -318,7 +319,7 @@ var TSinaAPI = {
}
var params = {
url: this.config.oauth_request_token,
- type: 'get',
+ type: 'GET',
user: user,
play_load: 'string',
api_host: this.config.oauth_host,
@@ -351,7 +352,7 @@ var TSinaAPI = {
}
var params = {
url: this.config.oauth_access_token,
- type: 'get',
+ type: 'GET',
user: user,
play_load: 'string',
api_host: this.config.oauth_host,
@@ -397,7 +398,7 @@ var TSinaAPI = {
verify_credentials: function (user, callback, context) {
var params = {
url: this.config.verify_credentials,
- type: 'get',
+ type: 'GET',
user: user,
play_load: 'user'
};
@@ -410,7 +411,7 @@ var TSinaAPI = {
}
var params = {
url: this.config.rate_limit_status,
- type: 'get',
+ type: 'GET',
play_load: 'rate',
data: data
};
@@ -421,7 +422,7 @@ var TSinaAPI = {
friends_timeline: function (data, callback, context) {
var params = {
url: this.config.friends_timeline,
- type: 'get',
+ type: 'GET',
play_load: 'status',
data: data
};
@@ -432,7 +433,7 @@ var TSinaAPI = {
user_timeline: function (data, callback, context) {
var params = {
url: this.config.user_timeline,
- type: 'get',
+ type: 'GET',
play_load: 'status',
data: data
};
@@ -443,7 +444,7 @@ var TSinaAPI = {
comments_timeline: function (data, callback, context) {
var params = {
url: this.config.comments_timeline,
- type: 'get',
+ type: 'GET',
play_load: 'comment',
data: data
};
@@ -454,7 +455,7 @@ var TSinaAPI = {
repost_timeline: function (data, callback, context) {
var params = {
url: this.config.repost_timeline,
- type: 'get',
+ type: 'GET',
play_load: 'status',
data: data
};
@@ -465,7 +466,7 @@ var TSinaAPI = {
mentions: function (data, callback, context){
var params = {
url: this.config.mentions,
- type: 'get',
+ type: 'GET',
play_load: 'status',
data: data
};
@@ -476,7 +477,7 @@ var TSinaAPI = {
followers: function (data, callback, context) {
var params = {
url: this.config.followers,
- type: 'get',
+ type: 'GET',
play_load: 'user',
data: data
};
@@ -486,7 +487,7 @@ var TSinaAPI = {
public_timeline: function (data, callback, context) {
var params = {
url: this.config.public_timeline,
- type: 'get',
+ type: 'GET',
play_load: 'status',
data: data
};
@@ -497,7 +498,7 @@ var TSinaAPI = {
friends: function (data, callback, context) {
var params = {
url: this.config.friends,
- type: 'get',
+ type: 'GET',
play_load: 'user',
data: data
};
@@ -505,106 +506,118 @@ var TSinaAPI = {
},
// page
- favorites: function(data, callback, context) {
- var params = {
- url: this.config.favorites,
- type: 'get',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
+ favorites: function (data, callback, context) {
+ var params = {
+ url: this.config.favorites,
+ type: 'GET',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
},
// id
- favorites_create: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.favorites_create,
- type: 'post',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
+ favorites_create: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.favorites_create,
+ type: 'POST',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
},
// id
- favorites_destroy: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.favorites_destroy,
- type: 'post',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
+ favorites_destroy: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.favorites_destroy,
+ type: 'POST',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
},
// ids
- counts: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.counts,
- type: 'get',
- play_load: 'count',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // id
- user_show: function(data, callback, context) {
- var params = {
- url: this.config.user_show,
- type: 'get',
- play_load: 'user',
- data: data
- };
- this._send_request(params, callback, context);
- },
+ counts: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.counts,
+ type: 'GET',
+ play_load: 'count',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // id
+ user_show: function (data, callback, context) {
+ var params = {
+ url: this.config.user_show,
+ type: 'GET',
+ play_load: 'user',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
// since_id, max_id, count, page
- direct_messages: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.direct_messages,
- type: 'get',
- play_load: 'message',
- data: data
- };
- this._send_request(params, callback, context);
+ direct_messages: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.direct_messages,
+ type: 'GET',
+ play_load: 'message',
+ data: data
+ };
+ this._send_request(params, callback, context);
},
// id
- destroy_msg: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.destroy_msg,
- type: 'post',
- play_load: 'message',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- /*data的参数列表:
- content 待发送消息的正文,请确定必要时需要进行URL编码 ( encode ) ,另外,不超过140英文或140汉字。
- message 必须 0 表示悄悄话 1 表示戳一下
- receiveUserId 必须,接收方的用户id
- source 可选,显示在网站上的来自哪里对应的标识符。如果想显示指定的字符,请与官方人员联系。
- */
- new_message: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.new_message,
- type: 'post',
- play_load: 'message',
- data: data
- };
- this._send_request(params, callback, context);
+ destroy_msg: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.destroy_msg,
+ type: 'POST',
+ play_load: 'message',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ /*data的参数列表:
+ content 待发送消息的正文,请确定必要时需要进行URL编码 ( encode ) ,另外,不超过140英文或140汉字。
+ message 必须 0 表示悄悄话 1 表示戳一下
+ receiveUserId 必须,接收方的用户id
+ source 可选,显示在网站上的来自哪里对应的标识符。如果想显示指定的字符,请与官方人员联系。
+ */
+ new_message: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.new_message,
+ type: 'POST',
+ play_load: 'message',
+ data: data
+ };
+ this._send_request(params, callback, context);
},
// id
- status_show: function(data, callback, context) {
+ status_show: function (data, callback, context) {
var params = {
url: this.config.status_show,
play_load: 'status',
@@ -613,330 +626,334 @@ var TSinaAPI = {
this._send_request(params, callback, context);
},
- update: function(data, callback, context) {
- //console.log(this.config.update);
- var params = {
- url: this.config.update,
- type: 'POST',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
- },
+ // 格式上传参数,方便子类覆盖做特殊处理
+ // 子类可以增加自己的参数
+ format_upload_params: function (user, data, pic) {
- // 格式上传参数,方便子类覆盖做特殊处理
- // 子类可以增加自己的参数
- format_upload_params: function(user, data, pic) {
-
- },
+ },
+
+ FILE_CONTENT_TYPES: {
+ '.gif': 'image/gif',
+ '.jpeg': 'image/jpeg',
+ '.jpg': 'image/jpeg',
+ '.png': 'image/png'
+ },
- FILE_CONTENT_TYPES: {
- '.gif': 'image/gif',
- '.jpeg': 'image/jpeg',
- '.jpg': 'image/jpeg',
- '.png': 'image/png'
-
- },
+ fileinfo: function (file) {
+ var name, content_type;
+ if (typeof file === 'string') {
+ var ext = path.extname(file);
+ content_type = this.FILE_CONTENT_TYPES[ext];
+ name = path.basename(file);
+ } else {
+ name = file.name || file.fileName;
+ content_type = file.fileType || file.type;
+ }
+ return { name: name, content_type: content_type };
+ },
- fileinfo: function(file) {
- var name, content_type;
- if(typeof(file) === 'string') {
- var ext = path.extname(file);
- content_type = this.FILE_CONTENT_TYPES[ext];
- name = path.basename(file);
- } else {
- name = file.name || file.fileName;
- content_type = file.fileType || file.type;
- }
- return {name: name, content_type: content_type};
- },
+ /**
+ * 上传图片
+ * data: {user: user1, source: xxx, status: xxx, ...}
+ * pic: filepath
+ * callback: finish callback function
+ **/
+ upload: function(data, pic, callback, context) {
+ var user = data.user;
+ delete data.user;
+ var auth_args = { type: 'post', data: {}, headers: {} };
+ var pic_field = this.config.pic_field || 'pic';
+ data.source = data.source || this.config.source;
- /**
- * 上传图片
- * data: {user: user1, source: xxx, status: xxx, ...}
- * pic: filepath
- * callback: finish callback function
- **/
- upload: function(data, pic, callback, context) {
- var user = data.user;
- delete data.user;
- var auth_args = {type: 'post', data: {}, headers: {}};
- var pic_field = this.config.pic_field || 'pic';
- data.source = data.source || this.config.source;
-
- var boundary = 'boundary' + (new Date).getTime();
- this.format_upload_params(user, data, pic , boundary);
- var dashdash = '--';
- var crlf = '\r\n';
-
- /* Build RFC2388 string. */
- var builder = '';
-
- builder += dashdash;
- builder += boundary;
- builder += crlf;
+ var boundary = 'boundary' + new Date().getTime();
+ this.format_upload_params(user, data, pic , boundary);
+ var dashdash = '--';
+ var crlf = '\r\n';
- for(var key in data) {
- var value = this.url_encode(data[key]);
- auth_args.data[key] = value;
- }
-
- var api = user.apiProxy || this.config.host;
- var url = api + this.config.upload + this.config.result_format;
+ /* Build RFC2388 string. */
+ var builder = '';
+
+ builder += dashdash;
+ builder += boundary;
+ builder += crlf;
+
+ for (var key in data) {
+ var value = this.url_encode(data[key]);
+ auth_args.data[key] = value;
+ }
+ var api = user.apiProxy || this.config.host;
+ var url = api + this.config.upload + this.config.result_format;
+
var fileinfo = this.fileinfo(pic);
-
+
//auth_args.data.format = 'json';
//auth_args.data.Filename = this.url_encode(fileinfo.name);
//auth_args.data.Upload = this.url_encode('Sumbit');
// 设置认证头部
- this.apply_auth(url, auth_args, user);
-
- for(var key in auth_args.data) {
- /* Generate headers. key */
- builder += 'Content-Disposition: form-data; name="' + key + '"';
- builder += crlf;
- builder += crlf;
- /* Append form data. */
- builder += auth_args.data[key];
- builder += crlf;
-
- /* Write boundary. */
- builder += dashdash;
- builder += boundary;
- builder += crlf;
- }
- /* Generate headers. [PIC] */
- builder += 'Content-Disposition: form-data; name="' + pic_field + '"';
-
- builder += '; filename="' + this.url_encode(fileinfo.name) + '"';
- builder += crlf;
-
- builder += 'Content-Type: '+ fileinfo.content_type + ';';
+ this.apply_auth(url, auth_args, user);
+
+ for (var key in auth_args.data) {
+ /* Generate headers. key */
+ builder += 'Content-Disposition: form-data; name="' + key + '"';
builder += crlf;
+ builder += crlf;
+ /* Append form data. */
+ builder += auth_args.data[key];
builder += crlf;
- // console.log(builder);
- var that = this;
- // 处理文件内容
- this.read_file(pic, function(file_buffer) {
- var endstr = crlf + dashdash + boundary + dashdash + crlf
- , buffer = null;
- if(typeof(BlobBuilder) === 'undefined') {
- var builderLength = new Buffer(builder).length;
- var size = builderLength + file_buffer.length + endstr.length;
- buffer = new Buffer(size);
- var offset = 0;
- buffer.write(builder);
- offset += builderLength ;
- file_buffer.copy(buffer, offset);
- offset += file_buffer.length;
- buffer.write(endstr, offset);
- } else {
- buffer = new BlobBuilder(); //NOTE WebKitBlogBuilder
- buffer.append(builder);
- buffer.append(pic);
- buffer.append(endstr);
- buffer = buffer.getBlob();
- }
-
- auth_args.headers['Content-Type'] = 'multipart/form-data;boundary=' + boundary;
-
- that.request(url, {
- type: 'POST',
- play_load: 'status',
- data: buffer,
- process_data: false,
- headers: auth_args.headers
- }, callback, context);
- });
- },
+ /* Write boundary. */
+ builder += dashdash;
+ builder += boundary;
+ builder += crlf;
+ }
+ /* Generate headers. [PIC] */
+ builder += 'Content-Disposition: form-data; name="' + pic_field + '"';
+
+ builder += '; filename="' + this.url_encode(fileinfo.name) + '"';
+ builder += crlf;
+
+ builder += 'Content-Type: '+ fileinfo.content_type + ';';
+ builder += crlf;
+ builder += crlf;
- read_file: function(pic, callback) {
- if (typeof pic === 'string') {
- fs.stat(pic, function (err, stats) {
- fs.readFile(pic, function (err, file_buffer) {
- if (!err) {
- callback(file_buffer);
- }
- });
- });
+ // console.log(builder);
+ var that = this;
+ // 处理文件内容
+ this.read_file(pic, function (file_buffer) {
+ var endstr = crlf + dashdash + boundary + dashdash + crlf;
+ var buffer = null;
+ if (typeof BlobBuilder === 'undefined') {
+ var builderLength = new Buffer(builder).length;
+ var size = builderLength + file_buffer.length + endstr.length;
+ buffer = new Buffer(size);
+ var offset = 0;
+ buffer.write(builder);
+ offset += builderLength ;
+ file_buffer.copy(buffer, offset);
+ offset += file_buffer.length;
+ buffer.write(endstr, offset);
} else {
- callback(pic);
+ buffer = new BlobBuilder(); //NOTE WebKitBlogBuilder
+ buffer.append(builder);
+ buffer.append(pic);
+ buffer.append(endstr);
+ buffer = buffer.getBlob();
}
- },
-
- repost: function(data, callback, context) {
- var params = {
- url: this.config.repost,
- type: 'post',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- comment: function(data, callback, context) {
- var params = {
- url: this.config.comment,
- type: 'post',
- play_load: 'comment',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- reply: function(data, callback, context) {
- var params = {
- url: this.config.reply,
- type: 'post',
- play_load: 'comment',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- comments: function(data, callback, context) {
- var params = {
- url: this.config.comments,
- type: 'get',
- play_load: 'comment',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // id
- comment_destroy: function(data, callback, context) {
- var params = {
- url: this.config.comment_destroy,
- type: 'post',
- play_load: 'comment',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- friendships_create: function(data, callback, context) {
- var params = {
- url: this.config.friendships_create,
- type: 'post',
- play_load: 'user',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // id
- friendships_destroy: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.friendships_destroy,
- type: 'post',
- play_load: 'user',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- friendships_show: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.friendships_show,
- type: 'get',
- play_load: 'user',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // type
- reset_count: function(data, callback, context) {
- if(!callback) return;
- var params = {
- url: this.config.reset_count,
- type: 'post',
- play_load: 'result',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // user_id, count, page
- tags: function(data, callback, context) {
- var params = {
- url: this.config.tags,
- play_load: 'tag',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // count, page
- tags_suggestions: function(data, callback, context) {
- var params = {
- url: this.config.tags_suggestions,
- play_load: 'tag',
- data: data
- };
- this._send_request(params, callback, context);
- },
+
+ auth_args.headers['Content-Type'] = 'multipart/form-data;boundary=' + boundary;
+
+ that.request(url, {
+ type: 'POST',
+ play_load: 'status',
+ data: buffer,
+ process_data: false,
+ headers: auth_args.headers
+ }, callback, context);
+ });
+ },
- // tags
- create_tag: function(data, callback, context) {
- var params = {
- url: this.config.create_tag,
- type: 'post',
- play_load: 'tag',
- data: data
- };
- this._send_request(params, callback, context);
- },
+ read_file: function (pic, callback) {
+ if (typeof pic === 'string') {
+ fs.stat(pic, function (err, stats) {
+ fs.readFile(pic, function (err, file_buffer) {
+ if (!err) {
+ callback(file_buffer);
+ }
+ });
+ });
+ } else {
+ callback(pic);
+ }
+ },
+
+ update: function (data, callback, context) {
+ var params = {
+ url: this.config.update,
+ type: 'POST',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ repost: function (data, callback, context) {
+ var params = {
+ url: this.config.repost,
+ type: 'POST',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ comment: function (data, callback, context) {
+ var params = {
+ url: this.config.comment,
+ type: 'POST',
+ play_load: 'comment',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ reply: function (data, callback, context) {
+ var params = {
+ url: this.config.reply,
+ type: 'POST',
+ play_load: 'comment',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ comments: function (data, callback, context) {
+ var params = {
+ url: this.config.comments,
+ type: 'GET',
+ play_load: 'comment',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // id
+ comment_destroy: function (data, callback, context) {
+ var params = {
+ url: this.config.comment_destroy,
+ type: 'POST',
+ play_load: 'comment',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ friendships_create: function (data, callback, context) {
+ var params = {
+ url: this.config.friendships_create,
+ type: 'POST',
+ play_load: 'user',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // id
+ friendships_destroy: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.friendships_destroy,
+ type: 'POST',
+ play_load: 'user',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ friendships_show: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.friendships_show,
+ play_load: 'user',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // type
+ reset_count: function (data, callback, context) {
+ if (!callback) {
+ return;
+ }
+ var params = {
+ url: this.config.reset_count,
+ type: 'POST',
+ play_load: 'result',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
- // tag_id
- destroy_tag: function(data, callback, context) {
- var params = {
- url: this.config.destroy_tag,
- type: 'post',
- play_load: 'tag',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // id
- destroy: function(data, callback, context) {
- if(!data || !data.id || !callback){return;}
- var params = {
- url: this.config.destroy,
- type: 'POST',
- play_load: 'status',
- data: data
- };
- this._send_request(params, callbac, context);
- },
+ // user_id, count, page
+ tags: function (data, callback, context) {
+ var params = {
+ url: this.config.tags,
+ play_load: 'tag',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
- // q, max_id, count
- search: function(data, callback, context) {
+ // count, page
+ tags_suggestions: function (data, callback, context) {
+ var params = {
+ url: this.config.tags_suggestions,
+ play_load: 'tag',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // tags
+ create_tag: function (data, callback, context) {
+ var params = {
+ url: this.config.create_tag,
+ type: 'POST',
+ play_load: 'tag',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // tag_id
+ destroy_tag: function (data, callback, context) {
+ var params = {
+ url: this.config.destroy_tag,
+ type: 'POST',
+ play_load: 'tag',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
- var params = {
- url: this.config.search,
- play_load: 'status',
- data: data
- };
- this._send_request(params, callback, context);
- },
-
- // q, page, count
- user_search: function(data, callback, context) {
- var params = {
- url: this.config.user_search,
- play_load: 'user',
- data: data
- };
- this._send_request(params, callback, context);
- },
+ // id
+ destroy: function (data, callback, context) {
+ if (!data || !data.id || !callback) {
+ return;
+ }
+ var params = {
+ url: this.config.destroy,
+ type: 'POST',
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // q, max_id, count
+ search: function (data, callback, context) {
+ var params = {
+ url: this.config.search,
+ play_load: 'status',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
+
+ // q, page, count
+ user_search: function (data, callback, context) {
+ var params = {
+ url: this.config.user_search,
+ play_load: 'user',
+ data: data
+ };
+ this._send_request(params, callback, context);
+ },
/**
* List all emotions.
@@ -1099,79 +1116,91 @@ var TSinaAPI = {
URL_RE: new RegExp('(?:\\[url\\s*=\\s*|)((?:www\\.|http[s]?://)[\\w\\.\\?%&\\-/#=;:!\\+~]+)(?:\\](.+)\\[/url\\]|)', 'ig'),
/**
- * format status.text to display
- */
- process_text: function(str_or_status, need_encode) {
- var str = str_or_status;
- if(need_encode === 'undedfined') {
- need_encode = true;
- }
- if(str_or_status.text !== undefined) {
- str = str_or_status.text;
- }
- if(str && this.config.need_process_text){
- if (need_encode) {
- str = HTMLEnCode(str);
- }
- str = str.replace(this.URL_RE, this._replace_url_callback);
- str = this.process_at(str, str_or_status); //@***
- str = this.process_emotional(str);
- str = this.process_search(str); //#xxXX#
- // iPhone emoji
- str = str.replace( /([\uE001-\uE537])/gi, this._get_iphone_emoji);
- }
- return str || '&nbsp;';
- },
- _replace_url_callback: function(m, g1, g2){
- var _url = g1;
- if(g1.indexOf('http') != 0){
- _url = 'http://' + g1;
- }
- return '<a target="_blank" class="link" href="{{url}}">{{value}}</a>'.format({
- url: _url, title: g1, value: g2||g1
- });
- },
-
- _get_iphone_emoji: function(str){
- return "<span class=\"iphoneEmoji "+ str.charCodeAt(0).toString(16).toUpperCase()+"\"></span>";
- },
- SEARCH_MATCH_RE: /#([^#]+)#/g,
- SEARCH_TPL: '<a target="_blank" href="{{search_url}}{{search}}" title="Search #{{search}}">#{{search}}#</a>',
- process_search: function(str) {
- return str.replace(this.SEARCH_MATCH_RE, this._process_search_callback);
- },
- _process_search_callback: function(m, g1) {
- // 修复#xxx@xxx#嵌套问题
- var search = g1.remove_html_tag();
- return this.SEARCH_TPL.format({search: search, search_url: this.config.search_url});
- },
- format_search_text: function(str) { // 格式化主题
- return '#' + str.trim() + '#';
- },
- AT_RE: /@([\w\-\_\u2E80-\u3000\u303F-\u9FFF]+)/g,
- process_at: function (str) {
- //@*** u4e00-\u9fa5:中文字符 \u2E80-\u9FFF:中日韩字符
- //【观点·@任志强】今年提出的1000万套的保障房任务可能根本完不成
- // http://blog.oasisfeng.com/2006/10/19/full-cjk-unicode-range/
- // CJK标点符号:3000-303F
- var tpl = '<a target="_blank" href="javascript:getUserTimeline(\'$1\');" rhref="'
- + this.config.user_home_url + '$1" title="'
- + _u.i18n("btn_show_user_title") + '">@$1</a>';
- return str.replace(AT_RE, tpl);
- },
- process_emotional: function(str){
- return str.replace(/\[([\u4e00-\u9fff,\uff1f,\w]{1,4})\]/g, this._replace_emotional_callback);
- },
- EMOTIONAL_TPL: '<img title="{{title}}" src="{{src}}" />',
- _replace_emotional_callback: function (m, g1) {
- if (g1) {
- var face = this.EMOTIONS[g1];
- if(face) {
- return this.EMOTIONAL_TPL.format({title: m, src: FACE_URL_PRE + face});
- }
- }
- return m;
- },
+ * format status.text to display
+ */
+ process_text: function (str_or_status, need_encode) {
+ var str = str_or_status;
+ if (need_encode === 'undedfined') {
+ need_encode = true;
+ }
+ if (str_or_status.text !== undefined) {
+ str = str_or_status.text;
+ }
+ if (str) {
+ if (need_encode) {
+ str = utils.htmlencode(str);
+ }
+ str = str.replace(this.URL_RE, this._replace_url_callback);
+ str = this.process_at(str, str_or_status); //@***
+ str = this.process_emotional(str);
+ str = this.process_search(str); //#xxXX#
+ // iPhone emoji
+ str = str.replace( /([\uE001-\uE537])/gi, this._get_iphone_emoji);
+ }
+ return str || '&nbsp;';
+ },
+ _replace_url_callback: function (m, g1, g2) {
+ var _url = g1;
+ if (g1.indexOf('http') !== 0) {
+ _url = 'http://' + g1;
+ }
+ return '<a target="_blank" class="link" href="{{url}}">{{value}}</a>'.format({
+ url: _url, title: g1, value: g2||g1
+ });
+ },
+
+ _get_iphone_emoji: function (str) {
+ return "<span class=\"iphoneEmoji "+ str.charCodeAt(0).toString(16).toUpperCase()+"\"></span>";
+ },
+
+ SEARCH_MATCH_RE: /#([^#]+)#/g,
+ SEARCH_TPL: '<a target="_blank" href="{{search_url}}{{search}}" title="Search #{{search}}">#{{search}}#</a>',
+
+ process_search: function (str) {
+ var that = this;
+ return str.replace(this.SEARCH_MATCH_RE, function (m, g1) {
+ return that._process_search_callback(m, g1);
+ });
+ },
+
+ _process_search_callback: function (m, g1) {
+ // 修复#xxx@xxx#嵌套问题
+ // var search = g1.remove_html_tag();
+ return this.SEARCH_TPL.format({ search: g1, search_url: this.config.search_url });
+ },
+
+ format_search_text: function (str) { // 格式化主题
+ return '#' + str.trim() + '#';
+ },
+
+ AT_RE: /@([\w\-\_\u2E80-\u3000\u303F-\u9FFF]+)/g,
+ process_at: function (str) {
+ //@*** u4e00-\u9fa5:中文字符 \u2E80-\u9FFF:中日韩字符
+ //【观点·@任志强】今年提出的1000万套的保障房任务可能根本完不成
+ // http://blog.oasisfeng.com/2006/10/19/full-cjk-unicode-range/
+ // CJK标点符号:3000-303F
+ var tpl = '<a class="at_user" data-name="$1" href="javascript:;" rhref="' +
+ this.config.user_home_url + '$1" title="show users">@$1</a>';
+ return str.replace(this.AT_RE, tpl);
+ },
+
+ process_emotional: function (str) {
+ var that = this;
+ return str.replace(/\[([\u4e00-\u9fff,\uff1f,\w]{1,4})\]/g, function (m, g1) {
+ return that._replace_emotional_callback(m, g1);
+ });
+ },
+
+ EMOTIONAL_TPL: '<img title="{{title}}" src="{{src}}" />',
+ _replace_emotional_callback: function (m, g1) {
+ if (g1) {
+ var face = this.EMOTIONS[g1];
+ if (face) {
+ return this.EMOTIONAL_TPL.format({ title: m, src: FACE_URL_PRE + face });
+ }
+ }
+ return m;
+ },
/**
* urlencode,子类覆盖是否需要urlencode处理
@@ -1180,7 +1209,7 @@ var TSinaAPI = {
* @returns {String} url encode text
*/
url_encode: function (text) {
- return OAuth.percentEncode(text);
+ return encodeURIComponent(text);
},
/**
@@ -1188,7 +1217,7 @@ var TSinaAPI = {
*/
before_send_request: function (args, user) {
- },
+ }
};
@@ -1212,15 +1241,14 @@ var WeiboUtil = {
* @param {String} str62 62进制值
* @return {String} 10进制值
*/
-WeiboUtil.str62to10 = function(str62) {
- var i10 = 0;
- for (var i = 0; i < str62.length; i++)
- {
- var n = str62.length - i - 1;
- var s = str62[i];
- i10 += this.str62keys.indexOf(s) * Math.pow(62, n);
- }
- return i10;
+WeiboUtil.str62to10 = function (str62) {
+ var i10 = 0;
+ for (var i = 0; i < str62.length; i++) {
+ var n = str62.length - i - 1;
+ var s = str62[i];
+ i10 += this.str62keys.indexOf(s) * Math.pow(62, n);
+ }
+ return i10;
};
/**
@@ -1228,15 +1256,15 @@ WeiboUtil.str62to10 = function(str62) {
* @param {String} int10 10进制值
* @return {String} 62进制值
*/
-WeiboUtil.int10to62 = function(int10) {
- var s62 = '';
- var r = 0;
- while (int10 != 0 && s62.length < 100) {
- r = int10 % 62;
- s62 = this.str62keys[r] + s62;
- int10 = Math.floor(int10 / 62);
- }
- return s62;
+WeiboUtil.int10to62 = function (int10) {
+ var s62 = '';
+ var r = 0;
+ while (int10 !== 0 && s62.length < 100) {
+ r = int10 % 62;
+ s62 = this.str62keys[r] + s62;
+ int10 = Math.floor(int10 / 62);
+ }
+ return s62;
};
/**
@@ -1244,28 +1272,26 @@ WeiboUtil.int10to62 = function(int10) {
* @param {String} url 微博URL字符,如 "wr4mOFqpbO"
* @return {String} 微博mid,如 "201110410216293360"
*/
-WeiboUtil.url2mid = function(url) {
- var mid = '';
+WeiboUtil.url2mid = function (url) {
+ var mid = '';
+ //从最后往前以4字节为一组读取URL字符
+ for (var i = url.length - 4; i > -4; i = i - 4) {
+ var offset1 = i < 0 ? 0 : i;
+ var offset2 = i + 4;
+ var str = url.substring(offset1, offset2);
- for (var i = url.length - 4; i > -4; i = i - 4) //从最后往前以4字节为一组读取URL字符
- {
- var offset1 = i < 0 ? 0 : i;
- var offset2 = i + 4;
- var str = url.substring(offset1, offset2);
-
- str = this.str62to10(str);
- if (offset1 > 0) //若不是第一组,则不足7位补0
- {
- while (str.length < 7)
- {
- str = '0' + str;
- }
- }
-
- mid = str + mid;
+ str = this.str62to10(str);
+ if (offset1 > 0) {
+ //若不是第一组,则不足7位补0
+ while (str.length < 7) {
+ str = '0' + str;
+ }
}
- return mid;
+ mid = str + mid;
+ }
+
+ return mid;
};
/**
@@ -1273,25 +1299,23 @@ WeiboUtil.url2mid = function(url) {
* @param {String} mid 微博mid,如 "201110410216293360"
* @return {String} 微博URL字符,如 "wr4mOFqpbO"
*/
-WeiboUtil.mid2url = function(mid) {
- if(!mid) {
- return mid;
- }
- mid = String(mid); //mid数值较大,必须为字符串!
- if(!/^\d+$/.test(mid)){ return mid; }
- var url = '';
-
- for (var i = mid.length - 7; i > -7; i = i - 7) //从最后往前以7字节为一组读取mid
- {
- var offset1 = i < 0 ? 0 : i;
- var offset2 = i + 7;
- var num = mid.substring(offset1, offset2);
-
- num = this.int10to62(num);
- url = num + url;
- }
+WeiboUtil.mid2url = function (mid) {
+ if (!mid) {
+ return mid;
+ }
+ mid = String(mid); //mid数值较大,必须为字符串!
+ if (!/^\d+$/.test(mid)) { return mid; }
+ var url = '';
+ // 从最后往前以7字节为一组读取mid
+ for (var i = mid.length - 7; i > -7; i = i - 7) {
+ var offset1 = i < 0 ? 0 : i;
+ var offset2 = i + 7;
+ var num = mid.substring(offset1, offset2);
- return url;
+ num = this.int10to62(num);
+ url = num + url;
+ }
+ return url;
};
View
84 lib/utils.js
@@ -37,39 +37,6 @@ Date.prototype.format = function (format) {
return format;
};
-if (!Object.extend) {
- Object.extend = function (destination) {
- for (var i = 1, len = arguments.length; i < len; i++) {
- var source = arguments[i];
- if (!source) {
- continue;
- }
- for (var property in source) {
- destination[property] = source[property];
- }
- }
- return destination;
- };
-}
-
-if (!Object.inherits) {
- Object.inherits = function (destination) {
- for (var i = 1, len = arguments.length; i < len; i++) {
- var source = arguments[i];
- if (!source) {
- continue;
- }
- for (var property in source) {
- destination[property] = source[property];
- }
- if (destination.super_ === undefined) {
- destination.super_ = source;
- }
- }
- return destination;
- };
-}
-
(function () {
var root = this; // window on browser
@@ -83,45 +50,26 @@ if (!Object.inherits) {
} else {
exports = module.exports;
crypto = require('crypto');
+ b64_hmac_sha1 = require('./sha1').b64_hmac_sha1;
}
- function Combo(callback) {
- this.callback = callback;
- this.items = 0;
- this.results = [];
- }
-
- Combo.prototype = {
- add: function () {
- var self = this;
- var id = this.items;
- this.items++;
- return function () {
- self.check(id, arguments);
- };
- },
- check: function (id, arguments) {
- this.results[id] = Array.prototype.slice.call(arguments);
- this.items--;
- if (this.items === 0) {
- this.callback.apply(this, this.results);
- }
- }
- };
-
var querystring = {
parse: function (s) {
var qs = {};
- if (!s) {
+ if (typeof s !== 'string') {
return qs;
}
var pairs = s.split('&');
- if (!pairs || pairs.length === 0) {
- return qs;
- }
for (var i = 0, len = pairs.length; i < len; i++) {
var pair = pairs[i].split('=', 2);
- qs[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
+ if (pair.length !== 2) {
+ continue;
+ }
+ var key = pair[0].trim();
+ if (!key) {
+ continue;
+ }
+ qs[decodeURIComponent(key)] = decodeURIComponent(pair[1]);
}
return qs;
},
@@ -139,6 +87,9 @@ if (!Object.inherits) {
if (typeof params === 'object') {
params = querystring.stringify(params);
}
+ if (!params) {
+ return url;
+ }
if (url.indexOf('?') < 0) {
url += '?';
} else {
@@ -154,6 +105,13 @@ if (!Object.inherits) {
return new crypto.Hmac().init("sha1", key).update(baseString).digest("base64");
}
+ // HTML 编码
+ // test: hard code testing 。。。 '"!@#$%^&*()-=+ |][ {} ~` &&&&&amp; &lt; & C++ c++c + +c &amp;
+ function htmlencode(str) {
+ if (!str) { return ''; }
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ }
+
exports.extend = function (destination) {
for (var i = 1, len = arguments.length; i < len; i++) {
var source = arguments[i];
@@ -184,9 +142,9 @@ if (!Object.inherits) {
};
exports.STRING_FORMAT_REGEX = STRING_FORMAT_REGEX;
- exports.Combo = Combo;
exports.querystring = querystring;
exports.base64HmacSha1 = base64HmacSha1;
exports.urljoin = urljoin;
+ exports.htmlencode = htmlencode;
})();
View
1  start-test.sh
@@ -1 +0,0 @@
-expresso test/*.test.js
View
93 test.js
@@ -1,93 +0,0 @@
-var sinaApp = {
- key : '1306060637',
- secret : '0850d7407392fb537bff0762406c567d',
- blogType: 'tsina',
- oauth_user : {
- blogtype: 'tsina',
- oauth_token_key: '2cfefac248e80189d73fb0cfea81fb51',
- oauth_verifier: '333178',
- oauth_token_secret: 'e77da0ea0bf4a985444387954939b43a',
- blogType: 'tsina',
- authtype: 'oauth'
- }
-}
-
-var qqApp = {
- key : '801004324',
- secret : 'f4dccb3a9f1689adcc66dc933b38445e',
- blogType: 'tqq',
- oauth_user : {
- oauth_token_key: '78dd54c7380b4cb9b99f061394dfcbf7',
- oauth_verifier: '987832',
- oauth_token_secret: '664c81d6061beed7d450a7b845312d3e',
- blogType: 'tqq',
- authtype: 'oauth'
- }
-}
-
-var sohuApp = {
- key : 'geDQ7cFZ7iruNPHm3lZk',
- secret : 'iQ%mtL!eh%xVl!SjQN^($Efdw41!#Ytt*r8SMtw8',
- blogType: 'tsohu',
- oauth_user : {
- oauth_token_key: 'a9e1909afeb947edb3f148532b7583aa',
- oauth_verifier: '80762835',
- oauth_token_secret: 'a865070cb253df351df6d74bfb81b11b',
- blogType: 'tsohu',
- authtype: 'oauth'
- }
-}
-
-var apps = [sinaApp, qqApp , sohuApp];
-//var apps = [sohuApp];
-
-var tapi = require('../node-weibo').tapi,
- querystring = require('querystring');
-
-for(var i = 0 ; i < apps.length; i++) {
- tapi.init(apps[i].blogType, apps[i].key, apps[i].secret);
-}
-
-for(var i = 0 ; i < apps.length; i++) {
- /*
- tapi.upload({user:apps[i].oauth_user ,status : '哈哈'}, './test/snake.jpg' ,function(err,data){
- if(err)
- console.log('err:'+ JSON.stringify(err));
- else {
- console.log('upload:'+ data.t_url);
- }
- });
- */
-
- /*
- tapi.public_timeline({user:apps[i].oauth_user}, function(error, data) {
- if(error)
- console.log('err:'+ JSON.stringify(error));
- else {
- console.log('data:'+ JSON.stringify(data));
- }
- });
- */
-
-
- tapi.verify_credentials(apps[i].oauth_user, function(error, t_user) {
- if(error)
- console.log('err:'+ JSON.stringify(error));
- else {
- console.log('user:'+ JSON.stringify(t_user));
- }
- });
-
-
- /*
- tapi.update({ user:apps[i].oauth_user, status : '今天天气不错 哈哈'},function(err,data){
- if(err)
- console.log('err:'+JSON.stringify(err));
- else {
- console.log('update:'+JSON.stringify(data));
- }
- });
- */
-};
-
-
View
4 test/base64.js
@@ -2,8 +2,8 @@
* Module dependencies.
*/
-var base64 = require('../lib/base64');
-
+var libpath = process.env.WEIBO_COV ? '../lib-cov' : '../lib';
+var base64 = require(libpath + '/base64');
describe('base64.js', function () {
View
15 test/config.js
@@ -2,10 +2,11 @@
* Module dependencies.
*/
-var tapi = require('../lib/tapi');
+var tapi = require('../');
// init appkey
tapi.init('tsina', '4010445928', 'd119f62bfb70a4ba8d9b68bf14d6e45a', 'oob');
+// tapi.init('tsina', '3538199806', '18cf587d60e11e3c160114fd92dd1f2b', 'oob');
// tapi.init('twitter', 'i1aAkHo2GkZRWbUOQe8zA', 'MCskw4dW5dhWAYKGl3laRVTLzT8jTonOIOpmzEY', 'oob');
// exports.tapi = tapi;
@@ -13,8 +14,8 @@ var users = exports.users = {
tsina: {
blogtype: 'tsina',
authtype: 'oauth',
- oauth_token_key: '10860b4bd170b003381ea6d953f3aba6',
- oauth_token_secret: 'c0af7008eba4d9de8e14a4c61e45b318'
+ oauth_token_key: 'd1ef5fa9aa9fee08fdc6267193a59d6a',
+ oauth_token_secret: '798722589f339cc4e9e0a66a9b53f693'
},
twitter: {
blogtype: 'twitter',
@@ -24,7 +25,7 @@ var users = exports.users = {
}
};
-// var user = users.tsina;
+var user = users.tsina;
// tapi.get_authorization_url(user, null, function (error, auth_url, res) {
// console.log(auth_url);
// console.log(user);
@@ -32,9 +33,9 @@ var users = exports.users = {
// tapi.get_access_token({ blogtype: 'tsina',
// authtype: 'oauth',
-// oauth_verifier: '774897',
-// oauth_token_key: '720a0a45ee131374bc681ac87245c9a9',
-// oauth_token_secret: 'd0c829b62cade4699d66255fca9e6345' }, function(error, auth_user) {
+// oauth_verifier: '838320',
+// oauth_token_key: '9bfc5e567e614e37763f4fecca8d6abb',
+// oauth_token_secret: 'ed003a5d06c52dda0d504abebaa4de46' }, function (error, auth_user) {
// console.log(auth_user);
// });
View
49 test/tapi.test.js
@@ -1,49 +0,0 @@
-/**
- * Module dependencies.
- */
-
-var assert = require('assert')
- , config = require('./config');
-var tapi = config.tapi;
-
-module.exports = {
- 'tapi test': function() {
- var blogtypes = ['tsina'];//, 'twitter'];
- for(var i = 0, len = blogtypes.length; i < len; i++) {
- var blogtype = blogtypes[i];
-
- var user = config.users[blogtype];
-
- tapi.public_timeline({user: {blogtype: blogtype}}, function(error, data) {
- assert.ifError(error);
- assert.ok(data.length > 0, 'public_timeline empty');
- });
-
- tapi.public_timeline({user: user}, function(error, data) {
- assert.ifError(error);
- assert.ok(data.length > 0, '(oauth) public_timeline empty');
- });
-
- var count = 5;
- tapi.public_timeline({user: user, count: count}, function(error, data) {
- assert.ifError(error);
- // assert.equal(data.length, count, blogtype + ' public_timeline count params not effect.');
- });
- var zero_count = 0;
- tapi.public_timeline({user: user, count: zero_count}, function(error, data) {
- assert.ifError(error);
- assert.ok(data.length == 19 || data.length == 20, 'public_timeline zero count params.');
- });
-
- tapi.user_timeline({user: user}, function(error, data){
- assert.ifError(error);
- assert.ok(data.length == 18 || data.length == 19 || data.length == 20, 'user_timeline length is wrong: ' + data.length);
- if(data.length > 1) {
- // 最新的在前面
- assert.ok(String(data[0].id) > String(data[data.length-1].id), 'user_timeline data[0].id not greater than data[-1].id');
- }
- });
-
- }
- }
-};
View
61 test/tapi.js → test/tsina.js
@@ -8,11 +8,11 @@
* Module dependencies.
*/
-var tapi = require('../lib/tapi');
+var tapi = require('../');
var should = require('should');
var users = require('./config').users;
-describe('tapi.js', function () {