[GalGame]面板安装OneList(go版本)-极简OneDrive目录列表
本文最后更新于 758 天前,其中的信息可能已经有所发展或是发生改变。

缘由:从SteamGalgame OneDrive – /上面看到了这个界面,既简约又好用,所以从网络上找啊找,看F12,找了几天就只找到了OneindexzdirzfileCuteOnesharelist这几个类似的界面。就是没找到一样的,于是感觉到可能是像OneManager-php后台可以更改界面样式的,所以直接使用笨方法,将看似关键的js直接复制后搜索。一捜不知道,向下翻了几行,果然看到了相关的github和图片界面QWQ。

于是,这篇教程在我搭建完成后,诞生了。

功能:

  • 支持 国际版, 个人免费版(家庭版), 世纪互联.
  • 支持同时列出多个盘的目录.(同时挂载多个网盘或单个网盘挂载成多个SubPath,要求每个SubPath唯一)
  • 支持文件夹内超过 200 个项目
  • 支持后台自动刷新缓存.
  • 支持路径中含有特殊字符.
  • 支持使用不同目录使用不同账户密码加密(HTTP 401).
  • 支持隐藏目录和文件(跳过缓存).
  • 支持自定义 ClientID 和 SecretKey .
  • 数据储存在内存中,响应更加迅速.

1.准备工作

2.开始

2.1 授权认证

不熟悉电脑的建议2.2完成后进行2.1

根据OneDrive的类型选择:
国际版、个人版(家庭版):点击此处
世纪互联版:点击此处

这里注意:授权后会跳转至一个以localhost开头的链接,请复制整个链接(包括localhost)到记事本里备用,不关闭这个网页也可以。

2.2 部署OneList

选择一个文件夹来部署OneList,这里以/www/wwwroot为例
在这个wwwroot文件夹下新建一个文件夹名为OneList,并进入
在里面选择终端,并根据你的服务器架构选择合适的OneList版本

#64位系统下载
wget https://raw.githubusercontent.com/MoeClub/OneList/master/Rewrite/amd64/linux/OneList
#32位系统下载
wget https://raw.githubusercontent.com/MoeClub/OneList//master/Rewrite/i386/linux/OneList
#arm架构下载
wget https://raw.githubusercontent.com/MoeClub/OneList/master/Rewrite/arm/linux/OneList

如果服务器无法下载,我们通过手动下载后上传来解决:直接框选相应架构wget后面的链接进浏览器地址栏下载,下载下来后直接上传进服务器。
打开上方的终端,给予OneList权限

chmod +x OneList

2.3 生成配置文件

上面的步骤完成后,我们继续使用终端来生成相关配置文件

#国际版,将url换成你上面复制的授权地址,包括http://loaclhost。
./OneList -a "url" -s "/onedrive01"
 
#个人版(家庭版),将url换成你上面复制的授权地址,包括http://loaclhost。
./OneList -ms -a "url" -s "/onedrive02"
 
#中国版(世纪互联),将url换成你上面复制的授权地址,包括http://loaclhost。
./OneList -cn -a "url" -s "/onedrive03"

# 在浏览器地址栏中获取以 http://loaclhost 开头的整个url内容
# 将获取的完整url内容替换命令中的 url 三个字母
# 每次产生的 url 只能用一次, 重试请重新获取 url
# 可以一个盘内的多个文件夹分别映射到多个`SubPath`上
# 此操作将会自动添加的配置文件
# 提示 Success! Add config. '/path/to/config.json' 则成功

输入相应的代码后回车,等待提示Success! Add config.'/path/to/config.json'信息,则添加成功。
如果出现error! Add config.'/path/to/config.json'信息,请检查你在2.1复制的链接是否正确,不正确请重新开始2.1的步骤。重新获得以http://loaclhost开头的链接。

  • 注意:授权的Url只能用一次,超过后请重新授权。
  • 命令中的/onedrive01参数为指定网盘地址后缀,例如https://xxx.com/onedrive01。
  • 授权多个网盘的话,重复授权多次即可,参数均会添加到一个配置文件,且后缀不能重复。
  • 地址后缀错填或后期想改,可以在稍后的配置文件中修改。

2.4 配置文件相关提示

