fetch repos locally

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-03-30 19:14:29 +02:00
parent a12b3ae671
commit 7105f2a5b2
8 changed files with 937 additions and 349 deletions

View File

@@ -1,14 +1,22 @@
---
import type { GiteaRepoWithMirrors } from "../lib/gitea";
import { getBannerUrl } from "../lib/gitea";
import { ExternalLink, ChevronDown } from "@lucide/astro";
interface Props {
repo: GiteaRepoWithMirrors;
repo: {
name: string;
description: string;
html_url: string;
website: string;
topics: string[];
banner_url: string;
mirrors: {
github?: string;
gitlab?: string;
};
};
}
const { repo } = Astro.props;
const bannerUrl = getBannerUrl(repo);
const platforms = [
...(repo.mirrors.github ? [{ label: "GitHub", url: repo.mirrors.github }] : []),
@@ -24,7 +32,7 @@ const hasMultiplePlatforms = platforms.length > 1;
>
<figure class="aspect-video bg-base-200 overflow-hidden">
<img
src={bannerUrl}
src={repo.banner_url}
alt={repo.name}
class="w-full h-full object-cover"
onerror="this.parentElement.style.display='none'"

View File

@@ -1,10 +1,9 @@
---
import GiteaProjectCard from "./GiteaProjectCard.astro";
import { ArrowRight } from "@lucide/astro";
import { fetchGiteaRepos } from "../lib/gitea";
import repos from "../data/repos.json";
const repos = await fetchGiteaRepos();
const latestRepos = repos.slice(0, 3); // 3 plus récents sur la homepage
const latestRepos = repos.slice(0, 3);
---
<section id="projects" class="py-20 px-4">

431
src/data/repos.json Normal file
View File

@@ -0,0 +1,431 @@
[
{
"id": 2,
"owner": {
"id": 1,
"login": "anotherhadi",
"login_name": "",
"source_id": 0,
"full_name": "Hadi",
"email": "anotherhadi@noreply.git.hadi.icu",
"avatar_url": "https://git.hadi.icu/avatars/a6f9dd8586f079ec7619ade21789a3c5dad02d7869f74a3cca0c976c81b8c9ae",
"html_url": "https://git.hadi.icu/anotherhadi",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-03-30T17:21:50+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "127.0.0.1",
"website": "https://hadi.icu",
"description": "Infosec engineer passionate about Linux/NixOS, blockchains, OSINT & FOSS. Hacking with Go, exploring open tech, and contributing whenever I can 🐧\r\n\r\n[Github](https://github.com/anotherhadi) | [Gitlab (mirror)](https://gitlab.com/anotherhadi)",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "anotherhadi"
},
"name": "default-creds",
"full_name": "anotherhadi/default-creds",
"description": "Default Creds is a centralized, community-driven repository of factory-set credentials. Designed for pentesters and security researchers, it helps identify weak access points during engagement phases or audit internal infrastructure before they become a security liability.",
"empty": false,
"private": false,
"fork": false,
"template": false,
"mirror": true,
"size": 505,
"language": "Nix",
"languages_url": "https://git.hadi.icu/api/v1/repos/anotherhadi/default-creds/languages",
"html_url": "https://git.hadi.icu/anotherhadi/default-creds",
"url": "https://git.hadi.icu/api/v1/repos/anotherhadi/default-creds",
"link": "",
"ssh_url": "gitea@git.hadi.icu:anotherhadi/default-creds.git",
"clone_url": "https://git.hadi.icu/anotherhadi/default-creds.git",
"original_url": "https://github.com/anotherhadi/default-creds",
"website": "https://default-creds.hadi.icu",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "main",
"archived": false,
"created_at": "2026-03-30T17:33:14+02:00",
"updated_at": "2026-03-30T18:24:55+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": false,
"push": false,
"pull": true
},
"has_code": true,
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": false,
"has_projects": true,
"projects_mode": "all",
"has_releases": true,
"has_packages": true,
"has_actions": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": false,
"allow_rebase": false,
"allow_rebase_explicit": false,
"allow_squash_merge": false,
"allow_fast_forward_only_merge": false,
"allow_rebase_update": false,
"allow_manual_merge": true,
"autodetect_manual_merge": false,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "https://git.hadi.icu/repo-avatars/ca9c61caff75a89dcc15461d13c6ce6aa5289366a8aae70d12a64987b29a88c8",
"internal": false,
"mirror_interval": "8h0m0s",
"object_format_name": "sha1",
"mirror_updated": "2026-03-30T18:26:10+02:00",
"topics": [
"cybersecurity",
"cybersecurity-tools",
"default-password",
"pentesting"
],
"licenses": [
"MIT"
],
"mirrors": {
"github": "https://github.com/anotherhadi/default-creds"
},
"banner_url": "https://git.hadi.icu/anotherhadi/default-creds/raw/branch/main/.github/assets/banner.png"
},
{
"id": 3,
"owner": {
"id": 1,
"login": "anotherhadi",
"login_name": "",
"source_id": 0,
"full_name": "Hadi",
"email": "anotherhadi@noreply.git.hadi.icu",
"avatar_url": "https://git.hadi.icu/avatars/a6f9dd8586f079ec7619ade21789a3c5dad02d7869f74a3cca0c976c81b8c9ae",
"html_url": "https://git.hadi.icu/anotherhadi",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-03-30T17:21:50+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "127.0.0.1",
"website": "https://hadi.icu",
"description": "Infosec engineer passionate about Linux/NixOS, blockchains, OSINT & FOSS. Hacking with Go, exploring open tech, and contributing whenever I can 🐧\r\n\r\n[Github](https://github.com/anotherhadi) | [Gitlab (mirror)](https://gitlab.com/anotherhadi)",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "anotherhadi"
},
"name": "blog",
"full_name": "anotherhadi/blog",
"description": "Thoughts, insights, and tutorials on cybersecurity, OSINT, and technology.",
"empty": false,
"private": false,
"fork": false,
"template": false,
"mirror": true,
"size": 2639,
"language": "Nix",
"languages_url": "https://git.hadi.icu/api/v1/repos/anotherhadi/blog/languages",
"html_url": "https://git.hadi.icu/anotherhadi/blog",
"url": "https://git.hadi.icu/api/v1/repos/anotherhadi/blog",
"link": "",
"ssh_url": "gitea@git.hadi.icu:anotherhadi/blog.git",
"clone_url": "https://git.hadi.icu/anotherhadi/blog.git",
"original_url": "https://github.com/anotherhadi/blog",
"website": "https://hadi.icu",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "main",
"archived": false,
"created_at": "2026-03-30T17:39:47+02:00",
"updated_at": "2026-03-30T18:23:24+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": false,
"push": false,
"pull": true
},
"has_code": true,
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": false,
"has_projects": true,
"projects_mode": "all",
"has_releases": true,
"has_packages": true,
"has_actions": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": false,
"allow_rebase": false,
"allow_rebase_explicit": false,
"allow_squash_merge": false,
"allow_fast_forward_only_merge": false,
"allow_rebase_update": false,
"allow_manual_merge": true,
"autodetect_manual_merge": false,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "https://git.hadi.icu/repo-avatars/527f936266a33d3ccfe22013ef2ca0f61e20a4941912b16e4b4e9dcb14bf4e30",
"internal": false,
"mirror_interval": "8h0m0s",
"object_format_name": "sha1",
"mirror_updated": "2026-03-30T18:25:47+02:00",
"topics": [
"blog",
"cybersecurity",
"portfolio"
],
"licenses": [
"MIT"
],
"mirrors": {
"github": "https://github.com/anotherhadi/blog"
},
"banner_url": "https://git.hadi.icu/anotherhadi/blog/raw/branch/main/.github/assets/banner.png"
},
{
"id": 1,
"owner": {
"id": 1,
"login": "anotherhadi",
"login_name": "",
"source_id": 0,
"full_name": "Hadi",
"email": "anotherhadi@noreply.git.hadi.icu",
"avatar_url": "https://git.hadi.icu/avatars/a6f9dd8586f079ec7619ade21789a3c5dad02d7869f74a3cca0c976c81b8c9ae",
"html_url": "https://git.hadi.icu/anotherhadi",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-03-30T17:21:50+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "127.0.0.1",
"website": "https://hadi.icu",
"description": "Infosec engineer passionate about Linux/NixOS, blockchains, OSINT & FOSS. Hacking with Go, exploring open tech, and contributing whenever I can 🐧\r\n\r\n[Github](https://github.com/anotherhadi) | [Gitlab (mirror)](https://gitlab.com/anotherhadi)",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "anotherhadi"
},
"name": "nixy",
"full_name": "anotherhadi/nixy",
"description": "Nixy simplifies and unifies the Hyprland ecosystem with a modular, easily customizable setup. It provides a structured way to manage your system configuration and dotfiles with minimal effort.",
"empty": false,
"private": false,
"fork": false,
"template": false,
"mirror": true,
"size": 429471,
"language": "Nix",
"languages_url": "https://git.hadi.icu/api/v1/repos/anotherhadi/nixy/languages",
"html_url": "https://git.hadi.icu/anotherhadi/nixy",
"url": "https://git.hadi.icu/api/v1/repos/anotherhadi/nixy",
"link": "",
"ssh_url": "gitea@git.hadi.icu:anotherhadi/nixy.git",
"clone_url": "https://git.hadi.icu/anotherhadi/nixy.git",
"original_url": "https://github.com/anotherhadi/nixy",
"website": "",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "main",
"archived": false,
"created_at": "2026-03-30T17:31:04+02:00",
"updated_at": "2026-03-30T18:05:44+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": false,
"push": false,
"pull": true
},
"has_code": true,
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": false,
"has_projects": true,
"projects_mode": "all",
"has_releases": true,
"has_packages": true,
"has_actions": false,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": false,
"allow_rebase": false,
"allow_rebase_explicit": false,
"allow_squash_merge": false,
"allow_fast_forward_only_merge": false,
"allow_rebase_update": false,
"allow_manual_merge": true,
"autodetect_manual_merge": false,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "https://git.hadi.icu/repo-avatars/b232b4486d5397e743db2fe6b581d2fa4eb4d41d5bbe2c8f1dbafd6021b352b0",
"internal": false,
"mirror_interval": "8h0m0s",
"object_format_name": "sha1",
"mirror_updated": "2026-03-30T18:05:56+02:00",
"topics": [
"caelestia",
"caelestia-shell",
"configuration",
"dotfiles",
"hacktoberfest",
"home-manager",
"hypridle",
"hyprland",
"hyprland-config",
"hyprlock",
"hyprpaper",
"kitty",
"nix",
"nixos",
"nixos-configuration",
"nixvim",
"rice",
"server",
"sops"
],
"licenses": [
"MIT"
],
"mirrors": {
"github": "https://github.com/anotherhadi/nixy"
},
"banner_url": "https://git.hadi.icu/anotherhadi/nixy/raw/branch/main/.github/assets/banner.png"
},
{
"id": 4,
"owner": {
"id": 1,
"login": "anotherhadi",
"login_name": "",
"source_id": 0,
"full_name": "Hadi",
"email": "anotherhadi@noreply.git.hadi.icu",
"avatar_url": "https://git.hadi.icu/avatars/a6f9dd8586f079ec7619ade21789a3c5dad02d7869f74a3cca0c976c81b8c9ae",
"html_url": "https://git.hadi.icu/anotherhadi",
"language": "",
"is_admin": false,
"last_login": "0001-01-01T00:00:00Z",
"created": "2026-03-30T17:21:50+02:00",
"restricted": false,
"active": false,
"prohibit_login": false,
"location": "127.0.0.1",
"website": "https://hadi.icu",
"description": "Infosec engineer passionate about Linux/NixOS, blockchains, OSINT & FOSS. Hacking with Go, exploring open tech, and contributing whenever I can 🐧\r\n\r\n[Github](https://github.com/anotherhadi) | [Gitlab (mirror)](https://gitlab.com/anotherhadi)",
"visibility": "public",
"followers_count": 0,
"following_count": 0,
"starred_repos_count": 0,
"username": "anotherhadi"
},
"name": "eleakxir",
"full_name": "anotherhadi/eleakxir",
"description": "Self-hosted search engine for leaked data. An OSINT tool that lets you connect to your own private and secure server, and visualize results in a clean, modern web interface.",
"empty": false,
"private": false,
"fork": false,
"template": false,
"mirror": false,
"size": 664,
"language": "Svelte",
"languages_url": "https://git.hadi.icu/api/v1/repos/anotherhadi/eleakxir/languages",
"html_url": "https://git.hadi.icu/anotherhadi/eleakxir",
"url": "https://git.hadi.icu/api/v1/repos/anotherhadi/eleakxir",
"link": "",
"ssh_url": "gitea@git.hadi.icu:anotherhadi/eleakxir.git",
"clone_url": "https://git.hadi.icu/anotherhadi/eleakxir.git",
"original_url": "",
"website": "https://eleakxir.hadi.icu",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 0,
"open_pr_counter": 0,
"release_counter": 0,
"default_branch": "main",
"archived": false,
"created_at": "2026-03-30T17:42:13+02:00",
"updated_at": "2026-03-30T17:45:56+02:00",
"archived_at": "1970-01-01T01:00:00+01:00",
"permissions": {
"admin": false,
"push": false,
"pull": true
},
"has_code": true,
"has_issues": true,
"internal_tracker": {
"enable_time_tracker": true,
"allow_only_contributors_to_track_time": true,
"enable_issue_dependencies": true
},
"has_wiki": true,
"has_pull_requests": true,
"has_projects": true,
"projects_mode": "all",
"has_releases": true,
"has_packages": true,
"has_actions": true,
"ignore_whitespace_conflicts": false,
"allow_merge_commits": true,
"allow_rebase": true,
"allow_rebase_explicit": true,
"allow_squash_merge": true,
"allow_fast_forward_only_merge": true,
"allow_rebase_update": true,
"allow_manual_merge": false,
"autodetect_manual_merge": false,
"default_delete_branch_after_merge": false,
"default_merge_style": "merge",
"default_allow_maintainer_edit": false,
"avatar_url": "https://git.hadi.icu/repo-avatars/fe3f6d37cea3ee37b7dbb9fb6bfadc59fdb6b8f7a357b4245ec6d35ef6a84b3d",
"internal": false,
"mirror_interval": "",
"object_format_name": "sha1",
"mirror_updated": "0001-01-01T00:00:00Z",
"topics": [],
"licenses": [],
"mirrors": {},
"banner_url": "https://git.hadi.icu/anotherhadi/eleakxir/raw/branch/main/.github/assets/banner.png"
}
]

