MLE: Force PNG
This commit is contained in:
parent
9621aa2224
commit
bdff0818e1
5 changed files with 27 additions and 162 deletions
|
|
@ -10,11 +10,9 @@ import path from "node:path";
|
|||
import { DATA_DIR } from "@main/utils/constants";
|
||||
import { dialog, IpcMainInvokeEvent, shell } from "electron";
|
||||
|
||||
import { getSettings, saveSettings } from "./settings";
|
||||
export * from "./updater";
|
||||
|
||||
import { LoggedAttachment } from "../types";
|
||||
import { LOGS_DATA_FILENAME } from "../utils/constants";
|
||||
import { getSettings, saveSettings } from "./settings";
|
||||
import { ensureDirectoryExists, getAttachmentIdFromFilename, sleep } from "./utils";
|
||||
|
||||
export { getSettings };
|
||||
|
|
@ -72,11 +70,12 @@ export async function writeImageNative(_event: IpcMainInvokeEvent, filename: str
|
|||
// returns the file name
|
||||
// ../../someMalicousPath.png -> someMalicousPath
|
||||
const attachmentId = getAttachmentIdFromFilename(filename);
|
||||
const safeName = `${attachmentId}.png`;
|
||||
|
||||
const existingImage = nativeSavedImages.get(attachmentId);
|
||||
if (existingImage) return;
|
||||
|
||||
const imagePath = path.join(imageDir, filename);
|
||||
const imagePath = path.join(imageDir, safeName);
|
||||
await ensureDirectoryExists(imageDir);
|
||||
await writeFile(imagePath, content);
|
||||
|
||||
|
|
@ -145,23 +144,23 @@ export async function chooseFile(_event: IpcMainInvokeEvent, title: string, filt
|
|||
|
||||
// doing it in native because you can only fetch images from the renderer
|
||||
// other types of files will cause cors issues
|
||||
export async function downloadAttachment(_event: IpcMainInvokeEvent, attachemnt: LoggedAttachment, attempts = 0, useOldUrl = false): Promise<{ error: string | null; path: string | null; }> {
|
||||
export async function downloadAttachment(_event: IpcMainInvokeEvent, attachment: LoggedAttachment, attempts = 0, useOldUrl = false): Promise<{ error: string | null; path: string | null; }> {
|
||||
try {
|
||||
if (!attachemnt?.url || !attachemnt.oldUrl || !attachemnt?.id || !attachemnt?.fileExtension)
|
||||
if (!attachment?.url || !attachment.oldUrl || !attachment?.id || !attachment?.fileExtension)
|
||||
return { error: "Invalid Attachment", path: null };
|
||||
|
||||
if (attachemnt.id.match(/[\\/.]/)) {
|
||||
if (attachment.id.match(/[\\/.]/)) {
|
||||
return { error: "Invalid Attachment ID", path: null };
|
||||
}
|
||||
|
||||
const existingImage = nativeSavedImages.get(attachemnt.id);
|
||||
const existingImage = nativeSavedImages.get(attachment.id);
|
||||
if (existingImage)
|
||||
return {
|
||||
error: null,
|
||||
path: existingImage
|
||||
};
|
||||
|
||||
const res = await fetch(useOldUrl ? attachemnt.oldUrl : attachemnt.url);
|
||||
const res = await fetch(useOldUrl ? attachment.oldUrl : attachment.url);
|
||||
|
||||
if (res.status !== 200) {
|
||||
if (res.status === 404 || res.status === 403 || res.status === 415)
|
||||
|
|
@ -170,23 +169,23 @@ export async function downloadAttachment(_event: IpcMainInvokeEvent, attachemnt:
|
|||
attempts++;
|
||||
if (attempts > 3) {
|
||||
return {
|
||||
error: `Failed to get attachment ${attachemnt.id} for caching. too many attempts, error code ${res.status}`,
|
||||
error: `Failed to get attachment ${attachment.id} for caching. too many attempts, error code ${res.status}`,
|
||||
path: null,
|
||||
};
|
||||
}
|
||||
|
||||
await sleep(1000);
|
||||
return downloadAttachment(_event, attachemnt, attempts, useOldUrl);
|
||||
return downloadAttachment(_event, attachment, attempts, useOldUrl);
|
||||
}
|
||||
|
||||
const ab = await res.arrayBuffer();
|
||||
const imageCacheDir = await getImageCacheDir();
|
||||
await ensureDirectoryExists(imageCacheDir);
|
||||
|
||||
const finalPath = path.join(imageCacheDir, `${attachemnt.id}${attachemnt.fileExtension}`);
|
||||
const finalPath = path.join(imageCacheDir, `${attachment.id}.png`);
|
||||
await writeFile(finalPath, Buffer.from(ab));
|
||||
|
||||
nativeSavedImages.set(attachemnt.id, finalPath);
|
||||
nativeSavedImages.set(attachment.id, finalPath);
|
||||
|
||||
return {
|
||||
error: null,
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { execFile as cpExecFile, ExecFileOptions } from "node:child_process";
|
||||
|
||||
import { readdir } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { promisify } from "util";
|
||||
|
||||
import type { GitResult } from "../types";
|
||||
import { memoize } from "../utils/memoize";
|
||||
|
||||
const execFile = promisify(cpExecFile);
|
||||
|
||||
const isFlatpak = process.platform === "linux" && Boolean(process.env.FLATPAK_ID?.includes("discordapp") || process.env.FLATPAK_ID?.includes("Discord"));
|
||||
if (process.platform === "darwin") process.env.PATH = `/usr/local/bin:${process.env.PATH}`;
|
||||
|
||||
|
||||
const VENCORD_USER_PLUGIN_DIR = join(__dirname, "..", "src", "userplugins");
|
||||
const getCwd = memoize(async () => {
|
||||
const dirs = await readdir(VENCORD_USER_PLUGIN_DIR, { withFileTypes: true });
|
||||
|
||||
for (const dir of dirs) {
|
||||
if (!dir.isDirectory()) continue;
|
||||
|
||||
const pluginDir = join(VENCORD_USER_PLUGIN_DIR, dir.name);
|
||||
const files = await readdir(pluginDir);
|
||||
|
||||
if (files.includes("LoggedMessageManager.ts")) return join(VENCORD_USER_PLUGIN_DIR, dir.name);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
|
||||
async function git(...args: string[]): Promise<GitResult> {
|
||||
const opts: ExecFileOptions = { cwd: await getCwd(), shell: true };
|
||||
|
||||
try {
|
||||
let result;
|
||||
if (isFlatpak) {
|
||||
result = await execFile("flatpak-spawn", ["--host", "git", ...args], opts);
|
||||
} else {
|
||||
result = await execFile("git", args, opts);
|
||||
}
|
||||
|
||||
return { value: result.stdout.trim(), stderr: result.stderr, ok: true };
|
||||
} catch (error: any) {
|
||||
return {
|
||||
ok: false,
|
||||
cmd: error.cmd as string,
|
||||
message: error.stderr as string,
|
||||
error
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function update() {
|
||||
return await git("pull");
|
||||
}
|
||||
|
||||
export async function getCommitHash() {
|
||||
return await git("rev-parse", "HEAD");
|
||||
}
|
||||
|
||||
export interface GitInfo {
|
||||
repo: string;
|
||||
gitHash: string;
|
||||
}
|
||||
|
||||
export async function getRepoInfo(): Promise<GitResult> {
|
||||
const res = await git("remote", "get-url", "origin");
|
||||
if (!res.ok) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const gitHash = await getCommitHash();
|
||||
if (!gitHash.ok) {
|
||||
return gitHash;
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
value: {
|
||||
repo: res.value
|
||||
.replace(/git@(.+):/, "https://$1/")
|
||||
.replace(/\.git$/, ""),
|
||||
gitHash: gitHash.value
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export interface Commit {
|
||||
hash: string;
|
||||
longHash: string;
|
||||
message: string;
|
||||
author: string;
|
||||
}
|
||||
|
||||
export async function getNewCommits(): Promise<GitResult> {
|
||||
const branch = await git("branch", "--show-current");
|
||||
if (!branch.ok) {
|
||||
return branch;
|
||||
}
|
||||
|
||||
const logFormat = "%H;%an;%s";
|
||||
const branchRange = `HEAD..origin/${branch.value}`;
|
||||
|
||||
try {
|
||||
await git("fetch");
|
||||
|
||||
const logOutput = await git("log", `--format="${logFormat}"`, branchRange);
|
||||
|
||||
if (!logOutput.ok) {
|
||||
return logOutput;
|
||||
}
|
||||
|
||||
if (logOutput.value.trim() === "") {
|
||||
return { ok: true, value: [] };
|
||||
}
|
||||
|
||||
const commitLines = logOutput.value.trim().split("\n");
|
||||
const commits: Commit[] = commitLines.map(line => {
|
||||
const [hash, author, ...rest] = line.split(";");
|
||||
return { longHash: hash, hash: hash.slice(0, 7), author, message: rest.join(";") } satisfies Commit;
|
||||
});
|
||||
|
||||
return { ok: true, value: commits };
|
||||
} catch (error: any) {
|
||||
return { ok: false, cmd: error.cmd, message: error.message, error };
|
||||
}
|
||||
}
|
||||
|
|
@ -25,4 +25,8 @@ export function getAttachmentIdFromFilename(filename: string) {
|
|||
return path.parse(filename).name;
|
||||
}
|
||||
|
||||
export function getAttachmentExtFromFilename(filename: string) {
|
||||
return path.parse(filename).ext;
|
||||
}
|
||||
|
||||
export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
|
|||
|
|
@ -158,10 +158,6 @@ export function getNative(): PluginNative<typeof import("../native")> {
|
|||
messageLoggerEnhancedUniqueIdThingyIdkMan: async () => { },
|
||||
showItemInFolder: async () => { },
|
||||
writeImageNative: async () => { },
|
||||
getCommitHash: async () => ({ ok: true, value: "" }),
|
||||
getRepoInfo: async () => ({ ok: true, value: { repo: "", gitHash: "" } }),
|
||||
getNewCommits: async () => ({ ok: true, value: [] }),
|
||||
update: async () => ({ ok: true, value: "" }),
|
||||
chooseFile: async () => "",
|
||||
downloadAttachment: async () => ({ error: "web", path: null }),
|
||||
} satisfies PluginNative<typeof import("../native")>;
|
||||
|
|
|
|||
|
|
@ -60,12 +60,12 @@ export async function getImage(attachmentId: string, fileExt?: string | null): P
|
|||
return await Native.getImageNative(attachmentId);
|
||||
}
|
||||
|
||||
export async function downloadAttachment(attachemnt: LoggedAttachment): Promise<string | undefined> {
|
||||
export async function downloadAttachment(attachment: LoggedAttachment): Promise<string | undefined> {
|
||||
if (IS_WEB) {
|
||||
return await downloadAttachmentWeb(attachemnt);
|
||||
return await downloadAttachmentWeb(attachment);
|
||||
}
|
||||
|
||||
const { path, error } = await Native.downloadAttachment(attachemnt);
|
||||
const { path, error } = await Native.downloadAttachment(attachment);
|
||||
|
||||
if (error || !path) {
|
||||
Flogger.error("Failed to download attachment", error, path);
|
||||
|
|
@ -87,31 +87,31 @@ export async function deleteImage(attachmentId: string): Promise<void> {
|
|||
}
|
||||
|
||||
|
||||
async function downloadAttachmentWeb(attachemnt: LoggedAttachment, attempts = 0) {
|
||||
if (!attachemnt?.url || !attachemnt?.id || !attachemnt?.fileExtension) {
|
||||
Flogger.error("Invalid attachment", attachemnt);
|
||||
async function downloadAttachmentWeb(attachment: LoggedAttachment, attempts = 0) {
|
||||
if (!attachment?.url || !attachment?.id || !attachment?.fileExtension) {
|
||||
Flogger.error("Invalid attachment", attachment);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch(attachemnt.url);
|
||||
const res = await fetch(attachment.url);
|
||||
if (res.status !== 200) {
|
||||
if (res.status === 404 || res.status === 403) return;
|
||||
attempts++;
|
||||
if (attempts > 3) {
|
||||
Flogger.warn(`Failed to get attachment ${attachemnt.id} for caching, error code ${res.status}`);
|
||||
Flogger.warn(`Failed to get attachment ${attachment.id} for caching, error code ${res.status}`);
|
||||
return;
|
||||
}
|
||||
|
||||
await sleep(1000);
|
||||
return downloadAttachmentWeb(attachemnt, attempts);
|
||||
return downloadAttachmentWeb(attachment, attempts);
|
||||
}
|
||||
const ab = await res.arrayBuffer();
|
||||
const path = `${DEFAULT_IMAGE_CACHE_DIR}/${attachemnt.id}${attachemnt.fileExtension}`;
|
||||
const path = `${DEFAULT_IMAGE_CACHE_DIR}/${attachment.id}${attachment.fileExtension}`;
|
||||
|
||||
// await writeImage(imageCacheDir, `${attachmentId}${fileExtension}`, new Uint8Array(ab));
|
||||
|
||||
await set(path, new Uint8Array(ab), ImageStore);
|
||||
idbSavedImages.set(attachemnt.id, { attachmentId: attachemnt.id, path });
|
||||
idbSavedImages.set(attachment.id, { attachmentId: attachment.id, path });
|
||||
|
||||
return path;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue