Skip to content

Commit

Permalink
resolving error for bounty
Browse files Browse the repository at this point in the history
  • Loading branch information
mvp5464 committed May 20, 2024
1 parent 847e4a1 commit 0b3ad17
Show file tree
Hide file tree
Showing 15 changed files with 933 additions and 61 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ CACHE_EXPIRE_S = 10

ADMINS = "Random,[email protected]"
NEXT_PUBLIC_DISABLE_FEATURES = "featurea,featureb,featurec"
EXCHANGE_RATE_SECRET="" # https://www.exchangerate-api.com/
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
GITHUB_PAT=""
128 changes: 78 additions & 50 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ model Course {
content CourseContent[]
purchasedBy UserPurchases[]
certificate Certificate[]
certIssued Boolean @default(false)
certIssued Boolean @default(false)
}

model UserPurchases {
Expand Down Expand Up @@ -64,12 +64,12 @@ model CourseContent {
}

model Certificate {
id String @id @default(cuid())
slug String @default("certId")
user User @relation(fields: [userId], references: [id])
userId String
course Course @relation(fields: [courseId], references: [id])
courseId Int
id String @id @default(cuid())
slug String @default("certId")
user User @relation(fields: [userId], references: [id])
userId String
course Course @relation(fields: [courseId], references: [id])
courseId Int
@@unique([userId, courseId])
}
Expand Down Expand Up @@ -147,6 +147,7 @@ model User {
questions Question[]
answers Answer[]
certificate Certificate[]
githubUser GithubUser?
}

model DiscordConnect {
Expand Down Expand Up @@ -206,75 +207,102 @@ model Comment {
votes Vote[]
isPinned Boolean @default(false)
}

model Question {
id Int @id @default(autoincrement())
title String
content String
slug String @unique
createdAt DateTime @default(now())
author User @relation(fields: [authorId], references: [id])
authorId String
upvotes Int @default(0)
downvotes Int @default(0)
id Int @id @default(autoincrement())
title String
content String
slug String @unique
createdAt DateTime @default(now())
author User @relation(fields: [authorId], references: [id])
authorId String
upvotes Int @default(0)
downvotes Int @default(0)
totalanswers Int @default(0)
answers Answer[]
votes Vote[]
tags String[]
updatedAt DateTime @updatedAt
answers Answer[]
votes Vote[]
tags String[]
updatedAt DateTime @updatedAt
@@index([authorId])
}

model Answer {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
question Question @relation(fields: [questionId], references: [id])
questionId Int
author User @relation(fields: [authorId], references: [id])
authorId String
votes Vote[]
upvotes Int @default(0)
downvotes Int @default(0)
totalanswers Int @default(0)
parentId Int?
responses Answer[] @relation("AnswerToAnswer")
parent Answer? @relation("AnswerToAnswer", fields: [parentId], references: [id])
updatedAt DateTime @updatedAt
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
question Question @relation(fields: [questionId], references: [id])
questionId Int
author User @relation(fields: [authorId], references: [id])
authorId String
votes Vote[]
upvotes Int @default(0)
downvotes Int @default(0)
totalanswers Int @default(0)
parentId Int?
responses Answer[] @relation("AnswerToAnswer")
parent Answer? @relation("AnswerToAnswer", fields: [parentId], references: [id])
updatedAt DateTime @updatedAt
@@index([questionId])
@@index([authorId])
@@index([parentId])
}


model Vote {
id Int @id @default(autoincrement())
questionId Int?
question Question? @relation(fields: [questionId], references: [id])
answerId Int?
answer Answer? @relation(fields: [answerId], references: [id])
commentId Int?
comment Comment? @relation(fields: [commentId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
voteType VoteType
createdAt DateTime @default(now())
id Int @id @default(autoincrement())
questionId Int?
question Question? @relation(fields: [questionId], references: [id])
answerId Int?
answer Answer? @relation(fields: [answerId], references: [id])
commentId Int?
comment Comment? @relation(fields: [commentId], references: [id])
userId String
user User @relation(fields: [userId], references: [id])
voteType VoteType
createdAt DateTime @default(now())
@@unique([questionId, userId])
@@unique([answerId, userId])
@@unique([commentId, userId])
@@unique([questionId, userId])
@@unique([answerId, userId])
@@unique([commentId, userId])
}

enum VoteType {
UPVOTE
DOWNVOTE
}

enum PostType {
QUESTION
ANSWER
}

enum CommentType {
INTRO
DEFAULT
}

model GithubUser {
id Int @id @default(autoincrement())
userId String @unique
username String @unique
email String? @unique
publicName String?
isLinked Boolean @default(false)
user User? @relation(fields: [userId], references: [id])
bountyInfo BountyInfo[]
}

model BountyInfo {
id Int @id @default(autoincrement())
username String
PR_Link String @unique
PR_Title String
repoName String
USD_amount Int
INR_amount Int
isPaid Boolean @default(false)
createdAt DateTime @default(now())
githubUser GithubUser? @relation(fields: [githubUserId], references: [userId])
githubUserId String?
}
79 changes: 79 additions & 0 deletions src/app/api/github-webhook/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { NextRequest, NextResponse } from 'next/server';
import db from '@/db';
import {
formatINR,
formatUSD,
getCurrencyRate,
sendBountyComment,
} from '@/utiles/bounty';

export async function POST(req: NextRequest) {
const body = await req.json();
const USD_amount = +body.bountyAmount.split('$')[1];
const PR_By = body.author;
const PR_Link = body.pr_link;
const repo_owner = body.repo_owner;
const repoName = PR_Link.split('/')[4];
const PR_No: string = PR_Link.split('/')[6];
const username = body.username;
const PR_Title = body.PR_Title;

try {
const INR_amount = await getCurrencyRate(USD_amount);
const commentBody = `💰Congratulation @${PR_By} for winning ${formatUSD.format(USD_amount).split('.')[0]} (${formatINR.format(INR_amount).split('.')[0]}) bounty.\n👉 To claim visit https://app.100xdevs.com/bounty.\n🐥Keep contributing.`;

const findBountyInfo = await db.bountyInfo.findUnique({
where: { PR_Link },
});

if (findBountyInfo) {
const commentBody = `[Duplicate]\n💰Bounty worth ${formatUSD.format(findBountyInfo.USD_amount).split('.')[0]} (${formatINR.format(findBountyInfo.INR_amount).split('.')[0]}) is already created to @${PR_By} for this PR.\n👉 To claim visit https://app.100xdevs.com/bounty.\n🐥Keep contributing.`;
sendBountyComment({ repo_owner, repoName, PR_No, commentBody });
return NextResponse.json(
{ message: 'duplicate bounty message' },
{ status: 401 },
);
}

const findUser = await db.githubUser.findUnique({
where: { username },
});

if (findUser) {
const addBountyInfo = await db.bountyInfo.create({
data: {
username,
PR_Title,
PR_Link,
repoName,
USD_amount,
INR_amount,
githubUserId: findUser.userId,
},
});
if (addBountyInfo) {
sendBountyComment({ repo_owner, repoName, PR_No, commentBody });
}
} else {
const addBountyInfo = await db.bountyInfo.create({
data: {
username,
PR_Title,
PR_Link,
repoName,
USD_amount,
INR_amount,
},
});
if (addBountyInfo) {
sendBountyComment({ repo_owner, repoName, PR_No, commentBody });
}
}
return NextResponse.json({ message: 'success' }, { status: 200 });
} catch (e) {
return NextResponse.json(
{ message: 'Error while updating database' },
{ status: 401 },
);
}
}
53 changes: 53 additions & 0 deletions src/app/api/github/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { NextRequest, NextResponse } from 'next/server';
import db from '@/db';

export async function POST(req: NextRequest) {
const { value: username, userId } = await req.json();
try {
await db.githubUser.upsert({
where: { userId, isLinked: false },
create: { userId, username },
update: { userId, username },
});
return NextResponse.json({ message: 'successful' }, { status: 200 });
} catch (e) {
return NextResponse.json({ message: 'failed' }, { status: 403 });
}
}

export async function PUT(req: NextRequest) {
const { username, email, publicName } = await req.json();
if (!username) {
return NextResponse.json(
{ message: 'error while fetching username' },
{ status: 403 },
);
}
try {
const findUser = await db.githubUser.findUnique({
where: { username, isLinked: false },
});
if (!findUser) {
return NextResponse.json(
{ message: 'Error while linking account, username is different' },
{ status: 401 },
);
}
const updateInfo = await db.githubUser.update({
where: { username },
data: { isLinked: true, email, publicName },
});

await db.bountyInfo.updateMany({
where: { username },
data: { githubUserId: updateInfo.userId },
});

return NextResponse.json({ message: 'successful' }, { status: 200 });
} catch (e) {
return NextResponse.json(
{ message: 'Error while linking account, username is different' },
{ status: 403 },
);
}
}
33 changes: 33 additions & 0 deletions src/app/bounty/[bountyId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import BountyUser from '@/components/BountyUser';
import { getGithubDetail } from '@/db/course';
import { authOptions } from '@/lib/auth';
import { getServerSession } from 'next-auth';
import { redirect } from 'next/navigation';

export default async function Page({
params,
}: {
params: { bountyId: string };
}) {
const session = await getServerSession(authOptions);
if (!session) {
redirect('/signin');
}
const { role } = session.user;

if (role === 'user') {
redirect('/bounty');
}

const userInfo = await getGithubDetail({ userId: params.bountyId });

if (!userInfo || userInfo.isLinked === false) {
redirect('/signInGithub');
}

return (
<div>
{role === 'admin' && <BountyUser userInfo={userInfo} role={role} />}
</div>
);
}
37 changes: 37 additions & 0 deletions src/app/bounty/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import BountyAdmin from '@/components/BountyAdmin';
import BountyUser from '@/components/BountyUser';
import { getAllBountyDetail, getGithubDetail } from '@/db/course';
import { authOptions } from '@/lib/auth';
import { getServerSession } from 'next-auth';
import { redirect } from 'next/navigation';

export default async function BountyPage() {
const session = await getServerSession(authOptions);

if (!session) {
redirect('/signin');
}

const { role, id } = session.user;

if (role === 'user') {
const userInfo = await getGithubDetail({ userId: id });
if (!userInfo || userInfo.isLinked === false) {
redirect('/signInGithub');
}
return <BountyUser userInfo={userInfo} role={role} />;
}

if (role === 'admin') {
const allGithubBountyInfo = await getAllBountyDetail();
if (!allGithubBountyInfo) {
return <div>No bounties</div>;
}
const allDetails = {
userInfo: allGithubBountyInfo.userInfo,
bountyInfo: allGithubBountyInfo.bountyInfo,
};

return <BountyAdmin allGithubBountyInfo={allDetails} />;
}
}
Loading

0 comments on commit 0b3ad17

Please sign in to comment.