mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 07:24:52 +09:00
Use config instead of constants, other review commetns
This commit is contained in:
1 parent
c6f10e2195
commit
25099c03ba
4 files changed
+35
-35
No files matched your search
@@ -524,7 +524,8 @@ export default class ControlConnection extends BaseConnection {
|
||||
const cacheKey = `${request.factorioVersion}-${request.hide_deprecated}`;
|
||||
const cachedData = this._controller.modPortalCache.get(cacheKey);
|
||||
|
||||
if (cachedData && Date.now() - cachedData.timestamp < Controller.MOD_PORTAL_CACHE_DURATION) {
|
||||
const cacheDuration = this._controller.config.get("controller.mod_portal_cache_duration_minutes") * 60 * 1000;
|
||||
if (cachedData && Date.now() - cachedData.timestamp < cacheDuration) {
|
||||
return new lib.ModPortalGetAllRequest.Response(cachedData.data);
|
||||
}
|
||||
|
||||
@@ -532,6 +533,7 @@ export default class ControlConnection extends BaseConnection {
|
||||
logger.info(`Fetching mod portal data for ${cacheKey}`);
|
||||
const mods = await lib.ModStore.fetchAllModsFromPortal(
|
||||
request.factorioVersion,
|
||||
this._controller.config.get("controller.mod_portal_page_size"),
|
||||
request.hide_deprecated
|
||||
);
|
||||
this._controller.modPortalCache.set(cacheKey, { timestamp: Date.now(), data: mods });
|
||||
@@ -555,7 +557,6 @@ export default class ControlConnection extends BaseConnection {
|
||||
// Check if mod already exists
|
||||
if (this._controller.modStore.files.has(filename)) {
|
||||
logger.verbose(`Mod ${filename} already exists, skipping download.`);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return this._controller.modStore.files.get(filename)!;
|
||||
}
|
||||
|
||||
@@ -564,11 +565,7 @@ export default class ControlConnection extends BaseConnection {
|
||||
const token = this._controller.config.get("controller.factorio_token");
|
||||
|
||||
if (!username || !token) {
|
||||
// Attempt download without credentials - might fail for some mods
|
||||
logger.warn(`Factorio username or token not configured. Attempting anonymous download for ${filename}.`);
|
||||
// Note: The Factorio Mod Portal API might reject downloads without credentials.
|
||||
// Consider throwing an error here if credentials are required by your setup.
|
||||
// throw new lib.RequestError("Factorio credentials (username, token) not configured on the controller.");
|
||||
throw new lib.RequestError("Factorio credentials (username, token) not configured on the controller.");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -97,12 +97,8 @@ export default class Controller {
|
||||
clusterLogBuildInterval: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
// Cache for mod portal requests
|
||||
static MOD_PORTAL_CACHE_DURATION = 30 * 60 * 1000; // 30 minutes
|
||||
modPortalCache = new Map<string, { timestamp: number, data: any[] }>();
|
||||
|
||||
/** @type {?module:lib.ProcessConnector} */
|
||||
process = null;
|
||||
|
||||
static async bootstrap(config: lib.ControllerConfig) {
|
||||
let databaseDirectory = config.get("controller.database_directory");
|
||||
await fs.ensureDir(databaseDirectory);
|
||||
|
||||
@@ -64,9 +64,6 @@ interface ModPortalResponse {
|
||||
results: ModDetails[];
|
||||
}
|
||||
|
||||
const MOD_PORTAL_API_URL = "https://mods.factorio.com/api/mods";
|
||||
const MOD_PORTAL_MAX_PAGE_SIZE = 1000; // Or largest allowed by API
|
||||
|
||||
export default class ModStore extends TypedEventEmitter<keyof ModStoreEvents, ModStoreEvents> {
|
||||
constructor(
|
||||
public modsDirectory: string,
|
||||
@@ -188,35 +185,33 @@ export default class ModStore extends TypedEventEmitter<keyof ModStoreEvents, Mo
|
||||
private async downloadModFromReleases(releases: Array<ModRelease>, version: string,
|
||||
username: string, token: string
|
||||
) {
|
||||
if (releases.length === 0) { return; }
|
||||
const selectedRelease = releases.find(release => release.version === version);
|
||||
|
||||
const latestRelease = releases.find(release => release.version === version);
|
||||
|
||||
if (latestRelease === undefined) {
|
||||
if (selectedRelease === undefined) {
|
||||
logger.warn(`Mod release matching version ${version} not found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(`https://mods.factorio.com/${latestRelease.download_url}`);
|
||||
const url = new URL(`https://mods.factorio.com/${selectedRelease.download_url}`);
|
||||
url.searchParams.set("username", username);
|
||||
url.searchParams.set("token", token);
|
||||
const tempFileName = `${this.modsDirectory}/${latestRelease.file_name}.tmp`;
|
||||
const finalFileName = `${this.modsDirectory}/${latestRelease.file_name}`;
|
||||
const tempFileName = `${this.modsDirectory}/${selectedRelease.file_name}.tmp`;
|
||||
const finalFileName = `${this.modsDirectory}/${selectedRelease.file_name}`;
|
||||
|
||||
await ModStore.downloadFile(url, tempFileName);
|
||||
await fs.rename(tempFileName, finalFileName);
|
||||
await this.loadFile(latestRelease.file_name);
|
||||
await this.loadFile(selectedRelease.file_name);
|
||||
|
||||
} catch (err: any) {
|
||||
logger.error(`Failed to download or load mod ${latestRelease.file_name} (${version}): ${err.message}`);
|
||||
logger.error(`Failed to download or load mod ${selectedRelease.file_name} (${version}): ${err.message}`);
|
||||
// Attempt to clean up temp file if it exists
|
||||
try {
|
||||
const tempFileName = `${this.modsDirectory}/${latestRelease.file_name}.tmp`;
|
||||
const tempFileName = `${this.modsDirectory}/${selectedRelease.file_name}.tmp`;
|
||||
await fs.unlink(tempFileName);
|
||||
} catch (unlinkErr: any) {
|
||||
if (unlinkErr.code !== "ENOENT") { // Ignore if file doesn't exist
|
||||
logger.warn(`Failed to clean up temp file ${latestRelease.file_name}.tmp: ${unlinkErr.message}`);
|
||||
logger.warn(`Failed to clean up temp file ${selectedRelease.file_name}.tmp: ${unlinkErr.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,11 +317,13 @@ export default class ModStore extends TypedEventEmitter<keyof ModStoreEvents, Mo
|
||||
* Handles pagination automatically to retrieve the complete list.
|
||||
*
|
||||
* @param factorioVersion - The Factorio version to fetch mods for (e.g., "1.1").
|
||||
* @param pageSize - The page size for fetching mods.
|
||||
* @param hide_deprecated - Whether to exclude deprecated mods.
|
||||
* @returns An array of mod details.
|
||||
*/
|
||||
static async fetchAllModsFromPortal(
|
||||
factorioVersion: string,
|
||||
pageSize: number,
|
||||
hide_deprecated: boolean = false
|
||||
): Promise<ModDetails[]> {
|
||||
logger.info(`Fetching all mods for Factorio version ${factorioVersion}...`);
|
||||
@@ -335,8 +332,8 @@ export default class ModStore extends TypedEventEmitter<keyof ModStoreEvents, Mo
|
||||
let hasMorePages = true;
|
||||
|
||||
while (hasMorePages) {
|
||||
const url = new URL(MOD_PORTAL_API_URL);
|
||||
url.searchParams.set("page_size", String(MOD_PORTAL_MAX_PAGE_SIZE));
|
||||
const url = new URL("https://mods.factorio.com/api/mods");
|
||||
url.searchParams.set("page_size", String(pageSize));
|
||||
url.searchParams.set("version", factorioVersion);
|
||||
url.searchParams.set("page", String(currentPage));
|
||||
url.searchParams.set("hide_deprecated", String(hide_deprecated));
|
||||
@@ -345,16 +342,12 @@ export default class ModStore extends TypedEventEmitter<keyof ModStoreEvents, Mo
|
||||
const response = await fetch(url.toString());
|
||||
|
||||
if (!response.ok) {
|
||||
let errorDetail = "";
|
||||
try {
|
||||
errorDetail = await response.text();
|
||||
} catch (bodyError) {
|
||||
logger.warn("Failed to read response body for failed portal request");
|
||||
}
|
||||
let errorMessage = `Mod portal fetch page ${currentPage} failed: `;
|
||||
errorMessage += `${response.status} ${response.statusText}`;
|
||||
if (errorDetail) {
|
||||
errorMessage += ` - ${errorDetail}`;
|
||||
try {
|
||||
errorMessage += ` - ${await response.text()}`;
|
||||
} catch (bodyError) {
|
||||
logger.warn("Failed to read response body for failed portal request");
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ export interface ControllerConfigFields {
|
||||
"controller.default_mod_pack_id": number | null;
|
||||
"controller.default_role_id": number | null;
|
||||
"controller.autosave_interval": number;
|
||||
"controller.mod_portal_cache_duration_minutes": number;
|
||||
"controller.mod_portal_page_size": number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,6 +199,18 @@ export class ControllerConfig extends classes.Config<ControllerConfigFields> {
|
||||
optional: true,
|
||||
initialValue: 1,
|
||||
},
|
||||
"controller.mod_portal_cache_duration_minutes": {
|
||||
title: "Mod Portal Cache Duration",
|
||||
description: "Duration in minutes to cache mod portal API responses.",
|
||||
type: "number",
|
||||
initialValue: 30,
|
||||
},
|
||||
"controller.mod_portal_page_size": {
|
||||
title: "Mod Portal Page Size",
|
||||
description: "Maximum number of results per page when querying the Factorio mod portal API.",
|
||||
type: "number",
|
||||
initialValue: 1000,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user