Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staging to main #108

Merged
merged 32 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
53bdebf
Merge pull request #101 from Giveth/feat/multiple_schema_support
aminlatifi Aug 12, 2024
589227a
add rfRounds column
MohammadPCh Aug 21, 2024
bf7f645
migration for adding rf_rounds and deleting source_status
MohammadPCh Aug 21, 2024
6c3f9e9
add rfRoundField to SourceConfig
MohammadPCh Aug 21, 2024
1fb2d83
add rf constants
MohammadPCh Aug 21, 2024
bb7faf8
add rfRounds to model
MohammadPCh Aug 21, 2024
755d63e
add rf type
MohammadPCh Aug 21, 2024
389eb12
add rf helper
MohammadPCh Aug 21, 2024
6aa94cb
add fetchRFProjectsByRound
MohammadPCh Aug 21, 2024
f5f8aa1
update updateOrCreateProject to handle rounds
MohammadPCh Aug 21, 2024
2e2899f
handle old rf4 attests
MohammadPCh Aug 21, 2024
e80b288
fix error handling
MohammadPCh Aug 22, 2024
35af541
fix condition
MohammadPCh Aug 22, 2024
a25e657
fix name
MohammadPCh Aug 22, 2024
a778112
remove old RF4 feature
MohammadPCh Aug 22, 2024
56d036b
Merge pull request #105 from Giveth/feat/handle-rf-projects-rounds
MohammadPCh Aug 22, 2024
6124912
fix build
MohammadPCh Aug 22, 2024
c40322e
add log for rf rounds fetching
MohammadPCh Aug 25, 2024
537509c
add logs
MohammadPCh Aug 25, 2024
1443cb2
add more logs
MohammadPCh Aug 25, 2024
bd71339
add AGORA_API_KEY to constants
MohammadPCh Aug 25, 2024
1305d36
fix typo
MohammadPCh Aug 25, 2024
a268975
remove assert
MohammadPCh Aug 25, 2024
fcb3ae6
re-active fetching giveth and gitcoin projects
MohammadPCh Aug 25, 2024
7209daa
Merge branch 'main' into develop
MohammadPCh Aug 28, 2024
97dcf46
add types
MohammadPCh Aug 28, 2024
1f12876
add constants
MohammadPCh Aug 28, 2024
35e78d0
add services
MohammadPCh Aug 28, 2024
248065f
add helper
MohammadPCh Aug 28, 2024
1520ff9
add fetchAndProcessRlProjects
MohammadPCh Aug 28, 2024
ab484b1
use fetchAndProcessRlProjects
MohammadPCh Aug 28, 2024
968cb33
Merge pull request #110 from Giveth/feat/handle-retro-list
MohammadPCh Aug 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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