🏠 Home 

SnapShotOnline.js

A Javascript API that captures local video images and uploads them to sm.ms or imagebam or nhd.

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/377790/678193/SnapShotOnlinejs.js

  1. // ==UserScript==
  2. // @name SnapShotOnline.js
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description A Javascript API that captures local video images and uploads them to sm.ms or imagebam or nhd.
  6. // @author You
  7. // @match *
  8. // @require https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js
  9. // @grant none
  10. // ==/UserScript==
  11. var $ = window.jQuery;
  12. window.SnapShotOnline = function(input_resource, textarea_img_###ode, input_upload_snapshot, input_copy_snapshot, span_bar, span_snapshot, select_number, video_resource, canvas_resource){
  13. var ctx_resource = canvas_resource[0].getContext('2d');
  14. var thumb_scale;
  15. var video_length, shot_num, shot_requests = [], counter, update_flag = false;
  16. var processing = false;
  17. var image_url, thumb_url;
  18. var shot_index;
  19. var downScaleCanvas = function(cv, scale){
  20. if (!(scale < 1) || !(scale > 0)) throw ('scale must be a positive number <1 ');
  21. var sqScale = scale * scale;
  22. var sw = cv.width;
  23. var sh = cv.height;
  24. var tw = Math.floor(sw * scale);
  25. var th = Math.floor(sh * scale);
  26. var sx = 0, sy = 0, sIndex = 0;
  27. var tx = 0, ty = 0, yIndex = 0, tIndex = 0;
  28. var tX = 0, tY = 0;
  29. var w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0;
  30. var crossX = false;
  31. var crossY = false;
  32. var sBuffer = cv.getContext('2d').
  33. getImageData(0, 0, sw, sh).data;
  34. var tBuffer = new Float32Array(3 * tw * th);
  35. var sR = 0, sG = 0, sB = 0;
  36. for (sy = 0; sy < sh; sy++) {
  37. ty = sy * scale;
  38. tY = 0 | ty;
  39. yIndex = 3 * tY * tw;
  40. crossY = (tY != (0 | ty + scale));
  41. if (crossY) {
  42. wy = (tY + 1 - ty);
  43. nwy = (ty + scale - tY - 1);
  44. }
  45. for (sx = 0; sx < sw; sx++, sIndex += 4) {
  46. tx = sx * scale;
  47. tX = 0 | tx;
  48. tIndex = yIndex + tX * 3;
  49. crossX = (tX != (0 | tx + scale));
  50. if (crossX) {
  51. wx = (tX + 1 - tx);
  52. nwx = (tx + scale - tX - 1);
  53. }
  54. sR = sBuffer[sIndex];
  55. sG = sBuffer[sIndex + 1];
  56. sB = sBuffer[sIndex + 2];
  57. if (!crossX && !crossY) {
  58. tBuffer[tIndex] += sR * sqScale;
  59. tBuffer[tIndex + 1] += sG * sqScale;
  60. tBuffer[tIndex + 2] += sB * sqScale;
  61. } else if (crossX && !crossY) {
  62. w = wx * scale;
  63. tBuffer[tIndex] += sR * w;
  64. tBuffer[tIndex + 1] += sG * w;
  65. tBuffer[tIndex + 2] += sB * w;
  66. nw = nwx * scale
  67. tBuffer[tIndex + 3] += sR * nw;
  68. tBuffer[tIndex + 4] += sG * nw;
  69. tBuffer[tIndex + 5] += sB * nw;
  70. } else if (crossY && !crossX) {
  71. w = wy * scale;
  72. tBuffer[tIndex] += sR * w;
  73. tBuffer[tIndex + 1] += sG * w;
  74. tBuffer[tIndex + 2] += sB * w;
  75. nw = nwy * scale
  76. tBuffer[tIndex + 3 * tw] += sR * nw;
  77. tBuffer[tIndex + 3 * tw + 1] += sG * nw;
  78. tBuffer[tIndex + 3 * tw + 2] += sB * nw;
  79. } else {
  80. w = wx * wy;
  81. tBuffer[tIndex] += sR * w;
  82. tBuffer[tIndex + 1] += sG * w;
  83. tBuffer[tIndex + 2] += sB * w;
  84. nw = nwx * wy;
  85. tBuffer[tIndex + 3] += sR * nw;
  86. tBuffer[tIndex + 4] += sG * nw;
  87. tBuffer[tIndex + 5] += sB * nw;
  88. nw = wx * nwy;
  89. tBuffer[tIndex + 3 * tw] += sR * nw;
  90. tBuffer[tIndex + 3 * tw + 1] += sG * nw;
  91. tBuffer[tIndex + 3 * tw + 2] += sB * nw;
  92. nw = nwx * nwy;
  93. tBuffer[tIndex + 3 * tw + 3] += sR * nw;
  94. tBuffer[tIndex + 3 * tw + 4] += sG * nw;
  95. tBuffer[tIndex + 3 * tw + 5] += sB * nw;
  96. }
  97. }
  98. }
  99. var resCV = document.createElement('canvas');
  100. resCV.width = tw;
  101. resCV.height = th;
  102. var resCtx = resCV.getContext('2d');
  103. var imgRes = resCtx.getImageData(0, 0, tw, th);
  104. var tByteBuffer = imgRes.data;
  105. var pxIndex = 0;
  106. for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 3, tIndex += 4, pxIndex++) {
  107. tByteBuffer[tIndex] = Math.ceil(tBuffer[sIndex]);
  108. tByteBuffer[tIndex + 1] = Math.ceil(tBuffer[sIndex + 1]);
  109. tByteBuffer[tIndex + 2] = Math.ceil(tBuffer[sIndex + 2]);
  110. tByteBuffer[tIndex + 3] = 255;
  111. }
  112. resCtx.putImageData(imgRes, 0, 0);
  113. return resCV;
  114. }
  115. var fadeInThenFadeOut = function(span_snapshot, content, time, color){
  116. span_snapshot.text(content).css('color', color).fadeIn(function(){
  117. $(this).delay(time).fadeOut(function(){
  118. span_snapshot.text('');
  119. });
  120. });
  121. }
  122. var DOMEventInit = function(){
  123. input_resource.on('change', function(e){
  124. if(e.target.files.length > 0){
  125. processAbort();
  126. input_upload_snapshot.prop('disabled', false);
  127. input_upload_snapshot.show();
  128. input_copy_snapshot.prop('disabled', true);
  129. input_copy_snapshot.hide();
  130. span_bar.css({
  131. 'width': '0%',
  132. 'background-color': '#DCEDEE'
  133. });
  134. update_flag = false;
  135. shot_index = 1;
  136. counter = 0;
  137. shot_requests = [];
  138. image_url = [];
  139. thumb_url = [];
  140. video_length = 0;
  141. thumb_scale = 1;
  142. }
  143. else{
  144. processAbort();
  145. input_upload_snapshot.prop('disabled', true);
  146. }
  147. });
  148. input_upload_snapshot.on('click', function(e){
  149. processing = true;
  150. input_upload_snapshot.prop('disabled', true);
  151. select_number.prop('disabled', true);
  152. shot_num = parseInt(select_number.val());
  153. var file = input_resource[0].files[0];
  154. video_resource[0].src = URL.createObjectURL(file);
  155. });
  156. video_resource.on('durationchange', function(){
  157. this.pause();
  158. update_flag = true;
  159. canvas_resource.attr({
  160. 'width': this.videoWidth,
  161. 'height': this.videoHeight
  162. });
  163. var thumb_width = shot_num==1?750:((shot_num - 1)%3>1?250:375);
  164. thumb_scale = thumb_width/this.videoWidth;
  165. video_length = this.duration;
  166. this.currentTime = Math.floor(shot_index*video_length/(shot_num + 1));
  167. });
  168. video_resource.on('timeupdate', function(){
  169. if(update_flag){
  170. ctx_resource.drawImage(this, 0, 0, canvas_resource[0].width, canvas_resource[0].height);
  171. canvas_resource[0].toBlob(
  172. (function(shot_ind){
  173. return function(blob){
  174. processOrigin(blob, shot_ind);
  175. }
  176. })(shot_index)
  177. );
  178. downScaleCanvas(canvas_resource[0], thumb_scale).toBlob(
  179. (function(shot_ind){
  180. return function(blob){
  181. processThumb(blob, shot_ind);
  182. }
  183. })(shot_index)
  184. );
  185. ++shot_index;
  186. if(shot_index > shot_num){
  187. video_resource[0].pause();
  188. }
  189. else{
  190. video_resource[0].currentTime = Math.floor(shot_index*video_length/(shot_num + 1));
  191. }
  192. }
  193. });
  194. input_copy_snapshot.on('click', function(e){
  195. e.preventDefault();
  196. textarea_img_###ode[0].select();
  197. try{
  198. var successful = document.execCommand('copy');
  199. var msg = successful?{'text': '成功', 'color': '#FFFFFF'}:{'text': '失败', 'color': '#DD8944'};
  200. fadeInThenFadeOut(span_snapshot, '截图###ode复制' + msg.text, 500, msg.color);
  201. }
  202. catch(error){
  203. fadeInThenFadeOut(span_snapshot, '无法复制截图###ode', 500, '#DD8944');
  204. }
  205. });
  206. select_number.prop('disabled', false);
  207. }
  208. var imageBanSuccessCallback = function(r###lt, array, shot_index, data){
  209. var form = data;
  210. r###lt = JSON.parse(r###lt);
  211. if(r###lt.success){
  212. array[shot_index - 1] = r###lt.data.link;
  213. }
  214. else{
  215. console.log('Error: Upload Image');
  216. }
  217. checkProcess();
  218. }
  219. var smmsSuccessCallback = function(r###lt, array, shot_index, data){
  220. var form = data;
  221. if(r###lt.code == 'success'){
  222. array[shot_index - 1] = r###lt.data.url;
  223. checkProcess();
  224. }
  225. else{
  226. var file_name = 'TYT.png';
  227. for(var pair of form.entries()) {
  228. if(pair[0] == 'smfile'){
  229. file_name = pair[1].name;
  230. break;
  231. }
  232. }
  233. form.append('image', form.get('smfile'));
  234. form.append('Name', file_name);
  235. form.delete('smfile');
  236. shot_requests.push($.ajax({
  237. 'method': 'POST',
  238. 'url': 'https://api.imageban.ru/v1',
  239. 'data': form,
  240. 'contentType': false,
  241. 'processData': false,
  242. 'headers': {
  243. 'Authorization': 'TOKEN rtaDTmC0SLXmq9RXtIPg'
  244. },
  245. 'success': (function(array, shot_ind){
  246. return function(r###lt){
  247. imageBanSuccessCallback(r###lt, array, shot_ind);
  248. }
  249. })(array, shot_index),
  250. 'error': checkProcess
  251. }));
  252. }
  253. }
  254. var nhdSuccessCallback = function(r###lt, array, shot_index, data){
  255. var form = data;
  256. if(r###lt.match(/parent\.tag_extimage\('[^\)']+'\)/)){
  257. var ###ode = r###lt.match(/parent\.tag_extimage\('([^\)']+)'\)/)[1];
  258. form.append('body', ###ode);
  259. form.delete('file');
  260. shot_requests.push($.ajax({
  261. 'method': 'POST',
  262. 'url': 'http://www.nexushd.org/preview.php',
  263. 'data': form,
  264. 'contentType': false,
  265. 'processData': false,
  266. 'success': (function(array, shot_ind){
  267. return function(r###lt){
  268. nhdPreviewCallback(r###lt, array, shot_ind);
  269. }
  270. })(array, shot_index),
  271. 'error': checkProcess
  272. }));
  273. }
  274. else{
  275. form.append('smfile', form.get('file'));
  276. form.delete('file');
  277. shot_requests.push($.ajax({
  278. 'method': 'POST',
  279. 'url': 'https://sm.ms/api/upload',
  280. 'data': form,
  281. 'contentType': false,
  282. 'processData': false,
  283. 'success': (function(array, shot_ind, form_data){
  284. return function(r###lt){
  285. smmsSuccessCallback(r###lt, array, shot_ind, form_data);
  286. }
  287. })(array, shot_index, form),
  288. 'error': checkProcess
  289. }));
  290. }
  291. }
  292. var nhdPreviewCallback = function(r###lt, array, shot_index){
  293. if(r###lt.match(/src="[^"]+"/)){
  294. array[shot_index - 1] = r###lt.match(/src="\/*([^"]+)"/)[1].replace(/\.thumb\.jpg$/, '');
  295. checkProcess();
  296. }
  297. else{
  298. console.log('Error: Display Image');
  299. checkProcess();
  300. }
  301. }
  302. var processOrigin = function(blob, shot_index){
  303. var form = new FormData();
  304. form.append(
  305. 'smfile', new File([blob], shot_index + '.png', {
  306. type: 'image/png',
  307. lastModified: Date.now()
  308. })
  309. );
  310. shot_requests.push($.ajax({
  311. 'method': 'POST',
  312. 'url': 'https://sm.ms/api/upload',
  313. 'data': form,
  314. 'contentType': false,
  315. 'processData': false,
  316. 'success': (function(array, shot_ind, form_data){
  317. return function(r###lt){
  318. smmsSuccessCallback(r###lt, array, shot_ind, form_data);
  319. }
  320. })(image_url, shot_index, form),
  321. 'error': checkProcess
  322. }));
  323. }
  324. var processThumb = function(blob, shot_index){
  325. var form = new FormData();
  326. form.append(
  327. 'file', new File([blob], shot_index + '.png', {
  328. type: 'image/png',
  329. lastModified: Date.now()
  330. })
  331. );
  332. shot_requests.push($.ajax({
  333. 'method': 'POST',
  334. 'url': 'http://www.nexushd.org/attachment.php',
  335. 'data': form,
  336. 'contentType': false,
  337. 'processData': false,
  338. 'success': (function(array, shot_ind, form_data){
  339. return function(r###lt){
  340. nhdSuccessCallback(r###lt, array, shot_ind, form_data);
  341. }
  342. })(thumb_url, shot_index, form),
  343. 'error': checkProcess
  344. }));
  345. };
  346. var processAbort = function(){
  347. processing = false;
  348. shot_requests.forEach(function(e){
  349. try{
  350. e.abort();
  351. }
  352. catch(error){}
  353. });
  354. select_number.prop('disabled', false);
  355. }
  356. var processDone = function(){
  357. processing = false;
  358. var ###ode = '';
  359. image_url.forEach(function(e, i){
  360. if(thumb_url[i]){
  361. ###ode += '[url=' + e + '][img]' + thumb_url[i] + '[/img][/url] ';
  362. }
  363. });
  364. textarea_img_###ode.val(###ode);
  365. input_upload_snapshot.hide();
  366. input_copy_snapshot.prop('disabled', false);
  367. input_copy_snapshot.show();
  368. select_number.prop('disabled', false);
  369. }
  370. var checkProcess = function(){
  371. if(processing){
  372. ++counter;
  373. span_bar.css({
  374. 'width': (counter/shot_num/2)*100 + '%'
  375. });
  376. if(counter == shot_num*2){
  377. span_bar.css({
  378. 'background-color': '#2276BB'
  379. });
  380. processDone();
  381. }
  382. }
  383. }
  384. return {
  385. init: function(){
  386. $(document).ready(DOMEventInit);
  387. }
  388. }
  389. }