Skip to content

Commit

Permalink
Merge pull request #108 from Giveth/develop
Browse files Browse the repository at this point in the history
Staging to main
  • Loading branch information
MohammadPCh authored Aug 28, 2024
2 parents 5b76cc2 + 968cb33 commit 0f2ae5d
Show file tree
Hide file tree
Showing 21 changed files with 253 additions and 85 deletions.
13 changes: 13 additions & 0 deletions db/migrations/1724279465327-Data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = class Data1724279465327 {
name = "Data1724279465327";

async up(db) {
await db.query(`ALTER TABLE "project" DROP COLUMN "source_status"`);
await db.query(`ALTER TABLE "project" ADD "rf_rounds" integer array`);
}

async down(db) {
await db.query(`ALTER TABLE "project" DROP COLUMN "rf_rounds"`);
await db.query(`ALTER TABLE "project" ADD "source_status" text`);
}
};
4 changes: 2 additions & 2 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ type Project @entity {
url: String
"Image of the project"
image: String
"Project status at the source. e.g. Keeped, Removed, Missing in rf4"
sourceStatus: String
"project data is imported from a source or not"
imported: Boolean! @index
lastUpdatedTimestamp: DateTime!
attests: [ProjectAttestation!]! @derivedFrom(field: "project")
attestedOrganisations: [OrganisationProject!]! @derivedFrom(field: "project")
"Rounds in which the project is included"
rfRounds: [Int!]
}

