Skip to content

Commit

Permalink
Merge pull request #66 from GeneralMagicio/feature/thank-you-cast
Browse files Browse the repository at this point in the history
Feature/thank you cast
  • Loading branch information
RamRamez authored Nov 11, 2024
2 parents 849704c + 6be8a78 commit d343d33
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 3 deletions.
1 change: 1 addition & 0 deletions prisma/migrations/20241106125304_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "FarcasterConnection" ADD COLUMN "thankYouCastSent" BOOLEAN DEFAULT FALSE;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ model FarcasterConnection {
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
user User @relation(fields: [userId], references: [id])
thankYouCastSent Boolean @default(false)
}

model WorldIdConnection {
Expand Down
8 changes: 6 additions & 2 deletions src/cronJobs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { schedule } from 'node-cron';
import { sendDailyCasts } from './neynar/utils';
import {
sendDailyDelegationCasts,
sendDailyThankYouCast,
} from './neynar/utils';

const sendCastsCronJobTime = '21 1 22 * * *'; // at 22:01 Tehran time every day

Expand All @@ -12,7 +15,8 @@ const sendCastsCronJob = () => {
sendCastsCronJobTime,
async () => {
try {
await sendDailyCasts();
await sendDailyDelegationCasts();
await sendDailyThankYouCast();
} catch (e) {
console.error('sendCastsCronJob error', e);
}
Expand Down
137 changes: 136 additions & 1 deletion src/neynar/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,141 @@ import { PrismaClient } from '@prisma/client';
import { FarcasterMetadata } from 'src/flow/types';
import neynarClient from './neynarClient';

const findMaxiUsers = async () => {
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.POSTGRES_PRISMA_URL,
},
},
});

await prisma.$connect();

const collectionCategories = await prisma.project.findMany({
where: {
type: 'collection',
},
select: {
id: true,
},
});
const collectionCategoryIds = collectionCategories.map(
(category) => category.id,
);

const usersWithFarcaster = await prisma.user.findMany({
where: {
farcasterConnection: {
isNot: null,
thankYouCastSent: false,
},
},
select: {
id: true,
},
});
const userIdsWithFarcaster = usersWithFarcaster.map((user) => user.id);

// Find users who have delegated or attested to all categories (Collection + Budget)
const maxiUsers = await prisma.user.findMany({
where: {
id: { in: userIdsWithFarcaster },
// Check that the user has attested or delegated to the Budget category
OR: [
{
budgetAttestations: {
some: {},
},
},
{
budgetDelegation: {
isNot: null,
},
},
],
// Ensure the user has attested or delegated to all Collection categories
AND: [
{
AND: collectionCategoryIds.map((categoryId) => ({
OR: [
{
attestations: {
some: {
collectionId: categoryId,
},
},
},
{
delegations: {
some: {
collectionId: categoryId,
},
},
},
],
})),
},
],
},
select: {
farcasterConnection: {
select: {
userId: true,
metadata: true,
},
},
},
});
return maxiUsers.map((user) => user.farcasterConnection);
};

const sendThankYouCast = async (username: string) => {
if (!farcasterSignerUUID) {
throw new Error(
'Make sure you set FARCASTER_SIGNER_UUID in your .env file',
);
}
await neynarClient.publishCast(
farcasterSignerUUID,
`@${username}! Thank you for playing with Pairwise!
YOU ROCK!`,
);
console.log(`The Thanks you Cast successfully sent to @${username}`);
};

const updateThankYouCastSent = async (userId?: number) => {
if (!userId) return;
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.POSTGRES_PRISMA_URL,
},
},
});
await prisma.farcasterConnection.update({
where: { userId },
data: { thankYouCastSent: true },
});
await prisma.$disconnect();
};

export const sendDailyThankYouCast = async () => {
const maxiUsers = await findMaxiUsers();
if (!maxiUsers || maxiUsers.length === 0) return;
for (const user of maxiUsers) {
try {
await sendThankYouCast(
(user?.metadata?.valueOf() as FarcasterMetadata)['username'],
);
await updateThankYouCastSent(user?.userId);
} catch (e) {
console.error('Error sending Thank you cast for user ID: ', user?.userId);
}
}
};

/**
* Returns an array of `{fid, username, totalDelegates}` mapping in which `totalDelegates` is
* the number of times that another user has delegated to this specific username/fid
Expand Down Expand Up @@ -77,7 +212,7 @@ export const getDelegations = async (start: number, end?: number) => {
return result;
};

export const sendDailyCasts = async () => {
export const sendDailyDelegationCasts = async () => {
const endTimestamp = new Date();
endTimestamp.setMinutes(0, 0, 0); // set to xx:00:00
const delegations = await getDelegations(
Expand Down

0 comments on commit d343d33

Please sign in to comment.