浏览器插件

Alist快速添加云盘分享存储油猴脚本
2023-02-01 我的站长站

Alist快速添加云盘分享存储油猴脚本

  • 软件编号:1503
  • 点击次数:
  • 软件语言:简体中文
  • 软件大小:9.25 KB
  • 提 取 码 :无需提取码
  • 下载权限:免费下载
  • 软件售价:免费下载
  • 下载次数:1

Alist快速添加存储脚本介绍

使用Alist添加存储时,如果经常需要手动复制分享ID、文件夹ID,再切换到Alist后台填写相关参数,操作起来还是比较麻烦。尤其是在手机上管理Alist,频繁来回切换页面会更加费劲。

针对这个问题,分享一个简单的Alist快速添加存储Userscript脚本。脚本主要用于阿里云盘分享页面,可以直接读取当前页面中的分享ID和目录ID,然后通过Alist接口创建对应的存储,从而减少手动复制粘贴的步骤。

脚本主要功能

  • 在阿里云盘分享页面增加“创建Alist存储”按钮。

  • 自动获取当前分享页面中的分享ID。

  • 自动获取当前页面对应的根目录ID。

  • 支持填写Alist挂载路径。

  • 支持填写阿里云盘分享密码。

  • 自动登录Alist后台并获取token

  • 调用Alist管理接口创建存储。

  • 手机端可以配合Via浏览器使用。

Alist快速添加存储脚本使用方法

这个脚本属于油猴(Userscript)类型脚本,使用前需要在支持用户脚本的浏览器或扩展中安装。

添加脚本时,将下面的完整代码复制进去,然后重点修改脚本开头的4个变量,也就是Alist地址、管理员用户名、管理员密码以及阿里云盘的refresh_token

需要修改的4个变量

const baseUrl = 'http://xxxxxxxx:5244'
const adminUser = '管理员用户名'
const adminPwd = '管理员密码'
const refresh_token = '自行获取云盘的refresh_token'

baseUrl填写自己的Alist访问地址,例如Alist实际运行在其他端口,就需要按照自己的环境进行修改。

adminUseradminPwd填写Alist管理员账号和密码,脚本会通过Alist登录接口获取Token,用于后续创建存储。

refresh_token则需要替换成自己的阿里云盘Refresh Token。原脚本说明中提到可以通过MT管理器查看相关日志获取,具体获取方式建议根据自己当前使用的环境确认。

具体使用流程

完成脚本配置后,打开阿里云盘对应的分享页面。如果脚本正常运行,页面下方会出现一个“创建Alist存储”按钮。

点击按钮后会弹出操作窗口,可以填写Alist挂载路径以及分享密码。脚本会根据当前页面URL自动读取分享ID和根目录ID。

确认无误后点击“确认”,脚本会调用Alist的存储创建接口。如果接口返回成功,页面会提示“创建成功”。

操作过程

  1. 配置脚本前面的4个变量。

  2. 在支持Userscript的浏览器中安装脚本。

  3. 打开阿里云盘分享页面。

  4. 点击“创建Alist存储”。

  5. 填写Alist挂载路径。

  6. 如果分享链接设置了密码,填写分享密码。

  7. 点击“确认”。

  8. 等待脚本调用Alist接口创建存储。

完整脚本代码

下面是完整的Alist快速添加存储脚本。使用时直接复制,然后按照上面的说明修改开头的4个变量即可。

