Pixiv Bookmark async

Add a bookmark in Pixiv on background using Fetch API.

目前为 2017-09-21 提交的版本。查看 最新版本

  1. /*
  2. // ==UserScript==
  3. // @namespace com.whoopsworkshop.hkgsherlock.userjs.pixiv_bookmark_async
  4. // @id com.whoopsworkshop.hkgsherlock.userjs.pixiv_bookmark_async
  5. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAAAA3NCSVQICAjb4U/gAAAAYnpUWHRSYXcgcHJvZmlsZSB0eXBlIEFQUDEAAHicVcixDYAwDADB3lN4hHccHDIOQgFFQoCyf0EBDVee7O1so696j2vrRxNVVVXPkmuuaQFmXgZuGAkoXy38TEQNDyseBiAPSLYUyXpQ8HMAAAUhSURBVFiF7ZltbBRFHMafmd29Xq9vh32lFNsCpYS38CZqFYtBG1FD0Eg0qBGNQQJBEZSgX/xmbUJCCKJGQxASEzQBCyRFECKQkFSFtOUKpWdbELgXoC29tne9u92d8cOVsne97W4LS/zAk/tyz8zO/G7mPzP/nSP46iiSSQSKbQJLWnZvUjiuyapeqaj7GNAe1X3MOtEH3+XIeghkpIdARtJdZcnFAcbBOHjsoykiBBSgBJSCWA3EOFQGhUEU3i4dN2981uTstNwMe6ZdEgXKOQ9GlM7+yJXu4Flvzw9tXZBVSAKEsZARvY1xUApDRFlUmLl6blFlWf7ER9LMNNp+s7f2vOeT+n/BOSRhVFg6QByQVTBeU1HyzuOl+ZmpCeVd/WFfYKA7FGWMO2xCXkZqSU768GZ+Pnvljd9aQAhEs8GaDEhWwbFrSdl7FVO0dlhWjzR7Drb497R1QuWg5O5PZxyMvzY5e9W8iS/NKor7aRwf7j/3tcsPhzR6IMYRkqsXlW5+fjoldwfaHxj48njLjibvYGQIOnPAOGQVIq1bNmvpzAnakoONV5cfOI8022iAIspj2Y7aNxcWOh3aGtv/uLThxD9wSBDMDTsHBuRV5bm7Vy7U2vUdt57c/SfSDZjoYBP90Z2VU/5atziBBsCOJi/SbWZpABDAIf3Y0bX4u9Na+4lJuYdXzEFINgJiHLLqWvPU2sqpMYvzuBpp5lG0koRTncH39/2t9V6eXbRpTiGUkZIaOjFF7Pv0uZkTxsW+1xy70Oy5PRaCZEy7Wm7+ftGr9ba+Mhcc4HrPgLrXL063D8b/lkNNW0602SXh/gABSJWqal0J3k9V5dBP0OhQ99VHL9Q0eEwuTrMigKIeafZovZULS6HqztpgfJxs9X9+5jLsozzazEgSdp29muBtmD1ej4kCUBl/9pcGOIw3ibGIkv2XuxO8F8rzoSSPI3o7FBUogcrv5Yg2ECFtN3u1xoxCJ5jOCG062AjAQhoAFJ6ekNYodDr0Fhrd3dEt1hxDigXRMyRC+sJx+yElBDT5GFCIVOUWj9BoRAHraTjPSh22YphOUFvMMtj3o/GZnbcnpDcKDwSIkuLsuPTN5bkNmrxr64EUtnHW+ATv8EU/RL2gtloR5YOKSVpDVtnOZr9ePmMxkMLeKs+dmp+l9b497Yak26+VQBxg/PsVC7ReTyj60cl26CcUlgFxIBRtXV2Raovre/ne+pGPcGMghetnU3pSGaLKpbWLEiZr44GGU7eCenu0WaCyjBSEZCgsMbfVQwlGXy9yBrdUlRfE0WyubdzW7IPNIPszPsJq361w3wj82nR9u8vnC4QhUFACQkDubPEc4ByMQ2GrpuVtqiwbSohjiijqq3vq67y9Zk7MYS+KYcW95umy/MyktfvCstsfuNId9AQGOkPRUFRlnKeniMVOx4yCrAWlOeKw6TjcdG3ZoWYIxOR7izHyN6fdVdMKpuRlAsiwS/NLcuaX5Jhpus51ff3x1o7eCFJE88elMdDWc9fXHXfDYftsRv4zpTkzC51F+lcOXf3hhqvdda03trl8AGATRpsWG9fOEGks868+76tu9EJl4JjstM8Z58hLk9JEIcp4IKK0BcJnbgWhMggUIhlzgmX6MYI7NxgCgPaI0u7r1aw7AgKkCLHSe9FYE8XYKrMgk/rf3TE+BDKSMRAf4WbAAsUDMY4BmcRHap/C8AD/hdEAMb68IKPni6WxTXlIlz9esu/F6SPcV9xf/QdhL+PXM2v0PQAAAABJRU5ErkJggg==
  6. // @name Pixiv Bookmark async
  7. // @version 201709211745+8
  8. // @author hkgsherlock
  9. // @license Unlicense
  10. // @description Add a bookmark in Pixiv on background using Fetch API.
  11. // @include /^https?:\/\/www\.pixiv\.net\/member_illust\.php?.*mode=(medium|manga).*$/
  12. // @grant none
  13. // ==/UserScript==
  14. */
  15.  
  16. const PIXIV_API_URL = 'https://www.pixiv.net/rpc/index.php';
  17. const BUTTON_TARGET_QUERY = '.bookmark-container .add-bookmark';
  18.  
  19. (() => {
  20. const target = document.querySelector(BUTTON_TARGET_QUERY);
  21.  
  22. target.addEventListener('click', (e) => {
  23. e.preventDefault();
  24.  
  25. const queryString = document.location.search.substr(1)
  26. .split('&')
  27. .map((e) => {
  28. const [key, value] = e.split('=');
  29. return {[key]: value};
  30. })
  31. .reduce((a,b)=>Object.assign(a,b),{});
  32. // https://google.com/search?q=pixiv+context+token
  33. const pixiv_context_token = window.pixiv.context.token; // not ranbu sry (; _ ;) i miss my manba-chan dayo~
  34. const illust_id = queryString.illust_id;
  35. const restricted = !!document.querySelector('.work-info .meta [class^="r-18"]');
  36. const comment = null;
  37. const tags = [...document.querySelectorAll('.tags .tag .text')].map((e) => e.innerText).join('+');
  38.  
  39. fetch(PIXIV_API_URL, {
  40. method: "POST",
  41. headers: {
  42. "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
  43. },
  44. credentials: "same-origin",
  45. body: [
  46. 'mode=save_illust_bookmark',
  47. `illust_id=${illust_id}`,
  48. `restrict=${!!restricted?1:0}`,
  49. 'comment'+(!!comment?`=${comment}`:''),
  50. 'tags'+(!!tags?`=${tags}`:''),
  51. `tt=${pixiv_context_token}`,
  52. ].join('&'),
  53. })
  54. .then((r) => r.json())
  55. .then((data) => {
  56. if (data.error) throw new Error(message || body.message);
  57. document.querySelector(BUTTON_TARGET_QUERY)
  58. .replaceWith(((id) => {
  59. const a = document.createElement('a');
  60. a.setAttribute('href', `bookmark_add.php?type=illust&illust_id=${id}`);
  61. a.classList.add('_bookmark-toggle-button');
  62. a.classList.add('bookmarked');
  63. a.classList.add('edit-bookmark');
  64. a.appendChild((() => {
  65. const span = document.createElement('span');
  66. span.classList.add('description');
  67. span.innerText = "ブックマークを編集";
  68. return span;
  69. })());
  70. a.appendChild((() => {
  71. const span = document.createElement('span');
  72. span.setAttribute('style', 'animation:nice-zoom-smile 1s forwards cubic-bezier(0.9, -1.5, 0.4, 1);'
  73. +'position:absolute;'
  74. +'top:50%;'
  75. +'left:50%;'
  76. +'width:32px;'
  77. +'height:32px;'
  78. +'margin:-16px 0 0 -16px;'
  79. +'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACdklEQVRIibWVXUhTcRiHHzaUOVysLJouI9MIv8gpmjbdzrmRidAExQjMWuTAqJAwKBTXhYWYSQol3WSzEgzsYwmK83PdZBeBhhKG0MdFpl0oGRna7GJbmGme6frB/+q87/Oc856Xc8C/aIFwP3skRwYUeI/sfwhiTx2OsJWYI6qA+EDDgxVB8uOTjszxqY7MCUWQ3AIoAinQN5Xvv+V2iUtul7jUfDG2CTAECq42HFBXzjmNr32C+V7hTXbaNhuwIxCC3K5rSXYf3HcGGnWtQJ6/sCA8q6gDsoFis357+eKgsLBS4HaJS8dMOy8Bxd5anbc3eCV0D555FsRoQ8pK87SVLRVxDcP21PY5p2HY7RJ/rgb/Pa4e48jI3bTHD2xxDaV52soYbUgZnlUWgCjwzNEy2Jh83+0SV71TP8/CQKPODliAMN9TaIUk9eXJp/q+zQo+O/S9Yoq6yjuuPxJt1oddmek0DG0UPttlGDIbwqqB6LVecuIJk6Z2zmkY9Rc+32scPZmrqQES19ukjPNHI6//6Dd+kApfHBTfXzgSWQdkrAf3xfSsJuGv3V/r9N3Q2QGTVDiA8PxmcptUwYvbKQ/xrKXk5Iy2HOySKphoS+8GcvwR5H98dOilVMGUI+sVkO+PoGi22/huOeSb0zjz5GrCnfbq+Oav3cYvy6997xOmgSKpcBlg9TVPd2SN15+NqVMp5VZABASVUl5Se3pv/SdH5pivLlQpK0Xin04VFa6wvm1N7z9TsMuG52OWBiiX1SiBVKDYkhteMXYvvUe3L/QcoJIi0ABWoBCIBeT/qJV7awq9PRopgi1ApJTCFdkNbN1A3+byC5PVP0NhP2rsAAAAAElFTkSuQmCC);'
  80. +'background-position:center;'
  81. +'background-repeat:no-repeat;'
  82. +'background-size:cover;'
  83. +'visibility:hidden;');
  84. return span;
  85. })());
  86. return a;
  87. })(illust_id));
  88. })
  89. .catch((err) => console.error(err));
  90. });
  91.  
  92. target.querySelector('.description').textContent += '*';
  93. })();