Source: models/News.js

import { fromNow, parseDate, timeDeltaToString, toNow, languageString } from 'warframe-worldstate-data/utilities';

import { cdn, deProxy } from '../supporting/ImgCdn.js';
import mdConfig from '../supporting/MarkdownSettings.js';

import WorldstateObject from './WorldstateObject.js';

const updateReg = /(update|hotfix)/i;
const primeAccessReg = /(access)/i;
const streamReg = /(devstream|prime-time|warframeinternational|stream)/i;
const langString = /(\/Lotus\/Language\/)/i;

/**
 * Represents a game news item
 * @augments {WorldstateObject}
 */
export default class News extends WorldstateObject {
  /**
   * @param   {object}             data            The news data
   * @param   {string}             locale     Locale to use for determining language
   */
  constructor(data, { locale = 'en' } = { locale: 'en' }) {
    super(data);

    /**
     * The news message
     * @type {string}
     */
    this.message = (data.Messages.find((msg) => msg.LanguageCode === locale) || { Message: '' }).Message;
    if (langString.test(this.message)) {
      this.message = languageString(this.message, locale);
    }

    /**
     * The link to the forum post
     * @type {string}
     */
    this.link = data.Prop;
    if ((!this.link || !this.link.length) && data.Links && data.Links.length) {
      this.link = (data.Links.find((l) => l.LanguageCode === locale) || { Link: 'https://www.warframe.com/' }).Link;
    }

    /**
     * The news's image link
     * @type {string}
     */
    this.imageLink = data.ImageUrl ? deProxy(data.ImageUrl) : cdn('img/news-placeholder.png');

    /**
     * Whether this has priority over other news or not
     * @type {boolean}
     */
    this.priority = data.Priority;

    /**
     * The date at which the post was published
     * @type {Date}
     */
    this.date = parseDate(data.Date);

    /**
     * The date at which the event starts
     * @type {?Date}
     */
    this.startDate = data.EventStartDate ? parseDate(data.EventStartDate) : undefined;

    /**
     * The date at which the event ends
     * @type {?Date}
     */
    this.endDate = data.EventEndDate ? parseDate(data.EventEndDate) : undefined;

    /**
     * ETA string (at time of object creation)
     * @type {string}
     */
    this.eta = this.getETAString();

    /**
     * Whether this is an update news item
     * @type {boolean}
     */
    this.update = this.isUpdate();

    /**
     * Whether this is a prime access news item
     * @type {boolean}
     */
    this.primeAccess = this.isPrimeAccess();

    /**
     * Whether or not this is a stream
     * @type {boolean}
     */
    this.stream = this.isStream();

    /**
     * Translation of the news item
     * @type {Record<string, string>}
     */
    this.translations = {};
    data.Messages.forEach((message) => {
      this.translations[message.LanguageCode ?? 'en'] = message.Message;

      if (langString.test(message.Message)) {
        this.translations[message.LanguageCode] = languageString(message.Message, message.LanguageCode);
      }
    });

    /**
     * The string representation of this object at creation
     * @type {string}
     */
    this.asString = this.toString();
  }

  /**
   * Get a string indicating how long it will take for the event to start or
   * how long it's been since the news went up
   * @returns {string} the estimated time of arrival for the event
   */
  getETAString() {
    if (this.endDate) {
      const timeDelta = fromNow(this.endDate);
      return `in ${timeDeltaToString(timeDelta)}`;
    }
    const timeDelta = toNow(this.date);
    return `${timeDeltaToString(timeDelta)} ago`;
  }

  /**
   * Whether or not this is about a game update
   * @returns {boolean} whether the news is about an update
   */
  isUpdate() {
    return updateReg.test(this.link);
  }

  /**
   * Whether this is about a new Prime Access
   * @returns {boolean} whether the news is about a new Prime Access
   */
  isPrimeAccess() {
    return primeAccessReg.test(this.link);
  }

  /**
   * Whether this is about a new stream
   * @returns {boolean} whether the news is for a stream
   */
  isStream() {
    return streamReg.test(this.message);
  }

  /**
   * String representation
   * @returns {string} string representation
   */
  toString() {
    return (
      `[${this.getETAString()}] ${mdConfig.linkBegin}${this.message}` +
      `${mdConfig.linkMid}${this.link}${mdConfig.linkEnd}`
    );
  }

  /**
   * The title of the news item in the specified language
   * @param {string} langCode Ex. 'es', 'de', 'fr'
   * @returns {string} The title of the news item in the specified language
   */
  getTitle(langCode) {
    return langCode in this.translations ? this.translations[langCode] : this.message;
  }
}