* Retrieve a file from the local filesystem * @returns {Promise } Resolved with file content or null on error
()
| 207 | * @returns {Promise<string|null>} Resolved with file content or null on error |
| 208 | */ |
| 209 | async loadComplimentFile () { |
| 210 | const { remoteFile, remoteFileRefreshInterval } = this.config; |
| 211 | const isRemote = remoteFile.startsWith("http://") || remoteFile.startsWith("https://"); |
| 212 | let url = isRemote ? remoteFile : this.file(remoteFile); |
| 213 | |
| 214 | try { |
| 215 | // Validate URL |
| 216 | const urlObj = new URL(url); |
| 217 | // Add cache-busting parameter to remote URLs to prevent cached responses |
| 218 | if (isRemote && remoteFileRefreshInterval !== 0) { |
| 219 | urlObj.searchParams.set("dummy", Date.now()); |
| 220 | } |
| 221 | url = urlObj.toString(); |
| 222 | } catch { |
| 223 | Log.warn(`[compliments] Invalid URL: ${url}`); |
| 224 | } |
| 225 | |
| 226 | try { |
| 227 | const response = await fetch(url); |
| 228 | if (!response.ok) { |
| 229 | Log.error(`[compliments] HTTP error: ${response.status} ${response.statusText}`); |
| 230 | return null; |
| 231 | } |
| 232 | return await response.text(); |
| 233 | } catch (error) { |
| 234 | Log.info("[compliments] fetch failed:", error.message); |
| 235 | return null; |
| 236 | } |
| 237 | }, |
| 238 | |
| 239 | /** |
| 240 | * Retrieve a random compliment. |