diff --git a/scripts/actions/event.ts b/scripts/actions/event.ts new file mode 100644 index 0000000..67cc463 --- /dev/null +++ b/scripts/actions/event.ts @@ -0,0 +1,20 @@ +export interface IEvent { + name: string; + date: string; + location: string; + img: string; + link: string; +} + +export function fetchEvent(existingEvent: IEvent[]): IEvent[] { + const events = [...existingEvent]; + + for (const event of events) { + const index = events.findIndex((x) => x.name === event.name); + if (index === -1) { + events.push(event); + } + } + + return events; +} \ No newline at end of file diff --git a/scripts/actions/fetch-projects-by-topic.ts b/scripts/actions/fetch-projects-by-topic.ts index 8e7084f..fc3e5f7 100644 --- a/scripts/actions/fetch-projects-by-topic.ts +++ b/scripts/actions/fetch-projects-by-topic.ts @@ -1,10 +1,14 @@ import fs from 'fs' -import path from 'path' import process from 'node:process' +import path from 'path' import { fileURLToPath } from 'url' const defaultTopicName = 'bangkok-open-source' +interface Language { + [key: string]: number; +} + const __dirname = path.dirname(fileURLToPath(import.meta.url)) const filePath = path.resolve(__dirname, '../../src/content/ring.generated.json') @@ -37,16 +41,30 @@ async function fetchPagedProjects( page = 1, perPage = 100 ): Promise { - const url = new URL('https://api.github.com/search/repositories') - url.searchParams.set('q', query) - url.searchParams.set('page', `${page}`) - url.searchParams.set('per_page', `${perPage}`) + const url = new URL('https://api.github.com/search/repositories'); + url.searchParams.set('q', query); + url.searchParams.set('page', `${page}`); + url.searchParams.set('per_page', `${perPage}`); - const resp = await fetch(url) + const resp = await fetch(url); if (!resp.ok) { - throw new Error(`Failed to fetch paged projects: ${resp.status} ${await resp.text()}`) + throw new Error(`Failed to fetch paged projects: ${resp.status} ${await resp.text()}`); } - return (await resp.json()) as SearchRepositoriesResponse + const result = (await resp.json()) as SearchRepositoriesResponse; + + // Fetch languages for each repository + const repositoriesWithLanguages = await Promise.all( + result.items.map(async (repo) => { + const languagesResp = await fetch(repo.languages_url); + if (!languagesResp.ok) { + throw new Error(`Failed to fetch languages for ${repo.full_name}`); + } + const languages: Language = await languagesResp.json(); + return { ...repo, languages: Object.keys(languages) }; + }) + ); + + return { ...result, items: repositoriesWithLanguages }; } function saveProjectsToJSON(projects: Project[]) { @@ -64,14 +82,15 @@ function saveProjectsToJSON(projects: Project[]) { async function main() { const topicName = process.argv[2] || defaultTopicName const topicLimit = Number(process.argv[3] ?? 1000) - const repositories = await fetchProjects(topicName, topicLimit) - // TODO: should be nice to have repo's languages from Repository.languages_url not just Repository.language + const repositories = await fetchProjects(topicName, topicLimit); + const projects = repositories.map((repo) => ({ name: repo.name, repo: repo.html_url, description: repo.description, - languages: [repo.language] - })) + languages: [repo.language], + languages_url: repo.languages_url + })); saveProjectsToJSON(projects) } @@ -175,5 +194,6 @@ interface Project { name: string repo: string description: string - languages: string[] + languages?: string[] + languages_url?: string } diff --git a/scripts/actions/project.ts b/scripts/actions/project.ts new file mode 100644 index 0000000..d0c1b0c --- /dev/null +++ b/scripts/actions/project.ts @@ -0,0 +1,27 @@ +export interface IProject { + name: string; + repo: string; + description: string; + languages?: string[]; +} + +export function fetchProjects(existingProjects: IProject[], newProjects: IProject[]): IProject[] { + const projects = [...existingProjects]; + + for (const project of newProjects) { + const index = projects.findIndex((x) => x.name === project.name); + if (index === -1) { + projects.push(project); + } + } + + return projects; +} + +export function shuffleProject(array: T[]): T[] { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + ;[array[i], array[j]] = [array[j], array[i]] + } + return array +} \ No newline at end of file diff --git a/src/components/CardLink.astro b/src/components/CardLink.astro index d422b47..1f2dd25 100644 --- a/src/components/CardLink.astro +++ b/src/components/CardLink.astro @@ -11,7 +11,10 @@ const { title, url, description, languages = [] } = Astro.props diff --git a/src/content/ring.generated.json b/src/content/ring.generated.json index 1690a97..8298be5 100644 --- a/src/content/ring.generated.json +++ b/src/content/ring.generated.json @@ -6,7 +6,8 @@ "description": "A client-side secure P2P file sharing using WebRTC.", "languages": [ "Svelte" - ] + ], + "languages_url": "https://api.github.com/repos/ntsd/zero-share/languages" } ] } \ No newline at end of file diff --git a/src/content/ring.json b/src/content/ring.json index 6351d3b..c6559f7 100644 --- a/src/content/ring.json +++ b/src/content/ring.json @@ -384,6 +384,7 @@ "languages": [ "JavaScript", "Discord.js" + ] }, { "name": "Arcade Game", @@ -397,6 +398,7 @@ "Socket-io", "Mqtt.js", "Mongoose" + ] }, { "name": "Bad Boyz", diff --git a/src/pages/index.astro b/src/pages/index.astro index 44f076b..2bf0846 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -6,33 +6,11 @@ import events from '../content/events.json' import sponsors from '../content/sponsors.json' import CardLink from '../components/CardLink.astro' import EventCard from '../components/EventCard.astro' +import { fetchProjects, shuffleProject } from '../../scripts/actions/project' +import { fetchEvent } from '../../scripts/actions/event' -// TODO: refactor dedupe logic to separate file? -// TODO: limit projects in index page -const projects = [...ring.projects] -for (const project of generatedRing.projects as typeof ring.projects) { - const index = projects.findIndex((x) => x.name === project.name) - if (index === -1) { - projects.push(project) - } -} - -function shuffle(array: T[]): T[] { - for (let i = array.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)) - ;[array[i], array[j]] = [array[j], array[i]] - } - return array -} - -const event = [...events.events] - .filter((x, i, a) => a.findIndex((y) => y.name === x.name) === i) - .sort((a, b) => { - const aDate = new Date(a.date) - const bDate = new Date(b.date) - return aDate.getTime() - bDate.getTime() - }) - .slice(0, 6) // Add this line to limit to 6 events +const projects = fetchProjects([...ring.projects], [...generatedRing.projects]) +const event = fetchEvent([...events.events]) --- @@ -48,10 +26,16 @@ const event = [...events.events]

1. Write code 💻

{ - shuffle(projects) + shuffleProject(projects) .slice(0, 6) - .map((x) => { - return + .map((project) => { + return ( + + ) }) }
@@ -63,8 +47,8 @@ const event = [...events.events]

2. Join events 🙌

{ - event.map((x) => { - return + event.map((event) => { + return }) }
diff --git a/src/pages/ring.astro b/src/pages/ring.astro index f5350d0..c75016e 100644 --- a/src/pages/ring.astro +++ b/src/pages/ring.astro @@ -3,15 +3,9 @@ import BaseLayout from '../layouts/BaseLayout.astro' import ring from '../content/ring.json' import generatedRing from '../content/ring.generated.json' import CardLink from '../components/CardLink.astro' +import { fetchProjects } from '../../scripts/actions/project' -// TODO: refactor dedupe logic to separate file? -const projects = [...ring.projects] -for (const project of generatedRing.projects as typeof ring.projects) { - const index = projects.findIndex((x) => x.name === project.name) - if (index === -1) { - projects.push(project) - } -} +const projects = fetchProjects([...ring.projects], [...generatedRing.projects]) ---