{"version":3,"file":"irc-message.mjs","names":[],"sources":["../../../src/message/parser/irc-message.ts"],"sourcesContent":["import type { IRCMessageTags } from \"../irc/tags\";\nimport { IRCMessage } from \"../irc/irc-message\";\nimport { ParseError } from \"./parse-error\";\nimport { parseTags } from \"./tags\";\n\nconst VALID_CMD_REGEX = /^(?:[A-Z]+|\\d{3})$/i;\n\nexport function parseIRCMessage(messageSource: string): IRCMessage {\n  let remainder = messageSource;\n\n  let ircTags: IRCMessageTags;\n  if (messageSource.startsWith(\"@\")) {\n    remainder = remainder.slice(1); // remove @ sign\n\n    const spaceIndex = remainder.indexOf(\" \");\n    if (spaceIndex === -1) {\n      // not found\n      throw new ParseError(\n        `No space found after tags declaration (given src: \"${messageSource}\")`,\n      );\n    }\n\n    const tagsSource = remainder.slice(0, spaceIndex);\n\n    if (tagsSource.length === 0) {\n      throw new ParseError(\n        `Empty tags declaration (nothing after @ sign) (given src: \"${messageSource}\")`,\n      );\n    }\n\n    ircTags = parseTags(tagsSource);\n    remainder = remainder.slice(spaceIndex + 1);\n  } else {\n    ircTags = {};\n  }\n\n  let ircPrefix;\n  let ircPrefixRaw;\n  if (remainder.startsWith(\":\")) {\n    remainder = remainder.slice(1); // remove : sign\n\n    const spaceIndex = remainder.indexOf(\" \");\n    if (spaceIndex === -1) {\n      // not found\n      throw new ParseError(\n        `No space found after prefix declaration (given src: \"${messageSource}\")`,\n      );\n    }\n\n    ircPrefixRaw = remainder.slice(0, spaceIndex);\n    remainder = remainder.slice(spaceIndex + 1);\n\n    if (ircPrefixRaw.length === 0) {\n      throw new ParseError(\n        `Empty prefix declaration (nothing after : sign) (given src: \"${messageSource}\")`,\n      );\n    }\n\n    if (ircPrefixRaw.includes(\"@\")) {\n      // full prefix (nick[[!user]@host])\n      // valid forms:\n      // nick (but this is not really possible to differentiate\n      //       from the hostname only, so if we don't get any @\n      //       we just assume it's a hostname.)\n      // nick@host\n      // nick!user@host\n\n      // split on @ first, then on !\n      const atIndex = ircPrefixRaw.indexOf(\"@\");\n      const nickAndUser = ircPrefixRaw.slice(0, atIndex);\n      const host = ircPrefixRaw.slice(atIndex + 1);\n\n      // now nickAndUser is either \"nick\" or \"nick!user\"\n      // => split on !\n      const exclamationIndex = nickAndUser.indexOf(\"!\");\n      let nick: string;\n      let user: string | undefined;\n      if (exclamationIndex === -1) {\n        // no ! found\n        nick = nickAndUser;\n        user = undefined;\n      } else {\n        nick = nickAndUser.slice(0, exclamationIndex);\n        user = nickAndUser.slice(exclamationIndex + 1);\n      }\n\n      if (host.length === 0 || nick.length === 0 || user?.length === 0) {\n        throw new ParseError(\n          `Host, nick or user is empty in prefix (given src: \"${messageSource}\")`,\n        );\n      }\n\n      ircPrefix = {\n        nickname: nick,\n        username: user,\n        hostname: host,\n      };\n    } else {\n      // just a hostname or just a nickname\n      ircPrefix = {\n        nickname: undefined,\n        username: undefined,\n        hostname: ircPrefixRaw,\n      };\n    }\n  } else {\n    ircPrefix = undefined;\n    ircPrefixRaw = undefined;\n  }\n\n  const spaceAfterCommandIndex = remainder.indexOf(\" \");\n\n  let ircCommand;\n  let ircParameters;\n\n  if (spaceAfterCommandIndex === -1) {\n    // no space after commands, i.e. no params.\n    ircCommand = remainder;\n    ircParameters = [];\n  } else {\n    // split command off\n    ircCommand = remainder.slice(0, spaceAfterCommandIndex);\n    remainder = remainder.slice(spaceAfterCommandIndex + 1);\n\n    ircParameters = [];\n\n    // introduce a new variable so it can be null (typescript shenanigans)\n    let parametersRemainder: string | null = remainder;\n    while (parametersRemainder !== null) {\n      if (parametersRemainder.startsWith(\":\")) {\n        // trailing param, remove : and consume the rest of the input\n        ircParameters.push(parametersRemainder.slice(1));\n        parametersRemainder = null;\n      } else {\n        // middle param\n        const spaceIndex = parametersRemainder.indexOf(\" \");\n\n        let parameter;\n        if (spaceIndex === -1) {\n          // no space found\n          parameter = parametersRemainder;\n          parametersRemainder = null;\n        } else {\n          parameter = parametersRemainder.slice(0, spaceIndex);\n          parametersRemainder = parametersRemainder.slice(spaceIndex + 1);\n        }\n\n        if (parameter.length === 0) {\n          throw new ParseError(\n            `Too many spaces found while trying to parse middle parameters (given src: \"${messageSource}\")`,\n          );\n        }\n        ircParameters.push(parameter);\n      }\n    }\n  }\n\n  if (!VALID_CMD_REGEX.test(ircCommand)) {\n    throw new ParseError(\n      `Invalid format for IRC command (given src: \"${messageSource}\")`,\n    );\n  }\n\n  ircCommand = ircCommand.toUpperCase();\n\n  return new IRCMessage({\n    rawSource: messageSource,\n    ircPrefixRaw,\n    ircPrefix,\n    ircCommand,\n    ircParameters,\n    ircTags,\n  });\n}\n"],"mappings":";;;;AAKA,MAAM,kBAAkB;AAExB,SAAgB,gBAAgB,eAAmC;CACjE,IAAI,YAAY;CAEhB,IAAI;AACJ,KAAI,cAAc,WAAW,IAAI,EAAE;AACjC,cAAY,UAAU,MAAM,EAAE;EAE9B,MAAM,aAAa,UAAU,QAAQ,IAAI;AACzC,MAAI,eAAe,GAEjB,OAAM,IAAI,WACR,sDAAsD,cAAc,IACrE;EAGH,MAAM,aAAa,UAAU,MAAM,GAAG,WAAW;AAEjD,MAAI,WAAW,WAAW,EACxB,OAAM,IAAI,WACR,8DAA8D,cAAc,IAC7E;AAGH,YAAU,UAAU,WAAW;AAC/B,cAAY,UAAU,MAAM,aAAa,EAAE;OAE3C,WAAU,EAAE;CAGd,IAAI;CACJ,IAAI;AACJ,KAAI,UAAU,WAAW,IAAI,EAAE;AAC7B,cAAY,UAAU,MAAM,EAAE;EAE9B,MAAM,aAAa,UAAU,QAAQ,IAAI;AACzC,MAAI,eAAe,GAEjB,OAAM,IAAI,WACR,wDAAwD,cAAc,IACvE;AAGH,iBAAe,UAAU,MAAM,GAAG,WAAW;AAC7C,cAAY,UAAU,MAAM,aAAa,EAAE;AAE3C,MAAI,aAAa,WAAW,EAC1B,OAAM,IAAI,WACR,gEAAgE,cAAc,IAC/E;AAGH,MAAI,aAAa,SAAS,IAAI,EAAE;GAU9B,MAAM,UAAU,aAAa,QAAQ,IAAI;GACzC,MAAM,cAAc,aAAa,MAAM,GAAG,QAAQ;GAClD,MAAM,OAAO,aAAa,MAAM,UAAU,EAAE;GAI5C,MAAM,mBAAmB,YAAY,QAAQ,IAAI;GACjD,IAAI;GACJ,IAAI;AACJ,OAAI,qBAAqB,IAAI;AAE3B,WAAO;AACP,WAAO,KAAA;UACF;AACL,WAAO,YAAY,MAAM,GAAG,iBAAiB;AAC7C,WAAO,YAAY,MAAM,mBAAmB,EAAE;;AAGhD,OAAI,KAAK,WAAW,KAAK,KAAK,WAAW,KAAK,MAAM,WAAW,EAC7D,OAAM,IAAI,WACR,sDAAsD,cAAc,IACrE;AAGH,eAAY;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACX;QAGD,aAAY;GACV,UAAU,KAAA;GACV,UAAU,KAAA;GACV,UAAU;GACX;QAEE;AACL,cAAY,KAAA;AACZ,iBAAe,KAAA;;CAGjB,MAAM,yBAAyB,UAAU,QAAQ,IAAI;CAErD,IAAI;CACJ,IAAI;AAEJ,KAAI,2BAA2B,IAAI;AAEjC,eAAa;AACb,kBAAgB,EAAE;QACb;AAEL,eAAa,UAAU,MAAM,GAAG,uBAAuB;AACvD,cAAY,UAAU,MAAM,yBAAyB,EAAE;AAEvD,kBAAgB,EAAE;EAGlB,IAAI,sBAAqC;AACzC,SAAO,wBAAwB,KAC7B,KAAI,oBAAoB,WAAW,IAAI,EAAE;AAEvC,iBAAc,KAAK,oBAAoB,MAAM,EAAE,CAAC;AAChD,yBAAsB;SACjB;GAEL,MAAM,aAAa,oBAAoB,QAAQ,IAAI;GAEnD,IAAI;AACJ,OAAI,eAAe,IAAI;AAErB,gBAAY;AACZ,0BAAsB;UACjB;AACL,gBAAY,oBAAoB,MAAM,GAAG,WAAW;AACpD,0BAAsB,oBAAoB,MAAM,aAAa,EAAE;;AAGjE,OAAI,UAAU,WAAW,EACvB,OAAM,IAAI,WACR,8EAA8E,cAAc,IAC7F;AAEH,iBAAc,KAAK,UAAU;;;AAKnC,KAAI,CAAC,gBAAgB,KAAK,WAAW,CACnC,OAAM,IAAI,WACR,+CAA+C,cAAc,IAC9D;AAGH,cAAa,WAAW,aAAa;AAErC,QAAO,IAAI,WAAW;EACpB,WAAW;EACX;EACA;EACA;EACA;EACA;EACD,CAAC"}