View File

@@ -1,79 +0,0 @@
export interface GiteaRepo {
id: number;
name: string;
full_name: string;
description: string;
html_url: string;
updated_at: string;
topics: string[];
stars_count: number;
language: string | null;
fork: boolean;
private: boolean;
website: string;
}
export interface RepoMirrors {
github?: string;
gitlab?: string;
}
export interface GiteaRepoWithMirrors extends GiteaRepo {
mirrors: RepoMirrors;
}
const GITEA_BASE = "https://git.hadi.icu";
const GITEA_USER = "anotherhadi";
const GITHUB_USER = "anotherhadi";
const GITLAB_USER = "anotherhadi";
async function checkMirrors(repoName: string): Promise<RepoMirrors> {
const mirrors: RepoMirrors = {};
const [githubRes, gitlabRes] = await Promise.allSettled([
fetch(`https://github.com/${GITHUB_USER}/${repoName}`, { method: "HEAD" }),
fetch(`https://gitlab.com/${GITLAB_USER}/${repoName}`, { method: "HEAD" }),
]);
if (githubRes.status === "fulfilled" && githubRes.value.ok) {
mirrors.github = `https://github.com/${GITHUB_USER}/${repoName}`;
}
if (gitlabRes.status === "fulfilled" && gitlabRes.value.ok) {
mirrors.gitlab = `https://gitlab.com/${GITLAB_USER}/${repoName}`;
}
return mirrors;
}
export async function fetchGiteaRepos(): Promise<GiteaRepoWithMirrors[]> {
try {
const res = await fetch(
`${GITEA_BASE}/api/v1/users/${GITEA_USER}/repos?limit=50&page=1`
);
if (!res.ok) throw new Error(`Gitea API: ${res.status}`);
const repos: GiteaRepo[] = await res.json();
const filtered = repos
.filter((r) => !r.fork && !r.private)
.sort(
(a, b) =>
new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
);
const reposWithMirrors = await Promise.all(
filtered.map(async (repo) => ({
...repo,
mirrors: await checkMirrors(repo.name),
}))
);
return reposWithMirrors;
} catch (e) {
console.error("Failed to fetch Gitea repos:", e);
return [];
}
}
export function getBannerUrl(repo: GiteaRepo): string {
return `${GITEA_BASE}/${repo.full_name}/raw/branch/main/.github/assets/banner.png`;
}

View File

@@ -2,9 +2,8 @@
import Layout from "../../layouts/Layout.astro";
import GiteaProjectCard from "../../components/GiteaProjectCard.astro";
import { ChevronLeft } from "@lucide/astro";
import { fetchGiteaRepos } from "../../lib/gitea";
const repos = await fetchGiteaRepos();
import repos from "../../data/repos.json";
---
<Layout