Ctrl K
ComunidadGuías…

src/services/conversion.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { formatNumberValue } from '~/services/formatLocale'

export function toFixed(value: number, fixed: number) {
  if (fixed === 0)
    return value
  const factor = 10 ** fixed
  return Math.round((value + Number.EPSILON) * factor) / factor
}
export function bytesToGb(bytes: number, fixes = 0) {
  return toFixed(Math.round(((bytes / 1024.0 / 1024.0 / 1024.0) + Number.EPSILON) * 100) / 100, fixes)
}
/**
 * Formats bytes to a human-readable string with the appropriate unit (B, KB, MB, GB, TB).
 * Automatically picks the right unit based on the size.
 */
export function formatBytes(bytes: number, decimals = 2): string {
  if (bytes === 0)
    return '0 B'
  if (!Number.isFinite(bytes) || bytes < 0)
    return '0 B'

  const k = 1024
  const dm = Math.max(0, decimals)
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))
  const index = Math.min(i, sizes.length - 1)

  return `${formatNumberValue(toFixed(bytes / k ** index, dm), { maximumFractionDigits: dm })} ${sizes[index]}`
}

export function getDaysBetweenDates(date1: string | Date, date2: string | Date) {
  const oneDay = 24 * 60 * 60 * 1000
  const firstDate = new Date(date1)
  const secondDate = new Date(date2)
  // Normalize both dates to UTC midnight — dashboard stats are bucketed by UTC day
  firstDate.setUTCHours(0, 0, 0, 0)
  secondDate.setUTCHours(0, 0, 0, 0)
  const res = Math.round(Math.abs((firstDate.valueOf() - secondDate.valueOf()) / oneDay))
  return res
}

export type ChecksumType = 'sha256' | 'crc32' | 'unknown'

export interface ChecksumInfo {
  type: ChecksumType
  label: string
  minPluginVersion: string
  features: string[]
}

/**
 * Detects the checksum algorithm type based on the hash string length.
 * SHA-256 = 64 hex characters (256 bits)
 * CRC32 = 8 hex characters (32 bits)
 *
 * Algorithm selection in CLI:
 * - SHA-256: Used with V2 encryption OR v6+, v7+, v8+
 * - CRC32: Used with v5 without V2 encryption
 *
 * Encrypted bundles store the RSA-encrypted digest (hex for V3, base64 for V2),
 * so its length says nothing about the algorithm. The CLI always hashes
 * encrypted bundles with SHA-256, so pass `encrypted` when the bundle has a
 * session key.
 */
export function getChecksumInfo(checksum: string | null | undefined, encrypted = false): ChecksumInfo {
  if (!checksum) {
    return {
      type: 'unknown',
      label: 'Unknown',
      minPluginVersion: '-',
      features: [],
    }
  }

  if (encrypted) {
    return {
      type: 'sha256',
      label: 'SHA-256 (encrypted)',
      minPluginVersion: 'v5 + encryption, v6, v7, v8',
      features: ['integrity-verification', 'corruption-detection', 'security'],
    }
  }

  const length = checksum.length

  // SHA-256: 64 hex characters
  // Used with V2 encryption OR plugin v6+, v7+, v8+
  if (length === 64) {
    return {
      type: 'sha256',
      label: 'SHA-256',
      minPluginVersion: 'v5 + encryption, v6, v7, v8',
      features: ['integrity-verification', 'corruption-detection', 'security'],
    }
  }

  // CRC32: 8 hex characters
  // Used with v5 without V2 encryption
  if (length === 8) {
    return {
      type: 'crc32',
      label: 'CRC32',
      minPluginVersion: 'v5 without encryption',
      features: ['fast-verification', 'corruption-detection'],
    }
  }

  return {
    type: 'unknown',
    label: 'Unknown',
    minPluginVersion: '-',
    features: [],
  }
}