type OrganisationProject @entity {
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ export const IMPORT_PROJECT_CRON_SCHEDULE =
export const DESCRIPTION_SUMMARY_LENGTH = Number(
process.env.DESCRIPTION_SUMMARY_LENGTH || 300
);

export const AGORA_API_KEY = process.env.AGORA_API_KEY;
14 changes: 9 additions & 5 deletions src/controllers/projectVerificationAttestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ export const handleProjectAttestation = async (

ctx.log.debug(`Processing project attestation with uid: ${uid}`);

const project = await getProject(
ctx,
projectVerificationAttestation.projectSource,
projectVerificationAttestation.projectId
);
let projectId = projectVerificationAttestation.projectId;
let projectSource = projectVerificationAttestation.projectSource;

if (projectVerificationAttestation.projectSource === "rf4") {
projectId = projectVerificationAttestation.projectId.replace("rf4-", "rf-");
projectSource = "rf";
}

const project = await getProject(ctx, projectSource, projectId);

// Delete the previous attestation
await removeDuplicateProjectAttestations(
Expand Down
12 changes: 7 additions & 5 deletions src/features/import-projects/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const updateOrCreateProject = async (
descriptionHtmlField,
urlField,
imageField,
sourceStatusField,
rfRoundField,
} = sourConfig;

const projectId = project[idField].toLowerCase();
Expand All @@ -42,15 +42,15 @@ export const updateOrCreateProject = async (
const url = project[urlField];
const image = project[imageField];
const descriptionHtml = descriptionHtmlField && project[descriptionHtmlField];
const sourceStatus = sourceStatusField && project[sourceStatusField];
const rfRound = rfRoundField && project[rfRoundField];

if (existingProject) {
const isUpdated =
existingProject.title !== title ||
existingProject.description !== description ||
existingProject.url !== url ||
existingProject.image !== image ||
existingProject.sourceStatus !== sourceStatus ||
(rfRound && !existingProject.rfRounds?.some((rfr) => rfr === rfRound)) ||
existingProject.descriptionHtml !== descriptionHtml ||
(!existingProject.descriptionSummary && description);

Expand All @@ -59,6 +59,8 @@ export const updateOrCreateProject = async (
);

if (isUpdated) {
const rfRounds = new Set(existingProject.rfRounds || []);
rfRound && rfRounds.add(rfRound);
const updatedProject = new Project({
...existingProject,
title,
Expand All @@ -67,8 +69,8 @@ export const updateOrCreateProject = async (
url,
descriptionHtml,
descriptionSummary,
sourceStatus,
lastUpdatedTimestamp: new Date(),
rfRounds: Array.from(rfRounds),
imported: true,
});

Expand Down Expand Up @@ -97,7 +99,7 @@ export const updateOrCreateProject = async (
descriptionSummary,
projectId,
source,
sourceStatus,
rfRounds: rfRound ? [rfRound] : [],
totalVouches: 0,
totalFlags: 0,
totalAttests: 0,
Expand Down
11 changes: 7 additions & 4 deletions src/features/import-projects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ import { IMPORT_PROJECT_CRON_SCHEDULE } from "../../constants";
import { fetchAndProcessGivethProjects } from "./giveth/index";
import { fetchAndProcessRpgf3Projects } from "./rpgf";
import { fetchAndProcessGitcoinProjects } from "./gitcoin";
import { fetchAndProcessRf4Projects } from "./rf4";
import { fetchRFProjectsByRound } from "./rf";
import { fetchAndProcessRlProjects } from "./retroList";

export const task = async () => {
console.log("Importing Projects", new Date());
fetchAndProcessGivethProjects();
await fetchAndProcessGivethProjects();
await fetchAndProcessGitcoinProjects();
// fetchAndProcessRpgf3Projects();
fetchAndProcessGitcoinProjects();
fetchAndProcessRf4Projects();
await fetchRFProjectsByRound(4);
// await fetchRFProjectsByRound(5); //TODO: It will fill on 20th Sep
await fetchAndProcessRlProjects(5);
};

export const importProjects = async () => {
Expand Down
20 changes: 20 additions & 0 deletions src/features/import-projects/retroList/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { SourceConfig } from "../types";
import { RoundNumber } from "./type";

// Define RL_API_URLS with specific round number keys
export const RL_API_URLS: Record<RoundNumber, string> = {
4: process.env.RL4_API_URL || "https://round4-api-eas.retrolist.app/projects",
5:
process.env.RL5_API_URL ||
"https://round5-api-eas.retrolist.app/5/projects",
};

export const rlSourceConfig: SourceConfig = {
source: "rf",
idField: "id",
titleField: "name",
descriptionField: "description",
imageField: "bannerImageUrl",
urlField: "url",
rfRoundField: "rfRound",
};
5 changes: 5 additions & 0 deletions src/features/import-projects/retroList/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { type RlProjectInfo } from "./type";

export const generateRlUrl = (project: RlProjectInfo) => {
return `/project/${project.id}`;
};
22 changes: 22 additions & 0 deletions src/features/import-projects/retroList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { updateOrCreateProject } from "../helpers";
import { rlSourceConfig } from "./constants";
import { generateRlUrl } from "./helper";
import { fetchRlProjects } from "./service";

export const fetchAndProcessRlProjects = async (round: number) => {
try {
const data = await fetchRlProjects(round);
if (!data) return;
for (const project of data) {
const processedProject = {
...project,
url: generateRlUrl(project),
rfRound: round,
};

await updateOrCreateProject(processedProject, rlSourceConfig);
}
} catch (error: any) {
console.log("error on fetchAndProcessRlProjects", error.message);
}
};
39 changes: 39 additions & 0 deletions src/features/import-projects/retroList/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Assuming RL_API_URLS and RlProjectInfo are defined as mentioned
import { RL_API_URLS } from "./constants";
import { RlProjectInfo, RoundNumber } from "./type";

export const fetchRlProjects = async (
round: number
): Promise<RlProjectInfo[] | null> => {
console.log(`Fetching RL projects for round ${round}`);
try {
// Check if the round exists in RL_API_URLS
if (!(round in RL_API_URLS)) {
console.log(`Invalid round number: ${round}`);
return null;
}

// Use type assertion to narrow down the type of 'round' to RoundNumber
const url = RL_API_URLS[round as RoundNumber];
const res = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

// Check if the response is ok (status code in the range 200-299)
if (!res.ok) {
console.log(`Failed to fetch data: ${res.status} ${res.statusText}`);
return null;
}

const data: RlProjectInfo[] = await res.json();
console.log(`Fetched ${data.length} projects for round ${round}`);

return data;
} catch (error: any) {
console.log("Error on fetching fetchRlProjects", error.message);
return null;
}
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type Rf4ProjectInfo = {
export type RoundNumber = 4 | 5;

export type RlProjectInfo = {
id: string;
name: string;
displayName: string;
Expand Down
14 changes: 14 additions & 0 deletions src/features/import-projects/rf/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SourceConfig } from "../types";

export const RF_API_URL =
process.env.RF4_API_URL || "https://vote.optimism.io/api/v1";

export const rfSourceConfig: SourceConfig = {
source: "rf",
idField: "id",
titleField: "name",
descriptionField: "description",
imageField: "projectCoverImageUrl",
urlField: "url",
rfRoundField: "rfRound",
};
26 changes: 26 additions & 0 deletions src/features/import-projects/rf/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { updateOrCreateProject } from "../helpers";
import { rfSourceConfig } from "./constants";
import { RfProjectInfo } from "./type";

export const generateRfUrl = (project: RfProjectInfo) => {
return `/project/${project.id}`;
};

const processProject = (project: RfProjectInfo, round: number) => {
const projectData = {
...project,
url: generateRfUrl(project),
rfRound: round,
};
return projectData;
};

export const saveBatchProjects = async (
projects: RfProjectInfo[],
round: number
) => {
for (const _project of projects) {
const project = processProject(_project, round);
await updateOrCreateProject(project, rfSourceConfig);
}
};
55 changes: 55 additions & 0 deletions src/features/import-projects/rf/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { AGORA_API_KEY } from "../../../constants";
import { RF_API_URL } from "./constants";
import { saveBatchProjects } from "./helpers";
import { RfApiResponse, RfProjectInfo } from "./type";

export const fetchRFProjectsByRound = async (round: number) => {
let offset = 0;
const limit = 10;
let hasNext = true;

console.log(
`[${new Date().toISOString()}] - Fetching projects for round: ${round}`
);

if (!AGORA_API_KEY) {
console.error("AGORA_API_KEY is not set");
return;
}

try {
while (hasNext) {
const response = await fetch(
`${RF_API_URL}/retrofunding/rounds/${round}/projects?limit=${limit}&offset=${offset}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${AGORA_API_KEY}`,
},
}
);
console.log(
`[${new Date().toISOString()}] - Fetching projects for round: ${round} at offset: ${offset} - ${response.status} - ${response.ok}`
);

if (!response.ok) {
throw new Error(
`HTTP error! status: ${response.status} for round: ${round} at offset: ${offset}`
);
}

const res: RfApiResponse = await response.json();

await saveBatchProjects(res.data, round);

hasNext = res.meta.has_next;
offset = res.meta.next_offset;
}
} catch (error) {
console.error(
`Error fetching projects for round: ${round} at offset: ${offset}`,
error
);
}
};
22 changes: 22 additions & 0 deletions src/features/import-projects/rf/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface RfProjectInfo {
id: string;
category: string;
organization: string | null;
name: string;
description: string;
profileAvatarUrl: string;
projectCoverImageUrl: string;
team: string[];
github: string[];
packages: string[];
links: string[];
}

export interface RfApiResponse {
meta: {
has_next: boolean;
total_returned: number;
next_offset: number;
};
data: RfProjectInfo[];
}
14 changes: 0 additions & 14 deletions src/features/import-projects/rf4/constants.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/features/import-projects/rf4/helpers.ts

This file was deleted.

22 changes: 0 additions & 22 deletions src/features/import-projects/rf4/index.ts

This file was deleted.

Loading

0 comments on commit 0f2ae5d

Please sign in to comment.