generated from heroku/node-js-getting-started
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
225 lines (207 loc) · 9.66 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import dotenv from 'dotenv';
dotenv.config();
import express from 'express';
import { eas_mint, eas_check } from './helpers/eas.js';
import { parse_cast, parse_action } from './helpers/neynar.js';
import { create_image } from './helpers/poll.js';
const app = express();
app.use(express.json());
const base_url = process.env["IS_PROD"] == 'true' ? 'https://ask.farpoll.com' : 'https://6cc1-2603-7000-8807-4100-39b4-aa62-5737-e5c5.ngrok-free.app';
console.log(base_url+ '/start')
app.get('/', (req, res) => {
const myurl = `https://linktr.ee/cryptodatabytes`
res.redirect(myurl)
});
app.get('/image', async (req, res) => {
console.log('image')
const showResults = req.query.show_results;
const cast_hash = req.query.cast_hash;
const pngBuffer = await create_image(showResults, cast_hash);
res.setHeader('Content-Type', 'image/png');
res.setHeader('Cache-Control', 'max-age=10');
res.send(pngBuffer);
});
app.get('/start', (req, res) => {
console.log('start')
res.setHeader('Content-Type', 'text/html');
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<title>Start the poll</title>
<meta property="og:title" content="Start the poll">
<meta property="og:image" content="https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F497f2650-6a20-4a36-8008-57aa5a90f74d_916x476.png">
<meta name="fc:frame" content="vNext">
<meta name="fc:frame:image" content="https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F497f2650-6a20-4a36-8008-57aa5a90f74d_916x476.png">
<meta name="fc:frame:post_url" content="${base_url}/poll">
<meta name="fc:frame:button:1" content="Load Poll">
</head>
<body>
<p>Create your own poll by copy and pasting "https://ask.farpoll.com/start" into a cast, and typing out a question with a '?' and options like [a,b,c].</p>
</body>
</html>
`);
});
app.post('/poll', async (req, res) => {
console.log('poll')
// const cast_hash = "0x27f8122fa7e4fdf22beafce0ff38eead51c644f3" //QA testing hardcode
// const attest_wallet = "0xFdB1636C17DBC312f5E48625981499a4a179d6f0" //QA testing hardcode
try {
const { cast_hash, button_index, trusted_data, fid, attest_wallet } = await parse_action(req.body);
const exists = await eas_check(cast_hash, attest_wallet)
let display_html;
// if (false) { //QA hardcode, this will make the attestation fire off again.
if (exists.exists) {
// user already has an attestation, show results
display_html = `
<meta property="og:image" content="https://og.onceupon.gg/card/${exists.hash}?max-age=1&datetime=${Date.now()}">
<meta name="fc:frame" content="vNext">
<meta name="fc:frame:image" content="https://og.onceupon.gg/card/${exists.hash}?max-age=1&datetime=${Date.now()}">
<meta name="fc:frame:post_url" content="${base_url}/results?attested=yes">
<meta name="fc:frame:button:1" content="you voted, click here show results">
`
} else {
// user has not voted yet, show poll options
const results = await parse_cast(cast_hash)
// console.log(results)
const buttons = results.options.map((option, index) => ({
[`fc:frame:button:${index + 1}`]: option
}))
display_html = `
<meta property="og:image" content="${base_url}/image?show_results=false&cast_hash=${cast_hash}">
<meta name="fc:frame" content="vNext">
<meta name="fc:frame:image" content="${base_url}/image?show_results=false&cast_hash=${cast_hash}">
<meta name="fc:frame:post_url" content="${base_url}/results?attested=no">
${buttons.map(button => Object.entries(button).map(([key, value]) => `<meta name="${key}" content="${value}">`).join('\n')).join('\n')}
`
}
res.setHeader('Content-Type', 'text/html');
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<title>Submit a vote</title>
<meta property="og:title" content="Submit a vote">
${display_html}
</head>
<body>
<p>Submit a vote</p>
</body>
</html>
`);
} catch (error) {
console.log(error)
res.send(400)
}
});
// app.post('/submit', async (req, res) => {
// console.log('submit')
// // const cast_hash = "0x27f8122fa7e4fdf22beafce0ff38eead51c644f3" //QA testing hardcode
// // const attest_wallet = "0xFdB1636C17DBC312f5E48625981499a4a179d6f0" //QA testing hardcode
// // const button_index = 1 //QA testing hardcode
// // const fid = 0 //QA testing hardcode
// // const trusted_data = "0x010101" //QA testing hardcode
// const { cast_hash, button_index, trusted_data, fid, attest_wallet } = await parse_action(req.body);
// try {
// const tx_id = await eas_mint(cast_hash, fid, attest_wallet, button_index, trusted_data); //add "verifiable=true" if you want to include trustedData in the mint. It's just expensive.
// // const tx_id = '0x5c06b77273988a2ad5177307dded64dddf41be2173178e47b45893dc334e985f' //QA testing hardcode for onceupon, if you don't want to fire off an attestation
// //bring this back later once tx hash get be consistently acquired
// Hit Once Upon API with txHash and the original POST body from the Frame
// console.log("call onceupon")
// const uri = encodeURIComponent(`${base_url}/results`);
// const button_text = encodeURIComponent("See Poll Results");
// const onceUponResponse = await fetch(`https://api.onceupon.gg/v1/transactions/${tx_id}/farcaster-frame?callback=${uri}&buttonText=${button_text}&delay=0`, {
// method: 'POST',
// body: JSON.stringify(req.body)
// });
// // // Assuming the second API returns HTML response
// // const htmlResponse = await onceUponResponse.text();
// // res.setHeader('Content-Type', 'text/html');
// // res.status(200).send(htmlResponse);
// } catch (error) {
// // Error handling
// console.error('Error in postHandler:', error);
// res.setHeader('Content-Type', 'text/html');
// res.status(200).send(`
// <!DOCTYPE html>
// <html>
// <head>
// <title>vote failed</title>
// <meta property="og:title" content="vote failed">
// <meta property="og:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
// <meta name="fc:frame" content="vNext">
// <meta name="fc:frame:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
// <meta name="fc:frame:post_url" content="${base_url}/poll">
// <meta name="fc:frame:button:1" content="failed, click to try again">
// </head>
// <body>
// <p>vote failed</p>
// </body>
// </html>
// `)
// }``
// });
app.post('/results', async (req, res) => {
console.log('results')
try {
const attested = req.query.attested;
const { cast_hash, button_index, trusted_data, fid, attest_wallet } = await parse_action(req.body);
// const cast_hash = "0x27f8122fa7e4fdf22beafce0ff38eead51c644f3" //QA testing hardcode for redirects
if (attested === 'no') {
await eas_mint(cast_hash, fid, attest_wallet, button_index, trusted_data); //add "verifiable=true" if you want to include trustedData in the mint. It's just expensive.
}
res.setHeader('Content-Type', 'text/html');
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<title>see results</title>
<meta property="og:title" content="see results">
<meta property="og:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
<meta name="fc:frame" content="vNext">
<meta name="fc:frame:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
<meta name="fc:frame:button:1" content="see data on voter wallets 👉">
<meta name="fc:frame:button:1:action" content="post_redirect">
<meta name="fc:frame:post_url" content="${base_url}/redirect">
</head>
<body>
<p>see results</p>
</body>
</html>`);
} catch (error) {
// Error handling
console.error('Error in syndicate');
res.setHeader('Content-Type', 'text/html');
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<title>vote failed</title>
<meta property="og:title" content="vote failed">
<meta property="og:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
<meta name="fc:frame" content="vNext">
<meta name="fc:frame:image" content="${base_url}/image?show_results=true&cast_hash=${cast_hash}">
<meta name="fc:frame:post_url" content="${base_url}/poll">
<meta name="fc:frame:button:1" content="failed, click to try again">
</head>
<body>
<p>vote failed</p>
</body>
</html>
`)
}
});
app.post('/redirect', async (req, res) => {
//need to first redirect to a url with the same host name, then I can redirect out to another domain
const cast_hash = req.body?.untrustedData?.castId?.hash
console.log('redirect: ' + cast_hash)
res.redirect(`${base_url}/dune?cast_hash=${cast_hash}`);
});
app.get('/dune', async (req, res) => {
const cast_hash = req.query.cast_hash;
const dune_url = `https://dune.com/ilemi/farpoll?cast_hash_t76384=${cast_hash}`
res.redirect(dune_url)
})
app.listen(process.env.PORT || 5001, () => {
console.log(`app listening on port ${process.env.PORT || 5001}`);
});