Skip to content

Commit 5a79ae0

Browse files
committed
Add tappads api endpoint
1 parent a6745a9 commit 5a79ae0

File tree

9 files changed

+70
-29
lines changed

9 files changed

+70
-29
lines changed

.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ TESTNET=true
2121
STABILITY_API_KEY=
2222
OPENAI_API_KEY=
2323
TELEMETREE_API_KEY=
24-
TELEMETREE_PROJECT_ID=
24+
TELEMETREE_PROJECT_ID=
25+
TAPPADS_SECRET_URL=/secret-url

src/backend/tappads.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
/* eslint-disable camelcase */
3+
import { usdToPoints } from "#root/bot/helpers/points"
4+
import { BalanceChangeType } from "#root/bot/models/balance"
5+
import { addPoints, findUserById } from "#root/bot/models/user"
6+
import { config } from "#root/config"
7+
import { logger } from "#root/logger"
8+
9+
const tappadsHandler = (fastify: any, _options: any, done: () => void) => {
10+
const secretUrl = config.TAPPADS_SECRET_URL
11+
// eslint-disable-next-line no-unused-vars
12+
fastify.get(secretUrl, async (request: any, _reply: any) => {
13+
const { offer, payout, currency, goal_id, clickid, sub3 } = request.query
14+
if (sub3) {
15+
const userId = Number(sub3)
16+
const user = await findUserById(userId)
17+
if (!user) {
18+
logger.error(`User ${userId} not found`)
19+
return { result: false }
20+
}
21+
logger.info(`User ${userId} solved ${offer}:${clickid}:${goal_id} with ${payout}${currency}`)
22+
const points = usdToPoints(payout)
23+
await addPoints(userId, points, BalanceChangeType.Task)
24+
return { result: true }
25+
}
26+
return { result: false }
27+
})
28+
done()
29+
}
30+
31+
export default tappadsHandler

src/bot/models/balance.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export enum BalanceChangeType {
99
Dice = 3,
1010
Referral = 4,
1111
Donation = 5, // TON
12+
Task = 6,
1213
}
1314

1415
export function getBalanceChangeTypeName(type: BalanceChangeType): string {

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const createConfigFromEnvironment = (environment: NodeJS.ProcessEnv) => {
3838
OPENAI_API_KEY: z.string(),
3939
TELEMETREE_API_KEY: z.string(),
4040
TELEMETREE_PROJECT_ID: z.string(),
41+
TAPPADS_SECRET_URL: z.string(),
4142
})
4243

4344
if (config.BOT_MODE === "webhook") {

src/frontend/components.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ declare module 'vue' {
1111
Clicker: typeof import('./src/components/Clicker.vue')['default']
1212
CNFT: typeof import('./src/components/CNFT.vue')['default']
1313
FAQ: typeof import('./src/components/FAQ.vue')['default']
14-
Feed: typeof import('./src/components/Feed.vue')['default']
1514
Header: typeof import('./src/components/Header.vue')['default']
1615
Main: typeof import('./src/components/Main.vue')['default']
1716
MainMenu: typeof import('./src/components/nested/MainMenu.vue')['default']
1817
Pagination: typeof import('./src/components/nested/Pagination.vue')['default']
1918
Presentation: typeof import('./src/components/Presentation.vue')['default']
2019
RouterLink: typeof import('vue-router')['RouterLink']
2120
RouterView: typeof import('vue-router')['RouterView']
21+
Tasks: typeof import('./src/components/Tasks.vue')['default']
2222
}
2323
}

