feat: add support for setting group icons in BlueBubbles, enhancing group management capabilities

This commit is contained in:
Tyler Yust
2026-01-20 00:34:59 -08:00
committed by Peter Steinberger
parent 574b848863
commit 14a072f5fa
18 changed files with 684 additions and 102 deletions

View File

@@ -181,6 +181,19 @@ async function sipsResizeToJpeg(params: {
});
}
async function sipsConvertToJpeg(buffer: Buffer): Promise<Buffer> {
return await withTempDir(async (dir) => {
const input = path.join(dir, "in.heic");
const output = path.join(dir, "out.jpg");
await fs.writeFile(input, buffer);
await runExec("/usr/bin/sips", ["-s", "format", "jpeg", input, "--out", output], {
timeoutMs: 20_000,
maxBuffer: 1024 * 1024,
});
return await fs.readFile(output);
});
}
export async function getImageMetadata(buffer: Buffer): Promise<ImageMetadata | null> {
if (prefersSips()) {
return await sipsMetadataFromBuffer(buffer).catch(() => null);
@@ -318,6 +331,14 @@ export async function resizeToJpeg(params: {
.toBuffer();
}
export async function convertHeicToJpeg(buffer: Buffer): Promise<Buffer> {
if (prefersSips()) {
return await sipsConvertToJpeg(buffer);
}
const sharp = await loadSharp();
return await sharp(buffer).jpeg({ quality: 90, mozjpeg: true }).toBuffer();
}
/**
* Internal sips-only EXIF normalization (no sharp fallback).
* Used by resizeToJpeg to normalize before sips resize.

View File

@@ -5,6 +5,8 @@ import { type MediaKind, mediaKindFromMime } from "./constants.js";
// Map common mimes to preferred file extensions.
const EXT_BY_MIME: Record<string, string> = {
"image/heic": ".heic",
"image/heif": ".heif",
"image/jpeg": ".jpg",
"image/png": ".png",
"image/webp": ".webp",
@@ -137,6 +139,10 @@ export function imageMimeFromFormat(format?: string | null): string | undefined
case "jpg":
case "jpeg":
return "image/jpeg";
case "heic":
return "image/heic";
case "heif":
return "image/heif";
case "png":
return "image/png";
case "webp":