aronson / discord-irc

Connects Discord and IRC channels by sending messages back and forth.
MIT License
4 stars 2 forks source link

Invalid JSON #29

Closed KeiroD closed 10 months ago

KeiroD commented 10 months ago

Hi,

I've been trying to get my discord-irc version updated to use yours since the previous one is no longer maintained. Unfortunately... I'm having trouble with getting the bot to use the config.json.

I get errors similar to the following:

bot@irc:~$ ./discord-irc-linux-x64 
error: Uncaught SyntaxError: Expected property name or '}' in JSON at position 11 (line 4 column 5)
    at JSON.parse (<anonymous>)
    at run (file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:39:26)
    at async file:///home/runner/work/discord-irc/discord-irc/discord-irc.ts:3:1

Sample config.json:

[

  {
    nickname: 'Example',
    server: 'irc.example.com',
    discordToken: 'redacted',
    channelMapping: {
      '#redacted': '#redacted',
      'redacted': '#redacted',
      'redacted': '#redacted'
    },
  },
];

I've also been using a JSON validator to verify that it's working as it should and even that is complaining. For reference, this's the one I was using: https://jsonlint.com

As an aside, will this bot run on its own without any requirement for using something like screen? I've been using pm2 for the previous iteration and I imagine it'd be the same but right now I've been focused on getting the bot online minimally.

aronson commented 10 months ago

JSON requires one to quote all property names with double quotes { "like_so": { ... } } Trailing commas and semi-colons are not typically valid. It's a bit different from typescript/javascript code.

Try something like this:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "discordToken": "redacted",
    "channelMapping": {
      "#redacted": "#redacted",
      "redacted": "#redacted",
      "redacted": "#redacted"
    }
  }
]

Note you can't have duplicate keys, but since you redacted real channel names I figure you've got that covered.

image

EDIT:

will this bot run on its own without any requirement for using something like screen?

Absolutely, but there is no background daemon mode. We use immortal in production in the largest server I know using my fork (15k users), but run the binary or deno task start directly when testing. If you want to background it, you'll need to nohup it like any other child process.

KeiroD commented 10 months ago

Hello!

Thanks for responding quickly and I can confirm that the suggested update you provided does work.

However, I'd like to note that you might want to also consider updating the long-form one also, as I also used this one as well and it's not quite valid according to jsonlint.com either.

Edit: Looks like with the valid short-form config I'm still encountering errors, but different ones. Do you want me to continue providing these here or in a new issue?

As for the background daemon mode -- understood. I was planning on using pm2, but I suppose that's not necessary, so all good as long as I can yeet it into the background so to speak.

aronson commented 10 months ago

Ah, I see the issue, the previous version of the fork allowed a more loose format of JSON and we never updated the README to reflect the change!

I've gone ahead and updated the README examples to be valid. Thank you for catching this.

31

Feel free to post your errors, happy to help you in this existing issue thread until we've got your instance working πŸ˜„

KeiroD commented 10 months ago

Heh... yep, that would do it. No worries, happy to help!

As for the errors --

