Tiezi Image Transfer Batch

帖子图片批量转存

  1. // ==UserScript==
  2. // @name Tiezi Image Transfer Batch
  3. // @description 帖子图片批量转存
  4. // @author 陌百百<feng_zilong@163.com>
  5. // @include http://tieba.baidu.com/photo/p*
  6. // @require http://code.jquery.com/jquery-1.9.1.min.js
  7. // @grant GM_xmlhttpRequest
  8. // @grant GM_addStyle
  9. // @version 1.0
  10. // @namespace https://greasyfork.org/users/1438
  11. // ==/UserScript==
  12.  
  13. $(function(){
  14. var config, _, ImageBatch, TransferUtil, BatchBtnView, u_, u$;
  15.  
  16. u_ = unsafeWindow['_'];
  17. u$ = unsafeWindow['$'];
  18.  
  19. //Practical methods
  20. _ = {};
  21. _.extend = function(obj){
  22. Array.prototype.forEach.call(Array.prototype.slice.call(arguments, 1), function(source){
  23. if(source){
  24. for (var prop in source){
  25. obj[prop] = source[prop];
  26. }
  27. }
  28. });
  29. return obj;
  30. };
  31.  
  32. var ctor = function(){};
  33. _.bind = function(func, context) {
  34. var nativeBind, args, bound;
  35. nativeBind = Function.prototype.bind;
  36. if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, Array.prototype.slice.call(arguments, 1));
  37. if (!_.isFunction(func)) throw new TypeError;
  38. args = Array.prototype.slice.call(arguments, 2);
  39. return bound = function() {
  40. if (!(this instanceof bound)) return func.apply(context, args.concat(Array.prototype.slice.call(arguments)));
  41. ctor.prototype = func.prototype;
  42. var self = new ctor;
  43. ctor.prototype = null;
  44. var result = func.apply(self, args.concat(Array.prototype.slice.call(arguments)));
  45. if (Object(result) === result) return result;
  46. return self;
  47. };
  48. };
  49.  
  50. _.defaults = function(obj){
  51. Array.prototype.forEach.call(Array.prototype.slice.call(arguments, 1), function(source) {
  52. if(source){
  53. for(var prop in source){
  54. if (obj[prop] === void 0) obj[prop] = source[prop];
  55. }
  56. }
  57. });
  58. return obj;
  59. };
  60.  
  61. _.template = function(text, data, settings){
  62. var noMatch, escapes, escaper, render;
  63. noMatch = /(.)^/;
  64. escapes = {
  65. "'": "'",
  66. '\\': '\\',
  67. '\r': 'r',
  68. '\n': 'n',
  69. '\t': 't',
  70. '\u2028': 'u2028',
  71. '\u2029': 'u2029'
  72. };
  73. escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  74. settings = _.defaults({}, settings, {
  75. evaluate: /<%([\s\S]+?)%>/g,
  76. interpolate: /<%=([\s\S]+?)%>/g,
  77. escape: /<%-([\s\S]+?)%>/g
  78. });
  79.  
  80. var matcher = new RegExp([(settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source].join('|') + '|$', 'g');
  81.  
  82. var index = 0;
  83. var source = "__p+='";
  84. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  85. source += text.slice(index, offset).replace(escaper, function(match) {
  86. return '\\' + escapes[match];
  87. });
  88.  
  89. if(escape){
  90. source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
  91. }
  92. if(interpolate){
  93. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  94. }
  95. if(evaluate){
  96. source += "';\n" + evaluate + "\n__p+='";
  97. }
  98. index = offset + match.length;
  99. return match;
  100. });
  101. source += "';\n";
  102.  
  103. if(!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  104.  
  105. source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n";
  106.  
  107. try {
  108. render = new Function(settings.variable || 'obj', '_', source);
  109. } catch (e) {
  110. e.source = source;
  111. throw e;
  112. }
  113.  
  114. if(data) return render(data, _);
  115. var template = function(data){
  116. return render.call(this, data, _);
  117. };
  118.  
  119. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  120.  
  121. return template;
  122. };
  123.  
  124. //Configure
  125. CFG = {
  126. TMPL : '<a href="#" title="<%= title%>"><%= text%></a>',
  127. COUNT_ONE_TIME : 15, //Image number transfered at one time
  128. INTERVAL : 500, //Interval(millisecond)
  129. RETRY_TIMES : 3 //Retry times when failed
  130. };
  131.  
  132.  
  133.  
  134. u_.Module.define({
  135. path: "common/widget/ImageViewer/MyHint",
  136. sub: {
  137. _container: null,
  138. _hint: null,
  139. initial: function(){},
  140. setContainer: function(a){
  141. this._container = a;
  142. },
  143. show: function(d, h){
  144. if(this._hint){
  145. this._hint.close();
  146. this._hint = null;
  147. }
  148. var l = this,
  149. h = h || {};
  150. var g = d || "";
  151. var f = {
  152. modal: false,
  153. showTitle: false,
  154. button: false,
  155. width: "auto"
  156. };
  157. h = $.extend(f, h);
  158. this._hint = u$.dialog.open(g, h);
  159. if(this._container){
  160. var e = this._container.offset(),
  161. m = this._hint.element,
  162. a = this._container.width(),
  163. j = this._container.height(),
  164. c = m.width(),
  165. b = m.height(),
  166. i = {
  167. left: e.left + a / 2 - m.width() / 2,
  168. top: e.top + j / 2 - m.height() / 2
  169. };
  170. m.offset(i);
  171. }
  172. return l._hint;
  173. }
  174. }
  175. });
  176.  
  177.  
  178. u_.Module.define({
  179. path: "common/widget/ImageViewer/tbFavBatch",
  180. requires: [],
  181. sub: {
  182. defaultConf: {
  183. appid: "314406",
  184. xiangceUrl: "http://favo.xiangce.baidu.com/",
  185. uploadUrl: "http://up.xiangce.baidu.com/",
  186. userId: 0,
  187. cacheEnabled: false
  188. },
  189. defaultData: {
  190. imgUrl: "",
  191. sourceURL: "",
  192. tags: "",
  193. descript: ""
  194. },
  195. conf: {},
  196. data: {},
  197. cache: {},
  198. initial: function() {
  199. this.conf = $.extend(this.conf, this.defaultConf);
  200. this.data = $.extend(this.data, this.defaultData);
  201. },
  202. setConf: function(a) {
  203. this.conf = $.extend(this.conf, a);
  204. },
  205. setData: function(a) {
  206. this.data = $.extend(this.data, a);
  207. },
  208. getConf: function() {
  209. return this.conf;
  210. },
  211. getData: function() {
  212. return this.data;
  213. },
  214. checkStatus: function(d) {
  215. if (d) {
  216. this.setData(d);
  217. }
  218. var a = this;
  219. var c = this.conf;
  220. var d = this.data;
  221. if (c.cacheEnabled && this.checkCache(d.imgUrl)) {
  222. return;
  223. }
  224. var b = c.xiangceUrl + "opencom/picture/fav/query?app_id=" + c.appid + "&url=" + d.imgUrl + "&callback=?";
  225. $.getJSON(b, function(e) {
  226. if (a.cacheEnabled) {
  227. var f = (e.errno == 0 && e.data && e.data.status != 0);
  228. a.setCache(c.imgUrl, f);
  229. }
  230. })
  231. },
  232. addToFav: function(d){
  233. if (d) {
  234. this.setData(d)
  235. }
  236. var a = this;
  237. var c = this.conf;
  238. var d = this.data;
  239. var b = c.uploadUrl + "opencom/picture/fav/upload?app_id=" + c.appid + "&descript=" + encodeURIComponent(d.descript) + "&uid=" + c.userId + "&source_url=" + encodeURIComponent(d.sourceURL) + "&tags=" + encodeURIComponent(d.tags) + "&url=" + encodeURIComponent(d.imgUrl) + "&callback=?";
  240. $.getJSON(b, function(e) {
  241. if (a.cacheEnabled) {
  242. var f = (e.errno == 0);
  243. a.setCache(c.imgUrl, f);
  244. }
  245. })
  246. },
  247. setCache: function(b, a){
  248. this.cache[b] = a ? 1 : 0;
  249. },
  250. checkCache: function(a){
  251. return this.cache[a];
  252. }
  253. }
  254. });
  255.  
  256. //Transfer Handler
  257. TransferHandler = function(){
  258. this._di = unsafeWindow.__moduleInstances__['common/widget/ImageViewer/data_interface'];
  259. this._h = this.getInstance('common/widget/ImageViewer/MyHint');
  260. this._h.setContainer($('.af_original'));
  261. this._fav = this.getInstance('common/widget/ImageViewer/tbFavBatch');
  262. this._fav.setConf({userId : this._di.pageData.user_id});
  263. console.log(this._fav);
  264.  
  265. this._completed = 0;
  266. this._cur = 0;
  267. this._count = 0;
  268. };
  269.  
  270. _.extend(TransferHandler.prototype, {
  271. _di : null,
  272. _fav : null,
  273. _hint : null,
  274. getInstance : function(path){
  275. var instance;
  276. u_.Module.use(path, [], function(e){
  277. instance = e;
  278. });
  279. return instance;
  280. },
  281. showHint : function(msg){
  282. this._h.show(msg);
  283. },
  284. transferAll : function(){
  285. var _this;
  286. _this = this;
  287. this._count = this._di.guide.pic_amount;
  288. this.showHint('正在转存(0.00%)');
  289. this.transfer();
  290. },
  291. transfer : function(){
  292. var _this;
  293. _this = this;
  294. console.log(this._cur);
  295.  
  296. if(this._completed === this._count){
  297. this._h._hint.element.find('#dialogJbody').text('转存完毕').end().bind('mousemove', function(){
  298. $(this).remove();
  299. });
  300. return;
  301. }
  302. if(this._cur >= this._di._guideRange[0] && this._cur <= this._di._guideRange[1]){
  303. imgUrl = this._di.guide.pic_list[this._cur].img.original.url;
  304. sourceURL = 'http://tieba.baidu.com/p/' + this._di.pageData.tid;
  305. descript = this._di.albumData.title;
  306. this._fav.addToFav({
  307. imgUrl : imgUrl,
  308. sourceURL : sourceURL,
  309. descript : descript,
  310. tags : '百度贴吧'
  311. });
  312. this._cur++;
  313. this._completed++;
  314. this.progress();
  315. setTimeout(function(){_this.transfer();}, 1000);
  316. } else if(this._cur < this._di._guideRange[0]){
  317. this._di._requestGuide(this._di.guide.pic_list[this._di._guideRange[0]].img.original.id, CFG['COUNT_ONE_TIME'], 0, function(){_this.transfer();});
  318. } else if(this._cur > this._di._guideRange[1]) {
  319. console.log('guideRange -- ' + this._di._guideRange[1]);
  320. this._di._requestGuide(this._di.guide.pic_list[this._di._guideRange[1]].img.original.id, 0, CFG['COUNT_ONE_TIME'], function(){_this.transfer();});
  321. }
  322. },
  323. progress : function(){
  324. this._h._hint.element.find('#dialogJbody').text('正在转存(' + (this._completed / this._count * 100).toFixed(2) + '%)');
  325. }
  326. });
  327.  
  328. //View
  329. TransferView = function(handler){
  330. this.handler = handler;
  331. this.init();
  332. };
  333.  
  334. _.extend(TransferView.prototype, {
  335. init : function(){
  336. this.$el = this.render();
  337. this.$el.bind('click', _.bind(this.clickHandler, this));
  338. },
  339. template : _.template(CFG['TMPL']),
  340. render : function(){
  341. var el;
  342. el = $(this.template({title : "批量转存" ,text : "批量转存"}));
  343. el.css({'padding-left' : 28, 'background-position' : '-372px 3px'});
  344. el.hover(function(){
  345. $(this).css('background-position', '-372px -57px');
  346. }, function(){
  347. $(this).css('background-position', '-372px 3px');
  348. });
  349. el.insertBefore('.link_share');
  350. return el;
  351. },
  352. clickHandler : function(){
  353. this.handler.transferAll();
  354. }
  355. });
  356.  
  357. function waitLoad(){
  358. var fav, contaner;
  359. fav = $('.link_share');
  360. container = $('.af_original');
  361. if(!fav.length || !container.length){
  362. console.log('wait');
  363. setTimeout(waitLoad, 100);
  364. } else {
  365. console.log('nowait');
  366. tv = new TransferView(new TransferHandler());
  367. console.log(tv);
  368. }
  369. }
  370. waitLoad();
  371.  
  372. });