src/frontend/src/components/Feed.vue renamed to src/frontend/src/components/Tasks.vue

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="feed-container">
2+
<div class="task-container">
33
<div v-if="refreshing" class="loading">
44
<div class="planet-loader"></div>
55
<p>Loading...</p>
@@ -9,23 +9,23 @@
99
</div>
1010
<template v-else>
1111
<ul
12-
v-if="feedItems.length"
13-
class="feed-list"
12+
v-if="taskItems.length"
13+
class="task-list"
1414
@touchstart="startRefresh"
1515
@touchmove="moveRefresh"
1616
@touchend="endRefresh"
1717
>
18-
<li v-for="item in feedItems" :key="item.id" class="feed-item">
18+
<li v-for="item in taskItems" :key="item.id" class="task-item">
1919
<div class="item-content">
20-
<img :src="item.icon" :alt="item.name" class="feed-icon" />
21-
<div class="feed-text">
20+
<img :src="item.icon" :alt="item.name" class="task-icon" />
21+
<div class="task-text">
2222
<h3>{{ item.name }}</h3>
2323
<p>{{ item.description }}</p>
2424
</div>
2525
</div>
2626
<p>{{ usdToPoints(item.payout) }} $CUBE</p>
2727
<button
28-
class="feed-button"
28+
class="task-button"
2929
:disabled="item.is_done"
3030
@click="handleClick(item)"
3131
:style="{
@@ -39,15 +39,15 @@
3939
</ul>
4040
<div v-else class="empty-state">
4141
<p>No entities detected</p>
42-
<button @click="fetchFeed" class="refresh-button">
42+
<button @click="fetchTasks" class="refresh-button">
4343
<span class="refresh-icon">↻</span> Scan Again
4444
</button>
4545
</div>
4646
</template>
4747
</div>
4848
</template>
4949

