Greasy Fork

Greasy Fork is available in English.

阿里云盘助手

支持生成文件下载链接,支持第三方播放器DPlayer(突破视频2分钟限制,选集,上下集)

当前为 2023-02-02 提交的版本,查看 最新版本

// ==UserScript==
// @name         阿里云盘助手
// @namespace    http://tampermonkey.net/
// @version      1.0.5
// @description  支持生成文件下载链接,支持第三方播放器DPlayer(突破视频2分钟限制,选集,上下集)
// @author       罗根大人
// @match        https://www.aliyundrive.com/*
// @connect      *
// @icon        https://img.alicdn.com/imgextra/i1/O1CN01JDQCi21Dc8EfbRwvF_!!6000000000236-73-tps-64-64.ico
// @require      https://cdn.bootcdn.net/ajax/libs/localforage/1.10.0/localforage.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/dplayer/1.27.0/DPlayer.min.js
// @require     https://cdn.bootcdn.net/ajax/libs/hls.js/1.3.0/hls.min.js
// @run-at       document-body
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @license MIT
// ==/UserScript==
(function() {
    'use strict'
    var showAria2SetHtml = '<div class="ant-modal-root"id="aria2-set-box"><div class="ant-modal-mask"></div><div tabindex="-1"class="ant-modal-wrap"role="dialog"><div role="document"class="ant-modal modal-wrapper--2yJKO"style="width: 340px;transform-origin: -14px 195px;"><div class="ant-modal-content"><div class="ant-modal-header"><div class="ant-modal-title">Aria2设置</div></div><div class="ant-modal-body"><div class="icon-wrapper--3dbbo"id="aria2-set-icon"><span data-role="icon"data-render-as="svg"data-icon-type="PDSClose"class="close-icon--33bP0 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSClose"></use></svg></span></div><div>推送链接:</div><div class="content-wrapper--1_WJv"><input id="aria2-link"class="ant-input ant-input-borderless input--3oFR6"type="text"></div><div>推送路径:</div><div class="content-wrapper--1_WJv"><input id="aria2-path"class="ant-input ant-input-borderless input--3oFR6"type="text"></div><div>RPC密钥:</div><div class="content-wrapper--1_WJv"><input id="aria2-token"class="ant-input ant-input-borderless input--3oFR6"type="text"></div></div><div class="ant-modal-footer"><div class="footer--3Q0je"><button id="aria2-set-save"class="button--2Aa4u primary--3AJe5 small---B8mi">确定</button></div></div></div></div></div></div>';

    let dp = {
        dPlayerNode: null,
        player: null,
        // 当前页信息
        page: {
            id: null,
            order: null,
            order_by: null,
            item: []
        },
        videoPage: {
            id: '',
            video: {},
            player: null
        }
    }

    let transcoding = {
        UHD: '4K 超清',
        QHD: '2K 超清',
        FHD: '1080 全高清',
        HD: '720 高清',
        SD: '540 标清',
        LD: '360 流畅'
    }

    class XXPlayer {

        onload = async function (video, size) {
            URL.revokeObjectURL(video.src);

            var FILE = video.src;
            var filesize = 0;
            var filetype = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
            var fileduration = 0
            var chunksize = 262144
            var totalSegments = 0
            var video = document.querySelector('video');
            // 视频块
            var currentChunk = 0
            // 提前缓存秒
            var maxBufferLength = 120
            // tt 已缓存多少秒
            var tt, sourceBuffer ,seeking=0,skip=false


            var mediaSource = new MediaSource();
            video.src = window.URL.createObjectURL(mediaSource);
            video.addEventListener('loadedmetadata', function(a) {
                console.log(a)
                fileduration = a.target.duration
            })

            /* video.addEventListener('seeking', function(e) {
                 var ranges = sourceBuffer.buffered;
                 let max = 0;
                 for (var i = 0, len = ranges.length; i < len; i += 1) {
                     max = Math.max(max, ranges.end(i))
                 }
                 currentChunk = Math.floor( video.currentTime / ( max / currentChunk) + currentChunk)
                 if (mediaSource.readyState === 'open') {
                     sourceBuffer.abort();
                     skip=true
                     callback()
                     console.log(mediaSource.readyState);
                 } else {
                     console.log('seek but not open?');
                     console.log(mediaSource.readyState);
                 }
                 // seeking = video.currentTime
             })*/

            function  getCurrentTime(){
                return  video.currentTime - seeking;

            }




            function callback(e) {
                if (!sourceBuffer)
                    sourceBuffer = mediaSource.addSourceBuffer(filetype);


                var d = false,
                    count = 0;
                (function readChunk_() {

                    GET(FILE, function(uInt8Array) {
                        var file = new Blob([uInt8Array], {
                            type: filetype
                        });

                        var reader = new FileReader();

                        reader.onload = function(e) {

                            if (count++ === 0 || skip) {
                                skip=false
                                sourceBuffer.addEventListener('updateend', function(_) {

                                    var ranges = sourceBuffer.buffered;
                                    console.log("CURRENT TIME: " + video.currentTime);
                                    console.log("BUFFERED RANGES: " + ranges.length);
                                    tt = 0
                                    for (var i = 0, len = ranges.length; i < len; i += 1) {
                                        console.log("RANGE: " + ranges.start(i) + " - " + ranges.end(i));
                                        tt = Math.max(tt, ranges.end(i))
                                    }
                                    tt = tt - getCurrentTime()

                                    if (file.size !== chunksize) {
                                        alert("我进来了")
                                        mediaSource.endOfStream();
                                    } else {
                                        // if (video.paused) {
                                        //     video.play();
                                        // }

                                        if (tt > maxBufferLength) {
                                            var __ = setInterval(function() {
                                                var ranges = sourceBuffer.buffered;

                                                tt = 0
                                                for (var i = 0, len = ranges.length; i < len; i += 1) {
                                                    tt = Math.max(tt, ranges.end(i))
                                                }
                                                tt = tt - getCurrentTime()

                                                if (tt <= maxBufferLength) {
                                                    clearInterval(__)
                                                    readChunk_();
                                                }
                                            }, 500)
                                        } else
                                            readChunk_();
                                    }
                                });
                            }

                            let a = new Uint8Array(e.target.result);
                            if (count === 1){
                                a[3]=a[3] -1;
                            }
                            sourceBuffer.appendBuffer(a);
                        };
                        reader.readAsArrayBuffer(file);
                    })

                })()
            }


            mediaSource.addEventListener('sourceopen', callback, false);
            mediaSource.addEventListener('webkitsourceopen', callback, false);


            function GET(url, callback) {

                if (filesize && (currentChunk-1) * chunksize > filesize){
                    mediaSource.endOfStream()
                    return
                }
                let start = (currentChunk) * chunksize
                let end  = (currentChunk + 1) * chunksize - 1
                if (start > filesize){
                    start = (currentChunk-1) * chunksize
                }
                if (end > filesize && filesize!==0){
                    end = filesize
                }


                var xhr = new XMLHttpRequest();
                xhr.open('GET', url, true);
                xhr.responseType = 'arraybuffer';

                xhr.setRequestHeader('Range', 'bytes=' + start + '-' + (end));
                currentChunk++
                xhr.send();

                xhr.onload = function(e) {

                    if (xhr.status != 200 && xhr.status != 206) {
                        alert("Unexpected status code " + xhr.status + " for " + url);
                        return false;
                    }
                    filesize = parseInt(size)
                    totalSegments = Math.ceil(filesize / chunksize) - 1

                    callback(new Uint8Array(xhr.response));
                };
            }



        }




    }

//   创建播放器
    dp.createDPlayer = function () {
        let jquery = getJquery()
        let videoNode = jquery('video')
        if (videoNode.length <= 0) {
            return false
        }

        if (!dp.dPlayerNode || jquery('#dplayer').length === 0) {
            dp.dPlayerNode = jquery('<div id=\'dplayer\' style=\'width: 100%; height: 100%;\'></div>')[0]
            videoNode[0].parentNode.parentNode.replaceWith(dp.dPlayerNode)
        }
        let video = dp.videoPage.video
        //视频信息
        let play_info = video.video_preview_play_info
        //清晰度
        let task_list = play_info.live_transcoding_task_list
        dp.videoPage.id = video.file_id
        let quality = [], defaultQuality = task_list.length - 1, locQuality = getItem("quality")

        task_list.forEach(function (item, index) {
            let name = transcoding[item.template_id]
            if (!name) {
                return
            }
            if (locQuality === item.template_id) {
                defaultQuality = index;
            }
            quality.push({
                templateId: item.template_id,
                name: name,
                url: item.url || item.preview_url,
                type: 'hls'
            })
        })

        if (defaultQuality < 0) {
            defaultQuality = 0
        }

        let options = {
            container: dp.dPlayerNode,
            video: {
                quality: quality,
                defaultQuality: defaultQuality,
                customType: {
                    hls: function (video, player) {
                        const hls = new Hls()
                        hls.loadSource(video.src)
                        hls.attachMedia(video)
                    }
                }
            },
            autoplay: true,
            screenshot: true,
            hotkey: false,
            airplay: true,
            volume: 1.0,
            contextmenu: []
        }

        if (video.xxType) {
            options.video = {
                type: 'customXX',
                url: video.url,
                customType: {
                    customXX: function (video, player) {
                        let xxPlayer = new XXPlayer();
                        xxPlayer.onload(video, dp.videoPage.video.size)
                    },
                },
            }
        }

        try {

            let player = dp.videoPage.player = new DPlayer(options)

            if (video.xxType) {
                return  true
            }
            player.on("quality_end", function () {
                setItem("quality", player.quality.templateId);
            });

            player.on('error',function (e) {
                console.log(e)
            })

            getJquery()(".header-left--3QcN-").on('click', function () {
                dp.saveVideoLookTime();
            })

            dp.selectEpisode()
            dp.getVideoLookTime()

        } catch (error) {
            console.error('播放器创建失败', error)
        }
        return true
    }

//获取上次观看时长
    dp.getVideoLookTime = function () {
        let id = dp.videoPage.id;
        if (id) {
            getVideoFile(function (response) {
                if (response && response.user_meta) {
                    let player = dp.videoPage.player
                    let userMeta = JSON.parse(response.user_meta)
                    player.seek(userMeta.play_cursor);
                    player.play();
                }

            })
        }

    }

// 更新保存的时长
    dp.saveVideoLookTime = function () {
        if (dp.videoPage.id) {
            updateVideoTime(function () {
                console.log("保存成功")
            });
        }
    }


//   选集
    dp.selectEpisode = function () {
        let jq = getJquery()
        if (jq('.dplayer-icons-right #btn-select-episode').length) return
        // if (document.querySelectorAll('.dplayer-menu-item').length < 4) return

        let fileList = dp.page.item
            , videoList = fileList.filter(function (item, index) {
            return item.category === 'video'
        })
            , fileIndex = videoList.findIndex(function (item, index) {
            return item.file_id === dp.videoPage.id
        })
        if (!(fileIndex > -1 && videoList.length > 1)) return

        var elevideo = '<section class="scroll-container--Ho4ra""><div class="scroll-wrapper--zw1q2"><ul class="drawer-list--JYzyI">'
        videoList.forEach(function (item, index) {
            let t;
            let created = item.created_at.split("T")[0];
            if (fileIndex === index) {
                t = getTime(dp.videoPage.video.video_preview_play_info.meta.duration);
                elevideo += `<li class="drawer-item--2cNtQ "data-is-current="true"><div class="thumbnail--1bhNX"style="background-image: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 100%), url(&quot;${item.thumbnail}&quot;);"></div><div class="meta--3-qtu"><p class="title--2vewu"title="${item.name}"><span data-role="icon"data-render-as="svg"data-icon-type="PDSPlayCircle"class="icon--2AFV7 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSPlayCircle"></use></svg></span><span class="filename--3hcxw">${item.name}</span></p><p class="duration--3hbgi">${t}</p><p class="time--2_PJ8">${created}</p></div></li>`
            } else {
                let d = item.video_media_metadata.duration;
                if (d) {
                    t = getTime(d);
                } else {
                    t = '时长无法获取'
                }
                elevideo += `<li class="drawer-item--2cNtQ "data-is-current="false"><div class="thumbnail--1bhNX"style="background-image: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 100%), url(&quot;${item.thumbnail}&quot;);"></div><div class="meta--3-qtu"><p class="title--2vewu"title="${item.name}"><span class="filename--3hcxw">${item.name}</span></p><p class="duration--3hbgi">${t}</p><p class="time--2_PJ8">${created}</p></div></li>`
            }
        })

        elevideo += '</ul></div></section>';
        let svg = '<svg t="1674881901474" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8038" width="200" height="200"><path d="M765.952 124.928l0 81.92 0 129.024 0 156.672 0 159.744q0 76.8 0.512 141.312t0.512 100.352q0 24.576-11.776 40.96t-29.696 22.016-39.424 0-39.936-24.064q-37.888-38.912-81.92-81.408t-90.624-85.504-94.208-86.016-91.648-82.944q-19.456-17.408-29.184-43.008t-8.704-53.248 11.776-54.272 32.256-45.056q39.936-34.816 79.36-70.144t80.896-72.704 87.04-78.336 96.768-87.04q22.528-20.48 45.568-27.136t41.472-2.048 29.696 20.48 11.264 40.448z" p-id="8039"></path></svg>'
        let disable = '<svg t="1674882113958" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14669" width="200" height="200"><path d="M512.631648 1023.999376a511.992507 511.992507 0 1 1 511.368127-511.368127 511.992507 511.992507 0 0 1-511.368127 511.368127zM512.631648 63.076853a449.554397 449.554397 0 1 0 448.930016 449.554396A450.178778 450.178778 0 0 0 512.631648 63.076853z" fill="#0F3567" p-id="14670"></path><path d="M138.877118 830.19148L818.328638 150.677522l44.143744 44.143744L183.020862 874.335224z" fill="#0F3567" p-id="14671"></path></svg>';
        let html = '';
        if (videoList[0] !== videoList[fileIndex]) {
            html += `<button class="dplayer-icon dplayer-play-icon prev-icon" title="${videoList[fileIndex - 1].name}">` + svg + '</button>'
        } else {
            html += '<button class="dplayer-icon dplayer-play-icon prev-icon"  title="没上集了">' + disable + '</button>'
        }
        html += '<button id="btn-select-episode" class="dplayer-icon dplayer-quality-icon" title="选集">选集</button> <div class="playlist-content" style="max-height: 330px;width: 100%;height: auto;box-sizing: border-box;overflow: hidden;position: absolute;left: 0;transition: all .38s ease-in-out;bottom: 52px;overflow-y: auto;transform: scale(0);z-index: 2;"><div class="list" style="background-color: rgba(0, 0, 0, 0.85);height: 100%;">' + elevideo + '</div></div>'
        if (videoList[videoList.length - 1] !== videoList[fileIndex]) {
            html += `<button class="dplayer-icon dplayer-play-icon next-icon" style="transform: rotate(-180deg)"  title="${videoList[fileIndex + 1].name}">` + svg + '</button>'
        } else {
            html += '<button class="dplayer-icon dplayer-play-icon next-icon"  title="没下集了">' + disable + '</button>'
        }

        jq('.dplayer-icons-right').prepend(html)

        jq('#btn-select-episode').on('click', function () {
            var eleEpisode = jq('.playlist-content')
            if (eleEpisode.css('transform').match(/\d+/) > 0) {
                eleEpisode.css('transform', 'scale(0)')
            } else {
                eleEpisode.css('transform', 'scale(1)')
                jq('.dplayer-mask').addClass('dplayer-mask-show')

                jq('.dplayer-icons-right .playlist-content').scrollTop((fileIndex + 1)
                    * jq('.dplayer-icons-right li')[0].offsetHeight - jq('.dplayer-icons-right .playlist-content').height() / 2)
            }
        })

        jq('.dplayer-mask').on('click', function () {
            var eleEpisode = jq('.playlist-content')
            if (eleEpisode.css('transform').match(/\d+/) > 0) {
                eleEpisode.css('transform', 'scale(0)')
                jq(this).removeClass('dplayer-mask-show')
            }
        })

        jq('.playlist-content li').on('click', function () {
            var $this = jq(this)
            if ($this.attr('data-is-current') === 'true') {
                return
            }
            jq('.dplayer-mask').removeClass('dplayer-mask-show')
            let file = videoList[$this.index()]
            dp.playByFile(file)
        })


        jq('.prev-icon').on('click', function () {
            var file = videoList[fileIndex - 1]
            file ? dp.playByFile(file) : showError('没有上一集了')
        })
        jq('.next-icon').on('click', function () {
            var file = videoList[fileIndex + 1]
            file ? dp.playByFile(file) : showError('没有下一集了')
        })
    }

//   通过视频文件来播放该视频
    dp.playByFile = function (file) {
        dp.saveVideoLookTime();
        let player = dp.videoPage.player
        try {
            player.pause()
            document.removeEventListener('click', player.docClickFun, true)
            player.container.removeEventListener('click', player.containerClickFun, true)
            player.fullScreen && player.fullScreen.destroy && player.fullScreen.destroy()
            player.hotkey && player.hotkey.destroy && player.hotkey.destroy()
            player.contextmenu && player.contextmenu.destroy && player.contextmenu.destroy()
            player.controller && player.controller.destroy && player.controller.destroy()
            player.timer && player.timer.destroy && player.timer.destroy()
        } catch (error) {
            console.error(error)
        }
        dp.videoPage.id = file.file_id

        dp.getVideoPreviewPlayInfo(function (response) {
            dp.playInfo({
                response: response
            });
            getJquery()('.header-file-name--CN_fq, .text--2KGvI').text(file.name)
        })
    }


    dp.getVideoPreviewPlayInfo = function (callback) {
        refresh_token(function (result) {
            if (result) {
                if (location.href.indexOf('aliyundrive.com/drive') > 0) {
                    videoPreviewPlayInfo(callback)
                } else {
                    share_token(function (result) {
                        if (result) {
                            shareLinkVideoPlayInfo(callback)
                        } else {
                            callback && callback('')
                        }
                    })
                }
            } else {
                callback && callback('')
            }
        })
    }

    dp.playerReady = function (callback) {
        let player = dp.videoPage.player
        if (player.video.duration > 0 || player.video.readyState > 2) {
            player.isReady = true
            callback && callback()
        } else if (player.isReady) {
            callback && callback()
        } else {
            player.video.ondurationchange = function () {
                player.video.ondurationchange = null
                player.isReady = true
                callback && callback()
            }
        }
    }

// 播放器
    dp.playInfo = function (res) {
        let list = res.response.video_preview_play_info.live_transcoding_task_list
        dp.videoPage.id = res.response.file_id
        if (list[0].hasOwnProperty("preview_url")) {

            dp.getVideoPreviewPlayInfo(function (response) {
                if (response === '') {
                    showError("播放信息获取失败,请刷新重试", 10000);
                    return;
                }
                dp.videoPage.video = response;
                initPre()
            })

        } else {
            dp.videoPage.video = res.response;
            initPre()
        }

        // dp.videoPage.video
        // initPre()
        // console.log(res)
    }

    dp.fileGet = function (response) {
        console.log(response)
    }

    dp.playPrivacyVideo = function (response) {
        let fileId = response.file_id;
        let fileIndex = dp.page.item.findIndex(function (item, index) {
            return item.file_id === fileId
        })
        let item = dp.page.item[fileIndex];
        getDownloadUrl(item.file_id, item.drive_id, function (download_url, resp) {
            console.log(download_url)
            dp.videoPage.video = {
                file_id: fileId,
                video_preview_play_info: {
                    live_transcoding_task_list: []
                },
                xxType: true,
                size: resp.size,
                url: download_url
            }
            initPre()
        })


    }

//当文件较多时,需要合并
    dp.fileList = function (res) {
        let data = res.data
        let response = res.response

        // 数据量过大,进行数组合并
        if (dp.page.id === data.parent_file_id && dp.page.order === data.order_direction && dp.page.order_by === data.order_by) {
            dp.page.item = dp.page.item.concat(response.items)
        } else {
            dp.page.id = data.parent_file_id
            dp.page.order = data.order_direction
            dp.page.order_by = data.order_by
            dp.page.item = response.items
        }
        showSuccess(`已加载${dp.page.item.length}个文件`)

        if (dp.isHome()) {
            dp.initMenuButton()
        } else {
            dp.initShareButton()
        }

    }

    dp.getPlayNode = function (e) {
        let fileList = dp.page.item
            , parent_file_id = fileList[0].parent_file_id
            , videoMemory = getItem('video_memory')
        if (videoMemory && videoMemory[parent_file_id]) {
            return videoMemory[parent_file_id][e]
        }
        return ''
    }
    dp.isHome = function () {
        return location.href.indexOf('com/drive') > 0
    }

    dp.isExpires = function (item) {
        let time = Date.parse(item.expire_time) - Date.now()
        return time > 0 && time < 1000 * Number(item.expires_in)
    }

    dp.setExpires = function (item, time) {
        item.expire_time = new Date(Date.now() + time).toISOString()
        item.expires_in = void 0 === time ? 600 : time
        return item
    }

    dp.showBox = function (fileList) {
        if (!fileList) {
            fileList = dp.selectedFileList()
            if (fileList.length === 0) {
                return
            }
        }
        let rowStyle = 'margin:10px 0px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;'
        let html = '<div class="ant-modal-root ant-modal-Link"><div class="ant-modal-mask"></div><div tabindex="-1" class="ant-modal-wrap" role="dialog"><div role="document" class="ant-modal modal-wrapper--2yJKO" style="width: 666px;"><div class="ant-modal-content"><div class="ant-modal-header"><div class="ant-modal-title" id="rcDialogTitle1">文件下载</div></div><div class="ant-modal-body"><div class="icon-wrapper--3dbbo"><span data-role="icon" data-render-as="svg" data-icon-type="PDSClose" class="close-icon--33bP0 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSClose"></use></svg></span></div>'
        html += '<p> 共加载了 ' + fileList.length + '个文件</p>'
        html += '<div class="item-list" style="padding: 20px; height: 410px; overflow-y: auto;">'
        fileList.forEach(function (item, index) {
            html += '<p>' + (++index) + ':' + item.name + '</p>'
            if (item.type === 'file') {
                html += '<p style="' + rowStyle + '"><a title="' + item.download_url + '" href="' + item.download_url + '" style="color: blue;">' + item.download_url + '</a></p>'
            } else if (item.type === 'folder') {
                html += '<p style="' + rowStyle + '"><font color="green">&emsp;&emsp;请进入文件夹下载</font></p>'
            }
        })
        html += '</div></div><div class="ant-modal-footer"><div class="footer--1r-ur"><div class="buttons--nBPeo">'
        html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi appreciation">👍 点个赞</button>'
        html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi aria2-download">Aria2 推送</button>';
        html += '<button class="button--2Aa4u primary--3AJe5 aria2-set" style="margin-left: 0;width: auto;border: 0 solid transparent;">⚙️</button>';
        html += '</div></div></div></div></div></div></div>'
        getJquery()('body').append(html)
        getJquery()('.ant-modal-Link .icon-wrapper--3dbbo').one('click', function () {
            getJquery()('.ant-modal-Link').remove()
        })
        getJquery()('.ant-modal-Link .ant-modal-wrap').on('click', function (event) {
            if (getJquery()(event.target).closest('.ant-modal-content').length === 0) {
                getJquery()('.ant-modal-Link').remove()
            }
        })
        getJquery()('.ant-modal-Link .appreciation').on('click', function () {
            window.open('http://greasyfork.icu/zh-CN/scripts/458626', '_blank')
        })

        getJquery()('.ant-modal-Link .aria2-set').on('click', function () {

            dp.showAria2Set();
        })
        getJquery()('.ant-modal-Link .aria2-download').on('click', function () {
            let fileAria2List = fileList.filter(function (item) {
                return item.type === "file";
            });
            if (fileAria2List.length === 0) {
                showError('当前未检索到文件(非文件夹)')
                return
            }
            dp.aria2Push(getJquery()(this), fileAria2List);
        })

    }

    dp.aria2Push = function (btn, fileAria2List) {
        let $ = getJquery();
        let link = getItem("aria2-link");
        let path = getItem("aria2-path");
        let token = getItem("aria2-token") || "";
        if (!link || !path) {
            showError('请点击右边齿轮按钮,设置好Aria2再来推送吧')
            return;
        }
        let dir = $(".breadcrumb--2FqFQ[data-calc=true] > .breadcrumb-item--tV9dn > .breadcrumb-item-link--M-p4b");
        let folderName = "\/阿里云盘";
        for (let i = 0; i < dir.length; i++) {
            folderName += "\/" + dir[i].innerText
        }

        let sendDownLoad = [];

        fileAria2List.forEach(function (item, index) {
            sendDownLoad.push({
                id: "",
                jsonrpc: "2.0",
                method: "aria2.addUri",
                params: [
                    "token:" + token,
                    [item.download_url],
                    {
                        out: item.name,
                        dir: path + folderName,
                        referer: "https://www.aliyundrive.com/",
                        "user-agent": navigator.userAgent
                    }
                ]
            });
        });
        let text = btn.text();
        btn.text("正在推送");

        $.ajax({
            type: "POST",
            url: link,
            data: JSON.stringify(sendDownLoad),
            crossDomain: true,
            processData: false,
            contentType: "application/json",
            success: function (result) {
                showSuccess("Aria2推送成功")
                btn.text(text);
            },
            error: function (error) {
                showError("Aria2 推送失败,请检查配置,或刷新后重试")
                btn.text(text);
            }
        });


    }


    dp.showAria2Set = function () {
        let $ = getJquery();

        $('body').append(showAria2SetHtml);
        let close = function () {
            $("#aria2-set-box").remove();
        }

        let link = $("#aria2-link");
        let path = $("#aria2-path");
        let token = $("#aria2-token");
        link.val(getItem("aria2-link") || "");
        path.val(getItem("aria2-path") || "");
        token.val(getItem("aria2-token") || "");

        $("#aria2-set-icon").one("click", close);

        $("#aria2-set-save").one("click", function () {
            setItem('aria2-link', link.val())
            setItem('aria2-path', path.val().replace(/\/$/, ""))
            setItem('aria2-token', token.val())
            close();
        });

    }

    dp.showDownloadHomePage = function () {
        let max = dp.page.item.length
        dp.page.item.forEach(function (item, index) {
            if (item.download_url && !dp.isExpires(item)) {
                item.download_url = ''
            }

            if (item.download_url || item.type === 'folder') {
                max--
                if (max === 0) {
                    dp.showBox()
                }
            } else {
                getDownloadUrl(item.file_id, item.drive_id, function (download_url) {
                    max--
                    if (download_url) {
                        dp.setExpires(item, 1600)
                        item.download_url = download_url
                    }
                    if (max === 0) {
                        dp.showBox()
                    }

                })
            }
        })

    }

    dp.initMenuButton = function () {
        let jq = getJquery()
        if (jq('.button-download-aliyun').length !== 0) {
            return
        }
        if (jq('#root header').length !== 0) {
            var html = ''
            html += '<div style="margin:1px 8px;"></div><button class="button--2Aa4u primary--3AJe5 small---B8mi button-download-aliyun">显示链接</button>'
            jq('#root header:eq(0)').append(html)
            jq('.button-download-aliyun').on('click', dp.showDownloadHomePage)

        } else {
            setTimeout(dp.initMenuButton, 1000)
        }
    }

    dp.selectedFileList = function () {
        let jq = getJquery()
        let selectedFileList = [], fileList = dp.page.item
        if (fileList.length === 0) {
            console.error('获取文件列表失败')
            return []
        }
        let node = ''
        if (jq('.tbody--3Y4Fn  .tr--5N-1q.tr--3Ypim').length) {
            node = jq('.tbody--3Y4Fn  .tr--5N-1q.tr--3Ypim')
        } else if (jq('.outer-wrapper--25yYA').length) {
            node = jq('.outer-wrapper--25yYA')
        }
        node.each(function (index) {
            var $this = jq(this)
            if ($this.attr('data-is-selected') === 'true') {
                let data_index = $this.closest('[data-index]').attr('data-index')
                data_index && selectedFileList.push(fileList[data_index])
            }
        })
        return selectedFileList.length ? selectedFileList : fileList
    }

// 分享按钮显示
    dp.initShareButton = function () {
        let jq = getJquery()
        if (jq('.button-download-aliyun').length !== 0) {
            return
        }
        if (jq('#root [class^=banner] [class^=right]').length !== 0) {
            var html = ''
            html += '<div style="margin:1px 7px;"></div><button class="button--2Aa4u primary--3AJe5 small---B8mi button-download-aliyun">显示链接</button>'
            jq('#root [class^=banner] [class^=right]').prepend(html)
            jq('.button-download-aliyun').on('click', dp.showDownloadSharePage)

        } else {
            setTimeout(dp.initShareButton, 500)
        }
    }

    dp.showDownloadSharePage = function () {
        if (document.querySelector('[class^=login]')) {
            document.querySelector('[class^=login]').click()
            return
        }
        let fileList = dp.selectedFileList()
        if (fileList.length === 0) {
            return
        }
        dp.getShareLinkDownloadUrlAll(fileList, function (fileList) {
            dp.showBox(fileList)
        })
    }

    dp.shareLinkDownloadUrl = function (file_id, share_id, callback) {
        var token = getToken()

        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/file/get_share_link_download_url',
            data: JSON.stringify({
                //expire_sec: 600,
                file_id: file_id,
                share_id: share_id
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=utf-8',
                'x-share-token': getItem('shareToken').share_token
            },
            async: true,
            success: function (response) {
                if (response.download_url) {
                    callback && callback(response.download_url)
                } else {
                    callback && callback('')
                }
            },
            error: function (error) {
                let errorCode = error.responseJSON ? error.responseJSON.code : ''
                if ('InvalidParameterNotMatch.ShareId' === errorCode) {
                    showError('错误:参数不匹配,请刷新', 10000)
                }
                callback && callback('')
            }
        })
    }

    dp.getShareLinkDownloadUrlAll = function (fileList, callback) {
        let max = fileList.length
        fileList.forEach(function (item, index) {
            if (item.download_url && !dp.isExpires(item)) {
                item.download_url = ''
            }
            if (item.download_url || item.type === 'folder') {
                max--
                if (max === 0) {
                    callback && callback(fileList)
                }
            } else {
                dp.getShareLinkDownloadUrl(item.file_id, item.share_id, function (download_url) {
                    if (download_url) {
                        dp.setExpires(item, 1600)
                        item.download_url = download_url
                    }
                    max--
                    if (max === 0) {
                        callback && callback(fileList)
                    }
                })
            }
        })
    }

    dp.getShareLinkDownloadUrl = function (file_id, share_id, callback) {
        refresh_token(function (result) {
            if (result) {
                share_token(function (result) {
                    if (result) {
                        dp.shareLinkDownloadUrl(file_id, share_id, callback)
                    } else {
                        callback && callback('')
                    }
                })
            } else {
                callback && callback('')
            }
        })
    }


// ---------  - ------------ end --------------------------


// --------------- start -----------------------------------

    class XMLHttp {
        request = function (param) {
        }
        response = function (param) {
        }
    }

    let http = new XMLHttp()

    http.response = function (res) {
        let config = res.config
        if (config.status === 404 && config.url.indexOf('/file/get_video_preview_play_info') > 0) {
            dp.playPrivacyVideo(JSON.parse(config.data))
            return;
        } else if (config.status != 200) {
            return
        }
        if (getJquery()('.ant-modal-mask').length > 0) {
            return
        }
        let response = res.response, url = config.url
        try {
            config.data = JSON.parse(config.data)
        } catch (error) {
            config.data = {}
        }

        response = {
            response: response,
            data: config.data
        }

        if (url.endsWith('/file/get')) {
            dp.fileGet(response)
        } else if (url.indexOf('/file/list') > 0 || url.indexOf('/file/search') > 0) {
            dp.fileList(response)
        } else if (url.indexOf('/file/get_video_preview_play_info') > 0) {
            dp.playInfo(response)
        }

    }

// 初始化 拦截XMLHttpRequest
    function initXMLHttpRequest() {
        let open = XMLHttpRequest.prototype.open
        XMLHttpRequest.prototype.open = function (...args) {
            let send = this.send
            let _this = this
            let post_data = []
            this.send = function (...data) {
                post_data = data
                return send.apply(_this, data)
            }
            // 请求前拦截
            http.request(args)

            this.addEventListener('readystatechange', function () {
                if (this.readyState === 4) {
                    let config = {
                        url: args[1],
                        status: this.status,
                        method: args[0],
                        data: post_data
                    }
                    // 请求后拦截
                    let res = this.response
                    if (typeof res == 'string') {
                        try {
                            res = JSON.parse(this.response)
                        } catch (e) {
                            console.log("解析出问题了, ", e)
                        }
                    }

                    http.response({config, response: res})
                }
            }, false)
            return open.apply(this, args)
        }
    }

    let getDownloadUrl = function (file_id, drive_id, callback) {
        let token = getToken()
        var that = getDownloadUrl
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/file/get_download_url',
            data: JSON.stringify({
                expire_sec: 14400,
                drive_id: drive_id,
                file_id: file_id
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=utf-8'
            },
            async: true,
            success: function (response) {
                if (response.url) {
                    callback && callback(response.url, response)
                } else {
                    console.error('获取下载链接失败', response)
                    callback && callback('')
                }
            },
            error: function (error) {
                let errorCode = error.responseJSON ? error.responseJSON.code : ''
                if (errorCode === 'TooManyRequests') {
                    setTimeout(function () {
                        that(file_id, drive_id, callback)
                    }, 500)
                } else {
                    console.error('获取下载链接 错误', error)
                    callback && callback('')
                }
            }
        })
    }

    let getHomeDownloadUrl = function (fileId, driveId, callback) {
        let token = getToken()
        if (token == null) {
            refresh_token(function (res) {
                getHomeDownloadUrl()
            })
        } else {
            getDownloadUrl(fileId, driveId, callback)
        }
    }

    let getToken = function () {
        let token = getLocalforage().getItem(`token`)
        if (token != null) {
            token = JSON.parse(token)

            if (dp.isExpires(token)) {
                return token
            }

            return null
        }
        return token
    }

    let getItem = function (n) {
        let item = getLocalforage().getItem(n)
        if (!item) {
            return null
        }
        try {
            return JSON.parse(item)
        } catch (e) {
            return item;
        }
    }

    let setItem = function (k, v) {
        localStorage.setItem(k, v instanceof Object ? JSON.stringify(v) : v)
    }

    let videoPreviewPlayInfo = function (callback) {
        let token = getToken() || {},
            file_id = dp.videoPage.id
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/file/get_video_preview_play_info',
            data: JSON.stringify({
                category: 'live_transcoding',
                drive_id: token.default_drive_id,
                file_id: file_id,
                template_id: '',
                get_subtitle_info: !0
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=UTF-8'
            },
            async: true,
            success: function (response) {
                callback && callback(response)
            },
            error: function (error) {
                callback && callback('')
            }
        })
    }

    let shareLinkVideoPlayInfo = function (callback) {
        var token = getToken() || {},
            share_id = shareId(),
            file_id = dp.videoPage.id
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info',
            data: JSON.stringify({
                category: 'live_transcoding',
                file_id: file_id,
                get_preview_url: true,
                share_id: share_id,
                template_id: '',
                get_subtitle_info: !0
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=UTF-8',
                'x-share-token': getItem('shareToken').share_token
            },
            async: true,
            success: function (response) {
                callback && callback(response)
            },
            error: function (error) {
                callback && callback('')
            }
        })
    }

    let getVideoFile = function (callback) {
        let token = getToken() || {}
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/file/get',
            data: JSON.stringify({
                drive_id: token.default_drive_id,
                file_id: dp.videoPage.id
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=UTF-8'
            },
            async: true,
            success: function (response) {
                callback && callback(response)
            },
            error: function (error) {
                callback && callback('')
            }
        })
    }

    let updateVideoTime = function (callback) {
        let token = getToken() || {}
        let player = dp.videoPage.player;
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/adrive/v2/video/update',
            data: JSON.stringify({
                drive_id: token.default_drive_id,
                duration: player.video.duration,
                file_id: dp.videoPage.id,
                play_cursor: player.video.currentTime
            }),
            headers: {
                'authorization': ''.concat(token.token_type || '', ' ').concat(token.access_token || ''),
                'content-type': 'application/json;charset=UTF-8'
            },
            async: true,
            success: function (response) {
                callback && callback(response)
            },
            error: function (error) {
                callback && callback('')
            }
        })
    }

    let shareId = function () {
        var url = location.href
        var match = url.match(/aliyundrive\.com\/s\/([a-zA-Z\d]+)/)
        return match ? match[1] : null
    }


    let share_token = function (callback) {
        var shareToken = getItem('shareToken')
        var share = shareId
        if (!shareToken) {
            showError('请登陆后刷新此页面重试!', 1e4)
            return callback && callback('')
        }
        if (dp.isExpires(shareToken)) {
            return callback && callback(shareToken)
        }
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/v2/share_link/get_share_token',
            data: JSON.stringify({
                share_id: share(),
                share_pwd: ''
            }),
            headers: {
                'Content-type': 'application/json;charset=utf-8'
            },
            success: function (response) {
                if (response.share_token) {
                    localStorage.setItem('shareToken', response instanceof Object ? JSON.stringify(response) : response)
                    callback && callback(response)
                } else {
                    callback && callback('')
                }
            },
            error: function (error) {
                if (error.responseJSON.code === 'InvalidResource.SharePwd') {
                    showError('请刷新并重新填写提取码', 1e4)
                }
                callback && callback('')
            }
        })
    }

    let hideShow = function () {
        let t = getJquery()('.aDrive-notice')
        t.length && 'function' == typeof t.remove ? t.remove() : 'function' == typeof t.removeNode && t.removeNode(true)
    }

    let showSuccess = function (msg, timeout) {
        let jq = getJquery()
        hideShow()
        let element = jq('.aDrive div')
        let elementhtml = '<div class="aDrive-notice"><div class="aDrive-notice-content"><div class="aDrive-custom-content aDrive-success"><span data-role="icon" data-render-as="svg" data-icon-type="PDSCheckmarkCircleFill" class="success-icon--2Zvcy icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSCheckmarkCircleFill"></use></svg></span><span><div class="content-wrapper--B7mAG" data-desc="false" style="margin-left: 44px; padding-right: 20px;"><div class="title-wrapper--3bQQ2">' + msg + '<div class="desc-wrapper--218x0"></div></div></div></span></div></div>'
        if (element.length) {
            element.append(elementhtml)
        } else {
            jq(document.body).append('<div><div class="aDrive"><div>' + elementhtml + '</div></div></div>')
        }
        var hide = hideShow
        setTimeout(function () {
            hide()
        }, timeout || 3000)
    }

    let showError = function (msg, timeout) {
        let jq = getJquery()
        hideShow()
        var element = jq('.aDrive div')
        var elementhtml = '<div class="aDrive-notice"><div class="aDrive-notice-content"><div class="aDrive-custom-content aDrive-error"><span data-role="icon" data-render-as="svg" data-icon-type="PDSCloseCircleFill" class="error-icon--1Ov4I icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSCloseCircleFill"></use></svg></span><span><div class="content-wrapper--B7mAG" data-desc="false" style="margin-left: 44px; padding-right: 20px;"><div class="title-wrapper--3bQQ2">' + msg + '<div class="desc-wrapper--218x0"></div></div></div></span></div></div></div>'
        if (element.length) {
            element.append(elementhtml)
        } else {
            jq(document.body).append('<div><div class="aDrive"><div>' + elementhtml + '</div></div></div>')
        }
        var hide = hideShow
        setTimeout(function () {
            hide()
        }, timeout || 3000)
    }

    let refresh_token = function (callback) {
        let token = getToken()
        if (token != null) {
            return callback && callback(token)
        }
        if (!(token && token.refresh_token)) {
            return callback && callback('')
        }
        getJquery().ajax({
            type: 'post',
            url: 'https://api.aliyundrive.com/token/refresh',
            data: JSON.stringify({
                refresh_token: token.refresh_token
            }),
            headers: {
                'Content-type': 'application/json;charset=utf-8'
            },
            success: function (response) {
                if (response instanceof Object && response.access_token) {
                    delete response.user_data
                    localStorage.setItem('token', response instanceof Object ? JSON.stringify(response) : response)
                    callback && callback(response)
                } else {
                    callback && callback('')
                }
            },
            error: function () {
                callback && callback('')
            }
        })
    }

    let getTime = function (time) {
        let h = parseInt(time / 60 / 60 % 24)
        h = h < 10 ? '0' + h : h
        let m = parseInt(time / 60 % 60)
        m = m < 10 ? '0' + m : m
        let s = parseInt(time % 60)
        s = s < 10 ? '0' + s : s
        return `${h}:${m}:${s}`
    }

    let getJquery = function () {
        return $
    }

    let getLocalforage = function () {
        return localStorage
    }


    let initPre = function () {
        if (!dp.createDPlayer()) {
            setTimeout(initPre, 500)
        }
    }

    initXMLHttpRequest()
    console.log('你好,罗根')



})()