Greasy Fork 支持简体中文。

Includes : Persist BETA

Persist Function

目前為 2014-12-24 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/7144/29375/Includes%20%3A%20Persist%20BETA.js

  1. // ==UserScript==
  2. // @name Includes : Persist BETA
  3. // @namespace http://gm.wesley.eti.br
  4. // @description Persist Function
  5. // @author w35l3y
  6. // @email w35l3y@brasnet.org
  7. // @copyright 2013+, w35l3y (http://gm.wesley.eti.br)
  8. // @license GNU GPL
  9. // @homepage http://gm.wesley.eti.br
  10. // @version 1.0.1.0
  11. // @language en
  12. // @include nowhere
  13. // @exclude *
  14. // ==/UserScript==
  15.  
  16. /**************************************************************************
  17.  
  18. This program is free software: you can redistribute it and/or modify
  19. it under the terms of the GNU General Public License as published by
  20. the Free Software Foundation, either version 3 of the License, or
  21. (at your option) any later version.
  22.  
  23. This program is distributed in the hope that it will be useful,
  24. but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. GNU General Public License for more details.
  27.  
  28. You should have received a copy of the GNU General Public License
  29. along with this program. If not, see <http://www.gnu.org/licenses/>.
  30.  
  31. **************************************************************************/
  32.  
  33. var Persist = function (s) {
  34. var service = Persist.services[s];
  35.  
  36. this.request = function (obj) {
  37. var k,
  38. xthis = this,
  39. params = function (def) {
  40. var list = {};
  41.  
  42. this.add = function (vars) {
  43. if (vars) {
  44. if (vars instanceof unsafeWindow.HTMLCollection) {
  45. vars = Array.prototype.slice.apply(vars);
  46. }
  47.  
  48. if (typeof vars == "object") {
  49. for (var k in vars) {
  50. var e = vars[k];
  51.  
  52. if (typeof e == "object" && (!/^(?:radio|checkbox)$/i.test(e.type) || e.checked)) {
  53. var n = e.name || k;
  54.  
  55. if (e.checked && /^checkbox$/i.test(e.type)) {
  56. if (n in list) {
  57. list[n].push(e.value);
  58. } else {
  59. list[n] = [e.value];
  60. }
  61. } else if ("value" in e) {
  62. list[n] = e.value;
  63. } else {
  64. list[n] = e;
  65. }
  66. } else {
  67. list[k] = e;
  68. }
  69. }
  70. } else {
  71. list = vars;
  72. }
  73. }
  74. };
  75. this.toString = function() {
  76. if (typeof list == "object") {
  77. var data = "";
  78. for (var key in list) {
  79. if (list[key] instanceof Array) {
  80. var keyarr = key.replace(/^\s+|\s+$/g, "");
  81. if (!/\[\w*\]$/.test(key)) keyarr += "[]";
  82.  
  83. for (var k in list[key]) {
  84. var v = list[key][k];
  85. data += "&" + encodeURIComponent(keyarr) + "=" + encodeURIComponent(v);
  86. }
  87. } else {
  88. data += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(list[key]);
  89. }
  90. }
  91.  
  92. return data.substr(1);
  93. } else {
  94. return list;
  95. }
  96. };
  97. },
  98. data = new params();
  99.  
  100. data.add(obj.pdata);
  101. data.add(obj.adata);
  102. data.add(obj.data);
  103. data.add(obj.odata);
  104. if (typeof obj.onload != "function") {
  105. obj.onload = function (obj) {
  106. console.log(["request.load", obj]);
  107. };
  108. }
  109.  
  110. if (typeof obj.onerror != "function") {
  111. obj.onerror = function (obj) {
  112. console.log(["request.error", obj]);
  113. };
  114. }
  115.  
  116. var update = function (obj, e) {
  117. obj.response = {
  118. raw : function () {return e;},
  119. text : function () {return e.responseText;},
  120. json : function () {
  121. try {
  122. return JSON.parse(e.responseText);
  123. } catch (x) {
  124. return eval("(" + e.responseText + ")");
  125. }
  126. },
  127. doc : function () {
  128. try {
  129. return new DOMParser().parseFromString(e.responseText, /^Content-Type: ([\w/]+)$/mi.test(e.responseHeaders) && RegExp.$1 || "text/html");
  130. } catch (x) {
  131. var doc = document.implementation.createHTMLDocument("");
  132. doc.documentElement.innerHTML = e.responseText;
  133.  
  134. return doc;
  135. }
  136. },
  137. };
  138. obj.value = e.responseText;
  139. },
  140. params = {
  141. url : obj.url,
  142. method : obj.method,
  143. onload : function (e) {
  144. update(obj, e);
  145.  
  146. obj[(/^2/.test(e.status)?"onload":"onerror")].apply(xthis, [obj]);
  147. },
  148. onerror : function (e) {
  149. update(obj, e);
  150.  
  151. obj.onerror.apply(xthis, [obj]);
  152. }
  153. },
  154. sdata = data.toString();
  155.  
  156. if (/^post$/i.test(obj.method)) {
  157. var p = {
  158. headers : {
  159. "Content-Type" : "application/x-www-form-urlencoded"
  160. },
  161. data : sdata,
  162. };
  163.  
  164. console.log(sdata);
  165.  
  166. for (k in p) {
  167. params[k] = p[k];
  168. }
  169. } else if (sdata) {
  170. params.url += "?" + sdata;
  171.  
  172. }
  173. if (typeof obj.headers == "object")
  174. for (k in obj.headers) {
  175. params.headers[k] = obj.headers[k];
  176. }
  177.  
  178. return GM_xmlhttpRequest(params);
  179. };
  180.  
  181. for (var k in service) {
  182. this[k] = service[k];
  183. }
  184. };
  185.  
  186. Persist.services = {
  187. LOCAL : {
  188. write : function (obj) {
  189. var label_keys = "persist_keys-" + obj.service,
  190. label_data = "persist_data-" + obj.service,
  191. mapping = JSON.parse(GM_getValue(label_keys, "{}")),
  192. data = JSON.parse(GM_getValue(label_data, "[]")),
  193. key = obj.key;
  194.  
  195. if (key in mapping) {
  196. key = mapping[obj.key];
  197. }
  198.  
  199. if (key in data) {
  200. var tv = typeof obj.value,
  201. td = typeof data[key];
  202.  
  203. if ((td != tv) && (td == "object" || tv == "object")) {
  204. throw ["Incompatible types ", td, tv].toString();
  205. } else {
  206. switch (td) {
  207. case "string":
  208. if (-1 == obj.mode) { // prepend
  209. data[key] = obj.value + data[key];
  210. } else if (1 == obj.mode) { // append
  211. data[key] += obj.value;
  212. } else { // overwrite (default)
  213. data[key] = obj.value;
  214. }
  215. break;
  216. case "boolean":
  217. if (-1 == obj.mode) { // unused
  218. throw ["Reserved action"].toString();
  219. } else if (1 == obj.mode) { // toggle
  220. data[key] = !data[key];
  221. } else { // overwrite (default)
  222. data[key] = !!value;
  223. }
  224. break;
  225. case "number":
  226. var value = Number(obj.value);
  227.  
  228. if (-1 == obj.mode) { // subtract
  229. data[key] -= value;
  230. } else if (1 == obj.mode) { // add
  231. data[key] += value;
  232. } else { // overwrite (default)
  233. data[key] = value;
  234. }
  235. break;
  236. case "object":
  237. if (-1 == obj.mode) { // prepend
  238. for (var k in data[key]) {
  239. obj.value[k] = data[key][k];
  240. }
  241. data[key] = obj.value;
  242. } else if (1 == obj.mode) { // append
  243. for (var k in obj.value) {
  244. data[key][k] = obj.value[k];
  245. }
  246. } else { // overwrite (default)
  247. data[key] = obj.value;
  248. }
  249. break;
  250. default:
  251. throw ["Unsupported type " + td, data[key], key].toString();
  252. }
  253.  
  254. obj.value = data[key];
  255. }
  256. } else {
  257. var tkey = data.push(obj.value);
  258. if (--tkey != key) {
  259. if ("key" in obj) {
  260. if (key in mapping) {
  261. console.log(["Wrong mapping... ", tkey, key]);
  262. }
  263.  
  264. mapping[key] = tkey;
  265. obj.key = key;
  266.  
  267. GM_setValue(label_keys, JSON.stringify(mapping));
  268. } else {
  269. obj.key = tkey;
  270. }
  271. }
  272. }
  273.  
  274. GM_setValue(label_data, JSON.stringify(data));
  275.  
  276. if (typeof obj.onload != "function") {
  277. obj.onload = function (obj) {
  278. console.log(["write.load", obj]);
  279. };
  280. }
  281.  
  282. return obj.onload.apply(this, [obj]);
  283. },
  284. delete : function (obj) {
  285. throw ["Not implemented"].toString();
  286. },
  287. read : function (obj) {
  288. var mapping = JSON.parse(GM_getValue("persist_keys-" + obj.service, "{}")),
  289. key = obj.key;
  290.  
  291. if (key in mapping) {
  292. key = mapping[key];
  293. }
  294.  
  295. obj.value = JSON.parse(GM_getValue("persist_data-" + obj.service, "[]"))[key];
  296.  
  297. if (typeof obj.onload != "function") {
  298. obj.onload = function (obj) {
  299. console.log(["read.load", obj]);
  300. };
  301. }
  302.  
  303. return obj.onload.apply(this, [obj]);
  304. },
  305. },
  306. PASTEBIN : {
  307. write : function (obj) {
  308. var execute = function (x) {
  309. var onload = x.onload,
  310. value = x.value,
  311. xthis = this,
  312. p = {
  313. url : "http://pastebin.com/api/api_post.php",
  314. method : "post",
  315. adata : JSON.parse(GM_getValue("pastebin_adata", JSON.stringify({
  316. // api_dev_key : "", // required
  317. // api_user_key : "",
  318. }))),
  319. pdata : {
  320. api_paste_format : "text",
  321. api_paste_private : "1",
  322. api_paste_expire_date : "N",
  323. api_paste_code : x.value, // required
  324. },
  325. odata : {
  326. api_paste_key : obj.key,
  327. api_option : "paste"
  328. },
  329. onload : function (y) {
  330. if (/^https?:\/\//i.test(y.value) && /\w+$/.test(y.value)) {
  331. var key = x.key;
  332. x.key = RegExp["$&"];
  333.  
  334. x.onload = onload;
  335. x.value = value;
  336.  
  337. x.onload.apply(xthis, [x]);
  338.  
  339. if (x.read) {
  340. /* It is implemented that way because currently there isn't an EDIT option via API */
  341. y.key = key;
  342. y.onload = function (z) {
  343. console.log(["delete.load", z]);
  344. };
  345. y.onerror = function (z) {
  346. console.log(["delete.error", z]);
  347. };
  348.  
  349. xthis.delete.apply(xthis, [y]);
  350. }
  351. } else {
  352. x.onerror.apply(xthis, [x]);
  353. }
  354. }
  355. };
  356. for (var i in p) {
  357. x[i] = p[i];
  358. }
  359. return this.request(x);
  360. };
  361.  
  362. if (1 == Math.abs(obj.mode)) { // prepend or append
  363. var value = obj.value,
  364. onload = obj.onload,
  365. xthis = this;
  366.  
  367. obj.onload = function (x) {
  368. obj.onload = onload;
  369.  
  370. if (-1 == obj.mode) { // prepend
  371. obj.value = value + obj.value;
  372. } else { // append
  373. obj.value += value;
  374. }
  375. return execute.apply(xthis, [obj]);
  376. };
  377.  
  378. return this.read.apply(this, [obj]);
  379. } else {
  380. return execute.apply(this, [obj]);
  381. }
  382. },
  383. read : function (obj) {
  384. if ("key" in obj) {
  385. var onload = obj.onload,
  386. xthis = this,
  387. p = {
  388. read : false,
  389. url : "http://pastebin.com/download.php",
  390. method : "get",
  391. adata : {
  392. i : obj.key
  393. },
  394. onload : function (x) {
  395. obj.onload = onload;
  396.  
  397. if (x.response.raw().finalUrl.indexOf(x.url)) {
  398. obj.value = "";
  399.  
  400. obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(this, [obj]);
  401. } else {
  402. obj.read = true;
  403.  
  404. obj.onload.apply(xthis, [obj]);
  405. }
  406. }
  407. };
  408. for (var i in p) {
  409. obj[i] = p[i];
  410. }
  411.  
  412. return this.request(obj);
  413. } else {
  414. obj.value = "";
  415. obj.read = false;
  416.  
  417. obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(this, [obj]);
  418. }
  419. },
  420. delete : function (obj) {
  421. var onload = obj.onload,
  422. value = obj.value,
  423. xthis = this,
  424. p = {
  425. url : "http://pastebin.com/api/api_post.php",
  426. method : "post",
  427. adata : JSON.parse(GM_getValue("pastebin_adata", JSON.stringify({
  428. // api_dev_key : "", // required
  429. // api_user_key : "",
  430. }))),
  431. pdata : {},
  432. odata : {
  433. api_paste_key : obj.key,
  434. api_option : "delete"
  435. },
  436. onload : function (x) {
  437. if (/^Paste Removed$/i.test(x.value)) {
  438. obj.onload = onload;
  439. obj.value = value;
  440.  
  441. obj.onload.apply(xthis, [obj]);
  442. } else {
  443. obj.onerror.apply(xthis, [obj]);
  444. }
  445. }
  446. };
  447. for (var i in p) {
  448. obj[i] = p[i];
  449. }
  450. return this.request(obj);
  451. },
  452. },
  453. PASTEBIN2 : {
  454. write : function (obj) {
  455. var ovalue = obj.value,
  456. xthis = this,
  457. execute = function (x) {
  458. var onload = x.onload,
  459. nvalue = x.value,
  460. p = {
  461. method : "post",
  462. adata : JSON.parse(GM_getValue("pastebin2_adata", JSON.stringify({
  463. // paste_private : "1",
  464. }))),
  465. pdata : {
  466. paste_format : "1",
  467. paste_private : "2",
  468. paste_expire_date : "N",
  469. paste_code : x.value, // required
  470. },
  471. odata : {
  472. submit : "Submit",
  473. submit_hidden : "submit_hidden",
  474. item_key : obj.key,
  475. post_key : obj.key,
  476. },
  477. onload : function (y) {
  478. var doc = y.response.doc(),
  479. url = y.response.raw().finalUrl;
  480.  
  481. if (/warning\.php\?p=(\d+)/i.test(url)) {
  482. x.code = RegExp.$1 - 1;
  483. x.value = [
  484. "You have reached your limit of [10] pastes per 24 hours.",
  485. "You have reached your limit of [20] pastes per 24 hours.",
  486. "You have reached your limit of [250] pastes per 24 hours.",
  487. ][x.code] || xpath("string(id('content_left')/div[2])", doc) || "Unknown error (WARN " + x.code + ")";
  488.  
  489. x.onerror.apply(xthis, [x]);
  490. } else if ((/^https?:/i.test(url)) && (/\/(\w+)$/.test(url))) {
  491. x.key = RegExp.$1;
  492.  
  493. if (xpath("string(.//text()[contains(., 'Pastebin.com is under heavy load right now')])", doc)) {
  494. x.onerror.apply(xthis, [x]);
  495. } else {
  496. if (xpath("id('siimage')", doc)[0]) {
  497. x.value = nvalue;
  498. GM_log(ovalue);
  499. alert("A new window will be opened. You must fill the captcha correctly, otherwise you will lose your data and a new paste will be created next time.");
  500. GM_openInTab(url);
  501. } else {
  502. var code = xpath("id('paste_code')", doc)[0];
  503. x.value = code && code.textContent || "";
  504. }
  505. x.onload = onload;
  506. x.onload.apply(xthis, [x]);
  507. }
  508. } else {
  509. x.value = [
  510. "You have exceeded the maximum file size of [500] kilobytes per paste.",
  511. "You cannot create an empty paste.",
  512. "You have reached the maximum number of [25] unlisted pastes.",
  513. "You have reached the maximum number of [10] private pastes.",
  514. ][/index\.php\?e=(\d+)/.test(url) && (x.code = RegExp.$1 - 1)] || xpath("string(id('notice'))", doc) || "Unknown error (ERROR " + x.code + ")";
  515.  
  516. x.onerror.apply(xthis, [x]);
  517. }
  518. }
  519. };
  520. for (var i in p) {
  521. x[i] = p[i];
  522. }
  523.  
  524. return this.request(x);
  525. };
  526.  
  527. if (1 == Math.abs(obj.mode)) { // prepend or append
  528. var onload = obj.onload;
  529.  
  530. if ("" != ovalue) {
  531. obj.onload = function (x) {
  532. obj.onload = onload;
  533.  
  534. if (-1 == obj.mode) { // prepend
  535. obj.value = ovalue + obj.value;
  536. } else { // append
  537. obj.value += ovalue;
  538. }
  539. return execute.apply(xthis, [obj]);
  540. };
  541. }
  542.  
  543. return xthis.read.apply(xthis, [obj]);
  544. } else {
  545. return execute.apply(xthis, [obj]);
  546. }
  547. },
  548. read : function (obj) {
  549. var xthis = this;
  550.  
  551. if ("key" in obj && obj.key) {
  552. var onload = obj.onload,
  553. p = {
  554. read : false,
  555. url : "http://pastebin.com/download.php",
  556. method : "get",
  557. adata : {
  558. i : obj.key
  559. },
  560. onload : function (x) {
  561. var url = x.response.raw().finalUrl;
  562.  
  563. x.onload = onload;
  564.  
  565. if (url.indexOf(x.url)) { // Unknown Paste ID
  566. x.value = "";
  567. x.url = "http://pastebin.com/post.php";
  568. x.key = "";
  569.  
  570. x[typeof x.onwarn == "function"?"onwarn":"onload"].apply(this, [x]);
  571. } else if (~x.value.indexOf("this is a private paste. If this is your private paste")) { // may occur false positive
  572. x.value = "This is a private paste (#"+x.key+"). You must login to Pastebin first.";
  573. x.onerror.apply(xthis, [x]);
  574. } else if (~x.value.indexOf("Pastebin.com is under heavy load right now")) {
  575. x.value = "Pastebin.com is under heavy load right now.";
  576. x.onerror.apply(xthis, [x]);
  577. } else {
  578. x.read = true;
  579. x.url = "http://pastebin.com/edit.php";
  580.  
  581. x.onload.apply(xthis, [x]);
  582. }
  583. }
  584. };
  585. for (var i in p) {
  586. obj[i] = p[i];
  587. }
  588.  
  589. return this.request(obj);
  590. } else {
  591. obj.read = false;
  592. obj.url = "http://pastebin.com/post.php";
  593. obj.key = "";
  594.  
  595. this.request({
  596. url : "http://pastebin.com/",
  597. method : "get",
  598. onload : function (c) {
  599. if (xpath("boolean(id('header_bottom')//a[contains(@href, '/logout')])", c.response.doc())) {
  600. obj.value = "";
  601.  
  602. obj[typeof obj.onwarn == "function"?"onwarn":"onload"].apply(xthis, [obj]);
  603. } else {
  604. obj.value = "You must login to Pastebin first.";
  605.  
  606. obj.onerror.apply(xthis, [obj]);
  607. }
  608. },
  609. onerror : function (c) {
  610. c.value = xpath("string(id('content_left')/div[1])", c.response.doc());
  611.  
  612. obj.onerror(c);
  613. },
  614. });
  615. }
  616. },
  617. delete : function (obj) {
  618. var onload = obj.onload,
  619. value = obj.value,
  620. xthis = this,
  621. p = {
  622. url : "http://pastebin.com/delete.php",
  623. method : "get",
  624. adata : {},
  625. pdata : {},
  626. odata : {
  627. i : obj.key,
  628. r : "/" + obj.key
  629. },
  630. onload : function (x) {
  631. if (/^Paste Removed$/i.test(x.value)) {
  632. obj.onload = onload;
  633. obj.value = value;
  634.  
  635. obj.onload.apply(xthis, [obj]);
  636. } else {
  637. obj.onerror.apply(xthis, [obj]);
  638. }
  639. }
  640. };
  641. for (var i in p) {
  642. obj[i] = p[i];
  643. }
  644. return this.request(obj);
  645. }
  646. }
  647. };
  648.  
  649. Persist.write = function (obj) {
  650. var p = new Persist(obj.service);
  651.  
  652. return p.write.apply(p, [obj]);
  653. };
  654.  
  655. Persist.delete = function (obj) {
  656. var p = new Persist(obj.service);
  657.  
  658. return p.delete.apply(p, [obj]);
  659. };
  660.  
  661. Persist.read = function (obj) {
  662. var p = new Persist(obj.service);
  663.  
  664. return p.read.apply(p, [obj]);
  665. };