<commit_before>import * as ua from 'universal-analytics';
import _merge = require('lodash.merge');
import * as crypto from 'crypto';
import { Analytics, BaseApp, ErrorCode, HandleRequest, JovoError } from 'jovo-core';
import { Jovo } from 'jovo-framework';
import { Config, Event, TransactionItem, Transaction } from './interfaces';
import { Helper } from './helper';

type validEndReasons = 'Stop' | 'ERROR' | 'EXCEEDED_MAX_REPROMPTS' | 'PLAYTIME_LIMIT_REACHED' | 'PlayTimeLimitReached' | 'USER_INITIATED' | 'undefined';

export class GoogleAnalytics implements Analytics {

  /**
   * Need to save start state -\> will change during handling
   * Need to save lastUsed for calculation timeouts (sessionEnded bug display devices)
   *
   * @param handleRequest - jovo HandleRequest objekt
   */
  static saveStartStateAndLastUsed(handleRequest: HandleRequest): void {
    const { jovo } = handleRequest;

    if (jovo) {
      const stateString: string = jovo.getState() ? jovo.getState() : '/';

      jovo.$data.startState = stateString;
      jovo.$data.lastUsedAt = jovo?.$user.$metaData.lastUsedAt;
    }
  }

  /**
   * Get end reason from session variables
   *
   * @param jovo - unser liebes Jovo objekt.
   * @returns - the endreason saved in the session data.
   */
  static getEndReason(jovo: Jovo): validEndReasons | undefined {
    const endReason: validEndReasons | undefined = jovo.$session.$data.endReason;
    return endReason;
  }
  readonly sessionTimeoutInMinutes = 5;

  config: Config = {
    trackingId: '',
    enableAutomaticEvents: true,
    trackEndReasons: false,
  };
  visitor: ua.Visitor | undefined;

  // this map can be overwritten by skill developers to map endreasons to different custom metric numbers
  readonly endReasonGoogleAnalyticsMap = new Map<validEndReasons, number>([
    ['Stop', 1],
    ['ERROR', 2],
    ['EXCEEDED_MAX_REPROMPTS', 3],
    ['PlayTimeLimitReached', 4],
    ['USER_INITIATED', 5],
    ['undefined', 6],
  ]);

  constructor(config?: Config) {
    if (config) {
      this.config = _merge(this.config, config);
    }
  }

  install(app: BaseApp) {
    if (!this.config.trackingId) {
      throw new JovoError(
        'trackingId has to be set.',
        ErrorCode.ERR_PLUGIN,
        'jovo-analytics-googleanalytics',
        '',
        'You can find your tracking id in Google Analytics by clicking: Admin -> Property Settings -> Tracking Id',
        'https://www.jovo.tech/docs/analytics/googleanalytics',
      );
    }

    app.middleware('before.handler')!.use(GoogleAnalytics.saveStartStateAndLastUsed.bind(this));
    app.middleware('after.platform.init')!.use(this.setGoogleAnalyticsObject.bind(this));
    app.middleware('after.response')!.use(this.track.bind(this));
    app.middleware('fail')!.use(this.sendError.bind(this));
  }


  /**
   * Sets end reason to session variables + updates google analytics metric
   *
   * @param jovo - unser liebes Jovo objekt
   * @param endReason - grund für session ende
   */
  setEndReason(jovo: Jovo, endReason: validEndReasons): void {
    jovo.$session.$data.endReason = endReason;
    const gaMetricNumber = this.endReasonGoogleAnalyticsMap.get(endReason);
    console.log(`[GOOGLE ANALYTICS 169] Der EndReason ist _${endReason}_ und indexGa _${gaMetricNumber}_.`);
    if (gaMetricNumber) {
      jovo.$googleAnalytics.setCustomMetric(gaMetricNumber, '1');
    } else {
      const undefinedMetricNumber = this.endReasonGoogleAnalyticsMap.get('undefined');
      if (undefinedMetricNumber) {
        jovo.$googleAnalytics.setCustomMetric(undefinedMetricNumber, '1');
        // @ts-ignore
        jovo.util169.toSlack169(`[GOOGLE ANALYTICS 169] Der Endreason _${endReason}_ wurde nicht als valide befunden.\n *[STAGE]* ${process.env.STAGE}`);
      } else {
        // @ts-ignore
        jovo.util169.toSlack169(
          `[GOOGLE ANALYTICS 169] Der Endreason _${endReason}_ wurde nicht als valide befunden.\n *[STAGE]* ${process.env.STAGE}. 
            Der Versuch ihn auf undefined zu setzen schlug fehl. Überprüfe, ob die endReasonGoogleAnalyticsMap mit falschen Werten überschrieben wurde.`,
        );
      }
    }
  }

