diff --git a/app/components/Analysis/Card.vue b/app/components/Analysis/Card.vue index e776199..6b70720 100644 --- a/app/components/Analysis/Card.vue +++ b/app/components/Analysis/Card.vue @@ -25,7 +25,7 @@ const { data, status, error } = useFetch( const { data: verifiedAutomations } = useVerifiedAutomations(); -const verifiedAutomation = computed(() => { +const verifiedAutomation = computed(() => { return verifiedAutomations.value?.find((account) => { return ( account.username.toLowerCase() === username.value?.toLowerCase() || @@ -34,6 +34,14 @@ const verifiedAutomation = computed(() => { }); }); +const { data: integrations } = useIntegrations(); +const activityReport = computed(() => { + return integrations.value?.find((item) => { + return item.username.toLowerCase() === username.value?.toLowerCase(); + }); +}); + +const hasActivityReport = computed(() => !!activityReport.value); const hasCommunityFlag = computed(() => !!verifiedAutomation.value); const flagCreatedAt = computed(() => { @@ -70,14 +78,14 @@ const scoreStyle = computed(() => { }; } - if (classification.value === "organic") { + if (classification.value === "automation") { return { - text: "text-green-500", - border: "border-green-500", + text: "text-orange-500", + border: "border-orange-500", }; } - if (classification.value === "mixed") { + if (classification.value === "mixed" || hasActivityReport) { return { text: "text-amber-500", border: "border-amber-500", @@ -85,8 +93,8 @@ const scoreStyle = computed(() => { } return { - text: "text-orange-500", - border: "border-orange-500", + text: "text-green-500", + border: "border-green-500", }; }); @@ -213,7 +221,7 @@ useSeoAnalysis(identifyAnalysis, {

Activity Signals

@@ -229,6 +237,12 @@ useSeoAnalysis(identifyAnalysis, {

+ +
+const props = defineProps<{ + items: IntegrationItem[]; +}>(); + +const isDisclosureOpen = ref(false); +const counter = computed(() => { + return props.items.length; +}); + + + diff --git a/app/composables/useIntegrations.ts b/app/composables/useIntegrations.ts new file mode 100644 index 0000000..979798f --- /dev/null +++ b/app/composables/useIntegrations.ts @@ -0,0 +1,7 @@ +import type { IntegrationItem } from "~~/shared/types/integrations"; + +export function useIntegrations() { + return useLazyAsyncData("integrations", async () => { + return $fetch("/api/integration/unsafe-labs"); + }); +} diff --git a/server/api/integration/unsafe-labs.get.ts b/server/api/integration/unsafe-labs.get.ts new file mode 100644 index 0000000..17a955a --- /dev/null +++ b/server/api/integration/unsafe-labs.get.ts @@ -0,0 +1,43 @@ +import { Octokit } from "octokit"; +import dayjs from "dayjs"; +import type { IntegrationItem } from "~~/shared/types/integrations"; + +export type IntegrationUsafeLab = { + username: string; + total_prs: number; + first_pr: string; + last_pr: string; +}; + +export default defineEventHandler(async () => { + const config = useRuntimeConfig(); + const octokit = new Octokit({ auth: config.githubToken }); + + try { + const { data } = await octokit.rest.repos.getContent({ + owner: "UnsafeLabs", + repo: "Bounty-Hunters", + path: "clankers.json", + }); + + if ("content" in data) { + const content = Buffer.from(data.content, "base64").toString("utf-8"); + const integrationData = JSON.parse(content) as IntegrationUsafeLab[]; + return integrationData.map((d) => ({ + label: "UnsafeLabs Bounty Hunters", + username: d.username, + createdAt: d.first_pr, + reason: `This account appears in the UnsafeLabs bounty hunters database. Submitted a total of ${d.total_prs} PR${d.total_prs === 1 ? "" : "s"} to the project. Activity detected from ${dayjs(d.first_pr).format("MMM D, YYYY")} through ${dayjs(d.last_pr).format("MMM D, YYYY")}.`, + link: `https://github.com/UnsafeLabs/Bounty-Hunters/pulls?q=is%3Apr+author%3A${d.username}`, + })) satisfies IntegrationItem[]; + } + + return []; + } catch (error) { + throw createError({ + statusCode: 500, + message: "Failed to fetch integration list", + cause: error, + }); + } +}); diff --git a/shared/types/integrations.ts b/shared/types/integrations.ts new file mode 100644 index 0000000..7eaece0 --- /dev/null +++ b/shared/types/integrations.ts @@ -0,0 +1,7 @@ +export type IntegrationItem = { + label: string; + username: string; + createdAt?: string; + reason: string; + link: string; +};