ali_api.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /*
  2. * @Author: samples jadehh@live.com
  3. * @Date: 2023-12-14 11:03:04
  4. * @LastEditors: samples jadehh@live.com
  5. * @LastEditTime: 2023-12-14 11:03:04
  6. * @FilePath: /lib/ali_api.js
  7. * @Description: 阿里云盘Api
  8. */
  9. import {_, jinja2} from "./cat.js";
  10. import * as Utils from "./utils.js";
  11. import {JadeLogging} from "./log.js";
  12. import {
  13. Code, Drive, getHeader, getOAuthCache, getUserCache, Item, OAuth, post, postJson, Sub, User, CLIENT_ID
  14. } from "./ali_object.js";
  15. let quality = {}, tempIds = [], shareToken = "", shareId = "", oauth = new OAuth(), user = new User(),
  16. driveInfo = new Drive(), tmpFolderName = "TV", curTmpFolderFileId = "",
  17. JadeLog = new JadeLogging("阿里云盘", "INFO");
  18. async function initSome() {
  19. let user_cache_str = await getUserCache();
  20. user = User.objectFrom(user_cache_str);
  21. if (!_.isEmpty(user.getRefreshToken())) {
  22. await JadeLog.info("读取用户缓存成功", true);
  23. } else {
  24. await JadeLog.error("读取用户缓存失败", true);
  25. }
  26. let oauth_cache_str = await getOAuthCache();
  27. oauth = OAuth.objectFrom(oauth_cache_str);
  28. if (!_.isEmpty(oauth.getAccessToken())) {
  29. await JadeLog.info("读取授权成功", true)
  30. } else {
  31. await JadeLog.error("读取授权失败", true)
  32. }
  33. // quality = {
  34. // "4K": "UHD", "2k": "QHD", "超清": "FHD", "高清": "HD", "标清": "SD", "流畅": "LD"
  35. // };
  36. quality = {
  37. "4K": "UHD", "2k": "QHD", "超清": "QHD", "高清": "HD", "标清": "SD", "流畅": "LD"
  38. };
  39. await JadeLog.info("阿里Api初始化完成")
  40. }
  41. async function getTempFileId() {
  42. curTmpFolderFileId = await createTmpFolder();
  43. }
  44. async function clearFile() {
  45. try {
  46. await deleteTmpFolderAndRecreate();
  47. } catch (e) {
  48. await JadeLog.error("清空缓存文件失败,失败原因为:{}" + e)
  49. }
  50. await cleanRecord()
  51. }
  52. async function cleanRecord() {
  53. await local.set("file", "file_id", JSON.stringify({}))
  54. }
  55. async function setShareId(share_id) {
  56. getOAuthCache().length === 0 && (await oauth.clean().save());
  57. getUserCache().length === 0 && (await user.clean().save());
  58. shareId = share_id;
  59. return await refreshShareToken();
  60. }
  61. function getHeaderAuth(shareToken) {
  62. const params = {};
  63. params["x-share-token"] = shareToken;
  64. params["X-Canary"] = "client=Android,app=adrive,version=v4.3.1";
  65. if (user.isAuthed()) {
  66. params.authorization = user.getAuthorization();
  67. }
  68. return params;
  69. }
  70. function getHeaderShare() {
  71. const params = getHeader();
  72. params["x-share-token"] = shareToken;
  73. params["X-Canary"] = "client=Android,app=adrive,version=v4.3.1";
  74. return params;
  75. }
  76. function getHeaderOpen() {
  77. const params = {};
  78. params.authorization = oauth.getAuthorization();
  79. return params;
  80. }
  81. function aliExpection(data_str) {
  82. if (data_str.indexOf("TooManyRequests") > -1) {
  83. Utils.sleep(1)
  84. return {code: 429, content: data_str}
  85. } else if (data_str.indexOf("AccessTokenInvalid") > -1) {
  86. return {code: 400, content: data_str}
  87. } else if (data_str.indexOf("AccessTokenExpired") > -1) {
  88. return {code: 401, content: data_str}
  89. } else if (data_str.indexOf("BadRequest") > -1) {
  90. return {code: 402, content: data_str}
  91. } else if (data_str.indexOf("NotFound.File") > -1 || data_str.indexOf("ForbiddenFileInTheRecycleBin") > -1) {
  92. return {code: 403, content: data_str}
  93. } else if (data_str.indexOf("ForbiddenNoPermission.File") > -1) {
  94. return {code: 500, content: data_str}
  95. } else if (data_str.indexOf("InvalidParameter.ToParentFileId") > -1) {
  96. return {code: 501, content: data_str}
  97. } else if (data_str.indexOf("NotFound.ParentFileId") > -1) {
  98. return {code: 502, content: data_str}
  99. } else if (data_str.indexOf("The resource drive has exceeded the limit. File size exceeded drive capacity") > -1) {
  100. return {code: 503, content: data_str}
  101. }
  102. return {code: 200, content: data_str}
  103. }
  104. async function alistManyRequest(data_str) {
  105. if (!(data_str.indexOf("Too Many Requests") > -1)) {
  106. return false;
  107. }
  108. await oauth.clean().save();
  109. return true;
  110. }
  111. // Alist Token获取
  112. async function alist(url_param, params) {
  113. let url = "https://api-cf.nn.ci/alist/ali_open/" + url_param;
  114. let response = await postJson(url, params, getHeader()), response_content = response.content;
  115. if (await alistManyRequest(response_content)) {
  116. await JadeLog.error(`Alist授权Token失败,失败原因为:太多请求,失败详情为:${response_content}`)
  117. return false;
  118. }
  119. oauth = await OAuth.objectFrom(response_content).save();
  120. return true;
  121. }
  122. // 阿里云盘用户Api
  123. async function auth(url, params, shareToken, retry) {
  124. url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
  125. let response = await postJson(url, params, getHeaderAuth(shareToken));
  126. await JadeLog.debug(`正在请求需要阿里登录的url:${url},参数为:${JSON.stringify(params)}`)
  127. response = aliExpection(response.content)
  128. if (retry && (response.code === 400)) {
  129. await JadeLog.error("登录阿里云盘失败,失败原因为:登录Token无效,准备重新授权,失败详情:" + response.content)
  130. await refreshAccessToken("")
  131. return await auth(url, params, shareToken, false);
  132. }
  133. await JadeLog.debug(`完成请求需要阿里登录的url:${url},参数为:${JSON.stringify(params)},请求结果为${response.content}`)
  134. return response.content;
  135. }
  136. // 需要授权的Api
  137. async function oauthFunc(url, params, retry) {
  138. url = url.startsWith("https") ? url : "https://open.aliyundrive.com/adrive/v1.0/" + url;
  139. await JadeLog.debug(`正在请求需要阿里授权的url:${url},参数为:${JSON.stringify(params)}`)
  140. let open_header = getHeaderOpen();
  141. let response = await postJson(url, params, open_header);
  142. response = aliExpection(response.content)
  143. if (retry && (response.code === 400 || response.code === 401 || response.code === 429 || response.code === 402 || response.code === 403)) {
  144. if (response.code === 400) {
  145. await JadeLog.error("阿里授权失败,失败原因为:授权Token无效,准备重新授权,失败详情:" + response.content)
  146. await activateRefreshOpenToken()
  147. } else if (response.code === 401) {
  148. await JadeLog.error("阿里授权失败,失败原因为:授权Token失效,准备重新授权,失败详情:" + response.content)
  149. await activateRefreshOpenToken()
  150. } else if (response.code === 402) {
  151. await JadeLog.error("阿里授权失败,失败原因为:授权Token失效,准备重新授权,失败详情:" + response.content)
  152. return await oauthFunc(url, params, true)
  153. } else if (response.code === 403) {
  154. await JadeLog.error("阿里授权失败,失败原因为:没有找到缓存文件,失败详情:" + response.content)
  155. await cleanRecord()
  156. return "retry"
  157. } else if (response.code === 429) {
  158. await JadeLog.error(`正在请求需要阿里授权的url:${url},请求过于频繁,稍后重试,10分钟后再重试`)
  159. Utils.sleep(10 * 60)
  160. return await oauthFunc(url, params, true)
  161. }
  162. return await oauthFunc(url, params, false)
  163. }
  164. await JadeLog.debug(`完成请求需要阿里授权的url:${url},参数为:${JSON.stringify(params)},请求结果为:${JSON.stringify(response)}`)
  165. return response.content;
  166. }
  167. async function shareFunc(url, params) {
  168. url = url.startsWith("https") ? url : "https://api.aliyundrive.com/" + url;
  169. let headers = getHeaderShare(), response = await postJson(url, params, headers);
  170. return response.content;
  171. }
  172. //主动刷新授权Token
  173. async function activateRefreshOpenToken() {
  174. await oauth.clean().save()
  175. await refreshOpenToken()
  176. }
  177. async function refreshShareToken() {
  178. try {
  179. let params = {};
  180. params.share_id = shareId;
  181. params.share_pwd = "";
  182. let response_content = await post("v2/share_link/get_share_token", params),
  183. response_json = JSON.parse(response_content);
  184. if (response_json["code"] === "ShareLink.Cancelled") {
  185. await JadeLog.error("分享链接被取消了")
  186. }
  187. shareToken = response_json.share_token;
  188. return shareToken
  189. } catch (e) {
  190. await JadeLog.error("刷新Share Token失败" + e)
  191. }
  192. }
  193. //支持切换Token
  194. async function refreshAccessToken(token) {
  195. try {
  196. if (_.isEmpty(user.getAccessToken()) || user.getRefreshToken() !== token) {
  197. let refresh_token_params = {};
  198. refresh_token_params.refresh_token = user.getRefreshToken();
  199. refresh_token_params.grant_type = "refresh_token";
  200. await JadeLog.info(`准备登录阿里云盘,登录Token为:${user.getRefreshToken()}`)
  201. let response_conetent = await post("https://auth.aliyundrive.com/v2/account/token", refresh_token_params);
  202. if (response_conetent.indexOf("InvalidParameter.RefreshToken") > 1 || _.isEmpty(response_conetent)) {
  203. if (_.isEmpty(response_conetent)) {
  204. await JadeLog.error(`登录阿里云盘失败,登录Token为:${user.getRefreshToken()},失败原因为:检查Token是否正确`)
  205. } else {
  206. await JadeLog.error(`登录阿里云盘失败,登录Token为:${user.getRefreshToken()},失败原因为:检查Token是否正确,返回结果为:${response_conetent}`)
  207. }
  208. } else {
  209. await JadeLog.info(`登录阿里云盘成功,登录Token为:${user.getRefreshToken()}`)
  210. user = await User.objectFrom(response_conetent).save();
  211. }
  212. } else {
  213. await JadeLog.info(`阿里云盘已登录,无需重复登录,登录Token为:${user.getRefreshToken()}`)
  214. }
  215. return true;
  216. } catch (e) {
  217. await JadeLog.error(`登录阿里云盘失败,登录Token为:${user.getRefreshToken()},失败原因为:${e}`)
  218. await user.clean().save();
  219. return true;
  220. }
  221. }
  222. async function oauthRequest() {
  223. try {
  224. let params = {};
  225. params.authorize = 1;
  226. params.scope = "user:base,file:all:read,file:all:write";
  227. let url = "https://open.aliyundrive.com/oauth/users/authorize?client_id=" + CLIENT_ID + "&redirect_uri=https://alist.nn.ci/tool/aliyundrive/callback&scope=user:base,file:all:read,file:all:write&state="
  228. await JadeLog.debug(`正在请求获取阿里授权码的url:${url},参数为:${params}`)
  229. let response_str = await auth(url, params, shareToken, true);
  230. await JadeLog.debug(`完成请求获取阿里授权码的url:${url},参数为:${params},返回值为:${response_str}`)
  231. if (_.isEmpty(response_str) || response_str.indexOf("AccessTokenInvalid") > -1) {
  232. if (_.isEmpty(response_str)) {
  233. await JadeLog.error(`请求获取阿里授权码失败,失败原因为:还未登录`)
  234. } else {
  235. await JadeLog.error(`请求获取阿里授权码失败,失败原因为:还未登录,失败详情为:${response_str}`)
  236. }
  237. } else {
  238. await JadeLog.info(`请求获取阿里授权码成功,返回值为:${response_str}`)
  239. return await oauthRedirect(Code.objectFrom(response_str).getCode());
  240. }
  241. } catch (e) {
  242. await JadeLog.error(`请求获取阿里授权失败,失败原因为:${e}`)
  243. return false;
  244. }
  245. }
  246. async function oauthRedirect(code) {
  247. try {
  248. let params = {};
  249. params.code = code;
  250. params.grant_type = "authorization_code";
  251. return await alist("code", params);
  252. } catch (e) {
  253. // // console.debug(_0x114c46);
  254. await oauth.clean().save();
  255. return false;
  256. }
  257. }
  258. async function refreshOpenToken() {
  259. try {
  260. // 刷新 Refresh Token
  261. if (_.isEmpty(oauth.getRefreshToken())) {
  262. return await oauthRequest();
  263. }
  264. // 刷新Access Token
  265. if (_.isEmpty(oauth.getAccessToken())) {
  266. let params = {};
  267. params.grant_type = "refresh_token";
  268. params.refresh_token = oauth.getRefreshToken();
  269. return await alist("token", params);
  270. }
  271. return true;
  272. } catch (e) {
  273. await JadeLog.error("刷新授权Token失败,失败原因为:" + e);
  274. await oauth.clean().save();
  275. return false;
  276. }
  277. }
  278. async function getFileByShare(share_token, share_url, video_item_list, sub_item_list) {
  279. await JadeLog.info(`正在获取播放链接,分享链接为:${share_url}`)
  280. let params = {};
  281. params.share_id = shareId;
  282. let file_id = share_url.split("folder/").slice(-1)[0]
  283. if (file_id.length !== 40) {
  284. file_id = ""
  285. }
  286. let response_str = await post("adrive/v3/share_link/get_share_by_anonymous", params),
  287. response_json = JSON.parse(response_str), item_file_id = getParentFileId(file_id, response_json),
  288. item = new Item(item_file_id);
  289. await listFiles(item, video_item_list, sub_item_list, share_token);
  290. }
  291. async function getVod(video_item_list, sub_item_list, type_name) {
  292. let play_foramt_list = ["原画", "超清", "高清", "标清"], episode_list = [], episode_str_list = [];
  293. for (const video_item of video_item_list) {
  294. episode_list.push(video_item.getDisplayName(type_name) + "$" + video_item.getFileId() + "+" + video_item.shareId + "+" + video_item.shareToken + findSubs(video_item.getName(), sub_item_list));
  295. }
  296. for (let index = 0; index < play_foramt_list.length; index++) {
  297. episode_str_list.push(episode_list.join("#"));
  298. }
  299. return {
  300. vod_play_url: episode_str_list.join("$$$"), vod_play_from: play_foramt_list.map(item => item).join("$$$"),
  301. };
  302. }
  303. async function listFiles(item, video_item_list, sub_item_list, share_token) {
  304. return await listFilesMarker(item, video_item_list, sub_item_list, "", share_token);
  305. }
  306. async function listFilesMarker(item, video_item_list, sub_item_list, netxt_markers, share_token) {
  307. let new_item = {}, file_list = [];
  308. new_item.limit = 200;
  309. new_item.share_id = shareId;
  310. new_item.share_token = share_token
  311. new_item.parent_file_id = item.getFileId();
  312. new_item.order_by = "name";
  313. new_item.order_direction = "ASC";
  314. if (netxt_markers.length > 0) {
  315. new_item.marker = netxt_markers;
  316. }
  317. let items = Item.objectFrom(await shareFunc("adrive/v2/file/list_by_share", new_item), shareToken);
  318. for (const r_item of items.getItems()) {
  319. if (r_item.getType() === "folder") {
  320. file_list.push(r_item);
  321. } else {
  322. if ((r_item.getCategory() === "video" || r_item.getCategory() === "audio")) {
  323. //判断数组中是否有file_id
  324. //
  325. let is_video_file_exists = false
  326. for (const video_item of video_item_list) {
  327. if (r_item.getFileId() === video_item.getFileId()) {
  328. is_video_file_exists = true
  329. await JadeLog.debug('视频分享文件重复,无需添加')
  330. }
  331. }
  332. if (!is_video_file_exists) {
  333. if (r_item.getCategory() === "video" && r_item.size / 1000000 > 10) {
  334. video_item_list.push(r_item.parentFunc(item.getName()));
  335. }
  336. }
  337. } else {
  338. if (Utils.isSub(r_item.getExt())) {
  339. let is_sub_file_exists = false
  340. for (const sub_item of sub_item_list) {
  341. if (r_item.getFileId() === sub_item.getFileId()) {
  342. is_sub_file_exists = true
  343. await JadeLog.debug('字幕分享文件重复,无需添加')
  344. }
  345. }
  346. if (!is_sub_file_exists) {
  347. sub_item_list.push(r_item);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. items.getNextMarker().length > 0 && (await listFilesMarker(item, video_item_list, sub_item_list, items.getNextMarker()));
  354. for (const file of file_list) {
  355. await listFiles(file, video_item_list, sub_item_list);
  356. }
  357. }
  358. function getParentFileId(file_id, items) {
  359. let file_infos = items.file_infos;
  360. if (!_.isEmpty(file_id)) {
  361. return file_id;
  362. }
  363. if (file_infos.length === 0) {
  364. return "";
  365. }
  366. let item = file_infos[0];
  367. if (item.type === "folder") {
  368. return item.file_id;
  369. }
  370. if (item.type === "file" && item.category === "video") {
  371. return "root";
  372. }
  373. return "";
  374. }
  375. //字幕匹配
  376. function pair(name, item_list, sub_item_list) {
  377. for (const item of item_list) {
  378. const sub_name = Utils.removeExt(item.getName()).toLowerCase();
  379. if (name.indexOf(sub_name) > -1 || sub_name.indexOf(name) > -1) {
  380. sub_item_list.push(item);
  381. }
  382. }
  383. }
  384. //找出所有字幕
  385. function findSubs(name, item_list) {
  386. let sub_item_list = [];
  387. pair(Utils.removeExt(name).toLowerCase(), item_list, sub_item_list);
  388. if (sub_item_list.length === 0) {
  389. for (const item of item_list) {
  390. sub_item_list.push(item);
  391. }
  392. }
  393. let sub_str = "";
  394. for (const item of sub_item_list) {
  395. sub_str += "+" + Utils.removeExt(item.getName()) + "@@@" + item.getExt() + "@@@" + item.getFileId();
  396. }
  397. return sub_str;
  398. }
  399. async function getSubs(sub_list, share_id) {
  400. let sub_url_list = [];
  401. for (const sub_str of sub_list) {
  402. if (!(sub_str.indexOf("@@@") > -1)) {
  403. continue;
  404. }
  405. let sub_split_list = sub_str.split("@@@"), sub_name = sub_split_list[0], sub_ext = sub_split_list[1],
  406. sub_file_id = sub_split_list[2], sub_url = await getDownloadUrl(sub_file_id, share_id);
  407. sub_url_list.push(Sub.create().setName(sub_name).setExt(sub_ext).setUrl(sub_url));
  408. }
  409. return sub_url_list;
  410. }
  411. async function getDriveInfo() {
  412. if (!_.isEmpty(driveInfo) && !_.isEmpty(driveInfo.default_drive_id)) {
  413. return driveInfo;
  414. }
  415. let _0x3740f3 = await oauthFunc("user/getDriveInfo", {}, true), _0x56fde5 = JSON.parse(_0x3740f3);
  416. driveInfo = {
  417. default_drive_id: _0x56fde5.default_drive_id,
  418. resource_drive_id: _0x56fde5.resource_drive_id,
  419. backup_drive_id: _0x56fde5.backup_drive_id
  420. };
  421. return driveInfo;
  422. }
  423. async function getDriveId() {
  424. if (_.isEmpty(user.getDriveId())) {
  425. let drive = await getDriveInfo();
  426. return drive.resource_drive_id;
  427. }
  428. return user.getDriveId();
  429. }
  430. async function getDownloadUrl(file_id, share_id, share_token) {
  431. let drive_id = await getDriveId();
  432. tempIds.unshift(await copy(file_id, share_id, share_token));
  433. let params = {};
  434. params.file_id = tempIds[0];
  435. params.drive_id = drive_id;
  436. if (tempIds[0] !== null) {
  437. let response_str = await oauthFunc("openFile/getDownloadUrl", params, true);
  438. if (response_str === "retry") {
  439. await JadeLog.info("尝试重新获取下载链接");
  440. return await getDownloadUrl(file_id, share_id)
  441. } else {
  442. await JadeLog.info("获取下载链接成功:返回结果为:" + response_str + "请求参数为:" + JSON.stringify(params));
  443. return JSON.parse(response_str).url;
  444. }
  445. } else {
  446. await JadeLog.error("获取下载链接失败:失败原因:请检查转存文件失败原因")
  447. return null;
  448. }
  449. }
  450. async function getVideoPreviewPlayInfo(file_id, share_id, shareToken) {
  451. let drive_id = await getDriveId();
  452. tempIds.unshift(await copy(file_id, share_id, shareToken));
  453. let params = {};
  454. params.file_id = tempIds[0];
  455. params.drive_id = drive_id;
  456. params.category = "live_transcoding";
  457. params.url_expire_sec = "14400";
  458. let response_str = await oauthFunc("openFile/getVideoPreviewPlayInfo", params, true);
  459. return JSON.parse(response_str).video_preview_play_info;
  460. }
  461. async function playerContent(file_id, share_id, share_token) {
  462. try {
  463. await JadeLog.info("正在获取原画的播放地址和字幕下载链接", true)
  464. let download_url = await getDownloadUrl(file_id, share_id, share_token);
  465. // let sub_list = await getSubs(file_id_list,share_id);
  466. await JadeLog.info("获取原画的播放地址和字幕下载链接成功", true)
  467. await JadeLog.info(`下载地址为:${download_url}`)
  468. return JSON.stringify({
  469. parse: 0, url: download_url, header: getHeader(), format: "application/octet-stream", subs: []
  470. });
  471. } catch (e) {
  472. await JadeLog.error("获取原画的播放地址和字幕下载链接失败:失败原因为:" + e);
  473. }
  474. }
  475. // 转码头的Url和字幕
  476. async function playerContentByFlag(file_id, flag, share_id, shareToken) {
  477. try {
  478. await JadeLog.info("正在获取转码后的播放地址和字幕下载链接", true)
  479. let video_preview_play_info = await getVideoPreviewPlayInfo(file_id, share_id, shareToken),
  480. video_preview_url = getPreviewUrl(video_preview_play_info, flag);
  481. // let sub_list = await getSubs(file_id_list,share_id),
  482. // sub_p_list = getSubsByPlayInfo(video_preview_play_info);
  483. // for (const sub_p of sub_p_list) {
  484. // sub_list.push(sub_p);
  485. // }
  486. await JadeLog.info("获取转码后的播放地址和字幕下载链接成功", true)
  487. await JadeLog.info(`下载地址为:${video_preview_url}`)
  488. return JSON.stringify({
  489. parse: 0, url: video_preview_url, header: getHeader(), format: "application/x-mpegURL", subs: []
  490. });
  491. } catch (e) {
  492. await JadeLog.error(`获取转码后的播放地址和字幕下载链接失败,失败原因为:${e}`)
  493. }
  494. }
  495. function getPreviewUrl(video_preview_play_info, flag) {
  496. if (!video_preview_play_info.hasOwnProperty("live_transcoding_task_list")) {
  497. return "";
  498. }
  499. let live_transcoding_task_list = video_preview_play_info.live_transcoding_task_list;
  500. for (let index = 0; index < live_transcoding_task_list.length; ++index) {
  501. let live_transcoding_task = live_transcoding_task_list[index];
  502. if (live_transcoding_task.template_id === quality[flag]) {
  503. return live_transcoding_task.url;
  504. }
  505. }
  506. return live_transcoding_task_list[0].url;
  507. }
  508. function getSubsByPlayInfo(video_preview_play_info) {
  509. if (!video_preview_play_info.hasOwnProperty("live_transcoding_subtitle_task_list")) {
  510. return [];
  511. }
  512. let live_transcoding_subtitle_task_list = video_preview_play_info.live_transcoding_subtitle_task_list,
  513. sub_p_list = [];
  514. for (let index = 0; index < live_transcoding_subtitle_task_list.length; ++index) {
  515. let live_transcoding_subtitle_task = live_transcoding_subtitle_task_list[index],
  516. language = live_transcoding_subtitle_task.language, url = live_transcoding_subtitle_task.url;
  517. sub_p_list.push(Sub.create().setUrl(url).setName(language).setLang(language).setExt("vtt"));
  518. }
  519. return sub_p_list;
  520. }
  521. async function copy(file_id, shareId, shareToken) {
  522. let copy_file_id
  523. let cache_dic = {}
  524. try {
  525. cache_dic = JSON.parse(await local.get("file", "file_id"))
  526. } catch (e) {
  527. }
  528. copy_file_id = cache_dic[file_id]
  529. if (typeof (copy_file_id) == "string") {
  530. await JadeLog.info(`file id为:${file_id},已经缓存过,copy file id为:${copy_file_id}`)
  531. } else {
  532. let params_str = "{\"requests\":[{\"body\":{\"file_id\":\"{{data.fileId}}\",\"share_id\":\"{{data.shareId}}\",\"auto_rename\":true,\"to_parent_file_id\":\"{{data.tmpFolderFileId}}\",\"to_drive_id\":\"{{data.driveId}}\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"0\",\"method\":\"POST\",\"url\":\"/file/copy\"}],\"resource\":\"file\"}",
  533. drive_id = await getDriveId(), params = {
  534. fileId: file_id, shareId: shareId, driveId: drive_id, tmpFolderFileId: curTmpFolderFileId
  535. };
  536. params_str = jinja2(params_str, {
  537. data: params
  538. });
  539. await JadeLog.debug(`正在转存文件,文件id为:${file_id}`, true)
  540. let response_str = await auth("adrive/v2/batch", JSON.parse(params_str), shareToken, true);
  541. let response = aliExpection(response_str)
  542. if (response.code === 500 || response.code === 501 || response.code === 502 || response.code === 503 || response.code === 403) {
  543. if (response.code === 500) {
  544. await JadeLog.error("转存文件失败,失败详情:" + response.content)
  545. return copy(file_id);
  546. } else if (response.code === 501) {
  547. await JadeLog.error("转存文件失败,失败详情:" + response.content)
  548. return copy(file_id)
  549. } else if (response.code === 502) {
  550. await JadeLog.error("转存文件失败,失败原因为:转存文件夹不存在,失败详情:" + response.content)
  551. return null;
  552. } else if (response.code === 503) {
  553. await JadeLog.error("转存文件失败,失败原因为:转存文件夹大小被限制" + response.content)
  554. await clearFile()
  555. return copy(file_id)
  556. } else if (response.code === 403) {
  557. await JadeLog.error("转存文件失败,失败原因为:没有找到File Id,失败详情:" + response.content)
  558. return null;
  559. }
  560. }
  561. await JadeLog.debug(`转存文件成功,文件id为:${file_id},请求结果为:${response_str}`)
  562. copy_file_id = JSON.parse(response_str).responses[0].body.file_id;
  563. let file_dic = {}
  564. try {
  565. JSON.parse(await local.get("file", "file_id"))
  566. } catch (e) {
  567. }
  568. file_dic[file_id] = copy_file_id
  569. await local.set("file", "file_id", JSON.stringify(file_dic))
  570. }
  571. return copy_file_id;
  572. }
  573. async function deleteTmpFolderAndRecreate() {
  574. // 删除缓存文件夹
  575. let file_id = await tmpFolderExistsFunc();
  576. file_id && (await trashFile(file_id), await recyclebinClear());
  577. await getTempFileId();
  578. }
  579. //放入回车站
  580. async function trashFile(file_id) {
  581. let params_str = "{\"requests\":[{\"body\":{\"file_id\":\"{{data.fileId}}\",\"drive_id\":\"{{data.driveId}}\"},\"headers\":{\"Content-Type\":\"application/json\"},\"id\":\"0\",\"method\":\"POST\",\"url\":\"/recyclebin/trash\"}],\"resource\":\"file\"}",
  582. drive_id = await getDriveId(), params = {
  583. fileId: file_id, driveId: drive_id
  584. };
  585. params_str = jinja2(params_str, {
  586. data: params
  587. });
  588. await JadeLog.debug(`正在准备删除文件,文件id为:${file_id}`, true)
  589. let response = await auth("v2/batch", JSON.parse(params_str), shareToken, true);
  590. await JadeLog.debug(`删除文件成功,文件id为:${file_id},请求结果为:${response}`)
  591. return true;
  592. }
  593. //清空回车站
  594. async function recyclebinClear() {
  595. let drive_id = await getDriveId(), params = {
  596. drive_id: drive_id
  597. };
  598. await auth("v2/recyclebin/clear", params, shareToken, true);
  599. await JadeLog.info("清空回车站成功", true)
  600. return true;
  601. }
  602. async function createTmpFolder() {
  603. //创建文件夹
  604. let file_id = await tmpFolderExistsFunc();
  605. if (file_id) {
  606. await JadeLog.info("文件夹存在,无需重新创建")
  607. return file_id;
  608. }
  609. await JadeLog.debug("文件夹不存在,重新创建文件夹")
  610. let drive_id = await getDriveId(), params = {
  611. check_name_mode: "refuse", drive_id: drive_id, name: tmpFolderName, parent_file_id: "root", type: "folder"
  612. }, response_str = await oauthFunc("openFile/create", params, true);
  613. let response_json = JSON.parse(response_str);
  614. if (_.isEmpty(response_json.drive_id)) {
  615. await JadeLog.error(`创建文件夹失败,失败原因为:${response_str}`)
  616. return null;
  617. }
  618. await JadeLog.info(`创建文件夹成功`, true)
  619. return response_json.file_id;
  620. }
  621. async function tmpFolderExistsFunc() {
  622. let drive_id = await getDriveId(), params = {
  623. drive_id: drive_id, parent_file_id: "root", limit: 100, order_by: "updated_at", order_direction: "DESC"
  624. }, response_str = await oauthFunc("openFile/list", params, true);
  625. let response_json = JSON.parse(response_str);
  626. if (_.isEmpty(response_json.items)) {
  627. return false;
  628. }
  629. for (const item of response_json.items) {
  630. if (item.name === tmpFolderName) {
  631. return item.file_id;
  632. }
  633. }
  634. return false;
  635. }
  636. async function setToken(token) {
  637. // Token设置
  638. user.setRefreshToken(token);
  639. await refreshAccessToken(token);
  640. await refreshOpenToken();
  641. }
  642. export {
  643. initSome, setToken, clearFile, setShareId, getFileByShare, getVod, playerContent, playerContentByFlag, getTempFileId
  644. };