  /**
   * Auto send intent data after each response. Also setting sessions and flowErrors
   * @param handleRequest
   */
  track(handleRequest: HandleRequest) {
    const jovo: Jovo = handleRequest.jovo!;
    if (!jovo) {
      throw new JovoError(
        'Jovo object is not set',
        ErrorCode.ERR_PLUGIN,
        'jovo-analytics-googleanalytics',
      );
    }
<commit_msg>:recycle: delete logs + add missing dependency<commit_after>import * as ua from 'universal-analytics';
import _merge = require('lodash.merge');
import * as crypto from 'crypto';
import { Analytics, BaseApp, ErrorCode, HandleRequest, JovoError } from 'jovo-core';
import { Jovo } from 'jovo-framework';
import { Config, Event, TransactionItem, Transaction } from './interfaces';
import { Helper } from './helper';

type validEndReasons = 'Stop' | 'ERROR' | 'EXCEEDED_MAX_REPROMPTS' | 'PLAYTIME_LIMIT_REACHED' | 'PlayTimeLimitReached' | 'USER_INITIATED' | 'undefined';

export class GoogleAnalytics implements Analytics {

  /**
   * Need to save start state -\> will change during handling
   * Need to save lastUsed for calculation timeouts (sessionEnded bug display devices)
   *
   * @param handleRequest - jovo HandleRequest objekt
   */
  static saveStartStateAndLastUsed(handleRequest: HandleRequest): void {
    const { jovo } = handleRequest;

    if (jovo) {
      const stateString: string = jovo.getState() ? jovo.getState() : '/';

      jovo.$data.startState = stateString;
      jovo.$data.lastUsedAt = jovo?.$user.$metaData.lastUsedAt;
    }
  }

  /**
   * Get end reason from session variables
   *
   * @param jovo - unser liebes Jovo objekt.
   * @returns - the endreason saved in the session data.
   */
  static getEndReason(jovo: Jovo): validEndReasons | undefined {
    const endReason: validEndReasons | undefined = jovo.$session.$data.endReason;
    return endReason;
  }
  readonly sessionTimeoutInMinutes = 5;

  config: Config = {
    trackingId: '',
    enableAutomaticEvents: true,
    trackEndReasons: false,
  };
  visitor: ua.Visitor | undefined;

  // this map can be overwritten by skill developers to map endreasons to different custom metric numbers
  readonly endReasonGoogleAnalyticsMap = new Map<validEndReasons, number>([
    ['Stop', 1],
    ['ERROR', 2],
    ['EXCEEDED_MAX_REPROMPTS', 3],
    ['PlayTimeLimitReached', 4],
    ['USER_INITIATED', 5],
    ['undefined', 6],
  ]);

  constructor(config?: Config) {
    if (config) {
      this.config = _merge(this.config, config);
    }
  }

  install(app: BaseApp) {
    if (!this.config.trackingId) {
      throw new JovoError(
        'trackingId has to be set.',
        ErrorCode.ERR_PLUGIN,
        'jovo-analytics-googleanalytics',
        '',
        'You can find your tracking id in Google Analytics by clicking: Admin -> Property Settings -> Tracking Id',
        'https://www.jovo.tech/docs/analytics/googleanalytics',
      );
    }

    app.middleware('before.handler')!.use(GoogleAnalytics.saveStartStateAndLastUsed.bind(this));
    app.middleware('after.platform.init')!.use(this.setGoogleAnalyticsObject.bind(this));
    app.middleware('after.response')!.use(this.track.bind(this));
    app.middleware('fail')!.use(this.sendError.bind(this));
  }


  /**
   * Sets end reason to session variables + updates google analytics metric
   *
   * @param jovo - unser liebes Jovo objekt
   * @param endReason - grund für session ende
   */
  setEndReason(jovo: Jovo, endReason: validEndReasons): void {
    jovo.$session.$data.endReason = endReason;
    const gaMetricNumber = this.endReasonGoogleAnalyticsMap.get(endReason);
    if (gaMetricNumber) {
      jovo.$googleAnalytics.setCustomMetric(gaMetricNumber, '1');
    } else {
      const undefinedMetricNumber = this.endReasonGoogleAnalyticsMap.get('undefined');
      if (undefinedMetricNumber) {
        jovo.$googleAnalytics.setCustomMetric(undefinedMetricNumber, '1');
      }
    }
  }

  /**
   * Auto send intent data after each response. Also setting sessions and flowErrors
   * @param handleRequest
   */
  track(handleRequest: HandleRequest) {
    const jovo: Jovo = handleRequest.jovo!;
    if (!jovo) {
      throw new JovoError(
        'Jovo object is not set',
        ErrorCode.ERR_PLUGIN,
        'jovo-analytics-googleanalytics',
      );
    }

{'fraction_non_alphanumeric': 0.11932355723746452, 'fraction_numerical': 0.004612109744560076, 'mean_word_length': 3.4323899371069184, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5630205', 'n_tokens_mistral': 2650, 'n_tokens_neox': 2588, 'n_words': 641}