{"version":3,"file":"privmsg.mjs","names":[],"sources":["../../../src/message/twitch-types/privmsg.ts"],"sourcesContent":["import type { TwitchBadgesList } from \"../badges\";\nimport type { Color } from \"../color\";\nimport type { TwitchEmoteList } from \"../emotes\";\nimport type { TwitchFlagList } from \"../flags\";\nimport type { SharedChatFields, SharedChatSource } from \"../shared-chat\";\nimport type { UserState } from \"./userstate\";\nimport { ChannelIRCMessage, type Channel } from \"../irc/channel-irc-message\";\nimport {\n  type IRCMessage,\n  requireNickname,\n  requireParameter,\n} from \"../irc/irc-message\";\nimport { tagParserFor } from \"../parser/tag-values\";\n\n// eslint-disable-next-line no-control-regex\nconst actionRegex = /^\\u0001ACTION (.*)\\u0001$/;\n\nexport function parseActionAndMessage(trailingParameter: string): {\n  isAction: boolean;\n  message: string;\n} {\n  const match: RegExpExecArray | null = actionRegex.exec(trailingParameter);\n  return match == null\n    ? {\n        isAction: false,\n        message: trailingParameter,\n      }\n    : {\n        isAction: true,\n        message: match[1]!,\n      };\n}\n\nexport interface MessageSender {\n  readonly login: string;\n  /** @deprecated Use {@link MessageSender.login} instead. */\n  readonly username: string;\n  readonly id: string;\n  readonly displayName: string;\n  readonly color: Color | undefined;\n  readonly colorRaw: string;\n  readonly badgeInfo: TwitchBadgesList;\n  readonly badgeInfoRaw: string;\n  readonly badges: TwitchBadgesList;\n  readonly badgesRaw: string;\n  readonly isMod: boolean;\n  readonly isModRaw: string;\n}\n\nexport interface ReplyParent {\n  readonly displayName: string;\n  readonly messageBody: string;\n  readonly messageId: string;\n  readonly userId: string;\n  readonly userLogin: string;\n}\n\ninterface CheerPrivmsgMessage extends PrivmsgMessage {\n  readonly bits: number;\n  readonly bitsRaw: string;\n}\n\ninterface ReplyPrivmsgMessage extends PrivmsgMessage {\n  readonly replyParent: ReplyParent;\n}\n\n/**\n * Omits `emoteSets` and `emoteSetsRaw` from {@link UserState} (because they are not sent\n * for `PRIVMSG` messages)\n * @deprecated Use {@link PrivmsgMessage.sender} instead.\n */\nexport type PrivmsgUserState = Omit<UserState, \"emoteSets\" | \"emoteSetsRaw\">;\n\nexport class PrivmsgMessage\n  extends ChannelIRCMessage\n  // eslint-disable-next-line ts/no-deprecated\n  implements PrivmsgUserState, Partial<SharedChatFields>\n{\n  private readonly _content: string;\n  private readonly _action: boolean;\n  private readonly _senderLogin: string;\n  private readonly _senderId: string;\n  private readonly _badgeInfo: TwitchBadgesList;\n  private readonly _badgeInfoRaw: string;\n  private readonly _badges: TwitchBadgesList;\n  private readonly _badgesRaw: string;\n  private readonly _bits: number | undefined;\n  private readonly _bitsRaw: string | undefined;\n  private readonly _color: Color | undefined;\n  private readonly _colorRaw: string;\n  private readonly _displayName: string;\n  private readonly _emotes: TwitchEmoteList;\n  private readonly _emotesRaw: string;\n  private readonly _flags: TwitchFlagList | undefined;\n  private readonly _flagsRaw: string | undefined;\n  private readonly _replyParentDisplayName: string | undefined;\n  private readonly _replyParentMessageBody: string | undefined;\n  private readonly _replyParentMessageId: string | undefined;\n  private readonly _replyParentUserId: string | undefined;\n  private readonly _replyParentUserLogin: string | undefined;\n  private readonly _id: string;\n  private readonly _isMod: boolean;\n  private readonly _isModRaw: string;\n  private readonly _channelRoomId: string;\n  private readonly _timestamp: Date;\n  private readonly _timestampRaw: string;\n  private readonly _sourceId: string | undefined;\n  private readonly _sourceChannelId: string | undefined;\n  private readonly _sourceBadges: TwitchBadgesList | undefined;\n  private readonly _sourceBadgesRaw: string | undefined;\n  private readonly _sourceBadgeInfo: TwitchBadgesList | undefined;\n  private readonly _sourceBadgeInfoRaw: string | undefined;\n\n  public get isAction(): boolean {\n    return this._action;\n  }\n\n  public get content(): string {\n    return this._content;\n  }\n\n  /**\n   * The id of the message.\n   * @example \"7eb848c9-1060-4e5e-9f4c-612877982e79\"\n   */\n  public get id(): string {\n    return this._id;\n  }\n\n  /**\n   * The timestamp of when the message was sent, as reported by Twitch.\n   * This is not necessarily the same as the time the message was received by your client.\n   */\n  public get timestamp(): Date {\n    return this._timestamp;\n  }\n\n  public get timestampRaw(): string {\n    return this._timestampRaw;\n  }\n\n  public get bits(): number | undefined {\n    return this._bits;\n  }\n\n  public get bitsRaw(): string | undefined {\n    return this._bitsRaw;\n  }\n\n  public get emotes(): TwitchEmoteList {\n    return this._emotes;\n  }\n\n  public get emotesRaw(): string {\n    return this._emotesRaw;\n  }\n\n  /**\n   * Can be an array of Twitch AutoMod flagged words, for use in moderation and/or filtering purposes.\n   *\n   * If the `flags` tag is missing or of a unparseable format, this will be `undefined`. This is unlike most other\n   * attributes which when missing or malformed will fail the message parsing. However since this attribute is\n   * completely undocumented we cannot rely on the `flags` tag being stable, so this soft fallback is used instead.\n   * While it will be a major version release if this attribute changes format in dank-twitch-irc, using this is still\n   * at your own risk since it may suddenly contain unexpected data or turn `undefined` one day as\n   * Twitch changes something. In short: **Use at your own risk** and make sure your\n   * implementation can handle the case where this is `undefined`.\n   */\n  public get flags(): TwitchFlagList | undefined {\n    return this._flags;\n  }\n\n  /**\n   * Twitch AutoMod raw flags string.\n   *\n   * If the `flags` tag is missing or of a unparseable format, this will be `undefined`. This is unlike most other\n   * attributes which when missing or malformed will fail the message parsing. However since this attribute is\n   * completely undocumented we cannot rely on the `flags` tag being stable, so this soft fallback is used instead.\n   * In short, ensure your implementation can handle the case where this is `undefined` or is in\n   * a format you don't expect.\n   */\n  public get flagsRaw(): string | undefined {\n    return this._flagsRaw;\n  }\n\n  public override get channel(): Channel & { readonly id: string } {\n    return {\n      login: this._channelLogin,\n      username: this._channelLogin,\n      id: this._channelRoomId,\n    };\n  }\n\n  public get sender(): MessageSender {\n    return {\n      login: this._senderLogin,\n      username: this._senderLogin,\n      id: this._senderId,\n      displayName: this._displayName,\n      color: this._color,\n      colorRaw: this._colorRaw,\n      badgeInfo: this._badgeInfo,\n      badgeInfoRaw: this._badgeInfoRaw,\n      badges: this._badges,\n      badgesRaw: this._badgesRaw,\n      isMod: this._isMod,\n      isModRaw: this._isModRaw,\n    };\n  }\n\n  public get replyParent(): ReplyParent | undefined {\n    if (this._replyParentMessageId == null) return undefined;\n    return {\n      displayName: this._replyParentDisplayName!,\n      messageBody: this._replyParentMessageBody!,\n      messageId: this._replyParentMessageId,\n      userId: this._replyParentUserId!,\n      userLogin: this._replyParentUserLogin!,\n    };\n  }\n\n  public get source(): SharedChatSource | undefined {\n    if (this._sourceId == null) return undefined;\n    return {\n      id: this._sourceId,\n      channelId: this._sourceChannelId!,\n      badges: this._sourceBadges!,\n      badgesRaw: this._sourceBadgesRaw!,\n      badgeInfo: this._sourceBadgeInfo!,\n      badgeInfoRaw: this._sourceBadgeInfoRaw!,\n    };\n  }\n\n  // ---- Deprecated aliases ----\n\n  /** @deprecated Use {@link content} instead. */\n  public get messageText(): string {\n    return this._content;\n  }\n\n  /** @deprecated Use {@link sender.login} instead. */\n  public get senderUsername(): string {\n    return this._senderLogin;\n  }\n\n  /** @deprecated Use {@link sender.id} instead. */\n  public get senderUserID(): string {\n    return this._senderId;\n  }\n\n  /** @deprecated Use {@link sender.id} instead. */\n  public get senderUserId(): string {\n    return this._senderId;\n  }\n\n  /** @deprecated Use {@link sender.badgeInfo} instead. */\n  public get badgeInfo(): TwitchBadgesList {\n    return this._badgeInfo;\n  }\n\n  /** @deprecated Use {@link sender.badgeInfoRaw} instead. */\n  public get badgeInfoRaw(): string {\n    return this._badgeInfoRaw;\n  }\n\n  /** @deprecated Use {@link sender.badges} instead. */\n  public get badges(): TwitchBadgesList {\n    return this._badges;\n  }\n\n  /** @deprecated Use {@link sender.badgesRaw} instead. */\n  public get badgesRaw(): string {\n    return this._badgesRaw;\n  }\n\n  /** @deprecated Use {@link sender.color} instead. */\n  public get color(): Color | undefined {\n    return this._color;\n  }\n\n  /** @deprecated Use {@link sender.colorRaw} instead. */\n  public get colorRaw(): string {\n    return this._colorRaw;\n  }\n\n  /** @deprecated Use {@link sender.displayName} instead. */\n  public get displayName(): string {\n    return this._displayName;\n  }\n\n  /** @deprecated Use {@link id} instead. */\n  public get messageID(): string {\n    return this._id;\n  }\n\n  /** @deprecated Use {@link id} instead. */\n  public get messageId(): string {\n    return this._id;\n  }\n\n  /** @deprecated Use {@link sender.isMod} instead. */\n  public get isMod(): boolean {\n    return this._isMod;\n  }\n\n  /** @deprecated Use {@link sender.isModRaw} instead. */\n  public get isModRaw(): string {\n    return this._isModRaw;\n  }\n\n  /** @deprecated Use {@link channel.id} instead. */\n  public get channelID(): string {\n    return this._channelRoomId;\n  }\n\n  /** @deprecated Use {@link timestamp} instead. */\n  public get serverTimestamp(): Date {\n    return this._timestamp;\n  }\n\n  /** @deprecated Use {@link timestampRaw} instead. */\n  public get serverTimestampRaw(): string {\n    return this._timestampRaw;\n  }\n\n  /** @deprecated Use {@link replyParent.displayName} instead. */\n  public get replyParentDisplayName(): string | undefined {\n    return this._replyParentDisplayName;\n  }\n\n  /** @deprecated Use {@link replyParent.messageBody} instead. */\n  public get replyParentMessageBody(): string | undefined {\n    return this._replyParentMessageBody;\n  }\n\n  /** @deprecated Use {@link replyParent.messageId} instead. */\n  public get replyParentMessageID(): string | undefined {\n    return this._replyParentMessageId;\n  }\n\n  /** @deprecated Use {@link replyParent.userId} instead. */\n  public get replyParentUserID(): string | undefined {\n    return this._replyParentUserId;\n  }\n\n  /** @deprecated Use {@link replyParent.userLogin} instead. */\n  public get replyParentUserLogin(): string | undefined {\n    return this._replyParentUserLogin;\n  }\n\n  /** @deprecated Use {@link source.id} instead. */\n  public get sourceID(): string | undefined {\n    return this._sourceId;\n  }\n\n  /** @deprecated Use {@link source.channelID} instead. */\n  public get sourceChannelID(): string | undefined {\n    return this._sourceChannelId;\n  }\n\n  /** @deprecated Use {@link source.badges} instead. */\n  public get sourceBadges(): TwitchBadgesList | undefined {\n    return this._sourceBadges;\n  }\n\n  /** @deprecated Use {@link source.badgesRaw} instead. */\n  public get sourceBadgesRaw(): string | undefined {\n    return this._sourceBadgesRaw;\n  }\n\n  /** @deprecated Use {@link source.badgeInfo} instead. */\n  public get sourceBadgesInfo(): TwitchBadgesList | undefined {\n    return this._sourceBadgeInfo;\n  }\n\n  /** @deprecated Use {@link source.badgeInfoRaw} instead. */\n  public get sourceBadgesInfoRaw(): string | undefined {\n    return this._sourceBadgeInfoRaw;\n  }\n\n  public constructor(ircMessage: IRCMessage) {\n    super(ircMessage);\n\n    const { isAction, message } = parseActionAndMessage(\n      requireParameter(this, 1),\n    );\n    this._content = message;\n    this._action = isAction;\n\n    this._senderLogin = requireNickname(this);\n\n    const tagParser = tagParserFor(this.ircTags);\n    this._channelRoomId = tagParser.requireString(\"room-id\");\n\n    this._senderId = tagParser.requireString(\"user-id\");\n\n    this._badgeInfo = tagParser.requireBadges(\"badge-info\");\n    this._badgeInfoRaw = tagParser.requireString(\"badge-info\");\n\n    this._badges = tagParser.requireBadges(\"badges\");\n    this._badgesRaw = tagParser.requireString(\"badges\");\n\n    this._bits = tagParser.getInt(\"bits\");\n    this._bitsRaw = tagParser.getString(\"bits\");\n\n    this._color = tagParser.getColor(\"color\");\n    this._colorRaw = tagParser.requireString(\"color\");\n\n    // trim: Twitch workaround for unsanitized data, see https://github.com/robotty/dank-twitch-irc/issues/33\n    this._displayName = tagParser.requireString(\"display-name\").trim();\n\n    this._emotes = tagParser.requireEmotes(\"emotes\", this._content);\n    this._emotesRaw = tagParser.requireString(\"emotes\");\n\n    this._flags = tagParser.getFlags(\"flags\", this._content);\n    this._flagsRaw = tagParser.getString(\"flags\");\n\n    this._replyParentDisplayName = tagParser.getTrimmedString(\n      \"reply-parent-display-name\",\n    );\n    this._replyParentMessageBody = tagParser.getString(\"reply-parent-msg-body\");\n    this._replyParentMessageId = tagParser.getString(\"reply-parent-msg-id\");\n    this._replyParentUserId = tagParser.getString(\"reply-parent-user-id\");\n    this._replyParentUserLogin = tagParser.getString(\"reply-parent-user-login\");\n\n    this._id = tagParser.requireString(\"id\");\n\n    this._isMod = tagParser.requireBoolean(\"mod\");\n    this._isModRaw = tagParser.requireString(\"mod\");\n\n    this._timestamp = tagParser.requireTimestamp(\"tmi-sent-ts\");\n    this._timestampRaw = tagParser.requireString(\"tmi-sent-ts\");\n\n    this._sourceId = tagParser.getString(\"source-id\");\n    this._sourceChannelId = tagParser.getString(\"source-room-id\");\n    this._sourceBadges = tagParser.getBadges(\"source-badges\");\n    this._sourceBadgesRaw = tagParser.getString(\"source-badges\");\n    this._sourceBadgeInfo = tagParser.getBadges(\"source-badge-info\");\n    this._sourceBadgeInfoRaw = tagParser.getString(\"source-badge-info\");\n  }\n\n  /**\n   * @deprecated Use {@link sender} instead.\n   */\n  // eslint-disable-next-line ts/no-deprecated\n  public extractUserState(): PrivmsgUserState {\n    return {\n      badgeInfo: this._badgeInfo,\n      badgeInfoRaw: this._badgeInfoRaw,\n      badges: this._badges,\n      badgesRaw: this._badgesRaw,\n      color: this._color,\n      colorRaw: this._colorRaw,\n      displayName: this._displayName,\n      isMod: this._isMod,\n      isModRaw: this._isModRaw,\n    };\n  }\n\n  public isCheer(): this is CheerPrivmsgMessage {\n    return this._bits != null;\n  }\n\n  public isReply(): this is ReplyPrivmsgMessage {\n    return this._replyParentMessageId != null;\n  }\n\n  /**\n   * Whether or not this message is during a shared chat session.\n   * This does NOT necessarily mean that the message is originating from another channel.\n   * Check if `message.source.channelId !== message.channel.id` for that\n   * @see https://dev.twitch.tv/docs/chat/irc/#shared-chat\n   */\n  // eslint-disable-next-line ts/no-deprecated\n  public isSharedChat(): this is this & SharedChatFields {\n    return this._sourceId != null;\n  }\n}\n"],"mappings":"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"}