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

332 generate bounty idea #416

3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
DATABASE_URL="postgresql://…"
ADMINS="0x…,0x…,0x…"
ADMINS="0x…,0x…,0x…"
OPENAI_API_KEY="sk-…"
48 changes: 48 additions & 0 deletions src/app/api/generateBounty/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export async function POST(): Promise<Response> {
try {
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
if (!OPENAI_API_KEY) {
throw new Error('Missing OpenAI API key');
}

const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4-turbo',
messages: [
{
role: 'system',
content: `Generate unique, creative, and fun bounty ideas for the "Pics or It Didn't Happen" (poidh) website. Each bounty should encourage users to engage in amusing, interesting, or surprising activities that can be easily documented with a photo, screenshot, or video.
Ensure the ideas are diverse, spanning different themes such as real-life actions, contributions, playful tasks, or simple creative(could be developer) projects.
Ideas must remain achievable and enjoyable for users of all skill levels. A user should share result either in video or in photo. Include:
Title: A short, catchy description of the bounty (max 50 characters).
Description: A clear and engaging explanation of what the user must do to complete the bounty (max 350 characters).
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
Return the ideas in JSON format like this:
{ 'title': '...', 'description': '...' }.`,
},
{
role: 'user',
content: 'Generate a bounty idea for a person to do.',
},
],
max_tokens: 100,
temperature: 1,
response_format: { type: 'json_object' },
}),
});

if (!response.ok) {
console.log('Error in response from OpenAI API.');
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
}

const data = await response.json();
return Response.json(data.choices[0].message.content);
} catch (error) {
console.error('Error communicating with OpenAI API:', error);
return Response.error();
}
}
75 changes: 71 additions & 4 deletions src/components/global/FormBounty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { trpcClient } from '@/trpc/client';
import GameButton from '@/components/global/GameButton';
import ButtonCTA from '@/components/ui/ButtonCTA';
import { InfoIcon } from '@/components/global/Icons';
import { Bounty } from '@/utils/types';

export default function FormBounty({
open,
Expand Down Expand Up @@ -107,6 +108,35 @@ export default function FormBounty({
},
});

const generateBountyMutation = useMutation({
mutationFn: async () => {
setName('Generating…');
setDescription('Generating…');
const res = await fetch('/api/generateBounty', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});

if (!res.ok) {
throw new Error(`Error: ${res.status}`);
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
}

return JSON.parse(await res.json());
},
onSuccess: (bounty: Bounty) => {
setName(bounty.title);
setDescription(bounty.description);
toast.success('Bounty generated successfully');
},
onError: (error) => {
setName('');
setDescription('');
toast.error('Failed to generate bounty: ' + error.message);
},
});

return (
<>
<Loading open={createBountyMutations.isPending} status={status} />
Expand All @@ -129,19 +159,43 @@ export default function FormBounty({
>
<DialogContent>
<Box display='flex' flexDirection='column' width='100%'>
<span>title</span>
<span
className={cn(
generateBountyMutation.isPending ? 'animate-pulse' : ''
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
)}
>
title
</span>
<input
disabled={generateBountyMutation.isPending}
type='text'
value={name}
onChange={(e) => setName(e.target.value)}
className='border bg-transparent border-[#D1ECFF] py-2 px-2 rounded-md mb-4'
className={cn(
'border py-2 px-2 rounded-md mb-4 bg-transparent border-[#D1ECFF]',
generateBountyMutation.isPending
? 'cursor-not-allowed animate-pulse'
: ''
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
)}
/>
<span>description</span>
<span
className={cn(
generateBountyMutation.isPending ? 'animate-pulse' : ''
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
)}
>
description
</span>
<textarea
disabled={generateBountyMutation.isPending}
rows={3}
value={description}
onChange={(e) => setDescription(e.target.value)}
className='border bg-transparent border-[#D1ECFF] py-2 px-2 rounded-md mb-4 max-h-28'
className={cn(
'border py-2 px-2 rounded-md mb-4 max-h-28 bg-transparent border-[#D1ECFF]',
generateBountyMutation.isPending
? 'cursor-not-allowed animate-pulse'
: ''
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
)}
></textarea>

<span>reward</span>
Expand Down Expand Up @@ -198,6 +252,19 @@ export default function FormBounty({
<ButtonCTA>create bounty</ButtonCTA>
</button>
</DialogActions>
<div className='py-4 mt-1 w-full flex justify-center items-center flex-row'>
<span className='mr-2'>need a bouty idea? click the</span>
<button
className={cn(
'cursor-pointer items-center text-center',
generateBountyMutation.isPending ? 'cursor-not-allowed' : ''
whtsupbab3 marked this conversation as resolved.
Show resolved Hide resolved
)}
onClick={() => generateBountyMutation.mutate()}
disabled={generateBountyMutation.isPending}
>
🤖
</button>
</div>
</Dialog>
</>
);
Expand Down
6 changes: 6 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ export type Wallet = {
ens: string | null;
degenName: string | null;
};

export type Bounty = {
title: string;
description: string;
isGenerating?: boolean;
};
yukigesho marked this conversation as resolved.
Show resolved Hide resolved
Loading