regions + city
parent
2575cbfc11
commit
117d7c4400
|
@ -1,8 +1,7 @@
|
||||||
import path from 'path';
|
|
||||||
import requestIp from 'request-ip';
|
import requestIp from 'request-ip';
|
||||||
import { browserName, detectOS } from 'detect-browser';
|
import { browserName, detectOS } from 'detect-browser';
|
||||||
import isLocalhost from 'is-localhost-ip';
|
import isLocalhost from 'is-localhost-ip';
|
||||||
import maxmind from 'maxmind';
|
import geoip from 'fast-geoip';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DESKTOP_OS,
|
DESKTOP_OS,
|
||||||
|
@ -12,8 +11,6 @@ import {
|
||||||
MOBILE_SCREEN_WIDTH,
|
MOBILE_SCREEN_WIDTH,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
let lookup;
|
|
||||||
|
|
||||||
export function getIpAddress(req) {
|
export function getIpAddress(req) {
|
||||||
// Cloudflare
|
// Cloudflare
|
||||||
if (req.headers['cf-connecting-ip']) {
|
if (req.headers['cf-connecting-ip']) {
|
||||||
|
@ -51,7 +48,7 @@ export function getDevice(screen, browser, os) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCountry(req, ip) {
|
export async function getLocation(req, ip) {
|
||||||
// Cloudflare
|
// Cloudflare
|
||||||
if (req.headers['cf-ipcountry']) {
|
if (req.headers['cf-ipcountry']) {
|
||||||
return req.headers['cf-ipcountry'];
|
return req.headers['cf-ipcountry'];
|
||||||
|
@ -62,23 +59,24 @@ export async function getCountry(req, ip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database lookup
|
const result = await geoip.lookup(ip);
|
||||||
if (!lookup) {
|
|
||||||
lookup = await maxmind.open(path.resolve('./public/geo/GeoLite2-Country.mmdb'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = lookup.get(ip);
|
return {
|
||||||
|
country: result?.country,
|
||||||
return result?.country?.iso_code;
|
region: result?.region,
|
||||||
|
city: result?.city,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getClientInfo(req, { screen }) {
|
export async function getClientInfo(req, { screen }) {
|
||||||
const userAgent = req.headers['user-agent'];
|
const userAgent = req.headers['user-agent'];
|
||||||
const ip = getIpAddress(req);
|
const ip = getIpAddress(req);
|
||||||
const country = await getCountry(req, ip);
|
const country = await getLocation(req, ip).country;
|
||||||
|
const region = await getLocation(req, ip).region;
|
||||||
|
const city = await getLocation(req, ip).city;
|
||||||
const browser = browserName(userAgent);
|
const browser = browserName(userAgent);
|
||||||
const os = detectOS(userAgent);
|
const os = detectOS(userAgent);
|
||||||
const device = getDevice(screen, browser, os);
|
const device = getDevice(screen, browser, os);
|
||||||
|
|
||||||
return { userAgent, browser, os, ip, country, device };
|
return { userAgent, browser, os, ip, country, device, region, city };
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,10 @@ export async function getSession(req) {
|
||||||
throw new Error(`Invalid website: ${website_uuid}`);
|
throw new Error(`Invalid website: ${website_uuid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { userAgent, browser, os, ip, country, device } = await getClientInfo(req, payload);
|
const { userAgent, browser, os, ip, country, device, region, city } = await getClientInfo(
|
||||||
|
req,
|
||||||
|
payload,
|
||||||
|
);
|
||||||
|
|
||||||
const website = await getWebsiteByUuid(website_uuid);
|
const website = await getWebsiteByUuid(website_uuid);
|
||||||
|
|
||||||
|
@ -46,6 +49,8 @@ export async function getSession(req) {
|
||||||
language,
|
language,
|
||||||
country,
|
country,
|
||||||
device,
|
device,
|
||||||
|
region,
|
||||||
|
city,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
"build-tracker": "rollup -c rollup.tracker.config.js",
|
"build-tracker": "rollup -c rollup.tracker.config.js",
|
||||||
"build-db": "npm-run-all copy-db-schema build-db-client",
|
"build-db": "npm-run-all copy-db-schema build-db-client",
|
||||||
"build-lang": "npm-run-all format-lang compile-lang",
|
"build-lang": "npm-run-all format-lang compile-lang",
|
||||||
"build-geo": "node scripts/build-geo.js",
|
|
||||||
"build-db-schema": "dotenv prisma introspect",
|
"build-db-schema": "dotenv prisma introspect",
|
||||||
"build-db-client": "dotenv prisma generate",
|
"build-db-client": "dotenv prisma generate",
|
||||||
"build-mysql-schema": "dotenv prisma introspect -- --schema=./prisma/schema.mysql.prisma",
|
"build-mysql-schema": "dotenv prisma introspect -- --schema=./prisma/schema.mysql.prisma",
|
||||||
|
@ -72,6 +71,7 @@
|
||||||
"date-fns-tz": "^1.1.4",
|
"date-fns-tz": "^1.1.4",
|
||||||
"detect-browser": "^5.2.0",
|
"detect-browser": "^5.2.0",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
"fast-geoip": "^1.1.40",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"immer": "^9.0.6",
|
"immer": "^9.0.6",
|
||||||
"ipaddr.js": "^2.0.1",
|
"ipaddr.js": "^2.0.1",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'lib/queri
|
||||||
import { ok, methodNotAllowed, unauthorized, badRequest } from 'lib/response';
|
import { ok, methodNotAllowed, unauthorized, badRequest } from 'lib/response';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
|
|
||||||
const sessionColumns = ['browser', 'os', 'device', 'country'];
|
const sessionColumns = ['browser', 'os', 'device', 'country', 'region', 'city'];
|
||||||
const pageviewColumns = ['url', 'referrer'];
|
const pageviewColumns = ['url', 'referrer'];
|
||||||
|
|
||||||
function getTable(type) {
|
function getTable(type) {
|
||||||
|
|
|
@ -62,6 +62,8 @@ model session {
|
||||||
screen String? @db.VarChar(11)
|
screen String? @db.VarChar(11)
|
||||||
language String? @db.VarChar(35)
|
language String? @db.VarChar(35)
|
||||||
country String? @db.Char(2)
|
country String? @db.Char(2)
|
||||||
|
region String? @db.VarChar(35)
|
||||||
|
city String? @db.VarChar(100)
|
||||||
website website @relation(fields: [website_id], references: [website_id])
|
website website @relation(fields: [website_id], references: [website_id])
|
||||||
event event[]
|
event event[]
|
||||||
pageview pageview[]
|
pageview pageview[]
|
||||||
|
|
|
@ -6,7 +6,7 @@ const zlib = require('zlib');
|
||||||
const tar = require('tar');
|
const tar = require('tar');
|
||||||
|
|
||||||
let url =
|
let url =
|
||||||
'https://raw.githubusercontent.com/GitSquared/node-geolite2-redist/master/redist/GeoLite2-Country.tar.gz';
|
'https://raw.githubusercontent.com/GitSquared/node-geolite2-redist/master/redist/GeoLite2-City.tar.gz';
|
||||||
|
|
||||||
if (process.env.MAXMIND_LICENSE_KEY) {
|
if (process.env.MAXMIND_LICENSE_KEY) {
|
||||||
url =
|
url =
|
||||||
|
|
Loading…
Reference in New Issue