From 933703ee4c8ad1154fbc08a3c03288739894c6bf Mon Sep 17 00:00:00 2001 From: TZGyn Date: Tue, 23 Jul 2024 06:10:34 +0800 Subject: [PATCH] update redirect to use geolite2 for geolocation --- README.md | 11 +++++++++++ redirect/.env.example | 4 +++- redirect/bun.lockb | Bin 26768 -> 30726 bytes redirect/package.json | 1 + redirect/src/index.ts | 36 ++++++++++++++++++++++++------------ 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 6e3ba6e..10998b5 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,17 @@ bun run src/index.ts ## Breaking Changes +### 23 July 2024 (For builds before this date) + +Transition from using ipbase to using geoipupdate for geolocation. + +Please add the following environment variables to your .env file + +```bash +GEOIPUPDATE_ACCOUNT_ID= +GEOIPUPDATE_LICENSE_KEY= +``` + ### 16 June 2024 (For builds before this date) (WARNING) Please backup your database before attempting diff --git a/redirect/.env.example b/redirect/.env.example index 0eddd23..9c42531 100644 --- a/redirect/.env.example +++ b/redirect/.env.example @@ -1,3 +1,5 @@ FALLBACK_URL=https://app.kon.sh DATABASE_URL=postgres://postgres:password@0.0.0.0:5432/link-shortener -APP_URL=kon.sh \ No newline at end of file +APP_URL=kon.sh +GEOIPUPDATE_ACCOUNT_ID= +GEOIPUPDATE_LICENSE_KEY= diff --git a/redirect/bun.lockb b/redirect/bun.lockb index d80d83f95766380e78b6a73b91a1d0ae927997a2..79e61a7eaac600a531ac402f86aba1c365f243d3 100755 GIT binary patch delta 5373 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 delta 3021 zcmd^BYiv|S6rQ=TZExT0R@&_r7DP%~VC!~Sx7!6STV5??NuagwmbO|;Lusomh6S`s zL?s#m^#p@4Adf`A7zwTfYk>q1{Q)Q%qF_h}5q@cnr^6mp`23%-QeE zIWuR@WAD5)B6oZtci8hbq`bdu#QXDtp&zS{eg46TljR>KymrcWFKcvvP1B}J!!=^H z&`0S&wQa_sB@rM*TW6rRqeX}f-B0SGGR%oW1bf;e8Z!p=+4`3$LZm^szOSu|)imHF zU$-Y6 z*R^+anPY^=1Rf8bA_QsDvSMef5GrJu;CyCB@2vLD?pCofPKbD5H7dUb%)XAnmVIb_ zrsavYULg*{nDuUhv%QZFOI!btDWbi$voioE#6FntDLpNHtJ{EY0<&jFpvU|GCM)=U zV7^HOCgy7by@=$W;Vi-tEH41({c@vx0(dI$LR`xtM19Z%0lS-z!_44Qz;y@OXY~bo z+Imkz8!AB~1^*0vck8;RU?PkZ9EUz%voAF?sw`G$m#JAkPGOTKw~!}BljkUa*++wz zU!XAN7wNa#`^$w(fgaI7Y;k|$1+Rtm&v>Z)-D+-eAjtzy|P^&SxKt9z*~MNo_NH9iHgOwnVR zqA7Rd>7$f+GMB;-Jx!ieO??Md!^)CmlG`)_R7fXdyz0ZKp81f&eT21@JZYLdMS(O; zO+&G8fZzx$nt{A@FU~99Bu}~~FHs;}Qx~BQ7C(A0j^2}g3ge%H@|_^!w|wlxM0sRqe^;@7vjRRG4y0OO5tOnv}A_zbP#OGzuX6$kvh@BUlMPO+`rPe`?Zu)LPzIrm-0l&r>#;#n@UEK;zy$So>@u*D@#ho?nee^4jrmj zK6eQZ19R=6N%b}SdFT~ggZ~H~eP#4YWiHLBm^p?&^AqWIwNp-} zsWpB%gPyLj$Rc{R#_uvdvLA1~{8`;kmn@2WzA$29yoAaw<){rCzj_`k(akhUs>zw%B{#xgE8IPmKo4>z5x})V6m=xLzd1K>w6u3I$Cd0ZmV>mKFjLEM-BxP%r7YY?QVU>9Voja_sgXF^%l94EDe6SkJ=lY z@+Q66;CC7Cp>SH;nz7jz-++a~KHKha3FBonuSq#^`F7lOeMJwii6%B$tj0^|)|I?9 z*XO)$*4G{OLevSZXtc-zT7$WWUTk!_qOYZ3>VmEBUO2lyBf1wZ(U%%|C5q%UoosSaNppI-2`#`;yIT=Cx~LM}nL!(x?PxxFySXqs85-!F;FcoS1-U+X ZY;|Qs^KLucX)X;dZ#kD9I`^zk{tlqNE-?TA diff --git a/redirect/package.json b/redirect/package.json index b5ae92e..725a9f3 100644 --- a/redirect/package.json +++ b/redirect/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "@elysiajs/cors": "^0.6.0", + "@maxmind/geoip2-node": "^5.0.0", "@types/pg": "^8.10.2", "@types/ua-parser-js": "^0.7.39", "elysia": "latest", diff --git a/redirect/src/index.ts b/redirect/src/index.ts index 7922f3f..e73a8ab 100644 --- a/redirect/src/index.ts +++ b/redirect/src/index.ts @@ -5,6 +5,8 @@ import { UAParser } from 'ua-parser-js' const fallback_url = Bun.env.FALLBACK_URL ?? 'https://app.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 app = new Elysia().use(cors()) @@ -20,9 +22,16 @@ app.get( const ip = request.headers.get('x-forwarded-for') - const geolocation = await ( - await fetch(`https://api.ipbase.com/v2/info?ip=${ip}`) - ).json() + 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') @@ -30,19 +39,23 @@ app.get( const query = db .selectFrom('shortener') - .leftJoin('project', 'project.id', 'shortener.project_id') .selectAll('shortener') - .select(['project.custom_domain as domain']) .where('shortener.code', '=', shortenerCode) - .where('project.custom_domain', '=', domain) - .orderBy('created_at', 'desc') if (domain) { - query.where('project.enable_custom_domain', '=', true) + query + .leftJoin('project', 'project.id', 'shortener.project_id') + .select(['project.custom_domain as domain']) + .where('project.custom_domain', '=', domain) + .where('project.enable_custom_domain', '=', true) } + query.orderBy('created_at', 'desc') + const shortener = await query.execute() + console.log('shortener', shortener) + if (!shortener.length || !shortener[0].active) { set.redirect = '/invalid' return @@ -50,10 +63,9 @@ app.get( const visitor_data = { shortener_id: shortener[0].id, - country: geolocation.data.location.country.name as string, - country_code: geolocation.data.location.country - .alpha2 as string, - city: geolocation.data.location.city.name as string, + 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,