File

src/utils/utils.service.ts

Index

Properties
Methods

Constructor

constructor(configService: ConfigService)
Parameters :
Name Type Optional
configService ConfigService No

Methods

Public buildConfirmUrl
buildConfirmUrl(code: string)
Parameters :
Name Type Optional
code string No
Returns : string
Public Async comparePass
comparePass(raw: string, hash: string)
Parameters :
Name Type Optional
raw string No
hash string No
Returns : Promise<boolean>
Public computeQueryObj
computeQueryObj(query?: string, extQuery?: string, favs?: boolean)
Parameters :
Name Type Optional
query string Yes
extQuery string Yes
favs boolean Yes
Returns : ComputedQueryResult
Public Async convertStreamToBuffer
convertStreamToBuffer(readable: Readable)
Parameters :
Name Type Optional
readable Readable No
Returns : Promise<Buffer>
Public createSignal
createSignal(signal: Sig, data)
Type parameters :
  • Sig
Parameters :
Name Type Optional
signal Sig No
data No
Public Async createUniformIds
createUniformIds(idLength: number, ids: number)
Parameters :
Name Type Optional Default value
idLength number No 10
ids number No 8
Returns : Promise<string[]>
Public decrypt
decrypt(data: string)
Parameters :
Name Type Optional
data string No
Returns : any
Public deeplyLocalizeObject
deeplyLocalizeObject(o: T, locale: string)
Type parameters :
  • T
Parameters :
Name Type Optional
o T No
locale string No
Returns : Object | Array
Public didTimeStampExpire
didTimeStampExpire(timeStamp: number)
Parameters :
Name Type Optional
timeStamp number No
Returns : boolean
Public encrypt
encrypt(data: string)
Parameters :
Name Type Optional
data string No
Returns : any
Public exploreStringsInUnknownObject
exploreStringsInUnknownObject(o: Object | Array<>)
Parameters :
Name Type Optional
o Object | Array<> No
Returns : {}
Public formatStr
formatStr(str: string, ...data: string[])
Parameters :
Name Type Optional
str string No
data string[] No
Returns : string
Public Async generateSnowflake
generateSnowflake(l: number)
Parameters :
Name Type Optional Default value
l number No 30
Returns : Promise<string>
Public getImageExtension
getImageExtension(img: string)
Parameters :
Name Type Optional
img string No
Returns : string
Public getImageName
getImageName(img: string)
Parameters :
Name Type Optional
img string No
Returns : string
Public Async hashPass
hashPass(pass: string)
Parameters :
Name Type Optional
pass string No
Returns : Promise<string>
Public humanize
humanize(dur: number)
Parameters :
Name Type Optional
dur number No
Returns : string
Private isEmail
isEmail(str: string)

The decorator should be used when possible

Parameters :
Name Type Optional
str string No
Returns : boolean
Public isImage
isImage(t: string)
Parameters :
Name Type Optional
t string No
Returns : any
Public isObjectRegular
isObjectRegular(o: Object)
Parameters :
Name Type Optional
o Object No
Returns : boolean
Public isOnlyDigit
isOnlyDigit(t: string)
Parameters :
Name Type Optional
t string No
Returns : any
Public isUpper
isUpper(t: string)
Parameters :
Name Type Optional
t string No
Returns : any
Public isUrl
isUrl(t: string)
Parameters :
Name Type Optional
t string No
Returns : any
Public parseTimeStr
parseTimeStr(str: string)
Parameters :
Name Type Optional
str string No
Returns : number
Public partitionArray
partitionArray(arr: T, length: number)
Type parameters :
  • T
Parameters :
Name Type Optional
arr T No
length number No
Returns : T[]
Public setAllPropsTo
setAllPropsTo(o: literal type, value: T)
Type parameters :
  • T
Parameters :
Name Type Optional
o literal type No
value T No
Returns : literal type
Public sha
sha(raw: string)
Parameters :
Name Type Optional
raw string No
Returns : string
Public splitMime
splitMime(mime: string, side: "type" | "extension")
Parameters :
Name Type Optional
mime string No
side "type" | "extension" No
Returns : string
Public stripExif
stripExif(data: Buffer)
Parameters :
Name Type Optional
data Buffer No
Returns : Buffer
Public transformCredential
transformCredential(data: string)
Parameters :
Name Type Optional
data string No
Returns : literal type