bot@irc:~$ ./discord-irc-linux-x64 
error: Uncaught TypeError: Cannot use 'in' operator to search for 'userName' in undefined
  if ('userName' in obj) {
                 ^
    at testIrcOptions (file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:6:18)
    at file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:50:36
    at Array.reduce (<anonymous>)
    at run (file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:49:31)
    at async file:///home/runner/work/discord-irc/discord-irc/discord-irc.ts:3:1

This is using the valid config that we worked out here. This is also on Ubuntu 22.04 -- and I still have the old discord-irc set up but otherwise that version is... it works, but obviously not as well as this one does.

Anyway, let me know if you need any further info to continue troubleshooting this.

aronson commented 10 months ago

I see now, that was a logical error on my part! We've always tested with ircOptions present, and I wrote validation code that assumes one has them in the first place. Seeing as they are optional I've made the fix.

Fixed in #37 Made a release for you, you'll need the new binary

KeiroD commented 10 months ago

Success!

... Sort of? I can see it show up Discord-side but only thing I've got is

bot@irc:~$ ./discord-irc-linux-x64 
[2023/10/09 3:44:08 AM] [AGNPH] [  INFO ]: Joining channel #stuff
[2023/10/09 3:44:08 AM] [AGNPH] [  INFO ]: Joining channel #stuff
[2023/10/09 3:44:08 AM] [AGNPH] [  INFO ]: Joining channel #stuff
[2023/10/09 3:44:08 AM] [AGNPH] [  INFO ]: Joining channel #stuff
[2023/10/09 3:44:08 AM] [AGNPH] [  INFO ]: Connected to Discord
[2023/10/09 3:44:38 AM] [AGNPH] [ βœ— ERROR ]: Received error event from IRC
{
  "type": "read"
}

When monitoring the join, the bot seems to just connect and not do anything until forcibly joined to channels it's configured to be in by way of oper actions. Once that's done though, it does seem to be relaying just fine. Just not sure why.

aronson commented 10 months ago

EDIT: Make sure you only attempt to join a given channel once. I see you're joining #stuff four times, which I don't think will work. Can you post your config again? I can try to replicate the setup on Libera.

Not sure what to tell you on this one, sounds like an issue with the IRC server.

My minimal config logs in to Libera and passes messages automatically within 30 seconds.

Can you try running with DEBUG=true ./discord-irc-linux-x64 and posting that? Could be more info. Make sure to redact any info you don't want leaked, like usernames if applicable.

My minimal config.json:

[
  {
    "nickname": "TestDiscordIRC",
    "server": "irc.libera.chat",
    "discordToken": "[REDACTED]",
    "channelMapping": {
      "#irc-test": "#irc-test"
    }
  }
]
image image image

Example working debug log output:

[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Connecting to IRC and Discord
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Fetch /api/v9/gateway/bot..."
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [  INFO ]: Joining channel #irc-test
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received notice:
"*** Checking Ident"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received notice:
"*** Looking up your hostname..."
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Recommended Shards: 1"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] === Session Limit Info ==="
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Remaining: 998/1000"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Reset After: 86120196ms"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launching 1 shard..."
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launching Shard: 0"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Initializing WebSocket..."
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Connected to Gateway!"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received HELLO. Heartbeat Interval: 41250"
[2023/10/09 5:32:38 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Sending Identify payload..."
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received Heartbeat Ack. Ping Recognized: 32ms"
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received READY. Session: 87f22d6947cbc1ba5137befa0ec6db1e"
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Resolving READY"
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Guilds arrived!"
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [  INFO ]: Connected to Discord
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launched 1 shards! Time taken: 0s"
[2023/10/09 5:32:39 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received notice:
"*** Found your hostname: 239.205.160.108.in-addr.arpa"
[2023/10/09 5:32:44 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received notice:
"*** No Ident response"
[2023/10/09 5:32:44 AM] [TestDiscordIRC] [  INFO ]: Connected to IRC
[2023/10/09 5:32:44 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Registered event:
{
  "source": {
    "name": "molybdenum.libera.chat"
  },
  "params": {
    "nick": "TestDiscordIRC",
    "text": "Welcome to the Libera.Chat Internet Relay Chat Network TestDiscordIRC"
  }
}
[2023/10/09 5:32:50 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received names: #irc-test
[
  {
    "prefix": "",
    "nick": "TestDiscordIRC"
  }
]
[2023/10/09 5:32:50 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received join: #irc-test -- TestDiscordIRC
[2023/10/09 5:32:50 AM] [TestDiscordIRC] [ ο†ˆ DEBUG ]: Received names: #irc-test
[
  {
    "prefix": "@",
    "nick": "Luigi"
  },
  {
    "prefix": "",
    "nick": "TestDiscordIRC"
  }
]
aronson commented 10 months ago

Since you mentioned this configuration is working for you with multiple channels, presumably the same IRC channel mapped to several different Discord channels, I'm going to add official support for this. As the code is now, the app will error out if you attempt to do this, but it works in theory as you've demonstrated.

Expect an update that fixes this soon. I also modified and enhanced logging since the last binary you downloaded, hopefully that helps.

KeiroD commented 10 months ago

Err... I didn't, not quite. I thought I commented on this earlier but got distracted. Whoops. ADHD at its finest.

These are actually just redacted channels but in theory it should work just fine for relaying to multiple channels but I haven't actually tested that.

Sorry about that. I also was going to mention that I wouldn't be able to test with that until tomorrow, but I'd definitely be happy to test the multi-channel setup as it should work.

aronson commented 10 months ago

Ah! No worries. From your redacted logs and the mention that using commands to join the bot manually to channels I assumed that was the case. That's lower priority, then, if you aren't actively using such a setup. I'll still implement it as it should be a supported use-case.

No rush πŸ™‚

KeiroD commented 10 months ago

Right, so testing this with the privmsg command seems to be failing because I forgot to include it. Here's the sample config which results in the error:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "discordToken": "redacted",
    "autoSendCommands": [
       ["PRIVMSG", "NickServ", "IDENTIFY redacted"],
    ],
    "channelMapping": {
      "#redacted-id": "redacted-id",
      "redacted-id1": "#redacted-id1",
      "redacted-id2": "#redacted-id2",
      "redacted-id3": "#redacted-id3"
    }
  }
]

Results in following error:

Error parsing configuration:
ZodError: [
  {
    "code": "too_big",
    "maximum": 2,
    "inclusive": true,
    "type": "array",
    "path": [
      0,
      "autoSendCommands",
      0
    ],
    "message": "Array must contain at most 2 element(s)"
  }
]
    at handleResult (https://deno.land/x/zod@v3.16.1/types.ts:30:19)
    at ZodArray.safeParse (https://deno.land/x/zod@v3.16.1/types.ts:134:12)
    at parseConfigObject (file:///home/runner/work/discord-irc/discord-irc/lib/config.ts:55:38)
    at run (file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:40:18)
    at async file:///home/runner/work/discord-irc/discord-irc/discord-irc.ts:3:1 {
  issues: [
    {
      code: "too_big",
      maximum: 2,
      inclusive: true,
      type: "array",
      path: [ 0, "autoSendCommands", 0 ],
      message: "Array must contain at most 2 element(s)"
    }
  ],
  addIssue: [Function: addIssue],
  addIssues: [Function: addIssues],
  name: "ZodError"
}

If I take out the autocommands bit, here's what I see:

root@irc:/home/Redactedbot# tail -f debug.log 
"please choose a different nick."
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Connected to Gateway!"
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received HELLO. Heartbeat Interval: 41250"
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Sending Identify payload..."
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received Heartbeat Ack. Ping Recognized: 104ms"
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received READY. Session: 2e4da13530290a1ecc7c8ac521349f73"
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Resolving READY"
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Guilds arrived!"
[2023/10/11 4:04:40 AM] [Redacted] [  INFO ]: Connected to Discord
[2023/10/11 4:04:40 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launched 1 shards! Time taken: 0s"
[2023/10/11 4:04:50 AM] [Redacted] [  WARN ]: Received Ctrl+C! Disconnecting...
[2023/10/11 4:04:50 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Destroying Shard"
[2023/10/11 4:04:50 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Closing with code 1000 and reason harmony-destroy"
^C
root@irc:/home/Redactedbot# >debug.log 
root@irc:/home/Redactedbot# tail -f debug.log 
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Connecting to IRC and Discord
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Fetch /api/v9/gateway/bot..."
[2023/10/11 4:04:58 AM] [Redacted] [  INFO ]: Joining channel #Redacted
[2023/10/11 4:04:58 AM] [Redacted] [  INFO ]: Joining channel #redacted
[2023/10/11 4:04:58 AM] [Redacted] [  INFO ]: Joining channel #redacted
[2023/10/11 4:04:58 AM] [Redacted] [  INFO ]: Joining channel #Redacted-mc
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received notice:
"*** Looking up your hostname..."
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received notice:
"*** Couldn't resolve your hostname; using your IP address instead"
[2023/10/11 4:04:58 AM] [Redacted] [  INFO ]: Connected to IRC
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Registered event:
{
  "source": {
    "name": "irc.example.com"
  },
  "params": {
    "nick": "Redacted",
    "text": "Welcome to the IRC Network Redacted!Redacted@localhost"
  }
}
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received notice:
"This nickname is registered and protected.  If it is your"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Recommended Shards: 1"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] === Session Limit Info ==="
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Remaining: 995/1000"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Reset After: 85330444ms"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launching 1 shard..."
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launching Shard: 0"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Initializing WebSocket..."
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received notice:
"nick, type \u0002/msg NickServ IDENTIFY \u001fpassword\u001f\u0002.  Otherwise,"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received notice:
"please choose a different nick."
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Connected to Gateway!"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received HELLO. Heartbeat Interval: 41250"
[2023/10/11 4:04:58 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Sending Identify payload..."
[2023/10/11 4:04:59 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received Heartbeat Ack. Ping Recognized: 102ms"
[2023/10/11 4:04:59 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Received READY. Session: c20718e51027c03938abffaa02d82d78"
[2023/10/11 4:04:59 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Resolving READY"
[2023/10/11 4:04:59 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shard 0] Guilds arrived!"
[2023/10/11 4:04:59 AM] [Redacted] [  INFO ]: Connected to Discord
[2023/10/11 4:04:59 AM] [Redacted] [ ο†ˆ DEBUG ]: Received debug event from Discord: "[Shards] Launched 1 shards! Time taken: 0s"

Seems like maybe the requirement to identify to the services is what's preventing it from actually joining the IRC channels? We can see that it says it joined the channels on IRC, but that's not actually happening here.

aronson commented 10 months ago

Here's a release that fixes it

This is a mix of two issues:

Note that it hasn't said it joined the channels yet, you'd want to look for output like this:

image

You want to add a block like this:

{
  // ...
  "ircOptions": {
    "password": "[REDACTED]" // this is your NickServ password
  }
}

However, I pushed an update that will support the auto-send commands you're running, and that should work as well, just tested it.

KeiroD commented 10 months ago

Hi,

Will be testing this momentarily. It looks like the bot is also crashing because of pluralkit/tupper bots proxying members that technically don't exist in Discord:

error: Uncaught (in promise) DiscordAPIError:
GET https://discord.com/api/v9/guilds/example-guild-id/members/exampleid returned 404
(10013) Unknown User
      throw new DiscordAPIError({
            ^
    at BucketHandler.execute (https://raw.githubusercontent.com/harmonyland/harmony/main/src/rest/bucket.ts:170:13)
    at eventLoopTick (ext:core/01_core.js:183:11)
    at async BucketHandler.push (https://raw.githubusercontent.com/harmonyland/harmony/main/src/rest/bucket.ts:46:13)
    at async RESTManager.make (https://raw.githubusercontent.com/harmonyland/harmony/main/src/rest/manager.ts:128:12)
    at async RESTManager.get (https://raw.githubusercontent.com/harmonyland/harmony/main/src/rest/manager.ts:135:12)

Regarding the password thing -- now that you've pointed out how this is supposed to work, I'm realizing that this part of the config wasn't the most obvious with regards to the autoSendCommands setting... it's using the ircOptions function for the password.

It might be for the best to update the README.md to explain this particular bit as I originally thought it was for the autoSendCommands function and not the ircOptions function to pass along the password correctly.

KeiroD commented 10 months ago

Looks like json is throwing a fit again. Here's the full redacted config:

[
  {
    "nickname": "Redacted",
    "server": "irc.example",
    "discordToken": "Redacted",
    autoSendCommands: [
      // Commands that will be sent on connect
      ['PRIVMSG', 'NickServ', 'IDENTIFY password'],
      ["MODE", "test", "+x"],
      ["AUTH", "test", "password"]
    ],
    "channelMapping": {
      "#redacted": "#redacted",
      "redacted-discord": "#redacted",
      "redacted-discord1": "#redacted1",
      "redacted-discord2": "#redacted"
     },
     "ircOptions": {
      "username": "test",
      "password": "password"
     },
    format: {
      // Optional custom formatting options
      // Patterns, represented by {$patternName}, are replaced when sending messages
      commandPrelude: 'Command sent by {$nickname}', // Message sent before a command
      ircText: '<{$displayUsername} [@{$discordUsername}]> {$text}', // When sending a message to IRC
      urlAttachment: '<{$displayUsername}> {$attachmentURL}', // When sending a Discord attachment to IRC
      discord: '**<{$author}>** {$withMentions}', // When sending a message to Discord
      // Other patterns that can be used:
      // {$discordChannel} (e.g. #general)
      // {$ircChannel} (e.g. #irc)
      webhookAvatarURL: 'https://robohash.org/{$nickname}', // Default avatar to use for webhook messages
    },
    ircNickColor: false, // Gives usernames a color in IRC for better readability (on by default)
    ircNickColors: [
      'light_blue',
      'dark_blue',
      'light_red',
      'dark_red',
      'light_green',
      'dark_green',
      'magenta',
      'light_magenta',
      'orange',
      'yellow',
      'cyan',
      'light_cyan',
    ], // Which irc-upd colors to use
    parallelPingFix: true, // Prevents users of both IRC and Discord from being mentioned in IRC when they speak in Discord (off by default)
    // Makes the bot hide the username prefix for messages that start
    // with one of these characters (commands):
    commandCharacters: ['!', '.'],
    ircStatusNotices: true, // Enables notifications in Discord when people join/part in the relevant IRC channel
    ignoreUsers: {
      irc: ['DCB', 'discord-irc'], // Ignore specified IRC nicks and do not send their messages to Discord.
      //discord: ['discord_nick1', 'discord_nick2'], // Ignore specified Discord nicks and do not send their messages to IRC.
      discordIds: ['redacted-id', 'redacted-id1'], // Ignore specified Discord ids and do not send their messages to IRC.
    },
    // List of webhooks per channel
    webhooks: {
      '#discord': 'https://discord.com/api/webhooks/id/token',
    },
  },
];

Edit: Looks like it's also throwing a fit on the ignoreUsers section... but this working config now has the bot joining channels and the like on its own:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
    ],
    "discordToken": "bloop",
    "channelMapping": {
      "#redacted": "#redacted",
      "redacted-discord-id": "#redacted1",
      "redacted-discord-id1": "#redacted2",
      "redacted-discord-id2": "#redacted3"
    },
  "ircOptions": {
    "password": "redacted"
    }
 }
]
KeiroD commented 10 months ago

Also appears that pings and display IRC users leaving/joining channels aren't working either. Sample config:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
    ],
    "discordToken": "bloop",
    "channelMapping": {
      "#redacted": "#redacted",
      "redacted-discord-id": "#redacted1",
      "redacted-discord-id1": "#redacted2",
      "redacted-discord-id2": "#redacted3"
    },
  "ircOptions": {
    "password": "redacted",
  "parallelPingFix": true,
  "ircStatusNotices": true,
    }
 }
]

This bot is also bridging to Telegram and have received reports the pings are distracting on Telegram but as far as I can tell, while this config is valid, and the bot joins channels successfully and the like the pings and part/joins aren't actually functional.

Edit: I was able to correct the ping issue by using the ircText option to edit how the message is displayed and that resolves the ping issues... but maybe this should still be investigated?

aronson commented 10 months ago

Addressing PluralKit/webhook support now. I'll send another comment when the release is out. I'll have to set up PluralKit in my test server, but I've seen it used before.

As for readme updating I agree. I plan to revise the documentation overall this weekend with better examples and will include that in the go. I don't want it to be confusing or misleading.

As for your JSON, you're missing the double quotes around property names and strings starting at format, which should be "format". This is why various sections are throwing errors. If you resolve that, it looks good to me.

You don't need to specify the default nick colors, deleting that section will use the defaults. You also don't need to specify them if you disable the nick colors as you have, which I don't recommend unless it causes problems with other bridge applications.

aronson commented 10 months ago

I'm not sure what you mean by "pings don't work". In which direction, irc->discord or vice versa? Are these pings in the format @username or are they in @displayName or @nickName?

We use this config in prod, nearly the same as the readme, which pings users and informs IRC users how to ping (which is by username, not displayName or nickName as those caused unwanted pings consistently for our 15k user server). Supporting spaces within pingable names is a problem for both performance and parsing reasons and leads to a large volume of unwanted pings and strange formatting issues. We tried it and scrapped it because it performed terribly, and was one of the motivating factors for the rewrite.

You'd want to ping me as @luigi___ from IRC, not @Luigi, despite me showing up as Luigi with my displayName in discord chat.

  "format": {
    "commandPrelude": "{$nickname} said:",
    "ircText": "<{$displayUsername} [@{$discordUsername}]> {$text}",
    "urlAttachment": "<{$displayUsername}> {$attachmentURL}",
    "discord": "<@**{$author}**> {$withMentions}"
  },
aronson commented 10 months ago

Join/part events are working on my end, which is odd...

image

EDIT: Just saw your edit, glad pings are working and hope our setup isn't too confusing. The bot has seen a number of undocumented changes underneath I'll have to address with that documentation update.

KeiroD commented 10 months ago

Yep, you got me on the "format".

I think the ping issue might still be present, hard to tell for sure but currently I've got a minimal valid json config with the ircText option that has the discord/telegram username @ mentions removed, so that's technically one way of fixing the issue:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
    ],
    "discordToken": "redacted",
    "channelMapping": {
      "#redacted": "#redacted",
      "discord-id": "#redacted1",
      "discord-id1": "#redacted2",
      "discord-id2": "#redacted3"
    },
    "format": {
      // Optional custom formatting options
      // Patterns, represented by {$patternName}, are replaced when sending messages
      "commandPrelude": "Command sent by {$nickname}", // Message sent before a command
      "ircText": "<{$displayUsername}> {$text}", // When sending a message to IRC
      "urlAttachment": "<{$displayUsername}> {$attachmentURL}", // When sending a Discord attachment to IRC
      "discord": "**<{$author}>** {$withMentions}", // When sending a message to Discord
      // Other patterns that can be used:
      // {$discordChannel} (e.g. #general)
      // {$ircChannel} (e.g. #irc)
      "webhookAvatarURL": "https://robohash.org/{$nickname}" // Default avatar to use for webhook messages
    },
  "ircOptions": {
    "password": "redacted",
  "parallelPingFix": false,
  "ircStatusNotices": true,
    }
 }
]

However... this particular config with the irc nick colors removed (I'd left that in, was planning on enabling that once this was all sorted.)... seems to throw a fit with JSONLint around "format" after fixing it and join/parts do not seem to be working now:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "discordToken": "redacted",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
      ],
    "channelMapping": {
      "#redacted": "#redacted",
      "discord-id": "#redacted1",
      "discord-id1": "#redacted2",
      "discord-id2": "#redacted3"
     },
     "ircOptions": {
      "username": "Example",
      "password": "redacted"
     },
    "format": {
      // Optional custom formatting options
      // Patterns, represented by {$patternName}, are replaced when sending messages
      "commandPrelude": "Command sent by {$nickname}", // Message sent before a command
      "ircText": "<{$displayUsername}> {$text}", // When sending a message to IRC
      "urlAttachment": "<{$displayUsername}> {$attachmentURL}", // When sending a Discord attachment to IRC
      "discord": "**<{$author}>** {$withMentions}", // When sending a message to Discord
      // Other patterns that can be used:
      // {$discordChannel} (e.g. #general)
      // {$ircChannel} (e.g. #irc)
      "webhookAvatarURL": "https://robohash.org/{$nickname}", // Default avatar to use for webhook messages
    },
    "parallelPingFix": true, // Prevents users of both IRC and Discord from being mentioned in IRC when they speak in Discord (off by default)
    // Makes the bot hide the username prefix for messages that start
    // with one of these characters (commands):
    "commandCharacters": ["!", "."],
    "ircStatusNotices": true, // Enables notifications in Discord when people join/part in the relevant IRC channel
    "ignoreUsers": {
      "irc": ["DCB", "discord-irc"], // Ignore specified IRC nicks and do not send their messages to Discord.
      //discord: ['discord_nick1', 'discord_nick2'], // Ignore specified Discord nicks and do not send their messages to IRC.
      "discordIds": ["211682893293027330", "1040073034373005324"], // Ignore specified Discord ids and do not send their messages to IRC.
    },
    // List of webhooks per channel
    "webhooks": {
      "#discord": "https://discord.com/api/webhooks/id/token",
    },
  },
]

I'd also realized everything else needed to be updated to use double-quotes.. and that seems to work? But JSONLint really hates comments. I also might be missing something in here even with the helpful pointer to where the error was happening. SPEAKING OF ERRORS... lol

bot@irc:~$ tail -f debug.log 
      expected: "array",
      received: "undefined",
      path: [ 0, "ignoreUsers", "discord" ],
      message: "Required"
    }
  ],
  addIssue: [Function: addIssue],
  addIssues: [Function: addIssues],
  name: "ZodError"
}
^C
bot@irc:~$ tail -f debug.log -n 120
Error parsing configuration:
ZodError: [
  {
    "code": "invalid_type",
    "expected": "array",
    "received": "undefined",
    "path": [
      0,
      "ignoreUsers",
      "discord"
    ],
    "message": "Required"
  }
]
    at handleResult (https://deno.land/x/zod@v3.16.1/types.ts:30:19)
    at ZodArray.safeParse (https://deno.land/x/zod@v3.16.1/types.ts:134:12)
    at parseConfigObject (file:///home/runner/work/discord-irc/discord-irc/lib/config.ts:55:38)
    at run (file:///home/runner/work/discord-irc/discord-irc/lib/cli.ts:40:18)
    at async file:///home/runner/work/discord-irc/discord-irc/discord-irc.ts:3:1 {
  issues: [
    {
      code: "invalid_type",
      expected: "array",
      received: "undefined",
      path: [ 0, "ignoreUsers", "discord" ],
      message: "Required"
    }
  ],
  addIssue: [Function: addIssue],
  addIssues: [Function: addIssues],
  name: "ZodError"
}
^C

I see you asked about pings -- I'm not entirely clear on this option but I think it's supposed to silence pings on Discord/IRC according to the documentation? I could be wrong on this.

aronson commented 10 months ago

I couldn't find a single JSONC linter online. If you have comments in your JSON, no online linter will validate it AFAIK. You'd have to use the command line, so I suggest removing the comments.

EDIT: Found one that supports comments, looks pretty powerful

New release fixing the ignore config bug you found.

I looked into the code and the parallel ping fix appears to actually do nothing at this point! I'll remove it. Its use is irrelevant with the other changes to pinging I mentioned.

KeiroD commented 10 months ago

Nice find on the linter that checks for comments! I've removed the comments from mine and have a copy of the config with comments so I know what option does what.

As for the join/part stuff... that seems to not be working still for me. I'm not sure why. Otherwise, things are working with this config aside from the join/part:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
    ],
    "discordToken": "redacted",
    "channelMapping": {
      "#redacted": "#redacted",
      "discord-id": "#redacted1",
      "discord-id2": "#redacted2",
      "discord-id3": "#redacted3"
    },
    "format": {
      "commandPrelude": "Command sent by {$nickname}",
      "ircText": "<{$displayUsername}> {$text}",
      "urlAttachment": "<{$displayUsername}> {$attachmentURL}",
      "discord": "**<{$author}>** {$withMentions}",
      "webhookAvatarURL": "https://robohash.org/{$nickname}"
    },
  "ircOptions": {
    "password": "redacted",
  "ircStatusNotices": true,
    "ignoreUsers": {
      "irc": ["DCB", "discord-irc"],
      "discordIds": ["211682893293027330", "1040073034373005324"],
    },
    }
 }
]

Anyway, so pings should work as intended when pinging users only as desired by removing the [@{$discordUsername}]> bit instead of bot pinging with every message.

Edit: Also have updated to the release with the ignore users bug fix.

aronson commented 10 months ago

Ah! I see the issue, your ircStatusNotices as well as ignoreUsers properties are in the wrong place. They're under ircOptions when they should be under the main-level scope. Just a misplaced }.

Try changing the final section to this:

[
  {
    // include the rest of the config above without comments
    "ircOptions": {
      "password": "redacted"
    },
    "ignoreUsers": {
      "irc": ["DCB", "discord-irc"],
      "discordIds": ["211682893293027330", "1040073034373005324"]
    },
    "ircStatusNotices": true
  }
]
KeiroD commented 10 months ago

Got it. Valid config is now:

[
  {
    "nickname": "Example",
    "server": "irc.example.com",
    "autoSendCommands": [
      ["PRIVMSG", "NickServ", "IDENTIFY password"]
    ],
    "discordToken": "redacted",
    "channelMapping": {
      "#redacted": "#redacted",
      "discord-id1": "#redacted1",
      "discord-id2": "#redacted2",
      "discord-id3": "#redacted3"
    },
    "format": {
      "commandPrelude": "Command sent by {$nickname}",
      "ircText": "<{$displayUsername}> {$text}",
      "urlAttachment": "<{$displayUsername}> {$attachmentURL}",
      "discord": "**<{$author}>** {$withMentions}",
      "webhookAvatarURL": "https://robohash.org/{$nickname}"
    },
    "ircStatusNotices": true,
    "ignoreUsers": {
      "irc": ["DCB", "discord-irc"],
      "discordIds": ["211682893293027330", "1040073034373005324"],
    },
  "ircOptions": {
    "password": "redacted"
    },
  }
}
]

That was a bit headache-inducing. Join/parts are now correctly displaying. I think all that's left for me to get stuff working is PluralKit/tupper support.

Edit: JSONLint says it doesn't like my discordIDs for ignoring users... but it seems to be valid for the bot? I can't tell if ignores are working but maybe that's not an issue. shrug Anyway, it doesn't crash so I'll take that as a win.

Edit2: Also, can we get an option to customize the leave/join part for the notices? It's not necessarily obvious that the user might be leaving on IRC and people might think a Discord user has left the server when that's not the case.

e.g.: User has left IRC [channel name]/ User has joined IRC [channel name]

aronson commented 10 months ago

You could set the ignore IDs to yourself temporarily to test, that's what I do.

Allowing end-users to customize those messages is a bit difficult with how the code is written right now. When I re-write the formatting internals I'll be able to include configuration for it.

For now, here's a release that makes it obvious these messages are about the IRC server.

I have PluralKit set up and am testing now. Not sure how to avoid duplicate messages from it on the IRC side though...

aronson commented 10 months ago

Both tupper and PluralKit are working fine in my tests. I don't get any crashes and messages are passed and presented as expected.

KeiroD commented 10 months ago

Hmm. I must've just assumed it was Pluralkit/tupper crashing the bot when it was something else. Doesn't seem to crash now. Also, as you mentioned, ignores for yourself does work! So that's good. Thanks for that, I should've thought of that, heh.

Regarding the customization of messages -- that's fair. I think your solution works just fine.

Edit: uhhh so how should I yeet this into background mode? I've been just yeeting it into a screen session.

aronson commented 10 months ago

Doesn't seem to crash now

I think that webhook user lookup issue was addressed a little while ago, so you may have had an old build at the time with the bug. We ran into a similar issue in the other discord server using the bot and I fixed it in code then.

How to yeet into the background? A few options, but it depends, what Linux distro are you running, and what version of that distro (e.g. Ubuntu 20.04, Fedora 38, etc.)? I think the best way is Docker as it's easy to update, but if you don't want to use Docker there are other options that depend on your distro we can explore. If you're open to Docker I can give you instructions on how to install it for your distro and set it up with this bot, as well as keep it up to date.

KeiroD commented 10 months ago

fixed it in code then.

That's probably it, yup.

I run Ubuntu 22.04 and while I'd be ok with running it in docker on this server, I'm not entirely sure how that'll go. I've also used pm2 for the previous iteration of discord-irc prior to your forking of this project.

I suppose I could also use tmux? In any case, I'll give docker a shot. Keeping it updated would be very nice indeed.

aronson commented 10 months ago

Options I'd use myself if I wanted something lightweight and to manually update the binaries, in no particular order:

Here's a preview of one of the updated wiki articles I'll be adding, which should cover all you need to know about using the app with Docker:

Installing Docker on Ubuntu

To install docker, follow steps 1 and 2 of the linked section of this guide

Running the Docker Image

To run the Docker image, you can use the docker run command. This command creates a new container from the Docker image and starts it. If the image is not available locally, Docker will pull it from the Docker registry. Here's how you can run your app:

docker run -v /path/to/config.json:/app/config.json ghcr.io/aronson/discord-irc

In this command, -v /path/to/config.json:/app/config.json is used to mount the config.json file from your host system to the Docker container. This is known as a bind mount. The file on the host system is linked to the file in the Docker container, and any changes made to the file will be reflected in both the host system and the Docker container.

The left side of /path/to/config.json:/app/config.json (separated by :) can be any path and/or file name, but the right side must be identical to what is shown here.

Running the Docker Image with --restart=always

To ensure that your Docker container restarts automatically if it crashes, you can use the --restart=always option when running the Docker container:

docker run --restart=always -v /path/to/config.json:/app/config.json ghcr.io/aronson/discord-irc

The --restart=always option ensures that the Docker container restarts automatically whenever it stops. If it's manually stopped, it's restarted only when Docker daemon restarts or the container itself is manually restarted.

Stopping the Running Instance

To stop an instance, you will need to know its container-id. Use the docker ps command to get a list of running and/or stopped containers.

To stop a running Docker container, you can use the docker stop command followed by the container ID or name:

docker stop container-id

The docker stop command sends a SIGTERM signal to the main process inside the Docker container. After a grace period, if the container is still running, Docker sends a SIGKILL signal to stop the container.

With discord-irc the docker stop command should take only a few seconds.

After stopping a container, one can start it again with docker start:

docker start container-id

Pulling Down an Updated Image and Replacing a Running Instance with the New Image

To pull down an updated image, you can use the docker pull command followed by the name of the image:

docker pull ghcr.io/aronson/discord-irc

This command pulls the latest version of the image from the Docker registry.

To replace a running instance with the new image, you first need to stop the running container, remove it, and then start a new container with the updated image:

docker stop container-id
docker rm container-id
docker run --restart=always -v /path/to/config.json:/app/config.json ghcr.io/aronson/discord-irc

In these commands, docker rm is used to remove the Docker container. After the old container is removed, a new container is started with the updated image.

KeiroD commented 10 months ago

Hi,

Just wanted to say thanks for the guide! So far, no further issues, I think. I'd be happy to continue testing the bot for every release moving forward to let you know of any new issues if you like?

Will switch to Docker and come back if I've any further issues but I think tentatively we're good but I'll let users continue trying to find new stuff, and close this by Saturday after I do the switch to Docker later today.

Again, thank you so much for working with me. I really appreciate it.

aronson commented 10 months ago

Glad it's working. Always happy to address issues as they arise.

I believe you can subscribe to notifications on this repository through GitHub to be notified of new releases as they're out. Sometimes we have a few rapid releases back-to-back. Feel free to report back if upgrades bring issues. I'll have to add a section to the guide on how to roll back to old versions.

EDIT: on the main github page, go here and choose "Custom"

image

Then choose "Releases" and hit apply.

image
aronson commented 10 months ago

We pushed a new release with a number of significant updates. The biggest one is we added long message splits and flood protection. Before these changes two things could happen

If your server has flood protection and/or you see the IRC bot getting disconnected in the log after sending a long Discord message, I suggest enabling it with this config snippet on the latest release by adding floodDelay to your ircOptions:

{
  // include other properties from before

  "ircOptions": {
    "password": "[REDACTED]",
    "floodDelay": 1000 // 1000-2000 milliseconds is a generally safe delay
  }
}

Let me know if you have any questions. The long message split is definitely a nice to have. Flood protection is disabled by default in discord-irc and on a casual or self-hosted IRC server you may not need it. The easiest way to test is to send a very long message two or three times in Discord and see if the bot gets kicked, at least on Libera.

KeiroD commented 10 months ago

Hi!

Got busy over the weekend, but did deploy on docker. Should be good! So far, so good! The IRC flood also works.

I think at this time I'm going to go ahead and close this issue, as everything appears to be working well at this point and I've not encountered any teething issues with config validations and the like. :D

Thanks again! I also have been following this repository ever since I came across this one.

Quu1337 commented 10 months ago

looks like irc-channel names need to be lowercase. joins the channel on uppercase names, works from discord->irc but not irc->discord πŸ€¦β€β™‚οΈ probably unrelated to any of this but eh

aronson commented 10 months ago

I know the source of the issue. I'll have a fix out before the weekend is over and update you in this thread.

Thanks for bringing that to my attention, uppercase names should work

aronson commented 10 months ago

OK that was actually way easier to fix than I expected.

If you're using binaries, you can find a download for the latest build here. If you're using docker, the image tag is sha-ed56525.

Tested with uppercase IRC channels and working on my end.

ssemkaz commented 10 months ago

The problem with "cannot use 'in'..." has not been resolved. What should I do? PS C:\Users\willi\OneDrive\Π Π°Π±ΠΎΡ‡ΠΈΠΉ стол\discord-irc-sync-master> & '.\discord-irc-windows-x64 (2).exe' error: Uncaught (in promise) TypeError: Cannot use 'in' operator to search for 'userName' in undefined if ('userName' in obj) { ^ at testIrcOptions (file:///D:/a/discord-irc/discord-irc/lib/cli.ts:6:18) at run (file:///D:/a/discord-irc/discord-irc/lib/cli.ts:65:34) at eventLoopTick (ext:core/01_core.js:183:11) at async file:///D:/a/discord-irc/discord-irc/discord-irc.ts:3:1

aronson commented 10 months ago

The fix was in another branch and not released yet. Try using this release I just made, @ssemkaz, or pulling main now.

https://github.com/aronson/discord-irc/releases/tag/6.0.0