kopia lustrzana https://github.com/cloudflare/wildebeest
MOW-109: configure Cloudflare Images variants
rodzic
e5f86ee51a
commit
6f86378812
|
@ -45,6 +45,39 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
|
- name: Configure Cloudflare Images variants
|
||||||
|
run: |
|
||||||
|
curl -XPOST https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/images/v1/variants \
|
||||||
|
-d '{
|
||||||
|
"id": "avatar",
|
||||||
|
"options": {
|
||||||
|
"metadata": "copyright",
|
||||||
|
"width": 400,
|
||||||
|
"height": 400
|
||||||
|
}
|
||||||
|
}' \
|
||||||
|
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}'
|
||||||
|
|
||||||
|
curl -XPOST https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/images/v1/variants \
|
||||||
|
-d '{
|
||||||
|
"id": "header",
|
||||||
|
"options": {
|
||||||
|
"metadata": "copyright",
|
||||||
|
"width": 1500,
|
||||||
|
"height": 500
|
||||||
|
}
|
||||||
|
}' \
|
||||||
|
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}'
|
||||||
|
|
||||||
|
curl -XPOST https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/images/v1/variants \
|
||||||
|
-d '{
|
||||||
|
"id": "usercontent",
|
||||||
|
"options": {
|
||||||
|
"metadata": "copyright"
|
||||||
|
}
|
||||||
|
}' \
|
||||||
|
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}'
|
||||||
|
|
||||||
- name: Create D1 database
|
- name: Create D1 database
|
||||||
uses: cloudflare/wrangler-action@2.0.0
|
uses: cloudflare/wrangler-action@2.0.0
|
||||||
with:
|
with:
|
||||||
|
@ -192,7 +225,7 @@ jobs:
|
||||||
echo "******"
|
echo "******"
|
||||||
env:
|
env:
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||||
|
|
||||||
- name: Create Queue
|
- name: Create Queue
|
||||||
uses: cloudflare/wrangler-action@2.0.0
|
uses: cloudflare/wrangler-action@2.0.0
|
||||||
with:
|
with:
|
||||||
|
@ -227,7 +260,7 @@ jobs:
|
||||||
curl https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/pages/projects/wildebeest-${{ env.OWNER_LOWER }} \
|
curl https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/pages/projects/wildebeest-${{ env.OWNER_LOWER }} \
|
||||||
-XPATCH \
|
-XPATCH \
|
||||||
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}' \
|
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}' \
|
||||||
-d ' {
|
-d '{
|
||||||
"deployment_configs": {
|
"deployment_configs": {
|
||||||
"production": {
|
"production": {
|
||||||
"queue_producers": {
|
"queue_producers": {
|
||||||
|
|
|
@ -19,7 +19,15 @@ type UploadResult = {
|
||||||
uploaded: string
|
uploaded: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function uploadImage(file: File, config: Config): Promise<URL> {
|
// 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 formData = new FormData()
|
||||||
const url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/images/v1`
|
const url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/images/v1`
|
||||||
|
|
||||||
|
@ -43,7 +51,31 @@ export async function uploadImage(file: File, config: Config): Promise<URL> {
|
||||||
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
|
throw new Error(`Cloudflare Images returned ${res.status}: ${body}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We assume there's only one variant for now.
|
return data.result
|
||||||
const variant = data.result.variants[0]
|
}
|
||||||
return new URL(variant)
|
|
||||||
|
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(file: File, config: Config): Promise<URL> {
|
||||||
|
const result = await upload(file, config)
|
||||||
|
return selectVariant(result, USER_CONTENT_VARIANT)
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,10 @@ describe('Mastodon APIs', () => {
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
result: {
|
result: {
|
||||||
variants: ['https://example.com/' + file.name],
|
variants: [
|
||||||
|
'https://example.com/' + file.name + '/avatar',
|
||||||
|
'https://example.com/' + file.name + '/header',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -205,8 +208,8 @@ describe('Mastodon APIs', () => {
|
||||||
assert.equal(res.status, 200)
|
assert.equal(res.status, 200)
|
||||||
|
|
||||||
const data = await res.json<any>()
|
const data = await res.json<any>()
|
||||||
assert.equal(data.avatar, 'https://example.com/selfie.jpg')
|
assert.equal(data.avatar, 'https://example.com/selfie.jpg/avatar')
|
||||||
assert.equal(data.header, 'https://example.com/mountain.jpg')
|
assert.equal(data.header, 'https://example.com/mountain.jpg/header')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('get remote actor by id', async () => {
|
test('get remote actor by id', async () => {
|
||||||
|
|
|
@ -19,7 +19,7 @@ describe('Mastodon APIs', () => {
|
||||||
success: true,
|
success: true,
|
||||||
result: {
|
result: {
|
||||||
id: 'abcd',
|
id: 'abcd',
|
||||||
variants: ['https://example.com/' + file.name],
|
variants: ['https://example.com/' + file.name + '/usercontent'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -70,7 +70,7 @@ export async function handleRequest(
|
||||||
const value = formData.get('avatar')! as any
|
const value = formData.get('avatar')! as any
|
||||||
|
|
||||||
const config = { accountId, apiToken }
|
const config = { accountId, apiToken }
|
||||||
const url = await images.uploadImage(value, config)
|
const url = await images.uploadAvatar(value, config)
|
||||||
await updateActorProperty(db, connectedActor.id, 'icon.url', url.toString())
|
await updateActorProperty(db, connectedActor.id, 'icon.url', url.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ export async function handleRequest(
|
||||||
const value = formData.get('header')! as any
|
const value = formData.get('header')! as any
|
||||||
|
|
||||||
const config = { accountId, apiToken }
|
const config = { accountId, apiToken }
|
||||||
const url = await images.uploadImage(value, config)
|
const url = await images.uploadHeader(value, config)
|
||||||
await updateActorProperty(db, connectedActor.id, 'image.url', url.toString())
|
await updateActorProperty(db, connectedActor.id, 'image.url', url.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export async function handleRequest(
|
||||||
const file = formData.get('file')! as any
|
const file = formData.get('file')! as any
|
||||||
|
|
||||||
const config = { accountId, apiToken }
|
const config = { accountId, apiToken }
|
||||||
const url = await media.uploadImage(file, config)
|
const url = await media.uploadUserContent(file, config)
|
||||||
|
|
||||||
const properties = {
|
const properties = {
|
||||||
url,
|
url,
|
||||||
|
|
Ładowanie…
Reference in New Issue