50-
<script setup lang="ts" name="FeedComponent">
50+
<script setup lang="ts" name="TasksComponent">
5151
import { ref, onMounted, Ref, watch } from "vue"
5252
import axios from "axios"
5353
import useLoadingAndError from "../composables/useLoadingAndError"
@@ -79,7 +79,7 @@ interface TappAdsOffer {
7979
const tappAdsKey: string = import.meta.env.VITE_APIKEY
8080
const { loadingInstance, showError } = useLoadingAndError()
8181
const userStore = useUserStore()
82-
const feedItems: Ref<TappAdsOffer[]> = ref([])
82+
const taskItems: Ref<TappAdsOffer[]> = ref([])
8383
const error = ref(null)
8484
const refreshing = ref(false)
8585
const startY = ref(0)
@@ -88,7 +88,7 @@ function escape(str: string) {
8888
return (str + "").replace(/[\\"']/g, "\\$&").replace(/\u0000/g, "\\0")
8989
}
9090
91-
const fetchFeed = async () => {
91+
const fetchTasks = async () => {
9292
if (refreshing.value) return
9393
refreshing.value = true
9494
loadingInstance.visible.value = true
@@ -104,7 +104,7 @@ const fetchFeed = async () => {
104104
ua: escape(navigator.userAgent),
105105
},
106106
})
107-
feedItems.value = response.data as TappAdsOffer[]
107+
taskItems.value = response.data as TappAdsOffer[]
108108
} catch (err) {
109109
showError(err)
110110
} finally {
@@ -118,7 +118,11 @@ const handleClick = async (item: any) => {
118118
loadingInstance.visible.value = true
119119
openLink(item.url)
120120
await sleep(1000)
121-
const res = await axios.get(item.click_postback)
121+
const userId = userStore.user?.id
122+
const ip = userStore.user?.ip ?? "0.0.0.0"
123+
const ua = escape(navigator.userAgent)
124+
const addParams = `&ip=${ip}&ua=${ua}&sub2=${userId}`
125+
const res = await axios.get(item.click_postback + addParams)
122126
if (res.data.is_done === true) {
123127
item.is_done = true
124128
}
@@ -137,7 +141,7 @@ const moveRefresh = (e: TouchEvent) => {
137141
const touch = e.touches[0]
138142
const pullDistance = touch.clientY - startY.value
139143
if (pullDistance > 50 && !refreshing.value) {
140-
fetchFeed()
144+
fetchTasks()
141145
}
142146
}
143147
@@ -147,33 +151,33 @@ const endRefresh = () => {
147151
148152
onMounted(() => {
149153
if (userStore.user) {
150-
fetchFeed()
154+
fetchTasks()
151155
}
152156
})
153157
154158
watch(
155159
() => userStore.user,
156160
() => {
157-
fetchFeed()
161+
fetchTasks()
158162
}
159163
)
160164
</script>
161165

162166
<style scoped>
163-
.feed-container {
167+
.task-container {
164168
max-height: 100vh;
165169
overflow-y: auto;
166170
background-color: rgba(0, 0, 51, 0.8);
167171
font-family: "Arial", sans-serif;
168172
color: #fff;
169173
}
170174
171-
.feed-list {
175+
.task-list {
172176
list-style-type: none;
173177
padding: 0;
174178
}
175179
176-
.feed-item {
180+
.task-item {
177181
display: flex;
178182
justify-content: space-between;
179183
align-items: center;
@@ -185,7 +189,7 @@ watch(
185189
transition: all 0.3s ease;
186190
}
187191
188-
.feed-item:hover {
192+
.task-item:hover {
189193
transform: translateY(-2px);
190194
box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);
191195
}
@@ -195,7 +199,7 @@ watch(
195199
align-items: center;
196200
}
197201
198-
.feed-icon {
202+
.task-icon {
199203
width: 50px;
200204
height: 50px;
201205
margin-right: 15px;
@@ -204,19 +208,19 @@ watch(
204208
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
205209
}
206210
207-
.feed-text h3 {
211+
.task-text h3 {
208212
margin: 0 0 5px 0;
209213
color: #fff;
210214
font-size: 18px;
211215
}
212216
213-
.feed-text p {
217+
.task-text p {
214218
margin: 0;
215219
color: #ccc;
216220
font-size: 14px;
217221
}
218222
219-
.feed-button {
223+
.task-button {
220224
padding: 8px 15px;
221225
background-color: rgba(255, 255, 255, 0.2);
222226
color: #fff;

src/frontend/src/components/nested/MainMenu.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<router-link to="/cnft" class="menu-link" active-class="active">🎨</router-link>
66
<router-link to="/clicker" class="menu-link" active-class="active">🖱️</router-link>
77
<router-link
8-
to="/feed"
8+
to="/tasks"
99
class="menu-link"
1010
v-show="isDevelopment"
1111
active-class="active"

src/frontend/src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import FAQComponent from "./components/FAQ.vue";
1212
import PresentationComponent from "./components/Presentation.vue";
1313
import { fluent } from "./fluent";
1414
import ClickerComponent from "./components/Clicker.vue";
15-
import FeedComponent from "./components/Feed.vue";
15+
import TasksComponent from "./components/Tasks.vue";
1616

1717
const routes = [
1818
// RESERVED: /cnfts /api
@@ -24,7 +24,7 @@ const routes = [
2424
];
2525

2626
if (import.meta.env.VITE_ENV === "development") {
27-
routes.push({ path: "/feed", mame: "FeedPage", component: FeedComponent });
27+
routes.push({ path: "/tasks", mame: "TasksPage", component: TasksComponent });
2828
}
2929

3030
const router = createRouter({

src/server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { authHandler } from "./backend/auth-handler"
99
import nftHandler from "./backend/nft-handler"
1010
import checkCaptcha from "./backend/captcha"
1111
import analyticsHandler from "./backend/analytics"
12+
import tappadsHandler from "./backend/tappads"
1213

1314
export const createServer = async (bot: Bot) => {
1415
const server = fastify({
@@ -27,6 +28,8 @@ export const createServer = async (bot: Bot) => {
2728

2829
await server.register(nftHandler, { prefix: "/api/nft" })
2930

31+
await server.register(tappadsHandler, { prefix: "/api/tappads" })
32+
3033
await server.register(checkCaptcha, { bot })
3134

3235
const __filename = fileURLToPath(import.meta.url)

0 commit comments

Comments
 (0)