/* * fs.ts * Copyright (C) 2023 veypi * 2023-10-08 01:55 * Distributed under terms of the MIT license. */ import * as webdav from 'webdav' import { proxy } from "./v2dom"; import logic from "./logic"; export interface fileProps { filename: string, basename: string, lastmod: string, size: number, type: "directory" | "file", etag: string } function delay(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } class davWraper { private client: webdav.WebDAVClient private host: string private prefix: string private token: string constructor(host: string, prefix: string, token: string) { this.host = host this.prefix = prefix this.token = token this.client = webdav.createClient(host + prefix) if (this.prefix.endsWith('/')) { this.prefix = this.prefix.slice(0, -1) } } set(k: 'host' | 'token', value: string) { if (value !== this[k]) { this[k] = value if (k === 'token') { this.client.setHeaders({ authorization: "bearer " + value }) } else if (k === 'host') { this.client = webdav.createClient(this.host + this.prefix) } } } putFileContents(filename: string, data: string | webdav.BufferLike, options?: webdav.PutFileContentsOptions) { return this.retry(() => this.client.putFileContents(filename, data, options)) } getFileContents(filename: string, options?: webdav.GetFileContentsOptions) { return this.retry(() => this.client.getFileContents(filename, options)) } getDirectoryContents(path: string, options?: webdav.GetDirectoryContentsOptions) { return this.retry(() => this.client.getDirectoryContents(path, options)) } stat(path: string, options?: webdav.StatOptions) { return this.retry(() => this.client.stat(path, options)) } urlwrap(path: string) { if (path.startsWith('/')) { return this.prefix + path } else { return this.prefix + '/' + path } } urlunwrap(url: string) { if (url.startsWith(this.prefix)) { return url.slice(this.prefix.length) } return url } private retry(fn: () => Promise): Promise { let retries = 0; function attempt(): Promise { return fn().catch(error => { if (retries < 3) { retries++; console.log(`Attempt ${retries} failed, retrying after 1 second...`); return delay(1000).then(attempt); } else { // 超过最大重试次数后不再重试 throw error; } }) } return attempt() } } let token = logic.token.oa.raw() const user = new davWraper(logic.Host(), '/fs/u/', token) const app = new davWraper(logic.Host(), '/fs/a/', token) export const set_host = (h: string) => { user.set('host', h) app.set('host', h) } const sync = () => { if (logic.token.oa.isVaild()) { let t = logic.token.oa.raw() // console.warn('sync oafs token: ' + t) user.set('token', t) app.set('token', t) } } proxy.Listen(() => { sync() }) const rename = (o: string, n?: string) => { let ext = '.' + o.split('.').pop()?.toLowerCase() if (n) { return n + ext } const d = performance.now().toString(36); return d + ext } // const get = (url: string): Promise => { // return fetch(cfg.Host() + url, { headers: { authorization: "bearer " + cfg.oa_token.value } }).then((response) => response.text()) // } // rename 可以保持url不变 // const upload = (f: FileList | File[], dir?: string, renames?: string[]) => { // return new Promise((resolve, reject) => { // var data = new FormData(); // for (let i = 0; i < f.length; i++) { // let nf = new File([f[i]], rename(f[i].name, renames && renames[i] ? renames[i] : undefined), { type: f[i].type }) // data.append('files', nf, nf.name) // } // axios.post("/api/upload/" + (dir || ''), data, { // headers: { // "Content-Type": 'multipart/form-data', // 'auth_token': cfg.oa_token.value, // } // }).then(e => { // resolve(e.data) // }).catch(reject) // }) // } const get_dav = (client: webdav.WebDAVClient, base_url: string) => { return { client: client, stat: client.stat, dir: client.getDirectoryContents, uploadstr: (dir: string, name: string, data: string) => { if (dir.startsWith('/')) { dir = dir.slice(1) } return new Promise((resolve, reject) => { let temp = () => { let reader = new FileReader() reader.onload = function (event) { var res = event.target?.result // let data = new Blob([res]) client.putFileContents(dir + name, res).then(e => { if (e) { resolve(base_url + dir + name) } }).catch(reject) } reader.readAsArrayBuffer(new Blob([data], { type: 'plain/text' })) } client.stat(dir).then(() => { temp() }).catch((_) => { client.createDirectory(dir, { recursive: true }).then(() => { temp() }).catch(e => { console.warn(e) }) }) }); } } } export default { user, app, rename, }