Skip to content

Commit 3a2bf7d

Browse files
committed
Copy avatar when duplicating NPC
1 parent e81b382 commit 3a2bf7d

File tree

3 files changed

+77
-33
lines changed

3 files changed

+77
-33
lines changed

functions/src/avatar.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {Bucket, CopyResponse, UploadResponse} from "@google-cloud/storage";
2+
3+
export const generateAvatarUrl = async (response: UploadResponse|CopyResponse, bucket: Bucket): Promise<string> => {
4+
if ("FIREBASE_STORAGE_EMULATOR_HOST" in process.env) {
5+
const [metadata] = await response[0].getMetadata();
6+
7+
return metadata.mediaLink;
8+
}
9+
10+
return "https://firebasestorage.googleapis.com/v0/b/"
11+
+ bucket.name
12+
+ "/o/"
13+
+ encodeURIComponent(response[0].name)
14+
+ "?alt=media"
15+
+ "&v="
16+
+ (+new Date());
17+
}
18+
19+
export const getAvatarPath = (partyId: string, characterId: string): string => `images/parties/${partyId}/characters/${characterId}.webp`;
20+
21+
export const METADATA = {
22+
contentType: "image/webp",
23+
cacheControl: `max-age=${365 * 24 * 60 * 60}`,
24+
};

functions/src/functions/changeCharacterAvatar.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import {storage} from 'firebase-admin';
22
import {file} from "tmp-promise";
33
import * as sharp from "sharp";
44
import * as t from "io-ts";
5-
import {UploadResponse} from "@google-cloud/storage/build/src/bucket";
6-
import {Bucket} from "@google-cloud/storage";
75
import {characterChange} from "../characterChange";
6+
import {generateAvatarUrl, getAvatarPath, METADATA} from "../avatar";
87

98
const imageSize = 500;
109

@@ -30,15 +29,12 @@ export const changeCharacterAvatar = characterChange(RequestBody,async (body, ch
3029
const response = await bucket.upload(
3130
tempFile.path,
3231
{
33-
destination: `images/parties/${partyId}/characters/${characterId}.webp`,
34-
metadata: {
35-
contentType: "image/webp",
36-
cacheControl: `max-age=${365 * 24 * 60 * 60}`,
37-
},
32+
destination: getAvatarPath(partyId, characterId),
33+
metadata: METADATA,
3834
}
3935
);
4036

41-
const url = generateAvatarUrl(response, bucket);
37+
const url = await generateAvatarUrl(response, bucket);
4238

4339
console.debug(`File url: ${url}`);
4440

@@ -71,17 +67,3 @@ const cropToRectangle = async (image: sharp.Sharp): Promise<sharp.Sharp> => {
7167
height: size,
7268
})
7369
}
74-
75-
const generateAvatarUrl = (response: UploadResponse, bucket: Bucket): string => {
76-
if ("FIREBASE_STORAGE_EMULATOR_HOST" in process.env) {
77-
return response[1].mediaLink;
78-
}
79-
80-
return "https://firebasestorage.googleapis.com/v0/b/"
81-
+ bucket.name
82-
+ "/o/"
83-
+ encodeURIComponent(response[0].name)
84-
+ "?alt=media"
85-
+ "&v="
86-
+ (+new Date());
87-
}

functions/src/functions/duplicateCharacter.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1-
import {firestore} from 'firebase-admin';
1+
import {firestore, storage} from 'firebase-admin';
22
import * as t from "io-ts";
33
import {characterChange} from "../characterChange";
44
import { v4 as uuidv4 } from "uuid";
5+
import {generateAvatarUrl, getAvatarPath, METADATA} from "../avatar";
56

67
const RequestBody = t.interface({
78
partyId: t.string,
89
characterId: t.string,
910
newName: t.string,
1011
});
1112

13+
type Character = {
14+
avatarUrl: string | null;
15+
}
16+
1217
export const duplicateCharacter = characterChange(RequestBody, async (body, character) => {
1318
const batch = firestore().batch();
1419
const newCharacterId = uuidv4();
1520
const newCharacter = character.parent.doc(newCharacterId);
16-
const characterData = (await character.get()).data();
17-
18-
batch.set(
19-
newCharacter,
20-
{
21-
...characterData,
22-
id: newCharacterId,
23-
name: body.newName,
24-
}
25-
)
21+
const characterData = (await character.get()).data() as Character;
22+
23+
const newCharacterData = {
24+
...characterData,
25+
id: newCharacterId,
26+
name: body.newName,
27+
avatarUrl: await copyAvatar(characterData.avatarUrl, body.partyId, body.characterId, newCharacterId),
28+
};
29+
30+
console.log("New character data", newCharacterData);
31+
32+
batch.set(newCharacter, newCharacterData);
2633

2734
const collections = await character.listCollections();
2835

@@ -45,3 +52,34 @@ export const duplicateCharacter = characterChange(RequestBody, async (body, char
4552
status: "success",
4653
};
4754
})
55+
56+
const copyAvatar = async (
57+
avatarUrl: string | null,
58+
partyId: string,
59+
characterId: string,
60+
newCharacterId: string,
61+
): Promise<string | null> => {
62+
if (avatarUrl === null) {
63+
return null;
64+
}
65+
66+
const bucket = storage().bucket();
67+
68+
try {
69+
const sourceFile = bucket.file(getAvatarPath(partyId, characterId));
70+
71+
if (!(await sourceFile.exists())[0]) {
72+
return null;
73+
}
74+
75+
const copyResponse = await sourceFile.copy(
76+
bucket.file(getAvatarPath(partyId, newCharacterId)),
77+
{metadata: METADATA}
78+
);
79+
80+
return await generateAvatarUrl(copyResponse, bucket);
81+
} catch (e) {
82+
console.error(e);
83+
return null;
84+
}
85+
}

0 commit comments

Comments
 (0)