added rate limiter + click limiter to redirect

main
TZGyn 1 year ago
parent 7bd9725bd0
commit 8a6aef7430
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

Binary file not shown.

@ -10,7 +10,8 @@
"@maxmind/geoip2-node": "^5.0.0", "@maxmind/geoip2-node": "^5.0.0",
"@types/pg": "^8.10.2", "@types/pg": "^8.10.2",
"@types/ua-parser-js": "^0.7.39", "@types/ua-parser-js": "^0.7.39",
"elysia": "latest", "elysia": "^1.1.5",
"elysia-rate-limit": "^4.1.0",
"kysely": "^0.26.3", "kysely": "^0.26.3",
"magic-regexp": "^0.7.0", "magic-regexp": "^0.7.0",
"nanoid": "^5.0.1", "nanoid": "^5.0.1",

@ -2,14 +2,28 @@ import { Elysia } from 'elysia'
import { db } from './database' import { db } from './database'
import { cors } from '@elysiajs/cors' import { cors } from '@elysiajs/cors'
import { UAParser } from 'ua-parser-js' import { UAParser } from 'ua-parser-js'
import geoip2 from '@maxmind/geoip2-node'
import { rateLimit } from 'elysia-rate-limit'
import { LRUCache } from 'lru-cache'
const WebServiceClient = geoip2.WebServiceClient
const fallback_url = Bun.env.FALLBACK_URL ?? 'https://app.kon.sh' const fallback_url = Bun.env.FALLBACK_URL ?? 'https://app.kon.sh'
const app_url = Bun.env.APP_URL ?? 'kon.sh' const app_url = Bun.env.APP_URL ?? 'kon.sh'
const geoipupdate_account_id = Bun.env.GEOIPUPDATE_ACCOUNT_ID
const geoipupdate_license_key = Bun.env.GEOIPUPDATE_LICENSE_KEY
const hosting_provider = Bun.env.HOSTING_PROVIDER const hosting_provider = Bun.env.HOSTING_PROVIDER
const app = new Elysia().use(cors()) const client = new WebServiceClient(
Bun.env.GEOIPUPDATE_ACCOUNT_ID || '',
Bun.env.GEOIPUPDATE_LICENSE_KEY || '',
{ host: 'geolite.info' }
)
const clickLimiter = new LRUCache({
ttl: 60 * 60 * 60 * 1000, // 1 hr
ttlAutopurge: true,
})
const app = new Elysia().use(cors()).use(rateLimit({ duration: 1000 }))
app.get('/', ({ set }) => (set.redirect = fallback_url + '/landing')) app.get('/', ({ set }) => (set.redirect = fallback_url + '/landing'))
app.get('/invalid', () => 'Invalid Shortener') app.get('/invalid', () => 'Invalid Shortener')
@ -17,7 +31,7 @@ app.get('/robots.txt', () => Bun.file('public/robots.txt'))
app.get( app.get(
'/:shortenerCode', '/:shortenerCode',
async ({ params: { shortenerCode }, set, request }) => { async ({ params: { shortenerCode }, set, request, cookie }) => {
try { try {
const request_domain = request.headers.get('host') const request_domain = request.headers.get('host')
const domain = request_domain !== app_url ? request_domain : null const domain = request_domain !== app_url ? request_domain : null
@ -28,21 +42,6 @@ app.get(
: 'x-forwarded-for' : 'x-forwarded-for'
) )
const WebServiceClient =
require('@maxmind/geoip2-node').WebServiceClient
const client = new WebServiceClient(
geoipupdate_account_id,
geoipupdate_license_key,
{ host: 'geolite.info' }
)
const geolocation = await client.city(ip)
const user_agent = request.headers.get('User-Agent')
const ua_parser = new UAParser(user_agent ?? '')
const query = db const query = db
.selectFrom('shortener') .selectFrom('shortener')
.selectAll('shortener') .selectAll('shortener')
@ -60,26 +59,15 @@ app.get(
const shortener = await query.execute() const shortener = await query.execute()
console.log('shortener', shortener) const user_agent = request.headers.get('User-Agent')
const ua_parser = new UAParser(user_agent ?? '')
if (!shortener.length || !shortener[0].active) { if (!shortener.length || !shortener[0].active) {
set.redirect = '/invalid' set.redirect = '/invalid'
return return
} }
const visitor_data = {
shortener_id: shortener[0].id,
country: geolocation.country.names.en as string,
country_code: geolocation.country.isoCode as string,
city: geolocation.city.names.en as string,
device_type: ua_parser.getDevice().type || 'desktop',
device_vendor: ua_parser.getDevice().vendor,
browser: ua_parser.getBrowser().name,
os: ua_parser.getOS().name,
}
await db.insertInto('visitor').values(visitor_data).execute()
if ( if (
ua_parser.getOS().name === 'iOS' && ua_parser.getOS().name === 'iOS' &&
shortener[0].ios && shortener[0].ios &&
@ -95,6 +83,28 @@ app.get(
} else { } else {
set.redirect = shortener[0].link set.redirect = shortener[0].link
} }
const clickKey = `${ip}_${shortener[0].id}`
const clickLimited = clickLimiter.has(clickKey)
if (clickLimited) return
clickLimiter.set(clickKey, 1)
const geolocation = await client.city(ip || '')
const visitor_data = {
shortener_id: shortener[0].id,
country: geolocation.country!.names.en,
country_code: geolocation.country!.isoCode,
city: geolocation.city!.names.en,
device_type: ua_parser.getDevice().type || 'desktop',
device_vendor: ua_parser.getDevice().vendor,
browser: ua_parser.getBrowser().name,
os: ua_parser.getOS().name,
}
await db.insertInto('visitor').values(visitor_data).execute()
} catch (error) { } catch (error) {
console.error(error) console.error(error)
set.redirect = fallback_url set.redirect = fallback_url

Loading…
Cancel
Save