返回

小雅网盘

   
摘要GPT
摘要小助理暂时失联跑路啦……😜

小雅网盘(基于alist)

网址:https://alist.xiaoya.pro/

alist文档:https://alist.nn.ci/zh//

小雅文档: https://xiaoyaliu.notion.site/xiaoya-docker-69404af849504fa5bcf9f2dd5ecaa75f

终端安装命令,端口 5678

bash -c "$(curl http://docker.xiaoya.pro/update_new.sh)"

或者 端口 6789

bash -c "$(curl http://docker.xiaoya.pro/update_new.sh)" -s host

阿里token获取地址:https://aliyuntoken.vercel.app/

阿里opentoken地址:https://alist.nn.ci/tool/aliyundrive/request.html

转存文件夹ID:网页版阿里云,进转存文件夹,地址栏内最后64开头的数字

创建一个名为 xiaoyakeeper 的docker定时运行小雅转存清理并升级小雅镜像

定时清理缓存

可以不加-tg

模式3:创建一个名为 xiaoyakeeper 的docker定时运行小雅转存清理并升级小雅镜像

bash -c "$(curl -s https://xiaoyahelper.zengge99.eu.org/aliyun_clear.sh | tail -n +2)" -s 3 -tg

模式5:与模式3的区别是实时清理,只要产生了播放缓存一分钟内立即清理。签到和定时升级同模式3

bash -c "$(curl -s https://xiaoyahelper.zengge99.eu.org/aliyun_clear.sh | tail -n +2)" -s 5 -tg

套娃挂载:

输入命令,获取令牌

docker exec -i xiaoya sqlite3 data/data.db <<EOF

select value from x_setting_items where key = "token";

EOF

挂载 :alist v3 输入令牌 输入链接 注意docker名称

同步小雅网盘

如果你是基于Linux系统的(包括openwrt),可以用以下方法设置定时更新,终端执行

crontab -e

添加一条记录

0 6 * * * docker restart xiaoya
  1. o 插入一行
  2. 然后把这堆文字输入进去
  3. 然后按键盘左上角 ESC键退出编辑模式
  4. 输入 :wq 保存退出

就是每天凌晨6点自动重启xiaoya docker去同步数据,你把6改成13,那就是下午1点

小雅CF反代

登录cloudflare,创建Worker 代码如下,修改const upstream_url = "alist地址";

免费地址寻找:网络空间雷达 复制ip

我的: xiaoya.taoshuge.eu.org

import { connect } from 'cloudflare:sockets';

  

const upstream_url = "http://183.134.157.38:5678";

  

const proxyList = ["mypikpak", "sharepoint"];

  

const replace_dict = {

  '$up_url': '$cust_url',

  '$upstream': '$custom_domain'

}

  

let up_scheme = upstream_url.split("://")[0]

let upstream = upstream_url.split("://")[1].split(":")[0];

let port_string = upstream_url.split("://")[1].split(":")[1];

if (!port_string) {

  port_string = up_scheme === "http" ? "80" : "443";

}

let port = parseInt(port_string);

const timeoutDuration = 5000;

const chunkSize = 1024 * 4;

  

