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

194 lines
5.1 KiB
TypeScript

4 weeks ago
/*
* 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'
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)
4 weeks ago
if (this.prefix.endsWith('/')) {
this.prefix = this.prefix.slice(0, -1)
}
4 weeks ago
}
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)
}
}
}
4 weeks ago
putFileContents(filename: string, data: string | webdav.BufferLike, options?: webdav.PutFileContentsOptions) {
4 weeks ago
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))
}
4 weeks ago
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
}
4 weeks ago
private retry<T>(fn: () => Promise<T>): Promise<T> {
let retries = 0;
function attempt(): Promise<T> {
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
}
4 weeks ago
const d = performance.now().toString(36);
return d + ext
4 weeks ago
}
// 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,
}