Pixiv Lazy plus

provide a direct link to original image ([s] link).

当前为 2015-02-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Pixiv Lazy plus
  3. // @namespace pixivlazyplus
  4. // @description provide a direct link to original image ([s] link).
  5. // @version 0.8.14.1
  6. // @include http://www.pixiv.net/*
  7. // ==/UserScript==
  8. // version 0.8.14.1 - fix new medium page layout
  9. // version 0.8.13 - fix image response lazy link position
  10. // version 0.8.12 - fix mypage right side lazy links
  11. // version 0.8.11 - fix double links in medium page
  12. // version 0.8.10 - fix double links in medium page
  13. // version 0.8.9 - append [U] link after canvas
  14. // version 0.8.8 - fix loading big manga URL bug introduced in 0.8.7
  15. // version 0.8.7 - fix loading big manga URL in with PNG format
  16. // version 0.8.6 - fix modifying big manga URL in manga page
  17. // version 0.8.5 - fix preloading new manga URL format
  18. // version 0.8.4 - fix detecting URL new format
  19. // version 0.8.3 - fix detecting URL new format
  20. // version 0.8.2 - fix detecting URL new format
  21. // version 0.8.1 - fix detecting ugoira in prev/next
  22. // version 0.8.0 - add ability for downloading ugoira as zip
  23. // version 0.7.9 - fix for no profile image
  24. // version 0.7.8 - fix for spapi return value changes
  25. // version 0.7.7 - change [s] to [M](go directly to manga page) for manga links
  26. // version 0.7.6 - fix prev/next [s] link
  27. // version 0.7.5 - fix new manga page
  28. // version 0.7.4 - fix modified images
  29. // version 0.7.3 - fix missing session ID when it is not the end of cookie
  30. // version 0.7.2 - fix comma in tags breaking parsing logic
  31. // version 0.7.1 - fix iPhone API by supplying session ID
  32. // version 0.7 - work with new sample images with iPhone API, fix old manga
  33. // version 0.6.1 - preload manga images
  34. // version 0.6 - change manga mode to big images
  35. // version 0.5 - remove [b] link, add stylish style class
  36. // version 0.4 - updated to filter new thumbnails
  37. // version 0.3 - fix a bug, hat-tip to syosyo
  38. // version 0.2 - updated on 2008-06-25
  39. var pixivlink_run = 0;
  40. var isNewManga = 1;
  41. var postProcImg = new Array();
  42. var preloadImg = new Array();
  43. var Imgs = new Array();
  44. var sessID = (/PHPSESSID=[^;]*?(?=;|$)/.exec(document.cookie) || "");
  45. var mangaFormat = 'jpg';
  46.  
  47. String.prototype.splitCSV = function(sep) {
  48. for (var foo = this.split(sep = sep || ","), x = foo.length - 1, tl; x >= 0; x--) {
  49. if (foo[x].replace(/"\s+$/, '"').charAt(foo[x].length - 1) == '"') {
  50. if ((tl = foo[x].replace(/^\s+"/, '"')).length > 1 && tl.charAt(0) == '"') {
  51. foo[x] = foo[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
  52. } else if (x) {
  53. foo.splice(x - 1, 2, [foo[x - 1], foo[x]].join(sep));
  54. } else foo = foo.shift().split(sep).concat(foo);
  55. } else foo[x].replace(/""/g, '"');
  56. } return foo;
  57. };
  58.  
  59. function GetImageIDFromLink(imageLink) {
  60. var imgID = 0; // If lower 11319936 it means Manga does not have Big version
  61.  
  62. var re = /\d+([_a-z0-9]+)?\.(jpe?g|gif|png)\??.*$|id=[0-9]+$/;
  63. var s = re.exec(imageLink);
  64. if (s && s.length > 0) {
  65. re = /\d+/;
  66. imgID = re.exec(s[0])[0];
  67. }
  68. return imgID;
  69. }
  70.  
  71. function getElementsByClassName(matchClass) {
  72. var clselems = new Array();
  73. var elems = document.getElementsByTagName('*'), i;
  74. for (i in elems) {
  75. if((' ' + elems[i].className + ' ').indexOf(' ' + matchClass + ' ')
  76. > -1) {
  77. clselems.push(elems[i]);
  78. }
  79. }
  80. return clselems;
  81. }
  82.  
  83. function pixivlink() {
  84. //alert(pixivlink_run);
  85. if (!pixivlink_run) pixivlink_run = 1;
  86. else return;
  87. var Items = document.getElementsByTagName('img');
  88. var rexa = /\?mode\=medium\&illust_id|\?mode\=big\&illust_id/;
  89. var rexb = /source.pixiv.net/;
  90. var rexc = /\/img-inf\//;
  91. var rexd = /\/mobile\//;
  92. var rexe = /\/c\//;
  93. for (var i = 0; i < Items.length; i++) {
  94. var imgR = Items[i];
  95. var aR = imgR.parentNode.parentNode;
  96. var aR2 = imgR.parentNode;
  97. var isThumbnail = ((' ' + aR2.className + ' ').indexOf(' _layout-thumbnail ') > -1) && ((' ' + aR2.className + ' ').indexOf(' ui-modal-trigger ') > -1)
  98. if (rexa.test(aR2.href) || isThumbnail) {
  99. aR = aR2;
  100. }
  101. if (rexa.test(aR.href) || isThumbnail) {
  102. var imgID = GetImageIDFromLink(imgR.src);
  103. var srcR = imgR.src.replace(/_s\.|_m\.|_100\.|_64x64\./i, ".");
  104. // var hrefR = aR.href.replace(/medium/i, "big");
  105. var tdR = aR.parentNode;
  106. /* var linkB = document.createElement('a');
  107. linkB.href = hrefR;
  108. linkB.target = '_blank';
  109. linkB.style.padding = '0 2px';
  110. linkB.className = '_pxlazy';
  111. linkB.appendChild(document.createTextNode('[b]'));
  112. tdR.appendChild(linkB);*/
  113. // tdR.appendChild(document.createTextNode(' '));
  114. if (!rexb.test(srcR) && Imgs.indexOf(imgID) == -1) {
  115. var linkS = document.createElement('a');
  116. linkS.href = srcR;
  117. linkS.target = '_blank';
  118. linkS.className = '_pxlazy _pxlazy_s';
  119. linkS.setAttribute('id', 'ill_' + imgID);
  120. linkS.appendChild(document.createTextNode('[s]'));
  121. if (aR2.tagName.toUpperCase() == 'DIV' && imgR.className.toLowerCase().indexOf('thumbnail') == -1) {
  122. var targetelem = getElementsByClassName('works_display');
  123. if(targetelem.length) {
  124. targetelem[0].appendChild(linkS);
  125. }
  126. } else {
  127. tdR.appendChild(linkS);
  128. }
  129. if (rexc.test(imgR.src)||rexd.test(imgR.src)||rexe.test(imgR.src)) {
  130. //GM_log("postProcImg.push("+imgID+")"+imgR.src);
  131. postProcImg.push(imgID);
  132. }
  133. Imgs.push(imgID);
  134. }
  135. }
  136. }
  137.  
  138. if (postProcImg.length > 0) {
  139. for (var x = 0; x < postProcImg.length; x++) {
  140. GM_xmlhttpRequest({
  141. url: 'http://spapi.pixiv.net/iphone/illust.php?' + sessID + (sessID ? '&' : '') + 'illust_id=' + postProcImg[x],
  142. method: "GET",
  143. headers: {
  144. Referer: "http://www.pixiv.net"
  145. },
  146. onload: function (response) {
  147. if (response.status == 200) {
  148. var rexb = /source.pixiv.net/;
  149. // var rexU = /\/c\//;
  150. var rexU = /_480mw\./;
  151. var rexe = /\/c\//;
  152. var vals = response.responseText.splitCSV();
  153. /*var vtxt = '';
  154. for(var x=0;x < vals.length;x++)
  155. vtxt=vtxt+x+':'+vals[x]+"\n";
  156. GM_log(vtxt);*/
  157. if (vals.length > 0) {
  158. var slnk, imgID, isRestricted;
  159. isRestricted = rexb.test(vals[6]);
  160. isUgoira = !rexU.test(vals[9]);
  161. if (!isRestricted) {
  162. //GM_log("imgID = vals[0]");
  163. imgID = vals[0];
  164. } else {
  165. //GM_log("GetImageIDFromLink("+response.finalUrl+")");
  166. imgID = GetImageIDFromLink(response.finalUrl);
  167. }
  168. slnk = document.getElementById('ill_' + imgID);
  169. if (slnk) {
  170. var goodSlink;
  171. if (vals[19].length > 0) {
  172. goodSlink = 'http://www.pixiv.net/member_illust.php?mode=manga&illust_id=' + imgID;
  173. slnk.innerHTML = '[M]';
  174. } else {
  175. var re = new RegExp('/' + vals[0] + '_.*$');
  176. if (isUgoira) {// grab zip!
  177. //GM_log("isUgoira");
  178. slnk.innerHTML = '[U]';
  179. goodSlink = vals[9].replace(/c\/\d+x\d+\/img-master/, 'img-zip-ugoira').replace(re, '/' + vals[0] + '_ugoira1920x1080.zip');
  180. } else if (rexe.test(vals[9])) {// new 480mw URL
  181. //GM_log("480mw");
  182. goodSlink = vals[9].replace(/c\/480x960\//, '').replace(/img-master/, 'img-original').replace(re, '/' + vals[0] + '_p0.' + vals[2]);
  183. } else if (!isRestricted && !rexe.test(vals[9])) {// use 480mw instead
  184. //GM_log("480mw");
  185. goodSlink = vals[9].replace(/mobile\//, '').replace(re, '/' + vals[0] + '.' + vals[2]);
  186. } else { //salvage from profile image
  187. //GM_log("salvage");
  188. re = /\/[0-9_]+\..*$/;
  189. goodSlink = vals[29].replace(/mobile\//, '').replace(/profile\//, 'img/').replace(re, '/' + imgID + '.' + vals[2]);
  190. }
  191. }
  192. slnk.href = goodSlink;
  193. slnk.title=vals[12];
  194. slnk.className = '_pxlazy _pxlazy_s _pxlazy_s_new';
  195. }
  196. }
  197. }
  198. }
  199. });
  200. }
  201. }
  202.  
  203. var links = document.getElementsByTagName('a');
  204. var tagslink = /tags\.php\?tag=/;
  205. for (var i = 0; i < links.length; i++) {
  206. if (tagslink.test(links[i].href))
  207. links[i].href = links[i].href.replace("tags.php?tag=", "search.php?s_mode=s_tag_full&word=");
  208. }
  209.  
  210. if (unsafeWindow.pixiv && unsafeWindow.pixiv.context.images) {
  211. var illustID = GetImageIDFromLink(unsafeWindow.pixiv.context.images[0]/*[0]*/);
  212. isNewManga = (illustID >= 11319936);
  213. //GM_log("illustID="+illustID);
  214. GM_xmlhttpRequest({
  215. url: 'http://spapi.pixiv.net/iphone/illust.php?' + sessID + (sessID ? '&' : '') + 'illust_id=' + illustID,
  216. method: "GET",
  217. headers: {
  218. Referer: "http://www.pixiv.net"
  219. },
  220. onload: function (response) {
  221. if (response.status == 200) {
  222. var vals = response.responseText.splitCSV();
  223. var rexe = /\/c\//;
  224. mangaFormat = vals[2];
  225. /*var vtxt = '';
  226. for(var x=0;x < vals.length;x++)
  227. vtxt=vtxt+x+':'+vals[x]+"\n";
  228. GM_log(vtxt);*/
  229. //GM_log("2nd");
  230. if (rexe.test(vals[9])) mangaFull();
  231. }
  232. }
  233. });
  234. var rexe = /\/c\//;
  235. //GM_log("isNewManga");
  236. //setTimeout(mangaFull,250);
  237. //GM_log("2nd");
  238. mangaFull();
  239. }
  240. }
  241.  
  242. function mangaFull() {
  243. Items = document.getElementsByTagName('img');
  244. var rexe = /\/img-/;
  245. for (var x = 0; x < unsafeWindow.pixiv.context.images.length; x++) {
  246. if (isNewManga) {
  247. if(rexe.test(unsafeWindow.pixiv.context.images[x]))
  248. unsafeWindow.pixiv.context.images[x]/*[0]*/ = unsafeWindow.pixiv.context.images[x]/*[0]*/.replace(/c\/1200x1200\//, '').replace(/img-master/, 'img-original').replace(/_p(\d+).*(\.[a-zA-Z\?\d]+)$/, "_p$1."+mangaFormat);
  249. else
  250. unsafeWindow.pixiv.context.images[x]/*[0]*/ = unsafeWindow.pixiv.context.images[x]/*[0]*/.replace(/_p(\d+\.[a-zA-Z\?\d]+)$/, "_big_p$1");
  251. }
  252. preloadImg.push(new Image());
  253. preloadImg[preloadImg.length - 1].src = unsafeWindow.pixiv.context.images[x]/*[0]*/;
  254. }
  255.  
  256. for (var x = 0; x < Items.length; x++) {
  257. var datasrc = Items[x].getAttribute("data-src");
  258. if (datasrc) {
  259. //GM_log("original-datasrc="+datasrc+" ,mangaFormat="+mangaFormat);
  260. if(rexe.test(datasrc))
  261. datasrc = datasrc.replace(/c\/1200x1200\//, '').replace(/img-master/, 'img-original').replace(/_p(\d+).*(\.[a-zA-Z\?\d]+)$/, "_p$1."+mangaFormat);
  262. else
  263. datasrc = datasrc.replace(/_p(\d+\.[a-zA-Z\?\d]+)$/, "_big_p$1");
  264. //GM_log("new-datasrc="+datasrc+" ,mangaFormat="+mangaFormat);
  265. }
  266. Items[x].setAttribute("data-src", datasrc);
  267. if (isNewManga) {
  268. //GM_log(x+".src="+Items[x].src);
  269. if(datasrc)
  270. Items[x].src = datasrc;
  271. else if(rexe.test(Items[x].src))
  272. Items[x].src = Items[x].src.replace(/c\/1200x1200\//, '').replace(/img-master/, 'img-original').replace(/_p(\d+).*(\.[a-zA-Z\?\d]+)$/, "_p$1$2");
  273. else
  274. Items[x].src = datasrc ? datasrc : Items[x].src.replace(/_p(\d+\.[a-zA-Z\?\d]+)$/, "_big_p$1");
  275. }
  276. }
  277. }
  278.  
  279. window.addEventListener("load", pixivlink, true);