export default {

  async fetch(request, env, ctx) {

    let url = new URL(request.url);

    let cust_url = new URL(request.url);

    url.port = port.toString();

    let original_url_hostname = url.hostname;

    url.hostname = upstream;

    url.protocol = up_scheme + ":";

  

    if (url.pathname.startsWith("/proxy/")) {

      let proxyUrl = new URL("https://" + url.pathname.replace(/\/proxy\//g, "") + url.search);

      let proxyReq = new Request(proxyUrl, request);

      let proxyResponse = await fetchOverTcp(proxyReq, 443);

      return proxyResponse;

    }

  

    let new_request = new Request(url, request);

    let original_response = await fetchOverTcp(new_request);

    let response_headers = original_response.headers;

    let new_response_headers = new Headers(response_headers);

  

    if (original_response.status === 302) {

      const locationHeader = new_response_headers.get('location');

      if (locationHeader && isReplace(locationHeader)) {

        const modifiedLocation = locationHeader.replace(/https:\/\/+/g, "https://" + original_url_hostname + "/proxy/");

        new_response_headers.set('location', modifiedLocation);

      }

    }

  

    const content_type = new_response_headers.get('content-type');

  

    if (url.pathname.includes("tvbox") || (content_type != null && (content_type.includes('text/html') || content_type.includes('json')) && (content_type.includes('UTF-8') || content_type.includes('utf-8')))) {

      let dic_def = {};

      dic_def["$upstream"] = upstream;

      dic_def["$custom_domain"] = original_url_hostname;

      dic_def["$cust_url"] = `${cust_url.protocol}//${cust_url.hostname}`;

      dic_def["$up_url"] = `${upstream_url}`;

      let original_text = replace_response_text(await original_response.text(), dic_def);

      let status = original_response.status;

      return new Response(original_text, {

        status,

        headers: new_response_headers

      });

    }

    else {

      return original_response;

    }

  },

};

  

async function fetchOverTcp(request, cust_port = null) {

  let url = new URL(request.url);

  let req = new Request(url, request);

  let out_port = cust_port ? cust_port : port

  if ((url.protocol === "https:" && out_port === 443) || (url.protocol === "http:" && out_port === 80)) {

    return await fetch(req);

  }

  

 

  let tcpSocket = connect({

    hostname: url.hostname,

    port: out_port,

  }, { secureTransport: "starttls" });

  

  if (url.protocol === "https:") {

    tcpSocket = tcpSocket.startTls();

  }

  

  try {

    const writer = tcpSocket.writable.getWriter();

  

    

    let headersString = '';

    let bodyString = '';

  

    for (let [name, value] of req.headers) {

      if (name === "host" || name === "x-forwarded-proto" || name === "x-real-ip" || name === "accept-encoding") {

        continue;

      }

      if (name === "connection") {

        value = "close";

      }

      headersString += `${name}: ${value}\r\n`;

    }

  

    let fullpath = url.pathname;

  

   

    if (url.search) {

      fullpath += url.search.replace(/%3F/g, "?");

    }

  

   

    if (req.method === "POST") {

      const body = await req.text();

      bodyString = `${body}`;

    }

  

   

    await writer.write(new TextEncoder().encode(`${req.method} ${fullpath} HTTP/1.0\r\nHost: ${url.hostname}:${port}\r\n${headersString}\r\n${bodyString}`));

    writer.releaseLock();

  

   

    const response = await constructHttpResponse(tcpSocket, timeoutDuration);

  

    return response;

  } catch (error) {

    tcpSocket.close();

    return new Response('Internal Server Error', { status: 500 });

  }

}

  

async function constructHttpResponse(tcpSocket, timeout) {

  const reader = tcpSocket.readable.getReader();

  let remainingData = new Uint8Array(0);

  try {

   

    while (true) {

      const { value, done } = await raceWithTimeout(reader.read(chunkSize), timeout);

      const newData = new Uint8Array(remainingData.length + value.length);

      newData.set(remainingData);

      newData.set(value, remainingData.length);

      remainingData = newData;

      const index = indexOfDoubleCRLF(remainingData);

      if (index !== -1) {

        const headerBytes = remainingData.subarray(0, index);

        const bodyBytes = remainingData.subarray(index + 4);

  

        const header = new TextDecoder().decode(headerBytes);

        const [statusLine, ...headers] = header.split('\r\n');

        const [httpVersion, statusCode, statusText] = statusLine.split(' ');

  

        

        const responseHeaders = {};

        headers.forEach((header) => {

          const [name, value] = header.split(': ');

          responseHeaders[name.toLowerCase()] = value;

        });

  

        responseHeaders['content-encoding'] = 'identity';

  

        const responseInit = {

          status: parseInt(statusCode),

          statusText,

          headers: new Headers(responseHeaders),

        };

  

        

        const bodyStream = new ReadableStream({

          async start(controller) {

            controller.enqueue(bodyBytes);

          },

          async pull(controller) {

            while (true) {

              try {

                const { value, done } = await raceWithTimeout(reader.read(chunkSize), timeout);

                if (value) {

                  controller.enqueue(value);

                }

                if (done) {

                  controller.close();

                  tcpSocket.close();

                  break;

                }

              } catch (e) {

                controller.close();

                tcpSocket.close();

                return;

              }

            }

          },

        });

  

        return new Response(bodyStream, responseInit);

      }

      if (done) {

        tcpSocket.close();

        break;

      }

    }

  

    return new Response();

  } catch (error) {

    tcpSocket.close();

  }

}

  

function raceWithTimeout(promise, timeout) {

  return Promise.race([

    promise,

    new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout-1')), timeout))

  ]);

}

  

function indexOfDoubleCRLF(data) {

  if (data.length < 4) {

    return -1;

  }

  for (let i = 0; i < data.length - 3; i++) {

    if (data[i] === 13 && data[i + 1] === 10 && data[i + 2] === 13 && data[i + 3] === 10) {

      return i;

    }

  }

  return -1;

}

  

function replace_response_text(text, dic_def) {

  var i, j;

  let new_replace_dict = {};

  for (i in replace_dict) {

    j = replace_dict[i]

    i = dic_def[i] ? dic_def[i] : i;

    j = dic_def[j] ? dic_def[j] : j;

    new_replace_dict[i] = j;

  }

  

  for (i in new_replace_dict) {

    j = new_replace_dict[i]

    let re = new RegExp(i, 'g')

    text = text.replace(re, j);

  }

  

  let host_name = dic_def["$custom_domain"];

  if (isReplace(text) && host_name) {

    text = text.replace(/https:\/\/+/g, "https://" + host_name + "/proxy/");

  }

  

  return text;

}

  

function isReplace(urlString) {

  for (let i = 0; i < proxyList.length; i++) {

    if (urlString.includes(proxyList[i])) {

      return true;

    }

  }

  return false;

}

其他内容扩充

  • 执行时机和清理缓存的操作是完全相同的。

  • 可以通过手动创建/etc/xiaoya/mycheckintoken.txt文件来定义多个网盘签到的32位refresh token,每行一个。若不添加文件,则使用默认小雅转存的网盘签到。

  • 自动刷新/etc/xiaoya/mycheckintoken.txt/etc/xiaoya/mytoken.txt文件,这有可能延长refresh token的时效,具体效果需要观察。

  • 定时运行模式包括:

    • 默认每天从运行脚本的下一分钟开始执行。
    • 运行时间可以通过手动创建/etc/xiaoya/myruntime.txt文件进行修改,例如06:00和18:00表示每天早晚6点各运行一次。
  • 自动升级的说明:

    • 定时升级的命令保存在/etc/xiaoya/mycmd.txt中。删除该文件将变成定时重启小雅。
    • 完成清理和签到后,脚本会自动执行/etc/xiaoya/mycmd.txt中的命令。该文件默认包含升级小雅镜像的命令,不建议修改。
  • 关于TG推送:

    • 所有模式加上-tg功能均可绑定消息推送的TG账号,只有第一次运行需要加上-tg参数。
知识共享许可证 CC BY-NC-SA 4.0
最后更新于 2024-06-15 18:08
使用 Hugo 构建
主题 hugo-magic小洋葱 魔改 由 Jimmy 设计
Written by Human, Not by AI