diff --git a/src/functions/http_sponsors.ts b/src/functions/http_sponsors.ts new file mode 100644 index 0000000..d00a486 --- /dev/null +++ b/src/functions/http_sponsors.ts @@ -0,0 +1,51 @@ +import { + app, + HttpRequest, + HttpResponseInit, + InvocationContext, +} from "@azure/functions"; +import { GitHubService } from "../services/GithubService"; + +export async function http_sponsors( + _: HttpRequest, + __: InvocationContext +): Promise { + let sponsors = []; + + const gitHubSponsors = await GitHubService.getSponsors(); + sponsors = [...gitHubSponsors]; + + const ocResponse = await fetch( + `https://opencollective.com/frontmatter/members.json` + ); + if (ocResponse && ocResponse.ok) { + const data = await ocResponse.json(); + sponsors = [ + ...sponsors, + ...data + .filter((s: any) => s.role === "BACKER" && s.isActive) + .map((s: any) => ({ + id: s.MemberId, + name: s.name, + url: s.website, + avatarUrl: s.image, + })), + ]; + } + + if (sponsors && sponsors.length > 0) { + return { + jsonBody: sponsors, + }; + } + + return { + jsonBody: null, + }; +} + +app.http("sponsors", { + methods: ["GET"], + authLevel: "anonymous", + handler: http_sponsors, +}); diff --git a/src/services/GithubService.ts b/src/services/GithubService.ts new file mode 100644 index 0000000..5dac04c --- /dev/null +++ b/src/services/GithubService.ts @@ -0,0 +1,91 @@ +export class GitHubService { + public static async verifyUser(token: string) { + if (!token) { + return; + } + + const username = await GitHubService.getUser(token); + if (!username) { + return; + } + + const sponsors = await GitHubService.getSponsors(); + const backers = (process.env.BACKERS || "").split(","); + + const sponsor = sponsors.find((s: any) => s.login === username); + + if (!backers?.includes(username) && !sponsor) { + return; + } + + return username; + } + + public static async getUser(token: string) { + const response = await fetch(`https://api.github.com/user`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) { + return; + } + + const data = await response.json(); + + return data.login; + } + + public static async getSponsors() { + const response = await fetch(`https://api.github.com/graphql`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `token ${process.env.GITHUB_AUTH}`, + }, + body: JSON.stringify({ + query: `query SponsorQuery { + viewer { + login + sponsors(first: 100) { + edges { + node { + ... on User { + id + name + login + url + avatarUrl + } + ... on Organization { + id + name + url + avatarUrl + } + } + } + } + } + }`, + }), + }); + + let sponsors = []; + + if (response && response.ok) { + const data = await response.json(); + sponsors = data.data.viewer.sponsors.edges.map((edge: any) => edge.node); + } + + if (sponsors && sponsors.length > 0) { + return sponsors; + } + + return []; + } +}