|
|
|
@ -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
|
|
|
|
|