diff --git a/src/server/api/routers/icon.ts b/src/server/api/routers/icon.ts index f53800d17..a5b6c2493 100644 --- a/src/server/api/routers/icon.ts +++ b/src/server/api/routers/icon.ts @@ -1,6 +1,7 @@ import { JsdelivrIconsRepository } from '~/tools/server/images/jsdelivr-icons-repository'; import { LocalIconsRepository } from '~/tools/server/images/local-icons-repository'; import { UnpkgIconsRepository } from '~/tools/server/images/unpkg-icons-repository'; +import { GitHubIconsRepository } from '~/tools/server/images/github-icons-repository'; import { createTRPCRouter, publicProcedure } from '../trpc'; @@ -8,8 +9,8 @@ export const iconRouter = createTRPCRouter({ all: publicProcedure.query(async () => { const respositories = [ new LocalIconsRepository(), - new JsdelivrIconsRepository( - JsdelivrIconsRepository.tablerRepository, + new GitHubIconsRepository( + GitHubIconsRepository.walkxcode, 'Walkxcode Dashboard Icons', 'Walkxcode on Github' ), diff --git a/src/tools/server/images/github-icons-repository.ts b/src/tools/server/images/github-icons-repository.ts new file mode 100644 index 000000000..2abb07d06 --- /dev/null +++ b/src/tools/server/images/github-icons-repository.ts @@ -0,0 +1,75 @@ +import { + AbstractIconRepository, + NormalizedIcon, + NormalizedIconRepositoryResult, +} from './abstract-icons-repository'; + +export class GitHubIconsRepository extends AbstractIconRepository { + static readonly walkxcode = { + api: 'https://api.github.com/repos/walkxcode/dashboard-icons/git/trees/main?recursive=true', + blob: 'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/{0}/{1}', + } as GitHubRepositoryUrl; + + constructor( + private readonly repository: GitHubRepositoryUrl, + private readonly displayName: string, + copyright: string + ) { + super(copyright); + } + + protected async fetchInternally(): Promise { + const response = await fetch(this.repository.api); + const body = (await response.json()) as GitHubRepo; + + const normalizedEntries = body.tree + .filter((file) => !['_banner.png', '_logo.png'].some((x) => file.path.includes(x))) + .filter((file) => ['.png', '.svg'].some((x) => file.path.endsWith(x))) + .map((file): NormalizedIcon => { + const fileNameParts = file.path.split('/'); + const fileName = fileNameParts[fileNameParts.length - 1]; + const extensions = fileName.split('.')[1]; + return { + url: this.repository.blob.replace('{0}', extensions).replace('{1}', fileName), + name: fileName, + size: file.size ?? 0, + }; + }); + + return { + entries: normalizedEntries, + count: normalizedEntries.length, + success: true, + name: this.displayName, + copyright: this.copyright, + }; + } +} + +type GitHubRepositoryUrl = { + api: string; + blob: string; +}; + +// Generated by https://quicktype.io + +export interface GitHubRepo { + sha: string; + url: string; + tree: Tree[]; + truncated: boolean; +} + +export interface Tree { + path: string; + mode: string; + type: Type; + sha: string; + url: string; + size?: number; +} + +export enum Type { + Blob = 'blob', + Tree = 'tree', +} diff --git a/src/tools/server/images/jsdelivr-icons-repository.ts b/src/tools/server/images/jsdelivr-icons-repository.ts index acce25790..737b1faa1 100644 --- a/src/tools/server/images/jsdelivr-icons-repository.ts +++ b/src/tools/server/images/jsdelivr-icons-repository.ts @@ -5,11 +5,6 @@ import { } from './abstract-icons-repository'; export class JsdelivrIconsRepository extends AbstractIconRepository { - static readonly tablerRepository = { - api: 'https://data.jsdelivr.com/v1/packages/gh/walkxcode/dashboard-icons@main?structure=flat', - blob: 'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/{0}/{1}', - } as JsdelivrRepositoryUrl; - static readonly papirusRepository = { api: 'https://data.jsdelivr.com/v1/packages/gh/PapirusDevelopmentTeam/papirus_icons@master?structure=flat', blob: 'https://cdn.jsdelivr.net/gh/PapirusDevelopmentTeam/papirus_icons/src/{1}', @@ -33,7 +28,7 @@ export class JsdelivrIconsRepository extends AbstractIconRepository { const body = (await response.json()) as JsdelivrResponse; const normalizedEntries = body.files - .filter((file) => !['_banner.png', '_logo.png'].some((x) => file.name.includes(x))) + .filter((file) => !['banner.png', 'logo.png'].some((x) => file.name.includes(x))) .filter((file) => ['.png', '.svg'].some((x) => file.name.endsWith(x))) .map((file): NormalizedIcon => { const fileNameParts = file.name.split('/');