This commit is contained in:
shafi54 2026-06-27 08:30:59 +05:30
parent ba14653721
commit 64d4d26909
8 changed files with 426 additions and 597 deletions

View file

@ -23,15 +23,13 @@
"license": "ISC", "license": "ISC",
"description": "", "description": "",
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.888.0",
"@aws-sdk/s3-request-presigner": "^3.888.0",
"@hono/node-server": "^1.19.11", "@hono/node-server": "^1.19.11",
"@hono/trpc-server": "^0.4.2", "@hono/trpc-server": "^0.4.2",
"@trpc/server": "^11.6.0", "@trpc/server": "^11.6.0",
"@turf/turf": "^7.2.0", "@turf/boolean-point-in-polygon": "^7.2.0",
"@turf/helpers": "^7.2.0",
"@types/bcryptjs": "^2.4.6", "@types/bcryptjs": "^2.4.6",
"aws4fetch": "^1.0.20", "aws4fetch": "^1.0.20",
"axios": "^1.11.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"dotenv": "^17.2.1", "dotenv": "^17.2.1",

View file

@ -1,5 +1,4 @@
import { Buffer } from 'buffer' import { Buffer } from 'buffer'
import axios from 'axios'
import { scaffoldProducts } from '@/src/trpc/apis/common-apis/common' import { scaffoldProducts } from '@/src/trpc/apis/common-apis/common'
import { scaffoldEssentialConsts } from '@/src/trpc/apis/common-apis/common-trpc-index' import { scaffoldEssentialConsts } from '@/src/trpc/apis/common-apis/common-trpc-index'
import { scaffoldStores } from '@/src/trpc/apis/user-apis/apis/stores' import { scaffoldStores } from '@/src/trpc/apis/user-apis/apis/stores'
@ -180,18 +179,19 @@ export async function clearUrlCache(urls: string[]): Promise<{ success: boolean;
} }
try { try {
const response = await axios.post( const resp = await fetch(
`https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`, `https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`,
{ files: urls },
{ {
method: 'POST',
headers: { headers: {
'Authorization': `Bearer ${cloudflareApiToken}`, 'Authorization': `Bearer ${cloudflareApiToken}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ files: urls }),
} }
) )
const result = response.data as { success: boolean; errors?: { message: string }[] } const result = await resp.json() as { success: boolean; errors?: { message: string }[] }
if (!result.success) { if (!result.success) {
const errorMessages = result.errors?.map(e => e.message) || ['Unknown error'] const errorMessages = result.errors?.map(e => e.message) || ['Unknown error']
@ -218,18 +218,19 @@ export async function clearAllCache(): Promise<{ success: boolean; errors?: stri
} }
try { try {
const response = await axios.post( const resp = await fetch(
`https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`, `https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`,
{ purge_everything: true },
{ {
method: 'POST',
headers: { headers: {
'Authorization': `Bearer ${cloudflareApiToken}`, 'Authorization': `Bearer ${cloudflareApiToken}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ purge_everything: true }),
} }
) )
const result = response.data as { success: boolean; errors?: { message: string }[] } const result = await resp.json() as { success: boolean; errors?: { message: string }[] }
if (!result.success) { if (!result.success) {
const errorMessages = result.errors?.map(e => e.message) || ['Unknown error'] const errorMessages = result.errors?.map(e => e.message) || ['Unknown error']

View file

@ -1,20 +1,20 @@
import axios from 'axios';
export async function extractCoordsFromRedirectUrl(url: string): Promise<{ latitude: string; longitude: string } | null> { export async function extractCoordsFromRedirectUrl(url: string): Promise<{ latitude: string; longitude: string } | null> {
try { try {
await axios.get(url, { maxRedirects: 0 }); const response = await fetch(url, { redirect: 'manual' })
return null; if (response.status === 301 || response.status === 302) {
} catch (error: any) { const redirectUrl = response.headers.get('location')
if (error.response?.status === 302 || error.response?.status === 301) { if (redirectUrl) {
const redirectUrl = error.response.headers.location; const coordsMatch = redirectUrl.match(/!3d([-\d.]+)!4d([-\d.]+)/)
const coordsMatch = redirectUrl.match(/!3d([-\d.]+)!4d([-\d.]+)/);
if (coordsMatch) { if (coordsMatch) {
return { return {
latitude: coordsMatch[1], latitude: coordsMatch[1],
longitude: coordsMatch[2], longitude: coordsMatch[2],
};
} }
} }
return null; }
}
return null
} catch {
return null
} }
} }

View file

@ -1,5 +1,4 @@
// import { Queue, Worker } from 'bullmq'; // import { Queue, Worker } from 'bullmq';
import { Expo } from 'expo-server-sdk';
// import { db } from '@/src/db/db_index' // import { db } from '@/src/db/db_index'
import { scaffoldAssetUrl } from '@/src/lib/s3-client' import { scaffoldAssetUrl } from '@/src/lib/s3-client'
import { queueDataPusher } from '@/src/lib/queue-data-pusher' import { queueDataPusher } from '@/src/lib/queue-data-pusher'
@ -51,6 +50,7 @@ export async function sendAdminNotification(data: {
imageUrl: string | null; imageUrl: string | null;
}) { }) {
const { token, title, body, imageUrl } = data; const { token, title, body, imageUrl } = data;
const { Expo } = await import('expo-server-sdk')
// Validate Expo push token // Validate Expo push token
if (!Expo.isExpoPushToken(token)) { if (!Expo.isExpoPushToken(token)) {

View file

@ -1,11 +1,5 @@
import axios from 'axios';
import { getIsDevMode, getTelegramBotToken, getTelegramChatIds } from '@/src/lib/env-exporter' import { getIsDevMode, getTelegramBotToken, getTelegramChatIds } from '@/src/lib/env-exporter'
/**
* Send a message to Telegram bot
* @param message The message text to send
* @returns Promise<boolean | null> indicating success, failure, or null if dev mode
*/
export const sendTelegramMessage = async (message: string): Promise<boolean | null> => { export const sendTelegramMessage = async (message: string): Promise<boolean | null> => {
if (getIsDevMode()) { if (getIsDevMode()) {
return null; return null;
@ -21,33 +15,32 @@ export const sendTelegramMessage = async (message: string): Promise<boolean | nu
const results = await Promise.all( const results = await Promise.all(
chatIds.map(async (chatId) => { chatIds.map(async (chatId) => {
try { try {
const response = await axios.post(`${telegramApiUrl}/sendMessage`, { const response = await fetch(`${telegramApiUrl}/sendMessage`, {
chat_id: chatId, method: 'POST',
text: message, headers: { 'Content-Type': 'application/json' },
parse_mode: 'HTML', body: JSON.stringify({ chat_id: chatId, text: message, parse_mode: 'HTML' }),
}); })
const data = await response.json() as { ok: boolean }
if (response.data && response.data.ok) { if (data.ok) {
console.log(`Telegram message sent successfully to ${chatId}`); console.log(`Telegram message sent successfully to ${chatId}`)
return true; return true
} else { } else {
console.error(`Telegram API error for ${chatId}:`, response.data); console.error(`Telegram API error for ${chatId}:`, data)
return false; return false
} }
} catch (error) { } catch (error) {
console.error(`Failed to send Telegram message to ${chatId}:`, error); console.error(`Failed to send Telegram message to ${chatId}:`, error)
return false; return false
} }
}) })
); )
console.log('sent telegram message successfully') console.log('sent telegram message successfully')
return results.some((result) => result)
// Return true if at least one message was sent successfully
return results.some((result) => result);
} catch (error) { } catch (error) {
console.error('Failed to send Telegram message:', error); console.error('Failed to send Telegram message:', error)
return false; return false
}
} }
};

View file

@ -6,7 +6,8 @@ import {
getCacheVersion, getCacheVersion,
} from '@/src/dbService' } from '@/src/dbService'
import type { StoresSummaryResponse } from '@packages/shared' import type { StoresSummaryResponse } from '@packages/shared'
import * as turf from '@turf/turf'; import { polygon as turfPolygon, point as turfPoint } from '@turf/helpers';
import { booleanPointInPolygon } from '@turf/boolean-point-in-polygon';
import { z } from 'zod'; import { z } from 'zod';
import { mbnrGeoJson } from '@/src/lib/mbnr-geojson' import { mbnrGeoJson } from '@/src/lib/mbnr-geojson'
import { generateUploadUrl } from '@/src/lib/s3-client' import { generateUploadUrl } from '@/src/lib/s3-client'
@ -15,7 +16,7 @@ import { getAllConstValues } from '@/src/lib/const-store'
import { CONST_KEYS } from '@/src/lib/const-keys' import { CONST_KEYS } from '@/src/lib/const-keys'
import { getAssetsDomain, getApiCacheKey } from '@/src/lib/env-exporter' import { getAssetsDomain, getApiCacheKey } from '@/src/lib/env-exporter'
const polygon = turf.polygon(mbnrGeoJson.features[0].geometry.coordinates); const polygon = turfPolygon(mbnrGeoJson.features[0].geometry.coordinates);
export async function scaffoldEssentialConsts() { export async function scaffoldEssentialConsts() {
const consts = await getAllConstValues(); const consts = await getAllConstValues();
@ -76,8 +77,8 @@ export const commonApiRouter = router({
.query(({ input }) => { .query(({ input }) => {
try { try {
const { lat, lng } = input; const { lat, lng } = input;
const point = turf.point([lng, lat]); // GeoJSON: [longitude, latitude] const point = turfPoint([lng, lat]); // GeoJSON: [longitude, latitude]
const isInside = turf.booleanPointInPolygon(point, polygon); const isInside = booleanPointInPolygon(point, polygon);
return { isInside }; return { isInside };
} catch (error) { } catch (error) {
throw new Error('Invalid coordinates or polygon data'); throw new Error('Invalid coordinates or polygon data');

View file

@ -15,6 +15,8 @@ import {
export { CacheCreator } export { CacheCreator }
let app: ReturnType<typeof createApp> | null = null
export default { export default {
async fetch( async fetch(
request: Request, request: Request,
@ -33,9 +35,10 @@ export default {
}, },
ctx: ExecutionContext ctx: ExecutionContext
) { ) {
console.log(env)
ensureWorkerInit(env) ensureWorkerInit(env)
const app = createApp() if (!app) {
app = createApp()
}
return app.fetch(request, env, ctx) return app.fetch(request, env, ctx)
}, },
async queue( async queue(

911
bun.lock

File diff suppressed because it is too large Load diff