// ==UserScript==
// @name         快速上传Alist
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  简单就完了
// @AuThor       52pojie
// @match       *://*.aliyundrive.com/*
// @Icon         https://www.google.com/s2/favicons?sz=64&domain=aliyundrive.com
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_log
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      *
// @run-at document-end
// ==/UserScript==
(function() {
    'use strict';
    const baseUrl = 'http://xxxxxxxx:5244'
    const adminUser = '管理员用户名'
    const adminPwd = '管理员密码'
    const refresh_token = '自行获取云盘的refresh_token(可以通过mt管理器查看日志)'
    const headerPost = async (url, data, headers, type) => {
        return new Promise((resolve, reject) => {
            let option = {
                method: "POST",
                url: url,
                headers: headers,
                data: data,
                responseType: type || 'json',
                onload: (res) => {
                    if (type === 'blob') {
                        resolve(res)
                    } else {
                        const _re = res.response || res
                        .responseText
                        typeof _re === 'string' ? resolve(JSON.parse(_re)) : resolve(_re)
                        }
                },
                onerror: (err) => {
                    reject(err);
                },
            }
            try {
                let req = GM_xmlhttpRequest(option);
            } catch (error) {
                console.error(error);
            }
        });
    };
    async function addStorage({mount_path, share_id, share_pwd = "", root_folder_id = "root", order_by = "", order_direction = ""}){
        return await headerPost(baseUrl + '/api/admin/storage/create',JSON.stringify({
            mount_path: mount_path,
            order: 0,
            remark: '',
            cache_expiration: 30,
            web_proxy: false,
            webdav_policy: "302_redirect",
            down_proxy_url: "",
            extract_folder: "",
            driver: "AliyundriveShare",
            addition: JSON.stringify({
                refresh_token: refresh_token,
                share_id,
                share_pwd,
                root_folder_id,
                order_by,
                order_direction
            })
        }), {
            "Authorization": GM_getValue('token'),
            "Content-Type": "application/json;charset=UTF-8"
        })
    };
    async function login() {
        const res = await headerPost(baseUrl + '/api/auth/login', JSON.stringify({username: adminUser, password: adminPwd, "otp_code":""}), {"Content-Type": "application/json;charset=UTF-8"})
        if (res.code === 200) {
            GM_setValue('token', res.data.token)
        } else {
            toast("登录失败")
        }
    }
    function toast(msg) {
        const t = (() => {
            if (document.querySelector('#J_single_toast')) {
                return document.querySelector('#J_single_toast')
            } else {
                const _t = document.createElement('div')
                _t.id = 'J_single_toast'
                document.body.appendChild(_t)
                return _t
            }
        })()
        t.innerText = msg
        t.classList.toggle('show')
        setTimeout(() => {t.classList.toggle('show')}, 1500)
    }
    function createCustomDom() {
        let mount_path = `/xx云盘分享_${+new Date}`
        const cBtn = document.createElement('div')
        cBtn.innerText = "创建Alist存储"
        cBtn.className = "cBtn"
        document.body.appendChild(cBtn)
        const dialog = document.createElement('div')
        dialog.className = "mount-path-dialog"
        dialog.innerHTML = `
            <div class="mask"></div>
            <div class="input-wrap">
                <div class="input-item">
                    <p>请输入Alist挂载路径:</p>
                    <input name="mount_path" value=${mount_path}>
                </div>
                <div class="input-item">
                    <p>请输入分享密码:</p>
                    <input name="share_pwd">
                </div>
                <div class="btn-group">
                    <div class="cancel btn">取消</div>
                    <div class="confirm btn">确认</div>
                </div>
            </div>`
        document.body.appendChild(dialog)
        cBtn.addEventListener('click', () => {
            dialog.style.display = 'block';
            dialog.querySelector('[name="mount_path"]').focus();
            dialog.querySelector('[name="mount_path"]').setSelectionRange(1, 999);
        })
        dialog.addEventListener('click', function(e){
            if (Array.from(dialog.querySelectorAll('.mask, .cancel')).includes(e.target)) {
                closeDialog()
            }
            if (e.target === dialog.querySelector('.confirm')) {
                const arr = window.location.pathname.split('/')
                addStorage({
                    mount_path: dialog.querySelector('[name="mount_path"]').value,
                    share_pwd: dialog.querySelector('[name="share_pwd"]').value,
                    share_id: arr[2],
                    root_folder_id: arr[4]
                }).then(res => {
                    if (res.code === 200) {
                        dialog.style.display = 'none'
                        toast('创建成功')
                    } else {
                        toast(res.message)
                    }
                })
            }
        })
        function closeDialog() {
            dialog.style.display = 'none'
        }
    }
    async function init() {
        GM_addStyle(`
        #J_single_toast {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 1001;
            display: none;
            background: rgba(0,0,0,0.8);
            color: var(--basic_white);
            padding: 10px;
            max-width: 300px;
            border-radius: 4px;
        }
         #J_single_toast.show {
            display: block;
        }
        .cBtn {
            position: fixed;
            left: 50%;
            transform: translateX(-50%);
            bottom: 80px;
            z-index: 999;
            bottom: calc(constant(safe-area-inset-bottom) + 80px);
            bottom: calc(env(safe-area-inset-bottom) + 80px);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            color: var(--basic_white);
            background: var(--theme_primary);
            height: 44px;
            padding: 0 16px;
            font-size: 16px;
            border-radius: 22px;
        }
        .mount-path-dialog {
            position: fixed;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            z-index: 1000;
            display: none;
            margin: auto;
        }
        .mount-path-dialog .mask {
            position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;
            background: rgba(0,0,0,0.6)
        }
        .mount-path-dialog .input-wrap {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            width: 300px;
            height: 280px;
            background: #fff;
            border-radius: 10px;
            box-sizing: boder-box;
        }
        .mount-path-dialog .input-wrap .input-item {
            margin-bottom: 8px;
        }
        .mount-path-dialog .input-wrap p {
            font-size: 14px;
            margin-bottom: 5px;
        }
        .mount-path-dialog .input-wrap input{
            display: block;
            width: 240px;
            height: 40px;
            margin: 0 auto 15px;
            font-size: 12px;
            border: 1px solid #ccc;
            padding-left: 8px;
            border-radius: 4px;
        }
        .mount-path-dialog .input-wrap .btn-group {
            display: flex;
            align-items: center;
            justify-content: space-between;
            width: 260px;
            margin: 0 auto;
        }
        .mount-path-dialog .input-wrap .btn-group .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            flex: 1;
            margin: 0 10px;
            height: 40px;
            background: var(--theme_primary);
            color: var(--basic_white);
            font-size: 16px;
            border-radius: 4px;
        }
        .mount-path-dialog .input-wrap .btn-group .cancel {
            background: #fff;
            color: #333;
            border: 1px solid #ccc;
        }
        `)
        await login()
        createCustomDom()
    }
    window.addEventListener ("load", init);
})();

