]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/geo-ip.ts
Fix live constraints tests
[github/Chocobozzz/PeerTube.git] / server / helpers / geo-ip.ts
CommitLineData
b2111066
C
1import { pathExists, writeFile } from 'fs-extra'
2import maxmind, { CountryResponse, Reader } from 'maxmind'
3import { join } from 'path'
4import { CONFIG } from '@server/initializers/config'
5import { logger, loggerTagsFactory } from './logger'
6import { isBinaryResponse, peertubeGot } from './requests'
7
8const lTags = loggerTagsFactory('geo-ip')
9
10const mmbdFilename = 'dbip-country-lite-latest.mmdb'
11const mmdbPath = join(CONFIG.STORAGE.BIN_DIR, mmbdFilename)
12
13export class GeoIP {
14 private static instance: GeoIP
15
16 private reader: Reader<CountryResponse>
17
18 private constructor () {
19 }
20
21 async safeCountryISOLookup (ip: string): Promise<string> {
22 if (CONFIG.GEO_IP.ENABLED === false) return null
23
24 await this.initReaderIfNeeded()
25
26 try {
27 const result = this.reader.get(ip)
28 if (!result) return null
29
30 return result.country.iso_code
31 } catch (err) {
32 logger.error('Cannot get country from IP.', { err })
33
34 return null
35 }
36 }
37
38 async updateDatabase () {
39 if (CONFIG.GEO_IP.ENABLED === false) return
40
41 const url = CONFIG.GEO_IP.COUNTRY.DATABASE_URL
42
43 logger.info('Updating GeoIP database from %s.', url, lTags())
44
45 const gotOptions = { context: { bodyKBLimit: 200_000 }, responseType: 'buffer' as 'buffer' }
46
47 try {
48 const gotResult = await peertubeGot(url, gotOptions)
49
50 if (!isBinaryResponse(gotResult)) {
51 throw new Error('Not a binary response')
52 }
53
54 await writeFile(mmdbPath, gotResult.body)
55
9295c68b 56 // Reinit reader
b2111066
C
57 this.reader = undefined
58
59 logger.info('GeoIP database updated %s.', mmdbPath, lTags())
60 } catch (err) {
61 logger.error('Cannot update GeoIP database from %s.', url, { err, ...lTags() })
62 }
63 }
64
65 private async initReaderIfNeeded () {
66 if (!this.reader) {
67 if (!await pathExists(mmdbPath)) {
68 await this.updateDatabase()
69 }
70
71 this.reader = await maxmind.open(mmdbPath)
72 }
73 }
74
75 static get Instance () {
76 return this.instance || (this.instance = new this())
77 }
78}