Greasy Fork

Greasy Fork is available in English.

阿里云盘助手

支持生成文件下载链接、修改文件后缀,支持第三方播放器DPlayer(突破视频2分钟限制,长按倍速,选集,上下集)

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

// ==UserScript==
// @name         阿里云盘助手
// @namespace    http://tampermonkey.net/
// @version      1.0.6
// @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 流畅'
}


//   创建播放器
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 fileList = dp.page.item;
    let  fileIndex = fileList.findIndex(function (item, index) {
        return item.file_id === dp.videoPage.id
    })
    let pic= ''
    if (fileIndex!==-1){
        pic =  fileList[fileIndex].thumbnail
    }

    let options = {
        container: dp.dPlayerNode,
        video: {
            quality: quality,
            defaultQuality: defaultQuality,
            pic:pic,
            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: []
    }


    try {

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

        player.on("quality_end", function () {
            setItem("quality", player.quality.templateId);
        });

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


        dp.dPlayerEvent();


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


// 播放器事件绑定
dp.dPlayerEvent = function () {
    var rightCount = 0;
    var rightInterval = null;
    var logKey = false;
    var playbackRate = null;


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

    document.onkeydown = function (event) {
        let player = dp.videoPage.player

        //右
        if (event.code === 'ArrowRight') {
            rightCount += 1;
            if (!playbackRate){
                playbackRate = player.video.playbackRate
            }
            if (!rightInterval) {

                rightInterval = setInterval(function () {
                    if (rightCount > 100) {
                        rightCount = 2;
                    }

                    if (rightCount > 1 && !logKey) {
                        dp.doubleSpeed()
                        logKey = true;
                    }

                }, 100)
            }


        } else if (event.code === 'ArrowLeft') {
            //左
            player.seek(player.video.currentTime - 5);
        } else if (event.code === 'ArrowUp') {
            //上
            player.volume(player.volume() + .01);
        } else if (event.code === 'ArrowDown') {
            //下
            player.volume(player.volume() - .01);
        } else if (event.code === 'Space') {
            //空格
            player.toggle();
        } else if (event.code === 'Enter') {
            //回车
            player.fullScreen.toggle();
        }


    }

    document.onkeyup = function (event) {
        let player = dp.videoPage.player
        if (event.code === 'ArrowRight') {
            if (rightCount === 1) {
                player.seek(player.video.currentTime + 5);
            }
            logKey = false;
            if (rightInterval){
                window.clearInterval(rightInterval)
            }

            rightInterval = null;
            rightCount = 0;

            if (playbackRate){
                player.speed(playbackRate)
                player.notice('恢复' + playbackRate)
                playbackRate=null
            }
        }
    }


}


// 长按双倍速
dp.doubleSpeed = function () {
    let player = dp.videoPage.player
    player.notice('长按加速' + player.video.playbackRate)
    player.speed(2)
}

//获取上次观看时长
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.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.request = function (req){

    // 后缀修改
    if (req.url.endsWith('file/update')) {
        let reqbody = JSON.parse(req.data[0]);
        let name = reqbody.name;
        //原本的后缀
        let i =  name.lastIndexOf('.');
        if (i===-1){
            return;
        }
        let newName = name.substring(0,i);
        if (newName.lastIndexOf('.')!==-1){
            reqbody.name = newName;
            req.data[0] = JSON.stringify(reqbody)
        }


    }

}

http.response = function (res) {
    let config = res.config
    if (config.status === 404 && config.url.indexOf('/file/get_video_preview_play_info') > 0) {
        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
            // 请求前拦截
            http.request({
                url: args[1],
                method: args[0],
                data: data
            })

            return send.apply(_this, data)
        }


        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('你好,罗根')



})()