[
  {
    // 如果是家庭版或者个人免费版, 此项应为 true.
    "MSAccount": false,
    // 如果是中国版(世纪互联), 此项应为 true.
    "MainLand": false,
    // 授权令牌
    "RefreshToken": "1234564567890ABCDEF",
    // 单配置文件中,此项要唯一.将此OneDrive中设置为`RootPath`目录映射在`http://127.0.0.1:5288/onedrive` 下.
    // (只推荐一个盘位的时候使用根目录"/".)
    "SubPath": "/onedrive",
    // 读取OneDrive的某个目录作为根目录. (支持根目录"/")
    "RootPath": "/Test",
    // 隐藏OneDrive目录中的文件夹和文件, 条目间使用 "|" 分割. (跳过缓存设置的条目.)
    "HidePath": "/Test/Obj01|/Test/Obj02",
    // 使用用户名和密码加密OneDrive目录. 目录和用户名密码间使用 "?" 分割, 用户名密码使用 ":" 分割, 条目间使用 "|" 分割. 无效条目将跳过. 
    "AuthPath": "/Test/Auth01?user01:pwd01|/Test/Auth02?user02:pwd02",
    // 缓存刷新间隔.(所有项目中的刷新时间取最小值为有效刷新间隔)
    "RefreshInterval": 900
  }
]

如果挂载多个盘符,SubPath参数请不要为/,单个网盘建议为/

2.5 启动OneList

在OneList文件夹下启动终端,运行一下命令,来启动项目。

#下载默认的index.html主题,与config.json同目录,即本文默认的/www/wwwroot/OneList
wget https://raw.githubusercontent.com/MoeClub/OneList/master/Rewrite/index.html
#监听8000地址,自行修改
/www/wwwroot/OneList/OneList -bind 0.0.0.0 -port 8000

注意:这里的终端一旦关闭OneList将停止运行,稍后解决这个问题。

如果你在配置文件里把SubPath的参数修改为/时,浏览器地址栏输入<ip:端口号>即可访问。
如果你在挂载网盘时的时候SubPath没有修改,而且是世纪互联版的话,输入<ip:端口号/onedrive01>就可以访问到了。
注意:如果文件路径不存在,则会显示No Found,如果目录下没有文件也会显示No Found。
我们把终端关闭。接下来解决后台运行的问题。

3. 后台运行和开机自启

3.1 安装进程守护管理器

在宝塔面板的软件商店里搜索“进程守护管理器”,点击安装。
安装好后,点击右边的“设置”,点击“添加守护进程”按钮。
名称随便填,然后在启动命令中填入

/www/wwwroot/OneList/OneList -bind 0.0.0.0 -port 8000

进程目录

/www/wwwroot/OneList

当状态显示RUNNING,就说明配置正确。显示其他状态请检查配置,首先可以看看是否已经在终端启动过OneList了,如果是在终端启动,请直接关闭终端再试。

注意,/**/**/OneList均需要根据你的安装位置来确定目录,如果不行,可以尝试将目录直接定位到OneList文件,或者在最后添加/

这样就可以通过“进程守护管理器”看到OneList的运行状态了,并且可以自动修复异常情况和开机自启。

4. 设置域名访问

宝塔面板新建网站,找到设置,创建反相XX,在目前URL里填写http://127.0.0.1:8000,点击提交即可
后面就可以用域名打开了,如果要设置SSL,需要先把这关闭,申请好证书再开启。

5. OneList的使用命令

(基本用不到)

Usage of OneList:
  -a string
        // 初始化配置文件,添加新配置
        Setup and Init auth.json.
  -bind string
        // 绑定IP地址(公网: 0.0.0.0)
        Bind Address (default "127.0.0.1")
  -port string
        // 绑定端口(HTTP:80)
        Port (default "5288")
  -s string
        // 设置 SubPath 项, 需要与 -a 一起使用.
        Set SubPath. [unique per account] (default "/")
  -c string
        // 配置文件
        Config file. (default "config.json")
  -t string
        // Index.html 目录样式文件
        Index file. (default "index.html")
  -cn
        // 开关
        // 授权中国版(世纪互联), 需要此参数.
        OneDrive by 21Vianet.
  -ms
        // 开关
        // 授权个人版(家庭版), 需要此参数.
        OneDrive by Microsoft.

6. 界面样式的更改

直接将OneList目录下的index.html文件替换,然后重启程序即可

