| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/tapi.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var utils = require('./utils'); |
| 14 | 1 | var TSinaAPI = require('./tsina'); |
| 15 | 1 | var TQQAPI = require('./tqq'); |
| 16 | 1 | var WeiboAPI = require('./weibo'); |
| 17 | 1 | var GithubAPI = require('./github'); |
| 18 | ||
| 19 | 1 | var TAPI = module.exports = { |
| 20 | TYPES: { | |
| 21 | weibo: WeiboAPI, // api v2.0 | |
| 22 | github: GithubAPI, | |
| 23 | tsina: TSinaAPI, // api v1.0 | |
| 24 | // twitter: TwitterAPI, | |
| 25 | tqq: TQQAPI, | |
| 26 | // tsohu: TSOHUAPI | |
| 27 | }, | |
| 28 | ||
| 29 | enables: {}, | |
| 30 | ||
| 31 | /** | |
| 32 | * Init API options, must init before use it. | |
| 33 | * | |
| 34 | * @param {String} blogtype, blog api type, e.g.: 'weibo', 'tqq', 'github' and so on. | |
| 35 | * @param {String} appkey | |
| 36 | * @param {String} secret | |
| 37 | * @param {String|Object} [oauth_callback] or [oauth_options] | |
| 38 | * - {String} [oauth_callback], oauth callback redirect uri. | |
| 39 | * - {String} [oauth_scope], comma separated list of scopes. e.g.: `status, user` | |
| 40 | * @return {[type]} [description] | |
| 41 | */ | |
| 42 | init: function (blogtype, appkey, secret, oauth_options) { | |
| 43 | 3 | if (!appkey) { |
| 44 | 0 | throw new TypeError('appkey must be set'); |
| 45 | } | |
| 46 | 3 | if (!secret) { |
| 47 | 0 | throw new TypeError('secret must be set'); |
| 48 | } | |
| 49 | 3 | if (typeof oauth_options === 'string') { |
| 50 | 3 | oauth_options = { |
| 51 | oauth_callback: oauth_options | |
| 52 | }; | |
| 53 | } | |
| 54 | 3 | var TypeAPI = this.TYPES[blogtype]; |
| 55 | 3 | if (!TypeAPI) { |
| 56 | 0 | throw new TypeError(blogtype + ' api not exists'); |
| 57 | } | |
| 58 | 3 | var options = { |
| 59 | appkey: appkey, | |
| 60 | secret: secret | |
| 61 | }; | |
| 62 | 3 | options = utils.extend(options, oauth_options); |
| 63 | 3 | var instance = new TypeAPI(options); |
| 64 | 3 | this.enables[blogtype] = instance; |
| 65 | }, | |
| 66 | ||
| 67 | /** | |
| 68 | * Auto detech which API instance to use by user. | |
| 69 | * | |
| 70 | * @param {User} user | |
| 71 | * @return {API} api instance | |
| 72 | */ | |
| 73 | api_dispatch: function (user) { | |
| 74 | 115 | var apiType = user.blogtype || user.blogType; |
| 75 | 115 | return this.enables[apiType]; |
| 76 | }, | |
| 77 | ||
| 78 | /** | |
| 79 | * Get api instance config by user | |
| 80 | * | |
| 81 | * @param {User} user | |
| 82 | * @return {Object} config | |
| 83 | */ | |
| 84 | get_config: function (user) { | |
| 85 | 13 | return this.api_dispatch(user).config; |
| 86 | }, | |
| 87 | ||
| 88 | /** | |
| 89 | * Check api support the method or not. | |
| 90 | * | |
| 91 | * @param {User} user | |
| 92 | * @param {String} method | |
| 93 | * @return {Boolean} true or false | |
| 94 | */ | |
| 95 | support: function (user, method) { | |
| 96 | 13 | return this.get_config(user)['support_' + method] !== false; |
| 97 | }, | |
| 98 | ||
| 99 | /** | |
| 100 | * Process text to display format. | |
| 101 | * | |
| 102 | * @param {User} user | |
| 103 | * @param {Status} status | |
| 104 | * @return {String} | |
| 105 | */ | |
| 106 | process_text: function (user, status) { | |
| 107 | 6 | return this.api_dispatch(user).process_text(status); |
| 108 | }, | |
| 109 | ||
| 110 | /** | |
| 111 | * Utils methods | |
| 112 | */ | |
| 113 | ||
| 114 | _timeline: function (method, user, cursor, callback) { | |
| 115 | 32 | if (typeof cursor === 'function') { |
| 116 | 15 | callback = cursor; |
| 117 | 15 | cursor = null; |
| 118 | } | |
| 119 | 32 | cursor = cursor || {}; |
| 120 | 32 | cursor.count = cursor.count || 20; |
| 121 | 32 | var max_id = cursor.max_id; |
| 122 | 32 | var self = this; |
| 123 | 32 | return self.api_dispatch(user)[method](user, cursor, function (err, result) { |
| 124 | 32 | if (err || !max_id) { |
| 125 | 32 | return callback(err, result); |
| 126 | } | |
| 127 | 0 | max_id = String(max_id); |
| 128 | // ignore the max_id status | |
| 129 | 0 | var needs = []; |
| 130 | 0 | var statuses = result.items || []; |
| 131 | 0 | for (var i = 0, l = statuses.length; i < l; i++) { |
| 132 | 0 | var status = statuses[i]; |
| 133 | 0 | if (status.id === max_id) { |
| 134 | 0 | continue; |
| 135 | } | |
| 136 | 0 | needs.push(status); |
| 137 | } | |
| 138 | 0 | result.items = needs; |
| 139 | 0 | callback(null, result); |
| 140 | }); | |
| 141 | }, | |
| 142 | ||
| 143 | /** | |
| 144 | * Status | |
| 145 | */ | |
| 146 | ||
| 147 | /** | |
| 148 | * Post a status | |
| 149 | * | |
| 150 | * @param {User} user, oauth user. | |
| 151 | * @param {String|Object} status | |
| 152 | * - {String} status, content text. | |
| 153 | * - {Number} [lat], latitude. | |
| 154 | * - {Number} [long], longitude. | |
| 155 | * - {String} [annotations], addtional information. | |
| 156 | * @param {Function(Error, Status)} callback | |
| 157 | * @return {Context} this | |
| 158 | */ | |
| 159 | update: function (user, status, callback) { | |
| 160 | 8 | if (typeof status === 'string') { |
| 161 | 6 | status = {status: status}; |
| 162 | } | |
| 163 | 8 | return this.api_dispatch(user).update(user, status, callback); |
| 164 | }, | |
| 165 | ||
| 166 | /** | |
| 167 | * Post a status contain an image. | |
| 168 | * | |
| 169 | * @param {User} user, oauth user. | |
| 170 | * @param {String|Object} status | |
| 171 | * - {String} status, content text. | |
| 172 | * - {Number} [lat], latitude. | |
| 173 | * - {Number} [long], longitude. | |
| 174 | * - {String} [annotations], addtional information. | |
| 175 | * @param {Object} pic | |
| 176 | * - {Buffer|ReadStream} data | |
| 177 | * - {String} [name], image file name | |
| 178 | * - {String} [content_type], data content type | |
| 179 | * @param {Function(Error, Status)} callback | |
| 180 | * @return {Context} this | |
| 181 | */ | |
| 182 | upload: function (user, status, pic, callback) { | |
| 183 | 6 | if (typeof status === 'string') { |
| 184 | 4 | status = {status: status}; |
| 185 | } | |
| 186 | 6 | return this.api_dispatch(user).upload(user, status, pic, callback); |
| 187 | }, | |
| 188 | ||
| 189 | /** | |
| 190 | * Repost a status. | |
| 191 | * | |
| 192 | * @param {User} user | |
| 193 | * @param {String|Number} id, need to repost status id. | |
| 194 | * @param {String|Object} status | |
| 195 | * - {String} status, content text | |
| 196 | * - {Number} [lat], latitude. | |
| 197 | * - {Number} [long], longitude. | |
| 198 | * - {Boolean} isComment, is comment or not, default is `false`. | |
| 199 | * @param {Function(Error, Status)} callback | |
| 200 | * @return {Context} this | |
| 201 | */ | |
| 202 | repost: function (user, id, status, callback) { | |
| 203 | 4 | if (typeof status === 'string') { |
| 204 | 0 | status = {status: status}; |
| 205 | } | |
| 206 | 4 | id = String(id); |
| 207 | 4 | return this.api_dispatch(user).repost(user, id, status, callback); |
| 208 | }, | |
| 209 | ||
| 210 | /** | |
| 211 | * Remove a status by id. | |
| 212 | * | |
| 213 | * @param {User} user | |
| 214 | * @param {String|Number} id | |
| 215 | * @param {Function(Error, Status)} callback | |
| 216 | * @return {Context} this | |
| 217 | */ | |
| 218 | destroy: function (user, id, callback) { | |
| 219 | 6 | id = String(id); |
| 220 | 6 | return this.api_dispatch(user).destroy(user, id, callback); |
| 221 | }, | |
| 222 | ||
| 223 | // upload_pic_url: function (data, pic, callback, context) { | |
| 224 | // return this.api_dispatch(data).upload_pic_url(data, pic, callback, context); | |
| 225 | // }, | |
| 226 | ||
| 227 | // // id çæ¨ | |
| 228 | // retweet: function (data, callback, context) { | |
| 229 | // return this.api_dispatch(data).retweet(data, callback, context); | |
| 230 | // }, | |
| 231 | ||
| 232 | /** | |
| 233 | * Get a status by id. | |
| 234 | * | |
| 235 | * @param {User} user | |
| 236 | * @param {String|Number} id | |
| 237 | * @param {Function(Error, Status)} callback | |
| 238 | * @return {Context} this | |
| 239 | */ | |
| 240 | show: function (user, id, callback) { | |
| 241 | 2 | return this.api_dispatch(user).show(user, String(id), callback); |
| 242 | }, | |
| 243 | ||
| 244 | /** | |
| 245 | * Get statuses comment count and repost count by ids. | |
| 246 | * | |
| 247 | * @param {User} user | |
| 248 | * @param {String|Array} ids, separate by comma. | |
| 249 | * @param {Function(err, counts)} callback | |
| 250 | * - {String} id | |
| 251 | * - {Number} comments | |
| 252 | * - {Number} reposts | |
| 253 | * @return {Context} this | |
| 254 | */ | |
| 255 | count: function (user, ids, callback) { | |
| 256 | 4 | if (Array.isArray(ids)) { |
| 257 | 0 | ids = ids.join(','); |
| 258 | } | |
| 259 | 4 | return this.api_dispatch(user).count(user, ids, callback); |
| 260 | }, | |
| 261 | ||
| 262 | /** | |
| 263 | * List home timeline statuses. | |
| 264 | * | |
| 265 | * @param {User} user | |
| 266 | * @param {Cursor} [cursor] | |
| 267 | * - {String} since_id | |
| 268 | * - {String} max_id | |
| 269 | * - {String} [since_time], only for tqq | |
| 270 | * - {String} [max_time], only for tqq | |
| 271 | * - {Number} count, default is `20` | |
| 272 | * - {Number} page | |
| 273 | * @param {Function(err, result)} callback | |
| 274 | * {Object} result: | |
| 275 | * - {Array} items, [Status, ...] | |
| 276 | * - {Cursor} cursor | |
| 277 | * - ... | |
| 278 | * @return {Context} this | |
| 279 | */ | |
| 280 | home_timeline: function (user, cursor, callback) { | |
| 281 | 4 | return this._timeline('home_timeline', user, cursor, callback); |
| 282 | }, | |
| 283 | ||
| 284 | /** | |
| 285 | * List home timeline statuses. | |
| 286 | * | |
| 287 | * @param {User} user | |
| 288 | * @param {Cursor} [cursor] | |
| 289 | * - {String} since_id | |
| 290 | * - {String} max_id | |
| 291 | * - {String} [since_time], only for tqq | |
| 292 | * - {String} [max_time], only for tqq | |
| 293 | * - {Number} count, default is `20` | |
| 294 | * - {Number} page | |
| 295 | * @param {Function(err, result)} callback | |
| 296 | * {Object} result: | |
| 297 | * - {Array} items, [Status, ...] | |
| 298 | * - {Cursor} cursor | |
| 299 | * - ... | |
| 300 | * @return {Context} this | |
| 301 | */ | |
| 302 | public_timeline: function (user, cursor, callback) { | |
| 303 | 4 | return this._timeline('public_timeline', user, cursor, callback); |
| 304 | }, | |
| 305 | ||
| 306 | /** | |
| 307 | * List user personal timeline statuses. | |
| 308 | * | |
| 309 | * @param {User} user | |
| 310 | * @param {Cursor} [cursor] | |
| 311 | * - {String} [uid], user id | |
| 312 | * - {String} [screen_name], `user.screen_name`, screen_name or uid must be set at least one. | |
| 313 | * - {String} [since_id] | |
| 314 | * - {String} [max_id] | |
| 315 | * - {String} [since_time], only for tqq | |
| 316 | * - {String} [max_time], only for tqq | |
| 317 | * - {Number} count, default is `20` | |
| 318 | * - {Number} page | |
| 319 | * @param {Function(err, result)} callback | |
| 320 | * {Object} result: | |
| 321 | * - {Array} items, [Status, ...] | |
| 322 | * - {Cursor} cursor | |
| 323 | * - ... | |
| 324 | * @return {Context} this | |
| 325 | */ | |
| 326 | user_timeline: function (user, cursor, callback) { | |
| 327 | 4 | return this._timeline('user_timeline', user, cursor, callback); |
| 328 | }, | |
| 329 | ||
| 330 | /** | |
| 331 | * List @me statuses. | |
| 332 | * | |
| 333 | * @param {User} user | |
| 334 | * @param {Cursor} [cursor] | |
| 335 | * - {String} since_id | |
| 336 | * - {String} max_id | |
| 337 | * - {String} [since_time], only for tqq | |
| 338 | * - {String} [max_time], only for tqq | |
| 339 | * - {Number} count, default is `20` | |
| 340 | * - {Number} page | |
| 341 | * @param {Function(err, result)} callback | |
| 342 | * {Object} result: | |
| 343 | * - {Array} items, [Status, ...] | |
| 344 | * - {Cursor} cursor | |
| 345 | * - ... | |
| 346 | * @return {Context} this | |
| 347 | */ | |
| 348 | mentions: function (user, cursor, callback) { | |
| 349 | 4 | return this._timeline('mentions', user, cursor, callback); |
| 350 | }, | |
| 351 | ||
| 352 | /** | |
| 353 | * List one status's reposted statuses | |
| 354 | * | |
| 355 | * @param {User} user | |
| 356 | * @param {String} id, status's id | |
| 357 | * @param {Cursor} [cursor] | |
| 358 | * - {String} since_id | |
| 359 | * - {String} max_id | |
| 360 | * - {String} [since_time], only for tqq | |
| 361 | * - {String} [max_time], only for tqq | |
| 362 | * - {Number} count, default is `20` | |
| 363 | * - {Number} page | |
| 364 | * - {Number} [filter_by_author], only support by `weibo`; | |
| 365 | * Filter statuses by author type, 0: all, 1: only I followingã2: stranger, default is `0`. | |
| 366 | * @param {Function(err, result)} callback | |
| 367 | * {Object} result: | |
| 368 | * - {Array} items, [Status, ...] | |
| 369 | * - {Cursor} cursor | |
| 370 | * - ... | |
| 371 | * @return {Context} this | |
| 372 | */ | |
| 373 | repost_timeline: function (user, id, cursor, callback) { | |
| 374 | 2 | if (typeof cursor === 'function') { |
| 375 | 0 | callback = cursor; |
| 376 | 0 | cursor = null; |
| 377 | } | |
| 378 | 2 | cursor = cursor || {}; |
| 379 | 2 | cursor.id = id; |
| 380 | 2 | return this._timeline('repost_timeline', user, cursor, callback); |
| 381 | }, | |
| 382 | ||
| 383 | /** | |
| 384 | * Search statuses by query. | |
| 385 | * | |
| 386 | * @param {AccessToken} user | |
| 387 | * @param {String|Object} query | |
| 388 | * - {String} q, query keyword | |
| 389 | * - {String} [long], longitude | |
| 390 | * - {String} [lat], latitude | |
| 391 | * - {String} [radius], radius for longitude and latitude. | |
| 392 | * @param {Cursor} [cursor] | |
| 393 | * - {Number} [count], default is `20` | |
| 394 | * - {Number} [page], default is the first page. | |
| 395 | * @param {Function(err, result)} callback | |
| 396 | * @return {Context} this | |
| 397 | */ | |
| 398 | search: function (user, query, cursor, callback) { | |
| 399 | 1 | if (typeof query === 'string') { |
| 400 | 1 | query = { |
| 401 | q: query | |
| 402 | }; | |
| 403 | } | |
| 404 | 1 | if (typeof cursor === 'function') { |
| 405 | 1 | callback = cursor; |
| 406 | 1 | cursor = null; |
| 407 | } | |
| 408 | 1 | return this.api_dispatch(user).search(user, query, cursor, callback); |
| 409 | }, | |
| 410 | ||
| 411 | /** | |
| 412 | * Favorite | |
| 413 | */ | |
| 414 | ||
| 415 | /** | |
| 416 | * List favorites. | |
| 417 | * | |
| 418 | * @param {User} user | |
| 419 | * @param {Cursor} [cursor] | |
| 420 | * - {String} since_id | |
| 421 | * - {String} max_id | |
| 422 | * - {String} [since_time], only for tqq | |
| 423 | * - {String} [max_time], only for tqq | |
| 424 | * - {Number} count, default is `20` | |
| 425 | * - {Number} page | |
| 426 | * @param {Function(err, result)} callback | |
| 427 | * {Object} result: | |
| 428 | * - {Array} items, [Favorite, ...] | |
| 429 | * - {Cursor} cursor | |
| 430 | * - ... | |
| 431 | * @return {Context} this | |
| 432 | */ | |
| 433 | favorites: function (user, cursor, callback) { | |
| 434 | 2 | return this._timeline('favorites', user, cursor, callback); |
| 435 | }, | |
| 436 | ||
| 437 | /** | |
| 438 | * Show a favorite item by item id. | |
| 439 | * | |
| 440 | * @param {User} user | |
| 441 | * @param {String} id, favorite item's id. | |
| 442 | * @param {Function(err, favorite)} callback | |
| 443 | * @return {Context} this | |
| 444 | */ | |
| 445 | favorite_show: function (user, id, callback) { | |
| 446 | 0 | return this.api_dispatch(user).favorite_show(user, id, callback); |
| 447 | }, | |
| 448 | ||
| 449 | /** | |
| 450 | * Add a status to favorites. | |
| 451 | * | |
| 452 | * @param {User} user | |
| 453 | * @param {String} id, status's id. | |
| 454 | * @param {Function(err, result)} callback | |
| 455 | * - {Object} result | |
| 456 | * - {String} id, relation item's id. | |
| 457 | * - addtional infomation maybe. | |
| 458 | * @return {Context} this | |
| 459 | */ | |
| 460 | favorite_create: function (user, id, callback) { | |
| 461 | 0 | return this.api_dispatch(user).favorite_create(user, id, callback); |
| 462 | }, | |
| 463 | ||
| 464 | /** | |
| 465 | * Remove the status from favorites. | |
| 466 | * | |
| 467 | * @param {User} user | |
| 468 | * @param {String} id, the favorite item's id. | |
| 469 | * @param {Function(err, result)} callback | |
| 470 | * - {Object} result | |
| 471 | * - {String} id, relation item's id. | |
| 472 | * - addtional infomation maybe. | |
| 473 | * @return {Context} this | |
| 474 | */ | |
| 475 | favorite_destroy: function (user, id, callback) { | |
| 476 | 0 | return this.api_dispatch(user).favorite_destroy(user, id, callback); |
| 477 | }, | |
| 478 | ||
| 479 | /** | |
| 480 | * Comment | |
| 481 | */ | |
| 482 | ||
| 483 | /** | |
| 484 | * List comments to my statues | |
| 485 | * | |
| 486 | * @param {User} user | |
| 487 | * @param {Cursor} [cursor] | |
| 488 | * - {String} since_id | |
| 489 | * - {String} max_id | |
| 490 | * - {String} [since_time], only for tqq | |
| 491 | * - {String} [max_time], only for tqq | |
| 492 | * - {Number} count, default is `20` | |
| 493 | * - {Number} page | |
| 494 | * @param {Function(err, result)} callback | |
| 495 | * {Object} result: | |
| 496 | * - {Array} items, [Comment, ...] | |
| 497 | * - {Cursor} cursor | |
| 498 | * - ... | |
| 499 | * @return {Context} this | |
| 500 | */ | |
| 501 | comments_timeline: function (user, cursor, callback) { | |
| 502 | 4 | return this._timeline('comments_timeline', user, cursor, callback); |
| 503 | }, | |
| 504 | ||
| 505 | /** | |
| 506 | * List @me comments | |
| 507 | * | |
| 508 | * @param {User} user | |
| 509 | * @param {Cursor} [cursor] | |
| 510 | * - {String} since_id | |
| 511 | * - {String} max_id | |
| 512 | * - {Number} count, default is `20` | |
| 513 | * - {Number} page | |
| 514 | * @param {Function(err, result)} callback | |
| 515 | * {Object} result: | |
| 516 | * - {Array} items, [Comment, ...] | |
| 517 | * - {Cursor} cursor | |
| 518 | * - ... | |
| 519 | * @return {Context} this | |
| 520 | */ | |
| 521 | comments_mentions: function (user, cursor, callback) { | |
| 522 | 2 | return this._timeline('comments_mentions', user, cursor, callback); |
| 523 | }, | |
| 524 | ||
| 525 | /** | |
| 526 | * List comments post by me | |
| 527 | * | |
| 528 | * @param {User} user | |
| 529 | * @param {Cursor} [cursor] | |
| 530 | * - {String} since_id | |
| 531 | * - {String} max_id | |
| 532 | * - {Number} count, default is `20` | |
| 533 | * - {Number} page | |
| 534 | * - {Number} [filter_by_source], only support by `weibo`; | |
| 535 | * Filter comments by source type, 0: all, 1: come from weibo, 2: come from weiqun, default is `0`. | |
| 536 | * @param {Function(err, result)} callback | |
| 537 | * {Object} result: | |
| 538 | * - {Array} items, [Comment, ...] | |
| 539 | * - {Cursor} cursor | |
| 540 | * - ... | |
| 541 | * @return {Context} this | |
| 542 | */ | |
| 543 | comments_by_me: function (user, cursor, callback) { | |
| 544 | 2 | return this._timeline('comments_by_me', user, cursor, callback); |
| 545 | }, | |
| 546 | ||
| 547 | /** | |
| 548 | * List comments to me | |
| 549 | * | |
| 550 | * @param {User} user | |
| 551 | * @param {Cursor} [cursor] | |
| 552 | * - {String} [since_id] | |
| 553 | * - {String} [max_id] | |
| 554 | * - {Number} [count], default is `20` | |
| 555 | * - {Number} [page] | |
| 556 | * - {Number} [filter_by_author], only support by `weibo`; | |
| 557 | * Filter comments by author type, 0: all, 1: I following, 2: stranger, default is `0`. | |
| 558 | * - {Number} [filter_by_source], only support by `weibo`; | |
| 559 | * Filter comments by source type, 0: all, 1: come from weibo, 2: come from weiqun, default is `0`. | |
| 560 | * @param {Function(err, result)} callback | |
| 561 | * {Object} result: | |
| 562 | * - {Array} items, [Comment, ...] | |
| 563 | * - {Cursor} cursor | |
| 564 | * - ... | |
| 565 | * @return {Context} this | |
| 566 | */ | |
| 567 | comments_to_me: function (user, cursor, callback) { | |
| 568 | 2 | return this._timeline('comments_to_me', user, cursor, callback); |
| 569 | }, | |
| 570 | ||
| 571 | /** | |
| 572 | * List one status's comments | |
| 573 | * | |
| 574 | * @param {User} user | |
| 575 | * @param {String} id, status's id | |
| 576 | * @param {Cursor} [cursor] | |
| 577 | * - {String} since_id | |
| 578 | * - {String} max_id | |
| 579 | * - {String} [since_time], only for tqq | |
| 580 | * - {String} [max_time], only for tqq | |
| 581 | * - {Number} count, default is `20` | |
| 582 | * - {Number} page | |
| 583 | * - {Number} [filter_by_author], only support by `weibo`; | |
| 584 | * Filter comments by author type, 0: all, 1: only I followingã2: stranger, default is `0`. | |
| 585 | * @param {Function(err, result)} callback | |
| 586 | * {Object} result: | |
| 587 | * - {Array} items, [Comment, ...] | |
| 588 | * - {Cursor} cursor | |
| 589 | * - ... | |
| 590 | * @return {Context} this | |
| 591 | */ | |
| 592 | comments: function (user, id, cursor, callback) { | |
| 593 | 2 | if (typeof cursor === 'function') { |
| 594 | 0 | callback = cursor; |
| 595 | 0 | cursor = null; |
| 596 | } | |
| 597 | 2 | cursor = cursor || {}; |
| 598 | 2 | cursor.id = id; |
| 599 | 2 | return this._timeline('comments', user, cursor, callback); |
| 600 | }, | |
| 601 | ||
| 602 | /** | |
| 603 | * post a comment to a status | |
| 604 | * | |
| 605 | * @param {AccessToken} user | |
| 606 | * @param {String} id, status's id | |
| 607 | * @param {String|Object} comment | |
| 608 | * - {String} comment | |
| 609 | * - {Number} [comment_ori], same comment to the original status when comment on a repost status, | |
| 610 | * 0: no, 1: yes, default is `0`. | |
| 611 | * @param {Function(err, result)} callback | |
| 612 | * - {Object} result | |
| 613 | * - {String} id, the comment id | |
| 614 | * @return {Context} this | |
| 615 | */ | |
| 616 | comment_create: function (user, id, comment, callback) { | |
| 617 | 7 | if (typeof comment === 'string') { |
| 618 | 7 | comment = {comment: comment}; |
| 619 | } | |
| 620 | 7 | return this.api_dispatch(user).comment_create(user, id, comment, callback); |
| 621 | }, | |
| 622 | ||
| 623 | /** | |
| 624 | * reply to a comment | |
| 625 | * @param {AccessToken} user | |
| 626 | * @param {String} cid, comment's id | |
| 627 | * @param {String} id, status's id | |
| 628 | * @param {String|Object} comment | |
| 629 | * - {String} comment | |
| 630 | * - {Number} without_mention, don't auto add `'reply@username'` to comment text or not, | |
| 631 | * 0: yes, 1: no, default is `0`, won't auto add. | |
| 632 | * - {Number} [comment_ori], same comment to the original status when comment on a repost status, | |
| 633 | * 0: no, 1: yes, default is `0`. | |
| 634 | * @param {Function(err, result)} callback | |
| 635 | * @return {Context} this | |
| 636 | */ | |
| 637 | comment_reply: function (user, cid, id, comment, callback) { | |
| 638 | 6 | if (typeof comment === 'string') { |
| 639 | 6 | comment = {comment: comment}; |
| 640 | } | |
| 641 | 6 | return this.api_dispatch(user).comment_reply(user, cid, id, comment, callback); |
| 642 | }, | |
| 643 | ||
| 644 | /** | |
| 645 | * remove a comment | |
| 646 | * @param {AccessToken} user | |
| 647 | * @param {String} cid, comment's id | |
| 648 | * @param {Function(err, result)} callback | |
| 649 | * @return {Context} this | |
| 650 | */ | |
| 651 | comment_destroy: function (user, cid, callback) { | |
| 652 | 1 | return this.api_dispatch(user).comment_destroy(user, cid, callback); |
| 653 | }, | |
| 654 | ||
| 655 | /** | |
| 656 | * OAuth | |
| 657 | */ | |
| 658 | ||
| 659 | /** | |
| 660 | * Get authorization token and login url. | |
| 661 | * | |
| 662 | * @param {Object} user | |
| 663 | * - {String} blogtype, 'weibo' or other blog type, | |
| 664 | * - {String} oauth_callback, 'login callback url' or 'oob' | |
| 665 | * @param {Function(err, auth_info)} callback | |
| 666 | * - {Object} auth_info | |
| 667 | * - {String} auth_url: 'http://xxxx/auth?xxx', | |
| 668 | * - {String} oauth_token: $oauth_token, | |
| 669 | * - {String} oauth_token_secret: $oauth_token_secret | |
| 670 | * @return {Context} this, blogType api. | |
| 671 | */ | |
| 672 | get_authorization_url: function (user, callback) { | |
| 673 | 6 | return this.api_dispatch(user).get_authorization_url(user, callback); |
| 674 | }, | |
| 675 | ||
| 676 | /** | |
| 677 | * Get access token. | |
| 678 | * | |
| 679 | * @param {Object} user | |
| 680 | * - {String} blogtype | |
| 681 | * - {String} oauth_token, authorization `oauth_token` | |
| 682 | * - {String} oauth_verifier, authorization `oauth_verifier` | |
| 683 | * - {String} oauth_token_secret, request token secret | |
| 684 | * @param {Function(err, token)} callback | |
| 685 | * - {Object} token | |
| 686 | * - {String} oauth_token | |
| 687 | * - {String} oauth_token_secret | |
| 688 | * @return {Context} this | |
| 689 | */ | |
| 690 | get_access_token: function (user, callback) { | |
| 691 | 3 | return this.api_dispatch(user).get_access_token(user, callback); |
| 692 | }, | |
| 693 | ||
| 694 | /** | |
| 695 | * User | |
| 696 | */ | |
| 697 | ||
| 698 | /** | |
| 699 | * Get user profile infomation by access token. | |
| 700 | * | |
| 701 | * @param {Object} user | |
| 702 | * - {String} blogtype | |
| 703 | * - {String} oauth_token, access oauth token | |
| 704 | * - {String} [oauth_token_secret], access oauth token secret, oauth v2 don't need this param. | |
| 705 | * @param {Function(err, User)} callback | |
| 706 | * @return {Context} this | |
| 707 | */ | |
| 708 | verify_credentials: function (user, callback) { | |
| 709 | 3 | return this.api_dispatch(user).verify_credentials(user, callback); |
| 710 | }, | |
| 711 | ||
| 712 | /** | |
| 713 | * Get user profile infomation by uid. | |
| 714 | * @param {Object} user | |
| 715 | * - {String} blogtype | |
| 716 | * - {String} oauth_token, access token | |
| 717 | * - {String} [oauth_token_secret], access oauth token secret, oauth v2 don't need this param. | |
| 718 | * @param {String} [uid], user id | |
| 719 | * @param {String} [screen_name], user screen_name | |
| 720 | * uid and screen_name MUST set one. | |
| 721 | * @param {Function(err, User)} callback | |
| 722 | * @return {Context} this | |
| 723 | */ | |
| 724 | user_show: function (user, uid, screen_name, callback) { | |
| 725 | 4 | if (typeof screen_name === 'function') { |
| 726 | 3 | callback = screen_name; |
| 727 | 3 | screen_name = null; |
| 728 | } | |
| 729 | 4 | return this.api_dispatch(user).user_show(user, uid, screen_name, callback); |
| 730 | }, | |
| 731 | ||
| 732 | rate_limit_status: function (user, callback) { | |
| 733 | 0 | return this.api_dispatch(user).rate_limit_status(user, callback); |
| 734 | }, | |
| 735 | ||
| 736 | /* | |
| 737 | * id false int64/string ç¨æ·ID(int64)æè æµç§°(string)ãè¯¥åæ°ä¸ºä¸ä¸ªREST飿 ¼åæ°ãè°ç¨ç¤ºä¾è§æ³¨æäºé¡¹ | |
| 738 | * user_id false int64 ç¨æ·IDï¼ä¸»è¦æ¯ç¨æ¥åºåç¨æ·IDè·å¾®åæµç§°ãå½å¾®åæµç§°ä¸ºæ°å导è´åç¨æ·IDäº§çæ§ä¹ï¼ç¹å«æ¯å½å¾®åæµç§°åç¨æ·ID䏿 ·çæ¶åï¼å»ºè®®ä½¿ç¨è¯¥åæ° | |
| 739 | * screen_name false string å¾®åæµç§°ï¼ä¸»è¦æ¯ç¨æ¥åºåç¨æ·UIDè·å¾®åæµç§°ï¼å½äºè 䏿 ·èäº§çæ§ä¹çæ¶åï¼å»ºè®®ä½¿ç¨è¯¥åæ° | |
| 740 | * id, user_id, screen_name å¯ä»¥ä»»éä¸ä¸ªåæ°ï¼å¨3个é½ä¸æä¾çæ åµä¸ï¼ç³»ç»è¿åå½åç»å½ç¨æ·çå ³æ³¨å表 | |
| 741 | * | |
| 742 | * cursor false int ç¨äºå页请æ±ï¼è¯·æ±ç¬¬1页cursorä¼ -1ï¼å¨è¿åçç»æä¸ä¼å¾å°next_cursoråæ®µï¼è¡¨ç¤ºä¸ä¸é¡µçcursorãnext_cursor为0表示已ç»å°è®°å½æ«å°¾ã | |
| 743 | * count false intï¼é»è®¤20ï¼æå¤§200 æ¯é¡µè¿åçæå¤§è®°å½æ°ï¼æå¤§ä¸è½è¶ è¿200ï¼é»è®¤ä¸º20ã | |
| 744 | */ | |
| 745 | friends: function (data, callback, context) { | |
| 746 | 0 | return this.api_dispatch(data).friends(data, callback, context); |
| 747 | }, | |
| 748 | ||
| 749 | // åfriends | |
| 750 | followers: function (data, callback, context) { | |
| 751 | 0 | return this.api_dispatch(data).followers(data, callback, context); |
| 752 | }, | |
| 753 | ||
| 754 | }; | |
| 755 | ||
| 756 | 1 | TAPI.friends_timeline = TAPI.home_timeline; |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/utils.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var STRING_FORMAT_REGEX = /\{\{([\w\s\.\'\"\(\),-\[\]]+)?\}\}/g; |
| 14 | 1 | exports.format = function (s, values) { |
| 15 | 94 | return s.replace(STRING_FORMAT_REGEX, function (match, key) { |
| 16 | 39 | return values[key]; |
| 17 | }); | |
| 18 | }; | |
| 19 | ||
| 20 | /** | |
| 21 | * æ ¼å¼åå符串 | |
| 22 | * eg: | |
| 23 | * '{0}天æ{1}ä¸ªå°æ¶'.format([1, 24]) | |
| 24 | * or | |
| 25 | * '{{day}}天æ{{hour}}ä¸ªå°æ¶'.format({day:1, hour:24}}) | |
| 26 | * @param {Object} values | |
| 27 | */ | |
| 28 | 1 | String.prototype.format = function (values) { |
| 29 | 84 | return exports.format(this, values); |
| 30 | }; | |
| 31 | ||
| 32 | 1 | var b64_hmac_sha1 = require('./sha1').b64_hmac_sha1; |
| 33 | 1 | var crypto = require('crypto'); |
| 34 | ||
| 35 | 1 | var querystring = { |
| 36 | parse: function (s) { | |
| 37 | 7 | var qs = {}; |
| 38 | 7 | if (typeof s !== 'string') { |
| 39 | 2 | return qs; |
| 40 | } | |
| 41 | 5 | var pairs = s.split('&'); |
| 42 | 5 | for (var i = 0, len = pairs.length; i < len; i++) { |
| 43 | 8 | var pair = pairs[i].split('=', 2); |
| 44 | 8 | if (pair.length !== 2) { |
| 45 | 3 | continue; |
| 46 | } | |
| 47 | 5 | var key = pair[0].trim(); |
| 48 | 5 | if (!key) { |
| 49 | 1 | continue; |
| 50 | } | |
| 51 | 4 | qs[decodeURIComponent(key)] = decodeURIComponent(pair[1]); |
| 52 | } | |
| 53 | 5 | return qs; |
| 54 | }, | |
| 55 | stringify: function (data) { | |
| 56 | 5 | var pairs = []; |
| 57 | 5 | data = data || {}; |
| 58 | 5 | for (var k in data) { |
| 59 | 7 | pairs.push(encodeURIComponent(k) + '=' + encodeURIComponent('' + data[k])); |
| 60 | } | |
| 61 | 5 | return pairs.join('&'); |
| 62 | } | |
| 63 | }; | |
| 64 | ||
| 65 | 1 | function urljoin(url, params) { |
| 66 | 5 | if (typeof params === 'object') { |
| 67 | 4 | params = querystring.stringify(params); |
| 68 | } | |
| 69 | 5 | if (!params) { |
| 70 | 2 | return url; |
| 71 | } | |
| 72 | 3 | if (url.indexOf('?') < 0) { |
| 73 | 1 | url += '?'; |
| 74 | } else { | |
| 75 | 2 | url += '&'; |
| 76 | } | |
| 77 | 3 | return url + params; |
| 78 | } | |
| 79 | ||
| 80 | 1 | function base64HmacSha1(baseString, key) { |
| 81 | 44 | if (b64_hmac_sha1) { |
| 82 | 44 | return b64_hmac_sha1(key, baseString); |
| 83 | } | |
| 84 | 0 | return new crypto.Hmac().init("sha1", key).update(baseString).digest("base64"); |
| 85 | } | |
| 86 | ||
| 87 | // HTML ç¼ç | |
| 88 | // test: hard code testing ããã '"!@#$%^&*()-=+ |][ {} ~` &&&&& < & C++ c++c + +c & | |
| 89 | 1 | function htmlencode(str) { |
| 90 | 0 | if (!str) { return ''; } |
| 91 | 0 | return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); |
| 92 | } | |
| 93 | ||
| 94 | 1 | exports.extend = function (destination) { |
| 95 | 8 | for (var i = 1, len = arguments.length; i < len; i++) { |
| 96 | 12 | var source = arguments[i]; |
| 97 | 12 | if (!source) { |
| 98 | 1 | continue; |
| 99 | } | |
| 100 | 11 | for (var property in source) { |
| 101 | 109 | destination[property] = source[property]; |
| 102 | } | |
| 103 | } | |
| 104 | 8 | return destination; |
| 105 | }; | |
| 106 | ||
| 107 | 1 | exports.STRING_FORMAT_REGEX = STRING_FORMAT_REGEX; |
| 108 | 1 | exports.querystring = querystring; |
| 109 | 1 | exports.base64HmacSha1 = base64HmacSha1; |
| 110 | 1 | exports.urljoin = urljoin; |
| 111 | 1 | exports.htmlencode = htmlencode; |
| 112 | ||
| 113 | 1 | var MIME_TYPES = { |
| 114 | 'jpg': 'image/jpeg', | |
| 115 | 'jpeg': 'image/jpeg', | |
| 116 | 'gif': 'image/gif', | |
| 117 | 'png': 'image/png', | |
| 118 | 'bmp': 'image/bmp', | |
| 119 | }; | |
| 120 | ||
| 121 | 1 | var BIN_TYPE = 'application/octet-stream'; |
| 122 | ||
| 123 | 1 | exports.mimeLookup = function (name, fallback) { |
| 124 | 19 | var ext = name.replace(/.*[\.\/]/, '').toLowerCase(); |
| 125 | 19 | return MIME_TYPES[ext] || fallback || BIN_TYPE; |
| 126 | }; | |
| 127 | ||
| 128 | /** | |
| 129 | * Escape the given string of `html`. | |
| 130 | * | |
| 131 | * @param {String} html | |
| 132 | * @return {String} | |
| 133 | */ | |
| 134 | 1 | exports.escape = function (html) { |
| 135 | 3 | return String(html) |
| 136 | .replace(/&(?!\w+;)/g, '&') | |
| 137 | .replace(/</g, '<') | |
| 138 | .replace(/>/g, '>') | |
| 139 | .replace(/"/g, '"'); | |
| 140 | }; | |
| 141 | ||
| 142 | /** | |
| 143 | * Remove all html tags. | |
| 144 | * | |
| 145 | * @param {String} s | |
| 146 | * @return {String} | |
| 147 | */ | |
| 148 | 1 | exports.removeHTML = function (s) { |
| 149 | 8 | return s.replace(/(<.*?>)/ig, ''); |
| 150 | }; |
| Line | Hits | Source |
|---|---|---|
| 1 | /* | |
| 2 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
| 3 | * in FIPS PUB 180-1 | |
| 4 | * Version 2.1a Copyright Paul Johnston 2000 - 2002. | |
| 5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
| 6 | * Distributed under the BSD License | |
| 7 | * See http://pajhome.org.uk/crypt/md5 for details. | |
| 8 | */ | |
| 9 | ||
| 10 | 1 | (function () { |
| 11 | ||
| 12 | 1 | var root = this; // window on browser |
| 13 | 1 | var exports; |
| 14 | 1 | var crypto; |
| 15 | 1 | if (typeof module === 'undefined') { |
| 16 | 0 | root.weibo = root.weibo || {}; |
| 17 | 0 | exports = root.weibo.sha1 = {}; |
| 18 | } else { | |
| 19 | 1 | exports = module.exports; |
| 20 | } | |
| 21 | ||
| 22 | /* | |
| 23 | * Configurable variables. You may need to tweak these to be compatible with | |
| 24 | * the server-side, but the defaults work in most cases. | |
| 25 | */ | |
| 26 | 1 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ |
| 27 | 1 | var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ |
| 28 | 1 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ |
| 29 | ||
| 30 | /* | |
| 31 | * These are the functions you'll usually want to call | |
| 32 | * They take string arguments and return either hex or base-64 encoded strings | |
| 33 | */ | |
| 34 | 1 | function hex_sha1(s) { |
| 35 | 0 | return binb2hex(core_sha1(str2binb(s), s.length * chrsz)); |
| 36 | } | |
| 37 | 1 | exports.hex_sha1 = hex_sha1; |
| 38 | ||
| 39 | 1 | function b64_sha1(s) { |
| 40 | 0 | return binb2b64(core_sha1(str2binb(s), s.length * chrsz)); |
| 41 | } | |
| 42 | 1 | exports.b64_sha1 = b64_sha1; |
| 43 | ||
| 44 | 1 | function str_sha1(s) { |
| 45 | 0 | return binb2str(core_sha1(str2binb(s), s.length * chrsz)); |
| 46 | } | |
| 47 | 1 | exports.str_sha1 = str_sha1; |
| 48 | ||
| 49 | 1 | function hex_hmac_sha1(key, data) { |
| 50 | 0 | return binb2hex(core_hmac_sha1(key, data)); |
| 51 | } | |
| 52 | 1 | exports.hex_hmac_sha1 = hex_hmac_sha1; |
| 53 | ||
| 54 | 1 | function b64_hmac_sha1(key, data) { |
| 55 | 47 | return binb2b64(core_hmac_sha1(key, data)); |
| 56 | } | |
| 57 | 1 | exports.b64_hmac_sha1 = b64_hmac_sha1; |
| 58 | ||
| 59 | 1 | function str_hmac_sha1(key, data) { |
| 60 | 0 | return binb2str(core_hmac_sha1(key, data)); |
| 61 | } | |
| 62 | 1 | exports.str_hmac_sha1 = str_hmac_sha1; |
| 63 | ||
| 64 | /* | |
| 65 | * Perform a simple self-test to see if the VM is working | |
| 66 | */ | |
| 67 | 1 | function sha1_vm_test() { |
| 68 | 0 | return hex_sha1("abc") === "a9993e364706816aba3e25717850c26c9cd0d89d"; |
| 69 | } | |
| 70 | ||
| 71 | /* | |
| 72 | * Calculate the SHA-1 of an array of big-endian words, and a bit length | |
| 73 | */ | |
| 74 | 1 | function core_sha1(x, len) { |
| 75 | /* append padding */ | |
| 76 | 133 | x[len >> 5] |= 0x80 << (24 - len % 32); |
| 77 | 133 | x[((len + 64 >> 9) << 4) + 15] = len; |
| 78 | ||
| 79 | 133 | var w = new Array(80); |
| 80 | 133 | var a = 1732584193; |
| 81 | 133 | var b = -271733879; |
| 82 | 133 | var c = -1732584194; |
| 83 | 133 | var d = 271733878; |
| 84 | 133 | var e = -1009589776; |
| 85 | ||
| 86 | 133 | for (var i = 0; i < x.length; i += 16) { |
| 87 | 538 | var olda = a; |
| 88 | 538 | var oldb = b; |
| 89 | 538 | var oldc = c; |
| 90 | 538 | var oldd = d; |
| 91 | 538 | var olde = e; |
| 92 | ||
| 93 | 538 | for (var j = 0; j < 80; j++) { |
| 94 | 43040 | if (j < 16) { |
| 95 | 8608 | w[j] = x[i + j]; |
| 96 | } | |
| 97 | else { | |
| 98 | 34432 | w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); |
| 99 | } | |
| 100 | 43040 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), |
| 101 | safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
| 102 | 43040 | e = d; |
| 103 | 43040 | d = c; |
| 104 | 43040 | c = rol(b, 30); |
| 105 | 43040 | b = a; |
| 106 | 43040 | a = t; |
| 107 | } | |
| 108 | ||
| 109 | 538 | a = safe_add(a, olda); |
| 110 | 538 | b = safe_add(b, oldb); |
| 111 | 538 | c = safe_add(c, oldc); |
| 112 | 538 | d = safe_add(d, oldd); |
| 113 | 538 | e = safe_add(e, olde); |
| 114 | } | |
| 115 | 133 | return [ a, b, c, d, e ]; |
| 116 | ||
| 117 | } | |
| 118 | ||
| 119 | /* | |
| 120 | * Perform the appropriate triplet combination function for the current | |
| 121 | * iteration | |
| 122 | */ | |
| 123 | 1 | function sha1_ft(t, b, c, d) { |
| 124 | 43040 | if (t < 20) { |
| 125 | 10760 | return (b & c) | ((~b) & d); |
| 126 | } | |
| 127 | 32280 | if (t < 40) { |
| 128 | 10760 | return b ^ c ^ d; |
| 129 | } | |
| 130 | 21520 | if (t < 60) { |
| 131 | 10760 | return (b & c) | (b & d) | (c & d); |
| 132 | } | |
| 133 | 10760 | return b ^ c ^ d; |
| 134 | } | |
| 135 | ||
| 136 | /* | |
| 137 | * Determine the appropriate additive constant for the current iteration | |
| 138 | */ | |
| 139 | 1 | function sha1_kt(t) { |
| 140 | 43040 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : |
| 141 | (t < 60) ? -1894007588 : -899497514; | |
| 142 | } | |
| 143 | ||
| 144 | /* | |
| 145 | * Calculate the HMAC-SHA1 of a key and some data | |
| 146 | */ | |
| 147 | 1 | function core_hmac_sha1(key, data) { |
| 148 | 47 | var bkey = str2binb(key); |
| 149 | 47 | if (bkey.length > 16) { |
| 150 | 39 | bkey = core_sha1(bkey, key.length * chrsz); |
| 151 | } | |
| 152 | ||
| 153 | 47 | var ipad = new Array(16), opad = new Array(16); |
| 154 | 47 | for(var i = 0; i < 16; i++) { |
| 155 | 752 | ipad[i] = bkey[i] ^ 0x36363636; |
| 156 | 752 | opad[i] = bkey[i] ^ 0x5C5C5C5C; |
| 157 | } | |
| 158 | ||
| 159 | 47 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); |
| 160 | 47 | return core_sha1(opad.concat(hash), 512 + 160); |
| 161 | } | |
| 162 | ||
| 163 | /* | |
| 164 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
| 165 | * to work around bugs in some JS interpreters. | |
| 166 | */ | |
| 167 | 1 | function safe_add(x, y) { |
| 168 | 174850 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); |
| 169 | 174850 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); |
| 170 | 174850 | return (msw << 16) | (lsw & 0xFFFF); |
| 171 | } | |
| 172 | ||
| 173 | /* | |
| 174 | * Bitwise rotate a 32-bit number to the left. | |
| 175 | */ | |
| 176 | 1 | function rol(num, cnt) { |
| 177 | 120512 | return (num << cnt) | (num >>> (32 - cnt)); |
| 178 | } | |
| 179 | ||
| 180 | /* | |
| 181 | * Convert an 8-bit or 16-bit string to an array of big-endian words | |
| 182 | * In 8-bit function, characters >255 have their hi-byte silently ignored. | |
| 183 | */ | |
| 184 | 1 | function str2binb(str) { |
| 185 | 94 | var bin = Array(); |
| 186 | 94 | var mask = (1 << chrsz) - 1; |
| 187 | 94 | for(var i = 0; i < str.length * chrsz; i += chrsz) |
| 188 | 21403 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); |
| 189 | 94 | return bin; |
| 190 | } | |
| 191 | 1 | exports.str2binb = str2binb; |
| 192 | ||
| 193 | /* | |
| 194 | * Convert an array of big-endian words to a string | |
| 195 | */ | |
| 196 | 1 | function binb2str(bin) { |
| 197 | 0 | var str = ""; |
| 198 | 0 | var mask = (1 << chrsz) - 1; |
| 199 | 0 | for(var i = 0; i < bin.length * 32; i += chrsz) |
| 200 | 0 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); |
| 201 | 0 | return str; |
| 202 | } | |
| 203 | 1 | exports.binb2str = binb2str; |
| 204 | ||
| 205 | /* | |
| 206 | * Convert an array of big-endian words to a hex string. | |
| 207 | */ | |
| 208 | 1 | function binb2hex(binarray) { |
| 209 | 0 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; |
| 210 | 0 | var str = ""; |
| 211 | 0 | for(var i = 0; i < binarray.length * 4; i++) { |
| 212 | 0 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + |
| 213 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | |
| 214 | } | |
| 215 | 0 | return str; |
| 216 | } | |
| 217 | 1 | exports.binb2hex = binb2hex; |
| 218 | ||
| 219 | /* | |
| 220 | * Convert an array of big-endian words to a base-64 string | |
| 221 | */ | |
| 222 | 1 | function binb2b64(binarray) { |
| 223 | 47 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 224 | 47 | var str = ""; |
| 225 | 47 | for(var i = 0; i < binarray.length * 4; i += 3) { |
| 226 | 329 | var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) |
| 227 | | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | |
| 228 | | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); | |
| 229 | 329 | for(var j = 0; j < 4; j++) |
| 230 | { | |
| 231 | 1363 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; |
| 232 | 1269 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); |
| 233 | } | |
| 234 | } | |
| 235 | 47 | return str; |
| 236 | } | |
| 237 | 1 | exports.binb2b64 = binb2b64; |
| 238 | ||
| 239 | })(); |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/tsina.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var inherits = require('util').inherits; |
| 14 | 1 | var utils = require('./utils'); |
| 15 | 1 | var EventProxy = require('eventproxy').EventProxy; |
| 16 | 1 | var fs = require('fs'); |
| 17 | 1 | var path = require('path'); |
| 18 | 1 | var TBase = require('./tbase'); |
| 19 | 1 | var weiboutil = require('./weibo_util'); |
| 20 | ||
| 21 | ||
| 22 | 1 | function TSinaAPI(options) { |
| 23 | 0 | TSinaAPI.super_.call(this); |
| 24 | ||
| 25 | 0 | var config = utils.extend({}, options, { |
| 26 | host: 'http://api.t.sina.com.cn' | |
| 27 | }); | |
| 28 | 0 | this.init(config); |
| 29 | } | |
| 30 | ||
| 31 | 1 | inherits(TSinaAPI, TBase); |
| 32 | 1 | module.exports = TSinaAPI; |
| 33 | ||
| 34 | 1 | TSinaAPI.prototype.format_authorization_url = function (params) { |
| 35 | 0 | params.forcelogin = 'true'; |
| 36 | 0 | return TSinaAPI.super_.prototype.format_authorization_url.call(this, params); |
| 37 | }; | |
| 38 | ||
| 39 | 1 | TSinaAPI.prototype.get_result_items = function (data, playload, args) { |
| 40 | 0 | return data.results || data.users || data; |
| 41 | }; | |
| 42 | ||
| 43 | 1 | TSinaAPI.prototype.format_search_status = function (status, args) { |
| 44 | 0 | if (!status.user && status.from_user) { // search data |
| 45 | 0 | status.user = { |
| 46 | screen_name: status.from_user, | |
| 47 | profile_image_url: status.profile_image_url, | |
| 48 | id: status.from_user_id | |
| 49 | }; | |
| 50 | 0 | delete status.profile_image_url; |
| 51 | 0 | delete status.from_user; |
| 52 | 0 | delete status.from_user_id; |
| 53 | } | |
| 54 | 0 | return this.format_status(status, args); |
| 55 | }; | |
| 56 | ||
| 57 | 1 | TSinaAPI.prototype.format_status = function (status, args) { |
| 58 | 0 | if (status.user) { |
| 59 | 0 | status.user = this.format_user(status.user, args); |
| 60 | } | |
| 61 | ||
| 62 | 0 | if (status.retweeted_status) { |
| 63 | 0 | status.retweeted_status = this.format_status(status.retweeted_status, args); |
| 64 | } | |
| 65 | 0 | if (status.user) { |
| 66 | 0 | status.t_url = 'http://weibo.com/' + status.user.id + '/' + weiboutil.mid2url(status.mid); |
| 67 | } | |
| 68 | 0 | return status; |
| 69 | }; | |
| 70 | ||
| 71 | 1 | TSinaAPI.prototype.format_user = function (user, args) { |
| 72 | 0 | user.t_url = 'http://weibo.com/' + (user.domain || user.id); |
| 73 | 0 | if (user.status) { |
| 74 | 0 | user.status = this.format_status(user.status, args); |
| 75 | 0 | if (!user.status.t_url) { |
| 76 | 0 | user.status.t_url = 'http://weibo.com/' + user.id + '/' + weiboutil.mid2url(user.status.mid || user.status.id); |
| 77 | } | |
| 78 | } | |
| 79 | 0 | return user; |
| 80 | }; | |
| 81 | ||
| 82 | 1 | TSinaAPI.prototype.format_comment = function (comment, args) { |
| 83 | 0 | comment.user = this.format_user(comment.user, args); |
| 84 | 0 | comment.status = this.format_status(comment.status, args); |
| 85 | 0 | return comment; |
| 86 | }; | |
| 87 | ||
| 88 | 1 | TSinaAPI.prototype.format_message = function (message, args) { |
| 89 | 0 | message.sender = this.format_user(message.sender, args); |
| 90 | 0 | message.recipient = this.format_user(message.recipient, args); |
| 91 | 0 | return message; |
| 92 | }; | |
| 93 | ||
| 94 | 1 | TSinaAPI.prototype.format_emotion = function (emotion, args) { |
| 95 | 0 | emotion.title = emotion.phrase.substring(1, emotion.phrase.length - 1); |
| 96 | 0 | return emotion; |
| 97 | }; | |
| 98 | ||
| 99 | ||
| 100 | // rate_limit_status: function (data, callback, context) { | |
| 101 | // var params = { | |
| 102 | // url: this.config.rate_limit_status, | |
| 103 | // type: 'GET', | |
| 104 | // play_load: 'rate', | |
| 105 | // data: data | |
| 106 | // }; | |
| 107 | // this._send_request(params, callback, context); | |
| 108 | // }, | |
| 109 | ||
| 110 | // // since_id, max_id, count, page | |
| 111 | // friends_timeline: function (data, callback, context) { | |
| 112 | // var params = { | |
| 113 | // url: this.config.friends_timeline, | |
| 114 | // type: 'GET', | |
| 115 | // play_load: 'status', | |
| 116 | // data: data | |
| 117 | // }; | |
| 118 | // this._send_request(params, callback, context); | |
| 119 | // }, | |
| 120 | ||
| 121 | // // id, user_id, screen_name, since_id, max_id, count, page | |
| 122 | // user_timeline: function (data, callback, context) { | |
| 123 | // var params = { | |
| 124 | // url: this.config.user_timeline, | |
| 125 | // type: 'GET', | |
| 126 | // play_load: 'status', | |
| 127 | // data: data | |
| 128 | // }; | |
| 129 | // this._send_request(params, callback, context); | |
| 130 | // }, | |
| 131 | ||
| 132 | // // id, count, page | |
| 133 | // comments_timeline: function (data, callback, context) { | |
| 134 | // var params = { | |
| 135 | // url: this.config.comments_timeline, | |
| 136 | // type: 'GET', | |
| 137 | // play_load: 'comment', | |
| 138 | // data: data | |
| 139 | // }; | |
| 140 | // this._send_request(params, callback, context); | |
| 141 | // }, | |
| 142 | ||
| 143 | // // id, since_id, max_id, count, page | |
| 144 | // repost_timeline: function (data, callback, context) { | |
| 145 | // var params = { | |
| 146 | // url: this.config.repost_timeline, | |
| 147 | // type: 'GET', | |
| 148 | // play_load: 'status', | |
| 149 | // data: data | |
| 150 | // }; | |
| 151 | // this._send_request(params, callback, context); | |
| 152 | // }, | |
| 153 | ||
| 154 | // // since_id, max_id, count, page | |
| 155 | // mentions: function (data, callback, context){ | |
| 156 | // var params = { | |
| 157 | // url: this.config.mentions, | |
| 158 | // type: 'GET', | |
| 159 | // play_load: 'status', | |
| 160 | // data: data | |
| 161 | // }; | |
| 162 | // this._send_request(params, callback, context); | |
| 163 | // }, | |
| 164 | ||
| 165 | // // id, user_id, screen_name, cursor, count | |
| 166 | // followers: function (data, callback, context) { | |
| 167 | // var params = { | |
| 168 | // url: this.config.followers, | |
| 169 | // type: 'GET', | |
| 170 | // play_load: 'user', | |
| 171 | // data: data | |
| 172 | // }; | |
| 173 | // this._send_request(params, callback, context); | |
| 174 | // }, | |
| 175 | ||
| 176 | // public_timeline: function (data, callback, context) { | |
| 177 | // var params = { | |
| 178 | // url: this.config.public_timeline, | |
| 179 | // type: 'GET', | |
| 180 | // play_load: 'status', | |
| 181 | // data: data | |
| 182 | // }; | |
| 183 | // this._send_request(params, callback, context); | |
| 184 | // }, | |
| 185 | ||
| 186 | // // id, user_id, screen_name, cursor, count | |
| 187 | // friends: function (data, callback, context) { | |
| 188 | // var params = { | |
| 189 | // url: this.config.friends, | |
| 190 | // type: 'GET', | |
| 191 | // play_load: 'user', | |
| 192 | // data: data | |
| 193 | // }; | |
| 194 | // this._send_request(params, callback, context); | |
| 195 | // }, | |
| 196 | ||
| 197 | // // page | |
| 198 | // favorites: function (data, callback, context) { | |
| 199 | // var params = { | |
| 200 | // url: this.config.favorites, | |
| 201 | // type: 'GET', | |
| 202 | // play_load: 'status', | |
| 203 | // data: data | |
| 204 | // }; | |
| 205 | // this._send_request(params, callback, context); | |
| 206 | // }, | |
| 207 | ||
| 208 | // // id | |
| 209 | // favorites_create: function (data, callback, context) { | |
| 210 | // var params = { | |
| 211 | // url: this.config.favorites_create, | |
| 212 | // type: 'POST', | |
| 213 | // play_load: 'status', | |
| 214 | // data: data | |
| 215 | // }; | |
| 216 | // this._send_request(params, callback, context); | |
| 217 | // }, | |
| 218 | ||
| 219 | // // id | |
| 220 | // favorites_destroy: function (data, callback, context) { | |
| 221 | // var params = { | |
| 222 | // url: this.config.favorites_destroy, | |
| 223 | // type: 'POST', | |
| 224 | // play_load: 'status', | |
| 225 | // data: data | |
| 226 | // }; | |
| 227 | // this._send_request(params, callback, context); | |
| 228 | // }, | |
| 229 | ||
| 230 | // // ids | |
| 231 | // counts: function (data, callback, context) { | |
| 232 | // var params = { | |
| 233 | // url: this.config.counts, | |
| 234 | // type: 'GET', | |
| 235 | // play_load: 'count', | |
| 236 | // data: data | |
| 237 | // }; | |
| 238 | // this._send_request(params, callback, context); | |
| 239 | // }, | |
| 240 | ||
| 241 | // // id | |
| 242 | // user_show: function (data, callback, context) { | |
| 243 | // var params = { | |
| 244 | // url: this.config.user_show, | |
| 245 | // type: 'GET', | |
| 246 | // play_load: 'user', | |
| 247 | // data: data | |
| 248 | // }; | |
| 249 | // this._send_request(params, callback, context); | |
| 250 | // }, | |
| 251 | ||
| 252 | // // since_id, max_id, count, page | |
| 253 | // direct_messages: function (data, callback, context) { | |
| 254 | // var params = { | |
| 255 | // url: this.config.direct_messages, | |
| 256 | // type: 'GET', | |
| 257 | // play_load: 'message', | |
| 258 | // data: data | |
| 259 | // }; | |
| 260 | // this._send_request(params, callback, context); | |
| 261 | // }, | |
| 262 | ||
| 263 | // // id | |
| 264 | // destroy_msg: function (data, callback, context) { | |
| 265 | // var params = { | |
| 266 | // url: this.config.destroy_msg, | |
| 267 | // type: 'POST', | |
| 268 | // play_load: 'message', | |
| 269 | // data: data | |
| 270 | // }; | |
| 271 | // this._send_request(params, callback, context); | |
| 272 | // }, | |
| 273 | ||
| 274 | // /*dataçåæ°åè¡¨ï¼ | |
| 275 | // content å¾ åéæ¶æ¯çæ£æï¼è¯·ç¡®å®å¿ è¦æ¶éè¦è¿è¡URLç¼ç ( encode ) ï¼å¦å¤ï¼ä¸è¶ è¿140è±ææ140æ±åã | |
| 276 | // message å¿ é¡» 0 表示ææè¯ 1 表示æ³ä¸ä¸ | |
| 277 | // receiveUserId å¿ é¡»ï¼æ¥æ¶æ¹çç¨æ·id | |
| 278 | // source å¯éï¼æ¾ç¤ºå¨ç½ç«ä¸çæ¥èªåªé对åºçæ è¯ç¬¦ãå¦ææ³æ¾ç¤ºæå®çå符ï¼è¯·ä¸å®æ¹äººåèç³»ã | |
| 279 | // */ | |
| 280 | // new_message: function (data, callback, context) { | |
| 281 | // var params = { | |
| 282 | // url: this.config.new_message, | |
| 283 | // type: 'POST', | |
| 284 | // play_load: 'message', | |
| 285 | // data: data | |
| 286 | // }; | |
| 287 | // this._send_request(params, callback, context); | |
| 288 | // }, | |
| 289 | ||
| 290 | // // id | |
| 291 | // status_show: function (data, callback, context) { | |
| 292 | // var params = { | |
| 293 | // url: this.config.status_show, | |
| 294 | // play_load: 'status', | |
| 295 | // data: data | |
| 296 | // }; | |
| 297 | // this._send_request(params, callback, context); | |
| 298 | // }, | |
| 299 | ||
| 300 | // // æ ¼å¼ä¸ä¼ åæ°ï¼æ¹ä¾¿åç±»è¦çåç¹æ®å¤ç | |
| 301 | // // åç±»å¯ä»¥å¢å èªå·±çåæ° | |
| 302 | // format_upload_params: function (user, data, pic) { | |
| 303 | ||
| 304 | // }, | |
| 305 | ||
| 306 | ||
| 307 | ||
| 308 | // repost: function (data, callback, context) { | |
| 309 | // var params = { | |
| 310 | // url: this.config.repost, | |
| 311 | // type: 'POST', | |
| 312 | // play_load: 'status', | |
| 313 | // data: data | |
| 314 | // }; | |
| 315 | // this._send_request(params, callback, context); | |
| 316 | // }, | |
| 317 | ||
| 318 | // comment: function (data, callback, context) { | |
| 319 | // var params = { | |
| 320 | // url: this.config.comment, | |
| 321 | // type: 'POST', | |
| 322 | // play_load: 'comment', | |
| 323 | // data: data | |
| 324 | // }; | |
| 325 | // this._send_request(params, callback, context); | |
| 326 | // }, | |
| 327 | ||
| 328 | // reply: function (data, callback, context) { | |
| 329 | // var params = { | |
| 330 | // url: this.config.reply, | |
| 331 | // type: 'POST', | |
| 332 | // play_load: 'comment', | |
| 333 | // data: data | |
| 334 | // }; | |
| 335 | // this._send_request(params, callback, context); | |
| 336 | // }, | |
| 337 | ||
| 338 | // comments: function (data, callback, context) { | |
| 339 | // var params = { | |
| 340 | // url: this.config.comments, | |
| 341 | // type: 'GET', | |
| 342 | // play_load: 'comment', | |
| 343 | // data: data | |
| 344 | // }; | |
| 345 | // this._send_request(params, callback, context); | |
| 346 | // }, | |
| 347 | ||
| 348 | // // id | |
| 349 | // comment_destroy: function (data, callback, context) { | |
| 350 | // var params = { | |
| 351 | // url: this.config.comment_destroy, | |
| 352 | // type: 'POST', | |
| 353 | // play_load: 'comment', | |
| 354 | // data: data | |
| 355 | // }; | |
| 356 | // this._send_request(params, callback, context); | |
| 357 | // }, | |
| 358 | ||
| 359 | // friendships_create: function (data, callback, context) { | |
| 360 | // var params = { | |
| 361 | // url: this.config.friendships_create, | |
| 362 | // type: 'POST', | |
| 363 | // play_load: 'user', | |
| 364 | // data: data | |
| 365 | // }; | |
| 366 | // this._send_request(params, callback, context); | |
| 367 | // }, | |
| 368 | ||
| 369 | // // id | |
| 370 | // friendships_destroy: function (data, callback, context) { | |
| 371 | // var params = { | |
| 372 | // url: this.config.friendships_destroy, | |
| 373 | // type: 'POST', | |
| 374 | // play_load: 'user', | |
| 375 | // data: data | |
| 376 | // }; | |
| 377 | // this._send_request(params, callback, context); | |
| 378 | // }, | |
| 379 | ||
| 380 | // friendships_show: function (data, callback, context) { | |
| 381 | // var params = { | |
| 382 | // url: this.config.friendships_show, | |
| 383 | // play_load: 'user', | |
| 384 | // data: data | |
| 385 | // }; | |
| 386 | // this._send_request(params, callback, context); | |
| 387 | // }, | |
| 388 | ||
| 389 | // // type | |
| 390 | // reset_count: function (data, callback, context) { | |
| 391 | // var params = { | |
| 392 | // url: this.config.reset_count, | |
| 393 | // type: 'POST', | |
| 394 | // play_load: 'result', | |
| 395 | // data: data | |
| 396 | // }; | |
| 397 | // this._send_request(params, callback, context); | |
| 398 | // }, | |
| 399 | ||
| 400 | // // user_id, count, page | |
| 401 | // tags: function (data, callback, context) { | |
| 402 | // var params = { | |
| 403 | // url: this.config.tags, | |
| 404 | // play_load: 'tag', | |
| 405 | // data: data | |
| 406 | // }; | |
| 407 | // this._send_request(params, callback, context); | |
| 408 | // }, | |
| 409 | ||
| 410 | // // count, page | |
| 411 | // tags_suggestions: function (data, callback, context) { | |
| 412 | // var params = { | |
| 413 | // url: this.config.tags_suggestions, | |
| 414 | // play_load: 'tag', | |
| 415 | // data: data | |
| 416 | // }; | |
| 417 | // this._send_request(params, callback, context); | |
| 418 | // }, | |
| 419 | ||
| 420 | // // tags | |
| 421 | // create_tag: function (data, callback, context) { | |
| 422 | // var params = { | |
| 423 | // url: this.config.create_tag, | |
| 424 | // type: 'POST', | |
| 425 | // play_load: 'tag', | |
| 426 | // data: data | |
| 427 | // }; | |
| 428 | // this._send_request(params, callback, context); | |
| 429 | // }, | |
| 430 | ||
| 431 | // // tag_id | |
| 432 | // destroy_tag: function (data, callback, context) { | |
| 433 | // var params = { | |
| 434 | // url: this.config.destroy_tag, | |
| 435 | // type: 'POST', | |
| 436 | // play_load: 'tag', | |
| 437 | // data: data | |
| 438 | // }; | |
| 439 | // this._send_request(params, callback, context); | |
| 440 | // }, | |
| 441 | ||
| 442 | // // id | |
| 443 | // destroy: function (data, callback, context) { | |
| 444 | // if (!data || !data.id) { | |
| 445 | // return; | |
| 446 | // } | |
| 447 | // var params = { | |
| 448 | // url: this.config.destroy, | |
| 449 | // type: 'POST', | |
| 450 | // play_load: 'status', | |
| 451 | // data: data | |
| 452 | // }; | |
| 453 | // this._send_request(params, callback, context); | |
| 454 | // }, | |
| 455 | ||
| 456 | // // q, max_id, count | |
| 457 | // search: function (data, callback, context) { | |
| 458 | // var params = { | |
| 459 | // url: this.config.search, | |
| 460 | // play_load: 'status', | |
| 461 | // data: data | |
| 462 | // }; | |
| 463 | // this._send_request(params, callback, context); | |
| 464 | // }, | |
| 465 | ||
| 466 | // // q, page, count | |
| 467 | // user_search: function (data, callback, context) { | |
| 468 | // var params = { | |
| 469 | // url: this.config.user_search, | |
| 470 | // play_load: 'user', | |
| 471 | // data: data | |
| 472 | // }; | |
| 473 | // this._send_request(params, callback, context); | |
| 474 | // }, | |
| 475 | ||
| 476 | // /** | |
| 477 | // * List all emotions. | |
| 478 | // * | |
| 479 | // * @param {Object} user | |
| 480 | // * @param {Function(err, emotions)} callback | |
| 481 | // * - {Object} emotions: { | |
| 482 | // * '[åå]': { | |
| 483 | // * url: "http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/41/zz2_org.gif", | |
| 484 | // * type: "face", | |
| 485 | // * title: "åå", | |
| 486 | // * }, | |
| 487 | // * ... | |
| 488 | // * } | |
| 489 | // * @param {Object} context, callback context | |
| 490 | // * @return this | |
| 491 | // */ | |
| 492 | // emotions: function (user, callback, context) { | |
| 493 | // // http://api.t.sina.com.cn/emotions.json?&source=3538199806&language=cnname | |
| 494 | // // http://api.t.sina.com.cn/emotions.json?&source=3538199806&language=twname | |
| 495 | ||
| 496 | // var ep = EventProxy.create(); | |
| 497 | // ep.after('emotions', this.config.emotion_types.length, function (datas) { | |
| 498 | // var emotions = {}; | |
| 499 | // for (var i = 0, l = datas.length; i < l; i++) { | |
| 500 | // var items = datas[i]; | |
| 501 | // if (!items) { | |
| 502 | // continue; | |
| 503 | // } | |
| 504 | // for (var j = 0, jl = items.length; j < jl; j++) { | |
| 505 | // var emotion = items[j]; | |
| 506 | // emotions[emotion.phrase] = emotion; | |
| 507 | // } | |
| 508 | // } | |
| 509 | // callback.call(this, null, emotions); | |
| 510 | // }); | |
| 511 | // ep.once('error', function (err) { | |
| 512 | // ep.unbind(); | |
| 513 | // callback.call(this, err); | |
| 514 | // }); | |
| 515 | // var that = this; | |
| 516 | // that.config.emotion_types.forEach(function (args) { | |
| 517 | // var data = { | |
| 518 | // user: user | |
| 519 | // }; | |
| 520 | // for (var k in args) { | |
| 521 | // data[k] = args[k]; | |
| 522 | // } | |
| 523 | // var params = { | |
| 524 | // url: that.config.emotions, | |
| 525 | // play_load: 'emotion', | |
| 526 | // need_source: true, | |
| 527 | // data: data | |
| 528 | // }; | |
| 529 | // that._send_request(params, function (err, emotions) { | |
| 530 | // if (err) { | |
| 531 | // return ep.emit('error', err); | |
| 532 | // } | |
| 533 | // ep.emit('emotions', emotions); | |
| 534 | // }); | |
| 535 | // }); | |
| 536 | // return this; | |
| 537 | // }, | |
| 538 | ||
| 539 | ||
| 540 | ||
| 541 | // URL_RE: new RegExp('(?:\\[url\\s*=\\s*|)((?:www\\.|http[s]?://)[\\w\\.\\?%&\\-/#=;:!\\+~]+)(?:\\](.+)\\[/url\\]|)', 'ig'), | |
| 542 | // /** | |
| 543 | // * format status.text to display | |
| 544 | // */ | |
| 545 | // process_text: function (str_or_status, need_encode) { | |
| 546 | // var str = str_or_status; | |
| 547 | // if (need_encode === 'undedfined') { | |
| 548 | // need_encode = true; | |
| 549 | // } | |
| 550 | // if (str_or_status.text !== undefined) { | |
| 551 | // str = str_or_status.text; | |
| 552 | // } | |
| 553 | // if (str) { | |
| 554 | // if (need_encode) { | |
| 555 | // str = utils.htmlencode(str); | |
| 556 | // } | |
| 557 | // str = str.replace(this.URL_RE, this._replace_url_callback); | |
| 558 | // str = this.process_at(str, str_or_status); //@*** | |
| 559 | // str = this.process_emotional(str); | |
| 560 | // str = this.process_search(str); //#xxXX# | |
| 561 | // // iPhone emoji | |
| 562 | // str = str.replace( /([\uE001-\uE537])/gi, this._get_iphone_emoji); | |
| 563 | // } | |
| 564 | // return str || ' '; | |
| 565 | // }, | |
| 566 | // _replace_url_callback: function (m, g1, g2) { | |
| 567 | // var _url = g1; | |
| 568 | // if (g1.indexOf('http') !== 0) { | |
| 569 | // _url = 'http://' + g1; | |
| 570 | // } | |
| 571 | // return '<a target="_blank" class="link" href="{{url}}">{{value}}</a>'.format({ | |
| 572 | // url: _url, title: g1, value: g2||g1 | |
| 573 | // }); | |
| 574 | // }, | |
| 575 | ||
| 576 | // _get_iphone_emoji: function (str) { | |
| 577 | // return "<span class=\"iphoneEmoji "+ str.charCodeAt(0).toString(16).toUpperCase()+"\"></span>"; | |
| 578 | // }, | |
| 579 | ||
| 580 | // SEARCH_MATCH_RE: /#([^#]+)#/g, | |
| 581 | // SEARCH_TPL: '<a target="_blank" href="{{search_url}}{{search}}" title="Search #{{search}}">#{{search}}#</a>', | |
| 582 | ||
| 583 | // process_search: function (str) { | |
| 584 | // var that = this; | |
| 585 | // return str.replace(this.SEARCH_MATCH_RE, function (m, g1) { | |
| 586 | // return that._process_search_callback(m, g1); | |
| 587 | // }); | |
| 588 | // }, | |
| 589 | ||
| 590 | // _process_search_callback: function (m, g1) { | |
| 591 | // // ä¿®å¤#xxx@xxx#åµå¥é®é¢ | |
| 592 | // // var search = g1.remove_html_tag(); | |
| 593 | // return this.SEARCH_TPL.format({ search: g1, search_url: this.config.search_url }); | |
| 594 | // }, | |
| 595 | ||
| 596 | // format_search_text: function (str) { // æ ¼å¼åä¸»é¢ | |
| 597 | // return '#' + str.trim() + '#'; | |
| 598 | // }, | |
| 599 | ||
| 600 | // AT_RE: /@([\w\-\_\u2E80-\u3000\u303F-\u9FFF]+)/g, | |
| 601 | // process_at: function (str) { | |
| 602 | // //@*** u4e00-\u9fa5:䏿å符 \u2E80-\u9FFF:䏿¥é©å符 | |
| 603 | // //ãè§ç¹Â·@ä»»å¿å¼ºãä»å¹´æåºç1000ä¸å¥çä¿éæ¿ä»»å¡å¯è½æ ¹æ¬å®ä¸æ | |
| 604 | // // http://blog.oasisfeng.com/2006/10/19/full-cjk-unicode-range/ | |
| 605 | // // CJKæ ç¹ç¬¦å·ï¼3000-303F | |
| 606 | // var tpl = '<a class="at_user" data-name="$1" href="javascript:;" rhref="' + | |
| 607 | // this.config.user_home_url + '$1" title="show users">@$1</a>'; | |
| 608 | // return str.replace(this.AT_RE, tpl); | |
| 609 | // }, | |
| 610 | ||
| 611 | // process_emotional: function (str) { | |
| 612 | // var that = this; | |
| 613 | // return str.replace(/\[([\u4e00-\u9fff,\uff1f,\w]{1,4})\]/g, function (m, g1) { | |
| 614 | // return that._replace_emotional_callback(m, g1); | |
| 615 | // }); | |
| 616 | // }, | |
| 617 | ||
| 618 | // EMOTIONAL_TPL: '<img title="{{title}}" src="{{src}}" />', | |
| 619 | // _replace_emotional_callback: function (m, g1) { | |
| 620 | // if (g1) { | |
| 621 | // var face = this.EMOTIONS[g1]; | |
| 622 | // if (face) { | |
| 623 | // return this.EMOTIONAL_TPL.format({ title: m, src: FACE_URL_PRE + face }); | |
| 624 | // } | |
| 625 | // } | |
| 626 | // return m; | |
| 627 | // }, | |
| 628 | ||
| 629 | // }; | |
| 630 | ||
| 631 | ||
| 632 | // //æ°æµªå¾®å表æ 转å | |
| 633 | // var FACE_URL_PRE = TSinaAPI.FACE_URL_PRE = 'http://timg.sjs.sinajs.cn/t3/style/images/common/face/ext/normal/'; | |
| 634 | // var FACE_TPL = TSinaAPI.FACE_TPL = '[{{name}}]'; | |
| 635 | // var FACES = TSinaAPI.FACES = { | |
| 636 | // "åµåµ": "eb/smile.gif", | |
| 637 | // "å»å»": "c2/tooth.gif", | |
| 638 | // "åå": "6a/laugh.gif", | |
| 639 | // "ç±ä½ ": "7e/love.gif", | |
| 640 | // "æ": "a4/dizzy.gif", | |
| 641 | // "泪": "d8/sad.gif", | |
| 642 | // "é¦å´": "b8/cz_thumb.gif", | |
| 643 | // "æç": "4d/crazy.gif", | |
| 644 | // "å¼": "19/hate.gif", | |
| 645 | // "å¯ç±": "9c/tz_thumb.gif", | |
| 646 | // "æ": "57/angry.gif", | |
| 647 | // "æ±": "13/sweat.gif", | |
| 648 | // "å°": "8b/sleepy.gif", | |
| 649 | // "害ç¾": "05/shame_thumb.gif", | |
| 650 | // "ç¡è§": "7d/sleep_thumb.gif", | |
| 651 | // "é±": "90/money_thumb.gif", | |
| 652 | // "å·ç¬": "7e/hei_thumb.gif", | |
| 653 | // "é ·": "40/cool_thumb.gif", | |
| 654 | // "è¡°": "af/cry.gif", | |
| 655 | // "åæ": "f4/cj_thumb.gif", | |
| 656 | // "éå´": "29/bz_thumb.gif", | |
| 657 | // "éè§": "71/bs2_thumb.gif", | |
| 658 | // "æé¼»å±": "b6/kbs_thumb.gif", | |
| 659 | // "è±å¿": "64/hs_thumb.gif", | |
| 660 | // "鼿": "1b/gz_thumb.gif", | |
| 661 | // "失æ": "0c/sw_thumb.gif", | |
| 662 | // "æè": "e9/sk_thumb.gif", | |
| 663 | // "çç ": "b6/sb_thumb.gif", | |
| 664 | // "亲亲": "8f/qq_thumb.gif", | |
| 665 | // "æéª": "89/nm_thumb.gif", | |
| 666 | // "太å¼å¿": "58/mb_thumb.gif", | |
| 667 | // "æå¾çä½ ": "17/ldln_thumb.gif", | |
| 668 | // "å³å¼å¼": "98/yhh_thumb.gif", | |
| 669 | // "å·¦å¼å¼": "6d/zhh_thumb.gif", | |
| 670 | // "å": "a6/x_thumb.gif", | |
| 671 | // "å§å±": "73/wq_thumb.gif", | |
| 672 | // "å": "9e/t_thumb.gif", | |
| 673 | // "坿": "af/kl_thumb.gif", | |
| 674 | // "æåæ°": "f3/k_thumb.gif", | |
| 675 | // "å鬼è¸": "88/zgl_thumb.gif", | |
| 676 | // "æ¡æ": "0c/ws_thumb.gif", | |
| 677 | // "è¶": "d9/ye_thumb.gif", | |
| 678 | // "good": "d8/good_thumb.gif", | |
| 679 | // "å¼±": "d8/sad_thumb.gif", | |
| 680 | // "ä¸è¦": "c7/no_thumb.gif", | |
| 681 | // "ok": "d6/ok_thumb.gif", | |
| 682 | // "èµ": "d0/z2_thumb.gif", | |
| 683 | // "æ¥": "40/come_thumb.gif", | |
| 684 | // "èç³": "6a/cake.gif", | |
| 685 | // "å¿": "6d/heart.gif", | |
| 686 | // "伤å¿": "ea/unheart.gif", | |
| 687 | // "é": "d3/clock_thumb.gif", | |
| 688 | // "çªå¤´": "58/pig.gif", | |
| 689 | // "åå¡": "64/cafe_thumb.gif", | |
| 690 | // "è¯ç": "1b/m_thumb.gif", | |
| 691 | // "å¹²æ¯": "bd/cheer.gif", | |
| 692 | // "绿ä¸å¸¦": "b8/green.gif", | |
| 693 | // "è¡ç": "cc/candle.gif", | |
| 694 | // "å¾®é£": "a5/wind_thumb.gif", | |
| 695 | // "æäº®": "b9/moon.gif", | |
| 696 | // "æé¥¼": "96/mooncake3_thumb.gif", | |
| 697 | // "满æ": "5d/moon1_thumb.gif", | |
| 698 | // "é 壶": "64/wine_thumb.gif", | |
| 699 | // "å¢": "11/tuan_thumb.gif", | |
| 700 | // "å": "53/yuan_thumb.gif", | |
| 701 | // "å·¦æ±æ±": "54/left_thumb.gif", | |
| 702 | // "峿±æ±": "0d/right_thumb.gif", | |
| 703 | // "ä¹ä¹": "66/guanbuzhao_thumb.gif", | |
| 704 | // "å¢åæé¥¼": "e6/tuanyuan_thumb.gif", | |
| 705 | // "å¿«å¿«": "49/lbq1_thumb.gif", | |
| 706 | // "ç»": "41/zz2_thumb.gif", | |
| 707 | // "å´è§": "f2/wg_thumb.gif", | |
| 708 | // "卿¦": "70/vw_thumb.gif", | |
| 709 | // "ç±å¿ä¸é": "c9/axcd_thumb.gif", | |
| 710 | // "å¥¥ç¹æ¼": "bc/otm_thumb.gif", | |
| 711 | // //äºè¿ | |
| 712 | // "彿": "dc/flag_thumb.gif", | |
| 713 | // "éç": "f4/jinpai_thumb.gif", | |
| 714 | // "é¶ç": "1e/yinpai_thumb.gif", | |
| 715 | // "éç": "26/tongpai_thumb.gif", | |
| 716 | // "å´è": "3f/weijin_thumb.gif", | |
| 717 | // "温æå¸½å": "f1/wennuanmaozi_thumb.gif", | |
| 718 | // "æå¥": "72/shoutao_thumb.gif", | |
| 719 | // "è½å¶": "79/yellowMood_thumb.gif", | |
| 720 | // "ç §ç¸æº": "33/camera_thumb.gif", | |
| 721 | // "ç½äº": "ff/y3_thumb.gif", | |
| 722 | // "礼ç©": "c4/liwu_thumb.gif", | |
| 723 | // "v5": "c5/v5_org.gif", | |
| 724 | // "书åå": "61/sdz_org.gif" | |
| 725 | // }; | |
| 726 | ||
| 727 | // // http://api.t.sina.com.cn/emotions.json | |
| 728 | // TSinaAPI.EMOTIONS = { | |
| 729 | // "åµåµ": "eb/smile.gif", "å»å»": "c2/tooth.gif", "åå": "6a/laugh.gif", "ç±ä½ ": "7e/love.gif", "æ": "a4/dizzy.gif", "泪": "d8/sad.gif", "é¦å´": "b8/cz_org.gif", "æç": "4d/crazy.gif", "å¼": "19/hate.gif", "å¯ç±": "9c/tz_org.gif", "æ": "57/angry.gif", "æ±": "13/sweat.gif", "å°": "8b/sleepy.gif", "害ç¾": "05/shame_org.gif", "ç¡è§": "7d/sleep_org.gif", "é±": "90/money_org.gif", "å·ç¬": "7e/hei_org.gif", "é ·": "40/cool_org.gif", "è¡°": "af/cry.gif", "åæ": "f4/cj_org.gif", "éå´": "29/bz_org.gif", "éè§": "71/bs2_org.gif", "æé¼»å±": "b6/kbs_org.gif", "è±å¿": "64/hs_org.gif", "鼿": "1b/gz_org.gif", "失æ": "0c/sw_org.gif", "æè": "e9/sk_org.gif", "çç ": "b6/sb_org.gif", "亲亲": "8f/qq_org.gif", "æéª": "89/nm_org.gif", "太å¼å¿": "58/mb_org.gif", "æå¾çä½ ": "17/ldln_org.gif", "å³å¼å¼": "98/yhh_org.gif", "å·¦å¼å¼": "6d/zhh_org.gif", "å": "a6/x_org.gif", "å§å±": "73/wq_org.gif", "å": "9e/t_org.gif", "坿": "af/kl_org.gif", "æåæ°": "f3/k_org.gif", "é¡¶": "91/d_org.gif", "çé®": "5c/yw_org.gif", "å鬼è¸": "88/zgl_org.gif", "æ¡æ": "0c/ws_org.gif", "è¶": "d9/ye_org.gif", "good": "d8/good_org.gif", "å¼±": "d8/sad_org.gif", "ä¸è¦": "c7/no_org.gif", "ok": "d6/ok_org.gif", "èµ": "d0/z2_org.gif", "æ¥": "40/come_org.gif", "èç³": "6a/cake.gif", "å¿": "6d/heart.gif", "伤å¿": "ea/unheart.gif", "é": "d3/clock_org.gif", "çªå¤´": "58/pig.gif", "åå¡": "64/cafe_org.gif", "è¯ç": "1b/m_org.gif", "æäº®": "b9/moon.gif", "太é³": "e5/sun.gif", "å¹²æ¯": "bd/cheer.gif", "å¾®é£": "a5/wind_org.gif", "飿º": "6d/travel_org.gif", "å å": "81/rabbit_org.gif", "çç«": "6e/panda_org.gif", "ç»å": "c9/geili_org.gif", "ç¥é©¬": "60/horse2_org.gif", "æµ®äº": "bc/fuyun_org.gif", "ç»": "41/zz2_org.gif", "å´è§": "f2/wg_org.gif", "卿¦": "70/vw_org.gif", "å¥¥ç¹æ¼": "bc/otm_org.gif", "å®ä¹ ": "48/sx_org.gif", "èªè¡è½¦": "46/zxc_org.gif", "ç §ç¸æº": "33/camera_org.gif", "å¶å": "b8/green_org.gif", "æ¥æè±å¼": "ca/chunnuanhuakai_org.gif", "åå®": "4b/paoxiao_org.gif", "彩è¹": "03/ch_org.gif", "æ²å°æ´": "69/sc_org.gif", "å°çä¸å°æ¶": "4f/diqiuxiuxiyixiaoshi_org.gif", "ç±å¿ä¼ é": "c9/axcd_org.gif", "è¡ç": "cc/candle.gif", "绿ä¸å¸¦": "b8/green.gif", "æ¤ç¼": "c3/zy_org.gif", "亲亲": "8f/qq_org.gif", "æéª": "89/nm_org.gif", "太å¼å¿": "58/mb_org.gif", "æå¾çä½ ": "17/ldln_org.gif", "æåæ°": "f3/k_org.gif", "çç ": "b6/sb_org.gif", "书åå": "61/sdz_org.gif", "失æ": "0c/sw_org.gif", "坿": "af/kl_org.gif", "æé¼»å±": "b6/kbs_org.gif", "é»çº¿": "91/h_org.gif", "è±å¿": "64/hs_org.gif", "å¯ç±": "9c/tz_org.gif", "å": "9e/t_org.gif", "å§å±": "73/wq_org.gif", "æè": "e9/sk_org.gif", "åå": "6a/laugh.gif", "å": "a6/x_org.gif", "å³å¼å¼": "98/yhh_org.gif", "å·¦å¼å¼": "6d/zhh_org.gif", "çé®": "5c/yw_org.gif", "é´é©": "6d/yx_org.gif", "å鬼è¸": "88/zgl_org.gif", "ç±ä½ ": "7e/love.gif", "é¦å´": "b8/cz_org.gif", "é¡¶": "91/d_org.gif", "é±": "90/money_org.gif", "å»å»": "c2/tooth.gif", "æ±": "13/sweat.gif", "åµåµ": "eb/smile.gif", "ç¡è§": "7d/sleep_org.gif", "å°": "8b/sleepy.gif", "害ç¾": "05/shame_org.gif", "æ²ä¼¤": "1a/bs_org.gif", "éè§": "71/bs2_org.gif", "æ±æ±": "7c/bb_org.gif", "ææ": "70/88_org.gif", "æ": "57/angry.gif", "åæ": "f4/cj_org.gif", "éå´": "29/bz_org.gif", "泪": "d8/sad.gif", "å·ç¬": "7e/hei_org.gif", "å¼": "19/hate.gif", "æ": "a4/dizzy.gif", "è¡°": "af/cry.gif", "æç": "4d/crazy.gif", "æ¤æ": "bd/fn_org.gif", "æå": "a0/gm_org.gif", "鼿": "1b/gz_org.gif", "é ·": "40/cool_org.gif", "æ¥": "40/come_org.gif", "good": "d8/good_org.gif", "haha": "13/ha_org.gif", "ä¸è¦": "c7/no_org.gif", "ok": "d6/ok_org.gif", "æ³å¤´": "cc/o_org.gif", "å¼±": "d8/sad_org.gif", "æ¡æ": "0c/ws_org.gif", "èµ": "d0/z2_org.gif", "è¶": "d9/ye_org.gif", "æå·®": "3e/bad_org.gif", "峿±æ±": "0d/right_org.gif", "å·¦æ±æ±": "54/left_org.gif", "ç²çº¢ä¸å¸¦": "77/pink_org.gif", "ç±å¿ä¼ é": "c9/axcd_org.gif", "å¿": "6d/heart.gif", "绿ä¸å¸¦": "b8/green.gif", "è¡ç": "cc/candle.gif", "å´è": "3f/weijin_org.gif", "温æå¸½å": "f1/wennuanmaozi_org.gif", "æå¥": "72/shoutao_org.gif", "红å ": "71/hongbao_org.gif", "å": "bf/xi_org.gif", "礼ç©": "c4/liwu_org.gif", "èç³": "6a/cake.gif", "黿": "31/r_org.gif", "é»ç³": "9f/diamond_org.gif", "大巴": "9c/dynamicbus_org.gif", "飿º": "6d/travel_org.gif", "èªè¡è½¦": "46/zxc_org.gif", "汽车": "a4/jc_org.gif", "ææº": "4b/sj2_org.gif", "ç §ç¸æº": "33/camera_org.gif", "è¯": "5d/y_org.gif", "çµè": "df/dn_org.gif", "æçº¸": "55/sz_org.gif", "è½å¶": "79/yellowMood_org.gif", "å£è¯æ ": "a2/christree_org.gif", "å£è¯å¸½": "06/chrishat_org.gif", "å£è¯è人": "c5/chrisfather_org.gif", "å£è¯éé": "64/chrisbell_org.gif", "å£è¯è¢": "08/chrisocks_org.gif", "å¾ç": "ce/tupianimage_org.gif", "å èæ": "c2/liumangxing_org.gif", "å°çä¸å°æ¶": "4f/diqiuxiuxiyixiaoshi_org.gif", "æ¤æ è": "56/zhishujie_org.gif", "ç²èç³": "bf/nycake_org.gif", "ç³æ": "34/candy_org.gif", "ä¸å£è": "73/nanguatou2_org.gif", "ç«ç¬": "3b/hj_org.gif", "é 壶": "64/wine_org.gif", "æé¥¼": "96/mooncake3_org.gif", "满æ": "5d/moon1_org.gif", "å·§å å": "b1/qkl_org.gif", "èå°": "12/jy_org.gif", "é ": "39/j2_org.gif", "ç": "5d/g_org.gif", "å·¥ä½": "b2/gz3_org.gif", "æ¡£æ¡": "ce/gz2_org.gif", "å¶å": "b8/green_org.gif", "é¢ç´": "b2/gq_org.gif", "å°è¿¹": "84/foot_org.gif", "é": "d3/clock_org.gif", "è¶": "a8/cha_org.gif", "西ç": "6b/watermelon.gif", "é¨ä¼": "33/umb_org.gif", "çµè§æº": "b3/tv_org.gif", "çµè¯": "9d/tel_org.gif", "太é³": "e5/sun.gif", "æ": "0b/star_org.gif", "å¨å": "a0/shao.gif", "è¯ç": "1b/m_org.gif", "é³ä¹": "d0/music_org.gif", "çµå½±": "77/movie_org.gif", "æäº®": "b9/moon.gif", "屿": "79/ktv_org.gif", "å°æ£": "3a/ice.gif", "æ¿å": "d1/house_org.gif", "帽å": "25/hat_org.gif", "è¶³ç": "c0/football.gif", "é²è±": "6c/flower_org.gif", "è±": "6c/flower.gif", "飿": "92/fan.gif", "å¹²æ¯": "bd/cheer.gif", "åå¡": "64/cafe_org.gif", "å å": "81/rabbit_org.gif", "ç¥é©¬": "60/horse2_org.gif", "æµ®äº": "bc/fuyun_org.gif", "ç»å": "c9/geili_org.gif", "è": "42/kawayi_org.gif", "鏿¢¨": "bb/pear_org.gif", "çç«": "6e/panda_org.gif", "äºç²": "89/hufen_org.gif", "ç»": "41/zz2_org.gif", "å´è§": "f2/wg_org.gif", "æé¸¡è": "91/rjd_org.gif", "å¥¥ç¹æ¼": "bc/otm_org.gif", "卿¦": "70/vw_org.gif", "伤å¿": "ea/unheart.gif", "çå»": "60/rw_org.gif", "å§": "15/j_org.gif", "orz": "c0/orz1_org.gif", "å® ": "d7/z_org.gif", "å°ä¸": "6b/xc_org.gif", "å¸ ": "36/s2_org.gif", "çªå¤´": "58/pig.gif", "å®ä¹ ": "48/sx_org.gif", "éª·é« ": "bd/kl2_org.gif", "便便": "34/s_org.gif", "éªäºº": "d9/xx2_org.gif", "é»ç": "a0/yellowcard.gif", "红ç": "64/redcard.gif", "è·³èè±": "70/twh_org.gif", "礼è±": "3d/bingo_org.gif", "æé": "b0/zt_org.gif", "å¹å·": "3b/th_org.gif", "é®å·": "9d/wh_org.gif", "å¥å·": "9b/jh_org.gif", "éå·": "cc/dh_org.gif", "1": "9b/1_org.gif", "2": "2c/2_org.gif", "3": "f3/3_org.gif", "4": "2c/4_org.gif", "5": "d5/5_org.gif", "6": "dc/6_org.gif", "7": "43/7_org.gif", "8": "6d/8_org.gif", "9": "26/9_org.gif", "0": "d8/ling_org.gif", "éª": "ce/03_org.gif", "å¦å¦": "c1/04_org.gif", "å¼å¼": "34/05_org.gif", "åºç¥": "67/06_org.gif", "å¿": "d3/01_org.gif", "çç¥å·": "0d/shengluehao_org.gif", "kiss": "59/kiss2_org.gif", "å": "53/yuan_org.gif", "å¢": "11/tuan_org.gif", "å¢åæé¥¼": "e6/tuanyuan_org.gif", "欢欢": "c3/liaobuqi_org.gif", "ä¹ä¹": "66/guanbuzhao_org.gif", "管ä¸çç±": "78/2guanbuzhao1_org.gif", "ç±": "09/ai_org.gif", "äºä¸èµ·ç±": "11/2liaobuqiai_org.gif", "æç¹å°": "68/youdiankun_org.gif", "yes": "9e/yes_org.gif", "å½åå»äº": "72/yanhuiqule_org.gif", "鏿¢¨å¾å¤§": "01/yalihenda_org.gif", "ç¾ç¾": "42/xiuxiu_org.gif", "忬¢ä½ ": "6b/xihuang_org.gif", "å°ä¾¿å±": "a0/xiaobianpi_org.gif", "æ å¥": "d6/wunai22_org.gif", "å å ": "da/tutu_org.gif", "åè头": "98/tushetou_org.gif", "头æ": "48/touyun_org.gif", "å¬é³ä¹": "d3/tingyinyue_org.gif", "ç¡å¤§è§": "65/shuijiao_org.gif", "éªéªç´«": "9e/shanshanzi_org.gif", "éªéªç»¿": "a8/shanshanlu_org.gif", "éªéªç°": "1e/shanshanhui_org.gif", "éªéªçº¢": "10/shanshanhong_org.gif", "éªéªç²": "9d/shanshanfen_org.gif", "åå®": "4b/paoxiao_org.gif", "æ¸å¤´": "2c/motou_org.gif", "çç¾å¥½": "d2/meihao_org.gif", "è¸çº¢èªç": "d8/lianhongzibao_org.gif", "åæ³£å¥³": "1c/kuqinv_org.gif", "åæ³£ç·": "38/kuqinan_org.gif", "空": "fd/kong_org.gif", "å°½æ ç©": "9f/jinqingwan_org.gif", "æå": "b8/jingxi_org.gif", "æå": "58/jingdai_org.gif", "è¡èå": "e1/huluobo_org.gif", "æ¬¢è ¾å»ç±": "63/huangtengquai_org.gif", "æåäº": "67/ganmao_org.gif", "æäº": "ef/fennu_org.gif", "æè¦å¥æ": "a6/fendou123_org.gif", "åè½": "95/faya_org.gif", "æ¥æè±å¼": "ca/chunnuanhuakai_org.gif", "æ½ç": "83/chouyan_org.gif", "æ": "31/ang_org.gif", "å": "12/aa_org.gif", "èªæåç®": "d3/zichashuangmu_org.gif", "å¦": "9f/yiwen_org.gif", "åå": "cf/xu_org.gif", "æå": "00/wochiwode_org.gif", "åµå": "a7/weiqu_org.gif", "v5": "c5/v5_org.gif", "è°æ": "f7/tiaoxi_org.gif", "æç": "d7/taihaoxiaole_org.gif", "æè´±": "b8/shoujian_org.gif", "è²": "a1/se_org.gif", "å·": "4a/pen_org.gif", "ä½ æç": "2e/nidongde_org.gif", "åµ": "a0/miaomiao_org.gif", "ç¾å³": "c1/meiwei_org.gif", "ææ": "46/jingkong_org.gif", "æå¨": "7c/gandong_org.gif", "æ¾å¼": "55/fangkai_org.gif", "ç´å": "e8/chidai_org.gif", "æ¯è¸": "99/chelian_org.gif", "ä¸ç¥ææª": "ab/buzhisuocuo_org.gif", "ç½ç¼": "24/baiyan_org.gif", "ç¥ç": "e1/weisuo_org.gif", "æç": "c9/tiaomei_org.gif", "æé": "3c/tiaodou_org.gif", "äº²è³æµ": "1c/qinerduo_org.gif", "åªç¼": "32/meiyan_org.gif", "å个泡": "32/maogepao_org.gif", "å§è³æµ": "f0/jiongerduo_org.gif", "鬼è¸": "14/guilian_org.gif", "æ¾çµ": "fd/fangdian_org.gif", "æ²å§": "ea/beiju_org.gif", "ææ¸": "78/touch_org.gif", "大æ±": "13/sweat_org.gif", "大æ": "74/suprise_org.gif", "æå": "0c/supcry_org.gif", "ææç¼": "5c/stareyes_org.gif", "好å°": "8b/sleepy_org.gif", "åå": "75/sick_org.gif", "å æä¸ä¸ª": "ee/plus1_org.gif", "ççå è¶": "19/pipioye_org.gif", "mua": "c6/muamua_org.gif", "颿½": "fd/mianchou_org.gif", "大ç¬": "6a/laugh_org.gif", "æ": "d6/knead_org.gif", "ççå å§": "38/jiong_org.gif", "åå°¼å è¶": "53/honeyoye_org.gif", "å¼å¿": "40/happy_org.gif", "嬿å¸": "af/handkerchief_org.gif", "å»": "6b/go_org.gif", "ææ»äº": "a4/dizzy_org.gif", "大å": "af/cry_org.gif", "æåé®é¢": "a1/coverface_org.gif", "ææ°": "ea/angery_org.gif", "886": "6f/886_org.gif", "é¾": "68/w_org.gif", "å°é£": "55/tf_org.gif", "æ²å°æ´": "69/sc_org.gif", "æ´è½¬å¤äº": "d2/qzdy_org.gif", "æµæ": "8e/lx_org.gif", "é¾å·é£": "6a/ljf_org.gif", "洪水": "ba/hs2_org.gif", "é£": "74/gf_org.gif", "å¤äºè½¬æ´": "f3/dyzq_org.gif", "彩è¹": "03/ch_org.gif", "å°é¹": "05/bb2_org.gif", "å¾®é£": "a5/wind_org.gif", "é³å ": "1a/sunny_org.gif", "éª": "00/snow_org.gif", "éªçµ": "e3/sh_org.gif", "ä¸é¨": "50/rain.gif", "é´å¤©": "37/dark_org.gif", "ç½ç¾": "07/byz2_org.gif", "å°æ": "46/ssz2_org.gif", "åé±¼": "e2/syz2_org.gif", "åå": "89/szz2_org.gif", "天秤": "6b/tpz2_org.gif", "天è": "1e/txz2_org.gif", "æ°´ç¶": "1b/spz2_org.gif", "å¤å¥³": "62/cnz2_org.gif", "éç": "3b/jnz2_org.gif", "å·¨è¹": "d2/jxz2_org.gif", "ç®å": "4a/leo2_org.gif", "æ©ç¾¯": "16/mjz2_org.gif", "天è座": "09/txz_org.gif", "天秤座": "c1/tpz_org.gif", "åå座": "d4/szz_org.gif", "å鱼座": "7f/syz_org.gif", "å°æåº§": "5d/ssz_org.gif", "æ°´ç¶åº§": "00/spz_org.gif", "æ©ç¾¯åº§": "da/mjz_org.gif", "ç®å座": "23/leo_org.gif", "å·¨è¹åº§": "a3/jxz_org.gif", "éç座": "8d/jnz_org.gif", "å¤å¥³åº§": "09/cnz_org.gif", "ç½ç¾åº§": "e0/byz_org.gif", "yeah": "1a/yeah_org.gif", "忬¢": "5f/xh_org.gif", "å¿å¨": "5f/xd_org.gif", "æ è": "53/wl_org.gif", "æèè¶³è¹": "b2/gx_org.gif", "æç¬": "09/gx2_org.gif", "çå": "eb/gd_org.gif", "çå": "38/fn2_org.gif", "åå¥": "31/d2_org.gif", "ä¸å±": "b0/bx_org.gif", "å æ²¹": "d4/jiayou_org.gif", "彿": "dc/flag_org.gif", "éç": "f4/jinpai_org.gif", "é¶ç": "1e/yinpai_org.gif", "éç": "26/tongpai_org.gif", "å¨å": "a0/shao.gif", "é»ç": "a0/yellowcard.gif", "红ç": "64/redcard.gif", "è¶³ç": "c0/football.gif", "篮ç": "2c/bball_org.gif", "é»8": "6b/black8_org.gif", "æç": "cf/volleyball_org.gif", "游泳": "b9/swimming_org.gif", "ä¹ä¹ç": "a5/pingpong_org.gif", "æç¯®": "7a/basketball_org.gif", "ç¾½æ¯ç": "77/badminton_org.gif", "å°é¨": "e0/zuqiu_org.gif", "å°ç®": "40/shejian_org.gif", "举é": "14/juzhong_org.gif", "å»å": "38/jijian_org.gif", "ç¦èº": "c5/fanzao_org.gif", "å²ç": "c1/ciya_org.gif", "æé±": "e6/youqian_org.gif", "å¾®ç¬": "05/weixiao_org.gif", "å¸ ç": "c1/shuaibao_org.gif", "çæ°": "0a/shengqi_org.gif", "çç äº": "19/shengbing_org.gif", "è²ç¯ç¯": "90/semimi_org.gif", "ç²å³": "d1/pilao_org.gif", "ç": "14/miao_org.gif", "å": "79/ku_org.gif", "好坿": "76/kelian_org.gif", "ç´§å¼ ": "75/jinzhang_org.gif", "æè®¶": "dc/jingya_org.gif", "æ¿å¨": "bb/jidong_org.gif", "è§é±": "2b/jianqian_org.gif", "æ±äº": "7d/han_org.gif", "奿": "4e/fendou_org.gif", "å°äººå¾å¿": "09/xrdz_org.gif", "ååå": "cc/whh_org.gif", "广°": "90/tq_org.gif", "å»ç»": "d3/sjdj_org.gif", "å": "1d/q_org.gif", "æç §": "ec/pz_org.gif", "ææ": "7c/pp_org.gif", "æå¼": "4d/nh_org.gif", "èæ": "9f/mb2_org.gif", "è·¯è¿": "70/lg_org.gif", "泪å¥": "34/lb_org.gif", "è¸åè²": "cd/lbs_org.gif", "亲": "05/kiss_org.gif", "ææ": "86/kb_org.gif", "äº¤ç»æå§": "e2/jgwb_org.gif", "欢欣é¼è": "2b/hxgw_org.gif", "é«å ´": "c7/gx3_org.gif", "å°´å°¬": "43/gg_org.gif", "åå²": "4e/fd_org.gif", "ç¯é": "19/fc_org.gif", "徿": "fb/dy_org.gif", "åµé¹": "fa/cn_org.gif", "å²é": "2f/cf_org.gif", "æ½è³å ": "eb/ceg_org.gif", "å·®å¾è¿å¢": "ee/cdyn_org.gif", "è¢«ç ¸": "5a/bz2_org.gif", "ææ": "6e/bt_org.gif", "å¿ è": "cf/bs3_org.gif", "ä¸å ³æäº": "e8/bgws_org.gif", "ä¸ç«": "64/bf_org.gif", "ä¸åç¿": "b6/bdw_org.gif", "ä¸éå¦": "79/bco_org.gif", "ç¨ç¨ç¼": "3b/zy2_org.gif", "ææ": "ec/zs_org.gif", "å¤é®å·": "17/wh2_org.gif", "跳绳": "79/ts_org.gif", "强å»": "b1/q3_org.gif", "䏿´»äº": "37/lb2_org.gif", "ç£å¤´": "6a/kt_org.gif", "åå": "55/bya_org.gif", "ä¸": "a2/bx2_org.gif", "çç¬": "d5/zk_org.gif", "å¤": "5f/wq2_org.gif", "è·": "87/q2_org.gif", "ç¾å¥½": "ae/mh_org.gif", "ä¹å": "5f/m2_org.gif", "æªè³æµ": "15/j3_org.gif", "æ": "bf/h2_org.gif", "high": "e7/f_org.gif", "è¹": "33/c_org.gif", "æ±æ": "f4/bz3_org.gif", "ä¸å ¬å¹³": "85/bgp_org.gif" | |
| 730 | // }; |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/tbase.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var querystring = require('querystring'); |
| 14 | 1 | var urllib = require('urllib'); |
| 15 | 1 | var utils = require('./utils'); |
| 16 | 1 | var OAuth = require('./oauth'); |
| 17 | 1 | var emoji = require('emoji'); |
| 18 | ||
| 19 | /** | |
| 20 | * TAPI Base class, support OAuth v1.0 | |
| 21 | */ | |
| 22 | 1 | function TBase() { |
| 23 | 4 | this.config = { |
| 24 | host: 'api start url', | |
| 25 | result_format: '.json', | |
| 26 | appkey: '', | |
| 27 | secret: '', | |
| 28 | oauth_host: '', | |
| 29 | oauth_callback: 'oob or url', | |
| 30 | oauth_version: '1.0', | |
| 31 | ||
| 32 | userinfo_has_counts: true, // ç¨æ·ä¿¡æ¯ä¸æ¯å¦å å«ç²ä¸æ°ã微忰çä¿¡æ¯ | |
| 33 | support_counts: true, // æ¯å¦æ¯ææ¹éè·å转ååè¯è®ºæ° | |
| 34 | support_comment: true, // 夿æ¯å¦æ¯æè¯è®ºå表 | |
| 35 | support_do_comment: true, // 夿æ¯å¦æ¯æåéè¯è®º | |
| 36 | support_repost_comment: true, // 夿æ¯å¦æ¯æè½¬ååæ¶åè¯è®º | |
| 37 | support_repost_comment_to_root: false, // 夿æ¯å¦æ¯æè½¬ååæ¶ç»åæä½è åè¯è®º | |
| 38 | support_upload: true, // æ¯å¦æ¯æä¸ä¼ å¾ç | |
| 39 | support_repost: true, // æ¯å¦æ¯ææ°æµªå½¢å¼è½¬è½½ | |
| 40 | repost_pre: '转:', // 转ååç¼ | |
| 41 | repost_delimiter: '//', //转åçåé符 | |
| 42 | image_shorturl_pre: ' [å¾] ', // RTå¾ç缩ååç¼ | |
| 43 | support_favorites: true, // 夿æ¯å¦æ¯ææ¶èå表 | |
| 44 | support_do_favorite: true, // 夿æ¯å¦æ¯ææ¶èåè½ | |
| 45 | support_geo: true, //æ¯å¦æ¯æå°çä½ç½®ä¿¡æ¯ä¸ä¼ | |
| 46 | // æ¯å¦æ¯æmax_id å页 | |
| 47 | support_max_id: true, | |
| 48 | support_destroy_msg: true, //æ¯å¦æ¯æå é¤ç§ä¿¡ | |
| 49 | support_direct_messages: true, | |
| 50 | support_sent_direct_messages: true, //æ¯å¦æ¯æèªå·±åéçç§ä¿¡ | |
| 51 | support_mentions: true, | |
| 52 | support_friendships_create: true, | |
| 53 | support_search: true, | |
| 54 | support_search_max_id: false, | |
| 55 | support_favorites_max_id: false, // æ¶èå页使ç¨max_id | |
| 56 | ||
| 57 | need_processMsg: true, //æ¯å¦éè¦å¤çæ¶æ¯çå 容 | |
| 58 | comment_need_user_id: false, // è¯è®ºæ¯å¦éè¦ä½¿ç¨å°ç¨æ·idï¼é»è®¤ä¸ºfalseï¼å ¼å®¹æææ§æ¥å£ | |
| 59 | ||
| 60 | // api | |
| 61 | public_timeline: '/statuses/public_timeline', | |
| 62 | home_timeline: '/statuses/home_timeline', | |
| 63 | user_timeline: '/statuses/user_timeline', | |
| 64 | mentions: '/statuses/mentions', | |
| 65 | comments_timeline: '/comments/timeline', | |
| 66 | comments_mentions: '/comments/mentions', | |
| 67 | comments_to_me: '/comments/to_me', | |
| 68 | comments_by_me: '/comments/by_me', | |
| 69 | ||
| 70 | repost_timeline: '/statuses/repost_timeline', | |
| 71 | comments: '/statuses/comments', | |
| 72 | ||
| 73 | show: '/statuses/show', | |
| 74 | count: '/statuses/count', | |
| 75 | update: '/statuses/update', | |
| 76 | upload: '/statuses/upload', | |
| 77 | repost: '/statuses/repost', | |
| 78 | destroy: '/statuses/destroy', | |
| 79 | ||
| 80 | followers: '/statuses/followers', | |
| 81 | friends: '/statuses/friends', | |
| 82 | favorites: '/favorites', | |
| 83 | favorites_create: '/favorites/create', | |
| 84 | favorites_destroy: '/favorites/destroy/{{id}}', | |
| 85 | ||
| 86 | comment_create: '/statuses/comment', | |
| 87 | comment_reply: '/statuses/reply', | |
| 88 | comment_destroy: '/statuses/comment_destroy', | |
| 89 | ||
| 90 | destroy_msg: '/direct_messages/destroy/{{id}}', | |
| 91 | direct_messages: '/direct_messages', | |
| 92 | sent_direct_messages: '/direct_messages/sent', //èªå·±åéçç§ä¿¡åè¡¨ï¼æå½æ¶ä¸ºä»ä¹è¦å½å为sent_direct_messagesæï¼ææ¦ | |
| 93 | new_message: '/direct_messages/new', | |
| 94 | verify_credentials: '/account/verify_credentials', | |
| 95 | user_show: '/users/show', | |
| 96 | rate_limit_status: '/account/rate_limit_status', | |
| 97 | friendships_create: '/friendships/create', | |
| 98 | friendships_destroy: '/friendships/destroy', | |
| 99 | friendships_show: '/friendships/show', | |
| 100 | reset_count: '/statuses/reset_count', | |
| 101 | emotions: '/emotions', | |
| 102 | ||
| 103 | // ç¨æ·æ ç¾ | |
| 104 | tags: '/tags', | |
| 105 | create_tag: '/tags/create', | |
| 106 | destroy_tag: '/tags/destroy', | |
| 107 | tags_suggestions: '/tags/suggestions', | |
| 108 | ||
| 109 | // æç´¢ | |
| 110 | search: '/statuses/search', | |
| 111 | user_search: '/users/search', | |
| 112 | ||
| 113 | oauth_authorize: '/oauth/authorize', | |
| 114 | oauth_request_token: '/oauth/request_token', | |
| 115 | oauth_access_token: '/oauth/access_token', | |
| 116 | ||
| 117 | // å¾çä¸ä¼ åæ®µåç§° | |
| 118 | pic_field: 'pic', | |
| 119 | }; | |
| 120 | } | |
| 121 | ||
| 122 | 1 | module.exports = TBase; |
| 123 | ||
| 124 | 1 | TBase.prototype.init = function (config) { |
| 125 | 4 | for (var k in config) { |
| 126 | 99 | this.config[k] = config[k]; |
| 127 | } | |
| 128 | }; | |
| 129 | ||
| 130 | /** | |
| 131 | * Utils methods | |
| 132 | */ | |
| 133 | ||
| 134 | 1 | TBase.prototype.URL_RE = new RegExp('(?:\\[url\\s*=\\s*|)((?:www\\.|http[s]?://)[\\w\\.\\?%&\\-/#=;:!\\+~]+)(?:\\](.+)\\[/url\\]|)', 'ig'); |
| 135 | ||
| 136 | 1 | TBase.prototype.process_text = function (status) { |
| 137 | 6 | var text = status.text; |
| 138 | 6 | if (!text) { |
| 139 | 3 | return ' '; |
| 140 | } | |
| 141 | 3 | text = utils.escape(text); |
| 142 | 3 | text = text.replace(this.URL_RE, this._replace_url); |
| 143 | ||
| 144 | 3 | text = this.process_at(text, status); //@*** |
| 145 | ||
| 146 | 3 | text = this.process_emotional(text, status); |
| 147 | ||
| 148 | 3 | text = this.process_search(text, status); //#xxXX# |
| 149 | ||
| 150 | 3 | text = emoji.unifiedToHTML(emoji.softbankToUnified(text)); |
| 151 | 3 | return text || ' '; |
| 152 | }; | |
| 153 | ||
| 154 | 1 | TBase.prototype._replace_url = function (m, g1, g2) { |
| 155 | 2 | var url = g1; |
| 156 | 2 | if (g1.indexOf('http') !== 0) { |
| 157 | 1 | url = 'http://' + g1; |
| 158 | } | |
| 159 | 2 | var tpl = '<a target="_blank" class="link" href="{{url}}">{{value}}</a>'; |
| 160 | 2 | return utils.format(tpl, { url: url, title: g1, value: g2 || g1 }); |
| 161 | }; | |
| 162 | ||
| 163 | 1 | TBase.prototype.SearchMatchReg = /#([^#]+)#/g; |
| 164 | 1 | TBase.prototype.process_search = function (text, status) { |
| 165 | 6 | var url = this.config.search_url; |
| 166 | 6 | return text.replace(this.SearchMatchReg, function (m, g1) { |
| 167 | // fixed #xxx@xxx# nesting problem | |
| 168 | 8 | var search = utils.removeHTML(g1); |
| 169 | 8 | var tpl = '<a target="_blank" href="{{url}}{{searchEncode}}" title="Search #{{search}}#">#{{search}}#</a>'; |
| 170 | 8 | return utils.format(tpl, {search: search, searchEncode: encodeURIComponent(search), url: url}); |
| 171 | }); | |
| 172 | }; | |
| 173 | ||
| 174 | // // return [[hash1, hash_value], ..., [#xxx#, xxx]] | |
| 175 | // TBase.prototype.findSearchText = function (text, status) { | |
| 176 | // var matchs = text.match(this.SearchMatchReg); | |
| 177 | // var result = []; | |
| 178 | // if (matchs) { | |
| 179 | // for (var i = 0, len = matchs.length; i < len; i++) { | |
| 180 | // var s = matchs[i]; | |
| 181 | // result.push([s, s.substring(1, s.length - 1)]); | |
| 182 | // } | |
| 183 | // } | |
| 184 | // return result; | |
| 185 | // }; | |
| 186 | ||
| 187 | // TBase.prototype.formatSearchText = function (str) { // æ ¼å¼åä¸»é¢ | |
| 188 | // return '#' + str.trim() + '#'; | |
| 189 | // }; | |
| 190 | ||
| 191 | 1 | TBase.prototype._at_match_rex = /@([â\w\-\_\u2E80-\u3000\u303F-\u9FFF]+)/g; |
| 192 | 1 | TBase.prototype.process_at = function (text, status) { |
| 193 | // Handle no-ascii | |
| 194 | //@*** u4e00-\u9fa5:䏿å符 \u2E80-\u9FFF:䏿¥é©å符 | |
| 195 | //ãè§ç¹Â·@ä»»å¿å¼ºãä»å¹´æåºç1000ä¸å¥çä¿éæ¿ä»»å¡å¯è½æ ¹æ¬å®ä¸æ | |
| 196 | // http://blog.oasisfeng.com/2006/10/19/full-cjk-unicode-range/ | |
| 197 | // CJKæ ç¹ç¬¦å·ï¼3000-303F | |
| 198 | 5 | var homeurl = this.config.user_home_url; |
| 199 | 5 | return text.replace(this._at_match_rex, function (m, g1) { |
| 200 | 4 | var url = homeurl + encodeURIComponent(g1); |
| 201 | 4 | return '<a class="at-user-link" href="' + url + '">@' + g1 + '</a>'; |
| 202 | }); | |
| 203 | }; | |
| 204 | ||
| 205 | // // è·åstré颿æ@ç¨æ·çåç§°å表ï¼ä¸å å«@符å | |
| 206 | // find_at_users: function (str) { | |
| 207 | // if (!str) { | |
| 208 | // return null; | |
| 209 | // } | |
| 210 | // var matchs = str.match(this._at_match_rex); | |
| 211 | // if (matchs) { | |
| 212 | // var users = []; | |
| 213 | // for(var i = 0, l = matchs.length; i < l; i++) { | |
| 214 | // var name = matchs[i].substring(1); | |
| 215 | // if(users.indexOf(name) < 0) { | |
| 216 | // users.push(name); | |
| 217 | // } | |
| 218 | // } | |
| 219 | // return users; | |
| 220 | // } | |
| 221 | // return null; | |
| 222 | // }, | |
| 223 | ||
| 224 | 1 | TBase.prototype.process_emotional = function (text, status) { |
| 225 | 3 | return text.replace(/\[([\u4e00-\u9fff,\uff1f,\w]{1,6})\]/g, this._replace_emotional.bind(this)); |
| 226 | }; | |
| 227 | ||
| 228 | 1 | TBase.prototype.EMOTION_TPL = '<img title="{{title}}" src="{{src}}" />'; |
| 229 | ||
| 230 | 1 | TBase.prototype._replace_emotional = function (m, g1) { |
| 231 | 0 | if (!g1) { |
| 232 | 0 | return m; |
| 233 | } | |
| 234 | // if (!this.bgEmotions && typeof getBackgroundView !== 'undefined') { | |
| 235 | // this.bgEmotions = getBackgroundView().Emotions; | |
| 236 | // if (this.bgEmotions) { | |
| 237 | // this.bgEmotions = this.bgEmotions.weibo; | |
| 238 | // } | |
| 239 | // } | |
| 240 | // var face = this.bgEmotions && this.bgEmotions[g1]; | |
| 241 | // if (!face) { | |
| 242 | // face = TSINA_API_EMOTIONS[g1]; | |
| 243 | // if (face) { | |
| 244 | // face = TSINA_FACE_URL_PRE + face; | |
| 245 | // } | |
| 246 | // } | |
| 247 | // if (face) { | |
| 248 | // return this.EMOTION_TPL.format({ title: m, src: face }); | |
| 249 | // } | |
| 250 | 0 | return m; |
| 251 | }; | |
| 252 | ||
| 253 | 1 | TBase.prototype.url_encode = function (text) { |
| 254 | 8 | return encodeURIComponent(text); |
| 255 | }; | |
| 256 | ||
| 257 | 1 | TBase.prototype._timeline = function (request_method, user, cursor, callback, playload) { |
| 258 | 32 | cursor = this.convert_cursor(cursor); |
| 259 | 32 | var params = { |
| 260 | type: 'GET', | |
| 261 | playload: playload || 'status[]', | |
| 262 | user: user, | |
| 263 | data: cursor, | |
| 264 | request_method: request_method | |
| 265 | }; | |
| 266 | 32 | var url = this.config[request_method]; |
| 267 | 32 | this.send_request(url, params, callback); |
| 268 | 32 | return this; |
| 269 | }; | |
| 270 | ||
| 271 | 1 | TBase.prototype.errorname = function (name) { |
| 272 | // get_access_token => GetAccessTokenError | |
| 273 | 21 | name = name.replace(/(?:^\w|\_\w)/g, function (m) { |
| 274 | 35 | if (m.length === 2) { |
| 275 | 14 | m = m.substring(1); |
| 276 | } | |
| 277 | 35 | return m.toUpperCase(); |
| 278 | }); | |
| 279 | 21 | return name + 'Error'; |
| 280 | }; | |
| 281 | ||
| 282 | 1 | TBase.prototype.detect_error = function (method, res, playload, data) { |
| 283 | 79 | if (res.statusCode === 200) { |
| 284 | 69 | return null; |
| 285 | } | |
| 286 | 10 | var errMessage = null; |
| 287 | 10 | if (method === 'get_request_token' || method === 'get_access_token') { |
| 288 | 1 | var token = querystring.parse(data); |
| 289 | 1 | if (token) { |
| 290 | 1 | errMessage = 'Get request token error, ' + (token.error_CN || token.error || data); |
| 291 | } else { | |
| 292 | 0 | errMessage = 'Get request token error, empty token string'; |
| 293 | } | |
| 294 | } else { | |
| 295 | 9 | errMessage = data.error_CN || data.error || data.message || data; |
| 296 | } | |
| 297 | 10 | var err = new Error(errMessage); |
| 298 | 10 | err.data = data; |
| 299 | 10 | err.name = this.errorname(method); |
| 300 | 10 | return err; |
| 301 | }; | |
| 302 | ||
| 303 | /** | |
| 304 | * å°è£ ææhttp请æ±ï¼èªå¨åºåå¤çhttpåhttps | |
| 305 | * args: { | |
| 306 | * data, | |
| 307 | * type: 'GET | POST | DELETE', | |
| 308 | * headers | |
| 309 | * } | |
| 310 | * callback.call(context, data, error, res || xhr) | |
| 311 | */ | |
| 312 | 1 | TBase.prototype.request = function (url, args, callback) { |
| 313 | 89 | var playload = args.playload; |
| 314 | 89 | if (playload !== 'string') { |
| 315 | 84 | args.dataType = 'json'; |
| 316 | } | |
| 317 | 89 | var self = this; |
| 318 | 89 | urllib.request(url, args, function (err, data, res) { |
| 319 | 89 | if (err) { |
| 320 | 0 | return callback(err); |
| 321 | } | |
| 322 | 89 | if (playload === 'string') { |
| 323 | 5 | data = data.toString(); |
| 324 | } | |
| 325 | // console.log(url, args, res.headers, res.statusCode, data) | |
| 326 | // console.log(data.data) | |
| 327 | 89 | err = self.detect_error(args.request_method, res, playload, data); |
| 328 | 89 | if (err) { |
| 329 | 20 | return callback(err); |
| 330 | } | |
| 331 | 69 | if (playload === 'string') { |
| 332 | 3 | return callback(null, data); |
| 333 | } | |
| 334 | 66 | callback(null, this.format_result(data, playload, args)); |
| 335 | }, this); | |
| 336 | }; | |
| 337 | ||
| 338 | 1 | TBase.prototype.send_request = function (url, params, callback) { |
| 339 | 83 | var args = { |
| 340 | type: 'GET', | |
| 341 | playload: 'status', | |
| 342 | headers: {} | |
| 343 | }; | |
| 344 | 83 | for (var k in params) { |
| 345 | 418 | args[k] = params[k]; |
| 346 | } | |
| 347 | 83 | args.type = (args.type || 'GET').toUpperCase(); |
| 348 | 83 | args.data = args.data || {}; |
| 349 | ||
| 350 | 83 | var user = args.user || args.data.user || {}; |
| 351 | 83 | args.user = user; |
| 352 | 83 | if (args.data && args.data.user) { |
| 353 | 0 | delete args.data.user; |
| 354 | } | |
| 355 | ||
| 356 | 83 | var api = args.api_host || this.config.host; |
| 357 | 83 | if (args.api_host) { |
| 358 | 5 | delete args.api_host; |
| 359 | } | |
| 360 | ||
| 361 | 83 | url = api + url.format(args.data); |
| 362 | // delete the url params | |
| 363 | 83 | url.replace(utils.STRING_FORMAT_REGEX, function (match, key) { |
| 364 | 0 | delete args.data[key]; |
| 365 | }); | |
| 366 | ||
| 367 | 83 | if (args.playload !== 'string' && this.config.result_format) { |
| 368 | 42 | url += this.config.result_format; |
| 369 | } | |
| 370 | ||
| 371 | 83 | this.apply_auth(url, args, user); |
| 372 | 83 | if (args.type === 'POST') { |
| 373 | 34 | args.headers['Content-Type'] = args.content_type || 'application/x-www-form-urlencoded;charset=UTF-8;'; |
| 374 | } | |
| 375 | 83 | this.request(url, args, callback); |
| 376 | }; | |
| 377 | ||
| 378 | /** | |
| 379 | * OAuth | |
| 380 | */ | |
| 381 | ||
| 382 | 1 | TBase.prototype.format_authorization_url = function (params) { |
| 383 | 6 | var login_url = (this.config.oauth_host || this.config.host) + this.config.oauth_authorize; |
| 384 | 6 | return OAuth.addToURL(login_url, params); |
| 385 | }; | |
| 386 | ||
| 387 | 1 | TBase.prototype.get_authorization_url = function (user, callback) { |
| 388 | 2 | var self = this; |
| 389 | 2 | self.get_request_token(user, function (err, token) { |
| 390 | 2 | var info = null; |
| 391 | 2 | if (err) { |
| 392 | 0 | return callback(err); |
| 393 | } | |
| 394 | 2 | if (token) { |
| 395 | 2 | var params = { |
| 396 | oauth_token: token.oauth_token, | |
| 397 | oauth_callback: user.oauth_callback || self.config.oauth_callback | |
| 398 | }; | |
| 399 | 2 | info = token; |
| 400 | 2 | info.blogtype = user.blogtype; |
| 401 | 2 | info.auth_url = self.format_authorization_url(params); |
| 402 | } | |
| 403 | 2 | callback(err, info); |
| 404 | }); | |
| 405 | 2 | return this; |
| 406 | }; | |
| 407 | ||
| 408 | 1 | TBase.prototype.get_request_token = function (user, callback) { |
| 409 | 2 | var self = this; |
| 410 | 2 | var url = self.config.oauth_request_token; |
| 411 | 2 | var params = { |
| 412 | type: 'GET', | |
| 413 | user: user, | |
| 414 | playload: 'string', | |
| 415 | data: { | |
| 416 | oauth_callback: user.oauth_callback || self.config.oauth_callback | |
| 417 | }, | |
| 418 | api_host: self.config.oauth_host, | |
| 419 | request_method: 'get_request_token' | |
| 420 | }; | |
| 421 | 2 | if (self.config.oauth_request_params) { |
| 422 | 0 | utils.extend(params.data, self.config.oauth_request_params); |
| 423 | } | |
| 424 | 2 | self.send_request(url, params, function (err, token) { |
| 425 | 2 | if (err) { |
| 426 | 0 | return callback(err); |
| 427 | } | |
| 428 | 2 | token = self.format_access_token(token); |
| 429 | 2 | token.blogtype = user.blogtype; |
| 430 | 2 | callback(null, token); |
| 431 | }); | |
| 432 | 2 | return this; |
| 433 | }, | |
| 434 | ||
| 435 | // user must contain oauth_pin or oauth_verifier | |
| 436 | TBase.prototype.get_access_token = function (user, callback) { | |
| 437 | 1 | if (!user.authtype) { |
| 438 | 1 | user.authtype = 'oauth'; |
| 439 | } | |
| 440 | 1 | var url = this.config.oauth_access_token; |
| 441 | 1 | var data = {}; |
| 442 | 1 | var params = { |
| 443 | type: 'GET', | |
| 444 | user: user, | |
| 445 | playload: 'string', | |
| 446 | data: data, | |
| 447 | api_host: this.config.oauth_host, | |
| 448 | request_method: 'get_access_token' | |
| 449 | }; | |
| 450 | 1 | var oauth_verifier = user.oauth_pin || user.oauth_verifier || 'no_verifier'; |
| 451 | 1 | if (oauth_verifier) { |
| 452 | 1 | data.oauth_verifier = oauth_verifier; |
| 453 | 1 | delete user.oauth_pin; |
| 454 | 1 | delete user.oauth_verifier; |
| 455 | } | |
| 456 | 1 | if (user.authtype === 'xauth') { |
| 457 | 0 | data.x_auth_username = user.username; |
| 458 | 0 | data.x_auth_password = user.password; |
| 459 | 0 | data.x_auth_mode = "client_auth"; |
| 460 | } | |
| 461 | 1 | this.send_request(url, params, function (err, token) { |
| 462 | 1 | if (err) { |
| 463 | 1 | return callback(err); |
| 464 | } | |
| 465 | 0 | token = querystring.parse(token); |
| 466 | 0 | token.blogtype = user.blogtype; |
| 467 | 0 | callback(null, token); |
| 468 | }); | |
| 469 | 1 | return this; |
| 470 | }; | |
| 471 | ||
| 472 | 1 | TBase.prototype.apply_auth = function (url, args, user) { |
| 473 | 40 | user.authtype = user.authtype || 'oauth'; |
| 474 | 40 | args.headers = args.headers || {}; |
| 475 | 40 | if (user.authtype === 'baseauth') { |
| 476 | 0 | if (user.username && user.password) { |
| 477 | 0 | args.headers.Authorization = urllib.make_base_auth_header(user.username, user.password); |
| 478 | } | |
| 479 | 40 | } else if (user.authtype === 'oauth' || user.authtype === 'xauth') { |
| 480 | 40 | var accessor = { |
| 481 | consumerSecret: this.config.secret | |
| 482 | }; | |
| 483 | // å·²éè¿oauthè®¤è¯ | |
| 484 | 40 | if (user.oauth_token_secret) { |
| 485 | 38 | accessor.tokenSecret = user.oauth_token_secret; |
| 486 | } | |
| 487 | 40 | var parameters = {}; |
| 488 | ||
| 489 | 40 | for (var k in args.data) { |
| 490 | 134 | parameters[k] = args.data[k]; |
| 491 | 134 | if (k.substring(0, 6) === 'oauth_') { // å é¤oauth_verifierç¸å ³åæ° |
| 492 | 3 | delete args.data[k]; |
| 493 | } | |
| 494 | } | |
| 495 | ||
| 496 | 40 | var message = { |
| 497 | action: url, | |
| 498 | method: args.type, | |
| 499 | parameters: parameters | |
| 500 | }; | |
| 501 | 40 | message.parameters.oauth_consumer_key = this.config.appkey; |
| 502 | 40 | message.parameters.oauth_version = '1.0'; |
| 503 | ||
| 504 | // å·²éè¿oauthè®¤è¯ | |
| 505 | 40 | if (user.oauth_token) { |
| 506 | 38 | message.parameters.oauth_token = user.oauth_token; |
| 507 | } | |
| 508 | // 设置æ¶é´æ³ | |
| 509 | 40 | OAuth.setTimestampAndNonce(message); |
| 510 | // ç¾ååæ° | |
| 511 | // console.log(message.parameters); | |
| 512 | 40 | OAuth.SignatureMethod.sign(message, accessor); |
| 513 | // oauthåæ°éè¿getæ¹å¼ä¼ é | |
| 514 | 40 | if (this.config.oauth_params_by_get) { |
| 515 | 40 | args.data = message.parameters; |
| 516 | //console.log(args.data); | |
| 517 | } else { | |
| 518 | // è·å认è¯å¤´é¨ | |
| 519 | 0 | args.headers.Authorization = OAuth.getAuthorizationHeader(this.config.oauth_realm, message.parameters); |
| 520 | } | |
| 521 | } | |
| 522 | }; | |
| 523 | ||
| 524 | /** | |
| 525 | * Result getters | |
| 526 | */ | |
| 527 | ||
| 528 | 1 | TBase.prototype.get_result_items = function (data, playload, args) { |
| 529 | 0 | throw new Error('Must override this method'); |
| 530 | }; | |
| 531 | ||
| 532 | 1 | TBase.prototype.get_result_item = function (data, playload, args) { |
| 533 | 31 | return data; |
| 534 | }; | |
| 535 | ||
| 536 | 1 | TBase.prototype.get_pagging_cursor = function (data, playload, args) { |
| 537 | 35 | return {}; |
| 538 | }; | |
| 539 | ||
| 540 | /** | |
| 541 | * Result formaters | |
| 542 | */ | |
| 543 | ||
| 544 | 1 | TBase.prototype.format_result = function (data, playload, args) { |
| 545 | // status[]: need Array and item type is `status` | |
| 546 | // status: need item, type is `status` | |
| 547 | 66 | var index = playload.indexOf('[]'); |
| 548 | 66 | var isList = index > 0; |
| 549 | 66 | if (isList) { |
| 550 | 35 | var itemPlayload = playload.substring(0, index); |
| 551 | 35 | var items = this.get_result_items(data, itemPlayload, args) || []; |
| 552 | 35 | for (var i = 0; i < items.length; i++) { |
| 553 | 343 | items[i] = this.format_result_item(items[i], itemPlayload, args); |
| 554 | } | |
| 555 | 35 | var result = {}; |
| 556 | 35 | result.items = items; |
| 557 | // try to get pagging cursor. | |
| 558 | 35 | result.cursor = this.get_pagging_cursor(data, itemPlayload, args); |
| 559 | 35 | return result; |
| 560 | } | |
| 561 | ||
| 562 | 31 | var item = this.get_result_item(data, playload, args); |
| 563 | 31 | return this.format_result_item(item, playload, args); |
| 564 | }; | |
| 565 | ||
| 566 | 1 | TBase.prototype.format_result_item = function (data, playload, args) { |
| 567 | 374 | var method = 'format_' + playload; |
| 568 | 374 | return this[method](data, args); |
| 569 | }; | |
| 570 | ||
| 571 | 1 | TBase.prototype.format_search_status = function (status, args) { |
| 572 | 0 | throw new Error('Must override this method.'); |
| 573 | }; | |
| 574 | ||
| 575 | 1 | TBase.prototype.format_status = function (status, args) { |
| 576 | 0 | throw new Error('Must override this method.'); |
| 577 | }; | |
| 578 | ||
| 579 | 1 | TBase.prototype.format_user = function (user, args) { |
| 580 | 0 | throw new Error('Must override this method.'); |
| 581 | }; | |
| 582 | ||
| 583 | 1 | TBase.prototype.format_comment = function (comment, args) { |
| 584 | 0 | throw new Error('Must override this method.'); |
| 585 | }; | |
| 586 | ||
| 587 | 1 | TBase.prototype.format_message = function (message, args) { |
| 588 | 0 | throw new Error('Must override this method.'); |
| 589 | }; | |
| 590 | ||
| 591 | 1 | TBase.prototype.format_emotion = function (emotion, args) { |
| 592 | 0 | throw new Error('Must override this method.'); |
| 593 | }; | |
| 594 | ||
| 595 | 1 | TBase.prototype.format_access_token = function (token) { |
| 596 | 2 | return querystring.parse(token); |
| 597 | }; | |
| 598 | ||
| 599 | 1 | TBase.prototype.format_count = function (count, args) { |
| 600 | 0 | throw new Error('Must override this method.'); |
| 601 | }; | |
| 602 | ||
| 603 | 1 | TBase.prototype.format_favorite = function (favorite, args) { |
| 604 | 0 | throw new Error('Must override this method.'); |
| 605 | }; | |
| 606 | ||
| 607 | /** | |
| 608 | * Params converters | |
| 609 | */ | |
| 610 | ||
| 611 | 1 | TBase.prototype.convert_cursor = function (cursor) { |
| 612 | 19 | return cursor; |
| 613 | }; | |
| 614 | ||
| 615 | 1 | TBase.prototype.convert_status = function (status) { |
| 616 | 9 | return status; |
| 617 | }; | |
| 618 | ||
| 619 | 1 | TBase.prototype.convert_comment = function (comment) { |
| 620 | 8 | return comment; |
| 621 | }; | |
| 622 | ||
| 623 | 1 | TBase.prototype.convert_user = function (data) { |
| 624 | 4 | return data; |
| 625 | }; | |
| 626 | ||
| 627 | 1 | TBase.prototype.convert_ids = function (ids) { |
| 628 | 2 | return {ids: ids}; |
| 629 | }; | |
| 630 | ||
| 631 | 1 | TBase.prototype.convert_favorite = function (id) { |
| 632 | 0 | return {id: id}; |
| 633 | }; | |
| 634 | ||
| 635 | /** | |
| 636 | * User | |
| 637 | */ | |
| 638 | ||
| 639 | 1 | TBase.prototype.verify_credentials = function (user, callback) { |
| 640 | 2 | var params = { |
| 641 | type: 'GET', | |
| 642 | user: user, | |
| 643 | playload: 'user', | |
| 644 | request_method: 'verify_credentials' | |
| 645 | }; | |
| 646 | 2 | var url = this.config.verify_credentials; |
| 647 | 2 | this.send_request(url, params, callback); |
| 648 | 2 | return this; |
| 649 | }; | |
| 650 | ||
| 651 | 1 | TBase.prototype.user_show = function (user, uid, screen_name, callback) { |
| 652 | 5 | var data = {}; |
| 653 | 5 | if (uid) { |
| 654 | 5 | data.uid = uid; |
| 655 | } | |
| 656 | 5 | if (screen_name) { |
| 657 | 1 | data.screen_name = screen_name; |
| 658 | 1 | delete data.uid; // only support one |
| 659 | } | |
| 660 | 5 | data = this.convert_user(data); |
| 661 | 5 | var params = { |
| 662 | type: 'GET', | |
| 663 | user: user, | |
| 664 | data: data, | |
| 665 | playload: 'user', | |
| 666 | request_method: 'user_show' | |
| 667 | }; | |
| 668 | 5 | var url = this.config.user_show; |
| 669 | 5 | this.send_request(url, params, callback); |
| 670 | 5 | return this; |
| 671 | }; | |
| 672 | ||
| 673 | /** | |
| 674 | * Status APIs | |
| 675 | */ | |
| 676 | ||
| 677 | 1 | TBase.prototype.update = function (user, status, callback) { |
| 678 | 8 | status = this.convert_status(status); |
| 679 | 8 | var params = { |
| 680 | type: 'POST', | |
| 681 | playload: 'status', | |
| 682 | user: user, | |
| 683 | data: status, | |
| 684 | request_method: 'update' | |
| 685 | }; | |
| 686 | 8 | var url = this.config.update; |
| 687 | 8 | this.send_request(url, params, callback); |
| 688 | 8 | return this; |
| 689 | }; | |
| 690 | ||
| 691 | 1 | TBase.prototype.upload = function (user, status, pic, callback) { |
| 692 | 6 | status = this.convert_status(status); |
| 693 | 6 | pic.name = pic.name || 'node-weibo-upload-image.jpg'; |
| 694 | 6 | if (!pic.content_type) { |
| 695 | 6 | pic.content_type = utils.mimeLookup(pic.name); |
| 696 | } | |
| 697 | 6 | if (Buffer.isBuffer(pic.data)) { |
| 698 | 0 | this._upload(user, status, pic, callback); |
| 699 | 0 | return this; |
| 700 | } | |
| 701 | 6 | var buffers = []; |
| 702 | 6 | var size = 0; |
| 703 | 6 | var self = this; |
| 704 | 6 | pic.data.on('data', function (chunk) { |
| 705 | 6 | size += chunk.length; |
| 706 | 6 | buffers.push(chunk); |
| 707 | }); | |
| 708 | 6 | pic.data.once('end', function () { |
| 709 | 6 | pic.data = Buffer.concat(buffers, size); |
| 710 | 6 | self._upload(user, status, pic, callback); |
| 711 | }); | |
| 712 | 6 | pic.data.once('error', function (err) { |
| 713 | 0 | callback(err); |
| 714 | }); | |
| 715 | 6 | return this; |
| 716 | }; | |
| 717 | ||
| 718 | 1 | TBase.prototype._upload = function (user, data, pic, callback) { |
| 719 | 6 | var auth_args = { |
| 720 | type: 'post', | |
| 721 | data: {}, | |
| 722 | headers: {} | |
| 723 | }; | |
| 724 | 6 | var pic_field = this.config.pic_field || 'pic'; |
| 725 | 6 | var boundary = 'boundary' + Date.now(); |
| 726 | // this.format_upload_params(user, data, pic , boundary); | |
| 727 | 6 | var dashdash = '--'; |
| 728 | 6 | var crlf = '\r\n'; |
| 729 | ||
| 730 | /* RFC2388 */ | |
| 731 | 6 | var builder = ''; |
| 732 | ||
| 733 | 6 | builder += dashdash; |
| 734 | 6 | builder += boundary; |
| 735 | 6 | builder += crlf; |
| 736 | ||
| 737 | 6 | var key; |
| 738 | 6 | for (key in data) { |
| 739 | 10 | var value = this.url_encode(data[key]); |
| 740 | 10 | auth_args.data[key] = value; |
| 741 | } | |
| 742 | ||
| 743 | 6 | var api = this.config.host; |
| 744 | 6 | var url = api + this.config.upload + this.config.result_format; |
| 745 | ||
| 746 | // 设置认è¯å¤´é¨ | |
| 747 | 6 | this.apply_auth(url, auth_args, user); |
| 748 | ||
| 749 | 6 | for (key in auth_args.data) { |
| 750 | /* Generate headers. key */ | |
| 751 | 34 | builder += 'Content-Disposition: form-data; name="' + key + '"'; |
| 752 | 34 | builder += crlf; |
| 753 | 34 | builder += crlf; |
| 754 | /* Append form data. */ | |
| 755 | 34 | builder += auth_args.data[key]; |
| 756 | 34 | builder += crlf; |
| 757 | ||
| 758 | /* Write boundary. */ | |
| 759 | 34 | builder += dashdash; |
| 760 | 34 | builder += boundary; |
| 761 | 34 | builder += crlf; |
| 762 | } | |
| 763 | /* Generate headers. [PIC] */ | |
| 764 | 6 | builder += 'Content-Disposition: form-data; name="' + pic_field + '"'; |
| 765 | ||
| 766 | 6 | builder += '; filename="' + this.url_encode(pic.name) + '"'; |
| 767 | 6 | builder += crlf; |
| 768 | ||
| 769 | 6 | builder += 'Content-Type: ' + pic.content_type + ';'; |
| 770 | 6 | builder += crlf; |
| 771 | 6 | builder += crlf; |
| 772 | ||
| 773 | 6 | var endstr = crlf + dashdash + boundary + dashdash + crlf; |
| 774 | 6 | var builderLength = Buffer.byteLength(builder); |
| 775 | 6 | var size = builderLength + pic.data.length + endstr.length; |
| 776 | 6 | var buffer = new Buffer(size); |
| 777 | 6 | var offset = 0; |
| 778 | 6 | buffer.write(builder); |
| 779 | 6 | offset += builderLength ; |
| 780 | 6 | pic.data.copy(buffer, offset); |
| 781 | 6 | offset += pic.data.length; |
| 782 | 6 | buffer.write(endstr, offset); |
| 783 | // if (typeof BlobBuilder === 'undefined') { | |
| 784 | // } | |
| 785 | // else { | |
| 786 | // buffer = new BlobBuilder(); //NOTE WebKitBlogBuilder | |
| 787 | // buffer.append(builder); | |
| 788 | // buffer.append(pic); | |
| 789 | // buffer.append(endstr); | |
| 790 | // buffer = buffer.getBlob(); | |
| 791 | // } | |
| 792 | 6 | auth_args.headers['Content-Type'] = 'multipart/form-data;boundary=' + boundary; |
| 793 | 6 | var params = { |
| 794 | type: 'POST', | |
| 795 | playload: 'status', | |
| 796 | content: buffer, | |
| 797 | headers: auth_args.headers, | |
| 798 | request_method: 'upload' | |
| 799 | }; | |
| 800 | 6 | this.request(url, params, callback); |
| 801 | 6 | return this; |
| 802 | }; | |
| 803 | ||
| 804 | 1 | TBase.prototype.repost = function (user, id, status, callback) { |
| 805 | 4 | status.id = id; |
| 806 | 4 | status = this.convert_status(status); |
| 807 | 4 | var params = { |
| 808 | type: 'POST', | |
| 809 | playload: 'status', | |
| 810 | user: user, | |
| 811 | data: status, | |
| 812 | request_method: 'repost' | |
| 813 | }; | |
| 814 | 4 | var url = this.config.repost; |
| 815 | 4 | this.send_request(url, params, callback); |
| 816 | 4 | return this; |
| 817 | }; | |
| 818 | ||
| 819 | 1 | TBase.prototype.destroy = function (user, id, callback) { |
| 820 | 6 | var params = { |
| 821 | type: 'POST', | |
| 822 | playload: 'status', | |
| 823 | user: user, | |
| 824 | data: {id: id}, | |
| 825 | request_method: 'destroy' | |
| 826 | }; | |
| 827 | 6 | var url = this.config.destroy; |
| 828 | 6 | this.send_request(url, params, callback); |
| 829 | 6 | return this; |
| 830 | }; | |
| 831 | ||
| 832 | 1 | TBase.prototype.show = function (user, id, callback) { |
| 833 | 2 | var params = { |
| 834 | type: 'GET', | |
| 835 | playload: 'status', | |
| 836 | user: user, | |
| 837 | data: { | |
| 838 | id: id | |
| 839 | }, | |
| 840 | request_method: 'show' | |
| 841 | }; | |
| 842 | 2 | var url = this.config.show; |
| 843 | 2 | this.send_request(url, params, callback); |
| 844 | 2 | return this; |
| 845 | }; | |
| 846 | ||
| 847 | 1 | TBase.prototype.count = function (user, ids, callback) { |
| 848 | 4 | var data = this.convert_ids(ids); |
| 849 | 4 | var params = { |
| 850 | type: 'GET', | |
| 851 | playload: 'count[]', | |
| 852 | user: user, | |
| 853 | data: data, | |
| 854 | request_method: 'count' | |
| 855 | }; | |
| 856 | 4 | var url = this.config.count; |
| 857 | 4 | this.send_request(url, params, function (err, result) { |
| 858 | 4 | if (err) { |
| 859 | 2 | return callback(err); |
| 860 | } | |
| 861 | 2 | callback(null, result.items); |
| 862 | }); | |
| 863 | 4 | return this; |
| 864 | }; | |
| 865 | ||
| 866 | 1 | TBase.prototype.home_timeline = function (user, cursor, callback) { |
| 867 | 4 | return this._timeline('home_timeline', user, cursor, callback); |
| 868 | }; | |
| 869 | ||
| 870 | 1 | TBase.prototype.user_timeline = function (user, cursor, callback) { |
| 871 | 4 | return this._timeline('user_timeline', user, cursor, callback); |
| 872 | }; | |
| 873 | ||
| 874 | 1 | TBase.prototype.public_timeline = function (user, cursor, callback) { |
| 875 | 4 | return this._timeline('public_timeline', user, cursor, callback); |
| 876 | }; | |
| 877 | ||
| 878 | 1 | TBase.prototype.mentions = function (user, cursor, callback) { |
| 879 | 4 | return this._timeline('mentions', user, cursor, callback); |
| 880 | }; | |
| 881 | ||
| 882 | 1 | TBase.prototype.repost_timeline = function (user, cursor, callback) { |
| 883 | 2 | return this._timeline('repost_timeline', user, cursor, callback); |
| 884 | }; | |
| 885 | ||
| 886 | 1 | TBase.prototype.search = function (user, query, cursor, callback) { |
| 887 | 1 | cursor = cursor || {}; |
| 888 | 1 | cursor.count = cursor.count || 20; |
| 889 | 1 | cursor = this.convert_cursor(cursor); |
| 890 | 1 | query = utils.extend(query, cursor); |
| 891 | 1 | var params = { |
| 892 | type: 'GET', | |
| 893 | playload: 'status[]', | |
| 894 | user: user, | |
| 895 | data: query, | |
| 896 | request_method: 'search' | |
| 897 | }; | |
| 898 | 1 | var url = this.config.search; |
| 899 | 1 | this.send_request(url, params, callback); |
| 900 | 1 | return this; |
| 901 | }; | |
| 902 | ||
| 903 | /** | |
| 904 | * Favorite | |
| 905 | */ | |
| 906 | ||
| 907 | 1 | TBase.prototype.favorites = function (user, cursor, callback) { |
| 908 | 2 | return this._timeline('favorites', user, cursor, callback, 'favorite[]'); |
| 909 | }; | |
| 910 | ||
| 911 | 1 | TBase.prototype.favorite_request = function (type, name, user, id, callback) { |
| 912 | 0 | var data = this.convert_favorite(id); |
| 913 | 0 | var params = { |
| 914 | type: type, | |
| 915 | playload: 'favorite', | |
| 916 | user: user, | |
| 917 | data: data, | |
| 918 | request_method: name | |
| 919 | }; | |
| 920 | 0 | var url = this.config[name]; |
| 921 | 0 | this.send_request(url, params, callback); |
| 922 | 0 | return this; |
| 923 | }; | |
| 924 | ||
| 925 | 1 | TBase.prototype.favorite_show = function (user, id, callback) { |
| 926 | 0 | return this.favorite_request('GET', 'favorite_show', user, id, callback); |
| 927 | }; | |
| 928 | ||
| 929 | 1 | TBase.prototype.favorite_create = function (user, id, callback) { |
| 930 | 0 | return this.favorite_request('POST', 'favorite_create', user, id, callback); |
| 931 | }; | |
| 932 | ||
| 933 | 1 | TBase.prototype.favorite_destroy = function (user, id, callback) { |
| 934 | 0 | return this.favorite_request('POST', 'favorite_destroy', user, id, callback); |
| 935 | }; | |
| 936 | ||
| 937 | /** | |
| 938 | * Comment | |
| 939 | */ | |
| 940 | ||
| 941 | 1 | TBase.prototype.comments = function (user, cursor, callback) { |
| 942 | 2 | return this._timeline('comments', user, cursor, callback, 'comment[]'); |
| 943 | }; | |
| 944 | ||
| 945 | 1 | TBase.prototype.comments_timeline = function (user, cursor, callback) { |
| 946 | 4 | return this._timeline('comments_timeline', user, cursor, callback, 'comment[]'); |
| 947 | }; | |
| 948 | ||
| 949 | 1 | TBase.prototype.comments_mentions = function (user, cursor, callback) { |
| 950 | 2 | return this._timeline('comments_mentions', user, cursor, callback, 'comment[]'); |
| 951 | }; | |
| 952 | ||
| 953 | 1 | TBase.prototype.comments_to_me = function (user, cursor, callback) { |
| 954 | 2 | return this._timeline('comments_to_me', user, cursor, callback, 'comment[]'); |
| 955 | }; | |
| 956 | ||
| 957 | 1 | TBase.prototype.comments_by_me = function (user, cursor, callback) { |
| 958 | 2 | return this._timeline('comments_by_me', user, cursor, callback, 'comment[]'); |
| 959 | }; | |
| 960 | ||
| 961 | 1 | TBase.prototype.comment_create = function (user, id, comment, callback) { |
| 962 | 7 | comment.id = id; |
| 963 | 7 | comment = this.convert_comment(comment); |
| 964 | 7 | var params = { |
| 965 | type: 'POST', | |
| 966 | playload: 'comment', | |
| 967 | user: user, | |
| 968 | data: comment, | |
| 969 | request_method: 'comment_create' | |
| 970 | }; | |
| 971 | 7 | var url = this.config.comment_create; |
| 972 | 7 | this.send_request(url, params, callback); |
| 973 | 7 | return this; |
| 974 | }; | |
| 975 | ||
| 976 | 1 | TBase.prototype.comment_reply = function (user, cid, id, comment, callback) { |
| 977 | 6 | comment.id = id; |
| 978 | 6 | comment.cid = cid; |
| 979 | 6 | comment = this.convert_comment(comment); |
| 980 | 6 | var params = { |
| 981 | type: 'POST', | |
| 982 | playload: 'comment', | |
| 983 | user: user, | |
| 984 | data: comment, | |
| 985 | request_method: 'comment_reply' | |
| 986 | }; | |
| 987 | 6 | var url = this.config.comment_reply; |
| 988 | 6 | this.send_request(url, params, callback); |
| 989 | 6 | return this; |
| 990 | }; | |
| 991 | ||
| 992 | 1 | TBase.prototype.comment_destroy = function (user, cid, callback) { |
| 993 | 1 | var comment = {cid: cid}; |
| 994 | 1 | comment = this.convert_comment(comment); |
| 995 | 1 | var params = { |
| 996 | type: 'POST', | |
| 997 | playload: 'comment', | |
| 998 | user: user, | |
| 999 | data: comment, | |
| 1000 | request_method: 'comment_destroy' | |
| 1001 | }; | |
| 1002 | 1 | var url = this.config.comment_destroy; |
| 1003 | 1 | this.send_request(url, params, callback); |
| 1004 | 1 | return this; |
| 1005 | }; | |
| 1006 |
| Line | Hits | Source |
|---|---|---|
| 1 | /* | |
| 2 | * Copyright 2008 Netflix, Inc. | |
| 3 | * | |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | * you may not use this file except in compliance with the License. | |
| 6 | * You may obtain a copy of the License at | |
| 7 | * | |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | * | |
| 10 | * Unless required by applicable law or agreed to in writing, software | |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | * See the License for the specific language governing permissions and | |
| 14 | * limitations under the License. | |
| 15 | */ | |
| 16 | // Here's some JavaScript software that's useful for implementing OAuth. | |
| 17 | // The HMAC-SHA1 signature method calls b64_hmac_sha1, defined by | |
| 18 | // http://pajhome.org.uk/crypt/md5/sha1.js | |
| 19 | /* An OAuth message is represented as an object like this: | |
| 20 | {method: "GET", action: "http://server.com/path", parameters: ...} | |
| 21 | The parameters may be either a map {name: value, name2: value2} | |
| 22 | or an Array of name-value pairs [[name, value], [name2, value2]]. | |
| 23 | The latter representation is more powerful: it supports parameters | |
| 24 | in a specific sequence, or several parameters with the same name; | |
| 25 | for example [["a", 1], ["b", 2], ["a", 3]]. | |
| 26 | Parameter names and values are NOT percent-encoded in an object. | |
| 27 | They must be encoded before transmission and decoded after reception. | |
| 28 | For example, this message object: | |
| 29 | {method: "GET", action: "http://server/path", parameters: {p: "x y"}} | |
| 30 | ... can be transmitted as an HTTP request that begins: | |
| 31 | GET /path?p=x%20y HTTP/1.0 | |
| 32 | (This isn't a valid OAuth request, since it lacks a signature etc.) | |
| 33 | Note that the object "x y" is transmitted as x%20y. To encode | |
| 34 | parameters, you can call OAuth.addToURL, OAuth.formEncode or | |
| 35 | OAuth.getAuthorization. | |
| 36 | This message object model harmonizes with the browser object model for | |
| 37 | input elements of an form, whose value property isn't percent encoded. | |
| 38 | The browser encodes each value before transmitting it. For example, | |
| 39 | see consumer.setInputs in example/consumer.js. | |
| 40 | */ | |
| 41 | ||
| 42 | 1 | (function () { |
| 43 | ||
| 44 | 1 | var utils; |
| 45 | 1 | if (typeof require !== 'undefined') { |
| 46 | 1 | utils = require('./utils'); |
| 47 | } else { | |
| 48 | 0 | utils = weibo.utils; |
| 49 | } | |
| 50 | ||
| 51 | 1 | var OAuth = {}; |
| 52 | ||
| 53 | 1 | OAuth.setProperties = function setProperties(into, from) { |
| 54 | 3 | if (into && from) { |
| 55 | 3 | for (var key in from) { |
| 56 | 24 | into[key] = from[key]; |
| 57 | } | |
| 58 | } | |
| 59 | 3 | return into; |
| 60 | }; | |
| 61 | ||
| 62 | // utility functions | |
| 63 | 1 | OAuth.setProperties(OAuth, { |
| 64 | percentEncode: function percentEncode(s) { | |
| 65 | 980 | if (!s) { |
| 66 | 6 | return ""; |
| 67 | } | |
| 68 | 974 | if (s instanceof Array) { |
| 69 | 0 | var e = ""; |
| 70 | 0 | for (var i = 0; i < s.length; ++s) { |
| 71 | 0 | if (e) { |
| 72 | 0 | e += '&'; |
| 73 | } | |
| 74 | 0 | e += percentEncode(s[i]); |
| 75 | } | |
| 76 | 0 | return e; |
| 77 | } | |
| 78 | 974 | s = encodeURIComponent(s); |
| 79 | // Now replace the values which encodeURIComponent doesn't do | |
| 80 | // encodeURIComponent ignores: - _ . ! ~ * ' ( ) | |
| 81 | // OAuth dictates the only ones you can ignore are: - _ . ~ | |
| 82 | // Source: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURIComponent | |
| 83 | 974 | s = s.replace(/\!/g, "%21"); |
| 84 | 974 | s = s.replace(/\*/g, "%2A"); |
| 85 | 974 | s = s.replace(/\'/g, "%27"); |
| 86 | // s = s.replace("(", "%28", "g"); | |
| 87 | 974 | s = s.replace(/\(/g, "%28"); |
| 88 | 974 | s = s.replace(/\)/g, "%29"); |
| 89 | 974 | return s; |
| 90 | }, | |
| 91 | decodePercent: decodeURIComponent, | |
| 92 | /** Convert the given parameters to an Array of name-value pairs. */ | |
| 93 | getParameterList: function getParameterList(parameters) { | |
| 94 | 86 | if (!parameters) { |
| 95 | 0 | return []; |
| 96 | } | |
| 97 | 86 | if (typeof parameters !== "object") { |
| 98 | 0 | return this.decodeForm(parameters + ""); |
| 99 | } | |
| 100 | 86 | if (parameters instanceof Array) { |
| 101 | 40 | return parameters; |
| 102 | } | |
| 103 | 46 | var list = []; |
| 104 | 46 | for (var p in parameters) { |
| 105 | 390 | list.push([ p, parameters[p] ]); |
| 106 | } | |
| 107 | 46 | return list; |
| 108 | }, | |
| 109 | /** Convert the given parameters to a map from name to value. */ | |
| 110 | getParameterMap: function getParameterMap(parameters) { | |
| 111 | 200 | if (!parameters) { |
| 112 | 0 | return {}; |
| 113 | } | |
| 114 | 200 | if (typeof parameters !== "object") { |
| 115 | 0 | return this.getParameterMap(this.decodeForm(parameters + "")); |
| 116 | } | |
| 117 | 200 | if (parameters instanceof Array) { |
| 118 | 0 | var map = {}; |
| 119 | 0 | for (var p = 0; p < parameters.length; ++p) { |
| 120 | 0 | var key = parameters[p][0]; |
| 121 | 0 | if (map[key] === undefined) { // first value wins |
| 122 | 0 | map[key] = parameters[p][1]; |
| 123 | } | |
| 124 | } | |
| 125 | 0 | return map; |
| 126 | } | |
| 127 | 200 | return parameters; |
| 128 | }, | |
| 129 | formEncode: function formEncode(parameters) { | |
| 130 | 46 | var form = ""; |
| 131 | 46 | var list = OAuth.getParameterList(parameters); |
| 132 | 46 | for (var p = 0, l = list.length; p < l; p++) { |
| 133 | 390 | var pair = list[p]; |
| 134 | 390 | var value = pair[1]; |
| 135 | 390 | if (!value) { |
| 136 | 4 | value = ""; |
| 137 | } | |
| 138 | 390 | if (form) { |
| 139 | 344 | form += '&'; |
| 140 | } | |
| 141 | 390 | form += OAuth.percentEncode(pair[0]) + '=' + OAuth.percentEncode(value); |
| 142 | } | |
| 143 | 46 | return form; |
| 144 | }, | |
| 145 | decodeForm: function decodeForm(form) { | |
| 146 | 0 | var list = []; |
| 147 | 0 | var nvps = form.split('&'); |
| 148 | 0 | for (var n = 0; n < nvps.length; ++n) { |
| 149 | 0 | var nvp = nvps[n]; |
| 150 | 0 | if (!nvp) { |
| 151 | 0 | continue; |
| 152 | } | |
| 153 | 0 | var equals = nvp.indexOf('='); |
| 154 | 0 | var name; |
| 155 | 0 | var value; |
| 156 | 0 | if (equals < 0) { |
| 157 | 0 | name = OAuth.decodePercent(nvp); |
| 158 | 0 | value = null; |
| 159 | } else { | |
| 160 | 0 | name = OAuth.decodePercent(nvp.substring(0, equals)); |
| 161 | 0 | value = OAuth.decodePercent(nvp.substring(equals + 1)); |
| 162 | } | |
| 163 | 0 | list.push([name, value]); |
| 164 | } | |
| 165 | 0 | return list; |
| 166 | }, | |
| 167 | setParameter: function setParameter(message, name, value) { | |
| 168 | 160 | var parameters = message.parameters; |
| 169 | 160 | if (parameters instanceof Array) { |
| 170 | 0 | for (var p = 0; p < parameters.length; ++p) { |
| 171 | 0 | if (parameters[p][0] === name) { |
| 172 | 0 | if (value === undefined) { |
| 173 | 0 | parameters.splice(p, 1); |
| 174 | } else { | |
| 175 | 0 | parameters[p][1] = value; |
| 176 | 0 | value = undefined; |
| 177 | } | |
| 178 | } | |
| 179 | } | |
| 180 | 0 | if (value !== undefined) { |
| 181 | 0 | parameters.push([name, value]); |
| 182 | } | |
| 183 | } else { | |
| 184 | 160 | parameters = OAuth.getParameterMap(parameters); |
| 185 | 160 | parameters[name] = value; |
| 186 | 160 | message.parameters = parameters; |
| 187 | } | |
| 188 | }, | |
| 189 | setParameters: function setParameters(message, parameters) { | |
| 190 | 0 | var list = OAuth.getParameterList(parameters); |
| 191 | 0 | for (var i = 0; i < list.length; ++i) { |
| 192 | 0 | OAuth.setParameter(message, list[i][0], list[i][1]); |
| 193 | } | |
| 194 | }, | |
| 195 | setTimestampAndNonce: function setTimestampAndNonce(message) { | |
| 196 | 40 | OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp()); |
| 197 | 40 | OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(32)); |
| 198 | }, | |
| 199 | addToURL: function addToURL(url, parameters) { | |
| 200 | 6 | if (parameters) { |
| 201 | 6 | var toAdd = OAuth.formEncode(parameters); |
| 202 | 6 | if (toAdd) { |
| 203 | 6 | if (url.indexOf('?') < 0) { |
| 204 | 6 | url += '?'; |
| 205 | } else { | |
| 206 | 0 | url += '&'; |
| 207 | } | |
| 208 | 6 | url += toAdd; |
| 209 | } | |
| 210 | } | |
| 211 | 6 | return url; |
| 212 | }, | |
| 213 | /** Construct the value of the Authorization header for an HTTP request. */ | |
| 214 | getAuthorizationHeader: function getAuthorizationHeader(realm, parameters) { | |
| 215 | 0 | var header = ''; |
| 216 | 0 | if (realm) { |
| 217 | 0 | header += ', realm="' + OAuth.percentEncode(realm) + '"'; |
| 218 | } | |
| 219 | 0 | var list = OAuth.getParameterList(parameters); |
| 220 | 0 | for (var p = 0; p < list.length; ++p) { |
| 221 | 0 | var parameter = list[p]; |
| 222 | 0 | var name = parameter[0]; |
| 223 | 0 | if (name.indexOf("oauth_") === 0) { |
| 224 | 0 | header += ', ' + OAuth.percentEncode(name) + '="' + OAuth.percentEncode(parameter[1]) + '"'; |
| 225 | } | |
| 226 | } | |
| 227 | 0 | return 'OAuth ' + header.substring(2); |
| 228 | }, | |
| 229 | ||
| 230 | timestamp: function timestamp() { | |
| 231 | 41 | return Math.floor(new Date().getTime() / 1000); |
| 232 | }, | |
| 233 | ||
| 234 | nonce: function nonce(length) { | |
| 235 | 141 | if (!length) { |
| 236 | 2 | return ''; |
| 237 | } | |
| 238 | 139 | var chars = OAuth.nonce.CHARS; |
| 239 | 139 | var result = ""; |
| 240 | 139 | for (var i = 0; i < length; ++i) { |
| 241 | 6230 | var rnum = Math.floor(Math.random() * chars.length); |
| 242 | 6230 | result += chars.substring(rnum, rnum + 1); |
| 243 | } | |
| 244 | 139 | return result; |
| 245 | } | |
| 246 | }); | |
| 247 | ||
| 248 | 1 | OAuth.nonce.CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; |
| 249 | /** Define a constructor function, | |
| 250 | without causing trouble to anyone who was using it as a namespace. | |
| 251 | That is, if parent[name] already existed and had properties, | |
| 252 | copy those properties into the new constructor. | |
| 253 | */ | |
| 254 | 1 | OAuth.declareClass = function declareClass(parent, name, newConstructor) { |
| 255 | 1 | var previous = parent[name]; |
| 256 | 1 | parent[name] = newConstructor; |
| 257 | 1 | if (newConstructor && previous) { |
| 258 | 0 | for (var key in previous) { |
| 259 | 0 | if (key !== "prototype") { |
| 260 | 0 | newConstructor[key] = previous[key]; |
| 261 | } | |
| 262 | } | |
| 263 | } | |
| 264 | 1 | return newConstructor; |
| 265 | }; | |
| 266 | ||
| 267 | /** An abstract algorithm for signing messages. */ | |
| 268 | 1 | OAuth.declareClass(OAuth, "SignatureMethod", function OAuthSignatureMethod() {}); |
| 269 | ||
| 270 | // instance members | |
| 271 | 1 | OAuth.setProperties(OAuth.SignatureMethod.prototype, { |
| 272 | /** Add a signature to the message. */ | |
| 273 | sign: function sign(message) { | |
| 274 | 40 | var baseString = OAuth.SignatureMethod.getBaseString(message); |
| 275 | 40 | var signature = this.getSignature(baseString); |
| 276 | // console.log(baseString, this.key, signature) | |
| 277 | 40 | OAuth.setParameter(message, "oauth_signature", signature); |
| 278 | 40 | return signature; // just in case someone's interested |
| 279 | }, | |
| 280 | /** Set the key string for signing. */ | |
| 281 | initialize: function initialize(name, accessor) { | |
| 282 | 40 | var consumerSecret; |
| 283 | 40 | if (accessor.accessorSecret && name.length > 9 && name.substring(name.length-9) === "-Accessor") { |
| 284 | 0 | consumerSecret = accessor.accessorSecret; |
| 285 | } else { | |
| 286 | 40 | consumerSecret = accessor.consumerSecret; |
| 287 | } | |
| 288 | 40 | this.key = OAuth.percentEncode(consumerSecret) + "&" + OAuth.percentEncode(accessor.tokenSecret); |
| 289 | } | |
| 290 | }); | |
| 291 | ||
| 292 | /* SignatureMethod expects an accessor object to be like this: | |
| 293 | {tokenSecret: "lakjsdflkj...", consumerSecret: "QOUEWRI..", accessorSecret: "xcmvzc..."} | |
| 294 | The accessorSecret property is optional. | |
| 295 | */ | |
| 296 | // Class members: | |
| 297 | 1 | OAuth.setProperties(OAuth.SignatureMethod, { |
| 298 | sign: function sign(message, accessor) { | |
| 299 | 40 | var name = OAuth.getParameterMap(message.parameters).oauth_signature_method; |
| 300 | 40 | if (!name) { |
| 301 | 40 | name = 'HMAC-SHA1'; |
| 302 | 40 | OAuth.setParameter(message, 'oauth_signature_method', name); |
| 303 | } | |
| 304 | 40 | OAuth.SignatureMethod.newMethod(name, accessor).sign(message); |
| 305 | }, | |
| 306 | ||
| 307 | /** Instantiate a SignatureMethod for the given method name. */ | |
| 308 | newMethod: function newMethod(name, accessor) { | |
| 309 | 40 | var Impl = OAuth.SignatureMethod.REGISTERED[name]; |
| 310 | 40 | if (typeof Impl === 'function') { |
| 311 | 40 | var method = new Impl(); |
| 312 | 40 | method.initialize(name, accessor); |
| 313 | 40 | return method; |
| 314 | } | |
| 315 | 0 | var err = new Error("signature_method_rejected"); |
| 316 | 0 | var acceptable = ""; |
| 317 | 0 | for (var r in OAuth.SignatureMethod.REGISTERED) { |
| 318 | 0 | if (acceptable) { |
| 319 | 0 | acceptable += '&'; |
| 320 | } | |
| 321 | 0 | acceptable += OAuth.percentEncode(r); |
| 322 | } | |
| 323 | 0 | err.oauth_acceptable_signature_methods = acceptable; |
| 324 | 0 | throw err; |
| 325 | }, | |
| 326 | /** A map from signature method name to constructor. */ | |
| 327 | REGISTERED: {}, | |
| 328 | /** Subsequently, the given constructor will be used for the named methods. | |
| 329 | The constructor will be called with no parameters. | |
| 330 | The resulting object should usually implement getSignature(baseString). | |
| 331 | You can easily define such a constructor by calling makeSubclass, below. | |
| 332 | */ | |
| 333 | registerMethodClass: function registerMethodClass(names, classConstructor) { | |
| 334 | 2 | for (var n = 0, l = names.length; n < l; ++n) { |
| 335 | 4 | OAuth.SignatureMethod.REGISTERED[names[n]] = classConstructor; |
| 336 | } | |
| 337 | }, | |
| 338 | /** Create a subclass of OAuth.SignatureMethod, with the given getSignature function. */ | |
| 339 | makeSubclass: function makeSubclass(getSignatureFunction) { | |
| 340 | 2 | var SuperClass = OAuth.SignatureMethod; |
| 341 | 2 | var subClass = function() { |
| 342 | 40 | SuperClass.call(this); |
| 343 | }; | |
| 344 | 2 | subClass.prototype = new SuperClass(); |
| 345 | // Delete instance variables from prototype: | |
| 346 | // delete subclass.prototype... There aren't any. | |
| 347 | 2 | subClass.prototype.getSignature = getSignatureFunction; |
| 348 | 2 | subClass.prototype.constructor = subClass; |
| 349 | 2 | return subClass; |
| 350 | }, | |
| 351 | getBaseString: function getBaseString(message) { | |
| 352 | 40 | var URL = message.action; |
| 353 | 40 | var q = URL.indexOf('?'); |
| 354 | 40 | var parameters; |
| 355 | 40 | if (q < 0) { |
| 356 | 40 | parameters = message.parameters; |
| 357 | } else { | |
| 358 | // Combine the URL query string with the other parameters: | |
| 359 | 0 | parameters = OAuth.decodeForm(URL.substring(q + 1)); |
| 360 | 0 | var toAdd = OAuth.getParameterList(message.parameters); |
| 361 | 0 | for (var a = 0, l = toAdd.length; a < l; ++a) { |
| 362 | 0 | parameters.push(toAdd[a]); |
| 363 | } | |
| 364 | } | |
| 365 | 40 | return OAuth.percentEncode(message.method.toUpperCase()) + '&' + |
| 366 | OAuth.percentEncode(OAuth.SignatureMethod.normalizeUrl(URL)) + '&' + | |
| 367 | OAuth.percentEncode(OAuth.SignatureMethod.normalizeParameters(parameters)); | |
| 368 | }, | |
| 369 | normalizeUrl: function normalizeUrl(url) { | |
| 370 | 40 | var uri = OAuth.SignatureMethod.parseUri(url); |
| 371 | 40 | var scheme = uri.protocol.toLowerCase(); |
| 372 | 40 | var authority = uri.authority.toLowerCase(); |
| 373 | 40 | var dropPort = (scheme === "http" && uri.port === 80) || (scheme === "https" && uri.port === 443); |
| 374 | 40 | if (dropPort) { |
| 375 | // find the last : in the authority | |
| 376 | 0 | var index = authority.lastIndexOf(":"); |
| 377 | 0 | if (index >= 0) { |
| 378 | 0 | authority = authority.substring(0, index); |
| 379 | } | |
| 380 | } | |
| 381 | 40 | var path = uri.path; |
| 382 | // if (!path) { | |
| 383 | // path = "/"; // conforms to RFC 2616 section 3.2.2 | |
| 384 | // } | |
| 385 | // we know that there is no query and no fragment here. | |
| 386 | 40 | return scheme + "://" + authority + path; |
| 387 | }, | |
| 388 | parseUri: function parseUri(str) { | |
| 389 | /* This function was adapted from parseUri 1.2.1 | |
| 390 | http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js | |
| 391 | */ | |
| 392 | 40 | var o = { |
| 393 | key: [ "source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], | |
| 394 | parser: { strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/ }}; | |
| 395 | 40 | var m = o.parser.strict.exec(str); |
| 396 | 40 | var uri = {}; |
| 397 | 40 | var i = 14; |
| 398 | 40 | while (i--) { |
| 399 | 560 | uri[o.key[i]] = m[i] || ""; |
| 400 | } | |
| 401 | 40 | return uri; |
| 402 | }, | |
| 403 | normalizeParameters: function normalizeParameters(parameters) { | |
| 404 | 40 | if (!parameters) { |
| 405 | 0 | return ""; |
| 406 | } | |
| 407 | 40 | var norm = []; |
| 408 | 40 | var list = OAuth.getParameterList(parameters); |
| 409 | 40 | for (var p = 0; p < list.length; ++p) { |
| 410 | 372 | var nvp = list[p]; |
| 411 | 372 | if (nvp[0] !== "oauth_signature") { |
| 412 | 372 | norm.push(nvp); |
| 413 | } | |
| 414 | } | |
| 415 | 40 | norm.sort(function (a, b) { |
| 416 | 1225 | if (a[0] < b[0]) { return -1; } |
| 417 | 1274 | if (a[0] > b[0]) { return 1; } |
| 418 | 0 | if (a[1] < b[1]) { return -1; } |
| 419 | 0 | if (a[1] > b[1]) { return 1; } |
| 420 | 0 | return 0; |
| 421 | }); | |
| 422 | 40 | return OAuth.formEncode(norm); |
| 423 | } | |
| 424 | }); | |
| 425 | ||
| 426 | 1 | OAuth.SignatureMethod.registerMethodClass(["PLAINTEXT", "PLAINTEXT-Accessor"], |
| 427 | OAuth.SignatureMethod.makeSubclass( | |
| 428 | function getSignature(baseString) { | |
| 429 | 0 | return this.key; |
| 430 | } | |
| 431 | )); | |
| 432 | ||
| 433 | 1 | OAuth.SignatureMethod.registerMethodClass(["HMAC-SHA1", "HMAC-SHA1-Accessor"], |
| 434 | OAuth.SignatureMethod.makeSubclass( | |
| 435 | function getSignature(baseString) { | |
| 436 | 40 | return utils.base64HmacSha1(baseString, this.key); |
| 437 | } | |
| 438 | )); | |
| 439 | ||
| 440 | 1 | var root = this; // window on browser |
| 441 | 1 | if (typeof module === 'undefined') { |
| 442 | 0 | root.weibo = root.weibo || {}; |
| 443 | 0 | root.weibo.OAuth = OAuth; |
| 444 | } else { | |
| 445 | 1 | module.exports = OAuth; |
| 446 | } | |
| 447 | ||
| 448 | })(); |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * æ°æµªå¾®åmidä¸urläºè½¬å®ç¨å·¥å · | |
| 3 | * ä½è : XiNGRZ (http://weibo.com/xingrz) | |
| 4 | */ | |
| 5 | ||
| 6 | 1 | var WeiboUtil = module.exports = { |
| 7 | // 62è¿å¶åå ¸ | |
| 8 | str62keys: [ | |
| 9 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", | |
| 10 | "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", | |
| 11 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" | |
| 12 | ], | |
| 13 | }; | |
| 14 | ||
| 15 | /** | |
| 16 | * 62è¿å¶å¼è½¬æ¢ä¸º10è¿å¶ | |
| 17 | * @param {String} str62 62è¿å¶å¼ | |
| 18 | * @return {String} 10è¿å¶å¼ | |
| 19 | */ | |
| 20 | 1 | WeiboUtil.str62to10 = function (str62) { |
| 21 | 0 | var i10 = 0; |
| 22 | 0 | for (var i = 0; i < str62.length; i++) { |
| 23 | 0 | var n = str62.length - i - 1; |
| 24 | 0 | var s = str62[i]; |
| 25 | 0 | i10 += this.str62keys.indexOf(s) * Math.pow(62, n); |
| 26 | } | |
| 27 | 0 | return i10; |
| 28 | }; | |
| 29 | ||
| 30 | /** | |
| 31 | * 10è¿å¶å¼è½¬æ¢ä¸º62è¿å¶ | |
| 32 | * @param {String} int10 10è¿å¶å¼ | |
| 33 | * @return {String} 62è¿å¶å¼ | |
| 34 | */ | |
| 35 | 1 | WeiboUtil.int10to62 = function (int10) { |
| 36 | 735 | var s62 = ''; |
| 37 | 735 | var r = 0; |
| 38 | 735 | while (int10 !== 0 && s62.length < 100) { |
| 39 | 2319 | r = int10 % 62; |
| 40 | 2319 | s62 = this.str62keys[r] + s62; |
| 41 | 2319 | int10 = Math.floor(int10 / 62); |
| 42 | } | |
| 43 | 735 | return s62; |
| 44 | }; | |
| 45 | ||
| 46 | /** | |
| 47 | * URLå符转æ¢ä¸ºmid | |
| 48 | * @param {String} url å¾®åURLå符ï¼å¦ "wr4mOFqpbO" | |
| 49 | * @return {String} å¾®åmidï¼å¦ "201110410216293360" | |
| 50 | */ | |
| 51 | 1 | WeiboUtil.url2mid = function (url) { |
| 52 | 0 | var mid = ''; |
| 53 | //仿åå¾å以4åè为ä¸ç»è¯»åURLå符 | |
| 54 | 0 | for (var i = url.length - 4; i > -4; i = i - 4) { |
| 55 | 0 | var offset1 = i < 0 ? 0 : i; |
| 56 | 0 | var offset2 = i + 4; |
| 57 | 0 | var str = url.substring(offset1, offset2); |
| 58 | ||
| 59 | 0 | str = this.str62to10(str); |
| 60 | 0 | if (offset1 > 0) { |
| 61 | //è¥ä¸æ¯ç¬¬ä¸ç»ï¼åä¸è¶³7ä½è¡¥0 | |
| 62 | 0 | while (str.length < 7) { |
| 63 | 0 | str = '0' + str; |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 67 | 0 | mid = str + mid; |
| 68 | } | |
| 69 | ||
| 70 | 0 | return mid; |
| 71 | }; | |
| 72 | ||
| 73 | /** | |
| 74 | * mid转æ¢ä¸ºURLå符 | |
| 75 | * @param {String} mid å¾®åmidï¼å¦ "201110410216293360" | |
| 76 | * @return {String} å¾®åURLå符ï¼å¦ "wr4mOFqpbO" | |
| 77 | */ | |
| 78 | 1 | WeiboUtil.mid2url = function (mid) { |
| 79 | 264 | if (!mid) { |
| 80 | 0 | return mid; |
| 81 | } | |
| 82 | 264 | mid = String(mid); //midæ°å¼è¾å¤§ï¼å¿ 须为åç¬¦ä¸²ï¼ |
| 83 | 264 | if (!/^\d+$/.test(mid)) { return mid; } |
| 84 | 264 | var url = ''; |
| 85 | // 仿åå¾å以7åè为ä¸ç»è¯»åmid | |
| 86 | 264 | for (var i = mid.length - 7; i > -7; i = i - 7) { |
| 87 | 735 | var offset1 = i < 0 ? 0 : i; |
| 88 | 735 | var offset2 = i + 7; |
| 89 | 735 | var num = mid.substring(offset1, offset2); |
| 90 | ||
| 91 | 735 | num = this.int10to62(num); |
| 92 | 735 | url = num + url; |
| 93 | } | |
| 94 | 264 | return url; |
| 95 | }; |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/tqq.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var inherits = require('util').inherits; |
| 14 | 1 | var TBase = require('./tbase'); |
| 15 | 1 | var utils = require('./utils'); |
| 16 | ||
| 17 | 1 | function TQQAPI(options) { |
| 18 | 1 | TQQAPI.super_.call(this); |
| 19 | ||
| 20 | 1 | var config = utils.extend({}, options, { |
| 21 | host: 'http://open.t.qq.com/api', | |
| 22 | result_format: '', | |
| 23 | oauth_host: 'https://open.t.qq.com', | |
| 24 | oauth_authorize: '/cgi-bin/authorize', | |
| 25 | oauth_request_token: '/cgi-bin/request_token', | |
| 26 | oauth_access_token: '/cgi-bin/access_token', | |
| 27 | ||
| 28 | // ç«ç¶æ¯éè¿getä¼ é | |
| 29 | oauth_params_by_get: true, | |
| 30 | support_comment: false, // 䏿¯æcomment_timeline | |
| 31 | support_do_comment: true, | |
| 32 | support_repost_timeline: true, // æ¯ææ¥ç转åå表 | |
| 33 | support_favorites_max_id: true, | |
| 34 | reply_dont_need_at_screen_name: true, // @å夿æ¡å¾®å æ éå¡«å @screen_name | |
| 35 | rt_at_name: true, // RTç@nameè䏿¯@screen_name | |
| 36 | repost_delimiter: ' || ', //è½¬åæ¶çåé符 | |
| 37 | support_counts: false, // åªært_countè¿ä¸ªï¼ä¸è¿è²ä¼¼æé®é¢ï¼æ»æ¯404ãææ¶éè | |
| 38 | ||
| 39 | home_timeline: '/statuses/home_timeline', | |
| 40 | mentions: '/statuses/mentions_timeline', | |
| 41 | comments_timeline: '/statuses/mentions_timeline', | |
| 42 | comments_mentions: '/statuses/mentions_timeline', | |
| 43 | ||
| 44 | repost_timeline: '/t/re_list', | |
| 45 | ||
| 46 | followers: '/friends/user_fanslist', | |
| 47 | friends: '/friends/user_idollist', | |
| 48 | favorites: '/fav/list_t', | |
| 49 | favorites_create: '/fav/addt', | |
| 50 | favorites_destroy: '/fav/delt', | |
| 51 | count: '/t/re_count', //ä» ä» æ¯è½¬ææ° | |
| 52 | show: '/t/show', | |
| 53 | update: '/t/add', | |
| 54 | upload: '/t/add_pic', | |
| 55 | repost: '/t/re_add', | |
| 56 | comment_create: '/t/comment', | |
| 57 | comment_reply: '/t/comment', | |
| 58 | comments: '/t/re_list', | |
| 59 | destroy: '/t/del', | |
| 60 | destroy_msg: '/private/del', | |
| 61 | direct_messages: '/private/recv', | |
| 62 | sent_direct_messages: '/private/send', | |
| 63 | new_message: '/private/add', | |
| 64 | rate_limit_status: '/account/rate_limit_status', | |
| 65 | friendships_create: '/friends/add', | |
| 66 | friendships_destroy: '/friends/del', | |
| 67 | friendships_show: '/friends/check', | |
| 68 | reset_count: '/statuses/reset_count', | |
| 69 | user_show: '/user/other_info', | |
| 70 | ||
| 71 | // ç¨æ·æ ç¾ | |
| 72 | tags: '/tags', | |
| 73 | create_tag: '/tags/create', | |
| 74 | destroy_tag: '/tags/destroy', | |
| 75 | tags_suggestions: '/tags/suggestions', | |
| 76 | ||
| 77 | // æç´¢ | |
| 78 | search: '/search/t', | |
| 79 | user_search: '/search/user', | |
| 80 | verify_credentials: '/user/info', | |
| 81 | ||
| 82 | gender_map: {0: 'n', 1: 'm', 2: 'f'}, | |
| 83 | ||
| 84 | // support apis | |
| 85 | support_comment_destroy: false, | |
| 86 | support_comments_mentions: false, | |
| 87 | support_comments_to_me: false, | |
| 88 | support_comments_by_me: false, | |
| 89 | }); | |
| 90 | ||
| 91 | 1 | this.init(config); |
| 92 | } | |
| 93 | ||
| 94 | 1 | inherits(TQQAPI, TBase); |
| 95 | 1 | module.exports = TQQAPI; |
| 96 | ||
| 97 | /** | |
| 98 | * Utils methods | |
| 99 | */ | |
| 100 | ||
| 101 | 1 | TQQAPI.prototype.detect_error = function (method, res, playload, data) { |
| 102 | 40 | var headers = res.headers; |
| 103 | 40 | var err; |
| 104 | 40 | if (res.statusCode === 200 && headers.status) { |
| 105 | 1 | err = new Error(headers.status); |
| 106 | 39 | } else if (data.errcode && data.msg) { |
| 107 | 9 | err = new Error(data.msg); |
| 108 | 30 | } else if (!data.data && data.msg && data.msg !== 'ok') { |
| 109 | 0 | err = new Error(data.msg); |
| 110 | } | |
| 111 | 40 | if (err) { |
| 112 | 10 | err.name = this.errorname(method); |
| 113 | 10 | err.data = data; |
| 114 | 10 | return err; |
| 115 | } | |
| 116 | 30 | return TQQAPI.super_.prototype.detect_error.call(this, method, res, playload, data); |
| 117 | }; | |
| 118 | ||
| 119 | 1 | TQQAPI.prototype.url_encode = function (text) { |
| 120 | 8 | return text; |
| 121 | }; | |
| 122 | ||
| 123 | /** | |
| 124 | * Result getters | |
| 125 | */ | |
| 126 | ||
| 127 | 1 | TQQAPI.prototype.get_result_items = function (data, playload, args) { |
| 128 | 15 | if (playload === 'count') { |
| 129 | 1 | var counts = []; |
| 130 | 1 | for (var id in data) { |
| 131 | 2 | var item = data[id]; |
| 132 | 2 | counts.push({id: id, reposts: item.count, comments: item.mcount}); |
| 133 | } | |
| 134 | 1 | return counts; |
| 135 | } | |
| 136 | 14 | return data.info; |
| 137 | }; | |
| 138 | ||
| 139 | /** | |
| 140 | * { hasnext: 0, | |
| 141 | info: | |
| 142 | [ [Object], | |
| 143 | [Object], | |
| 144 | [Object], | |
| 145 | [Object], | |
| 146 | [Object], | |
| 147 | [Object], | |
| 148 | [Object], | |
| 149 | [Object], | |
| 150 | [Object] ], | |
| 151 | timestamp: 1348753615, | |
| 152 | user: { GreenMango: 'éè', 'node-weibo': 'node-weibo' } }, | |
| 153 | */ | |
| 154 | // TQQAPI.prototype.get_pagging_cursor = function (data, playload, args) { | |
| 155 | // return {}; | |
| 156 | // }; | |
| 157 | ||
| 158 | /** | |
| 159 | * Result formatters | |
| 160 | */ | |
| 161 | ||
| 162 | 1 | TQQAPI.prototype.format_result = function (data, playload, args) { |
| 163 | 28 | data = data.data; |
| 164 | 28 | var result = TQQAPI.super_.prototype.format_result.call(this, data, playload, args); |
| 165 | 28 | if (data.user) { |
| 166 | 15 | result.users = data.user; |
| 167 | } | |
| 168 | 28 | return result; |
| 169 | }; | |
| 170 | ||
| 171 | 1 | TQQAPI.prototype.format_search_status = function (status, args) { |
| 172 | 0 | throw new Error('Must override this method.'); |
| 173 | }; | |
| 174 | ||
| 175 | /** | |
| 176 | * | |
| 177 | { city_code: '1', | |
| 178 | count: 0, | |
| 179 | country_code: '1', | |
| 180 | emotiontype: 0, | |
| 181 | emotionurl: '', | |
| 182 | from: 'å¾®å弿¾å¹³å°', | |
| 183 | fromurl: 'http://wiki.open.t.qq.com/index.php/%E4%BA%A7%E5%93%81%E7%B1%BBFAQ#.E6.8F.90.E4.BA.A4.E5.BA.94.E7.94.A8.E6.9D.A5.E6.BA.90.E5.AD.97.E6.AE.B5.E5.AE.A1.E6.A0.B8.E8.83.BD.E5.BE.97.E5.88.B0.E4.BB.80.E4.B9.88.E5.A5.BD.E5.A4.84.EF.BC.9F\n', | |
| 184 | geo: '广ä¸çä¸å±±å¸åº·ä¹è·¯ï¼ï¼å·', | |
| 185 | head: 'http://app.qlogo.cn/mbloghead/cb1c4eb21aa2b52a233a', | |
| 186 | id: '102460077174373', | |
| 187 | image: null, | |
| 188 | isrealname: 2, | |
| 189 | isvip: 0, | |
| 190 | jing: '113.421234', | |
| 191 | latitude: '22.354231', | |
| 192 | location: 'ä¸å½ æµæ± æå·', | |
| 193 | longitude: '113.421234', | |
| 194 | mcount: 0, | |
| 195 | music: null, | |
| 196 | name: 'node-weibo', | |
| 197 | nick: 'node-weibo', | |
| 198 | openid: 'EA68676D5E9DA465822CD0CEB2DC6EF5', | |
| 199 | origtext: 'è¿æ¯update(user, status, callback) çåå æµè¯ï¼å½åæ¶é´ Thu Sep 27 2012 17:04:25 GMT+0800 (CST)', | |
| 200 | province_code: '33', | |
| 201 | self: 1, | |
| 202 | source: null, | |
| 203 | status: 0, | |
| 204 | text: 'è¿æ¯update(user, status, callback) çåå æµè¯ï¼å½åæ¶é´ Thu Sep 27 2012 17:04:25 GMT+0800 (CST)', | |
| 205 | timestamp: 1348736665, | |
| 206 | type: 1, | |
| 207 | user: { 'node-weibo': 'node-weibo' }, | |
| 208 | video: null, | |
| 209 | wei: '22.354231' } | |
| 210 | ||
| 211 | * @param {[type]} status [description] | |
| 212 | * @param {[type]} args [description] | |
| 213 | * @return {[type]} [description] | |
| 214 | */ | |
| 215 | 1 | TQQAPI.prototype.format_status = function (data, args) { |
| 216 | 187 | var status = {}; |
| 217 | 187 | status.id = String(data.id); |
| 218 | 187 | status.t_url = 'http://t.qq.com/p/t/' + data.id; |
| 219 | 187 | status.created_at = new Date(data.timestamp * 1000); |
| 220 | 187 | status.text = data.origtext; |
| 221 | 187 | status.source = '<a href="' + data.fromurl + '">' + data.from + '</a>'; |
| 222 | // status.favorited = | |
| 223 | 187 | if (data.image && data.image[0]) { |
| 224 | 82 | var image = data.image[0]; |
| 225 | 82 | status.thumbnail_pic = image + '/160'; |
| 226 | 82 | status.bmiddle_pic = image + '/460'; |
| 227 | 82 | status.original_pic = image + '/2000'; |
| 228 | } | |
| 229 | 187 | if (data.latitude && String(data.latitude) !== '0') { |
| 230 | 17 | status.geo = this.format_geo(data, args); |
| 231 | } | |
| 232 | 187 | if (data.name) { |
| 233 | 175 | status.user = this.format_user(data, args); |
| 234 | } | |
| 235 | 187 | status.reposts_count = data.count || 0; |
| 236 | 187 | status.comments_count = data.mcount || 0; |
| 237 | 187 | if (data.source) { |
| 238 | 33 | status.retweeted_status = this.format_status(data.source, args); |
| 239 | } | |
| 240 | 187 | return status; |
| 241 | // type:å¾®åç±»å 1-ååå表ã2-转载ã3-ç§ä¿¡ 4-åå¤ 5-空å 6-æå 7: ç¹è¯ | |
| 242 | // status.status_type = data.type; | |
| 243 | // if(data.type == 7) { | |
| 244 | // // è ¾è®¯çç¹è¯ä¼ä»æ¥hometimelineï¼å¾ä¸ç»å | |
| 245 | // status.status_type = 'comments_timeline'; | |
| 246 | // } | |
| 247 | ||
| 248 | // status.created_at = new Date(data.timestamp * 1000); | |
| 249 | // status.timestamp = data.timestamp; | |
| 250 | // if(data.image){ | |
| 251 | // status.thumbnail_pic = data.image[0] + '/160'; | |
| 252 | // status.bmiddle_pic = data.image[0] + '/460'; | |
| 253 | // status.original_pic = data.image[0] + '/2000'; | |
| 254 | // } | |
| 255 | // if (data.source) { | |
| 256 | // if(data.type == 4) { | |
| 257 | // // åå¤ | |
| 258 | // status.text = '@' + data.source.name + ' ' + status.text; | |
| 259 | // status.related_dialogue_url = 'http://t.qq.com/p/r/' + status.id; | |
| 260 | // status.in_reply_to_status_id = data.source.id; | |
| 261 | // status.in_reply_to_screen_name = data.source.nick; | |
| 262 | // } else { | |
| 263 | // status.retweeted_status = | |
| 264 | // this.format_result_item(data.source, 'status', args, users); | |
| 265 | // // è¯è®º | |
| 266 | // if(play_load == 'comment') { | |
| 267 | // status.status = status.retweeted_status; | |
| 268 | // delete status.retweeted_status; | |
| 269 | // } | |
| 270 | // } | |
| 271 | // } | |
| 272 | // status.repost_count = data.count || 0; | |
| 273 | // status.comments_count = data.mcount || 0; // è¯è®ºæ° | |
| 274 | // status.source = data.from; | |
| 275 | // status.user = this.format_result_item(data, 'user', args, users); | |
| 276 | // // æ¶ä»¶äºº | |
| 277 | // // tohead: "" | |
| 278 | // // toisvip: 0 | |
| 279 | // // toname: "macgirl" | |
| 280 | // // tonick: "ç¾ä»ª" | |
| 281 | // if(data.toname) { | |
| 282 | // status.recipient = { | |
| 283 | // name: data.toname, | |
| 284 | // nick: data.tonick, | |
| 285 | // isvip: data.toisvip, | |
| 286 | // head: data.tohead | |
| 287 | // }; | |
| 288 | // status.recipient = this.format_result_item(status.recipient, 'user', args, users); | |
| 289 | // } | |
| 290 | ||
| 291 | // // 妿ætext屿§ï¼åæ¿æ¢å ¶ä¸ç@xxx 为 䏿å(@xxx) | |
| 292 | // if(status && status.text) { | |
| 293 | // var matchs = status.text.match(this.ONLY_AT_USER_RE); | |
| 294 | // if(matchs) { | |
| 295 | // status.users = {}; | |
| 296 | // for(var j=0; j<matchs.length; j++) { | |
| 297 | // var name = matchs[j].trim().substring(1); | |
| 298 | // status.users[name] = users[name]; | |
| 299 | // } | |
| 300 | // } | |
| 301 | // } | |
| 302 | // data = status; | |
| 303 | }; | |
| 304 | ||
| 305 | /** | |
| 306 | * | |
| 307 | { birth_day: 1, | |
| 308 | birth_month: 1, | |
| 309 | birth_year: 2010, | |
| 310 | city_code: '1', | |
| 311 | comp: null, | |
| 312 | country_code: '1', | |
| 313 | edu: null, | |
| 314 | email: '', | |
| 315 | exp: 56, | |
| 316 | fansnum: 3, | |
| 317 | favnum: 0, | |
| 318 | head: 'http://app.qlogo.cn/mbloghead/2045de7c75623f2c2b06', | |
| 319 | homecity_code: '', | |
| 320 | homecountry_code: '', | |
| 321 | homepage: '', | |
| 322 | homeprovince_code: '', | |
| 323 | hometown_code: '', | |
| 324 | idolnum: 46, | |
| 325 | industry_code: 0, | |
| 326 | introduction: '', | |
| 327 | isent: 0, | |
| 328 | ismyblack: 0, | |
| 329 | ismyfans: 0, | |
| 330 | ismyidol: 0, | |
| 331 | isrealname: 2, | |
| 332 | isvip: 0, | |
| 333 | level: 1, | |
| 334 | location: 'ä¸å½ æå·', | |
| 335 | mutual_fans_num: 0, | |
| 336 | name: 'node-weibo', | |
| 337 | nick: 'node-weibo', | |
| 338 | openid: 'EA68676D5E9DA465822CD0CEB2DC6EF5', | |
| 339 | province_code: '33', | |
| 340 | regtime: 1348724066, | |
| 341 | send_private_flag: 2, | |
| 342 | sex: 1, | |
| 343 | tag: null, | |
| 344 | tweetinfo: | |
| 345 | [ { city_code: '1', | |
| 346 | country_code: '1', | |
| 347 | emotiontype: 0, | |
| 348 | emotionurl: '', | |
| 349 | from: 'è ¾è®¯å¾®å', | |
| 350 | fromurl: 'http://t.qq.com\n', | |
| 351 | geo: '', | |
| 352 | id: '70997003338788', | |
| 353 | image: null, | |
| 354 | latitude: '0', | |
| 355 | location: 'ä¸å½ æå·', | |
| 356 | longitude: '0', | |
| 357 | music: null, | |
| 358 | origtext: '#æ°äººæ¥å°# ä¼å¤§çæ ç¨é½æ¯ä»ç¬¬ä¸æ¡å¾®åå¼å§çï¼', | |
| 359 | province_code: '33', | |
| 360 | self: 1, | |
| 361 | status: 0, | |
| 362 | text: '#æ°äººæ¥å°# ä¼å¤§çæ ç¨é½æ¯ä»ç¬¬ä¸æ¡å¾®åå¼å§çï¼', | |
| 363 | timestamp: 1348724111, | |
| 364 | type: 1, | |
| 365 | video: null } ], | |
| 366 | tweetnum: 1, | |
| 367 | verifyinfo: '' } | |
| 368 | */ | |
| 369 | 1 | TQQAPI.prototype.format_user = function (data, args) { |
| 370 | 177 | var user = {}; |
| 371 | 177 | user.id = data.name; |
| 372 | 177 | user.t_url = 'http://t.qq.com/' + data.name; |
| 373 | 177 | user.screen_name = data.nick; |
| 374 | 177 | user.name = data.name; |
| 375 | 177 | user.location = data.location || ''; |
| 376 | 177 | user.description = data.introduction || ''; |
| 377 | // no url | |
| 378 | 177 | if (data.head) { |
| 379 | 173 | user.profile_image_url = data.head + '/50'; // ç«ç¶ç´æ¥è·åçå°åæ æ³æ¿å°å¤´å |
| 380 | 173 | user.avatar_large = data.head + '/180'; |
| 381 | } else { | |
| 382 | 4 | user.profile_image_url = 'http://mat1.gtimg.com/www/mb/images/head_50.jpg'; |
| 383 | 4 | user.avatar_large = 'http://mat1.gtimg.com/www/mb/images/head_180.jpg'; |
| 384 | } | |
| 385 | 177 | user.gender = this.config.gender_map[data.sex||0]; |
| 386 | 177 | user.followers_count = data.fansnum || 0; |
| 387 | 177 | user.friends_count = data.idolnum || 0; |
| 388 | 177 | user.statuses_count = data.tweetnum || 0; |
| 389 | 177 | user.favourites_count = data.favnum || 0; |
| 390 | 177 | if (data.regtime) { |
| 391 | 2 | user.created_at = new Date(data.regtime * 1000); |
| 392 | } | |
| 393 | 177 | user.following = data.ismyidol || false; |
| 394 | 177 | user.follow_me = data.ismyfans || false; |
| 395 | // send_private_flag : æ¯å¦å 许ææäººç»å½åç¨æ·åç§ä¿¡ï¼0-ä» æå¶åï¼1-å人+å¬ä¼ï¼2-ææäºº, | |
| 396 | 177 | user.allow_all_act_msg = data.send_private_flag === 2; |
| 397 | // no geo_enabled | |
| 398 | 177 | user.verified = !!data.isvip; |
| 399 | // no verified_type | |
| 400 | 177 | user.verified_reason = data.verifyinfo || ''; |
| 401 | // user.remark = | |
| 402 | 177 | user.allow_all_comment = true; |
| 403 | // user.online_status = true; | |
| 404 | 177 | user.bi_followers_count = data.mutual_fans_num || 0; |
| 405 | // user.lang | |
| 406 | 177 | if (data.tweetinfo && data.tweetinfo[0]) { |
| 407 | 2 | user.status = this.format_status(data.tweetinfo[0], args); |
| 408 | } | |
| 409 | ||
| 410 | 177 | if (data.tag) { |
| 411 | 1 | user.tags = data.tag; |
| 412 | } | |
| 413 | 177 | return user; |
| 414 | }; | |
| 415 | ||
| 416 | 1 | TQQAPI.prototype.format_count = function (count, args) { |
| 417 | 2 | return count; |
| 418 | }; | |
| 419 | ||
| 420 | 1 | TQQAPI.prototype.format_geo = function (data, args) { |
| 421 | 17 | var geo = { |
| 422 | longitude: data.longitude, | |
| 423 | latitude: data.latitude, | |
| 424 | // city_name string City name "广å·" | |
| 425 | // province_name string Province name "广ä¸" | |
| 426 | address: data.geo, | |
| 427 | }; | |
| 428 | 17 | return geo; |
| 429 | }; | |
| 430 | ||
| 431 | 1 | TQQAPI.prototype.format_comment = function (data, args) { |
| 432 | 17 | var comment = this.format_status(data, args); |
| 433 | 17 | if (comment.retweeted_status) { |
| 434 | 15 | comment.status = comment.retweeted_status; |
| 435 | 15 | delete comment.retweeted_status; |
| 436 | } | |
| 437 | 17 | return comment; |
| 438 | }; | |
| 439 | ||
| 440 | 1 | TQQAPI.prototype.format_message = function (message, args) { |
| 441 | 0 | throw new Error('Must override this method.'); |
| 442 | }; | |
| 443 | ||
| 444 | 1 | TQQAPI.prototype.format_emotion = function (emotion, args) { |
| 445 | 0 | throw new Error('Must override this method.'); |
| 446 | }; | |
| 447 | ||
| 448 | 1 | TQQAPI.prototype.format_favorite = function (status, args) { |
| 449 | 19 | var favorite = { |
| 450 | created_at: new Date(status.storetime * 1000), | |
| 451 | status: this.format_status(status) | |
| 452 | }; | |
| 453 | 19 | return favorite; |
| 454 | }; | |
| 455 | ||
| 456 | /** | |
| 457 | * Params converters | |
| 458 | */ | |
| 459 | ||
| 460 | 1 | TQQAPI.prototype.convert_comment = function (comment) { |
| 461 | // http://wiki.open.t.qq.com/index.php/%E5%BE%AE%E5%8D%9A%E7%9B%B8%E5%85%B3/%E7%82%B9%E8%AF%84%E4%B8%80%E6%9D%A1%E5%BE%AE%E5%8D%9A | |
| 462 | 6 | var data = { |
| 463 | content: comment.comment, | |
| 464 | reid: comment.id | |
| 465 | }; | |
| 466 | 6 | return data; |
| 467 | }; | |
| 468 | ||
| 469 | 1 | TQQAPI.prototype.convert_status = function (status) { |
| 470 | // syncflag å¾®å忥å°ç©ºé´å享æ è®°ï¼å¯éï¼0-忥ï¼1-ä¸åæ¥ï¼é»è®¤ä¸º0ï¼ï¼ç®åä» æ¯æoauth1.0é´ææ¹å¼ | |
| 471 | 9 | var data = { |
| 472 | content: status.status | |
| 473 | }; | |
| 474 | 9 | if (status.long) { |
| 475 | 4 | data.longitude = status.long; |
| 476 | 4 | data.latitude = status.lat; |
| 477 | } | |
| 478 | 9 | if (status.id) { |
| 479 | 2 | data.reid = status.id; |
| 480 | } | |
| 481 | 9 | return data; |
| 482 | }; | |
| 483 | ||
| 484 | 1 | TQQAPI.prototype.convert_user = function (user) { |
| 485 | 1 | var data = { |
| 486 | name: user.uid || user.screen_name | |
| 487 | }; | |
| 488 | 1 | return data; |
| 489 | }; | |
| 490 | ||
| 491 | 1 | TQQAPI.prototype.convert_ids = function (ids) { |
| 492 | 2 | return { |
| 493 | ids: ids, | |
| 494 | flag: '2' | |
| 495 | }; | |
| 496 | }; | |
| 497 | ||
| 498 | /** | |
| 499 | * pageflag | |
| 500 | å页æ è¯ï¼0ï¼ç¬¬ä¸é¡µï¼1ï¼åä¸ç¿»é¡µï¼2ï¼åä¸ç¿»é¡µï¼ | |
| 501 | pagetime | |
| 502 | æ¬é¡µèµ·å§æ¶é´ï¼ç¬¬ä¸é¡µï¼å¡«0ï¼åä¸ç¿»é¡µï¼å¡«ä¸ä¸æ¬¡è¯·æ±è¿åçç¬¬ä¸æ¡è®°å½æ¶é´ï¼åä¸ç¿»é¡µï¼å¡«ä¸ä¸æ¬¡è¯·æ±è¿åçæå䏿¡è®°å½æ¶é´ï¼ | |
| 503 | reqnum | |
| 504 | æ¯æ¬¡è¯·æ±è®°å½çæ¡æ°ï¼1-70æ¡ï¼ | |
| 505 | type | |
| 506 | æåç±»åï¼éå¡«ååè¿å¶æ°åï¼ | |
| 507 | 0x1 ååå表 0x2 转载 å¦éæåå¤ä¸ªç±»å请使ç¨|ï¼å¦(0x1|0x2)å¾å°3ï¼åtype=3å³å¯ï¼å¡«é¶è¡¨ç¤ºæåææç±»å | |
| 508 | contenttype | |
| 509 | å å®¹è¿æ»¤ã0-表示ææç±»åï¼1-å¸¦ææ¬ï¼2-另龿¥ï¼4-带å¾çï¼8-带è§é¢ï¼0x10-带é³é¢ | |
| 510 | 建议ä¸ä½¿ç¨contenttype为1çç±»åï¼å¦æè¦æååªæææ¬çå¾®åï¼å»ºè®®ä½¿ç¨0x80 | |
| 511 | * | |
| 512 | */ | |
| 513 | 1 | TQQAPI.prototype.convert_cursor = function (cursor) { |
| 514 | 14 | var data = {}; |
| 515 | // type: æåç±»å, 0x1 ååå表 0x2 转载 0x8 åå¤ 0x10 空å 0x20 æå 0x40 ç¹è¯ | |
| 516 | 14 | data.type = String(0x1 | 0x2 | 0x8 | 0x10 | 0x20); |
| 517 | 14 | data.contenttype = '0'; |
| 518 | 14 | data.reqnum = cursor.count; |
| 519 | 14 | if (cursor.max_id) { |
| 520 | // get older statuses | |
| 521 | 0 | data.pageflag = '1'; |
| 522 | 0 | data.pagetime = cursor.max_time; |
| 523 | 0 | data.lastid = cursor.max_id; |
| 524 | 14 | } else if (cursor.since_id) { |
| 525 | // get newer statuses | |
| 526 | // 0ï¼ç¬¬ä¸é¡µï¼1ï¼åä¸ç¿»é¡µï¼2ï¼åä¸ç¿»é¡µ | |
| 527 | 0 | data.pageflag = '2'; |
| 528 | 0 | data.pagetime = cursor.since_time; |
| 529 | // data.lastid = cursor.sina_id; | |
| 530 | } else { | |
| 531 | // top page | |
| 532 | 14 | data.pageflag = '0'; |
| 533 | 14 | data.pagetime = '0'; |
| 534 | 14 | data.lastid = '0'; |
| 535 | } | |
| 536 | 14 | if (typeof cursor.callback === 'function') { |
| 537 | 7 | data = cursor.callback(data); |
| 538 | } | |
| 539 | 14 | return data; |
| 540 | }; | |
| 541 | ||
| 542 | /** | |
| 543 | * Status | |
| 544 | */ | |
| 545 | ||
| 546 | 1 | TQQAPI.prototype.repost_timeline = function (user, cursor, callback) { |
| 547 | 1 | cursor.callback = function (data) { |
| 548 | 1 | data.rootid = cursor.id; |
| 549 | 1 | data.flag = '0'; |
| 550 | // twitterid å¾®åidï¼ä¸pageflagãpagetimeå ±å使ç¨ï¼å®ç°ç¿»é¡µåè½ï¼ç¬¬1页填0ï¼ç»§ç»åä¸ç¿»é¡µï¼å¡«ä¸ä¸æ¬¡è¯·æ±è¿åçæå䏿¡è®°å½idï¼ | |
| 551 | 1 | if (data.lastid) { |
| 552 | 1 | data.twitterid = data.lastid; |
| 553 | 1 | delete data.lastid; |
| 554 | } | |
| 555 | 1 | return data; |
| 556 | }; | |
| 557 | 1 | return TQQAPI.super_.prototype.repost_timeline.call(this, user, cursor, callback); |
| 558 | }; | |
| 559 | ||
| 560 | 1 | TQQAPI.prototype.user_timeline = function (user, cursor, callback) { |
| 561 | 2 | cursor.callback = function (data) { |
| 562 | 2 | if (cursor.uid || cursor.screen_name) { |
| 563 | 1 | data.name = cursor.uid || cursor.screen_name; |
| 564 | } | |
| 565 | 2 | return data; |
| 566 | }; | |
| 567 | 2 | return TQQAPI.super_.prototype.user_timeline.call(this, user, cursor, callback); |
| 568 | }; | |
| 569 | ||
| 570 | 1 | TQQAPI.prototype.search = function (user, query, cursor, callback) { |
| 571 | 1 | cursor = cursor || {}; |
| 572 | 1 | var q = { |
| 573 | keyword: query.q | |
| 574 | }; | |
| 575 | 1 | if (query.long && query.lat && query.radius) { |
| 576 | 0 | q.longitude = query.long; |
| 577 | 0 | q.latitude = query.lat; |
| 578 | 0 | q.radius = query.radius; |
| 579 | } | |
| 580 | 1 | cursor.callback = function (data) { |
| 581 | 1 | data.pagesize = data.reqnum || 20; |
| 582 | 1 | return data; |
| 583 | }; | |
| 584 | 1 | return TQQAPI.super_.prototype.search.call(this, user, q, cursor, callback); |
| 585 | }; | |
| 586 | ||
| 587 | /** | |
| 588 | * Comment | |
| 589 | */ | |
| 590 | ||
| 591 | 1 | TQQAPI.prototype.comments_timeline = function (user, cursor, callback) { |
| 592 | 2 | cursor.callback = function (data) { |
| 593 | 2 | data.type = String(0x40); |
| 594 | 2 | return data; |
| 595 | }; | |
| 596 | 2 | return TQQAPI.super_.prototype.comments_timeline.call(this, user, cursor, callback); |
| 597 | }; | |
| 598 | ||
| 599 | 1 | TQQAPI.prototype.comments = function (user, cursor, callback) { |
| 600 | 1 | cursor.callback = function (data) { |
| 601 | 1 | data.rootid = cursor.id; |
| 602 | 1 | data.flag = '1'; |
| 603 | 1 | if (data.lastid) { |
| 604 | 1 | data.twitterid = data.lastid; |
| 605 | 1 | delete data.lastid; |
| 606 | } | |
| 607 | 1 | return data; |
| 608 | }; | |
| 609 | 1 | return TQQAPI.super_.prototype.comments.call(this, user, cursor, callback); |
| 610 | }; | |
| 611 | ||
| 612 | 1 | TQQAPI.prototype.comment_destroy = function (user, cid, callback) { |
| 613 | 0 | callback(new TypeError('comment_destroy not support.')); |
| 614 | }; | |
| 615 |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/weibo.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var TBaseOauthV2 = require('./tbase_oauth_v2'); |
| 14 | 1 | var inherits = require('util').inherits; |
| 15 | 1 | var utils = require('./utils'); |
| 16 | 1 | var weiboutil = require('./weibo_util'); |
| 17 | ||
| 18 | ||
| 19 | 1 | function WeiboAPI(options) { |
| 20 | 2 | WeiboAPI.super_.call(this); |
| 21 | ||
| 22 | 2 | var config = utils.extend({}, options, { |
| 23 | host: 'https://api.weibo.com/2', | |
| 24 | user_home_url: 'http://weibo.com/n/', | |
| 25 | search_url: 'http://s.weibo.com/weibo/', | |
| 26 | ||
| 27 | oauth_host: 'https://api.weibo.com/oauth2', | |
| 28 | oauth_authorize: '/authorize', | |
| 29 | oauth_access_token: '/access_token', | |
| 30 | verify_credentials: '/users/show', | |
| 31 | ||
| 32 | comments: '/comments/show', | |
| 33 | comment_create: '/comments/create', | |
| 34 | comment_reply: '/comments/reply', | |
| 35 | comment_destroy: '/comments/destroy', | |
| 36 | ||
| 37 | support_search: false, | |
| 38 | }); | |
| 39 | ||
| 40 | 2 | this.init(config); |
| 41 | } | |
| 42 | ||
| 43 | 1 | inherits(WeiboAPI, TBaseOauthV2); |
| 44 | 1 | module.exports = WeiboAPI; |
| 45 | ||
| 46 | /** | |
| 47 | * Result getters | |
| 48 | */ | |
| 49 | ||
| 50 | 1 | WeiboAPI.prototype.get_result_items = function (data, playload, args) { |
| 51 | 20 | return data.statuses || data.comments || data.reposts || |
| 52 | data.messages || data.favorites || data; | |
| 53 | }; | |
| 54 | ||
| 55 | /** | |
| 56 | * Result formatters | |
| 57 | */ | |
| 58 | ||
| 59 | 1 | WeiboAPI.prototype.format_search_status = function (status, args) { |
| 60 | 0 | return status; |
| 61 | }; | |
| 62 | ||
| 63 | 1 | WeiboAPI.prototype.format_status = function (status, args) { |
| 64 | 266 | status.id = status.idstr; |
| 65 | 266 | status.created_at = new Date(status.created_at); |
| 66 | 266 | if (status.user) { |
| 67 | 258 | status.user = this.format_user(status.user, args); |
| 68 | 258 | status.t_url = 'http://weibo.com/' + status.user.id + '/' + weiboutil.mid2url(status.mid); |
| 69 | } | |
| 70 | ||
| 71 | // geo: { type: 'Point', coordinates: [ 22.354231, 113.421234 ] } latitude, longitude | |
| 72 | 266 | if (status.geo && status.geo.type === 'Point' && status.geo.coordinates) { |
| 73 | 22 | var geo = { |
| 74 | latitude: String(status.geo.coordinates[0]), | |
| 75 | longitude: String(status.geo.coordinates[1]), | |
| 76 | }; | |
| 77 | 22 | status.geo = geo; |
| 78 | } | |
| 79 | ||
| 80 | 266 | if (status.retweeted_status) { |
| 81 | 52 | status.retweeted_status = this.format_status(status.retweeted_status, args); |
| 82 | 52 | if (!status.retweeted_status.t_url) { |
| 83 | 3 | status.retweeted_status.t_url = |
| 84 | 'http://weibo.com/' + status.user.id + '/' + weiboutil.mid2url(status.retweeted_status.mid); | |
| 85 | } | |
| 86 | } | |
| 87 | 266 | return status; |
| 88 | }; | |
| 89 | ||
| 90 | 1 | WeiboAPI.prototype.format_user = function (user, args) { |
| 91 | 370 | user.id = user.idstr; |
| 92 | 370 | user.created_at = new Date(user.created_at); |
| 93 | 370 | user.t_url = 'http://weibo.com/' + (user.domain || user.id); |
| 94 | 370 | if (user.status) { |
| 95 | 3 | user.status = this.format_status(user.status, args); |
| 96 | 3 | if (!user.status.t_url) { |
| 97 | 3 | user.status.t_url = user.t_url + '/' + weiboutil.mid2url(user.status.mid || user.status.id); |
| 98 | } | |
| 99 | } | |
| 100 | 370 | return user; |
| 101 | }; | |
| 102 | ||
| 103 | 1 | WeiboAPI.prototype.format_comment = function (comment, args) { |
| 104 | 109 | comment.id = comment.idstr; |
| 105 | 109 | comment.created_at = new Date(comment.created_at); |
| 106 | 109 | if (comment.user) { |
| 107 | 109 | comment.user = this.format_user(comment.user, args); |
| 108 | } | |
| 109 | 109 | if (comment.status) { |
| 110 | 79 | comment.status = this.format_status(comment.status, args); |
| 111 | } | |
| 112 | 109 | if (comment.reply_comment) { |
| 113 | 30 | comment.reply_comment = this.format_comment(comment.reply_comment, args); |
| 114 | } | |
| 115 | 109 | return comment; |
| 116 | }; | |
| 117 | ||
| 118 | 1 | WeiboAPI.prototype.format_message = function (message, args) { |
| 119 | 0 | return message; |
| 120 | }; | |
| 121 | ||
| 122 | 1 | WeiboAPI.prototype.format_emotion = function (emotion, args) { |
| 123 | 0 | return emotion; |
| 124 | }; | |
| 125 | ||
| 126 | 1 | WeiboAPI.prototype.format_count = function (count, args) { |
| 127 | 2 | count.id = String(count.id); |
| 128 | 2 | return count; |
| 129 | }; | |
| 130 | ||
| 131 | 1 | WeiboAPI.prototype.format_favorite = function (favorite, args) { |
| 132 | 20 | favorite.status = this.format_status(favorite.status); |
| 133 | 20 | favorite.created_at = new Date(favorite.favorited_time); |
| 134 | 20 | delete favorite.favorited_time; |
| 135 | 20 | return favorite; |
| 136 | }; | |
| 137 | ||
| 138 | /** | |
| 139 | * User | |
| 140 | */ | |
| 141 | ||
| 142 | 1 | WeiboAPI.prototype.verify_credentials = function (user, callback) { |
| 143 | 1 | var uid = user.uid || user.id; |
| 144 | 1 | return this.user_show(user, uid, null, callback); |
| 145 | }; | |
| 146 |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/tbase_oauth_v2.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var TBase = require('./tbase'); |
| 14 | 1 | var inherits = require('util').inherits; |
| 15 | 1 | var utils = require('./utils'); |
| 16 | 1 | var querystring = require('querystring'); |
| 17 | ||
| 18 | /** | |
| 19 | * TAPI Base class, support OAuth v2.0 | |
| 20 | */ | |
| 21 | 1 | function TBaseOauthV2() { |
| 22 | 3 | TBaseOauthV2.super_.call(this); |
| 23 | 3 | this.config.oauth_version = '2.0'; |
| 24 | } | |
| 25 | ||
| 26 | 1 | inherits(TBaseOauthV2, TBase); |
| 27 | 1 | module.exports = TBaseOauthV2; |
| 28 | ||
| 29 | /** | |
| 30 | * Result formatters | |
| 31 | */ | |
| 32 | ||
| 33 | 1 | TBaseOauthV2.prototype.format_access_token = function (token) { |
| 34 | 0 | token = JSON.parse(token); |
| 35 | 0 | return token; |
| 36 | }; | |
| 37 | ||
| 38 | /** | |
| 39 | * OAuth | |
| 40 | */ | |
| 41 | ||
| 42 | 1 | TBaseOauthV2.prototype.convert_token = function (user) { |
| 43 | 6 | var params = { |
| 44 | redirect_uri: user.oauth_callback || this.config.oauth_callback, | |
| 45 | client_id: this.config.appkey, | |
| 46 | response_type: 'code', | |
| 47 | }; | |
| 48 | 6 | var oauth_scope = user.oauth_scope || this.config.oauth_scope; |
| 49 | 6 | if (oauth_scope) { |
| 50 | 0 | params.oauth_scope = oauth_scope; |
| 51 | } | |
| 52 | 6 | if (user.state) { |
| 53 | // An unguessable random string. It is used to protect against cross-site request forgery attacks. | |
| 54 | 0 | params.state = user.state; |
| 55 | } | |
| 56 | 6 | return params; |
| 57 | }; | |
| 58 | ||
| 59 | 1 | TBaseOauthV2.prototype.get_authorization_url = function (user, callback) { |
| 60 | 4 | var data = this.convert_token(user); |
| 61 | 4 | data.response_type = 'code'; |
| 62 | 4 | var info = { |
| 63 | blogtype: user.blogtype, | |
| 64 | auth_url: this.format_authorization_url(data) | |
| 65 | }; | |
| 66 | 4 | process.nextTick(function () { |
| 67 | 4 | callback(null, info); |
| 68 | }); | |
| 69 | 4 | return this; |
| 70 | }; | |
| 71 | ||
| 72 | 1 | TBaseOauthV2.prototype.get_access_token = function (user, callback) { |
| 73 | 2 | var params = { |
| 74 | type: 'POST', | |
| 75 | user: user, | |
| 76 | playload: 'string', | |
| 77 | api_host: this.config.oauth_host, | |
| 78 | request_method: 'get_access_token' | |
| 79 | }; | |
| 80 | 2 | var data = this.convert_token(user); |
| 81 | 2 | data.grant_type = 'authorization_code'; |
| 82 | 2 | data.client_secret = this.config.secret; |
| 83 | 2 | var code = user.code || user.oauth_verifier || user.oauth_pin; |
| 84 | 2 | if (code) { |
| 85 | 0 | data.code = code; |
| 86 | } | |
| 87 | ||
| 88 | 2 | params.data = data; |
| 89 | 2 | var self = this; |
| 90 | 2 | var url = self.config.oauth_access_token; |
| 91 | 2 | self.send_request(url, params, function (err, token) { |
| 92 | 2 | if (err) { |
| 93 | 1 | return callback(err); |
| 94 | } | |
| 95 | // { access_token: '2.00EkofzBtMpzNBb9bc3108d8MwDTTE', | |
| 96 | // remind_in: '633971', | |
| 97 | // expires_in: 633971, | |
| 98 | // uid: '1827455832' } | |
| 99 | 1 | token = self.format_access_token(token); |
| 100 | 1 | if (!token.access_token) { |
| 101 | 1 | var message = token.error || JSON.stringify(token); |
| 102 | 1 | err = new Error(message); |
| 103 | 1 | err.data = token; |
| 104 | 1 | err.name = self.errorname('get_access_token'); |
| 105 | 1 | return callback(err); |
| 106 | } | |
| 107 | 0 | token.blogtype = user.blogtype; |
| 108 | 0 | callback(null, token); |
| 109 | }); | |
| 110 | 2 | return this; |
| 111 | }; | |
| 112 | ||
| 113 | 1 | TBaseOauthV2.prototype.apply_auth = function (url, args, user) { |
| 114 | 49 | args.data = args.data || {}; |
| 115 | 49 | args.data.access_token = user.access_token; |
| 116 | }; | |
| 117 |
| Line | Hits | Source |
|---|---|---|
| 1 | /*! | |
| 2 | * node-weibo - lib/github.js | |
| 3 | * Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | |
| 4 | * MIT Licensed | |
| 5 | */ | |
| 6 | ||
| 7 | 1 | "use strict"; |
| 8 | ||
| 9 | /** | |
| 10 | * Module dependencies. | |
| 11 | */ | |
| 12 | ||
| 13 | 1 | var TBaseOauthV2 = require('./tbase_oauth_v2'); |
| 14 | 1 | var inherits = require('util').inherits; |
| 15 | 1 | var TSinaAPI = require('./tsina'); |
| 16 | 1 | var utils = require('./utils'); |
| 17 | 1 | var querystring = require('querystring'); |
| 18 | ||
| 19 | ||
| 20 | 1 | function GithubAPI(options) { |
| 21 | 1 | GithubAPI.super_.call(this); |
| 22 | 1 | var config = utils.extend({}, options, { |
| 23 | host: 'https://api.github.com', | |
| 24 | result_format: '', | |
| 25 | oauth_key: '', | |
| 26 | oauth_secret: '', | |
| 27 | oauth_host: 'https://github.com', | |
| 28 | oauth_authorize: '/login/oauth/authorize', | |
| 29 | oauth_access_token: '/login/oauth/access_token', | |
| 30 | ||
| 31 | verify_credentials: '/user', | |
| 32 | user_show: '/users/{{uid}}', | |
| 33 | ||
| 34 | support_favorites: false, | |
| 35 | }); | |
| 36 | 1 | this.init(config); |
| 37 | } | |
| 38 | ||
| 39 | 1 | inherits(GithubAPI, TBaseOauthV2); |
| 40 | 1 | module.exports = GithubAPI; |
| 41 | ||
| 42 | /** | |
| 43 | * Utils methods | |
| 44 | */ | |
| 45 | ||
| 46 | 1 | GithubAPI.prototype.url_encode = function (text) { |
| 47 | 0 | return text; |
| 48 | }; | |
| 49 | ||
| 50 | /** | |
| 51 | * OAuth | |
| 52 | */ | |
| 53 | ||
| 54 | 1 | GithubAPI.prototype.convert_token = function (user) { |
| 55 | 3 | var data = GithubAPI.super_.prototype.convert_token.call(this, user); |
| 56 | 3 | data.state = Date.now(); |
| 57 | 3 | return data; |
| 58 | }; | |
| 59 | ||
| 60 | /** | |
| 61 | * Result formatters | |
| 62 | */ | |
| 63 | ||
| 64 | 1 | GithubAPI.prototype.format_access_token = function (token) { |
| 65 | 1 | token = querystring.parse(token); |
| 66 | 1 | return token; |
| 67 | }; | |
| 68 | ||
| 69 | /** | |
| 70 | * | |
| 71 | { | |
| 72 | public_repos: 67, | |
| 73 | following: 84, | |
| 74 | created_at: '2009-11-21T08:07:35Z', | |
| 75 | type: 'User', | |
| 76 | email: 'fengmk2@gmail.com', | |
| 77 | bio: 'nodejs', | |
| 78 | blog: 'http://fengmk2.github.com', | |
| 79 | location: 'Hangzhou, China', | |
| 80 | gravatar_id: '95b9d41231617a05ced5604d242c9670', | |
| 81 | avatar_url: 'https://secure.gravatar.com/avatar/95b9d41231617a05ced5604d242c9670?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png', | |
| 82 | public_gists: 21, | |
| 83 | followers: 293, | |
| 84 | login: 'fengmk2', | |
| 85 | name: 'fengmk2', | |
| 86 | company: 'http://www.taobao.com/', | |
| 87 | id: 156269, | |
| 88 | html_url: 'https://github.com/fengmk2', | |
| 89 | hireable: false, | |
| 90 | url: 'https://api.github.com/users/fengmk2' | |
| 91 | } | |
| 92 | */ | |
| 93 | 1 | GithubAPI.prototype.format_user = function (data) { |
| 94 | 2 | var user = { |
| 95 | id: data.login, | |
| 96 | t_url: data.html_url, | |
| 97 | screen_name: data.name, | |
| 98 | name: data.login, | |
| 99 | location: data.location, | |
| 100 | url: data.blog || data.url, | |
| 101 | profile_image_url: data.avatar_url + '&s=50', | |
| 102 | avatar_large: data.avatar_url + '&s=180', | |
| 103 | gender: 'n', | |
| 104 | following: false, | |
| 105 | verified: false, | |
| 106 | follow_me: false, | |
| 107 | followers_count: data.followers, | |
| 108 | friends_count: data.following, | |
| 109 | statuses_count: data.public_repos, | |
| 110 | favourites_count: 0, | |
| 111 | created_at: new Date(data.created_at), | |
| 112 | email: data.email, | |
| 113 | }; | |
| 114 | 2 | return user; |
| 115 | }; | |
| 116 | ||
| 117 |
| Line | Hits | Source |
|---|---|---|
| 1 | /** | |
| 2 | * | |
| 3 | * Base64 encode / decode | |
| 4 | * http://www.webtoolkit.info/ | |
| 5 | * | |
| 6 | **/ | |
| 7 | ||
| 8 | // support atob and btoa native method in browser | |
| 9 | ||
| 10 | 1 | (function () { |
| 11 | ||
| 12 | 1 | var Base64 = { |
| 13 | ||
| 14 | // private property | |
| 15 | _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", | |
| 16 | ||
| 17 | // public method for encoding | |
| 18 | encode: function (input) { | |
| 19 | 8 | var output = ""; |
| 20 | 8 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4; |
| 21 | 8 | var i = 0; |
| 22 | ||
| 23 | 8 | input = Base64._utf8_encode(input); |
| 24 | ||
| 25 | 8 | while (i < input.length) { |
| 26 | ||
| 27 | 158 | chr1 = input.charCodeAt(i++); |
| 28 | 158 | chr2 = input.charCodeAt(i++); |
| 29 | 158 | chr3 = input.charCodeAt(i++); |
| 30 | ||
| 31 | 158 | enc1 = chr1 >> 2; |
| 32 | 158 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); |
| 33 | 158 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); |
| 34 | 158 | enc4 = chr3 & 63; |
| 35 | ||
| 36 | 158 | if (isNaN(chr2)) { |
| 37 | 0 | enc3 = enc4 = 64; |
| 38 | 158 | } else if (isNaN(chr3)) { |
| 39 | 4 | enc4 = 64; |
| 40 | } | |
| 41 | ||
| 42 | 158 | output = output + |
| 43 | this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + | |
| 44 | this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); | |
| 45 | ||
| 46 | } | |
| 47 | ||
| 48 | 8 | return output; |
| 49 | }, | |
| 50 | ||
| 51 | // public method for decoding | |
| 52 | decode: function (input) { | |
| 53 | 0 | var output = ""; |
| 54 | 0 | var chr1, chr2, chr3; |
| 55 | 0 | var enc1, enc2, enc3, enc4; |
| 56 | 0 | var i = 0; |
| 57 | ||
| 58 | 0 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); |
| 59 | ||
| 60 | 0 | while (i < input.length) { |
| 61 | ||
| 62 | 0 | enc1 = this._keyStr.indexOf(input.charAt(i++)); |
| 63 | 0 | enc2 = this._keyStr.indexOf(input.charAt(i++)); |
| 64 | 0 | enc3 = this._keyStr.indexOf(input.charAt(i++)); |
| 65 | 0 | enc4 = this._keyStr.indexOf(input.charAt(i++)); |
| 66 | ||
| 67 | 0 | chr1 = (enc1 << 2) | (enc2 >> 4); |
| 68 | 0 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); |
| 69 | 0 | chr3 = ((enc3 & 3) << 6) | enc4; |
| 70 | ||
| 71 | 0 | output = output + String.fromCharCode(chr1); |
| 72 | ||
| 73 | 0 | if (enc3 != 64) { |
| 74 | 0 | output = output + String.fromCharCode(chr2); |
| 75 | } | |
| 76 | 0 | if (enc4 != 64) { |
| 77 | 0 | output = output + String.fromCharCode(chr3); |
| 78 | } | |
| 79 | ||
| 80 | } | |
| 81 | ||
| 82 | 0 | output = Base64._utf8_decode(output); |
| 83 | ||
| 84 | 0 | return output; |
| 85 | ||
| 86 | }, | |
| 87 | ||
| 88 | // private method for UTF-8 encoding | |
| 89 | _utf8_encode : function (string) { | |
| 90 | 8 | string = string.replace(/\r\n/g,"\n"); |
| 91 | 8 | var utftext = ""; |
| 92 | ||
| 93 | 8 | for (var n = 0; n < string.length; n++) { |
| 94 | ||
| 95 | 228 | var c = string.charCodeAt(n); |
| 96 | ||
| 97 | 228 | if (c < 128) { |
| 98 | 102 | utftext += String.fromCharCode(c); |
| 99 | } | |
| 100 | 126 | else if ((c > 127) && (c < 2048)) { |
| 101 | 10 | utftext += String.fromCharCode((c >> 6) | 192); |
| 102 | 10 | utftext += String.fromCharCode((c & 63) | 128); |
| 103 | } | |
| 104 | else { | |
| 105 | 116 | utftext += String.fromCharCode((c >> 12) | 224); |
| 106 | 116 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); |
| 107 | 116 | utftext += String.fromCharCode((c & 63) | 128); |
| 108 | } | |
| 109 | ||
| 110 | } | |
| 111 | ||
| 112 | 8 | return utftext; |
| 113 | }, | |
| 114 | ||
| 115 | // private method for UTF-8 decoding | |
| 116 | _utf8_decode : function (utftext) { | |
| 117 | 0 | var string = ""; |
| 118 | 0 | var i = 0; |
| 119 | 0 | var c = 0, c1 = 0, c2 = 0; |
| 120 | ||
| 121 | 0 | while ( i < utftext.length ) { |
| 122 | ||
| 123 | 0 | c = utftext.charCodeAt(i); |
| 124 | ||
| 125 | 0 | if (c < 128) { |
| 126 | 0 | string += String.fromCharCode(c); |
| 127 | 0 | i++; |
| 128 | } | |
| 129 | 0 | else if((c > 191) && (c < 224)) { |
| 130 | 0 | c2 = utftext.charCodeAt(i+1); |
| 131 | 0 | string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); |
| 132 | 0 | i += 2; |
| 133 | } | |
| 134 | else { | |
| 135 | 0 | c2 = utftext.charCodeAt(i+1); |
| 136 | 0 | c3 = utftext.charCodeAt(i+2); |
| 137 | 0 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); |
| 138 | 0 | i += 3; |
| 139 | } | |
| 140 | } | |
| 141 | 0 | return string; |
| 142 | }, | |
| 143 | /** | |
| 144 | * A str encode and decode use on phpwind | |
| 145 | * | |
| 146 | * e.g.: var my_key = 'awejfosjdlxldfjlsdfwerwljxoasldf!@##@' | |
| 147 | * // encode | |
| 148 | * var encode_str = Base64.strcode('fawaveåå¨', my_key); | |
| 149 | * // decode | |
| 150 | * var source_str = Base64.strcode(encode_str, my_key, true) | |
| 151 | * | |
| 152 | * @param {String} str | |
| 153 | * @param {String} key | |
| 154 | * @param {Boolen} decode, default is `false` | |
| 155 | * @return {String} encode or decode string | |
| 156 | * @api public | |
| 157 | */ | |
| 158 | strcode: function (str, key, decode) { | |
| 159 | 0 | var keybuffer = this.utf8_encode(key); |
| 160 | 0 | var key_length = keybuffer.length; |
| 161 | 0 | var buffer = null, encoding = 'base64'; |
| 162 | 0 | if(decode) { |
| 163 | 0 | buffer = this.decode(str); |
| 164 | } else { | |
| 165 | 0 | buffer = this.utf8_encode(str); |
| 166 | } | |
| 167 | 0 | var buf = ''; |
| 168 | 0 | for (var i = 0, len = buffer.length; i < len; i++) { |
| 169 | 0 | var k = i % key_length; |
| 170 | 0 | buf += String.fromCharCode(buffer.charCodeAt(i) ^ keybuffer.charCodeAt(k)); |
| 171 | } | |
| 172 | 0 | if (decode) { |
| 173 | 0 | return this.utf8_decode(buffer); |
| 174 | } else { | |
| 175 | 0 | return this.encode(buffer); |
| 176 | } | |
| 177 | } | |
| 178 | }; | |
| 179 | ||
| 180 | 1 | Base64.utf8_encode = Base64._utf8_encode; |
| 181 | 1 | Base64.utf8_decode = Base64._utf8_decode; |
| 182 | ||
| 183 | 1 | var root = this; // window on browser |
| 184 | 1 | if (typeof module === 'undefined') { |
| 185 | 0 | root.weibo = root.weibo || {}; |
| 186 | 0 | root.weibo.base64 = Base64; |
| 187 | } else { | |
| 188 | 1 | module.exports = Base64; |
| 189 | } | |
| 190 | ||
| 191 | })(); |