baidu-netdisk-rename

Renaming tool for web-based version of baidu netdisk. It supports batch renaming. 百度网盘的重命名小工具,支持批量重命名。

当前为 2020-04-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name baidu-netdisk-rename
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description Renaming tool for web-based version of baidu netdisk. It supports batch renaming. 百度网盘的重命名小工具,支持批量重命名。
  6. // @author neotan
  7. // @match https://pan.baidu.com/disk/*
  8. // @grant GM_addStyle
  9. // @grant GM_getResourceText
  10. // @resource purecss https://cdn.jsdelivr.net/npm/purecss@1.0.1/build/pure-min.min.css
  11. // @resource responsiveCss https://cdn.jsdelivr.net/npm/purecss@1.0.1/build/grids-responsive-min.css
  12. // ==/UserScript==
  13.  
  14. ;(async function () {
  15. 'use strict'
  16.  
  17. // ------------------- Utilities START ------------------- //
  18. function getMeta() {
  19. var filemanagerUrl
  20. var taskqueryUrl
  21.  
  22. try {
  23. var scriptTag = $('script').filter((i, ctt) => {
  24. return !ctt.src && ctt.text.includes('bdstoken')
  25. })[0]
  26. var txt = scriptTag.text.match(/var context=([\s\S]*?)var yunData/).pop().trim()
  27. var meta = JSON.parse(txt.slice(0, -1))
  28.  
  29. if (meta && meta.bdstoken) {
  30. filemanagerUrl = `https://pan.baidu.com/api/filemanager?opera=rename&async=2&onnest=fail&channel=chunlei&web=1&app_id=250528&bdstoken=${meta.bdstoken}&clienttype=0`
  31. taskqueryUrl = `https://pan.baidu.com/share/taskquery?taskid=1052678625270016&channel=chunlei&web=1&app_id=250528&bdstoken=${meta.bdstoken}&clienttype=0`
  32. }
  33. } catch (e) {
  34. console.error(e)
  35. }
  36.  
  37. return {
  38. filemanagerUrl,
  39. taskqueryUrl,
  40. }
  41. }
  42.  
  43. function getFileNames() {
  44. var nodes = document.querySelectorAll('.file-name .text a')
  45. return [...nodes].map(n => n.textContent)
  46. }
  47.  
  48. function escapeRegExp(str) {
  49. return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
  50. }
  51.  
  52. function createFileName(oldName, searchStr, replaceStr, applyToAll, caseSenstive, useRegexp = true) {
  53. var g = applyToAll ? 'g' : ''
  54. var i = caseSenstive ? '' : 'i'
  55. var rex = new RegExp(escapeRegExp(searchStr), g + i)
  56.  
  57. return oldName.replace(rex, replaceStr)
  58. }
  59.  
  60. function getCWD() {
  61. var addr = window.location.href
  62. var urlParams = new URLSearchParams(addr.substring(addr.indexOf('?') + 1))
  63. var cwd = urlParams.get('path')
  64. if (!cwd) {
  65. throw new Error('Can\'t get current working directory.')
  66. }
  67. return cwd
  68. }
  69.  
  70. function getBatchActions(cwd, batchText, applyToAll = true, caseSenstive = false, separator) {
  71. if (batchText && separator) {
  72. return batchText
  73. //.replace(/(^[ \t]*\n)/gm, "")
  74. .split('\n')
  75. .map(line => {
  76. line = line.trim()
  77. var namingPair = line.split(separator)
  78. if (namingPair && namingPair.length === 2) {
  79. return getAction(cwd, namingPair[0].trim(), namingPair[0].trim(), namingPair[1].trim(), applyToAll, caseSenstive)
  80. }
  81. })
  82. .filter(action => {
  83. console.log(action)
  84. return !!action
  85. })
  86. }
  87. }
  88.  
  89. function getAction(cwd, fileName, searchStr, replaceStr, applyToAll = true, caseSenstive = false) {
  90. var path = cwd + '/' + fileName
  91. var newname = createFileName(fileName, searchStr, replaceStr, applyToAll, caseSenstive)
  92.  
  93. return fileName !== newname ? {path, newname} : ''
  94. }
  95.  
  96. function getFormData(actions) {
  97. var formData = new FormData()
  98. formData.append('filelist', JSON.stringify(actions))
  99.  
  100. return formData
  101. }
  102.  
  103. function showMsg(msg) {
  104. $('.msg').html(msg).show('slow').delay(10000).hide(500)
  105. }
  106.  
  107. function postData(url, formData) {
  108. fetch(url, {
  109. method: 'POST',
  110. body: formData,
  111. })
  112. .then(res => res.json())
  113. .catch(err => console.error('Error:', err))
  114. .then(res => console.log('Response:', res))
  115. }
  116.  
  117. function toBatchMode() {
  118. $('.single-mode').map(function () {
  119. $(this).slideUp(() => {
  120. $('.batch-mode').map(function () {
  121. $(this).slideDown()
  122. })
  123. })
  124. })
  125.  
  126. }
  127.  
  128. function toSingleMode() {
  129. $('.batch-mode').map(function () {
  130. $(this).slideUp(() => {
  131. $('.single-mode').map(function () {
  132. $(this).slideDown()
  133. })
  134. })
  135. })
  136. }
  137.  
  138. // ------------------- Utilities END ------------------- //
  139.  
  140. // ------------------- Main Functions declaration START ------------------- //
  141. var msg = ''
  142. var isBatchMode = $('.batch-switcher').prop('checked', true)
  143. var customCss = `
  144. .pure-g {
  145. padding: 5px;
  146. display: flex;
  147. align-items: center;
  148. background: #f1f1f1;
  149. }
  150. .netdisk-rename{
  151. display: flex;
  152. }
  153. .rename-form {
  154. width: 100%;
  155. display: none;
  156. }
  157. .rename-form > label {
  158. white-space: nowrap;
  159. }
  160. .rename-btn-wrapper > label:not(:first-child) {
  161. margin-left: 10px;
  162. }
  163. .rename-form__input-text {
  164. width: 80%;
  165. }
  166. .rename-btn-wrapper > label:not(:last-child) {
  167. margin-right: 10px;
  168. }
  169. .msg{
  170. background: #b1e279;
  171. padding: 8px 10px;
  172. display: none;
  173. }
  174. .toggle-btn{
  175. font-size: 10px;
  176. position: absolute;
  177. top: 0;
  178. left: 0;
  179. z-index: 2147483647;
  180. width: 26px;
  181. transition: all .2s;
  182. }
  183. .rename-btn{
  184. width: 100%;
  185. }
  186. .rename-btn-wrapper{
  187. display: flex;
  188. }
  189. .author-label{
  190. font-size: 1.3rem;
  191. }
  192. .batch-mode{
  193. display: none;
  194. }
  195. .enlarge {
  196. width: 100px;
  197. height: 30px;
  198. font-size: 12px;
  199. }
  200. `
  201. var domHtml = `
  202. <div class="netdisk-rename">
  203. <button class="pure-button pure-button-primary toggle-btn" title="Toggle Netdisk renaming panel">R</button>
  204. <form class="pure-g pure-form rename-form">
  205. <div class="rename-btn-wrapper">
  206. <label class="pure-u-1 pure-button">Case Senstive? <input type="checkbox" name="caseSenstive" checked></label>
  207. <label class="pure-u-1 pure-button">Apply to all? <input type="checkbox" name="applyToAll" checked></label>
  208. <label class="pure-u-1 pure-button">Batch <input type="checkbox" class="batch-switcher" name="isBatchMode"></label>
  209. <button class="pure-button pure-button-primary rename-btn" type="submit">Rename</button>
  210. <a class="pure-link author-label" href="https://greasyfork.org/en/scripts/398489-baidu-netdisk-rename">&#9784;</a>
  211. </div>
  212. <div class="single-mode">
  213. <label class="pure-u-8-24">Replace: <input class="rename-form__input-text" type="text" name="searchStr"/></label>
  214. <label class="pure-u-8-24">with: <input class="rename-form__input-text" type="text" name="replaceStr"/></label>
  215. <label class="pure-u-7-24">Extension: <input class="rename-form__input-text" type="text" name="extention" size=10 value=".mp4" placeholder="all files"/></label>
  216. </div>
  217. <div class="batch-mode">
  218. <label class="pure-u-8-24">Separator: <input class="rename-form__input-text" type="text" name="separator" value="###"/></label>
  219. <label class="pure-u-1">
  220. <textarea class="pure-u-1" name="batchText" rows="4">
  221. oldName1 ### newName1
  222. oldName2 ### newName2
  223. </textarea>
  224. </label>
  225. </div>
  226. <div class="pure-u-1 msg">${msg}</div>
  227. </form>
  228. </div>
  229. `
  230.  
  231. function main() {
  232. GM_addStyle(GM_getResourceText('purecss'))
  233. GM_addStyle(GM_getResourceText('responsiveCss'))
  234. GM_addStyle(customCss)
  235. $('#layoutMain').prepend($(domHtml))
  236.  
  237. // initiate listeners
  238. $('.toggle-btn').hover(function () {
  239. $(this).addClass('enlarge').text('Rename Panel')
  240. }, function () {
  241. $(this).removeClass('enlarge').text('R')
  242. })
  243. $('.toggle-btn').click(() => $('.rename-form').slideToggle('fast'))
  244. $('.rename-form').submit(function (event) {
  245. event.preventDefault()
  246. var urlParams = new URLSearchParams($(this).serialize())
  247. var searchStr = urlParams.get('searchStr')
  248. var replaceStr = urlParams.get('replaceStr')
  249. var extention = urlParams.get('extention')
  250. var applyToAll = urlParams.get('applyToAll')
  251. var caseSenstive = urlParams.get('caseSenstive')
  252.  
  253. var isBatchMode = urlParams.get('isBatchMode')
  254. var batchText = urlParams.get('batchText')
  255. var separator = urlParams.get('separator')
  256.  
  257. var fileNames = getFileNames().filter(name => name.endsWith(extention))
  258. var cwd = getCWD()
  259.  
  260. var actions = []
  261. if (isBatchMode) {
  262. actions = getBatchActions(cwd, batchText, applyToAll = true, caseSenstive = false, separator)
  263. } else {
  264. actions = fileNames.map(fileName => getAction(cwd, fileName, searchStr, replaceStr, applyToAll, caseSenstive)).filter(action => action)
  265. }
  266.  
  267. var formData = getFormData(actions)
  268. var {filemanagerUrl, taskqueryUrl} = getMeta()
  269.  
  270. if (actions.length > 0 && filemanagerUrl && taskqueryUrl) {
  271. postData(filemanagerUrl, formData)
  272. postData(taskqueryUrl, formData)
  273. showMsg(`Tried renaming ${actions.length} files, please <a onclick="location.reload()" style="cursor:pointer;">Refresh</a> for result.`)
  274. } else {
  275. showMsg('Nothing matched!')
  276. }
  277. })
  278.  
  279. $('.batch-switcher').change(function () {
  280. if (this.checked) {
  281. toBatchMode()
  282. } else {
  283. toSingleMode()
  284. }
  285. })
  286. console.log('baidu-netdisk-rename initiated!')
  287. }
  288.  
  289. // ------------------- Main Functions declaration END ------------------- //
  290.  
  291. // ------------------- Main Functions execution START ------------------- //
  292. main()
  293. })()