1.HaorWu

  • 特点
  • 支持移动端自适应
  • 支持当页搜索
  • 支持按文件名,日期,大小排序
  • 支持主动查看图片
  • 支持在线播放视频
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge, Chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1,viewport-fit=cover">
    <title>GalGame记录页</title>
    <link href="https://s0.pstatp.com/cdn/expire-1-M/mdui/0.4.2/css/mdui.min.css" rel="stylesheet">
    <link href="https://s0.pstatp.com/cdn/expire-1-M/dplayer/1.25.0/DPlayer.min.css" rel="stylesheet">
    <style>
    body{background-color:#f2f5fa}.nexmoe-item{margin:15px 0 !important;padding:15px !important;border-radius:5px;background-color:#fff;-webkit-box-shadow:0 .5em 3em rgba(161,177,204,.4);box-shadow:0 .5em 3em rgba(161,177,204,.4);background-color:#fff}.mdui-img-fluid,.mdui-video-fluid{border-radius:5px;border:1px solid #eee}.mdui-list{padding:0}.mdui-list-item{margin:0 !important;border-radius:5px;padding:0 10px 0 5px !important;border-bottom:1px solid #eee;margin-bottom:10px !important}.mdui-list-item:last-child{margin-bottom:0 !important}.mdui-toolbar{width:auto}.mdui-appbar .mdui-toolbar{height:56px;font-size:16px}.mdui-toolbar>*{padding:0 6px;margin:0 2px}.mdui-toolbar>.mdui-typo-headline{padding:0 16px 0 0}.mdui-toolbar>i{padding:0}.mdui-toolbar h3.title{padding:0 16px;line-height:30px;border-radius:30px;border:1px solid #eee;opacity:1;background-color:#1e89f2;color:#ffff}.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{opacity:1}.mdui-list>.th{background-color:initial}.mdui-list-item>a{width:100%;line-height:48px}.mdui-toolbar>a{padding:0 16px;line-height:30px;border-radius:30px;border:1px solid #eee}.mdui-toolbar>a:last-child{opacity:1;background-color:#1e89f2;color:#ffff}@media screen and (max-width:980px){.mdui-list-item .mdui-text-right{display:none}.mdui-container{width:100% !important;margin:0}.mdui-toolbar>a:last-child,.mdui-toolbar>.mdui-typo-headline,.mdui-toolbar>i:first-child{display:block}}#main-page{cursor:pointer}.nav-a{text-decoration:none;color:#333}.nav-a:hover{text-decoration:underline}.file{width:100%;display:flex;align-items:center}.file a{color:unset;width:100%}#text-input,#close{display:none}#text-input{width:40%}#dplayerContainer{position:relative;background-color:#000;display:none;padding:10px}.close-icon{color:#fff}#viewerContainer{width:100%;height:100%}.viewer-img{width:450px;position:relative;left:30%;z-index:1000}span.overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.8);z-index:999}#viewerClose{z-index:1000;color:#fff;background:rgba(255,255,255,.12);display:inline-block;position:absolute;bottom:0;cursor:pointer}@media screen and (max-width:768px){.viewer-img{width:60%;position:relative;left:20%;z-index:1000}}
    </style>
</head>
<body>
    <div class="container mdui-container">
        <div class="mdui-container-fluid">
            <div class="mdui-toolbar nexmoe-item nav">
                <i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-blue" id="main-page" onclick="goto(rootPath)">home</i>
                <span id="path">/</span>
                <div class="mdui-toolbar-spacer"></div>
                <input type="text" id="text-input" class="mdui-textfield-input" oninput="search(this)" placeholder="请输入关键字">
                <button type="button" id="close" class="mdui-textfield-close mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">close</i></button>
                <button type="button" id="btn" class="mdui-textfield-icon mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">search</i></button>
            </div>
        </div>
        <div class="mdui-container-fluid">
            <div class="list-wrapper nexmoe-item">
                <div class="list-header">
                    <div class="file mdui-list-item th">
                        <span class="name mdui-col-xs-12 mdui-col-sm-7" onclick="view('name')">列表</span>
                        <span class="time mdui-col-sm-3 mdui-text-right" onclick="view('date')">时间</span>
                        <span class="size mdui-col-sm-2 mdui-text-right" onclick="view('size')">大小</span>
                    </div>
                </div>
                <div id="file-list"></div>
            </div>
        </div>
    </div>
    <script src="https://s0.pstatp.com/cdn/expire-1-M/??mdui/0.4.0/js/mdui.min.js,dplayer/1.25.0/DPlayer.min.js"></script>
    <script>
    let domain = window.location.host,
        rootPath = "{{.RootPath}}",
        currentPath = "{{.CurrentPath}}",
        rawData = "{{.RawData}}",
        title = 'GalGame记录页',
        $ = mdui.JQ;
    if (currentPath === "/") {
        currentPath = "";
    }
    let reverse = false,
        pageData = JSON.parse(window.atob(rawData)),
        arrayPath = new Array(),
        arrayFloder = new Array(),
        arryVideo = new Array(),
        arrayFile = new Array();
    for (let item in pageData) {
        if (item.indexOf("@") == 0) {
            continue
        }
        if (getFileType(decodeURIComponent(pageData[item]['name'])) == "video") {
            arryVideo.push(decodeURIComponent(pageData[item]['name']))
        }
        if (pageData[item]['@type'] == 'file') {
            arrayFile.push(pageData[item])
        } else if (pageData[item]['@type'] == 'folder') {
            arrayFloder.push(pageData[item])
        }
    }
    function goto(thePath) {
        window.location.href = thePath
    }
    function sizeNum(Size) {
        let dataArray = Size.split(" ", 2),
            dataNum = 0;
        switch (dataArray[1]) {
            case "B":
                dataNum = Math.pow(2, 0) * dataArray[0];
                break;
            case "KB":
                dataNum = Math.pow(2, 10) * dataArray[0];
                break;
            case "MB":
                dataNum = Math.pow(2, 20) * dataArray[0];
                break;
            case "GB":
                dataNum = Math.pow(2, 30) * dataArray[0];
                break;
            case "TB":
                dataNum = Math.pow(2, 40) * dataArray[0];
                break;
            case "PB":
                dataNum = Math.pow(2, 50) * dataArray[0];
                break;
            default:
                dataNum = 2 ** 50 * dataArray[0]
        }
        return dataNum
    }
    function compare(property) {
        if (property === "size") {
            return function(a, b) {
                let value0 = sizeNum(a[property].toUpperCase());
                let value1 = sizeNum(b[property].toUpperCase());
                return value0 - value1
            }
        } else {
            return function(a, b) {
                let value0 = a[property].toLowerCase();
                let value1 = b[property].toLowerCase();
                return value0.localeCompare(value1)
            }
        }
    }
    function clear() {
        let classList = new Array("file-wrapper");
        for (let item in classList) {
            let obj = document.getElementsByClassName(classList[item]);
            for (let i = obj.length - 1; i >= 0; i--) {
                obj[i].parentNode.removeChild(obj[i])
            }
        }
        let nav = document.getElementById("path"),
            pathSpan = document.createElement("span"),
            locPath = currentPath.trim().replace(/^\//, "").replace(/\/$/, "");
        locArray = new Array('');
        if (nav.innerHTML.length > 0) {
            nav.innerHTML = ''
        }
        if (locPath !== "") {
            let locPathArr = locPath.split("/"),
                localHref = "";
            for (let j = 0; j < locPathArr.length; j++) {
                localHref += "/" + locPathArr[j];
                if (j === 0 && rootPath !== "/") {
                    continue
                }
                navTemp = `<a class="nav-a" href="https://${window.location.host}${localHref}">${locPathArr[j]}</a>`;
                locArray.push(navTemp)
            }
        }
        pathSpan.innerHTML = locArray.join("/");
        nav.appendChild(pathSpan);
        navText = (nav.innerHTML.length === 0) ? '/' : pathSpan.innerHTML.replace(/<[^>]+>/g, "");
        document.title += navText.substr(1);
        arrayPath = locArray
    }
    function search(obj) {
        let searchVal = obj.value;
        if (searchVal === undefined) {
            return
        } else {
            searchVal = searchVal.toString().toLowerCase()
        }
        let showArray = document.getElementsByClassName("file-wrapper");
        for (let i = 0; i < showArray.length; i++) {
            let content = showArray[i].children[0].querySelector("span.mdui-text-truncate").innerText;
            if (content !== undefined && content.length > 0) {
                let newAttr = '';
                if (content.toLowerCase().indexOf(searchVal) < 0) {
                    newAttr = "none"
                }
                showArray[i].style.display = newAttr
            }
        }
    }
    function view(Property) {
        arrayFloder.sort(compare(Property));
        arrayFile.sort(compare(Property));
        if (reverse) {
            arrayFloder.reverse();
            arrayFile.reverse();
        }
        reverse = !(reverse);
        clear();
        let obj = document.getElementById('file-list'),
            items = arrayFloder.concat(arrayFile);
        for (let item in items) {
            let newChild = document.createElement("div"),
                icon = (items[item]['@type'] == 'folder') ? 'folder_open' : 'image_aspect_ratio',
                itemName = decodeURIComponent(items[item]['name']),
                protocol  = (document.location.protocol == 'https:') ? 'https:' : 'http:';
            let href = protocol + '//' + domain + currentPath + '/' + itemName;
            let fileType = getFileType(itemName);
            if (icon == 'image_aspect_ratio') {
                icon = getFileIcon(fileType)
            }
            newChild.setAttribute('class', 'row file-wrapper mdui-list-item mdui-ripple');
            newChild.innerHTML = `
            <div class="file">
                <i class="mdui-icon material-icons">${icon}</i>
                <a href="javascript:;">
                    <span class="name mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate">${itemName}</span>
                    <span class="time mdui-col-sm-3 mdui-text-right">${items[item]['date']}</span>
                    <span class="size mdui-col-sm-2 mdui-text-right">${items[item]['size']}</span>
                </a>
            </div>`;
            obj.appendChild(newChild);
            newChild.addEventListener('click',function(e){
                if (fileType == "video") {
                    let dplayerContainer = `
                        <div id="dplayerContainer" class="mdui-container-fluid">
                            <div align="right">
                                <button type="button" id="closevideo" onclick="dpClose()" class="mdui-textfield-close mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons close-icon">close</i></button>
                            </div>
                            <div id="dplayer"></div>
                        </div>`;
                    $('#dplayerContainer').remove();
                    $(newChild).after(dplayerContainer);
                    dpOpen(href)
                }else if(fileType == "image"){
                    let imgEle = `
                        <div id="viewerContainer" onclick="$(this).remove()">
                            <span class="overlay"></span>
                            <img class="viewer-img" src="https://www.qfya.com/${href}">
                        </div>
                        `;
                    $('#viewerContainer').remove();
                    $(newChild).after(imgEle)
                }else{
                    window.location.href = href
                }
            },false)
            newChild.oncontextmenu = function() {
                $(newChild).find('a').attr('href', href)
            }
        }
    }
    function getFileType(name) {
        if (!name) return false;
        let imgType = ['gif', 'jpeg', 'jpg', 'bmp', 'png'],
            videoType = ['avi', 'wmv', 'mkv', 'mp4', 'mov', '3gp', 'flv', 'mpg', 'rmvb'],
            textType = ['txt', 'pdf', 'css', 'js', 'text', 'doc', 'docx', 'ppt', 'xml'],
            musicType = ['wav', 'acc', 'flac', 'ape', 'ogg', 'mp3'];
        if (RegExp("\.(" + imgType.join("|") + ")$", "i").test(name.toLowerCase())) {
            return 'image'
        }else if (RegExp("\.(" + videoType.join("|") + ")$", "i").test(name.toLowerCase())) {
            return 'video'
        }else if (RegExp("\.(" + textType.join("|") + ")$", "i").test(name.toLowerCase())) {
            return 'text'
        }else if (RegExp("\.(" + musicType.join("|") + ")$", "i").test(name.toLowerCase())) {
            return 'music'
        } else {
            return false
        }
    }
    function getFileIcon(fileType){
        switch(fileType) {
            case 'image':
                icon = 'image';
                break;
            case 'video':
                icon = 'ondemand_video';
                break;
            case 'music':
                icon = 'music_video';
                break;
            case 'text':
                icon = 'text_fields';
                break;
            default:
                icon = 'insert_drive_file';
                break;
        }
        return icon
    }
    function dpClose() {
        $('#dplayerContainer').remove();
        if (dp) {dp.destroy()}
    }
    function dpOpen(link) {
        $('#dplayerContainer').show();
        dp = new DPlayer({
            container: document.getElementById('dplayer'),
            autoplay: true,
            video: {
                url: link,
            },
        })
    }
    $('#btn').on('click', function(event) {
        event.preventDefault();
        $('#text-input').show();
        $('#close').show()
        $('#btn').hide()
    });
    $('#close').on('click', function(event) {
        event.preventDefault();
        $('#text-input').hide();
        $('#close').hide();
        $('#btn').show()
    });
    window.onload = view("name")
    </script>
</body>
</html>

2. jackjieYYY

最后如果我们只想显示网盘的某些文件夹,那么可以分别挂载该网盘的不同目录即可,具体操作看配置文件说明

本博客所有文章除特别声明外,均采用署名-非商业性使用-相同方式共享 4.0进行许可,仅供个人学习使用。
上一篇
下一篇