Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export

Writes Mangakakalot, Manganelo, Manganato, Manga4life Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click

目前为 2022-09-10 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Mananelo/Mangakakalot/Manganato/Manga4life Bookmarks Export
  3. // @namespace http://smoondev.com/
  4. // @version 2.20
  5. // @description Writes Mangakakalot, Manganelo, Manganato, Manga4life Bookmarks (name and visited number) to "manga_bookmarks.txt" on "Export Bookmarks" button click
  6. // @author Shawn Moon
  7. // @match https://mangakakalot.com/bookmark*
  8. // @match https://manganelo.com/bookmark*
  9. // @match https://manganato.com/bookmark*
  10. // @match https://manga4life.com/user/bookmark.php
  11. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
  12. // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js
  13. // ==/UserScript==
  14.  
  15. function addBookarkStyles(css) {
  16. var head, style;
  17. head = document.getElementsByTagName('head')[0];
  18. if (!head) { return; }
  19. style = document.createElement('style');
  20. style.type = 'text/css';
  21. style.innerHTML = css;
  22. head.appendChild(style);
  23. }
  24.  
  25. addBookarkStyles(`
  26. #export_container_nato, #export_container_kakalot, #export_container_m4l {
  27. color: #000;
  28. cursor: pointer;
  29. float: right;
  30. }
  31.  
  32. #export_container_fun {
  33. display: inline-block;
  34. vertical-align: bottom;
  35. }
  36.  
  37. #export_container_kakalot {
  38. margin-right: 10px;
  39. }
  40.  
  41. #export_nato:hover, #export_kakalot:hover, #export_m4l:hover {
  42. background-color: #b6e4e3;
  43. color: #000;
  44. cursor: pointer;
  45. }
  46.  
  47. #export_nato, #export_kakalot, #export_m4l {
  48. border-radius: 5px;
  49. text-decoration: none;
  50. color: #fff;
  51. background-color: #76cdcb;
  52. border: none;
  53. font-weight: 600;
  54. }
  55.  
  56. #export_nato, #export_kakalot {
  57. padding: 4px 8px;
  58. }
  59.  
  60. #export_m4l {
  61. padding: 1px 12px;
  62. font-size: 16.5px;
  63. }
  64.  
  65. #export_fun {
  66. color: #f05759;
  67. background-color: #fff;
  68. border: 1px solid #f05759;
  69. display: inline-block;
  70. margin-bottom: 0;
  71. font-weight: 400;
  72. text-align: center;
  73. touch-action: manipulation;
  74. cursor: pointer;
  75. white-space: nowrap;
  76. padding: 6px 12px;
  77. border-radius: 0;
  78. user-select: none;
  79. transition: all .2s ease-in-out;
  80. }
  81.  
  82. #export_fun:hover {
  83. color: #fff;
  84. background-color: #f05759;
  85. }
  86.  
  87. #inclURL_nato, #inclURL_kakalot, #inclURL_fun, #inclURL_m4l {
  88. margin-left: 10px;
  89. }
  90.  
  91. .inclURL_kakalot, .inclURL_m4l {
  92. color: #ffffff;
  93. }
  94.  
  95. .inclURL_m4l {
  96. color: #ffffff;
  97. font-size: 15px;
  98. font-weight: 500;
  99. }
  100.  
  101. .inclURL_fun {
  102. font-weight:normal;
  103. }
  104.  
  105. #temp_data {
  106. position: absolute; top: -9999px;
  107. left: -9999px;
  108. }
  109. `);
  110.  
  111. (async function() {
  112. 'use strict';
  113. let pageI, bmTag, bmTitle, lastViewed, btnContainer, exportButtonID, inclURL, bookmarkedTitles = '',
  114. exportContainer, pageCount = 0, domain = window.location.hostname, bookmarkHeader = `===========================\n${domain} Bookmarks\n===========================\n`
  115.  
  116. if(domain == 'mangakakalot.com') {
  117. pageI = '.group_page a'
  118. bmTag = '.bookmark_item'
  119. bmTitle = '.bookmark_title'
  120. lastViewed = '.bookmark_chap a'
  121. btnContainer = '.breadcrumbs p'
  122.  
  123. inclURL = 'inclURL_kakalot'
  124. pageCount = parseInt($(`${pageI}`).last().text().replace(/\D+/g, ''))
  125. exportButtonID = 'export_kakalot'
  126. exportContainer = 'export_container_kakalot'
  127. } else if(domain == 'manganato.com' || domain == 'm.manganelo.com') {
  128. btnContainer = '.panel-breadcrumb'
  129.  
  130. inclURL = 'inclURL_nato'
  131. exportButtonID = 'export_nato'
  132. exportContainer = 'export_container_nato'
  133. } else if (domain == 'mangakakalot.fun') {
  134. bmTag = '.list-group-item'
  135. bmTitle = '.media-heading a'
  136. lastViewed = '.media-body p a'
  137. btnContainer = '.container-fluid:first div:last'
  138.  
  139. inclURL = 'inclURL_fun'
  140. exportButtonID = 'export_fun'
  141. exportContainer = 'export_container_fun'
  142. } else if (domain == 'manga4life.com') {
  143. inclURL = 'inclURL_m4l'
  144. exportButtonID = 'export_m4l'
  145. btnContainer = '.BoxHeader'
  146. exportContainer = 'export_container_m4l'
  147. }
  148.  
  149. const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay));
  150.  
  151. const saveFile = saveData => {
  152. // save file
  153. const fileData = new Blob([saveData], {type:"application/octet-stream"})
  154. saveAs(fileData, "manga_bookmarks.txt")
  155.  
  156. $(`#${exportButtonID}`).html('Export Bookmarks').prop('disabled', false)
  157. }
  158.  
  159. const deleteTemp = () => {
  160. // delete temp container
  161. $('#temp_data').remove()
  162. }
  163.  
  164. const getCookie = (name = 'user_acc') => {
  165. let returnVal = false
  166. const value = `; ${document.cookie}`
  167. try {
  168. const parts = value.split(`; ${name}=`)
  169. if (parts.length === 2) {
  170. let user = parts.pop().split(';').shift()
  171. if(name == 'user_acc') {
  172. user = JSON.parse(decodeURIComponent(user))
  173. returnVal = user.user_data
  174. }
  175.  
  176. }
  177. } catch (e) {
  178. returnVal = false
  179. }
  180.  
  181. return returnVal
  182. }
  183.  
  184. const getBMs = async (userCookie, currentPage = 1) => {
  185. var myHeaders = new Headers();
  186. myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
  187.  
  188. var urlencoded = new URLSearchParams();
  189. urlencoded.append("out_type", "json");
  190. urlencoded.append("bm_source", "manganato");
  191. urlencoded.append("bm_page", currentPage);
  192. urlencoded.append("user_data", userCookie);
  193.  
  194. var requestOptions = {
  195. method: 'POST',
  196. headers: myHeaders,
  197. body: urlencoded,
  198. redirect: 'follow'
  199. };
  200.  
  201. let bmArray = []
  202.  
  203. return await fetch("https://user.mngusr.com/bookmark_get_list_full", requestOptions)
  204. .then(response => response.json())
  205. .then(result => result)
  206. .catch(error => console.log('ExportError', error));
  207. }
  208.  
  209. const getFunBMs = (url) => {
  210. let bmItems = $(`${bmTag}`)
  211. for(let i = 0; i < bmItems.length; i++) {
  212. let title = $(bmItems[i]).find(bmTitle)[0]?.text || false
  213. let lastViewed = $(bmItems[i]).find('.media-body p a')[0] || false
  214. bookmarkedTitles += `${title} || Viewed: ${lastViewed ? lastViewed.text : 'None'} ${url ? (lastViewed ? `- ${lastViewed.href}` : '') : ''} \n`
  215. }
  216. saveFile(bookmarkedTitles)
  217. }
  218.  
  219. const getM4LBMs = (url) => {
  220. var myHeaders = new Headers();
  221. let userCookie = document.cookie
  222. myHeaders.append("cookie", userCookie);
  223.  
  224. var urlencoded = new URLSearchParams();
  225.  
  226. var requestOptions = {
  227. method: 'POST',
  228. headers: myHeaders,
  229. body: urlencoded,
  230. redirect: 'follow'
  231. };
  232.  
  233. fetch("https://manga4life.com/user/bookmark.get.php", requestOptions)
  234. .then(response => response.json())
  235. .then(result => {
  236. let {success = false, val = []} = result
  237. if(success && val.length) {
  238. for(let i = 0; i < val.length; i++) {
  239. let chapter = parseInt(val[i].Chapter.slice(1, -1))
  240. let page = val[i].Page == 0 ? '' : `-page-${val[i].Page}`
  241. let link = `https://manga4life.com/read-online/${val[i].IndexName}-chapter-${chapter}${page}.html`
  242. bookmarkedTitles += `${val[i].SeriesName} || Viewed: ${chapter} ${url ? `- ${link}` : ''} \n`
  243. }
  244. saveFile(bookmarkedTitles)
  245. }
  246. })
  247. .catch(error => console.log('error', error));
  248. }
  249.  
  250. if($(`${exportContainer}`).length === 0){
  251. $(`${btnContainer}`).append(`<div id='${exportContainer}'><button id='${exportButtonID}'>Export Bookmarks</button><input type="checkbox" id="${inclURL}"><span style="margin-left: 5px;"><label for="${inclURL}" class='${inclURL}'>Add URL</span></label></div>`)
  252. }
  253.  
  254. const getBookmarks = (url) => {
  255. // main function generate file
  256. deleteTemp()
  257.  
  258. $('body').append("<div id='temp_data'>")
  259. let pageSuccess = 0;
  260. let bookmarkedTitles = bookmarkHeader
  261.  
  262. for(let i = 0; i < pageCount; i++) {
  263. $("#temp_data").append(`<div id='page${i+1}'>`)
  264. $(`#page${i+1}`).load(`https://${domain}/bookmark?page=${i+1} ${bmTag}`, (resp,status,xhr) => {
  265. if(status == "success") { pageSuccess++ }
  266. if(pageSuccess == pageCount) {
  267. let bmItem = $(`#temp_data ${bmTag}`)
  268. for(let j = 0; j < bmItem.length; j++) {
  269. if($(bmItem[j]).find(`${bmTitle}`).text()) {
  270. let last_viewed = $(bmItem[j]).find(`${lastViewed}`),
  271. bookmarked_title = $(bmItem[j]).find(`${bmTitle}`);
  272. if(bookmarked_title.length > 0) {
  273. bookmarkedTitles += $(bmItem[j]).find(`${bmTitle}`).text() + ` || Viewed: ${last_viewed.length > 0 ? last_viewed[0].text : 'Not Found' } ${url ? `- ${last_viewed[0].href}` : ''} \n`
  274. }
  275. }
  276. }
  277.  
  278. saveFile(bookmarkedTitles)
  279. deleteTemp()
  280. }
  281. })
  282. }
  283. }
  284.  
  285. $(`#${exportButtonID}`).on('click', async function() {
  286. bookmarkedTitles = bookmarkHeader
  287. let inclURLCheck = $(`#${inclURL}`).is(':checked');
  288.  
  289. if(domain == 'mangakakalot.com') {
  290. $(this).html('Generating File...').prop('disabled', true)
  291. getBookmarks(inclURLCheck)
  292. } else if(domain == 'manganato.com' || domain == 'm.manganelo.com') {
  293. let userData = getCookie()
  294. if(userData) {
  295. $(this).html('Generating File...').prop('disabled', true)
  296. let initBMFetch = await getBMs(userData)
  297. pageCount = initBMFetch.bm_page_total || 0
  298. if(pageCount > 0) {
  299. for(let i = 1; i <= pageCount; i++) {
  300. let currPage = await getBMs(userData, i)
  301. let currPageBMs = currPage.data
  302. for(let j = 0; j < currPageBMs.length; j++) {
  303. bookmarkedTitles += `${currPageBMs[j].note_story_name} || Viewed: ${currPageBMs[j].chapter_namenow} ${inclURLCheck ? `- ${currPageBMs[j].link_chapter_now}` : ''} \n`
  304. }
  305. }
  306.  
  307. saveFile(bookmarkedTitles)
  308. }
  309. }
  310. } else if (domain == 'mangakakalot.fun') {
  311. getFunBMs(inclURLCheck)
  312. } else if (domain == 'manga4life.com') {
  313. getM4LBMs(inclURLCheck)
  314. }
  315. })
  316. })();