-
Notifications
You must be signed in to change notification settings - Fork 371
Expand file tree
/
Copy pathimage.ts
More file actions
96 lines (78 loc) · 2.48 KB
/
Copy pathimage.ts
File metadata and controls
96 lines (78 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
export type Config = {
accountId: string
apiToken: string
}
type APIResult<T> = {
success: boolean
errors: Array<any>
messages: Array<any>
result: T
}
type UploadResult = {
id: string
filename: string
metadata: object
requireSignedURLs: boolean
variants: Array<string>
uploaded: string
}
// https://docs.joinmastodon.org/user/profile/#avatar
const AVATAR_VARIANT = 'avatar'
// https://docs.joinmastodon.org/user/profile/#header
const HEADER_VARIANT = 'header'
const USER_CONTENT_VARIANT = 'usercontent'
async function upload(file: File, config: Config): Promise<UploadResult> {
const formData = new FormData()
const url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/images/v1`
formData.set('file', file)
const res = await fetch(url, {
method: 'POST',
body: formData,
headers: {
authorization: 'Bearer ' + config.apiToken,
},
})
if (!res.ok) {
const body = await res.text()
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
}
const data = await res.json<APIResult<UploadResult>>()
if (!data.success) {
const body = await res.text()
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
}
return data.result
}
function selectVariant(res: UploadResult, name: string): URL {
for (let i = 0, len = res.variants.length; i < len; i++) {
const variant = res.variants[i]
if (variant.endsWith(`/${name}`)) {
return new URL(variant)
}
}
throw new Error(`variant "${name}" not found`)
}
export async function uploadAvatar(file: File, config: Config): Promise<URL> {
const result = await upload(file, config)
return selectVariant(result, AVATAR_VARIANT)
}
export async function uploadHeader(file: File, config: Config): Promise<URL> {
const result = await upload(file, config)
return selectVariant(result, HEADER_VARIANT)
}
export async function uploadUserContent(request: Request, config: Config): Promise<URL> {
const url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/images/v1`
const newRequest = new Request(url, request)
newRequest.headers.set('authorization', 'Bearer ' + config.apiToken)
const res = await fetch(newRequest)
if (!res.ok) {
const body = await res.text()
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
}
const data = await res.json<APIResult<UploadResult>>()
if (!data.success) {
const body = await res.text()
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
}
return selectVariant(data.result, USER_CONTENT_VARIANT)
}