From d94e3e650aa1133a8626816a283f34ae5d6c7242 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 4 Oct 2022 23:54:25 +0800 Subject: [PATCH] geoip: use context.service --- packages/geoip/index.ts | 34 +++++++++++++++++++++++++++ packages/geoip/lib.ts | 35 ---------------------------- packages/geoip/package.json | 5 +--- packages/hydrooj/src/context.ts | 3 ++- packages/hydrooj/src/handler/home.ts | 29 +++++++++++++---------- packages/hydrooj/src/interface.ts | 23 +++++++++--------- 6 files changed, 65 insertions(+), 64 deletions(-) create mode 100644 packages/geoip/index.ts delete mode 100644 packages/geoip/lib.ts diff --git a/packages/geoip/index.ts b/packages/geoip/index.ts new file mode 100644 index 000000000..165073318 --- /dev/null +++ b/packages/geoip/index.ts @@ -0,0 +1,34 @@ +import fs from 'fs'; +import { Reader } from 'maxmind'; +import { Context, findFileSync, Service } from 'hydrooj'; + +const buffer = fs.readFileSync(findFileSync('@hydrooj/geoip/GeoLite2-City.mmdb')); +const reader = new Reader(buffer); + +export interface Result { + location?: string, + continent?: string, + country?: string, + city?: string, + display: string +} + +export function apply() { + Context.service('geoip', class GeoIPService extends Service { + provider = 'MaxMind'; + lookup(ip: string, locale: string): Result { + const res: any = reader.get(ip); + if (!res) return { display: 'Unknown address'.translate(locale) }; + const ret: Result = { display: '' }; + if (res.location) ret.location = res.location; + if (res.continent) ret.continent = res.continent.names[locale] || res.continent.names.en; + if (res.country || res.registered_country) { + ret.country = (res.country || res.registered_country).names[locale] + || (res.country || res.registered_country).names.en; + } + if (res.city) ret.city = res.city.names[locale] || res.city.names.en; + ret.display = `${ret.continent} ${ret.country}${ret.city ? ` ${ret.city}` : ''}`; + return ret; + } + }); +} diff --git a/packages/geoip/lib.ts b/packages/geoip/lib.ts deleted file mode 100644 index dd6fe6118..000000000 --- a/packages/geoip/lib.ts +++ /dev/null @@ -1,35 +0,0 @@ -import 'hydrooj'; - -import fs from 'fs'; -import { Reader } from 'maxmind'; -import { findFileSync } from '@hydrooj/utils/lib/utils'; - -const buffer = fs.readFileSync(findFileSync('@hydrooj/geoip/GeoLite2-City.mmdb')); -const reader = new Reader(buffer); - -export interface Result { - location?: string, - continent?: string, - country?: string, - city?: string, - display: string -} - -export function lookup(ip: string, locale: string): Result { - const res: any = reader.get(ip); - if (!res) return { display: 'Unknown address'.translate(locale) }; - const ret: Result = { display: '' }; - if (res.location) ret.location = res.location; - if (res.continent) ret.continent = res.continent.names[locale] || res.continent.names.en; - if (res.country || res.registered_country) { - ret.country = (res.country || res.registered_country).names[locale] - || (res.country || res.registered_country).names.en; - } - if (res.city) ret.city = res.city.names[locale] || res.city.names.en; - ret.display = `${ret.continent} ${ret.country}${ret.city ? ` ${ret.city}` : ''}`; - return ret; -} - -export const provider = 'MaxMind'; - -global.Hydro.lib.geoip = { provider, lookup }; diff --git a/packages/geoip/package.json b/packages/geoip/package.json index 0eb7171f0..53e447854 100644 --- a/packages/geoip/package.json +++ b/packages/geoip/package.json @@ -1,7 +1,7 @@ { "name": "@hydrooj/geoip", "version": "1.2.3", - "main": "package.json", + "main": "index.ts", "repository": "git@github.com:hydro-dev/Hydro.git", "author": "undefined ", "license": "AGPL-3.0-or-later", @@ -11,8 +11,5 @@ "preferUnplugged": true, "scripts": { "prepublish": "./download.sh" - }, - "peerDependencies": { - "hydrooj": "*" } } diff --git a/packages/hydrooj/src/context.ts b/packages/hydrooj/src/context.ts index e16f0f2c8..45420557d 100644 --- a/packages/hydrooj/src/context.ts +++ b/packages/hydrooj/src/context.ts @@ -1,6 +1,6 @@ import * as cordis from 'cordis'; import Schema from 'schemastery'; -import { ModuleInterfaces } from './interface'; +import { GeoIP, ModuleInterfaces } from './interface'; import { inject } from './lib/ui'; import { Loader } from './loader'; import { EventMap } from './service/bus'; @@ -33,6 +33,7 @@ export interface Context { inject: typeof inject; api: ApiMixin; broadcast: Context['emit']; + geoip?: GeoIP; } export class Context extends cordis.Context { diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index 4ad8f2c23..d89923c9e 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -1,6 +1,7 @@ import yaml from 'js-yaml'; import { ObjectID } from 'mongodb'; import { camelCase } from '@hydrooj/utils/lib/utils'; +import { Context } from '../context'; import { BlacklistedError, DomainAlreadyExistsError, InvalidTokenError, NotFoundError, PermissionError, UserAlreadyExistError, @@ -9,6 +10,7 @@ import { import { DomainDoc, MessageDoc, Setting } from '../interface'; import avatar from '../lib/avatar'; import * as mail from '../lib/mail'; +import * as useragent from '../lib/useragent'; import { isDomainId, isEmail, isPassword } from '../lib/validator'; import BlackListModel from '../model/blacklist'; import { PERM, PRIV } from '../model/builtin'; @@ -28,8 +30,6 @@ import { } from '../service/server'; import { md5 } from '../utils'; -const { geoip, useragent } = global.Hydro.lib; - export class HomeHandler extends Handler { uids = new Set(); @@ -147,6 +147,7 @@ export class HomeHandler extends Handler { } } +let geoip: Context['geoip'] = null; class HomeSecurityHandler extends Handler { async get() { // TODO(iceboy): pagination? or limit session count for uid? @@ -154,17 +155,18 @@ class HomeSecurityHandler extends Handler { for (const session of sessions) { session.isCurrent = session._id === this.session._id; session._id = md5(session._id); - if (useragent) session.updateUa = useragent.parse(session.updateUa || session.createUa || ''); - if (geoip) { - session.updateGeoip = geoip.lookup( - session.updateIp || session.createIp, - this.translate('geoip_locale'), - ); - } + session.updateUa = useragent.parse(session.updateUa || session.createUa || ''); + session.updateGeoip = geoip?.lookup?.( + session.updateIp || session.createIp, + this.translate('geoip_locale'), + ); } this.response.template = 'home_security.html'; - this.response.body = { sessions, geoipProvider: geoip?.provider }; - if (useragent) this.response.body.icon = useragent.icon; + this.response.body = { + sessions, + geoipProvider: geoip?.provider, + icon: useragent.icon, + }; } @param('current', Types.String) @@ -432,7 +434,10 @@ class HomeMessagesConnectionHandler extends ConnectionHandler { } } -export async function apply(ctx) { +export async function apply(ctx: Context) { + ctx.using(['geoip'], (g) => { + geoip = g.geoip; + }); ctx.Route('homepage', '/', HomeHandler); ctx.Route('home_security', '/home/security', HomeSecurityHandler, PRIV.PRIV_USER_PROFILE); ctx.Route('user_changemail_with_code', '/home/changeMail/:code', UserChangemailWithCodeHandler, PRIV.PRIV_USER_PROFILE); diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index f81f08872..26c2d739d 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -671,18 +671,17 @@ export interface ProblemSearchOptions { export type ProblemSearch = (domainId: string, q: string, options?: ProblemSearchOptions) => Promise; export interface Lib extends Record { - difficulty: typeof import('./lib/difficulty'), - buildContent: typeof import('./lib/content').buildContent, - i18n: typeof import('./lib/i18n'), - mail: typeof import('./lib/mail'), - paginate: typeof import('./lib/paginate'), - rank: typeof import('./lib/rank'), - rating: typeof import('./lib/rating'), - testdataConfig: typeof import('./lib/testdataConfig'), - useragent: typeof import('./lib/useragent'), - validator: typeof import('./lib/validator'), - template?: any, - geoip?: GeoIP, + difficulty: typeof import('./lib/difficulty'); + buildContent: typeof import('./lib/content').buildContent; + i18n: typeof import('./lib/i18n'); + mail: typeof import('./lib/mail'); + paginate: typeof import('./lib/paginate'); + rank: typeof import('./lib/rank'); + rating: typeof import('./lib/rating'); + testdataConfig: typeof import('./lib/testdataConfig'); + useragent: typeof import('./lib/useragent'); + validator: typeof import('./lib/validator'); + template?: any; problemSearch: ProblemSearch; }