all repos — red-anatomia @ 43cc40161c75c7c9bb5bef2c1ce2d551b7f24484

red-anatomia

src/detection/dataset.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
import { readFileSync, existsSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

export interface Fingerprint {
  cats?: number[];
  html?: string | string[];
  text?: string | string[];
  css?: string | string[];
  headers?: Record<string, string>;
  meta?: Record<string, string | string[]>;
  cookies?: Record<string, string>;
  scriptSrc?: string | string[];
  scripts?: string | string[];
  url?: string | string[];
  js?: Record<string, string>;
  dns?: Record<string, string | string[]>;
  certIssuer?: string;
  implies?: string | string[];
  requires?: string | string[];
  excludes?: string | string[];
  website?: string;
  icon?: string;
  description?: string;
}

export interface Categoria {
  name: string;
  priority: number;
}

export interface Dataset {
  tecnologias: Record<string, Fingerprint>;
  categorias: Record<string, Categoria>;
  meta: { versao?: string; atualizadoEm?: string };
}

let cache: Dataset | undefined;

function acharPastaDados(): string {
  const candidatos: string[] = [];
  let dir = dirname(fileURLToPath(import.meta.url));
  for (let i = 0; i < 6; i++) {
    candidatos.push(join(dir, 'data', 'fingerprints'));
    dir = dirname(dir);
  }
  candidatos.push(join(process.cwd(), 'data', 'fingerprints'));

  for (const c of candidatos) {
    if (existsSync(join(c, 'technologies.json'))) return c;
  }
  throw new Error('Não encontrei o dataset de fingerprints (data/fingerprints/technologies.json).');
}

export function carregarDataset(): Dataset {
  if (cache) return cache;
  const pasta = acharPastaDados();

  const tecnologias = lerJson<Record<string, Fingerprint>>(join(pasta, 'technologies.json'));
  const categorias = lerJson<Record<string, Categoria>>(join(pasta, 'categories.json'));
  const meta = existsSync(join(pasta, 'meta.json'))
    ? lerJson<{ versao?: string; atualizadoEm?: string }>(join(pasta, 'meta.json'))
    : {};

  cache = { tecnologias, categorias, meta };
  return cache;
}

function lerJson<T>(caminho: string): T {
  return JSON.parse(readFileSync(caminho, 'utf8')) as T;
}