wandering-eye/src/lib/lookup.ts

95 lines
2.2 KiB
TypeScript

import net from 'node:net'
import TsCache from '$lib/ts-cache.js'
import geoip from 'geoip-lite'
import whoiser from 'whoiser'
import {
AbuseIPDBClient,
type APICheckEndpointResponse
} from 'abuseipdb-client'
import type { Whois } from './Result/ip'
export const WHOIS_CACHE_TTL = process.env.WHOIS_CACHE_TTL
? parseInt(process.env.WHOIS_CACHE_TTL)
: 60 * 60 * 24
const ABUSEIPDB_KEY = process.env.ABUSEIPDB_KEY
let ipdb: AbuseIPDBClient | null = null
if (ABUSEIPDB_KEY) ipdb = new AbuseIPDBClient(ABUSEIPDB_KEY)
const whoisCache = new TsCache<Lookup>(WHOIS_CACHE_TTL)
function isIp(query: string) {
const isIp = net.isIP(query)
if (isIp == 4 || isIp == 6) return true
return false
}
async function whoisLookup(query: string, ip: boolean = false) {
const whoisCheck = await whoiser(query, {
timeout: 1000
})
const whoisData = ip
? whoisCheck
: Object.values(whoisCheck)
.reverse()
// @ts-expect-error whoiser types are wrong
.find(a => !a.error)
if (!whoisData) throw new Error("Couldn't get successful Whois response")
return whoisData
}
function geoLookup(query: string) {
const geoLookup = geoip.lookup(query)
// Don't want to use geo location if it's just the center of America
if (geoLookup && geoLookup.ll[0] != 37.751 && geoLookup.ll[1] != -97.822) {
return geoLookup
}
return null
}
type IPDBLookup = APICheckEndpointResponse['data']
async function ipdbLookup(query: string): Promise<IPDBLookup | null> {
const ipdbCheck = await ipdb?.check(query, { maxAgeInDays: 60 })
return ipdbCheck?.result?.data ?? null
}
export type Lookup = {
query: string
whois: Whois
geo: geoip.Lookup | null
check: IPDBLookup | null
isIp: boolean
}
export default async function lookup(query: string) {
const ip = isIp(query)
if (whoisCache.has(query)) {
const value = whoisCache.get(query)
if (value) return value
}
let whoquery = query
if (!ip) {
whoquery = whoquery
.split('.')
.slice(whoquery.split('.').length - 2)
.join('.')
}
const whois = <Whois>await whoisLookup(whoquery, ip)
const geo = ip ? geoLookup(query) : null
const check = ip ? await ipdbLookup(query) : null
const value = {
query,
whois,
geo,
check,
isIp: ip
}
whoisCache.set(query, value)
return value
}