Properties

Public Enums
Type : object
Default value : { Responses: Resps, Codes: CodesEnum }
Private Readonly logger
Default value : new Logger(UtilsService.name)
import { Injectable, Logger } from '@nestjs/common';
import * as Resps from './enums/responses.enum';
import * as crypto from 'crypto';
import * as bcrypt from 'bcrypt';
import * as CodesEnum from './enums/codes.enum';
import { ConfigService } from '@nestjs/config';
import { nanoid, customAlphabet } from 'nanoid/async';
const modifyExif = require('modify-exif');
import timestring from 'timestring';
import humanizeDuration from 'humanize-duration';

import { extname } from 'path';
import { ComputedQueryResult } from 'types';
import GetLocale from '../locales/getter';
import { Signals } from './enums/responses.enum';
import { Readable } from 'stream';
@Injectable()
export class UtilsService {
  public Enums = { Responses: Resps, Codes: CodesEnum };
  private readonly logger = new Logger(UtilsService.name);
  constructor(private readonly configService: ConfigService) {}
  public getImageName(img: string): string {
    return img.split('.')[0];
  }
  public getImageExtension(img: string): string {
    return extname(img).slice(1);
  }

  public sha(raw: string): string {
    return crypto.createHash('sha256').update(raw).digest('hex');
  }

  /**
   * The decorator should be used when possible
   */
  private isEmail(str: string): boolean {
    return /^\S+@\S+$/.test(str);
  }

  public transformCredential(data: string): {
    type: 'email_hash' | 'username';
    value: string;
  } {
    if (this.isEmail(data)) {
      const hash = this.sha(data);
      this.logger.log('Transforming into email');
      return {
        type: 'email_hash',
        value: hash,
      };
    } else {
      return {
        type: 'username',
        value: data,
      };
    }
  }

  public async comparePass(raw: string, hash: string): Promise<boolean> {
    return await bcrypt.compare(raw, hash);
  }

  public async hashPass(pass: string): Promise<string> {
    return await bcrypt.hash(pass, 10);
  }

  public splitMime(mime: string, side: 'type' | 'extension'): string {
    return mime.split('/')[side === 'type' ? 0 : 1];
  }

  public async generateSnowflake(l = 30): Promise<string> {
    const customA = customAlphabet(
      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
      l,
    );
    return await customA();
  }

  public encrypt(data: string) {
    const keyBuf = Buffer.from(this.configService.get<string>('ENCR_KEY'), 'utf8');
    const iv = crypto.randomBytes(16);

    const encryptionContext = crypto.createCipheriv('aes-256-cbc', keyBuf, iv);
    const firstHalf = encryptionContext.update(Buffer.from(data));
    const lastHalf = Buffer.concat([firstHalf, encryptionContext.final()]);
    return Buffer.concat([iv, lastHalf]).toString('hex');
  }

  public decrypt(data: string) {
    const keyBuf = Buffer.from(this.configService.get<string>('ENCR_KEY'));
    const convertedData = Buffer.from(data, 'hex');

    const iv = convertedData.slice(0, 16);
    const buf = convertedData.slice(16);

    const decryptionContext = crypto.createDecipheriv(
      'aes-256-cbc',
      keyBuf,
      iv,
    );
    const firstPart = decryptionContext.update(buf);
    return Buffer.concat([firstPart, decryptionContext.final()]).toString(
      'binary',
    );
  }

  public buildConfirmUrl(code: string): string {
    return `https://api.file.glass/v3/auth/confirm/${code}`;
  }

  public didTimeStampExpire(timeStamp: number) {
    return timeStamp < Date.now();
  }
  public setAllPropsTo<T>(
    o: { [key: string]: unknown },
    value: T,
  ): { [key: string]: T } {
    if (!o) {
      return o as { [key: string]: T };
    }
    const resObject = {};
    for (const [k, v] of Object.entries(o)) {
      resObject[k] = value;
    }
    return resObject;
  }

  public stripExif(data: Buffer): Buffer {
    return modifyExif(data, (dat) => {
      dat.Gps = {};
      dat.Exif['36867'] = '6969:69:69';
      dat.Exif['36868'] = '6969:69:69';
    });
  }
  public async createUniformIds(idLength = 10, ids = 8): Promise<string[]> {
    const generated: string[] = [];
    for (let i = 0; i < ids; i++) {
      generated.push(await nanoid(idLength));
    }
    return generated;
  }

