generated from nhcarrigan/template
feat: set up service to fetch comic data
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -40,3 +40,6 @@ testem.log
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# We upload this to our CDN.
|
||||
comics.json
|
||||
|
15
removeBadge.js
Normal file
15
removeBadge.js
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Run this in the Discord console to remove the bot badges from the app.
|
||||
* This is how we create the appearance that the webhook is a user.
|
||||
*/
|
||||
const appBadges = document.querySelectorAll("[class^='botTag']")
|
||||
for (const badge of appBadges) {
|
||||
badge.remove();
|
||||
}
|
75
src/app/comic-service.ts
Normal file
75
src/app/comic-service.ts
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
const oneDay = 1000 * 60 * 60 * 24;
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class ComicService {
|
||||
// eslint-disable-next-line @typescript-eslint/class-literal-property-style -- I should turn this rule off.
|
||||
private readonly comicsUrl: string = "https://cdn.yurigpt.com/comics.json";
|
||||
|
||||
private ttl = 0;
|
||||
|
||||
private comics: Array<{
|
||||
number: number;
|
||||
title: string;
|
||||
date: string;
|
||||
}> = [];
|
||||
|
||||
public constructor() {
|
||||
void this.loadComics();
|
||||
}
|
||||
private static isObject(object: unknown): object is Record<string, unknown> {
|
||||
return typeof object === "object" && object !== null;
|
||||
}
|
||||
|
||||
private static validateComics(
|
||||
comics: unknown,
|
||||
): comics is Array<{ number: number; title: string; date: string }> {
|
||||
if (!Array.isArray(comics)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return comics.every((comic) => {
|
||||
if (!ComicService.isObject(comic)) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
"number" in comic
|
||||
&& "title" in comic
|
||||
&& "date" in comic
|
||||
&& typeof comic["number"] === "number"
|
||||
&& typeof comic["title"] === "string"
|
||||
&& typeof comic["date"] === "string"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public async loadComics(): Promise<void> {
|
||||
if (this.ttl > Date.now()) {
|
||||
return;
|
||||
}
|
||||
this.comics = [];
|
||||
const response = await fetch(this.comicsUrl);
|
||||
const data: unknown = await response.json();
|
||||
if (ComicService.validateComics(data)) {
|
||||
this.comics = data.sort((a, b) => {
|
||||
return a.number - b.number;
|
||||
});
|
||||
this.ttl = Date.now() + oneDay;
|
||||
} else {
|
||||
console.error("Invalid comics data format:", data);
|
||||
}
|
||||
}
|
||||
|
||||
public getComics(): Array<{ number: number; title: string; date: string }> {
|
||||
return this.comics;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user