使用安全注意事项

这个脚本需要填写Alist管理员账号、管理员密码以及阿里云盘的refresh_token,这些信息都属于比较敏感的凭据,因此不要把填写完成后的脚本直接公开分享

发布脚本时建议保留占位符,让使用者自行填写自己的信息。尤其是refresh_token,不要提交到公开代码仓库,也不要发送给不可信的人。

另外,脚本使用了GM_xmlhttpRequest跨域请求Alist接口,并通过@connect *允许连接任意域名。使用时建议只在自己信任的脚本管理器和浏览器环境中运行,并仔细检查脚本来源。

手机端使用体验

如果平时主要通过手机管理Alist,这种脚本会更加方便。安装好用户脚本后,可以直接在阿里云盘分享页面完成相关操作,不需要频繁在阿里云盘和Alist后台之间切换。

原作者特别提到了Via浏览器,因此手机用户可以根据自己的浏览器脚本支持情况进行测试。不同浏览器对Userscript、GM API以及跨域请求的支持可能存在差异,如果脚本没有正常运行,需要检查浏览器的脚本功能是否开启。

总结

这个Alist快速添加存储脚本属于比较实用的小工具,核心思路就是把原本需要手动完成的分享ID、目录ID复制以及Alist存储创建操作串联起来。

对于经常添加阿里云盘分享存储的Alist用户来说,可以减少重复的复制粘贴和页面切换操作。脚本本身比较简单,主要适合有一定Alist使用经验的用户,根据自己的服务器地址和账号信息进行配置即可。

需要注意的是,Alist版本、接口以及阿里云盘页面结构后续都可能发生变化,因此脚本能否长期正常使用需要以实际环境测试结果为准。

下载地址

· 积分下载:下载扣除对应积分,不扣除下载次数
· 会员免费:VIP会员免费下载,扣除下载次数
· 下载即代表您已阅读并同意 [服务条款]

浏览器插件标签