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. .split('\n')
  74. .map(line => {
  75. line = line.trim()
  76. var namingPair = line.split(separator)
  77. if (namingPair && namingPair.length === 2) {
  78. return getAction(cwd, namingPair[0].trim(), namingPair[0].trim(), namingPair[1].trim(), applyToAll, caseSenstive)
  79. }
  80. })
  81. .filter(action => action)
  82. }
  83. }
  84.  
  85. function getAction(cwd, fileName, searchStr, replaceStr, applyToAll = true, caseSenstive = false) {
  86. var path = cwd + '/' + fileName
  87. var newname = createFileName(fileName, searchStr, replaceStr, applyToAll, caseSenstive)
  88.  
  89. return fileName !== newname ? {path, newname} : ''
  90. }
  91.  
  92. function getFormData(actions) {
  93. var formData = new FormData()
  94. formData.append('filelist', JSON.stringify(actions))
  95.  
  96. return formData
  97. }
  98.  
  99. function showMsg(msg) {
  100. $('.msg').html(msg).show('slow').delay(10000).hide(500)
  101. }
  102.  
  103. function postData(url, formData) {
  104. fetch(url, {
  105. method: 'POST',
  106. body: formData,
  107. })
  108. .then(res => res.json())
  109. .catch(err => console.error('Error:', err))
  110. .then(res => console.log('Response:', res))
  111. }
  112.  
  113. function toBatchMode() {
  114. $('.single-mode').map(function () {
  115. $(this).slideUp(() => {
  116. $('.batch-mode').map(function () {
  117. $(this).slideDown()
  118. })
  119. })
  120. })
  121.  
  122. }
  123.  
  124. function toSingleMode() {
  125. $('.batch-mode').map(function () {
  126. $(this).slideUp(() => {
  127. $('.single-mode').map(function () {
  128. $(this).slideDown()
  129. })
  130. })
  131. })
  132. }
  133.  
  134. // ------------------- Utilities END ------------------- //
  135.  
  136. // ------------------- Main Functions declaration START ------------------- //
  137. var msg = ''
  138. var isBatchMode = $('.batch-switcher').prop('checked', true)
  139. var customCss = `
  140. .pure-g {
  141. padding: 5px;
  142. display: flex;
  143. align-items: center;
  144. background: #f1f1f1;
  145. }
  146. .netdisk-rename{
  147. display: flex;
  148. }
  149. .rename-form {
  150. width: 100%;
  151. display: none;
  152. }
  153. .rename-form > label {
  154. white-space: nowrap;
  155. }
  156. .rename-btn-wrapper > label:not(:first-child) {
  157. margin-left: 10px;
  158. }
  159. .rename-form__input-text {
  160. width: 80%;
  161. }
  162. .rename-btn-wrapper > label:not(:last-child) {
  163. margin-right: 10px;
  164. }
  165. .msg{
  166. background: #b1e279;
  167. padding: 8px 10px;
  168. display: none;
  169. }
  170. .toggle-btn{
  171. font-size: 10px;
  172. position: absolute;
  173. top: 0;
  174. left: 0;
  175. z-index: 2147483647;
  176. width: 26px;
  177. transition: all .2s;
  178. }
  179. .rename-btn{
  180. width: 100%;
  181. }
  182. .rename-btn-wrapper{
  183. display: flex;
  184. }
  185. .author-label{
  186. font-size: 1.3rem;
  187. }
  188. .batch-mode{
  189. display: none;
  190. }
  191. .enlarge {
  192. width: 100px;
  193. height: 30px;
  194. font-size: 12px;
  195. }
  196. `
  197. var domHtml = `
  198. <div class="netdisk-rename">
  199. <button class="pure-button pure-button-primary toggle-btn" title="Toggle Netdisk renaming panel">R</button>
  200. <form class="pure-g pure-form rename-form">
  201. <div class="rename-btn-wrapper">
  202. <label class="pure-u-1 pure-button">Case Senstive? <input type="checkbox" name="caseSenstive" checked></label>
  203. <label class="pure-u-1 pure-button">Apply to all? <input type="checkbox" name="applyToAll" checked></label>
  204. <label class="pure-u-1 pure-button">Batch <input type="checkbox" class="batch-switcher" name="isBatchMode"></label>
  205. <button class="pure-button pure-button-primary rename-btn" type="submit">Rename</button>
  206. <a class="pure-link author-label" href="https://greasyfork.org/en/scripts/398489-baidu-netdisk-rename">&#9784;</a>
  207. </div>
  208. <div class="single-mode">
  209. <label class="pure-u-8-24">Replace: <input class="rename-form__input-text" type="text" name="searchStr"/></label>
  210. <label class="pure-u-8-24">with: <input class="rename-form__input-text" type="text" name="replaceStr"/></label>
  211. <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>
  212. </div>
  213. <div class="batch-mode">
  214. <label class="pure-u-8-24">Separator: <input class="rename-form__input-text" type="text" name="separator" value="###"/></label>
  215. <label class="pure-u-1">
  216. <textarea class="pure-u-1" name="batchText" rows="4">
  217. oldName1 ### newName1
  218. oldName2 ### newName2
  219. </textarea>
  220. </label>
  221. </div>
  222. <div class="pure-u-1 msg">${msg}</div>
  223. </form>
  224. </div>
  225. `
  226.  
  227. function main() {
  228. GM_addStyle(GM_getResourceText('purecss'))
  229. GM_addStyle(GM_getResourceText('responsiveCss'))
  230. GM_addStyle(customCss)
  231. $('#layoutMain').prepend($(domHtml))
  232.  
  233. // initiate listeners
  234. $('.toggle-btn').hover(function () {
  235. $(this).addClass('enlarge').text('Rename Panel')
  236. }, function () {
  237. $(this).removeClass('enlarge').text('R')
  238. })
  239. $('.toggle-btn').click(() => $('.rename-form').slideToggle('fast'))
  240. $('.rename-form').submit(function (event) {
  241. event.preventDefault()
  242. var urlParams = new URLSearchParams($(this).serialize())
  243. var searchStr = urlParams.get('searchStr')
  244. var replaceStr = urlParams.get('replaceStr')
  245. var extention = urlParams.get('extention')
  246. var applyToAll = urlParams.get('applyToAll')
  247. var caseSenstive = urlParams.get('caseSenstive')
  248.  
  249. var isBatchMode = urlParams.get('isBatchMode')
  250. var batchText = urlParams.get('batchText')
  251. var separator = urlParams.get('separator')
  252.  
  253. var fileNames = getFileNames().filter(name => name.endsWith(extention))
  254. var cwd = getCWD()
  255.  
  256. var actions = []
  257. if (isBatchMode) {
  258. actions = getBatchActions(cwd, batchText, applyToAll = true, caseSenstive = false, separator)
  259. } else {
  260. actions = fileNames.map(fileName => getAction(cwd, fileName, searchStr, replaceStr, applyToAll, caseSenstive)).filter(action => action)
  261. }
  262.  
  263. var formData = getFormData(actions)
  264. var {filemanagerUrl, taskqueryUrl} = getMeta()
  265.  
  266. if (actions.length > 0 && filemanagerUrl && taskqueryUrl) {
  267. postData(filemanagerUrl, formData)
  268. postData(taskqueryUrl, formData)
  269. showMsg(`Tried renaming ${actions.length} files, please <a onclick="location.reload()" style="cursor:pointer;">Refresh</a> for result.`)
  270. } else {
  271. showMsg('Nothing matched!')
  272. }
  273. })
  274.  
  275. $('.batch-switcher').change(function () {
  276. if (this.checked) {
  277. toBatchMode()
  278. } else {
  279. toSingleMode()
  280. }
  281. })
  282. console.log('baidu-netdisk-rename initiated!')
  283. }
  284.  
  285. // ------------------- Main Functions declaration END ------------------- //
  286.  
  287. // ------------------- Main Functions execution START ------------------- //
  288. main()
  289. })()