You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/oaer/lib/fs.ts

181 lines
5.0 KiB
TypeScript

/*
* fs.ts
* Copyright (C) 2023 veypi <i@veypi.com>
* 2023-10-08 01:55
* Distributed under terms of the MIT license.
*/
import * as webdav from 'webdav'
export { type FileStat } from 'webdav'
import { proxy } from "./v2dom";
import logic from "./logic";
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(this.host + this.prefix)
this.set(host, prefix, token)
}
set(host: string, prefix: string, token: string) {
this.host = host
this.prefix = prefix
this.token = token
this.client = webdav.createClient(this.host + this.prefix)
if (this.prefix.endsWith('/')) {
this.prefix = this.prefix.slice(0, -1)
}
this.client.setHeaders({
authorization: "bearer " + this.token
})
}
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<T>(fn: () => Promise<T>): Promise<T> {
let retries = 0;
function attempt(): Promise<T> {
return fn().catch(error => {
console.log(error.status)
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/' + logic.oa_id, token)
const sync = () => {
if (logic.token.oa.isVaild()) {
let t = logic.token.oa.raw()
// console.warn('sync oafs token: ' + t)
user.set(logic.Host(), '/fs/u/', t)
app.set(logic.Host(), '/fs/a/' + logic.app_id, 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<string> => {
// 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<string[]>((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,
}