  public computeQueryObj(
    query?: string,
    extQuery?: string,
    favs?: boolean,
  ): ComputedQueryResult {
    const final: ComputedQueryResult = {};
    if (query) {
      final.path = { contains: query, mode: 'insensitive' };
    }
    if (extQuery) {
      final.OR = [
        {
          extension: { contains: extQuery, mode: 'insensitive' },
        },
        { mime: { contains: extQuery, mode: 'insensitive' } },
      ];
    }

    if (favs === true) {
      final.favorite = true;
    }
    this.logger.debug('Computed query object:', final);
    return final;
  }
  public formatStr(str: string, ...data: string[]): string {
    data.forEach((word, idx) => {
      str = str.replace(`\$${idx}`, word);
    });
    return str;
  }
  public parseTimeStr(str: string): number {
    return Date.now() + timestring(str, 'ms');
  }

  public humanize(dur: number): string {
    return humanizeDuration(dur);
  }

  public isObjectRegular(o: Object): boolean {
    return !(o instanceof Date) && !(o instanceof RegExp) && !Array.isArray(o);
  }

  public deeplyLocalizeObject<T extends Object | Array<string>>(
    o: T,
    locale: string,
  ): Object | Array<string> {
    try {
      if (!o) {
        return o;
      }
      const resolvedString = this.exploreStringsInUnknownObject(o);
      if (Array.isArray(o)) {
        return o.map((l) => {
          if (
            typeof l === 'string' &&
            l.includes('_') &&
            l.length < 50 &&
            !this.isUrl(l) &&
            !this.isOnlyDigit(l) &&
            !this.isImage(l)
          ) {
            return GetLocale(l, locale);
          }
          return l;
        });
      }

      for (const [k, v] of Object.entries(o)) {
        if (
          typeof v === 'string' &&
          v.includes('_') &&
          v.length < 50 &&
          !this.isUrl(v) &&
          !this.isOnlyDigit(v) &&
          !this.isImage(v)
        ) {
          o[`${k}_LOC`] = GetLocale(v, locale);
        } else if (typeof v === 'object' && this.isObjectRegular(v)) {
          o[k] = this.deeplyLocalizeObject(v, locale);
        } else if (Array.isArray(v)) {
          o[k] = v.map((l) => GetLocale(l, locale));
        }
      }
      return o;
    } catch (err) {
      return o;
    }
  }

  public exploreStringsInUnknownObject(o: Object | Array<unknown>) {
    let finals: string[] = [];
    if (Array.isArray(o)) {
      o.forEach((e) => {
        if (typeof e === 'string') {
          finals.push(e);
        } else {
          finals = finals.concat(this.exploreStringsInUnknownObject(e));
        }
      });
    } else if (typeof o === 'object') {
      for (const [k, v] of Object.entries(o)) {
        if (typeof v === 'string') {
          finals.push(v);
        } else {
          finals = finals.concat(this.exploreStringsInUnknownObject(v));
        }
      }
    } else if (typeof o === 'string') {
      finals.push(o);
    }
    return finals;
  }

  public createSignal<Sig extends keyof Signals>(
    signal: Sig,
    data: Signals[Sig],
  ) {
    return {
      signal,
      data,
    };
  }
  public async convertStreamToBuffer(readable: Readable): Promise<Buffer> {
    if (readable instanceof Buffer) {
      return readable as Buffer;
    }
    this.logger.debug('Converting readable stream to buffer');
    const chunks: Uint8Array[] = [];
    for await (const chunk of readable) {
      chunks.push(chunk);
    }
    this.logger.debug('Conversion finished');
    return Buffer.concat(chunks);
  }

  public isUpper(t: string) {
    return /^[A-Z_]+$/.test(t);
  }

  public isUrl(t: string) {
    return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/.test(
      t,
    );
  }

  public isOnlyDigit(t: string) {
    return /^[\d*\s*]+$/.test(t);
  }

  public isImage(t: string) {
    return t.includes('.');
  }

  public partitionArray<T extends Array<unknown>>(arr: T, length: number): T[] {
    const result: any[] = [];

    for (let i = 0; i < arr.length; i++) {
      if (i % length === 0) result.push([]);
      result[result.length - 1].push(arr[i]);
    }
    return result;
  }
}

results matching ""

    No results matching ""