diff --git a/README.md b/README.md new file mode 100644 index 0000000..4442241 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# contribapi + +tiny extensible api to merge contribution heatmap from forgejo (git.gay, codeberg, etc) +and github. + +## usage + +this runs as a cloudflare worker + +### configuration + +for testing, put these variables in `.dev.vars`. in production you will need to use wrangler +to update worker secrets with this command: + +```sh +pnpx wrangler secret put +# it will prompt you for value +``` + +**1. codeberg** + +codeberg (or forgejo in general) do not need api keys to get user heatmap. + +```env +CODEBERG_USERNAME=dragsbruh +``` + +**2. github** + +github needs an api key. i recommend you use a fine grained personal access token +with access to commit statuses of all repos. + +https://github.com/settings/personal-access-tokens + +```env +GITHUB_USERNAME=dragsbruh +GITHUB_TOKEN=github_pat_xxxxxxxxxx +``` + +**other forgejo instances** + +ill use [git.gay](https://git.gay) in this example + +- copy `src/forgejo.example.ts` to, `src/gitdotgay.ts` +- read comments in `src/gitdotgay.ts` and change as described, its like 4 changes +- read `queryForges` function in `src/index.ts` and add your query function as shown + +to remove github/etc, its the same, you just remove `queryGithub` + +### deploying + +```sh +pnpm deploy +``` diff --git a/src/codeberg.ts b/src/codeberg.ts index 4e31ce4..644e529 100644 --- a/src/codeberg.ts +++ b/src/codeberg.ts @@ -5,7 +5,7 @@ export const codebergResponse = z.array(daySchema); export async function queryCodeberg(env: Env): Promise<{ codeberg: Day[] }> { const response = await fetch( - `https://soxy.dragsbruh.workers.dev/?u=https://codeberg.org/api/v1/users/${env.CODEBERG_USERNAME}/heatmap`, + `https://codeberg.org/api/v1/users/${env.CODEBERG_USERNAME}/heatmap`, { headers: { "User-Agent": USER_AGENT, diff --git a/src/forgejo.example.ts b/src/forgejo.example.ts new file mode 100644 index 0000000..72bb175 --- /dev/null +++ b/src/forgejo.example.ts @@ -0,0 +1,20 @@ +import { z } from "zod"; +import { Day, daySchema, USER_AGENT } from "./common"; + +// CHANGE `forgejoResponse` +export const forgejoResponse = z.array(daySchema); + +// CHANGE `queryForgejo` AND `{ forgejo: Day[] }` +export async function queryForgejo(env: Env): Promise<{ forgejo: Day[] }> { + const response = await fetch( + // CHANGE `https://example.com` and `env.FORGEJO_USERNAME` + `https://example.com/api/v1/users/${env.FORGEJO_USERNAME}/heatmap`, + { + headers: { + "User-Agent": USER_AGENT, + }, + }, + ); + // CHANGE `forgejo:` and `forgejoResponse` + return { forgejo: forgejoResponse.parse(await response.json()) }; +} diff --git a/src/index.ts b/src/index.ts index dda11bc..d8d7ea0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,14 @@ const corsHeaders = { "Access-Control-Allow-Headers": "Content-Type", }; +function queryForges(env: Env) { + // CHANGE add/remove forges here + return [ + queryGithub(env), + queryCodeberg(env), + ]; +} + export default { async fetch(request, env): Promise { if (request.method === "OPTIONS") { @@ -17,7 +25,7 @@ export default { return new Response("OwO wutz that"); } - const responses = await Promise.all([queryGithub(env), queryCodeberg(env)]); + const responses = await Promise.all(queryForges(env)); const merged = Object.assign({}, ...responses); return Response.json(merged, {