snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
519
apps/meteor/server/bridges/irc/servers/RFC2813/codes.js
Normal file
519
apps/meteor/server/bridges/irc/servers/RFC2813/codes.js
Normal file
@@ -0,0 +1,519 @@
|
||||
/**
|
||||
* This file is part of https://github.com/martynsmith/node-irc
|
||||
* by https://github.com/martynsmith
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
'001': {
|
||||
name: 'rpl_welcome',
|
||||
type: 'reply',
|
||||
},
|
||||
'002': {
|
||||
name: 'rpl_yourhost',
|
||||
type: 'reply',
|
||||
},
|
||||
'003': {
|
||||
name: 'rpl_created',
|
||||
type: 'reply',
|
||||
},
|
||||
'004': {
|
||||
name: 'rpl_myinfo',
|
||||
type: 'reply',
|
||||
},
|
||||
'005': {
|
||||
name: 'rpl_isupport',
|
||||
type: 'reply',
|
||||
},
|
||||
'200': {
|
||||
name: 'rpl_tracelink',
|
||||
type: 'reply',
|
||||
},
|
||||
'201': {
|
||||
name: 'rpl_traceconnecting',
|
||||
type: 'reply',
|
||||
},
|
||||
'202': {
|
||||
name: 'rpl_tracehandshake',
|
||||
type: 'reply',
|
||||
},
|
||||
'203': {
|
||||
name: 'rpl_traceunknown',
|
||||
type: 'reply',
|
||||
},
|
||||
'204': {
|
||||
name: 'rpl_traceoperator',
|
||||
type: 'reply',
|
||||
},
|
||||
'205': {
|
||||
name: 'rpl_traceuser',
|
||||
type: 'reply',
|
||||
},
|
||||
'206': {
|
||||
name: 'rpl_traceserver',
|
||||
type: 'reply',
|
||||
},
|
||||
'208': {
|
||||
name: 'rpl_tracenewtype',
|
||||
type: 'reply',
|
||||
},
|
||||
'211': {
|
||||
name: 'rpl_statslinkinfo',
|
||||
type: 'reply',
|
||||
},
|
||||
'212': {
|
||||
name: 'rpl_statscommands',
|
||||
type: 'reply',
|
||||
},
|
||||
'213': {
|
||||
name: 'rpl_statscline',
|
||||
type: 'reply',
|
||||
},
|
||||
'214': {
|
||||
name: 'rpl_statsnline',
|
||||
type: 'reply',
|
||||
},
|
||||
'215': {
|
||||
name: 'rpl_statsiline',
|
||||
type: 'reply',
|
||||
},
|
||||
'216': {
|
||||
name: 'rpl_statskline',
|
||||
type: 'reply',
|
||||
},
|
||||
'218': {
|
||||
name: 'rpl_statsyline',
|
||||
type: 'reply',
|
||||
},
|
||||
'219': {
|
||||
name: 'rpl_endofstats',
|
||||
type: 'reply',
|
||||
},
|
||||
'221': {
|
||||
name: 'rpl_umodeis',
|
||||
type: 'reply',
|
||||
},
|
||||
'241': {
|
||||
name: 'rpl_statslline',
|
||||
type: 'reply',
|
||||
},
|
||||
'242': {
|
||||
name: 'rpl_statsuptime',
|
||||
type: 'reply',
|
||||
},
|
||||
'243': {
|
||||
name: 'rpl_statsoline',
|
||||
type: 'reply',
|
||||
},
|
||||
'244': {
|
||||
name: 'rpl_statshline',
|
||||
type: 'reply',
|
||||
},
|
||||
'250': {
|
||||
name: 'rpl_statsconn',
|
||||
type: 'reply',
|
||||
},
|
||||
'251': {
|
||||
name: 'rpl_luserclient',
|
||||
type: 'reply',
|
||||
},
|
||||
'252': {
|
||||
name: 'rpl_luserop',
|
||||
type: 'reply',
|
||||
},
|
||||
'253': {
|
||||
name: 'rpl_luserunknown',
|
||||
type: 'reply',
|
||||
},
|
||||
'254': {
|
||||
name: 'rpl_luserchannels',
|
||||
type: 'reply',
|
||||
},
|
||||
'255': {
|
||||
name: 'rpl_luserme',
|
||||
type: 'reply',
|
||||
},
|
||||
'256': {
|
||||
name: 'rpl_adminme',
|
||||
type: 'reply',
|
||||
},
|
||||
'257': {
|
||||
name: 'rpl_adminloc1',
|
||||
type: 'reply',
|
||||
},
|
||||
'258': {
|
||||
name: 'rpl_adminloc2',
|
||||
type: 'reply',
|
||||
},
|
||||
'259': {
|
||||
name: 'rpl_adminemail',
|
||||
type: 'reply',
|
||||
},
|
||||
'261': {
|
||||
name: 'rpl_tracelog',
|
||||
type: 'reply',
|
||||
},
|
||||
'265': {
|
||||
name: 'rpl_localusers',
|
||||
type: 'reply',
|
||||
},
|
||||
'266': {
|
||||
name: 'rpl_globalusers',
|
||||
type: 'reply',
|
||||
},
|
||||
'300': {
|
||||
name: 'rpl_none',
|
||||
type: 'reply',
|
||||
},
|
||||
'301': {
|
||||
name: 'rpl_away',
|
||||
type: 'reply',
|
||||
},
|
||||
'302': {
|
||||
name: 'rpl_userhost',
|
||||
type: 'reply',
|
||||
},
|
||||
'303': {
|
||||
name: 'rpl_ison',
|
||||
type: 'reply',
|
||||
},
|
||||
'305': {
|
||||
name: 'rpl_unaway',
|
||||
type: 'reply',
|
||||
},
|
||||
'306': {
|
||||
name: 'rpl_nowaway',
|
||||
type: 'reply',
|
||||
},
|
||||
'311': {
|
||||
name: 'rpl_whoisuser',
|
||||
type: 'reply',
|
||||
},
|
||||
'312': {
|
||||
name: 'rpl_whoisserver',
|
||||
type: 'reply',
|
||||
},
|
||||
'313': {
|
||||
name: 'rpl_whoisoperator',
|
||||
type: 'reply',
|
||||
},
|
||||
'314': {
|
||||
name: 'rpl_whowasuser',
|
||||
type: 'reply',
|
||||
},
|
||||
'315': {
|
||||
name: 'rpl_endofwho',
|
||||
type: 'reply',
|
||||
},
|
||||
'317': {
|
||||
name: 'rpl_whoisidle',
|
||||
type: 'reply',
|
||||
},
|
||||
'318': {
|
||||
name: 'rpl_endofwhois',
|
||||
type: 'reply',
|
||||
},
|
||||
'319': {
|
||||
name: 'rpl_whoischannels',
|
||||
type: 'reply',
|
||||
},
|
||||
'321': {
|
||||
name: 'rpl_liststart',
|
||||
type: 'reply',
|
||||
},
|
||||
'322': {
|
||||
name: 'rpl_list',
|
||||
type: 'reply',
|
||||
},
|
||||
'323': {
|
||||
name: 'rpl_listend',
|
||||
type: 'reply',
|
||||
},
|
||||
'324': {
|
||||
name: 'rpl_channelmodeis',
|
||||
type: 'reply',
|
||||
},
|
||||
'329': {
|
||||
name: 'rpl_creationtime',
|
||||
type: 'reply',
|
||||
},
|
||||
'331': {
|
||||
name: 'rpl_notopic',
|
||||
type: 'reply',
|
||||
},
|
||||
'332': {
|
||||
name: 'rpl_topic',
|
||||
type: 'reply',
|
||||
},
|
||||
'333': {
|
||||
name: 'rpl_topicwhotime',
|
||||
type: 'reply',
|
||||
},
|
||||
'341': {
|
||||
name: 'rpl_inviting',
|
||||
type: 'reply',
|
||||
},
|
||||
'342': {
|
||||
name: 'rpl_summoning',
|
||||
type: 'reply',
|
||||
},
|
||||
'351': {
|
||||
name: 'rpl_version',
|
||||
type: 'reply',
|
||||
},
|
||||
'352': {
|
||||
name: 'rpl_whoreply',
|
||||
type: 'reply',
|
||||
},
|
||||
'353': {
|
||||
name: 'rpl_namreply',
|
||||
type: 'reply',
|
||||
},
|
||||
'364': {
|
||||
name: 'rpl_links',
|
||||
type: 'reply',
|
||||
},
|
||||
'365': {
|
||||
name: 'rpl_endoflinks',
|
||||
type: 'reply',
|
||||
},
|
||||
'366': {
|
||||
name: 'rpl_endofnames',
|
||||
type: 'reply',
|
||||
},
|
||||
'367': {
|
||||
name: 'rpl_banlist',
|
||||
type: 'reply',
|
||||
},
|
||||
'368': {
|
||||
name: 'rpl_endofbanlist',
|
||||
type: 'reply',
|
||||
},
|
||||
'369': {
|
||||
name: 'rpl_endofwhowas',
|
||||
type: 'reply',
|
||||
},
|
||||
'371': {
|
||||
name: 'rpl_info',
|
||||
type: 'reply',
|
||||
},
|
||||
'372': {
|
||||
name: 'rpl_motd',
|
||||
type: 'reply',
|
||||
},
|
||||
'374': {
|
||||
name: 'rpl_endofinfo',
|
||||
type: 'reply',
|
||||
},
|
||||
'375': {
|
||||
name: 'rpl_motdstart',
|
||||
type: 'reply',
|
||||
},
|
||||
'376': {
|
||||
name: 'rpl_endofmotd',
|
||||
type: 'reply',
|
||||
},
|
||||
'381': {
|
||||
name: 'rpl_youreoper',
|
||||
type: 'reply',
|
||||
},
|
||||
'382': {
|
||||
name: 'rpl_rehashing',
|
||||
type: 'reply',
|
||||
},
|
||||
'391': {
|
||||
name: 'rpl_time',
|
||||
type: 'reply',
|
||||
},
|
||||
'392': {
|
||||
name: 'rpl_usersstart',
|
||||
type: 'reply',
|
||||
},
|
||||
'393': {
|
||||
name: 'rpl_users',
|
||||
type: 'reply',
|
||||
},
|
||||
'394': {
|
||||
name: 'rpl_endofusers',
|
||||
type: 'reply',
|
||||
},
|
||||
'395': {
|
||||
name: 'rpl_nousers',
|
||||
type: 'reply',
|
||||
},
|
||||
'401': {
|
||||
name: 'err_nosuchnick',
|
||||
type: 'error',
|
||||
},
|
||||
'402': {
|
||||
name: 'err_nosuchserver',
|
||||
type: 'error',
|
||||
},
|
||||
'403': {
|
||||
name: 'err_nosuchchannel',
|
||||
type: 'error',
|
||||
},
|
||||
'404': {
|
||||
name: 'err_cannotsendtochan',
|
||||
type: 'error',
|
||||
},
|
||||
'405': {
|
||||
name: 'err_toomanychannels',
|
||||
type: 'error',
|
||||
},
|
||||
'406': {
|
||||
name: 'err_wasnosuchnick',
|
||||
type: 'error',
|
||||
},
|
||||
'407': {
|
||||
name: 'err_toomanytargets',
|
||||
type: 'error',
|
||||
},
|
||||
'409': {
|
||||
name: 'err_noorigin',
|
||||
type: 'error',
|
||||
},
|
||||
'411': {
|
||||
name: 'err_norecipient',
|
||||
type: 'error',
|
||||
},
|
||||
'412': {
|
||||
name: 'err_notexttosend',
|
||||
type: 'error',
|
||||
},
|
||||
'413': {
|
||||
name: 'err_notoplevel',
|
||||
type: 'error',
|
||||
},
|
||||
'414': {
|
||||
name: 'err_wildtoplevel',
|
||||
type: 'error',
|
||||
},
|
||||
'421': {
|
||||
name: 'err_unknowncommand',
|
||||
type: 'error',
|
||||
},
|
||||
'422': {
|
||||
name: 'err_nomotd',
|
||||
type: 'error',
|
||||
},
|
||||
'423': {
|
||||
name: 'err_noadmininfo',
|
||||
type: 'error',
|
||||
},
|
||||
'424': {
|
||||
name: 'err_fileerror',
|
||||
type: 'error',
|
||||
},
|
||||
'431': {
|
||||
name: 'err_nonicknamegiven',
|
||||
type: 'error',
|
||||
},
|
||||
'432': {
|
||||
name: 'err_erroneusnickname',
|
||||
type: 'error',
|
||||
},
|
||||
'433': {
|
||||
name: 'err_nicknameinuse',
|
||||
type: 'error',
|
||||
},
|
||||
'436': {
|
||||
name: 'err_nickcollision',
|
||||
type: 'error',
|
||||
},
|
||||
'441': {
|
||||
name: 'err_usernotinchannel',
|
||||
type: 'error',
|
||||
},
|
||||
'442': {
|
||||
name: 'err_notonchannel',
|
||||
type: 'error',
|
||||
},
|
||||
'443': {
|
||||
name: 'err_useronchannel',
|
||||
type: 'error',
|
||||
},
|
||||
'444': {
|
||||
name: 'err_nologin',
|
||||
type: 'error',
|
||||
},
|
||||
'445': {
|
||||
name: 'err_summondisabled',
|
||||
type: 'error',
|
||||
},
|
||||
'446': {
|
||||
name: 'err_usersdisabled',
|
||||
type: 'error',
|
||||
},
|
||||
'451': {
|
||||
name: 'err_notregistered',
|
||||
type: 'error',
|
||||
},
|
||||
'461': {
|
||||
name: 'err_needmoreparams',
|
||||
type: 'error',
|
||||
},
|
||||
'462': {
|
||||
name: 'err_alreadyregistred',
|
||||
type: 'error',
|
||||
},
|
||||
'463': {
|
||||
name: 'err_nopermforhost',
|
||||
type: 'error',
|
||||
},
|
||||
'464': {
|
||||
name: 'err_passwdmismatch',
|
||||
type: 'error',
|
||||
},
|
||||
'465': {
|
||||
name: 'err_yourebannedcreep',
|
||||
type: 'error',
|
||||
},
|
||||
'467': {
|
||||
name: 'err_keyset',
|
||||
type: 'error',
|
||||
},
|
||||
'471': {
|
||||
name: 'err_channelisfull',
|
||||
type: 'error',
|
||||
},
|
||||
'472': {
|
||||
name: 'err_unknownmode',
|
||||
type: 'error',
|
||||
},
|
||||
'473': {
|
||||
name: 'err_inviteonlychan',
|
||||
type: 'error',
|
||||
},
|
||||
'474': {
|
||||
name: 'err_bannedfromchan',
|
||||
type: 'error',
|
||||
},
|
||||
'475': {
|
||||
name: 'err_badchannelkey',
|
||||
type: 'error',
|
||||
},
|
||||
'481': {
|
||||
name: 'err_noprivileges',
|
||||
type: 'error',
|
||||
},
|
||||
'482': {
|
||||
name: 'err_chanoprivsneeded',
|
||||
type: 'error',
|
||||
},
|
||||
'483': {
|
||||
name: 'err_cantkillserver',
|
||||
type: 'error',
|
||||
},
|
||||
'491': {
|
||||
name: 'err_nooperhost',
|
||||
type: 'error',
|
||||
},
|
||||
'501': {
|
||||
name: 'err_umodeunknownflag',
|
||||
type: 'error',
|
||||
},
|
||||
'502': {
|
||||
name: 'err_usersdontmatch',
|
||||
type: 'error',
|
||||
},
|
||||
};
|
||||
195
apps/meteor/server/bridges/irc/servers/RFC2813/index.js
Normal file
195
apps/meteor/server/bridges/irc/servers/RFC2813/index.js
Normal file
@@ -0,0 +1,195 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import net from 'node:net';
|
||||
import util from 'node:util';
|
||||
|
||||
import { Logger } from '@rocket.chat/logger';
|
||||
|
||||
import localCommandHandlers from './localCommandHandlers';
|
||||
import parseMessage from './parseMessage';
|
||||
import peerCommandHandlers from './peerCommandHandlers';
|
||||
|
||||
const logger = new Logger('IRC Server');
|
||||
|
||||
class RFC2813 {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
|
||||
// Hold registered state
|
||||
this.registerSteps = [];
|
||||
this.isRegistered = false;
|
||||
|
||||
// Hold peer server information
|
||||
this.serverPrefix = null;
|
||||
|
||||
// Hold the buffer while receiving
|
||||
this.receiveBuffer = Buffer.from('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup socket
|
||||
*/
|
||||
setupSocket() {
|
||||
// Setup socket
|
||||
this.socket = new net.Socket();
|
||||
this.socket.setNoDelay();
|
||||
this.socket.setEncoding('utf-8');
|
||||
this.socket.setKeepAlive(true);
|
||||
this.socket.setTimeout(90000);
|
||||
|
||||
this.socket.on('data', this.onReceiveFromPeer.bind(this));
|
||||
|
||||
this.socket.on('connect', this.onConnect.bind(this));
|
||||
this.socket.on('error', (err) => logger.error({ msg: 'Socket error', err }));
|
||||
this.socket.on('timeout', () => this.log({ msg: 'Timeout' }));
|
||||
this.socket.on('close', () => this.log({ msg: 'Connection Closed' }));
|
||||
// Setup local
|
||||
this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log helper
|
||||
*/
|
||||
log(message) {
|
||||
// TODO logger: debug?
|
||||
if (typeof message === 'string') {
|
||||
logger.info({ msg: message });
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect
|
||||
*/
|
||||
register() {
|
||||
this.log({
|
||||
msg: 'Connecting to IRC server',
|
||||
host: this.config.server.host,
|
||||
port: this.config.server.port,
|
||||
});
|
||||
|
||||
if (!this.socket) {
|
||||
this.setupSocket();
|
||||
}
|
||||
|
||||
this.socket.connect(this.config.server.port, this.config.server.host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect
|
||||
*/
|
||||
disconnect() {
|
||||
this.log('Disconnecting from server.');
|
||||
|
||||
if (this.socket) {
|
||||
this.socket.destroy();
|
||||
this.socket = undefined;
|
||||
}
|
||||
this.isRegistered = false;
|
||||
this.registerSteps = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the server connection
|
||||
*/
|
||||
onConnect() {
|
||||
this.log('Connected! Registering as server...');
|
||||
|
||||
this.write({
|
||||
command: 'PASS',
|
||||
parameters: [this.config.passwords.local, '0210', 'ngircd'],
|
||||
});
|
||||
|
||||
this.write({
|
||||
command: 'SERVER',
|
||||
parameters: [this.config.server.name],
|
||||
trailer: this.config.server.description,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command message through the socket
|
||||
*/
|
||||
write(command) {
|
||||
let buffer = command.prefix ? `:${command.prefix} ` : '';
|
||||
buffer += command.command;
|
||||
|
||||
if (command.parameters && command.parameters.length > 0) {
|
||||
buffer += ` ${command.parameters.join(' ')}`;
|
||||
}
|
||||
|
||||
if (command.trailer) {
|
||||
buffer += ` :${command.trailer}`;
|
||||
}
|
||||
|
||||
this.log({ msg: 'Sending Command', buffer });
|
||||
|
||||
return this.socket.write(`${buffer}\r\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Peer message handling
|
||||
*
|
||||
*
|
||||
*/
|
||||
onReceiveFromPeer(chunk) {
|
||||
if (typeof chunk === 'string') {
|
||||
this.receiveBuffer += chunk;
|
||||
} else {
|
||||
this.receiveBuffer = Buffer.concat([this.receiveBuffer, chunk]);
|
||||
}
|
||||
|
||||
const lines = this.receiveBuffer.toString().split(/\r\n|\r|\n|\u0007/); // eslint-disable-line no-control-regex
|
||||
|
||||
// If the buffer does not end with \r\n, more chunks are coming
|
||||
if (lines.pop()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the buffer
|
||||
this.receiveBuffer = Buffer.from('');
|
||||
|
||||
lines.forEach((line) => {
|
||||
if (line.length && !line.startsWith('a')) {
|
||||
const parsedMessage = parseMessage(line);
|
||||
|
||||
if (peerCommandHandlers[parsedMessage.command]) {
|
||||
this.log({ msg: 'Handling peer message', line });
|
||||
|
||||
const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage);
|
||||
|
||||
if (command) {
|
||||
this.log({ msg: 'Emitting peer command to local', command });
|
||||
this.emit('peerCommand', command);
|
||||
}
|
||||
} else {
|
||||
this.log({ msg: 'Unhandled peer message', parsedMessage });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Local message handling
|
||||
*
|
||||
*
|
||||
*/
|
||||
onReceiveFromLocal(command, parameters) {
|
||||
if (localCommandHandlers[command]) {
|
||||
this.log({ msg: 'Handling local command', command });
|
||||
|
||||
localCommandHandlers[command].call(this, parameters, this);
|
||||
} else {
|
||||
this.log({ msg: 'Unhandled local command', command });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(RFC2813, EventEmitter);
|
||||
|
||||
export default RFC2813;
|
||||
@@ -0,0 +1,111 @@
|
||||
function registerUser(parameters) {
|
||||
const {
|
||||
name,
|
||||
profile: {
|
||||
irc: { nick, username },
|
||||
},
|
||||
} = parameters;
|
||||
|
||||
this.write({
|
||||
prefix: this.config.server.name,
|
||||
command: 'NICK',
|
||||
parameters: [nick, 1, username, 'irc.rocket.chat', 1, '+i'],
|
||||
trailer: name,
|
||||
});
|
||||
}
|
||||
|
||||
function joinChannel(parameters) {
|
||||
const {
|
||||
room: { name: roomName },
|
||||
user: {
|
||||
profile: {
|
||||
irc: { nick },
|
||||
},
|
||||
},
|
||||
} = parameters;
|
||||
|
||||
this.write({
|
||||
prefix: this.config.server.name,
|
||||
command: 'NJOIN',
|
||||
parameters: [`#${roomName}`],
|
||||
trailer: nick,
|
||||
});
|
||||
}
|
||||
|
||||
function joinedChannel(parameters, handler) {
|
||||
const roomName = parameters.room?.name;
|
||||
const nick = parameters.user?.profile?.irc?.nick;
|
||||
|
||||
if (!roomName) {
|
||||
handler.log('Skipping room with no name.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nick) {
|
||||
handler.log('Skipping user with no irc nick.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.write({
|
||||
prefix: nick,
|
||||
command: 'JOIN',
|
||||
parameters: [`#${roomName}`],
|
||||
});
|
||||
}
|
||||
|
||||
function leftChannel(parameters) {
|
||||
const {
|
||||
room: { name: roomName },
|
||||
user: {
|
||||
profile: {
|
||||
irc: { nick },
|
||||
},
|
||||
},
|
||||
} = parameters;
|
||||
|
||||
this.write({
|
||||
prefix: nick,
|
||||
command: 'PART',
|
||||
parameters: [`#${roomName}`],
|
||||
});
|
||||
}
|
||||
|
||||
function sentMessage(parameters) {
|
||||
const {
|
||||
user: {
|
||||
profile: {
|
||||
irc: { nick },
|
||||
},
|
||||
},
|
||||
to,
|
||||
message,
|
||||
} = parameters;
|
||||
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const lines = message.toString().split(/\r\n|\r|\n|\u0007/);
|
||||
for (const line of lines) {
|
||||
this.write({
|
||||
prefix: nick,
|
||||
command: 'PRIVMSG',
|
||||
parameters: [to],
|
||||
trailer: line,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function disconnected(parameters) {
|
||||
const {
|
||||
user: {
|
||||
profile: {
|
||||
irc: { nick },
|
||||
},
|
||||
},
|
||||
} = parameters;
|
||||
|
||||
this.write({
|
||||
prefix: nick,
|
||||
command: 'QUIT',
|
||||
});
|
||||
}
|
||||
|
||||
export default { registerUser, joinChannel, joinedChannel, leftChannel, sentMessage, disconnected };
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* This file is part of https://github.com/martynsmith/node-irc
|
||||
* by https://github.com/martynsmith
|
||||
*/
|
||||
|
||||
const replyFor = require('./codes');
|
||||
|
||||
/**
|
||||
* parseMessage(line, stripColors)
|
||||
*
|
||||
* takes a raw "line" from the IRC server and turns it into an object with
|
||||
* useful keys
|
||||
* @param {String} line Raw message from IRC server.
|
||||
* @return {Object} A parsed message object.
|
||||
*/
|
||||
module.exports = function parseMessage(line) {
|
||||
const message = {};
|
||||
let match;
|
||||
|
||||
// Parse prefix
|
||||
match = line.match(/^:([^ ]+) +/);
|
||||
if (match) {
|
||||
message.prefix = match[1];
|
||||
line = line.replace(/^:[^ ]+ +/, '');
|
||||
match = message.prefix.match(/^([_a-zA-Z0-9\~\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/);
|
||||
if (match) {
|
||||
message.nick = match[1];
|
||||
message.user = match[3];
|
||||
message.host = match[4];
|
||||
} else {
|
||||
message.server = message.prefix;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse command
|
||||
match = line.match(/^([^ ]+) */);
|
||||
message.command = match[1];
|
||||
message.rawCommand = match[1];
|
||||
message.commandType = 'normal';
|
||||
line = line.replace(/^[^ ]+ +/, '');
|
||||
|
||||
if (replyFor[message.rawCommand]) {
|
||||
message.command = replyFor[message.rawCommand].name;
|
||||
message.commandType = replyFor[message.rawCommand].type;
|
||||
}
|
||||
|
||||
message.args = [];
|
||||
let middle;
|
||||
let trailing;
|
||||
|
||||
// Parse parameters
|
||||
if (line.search(/^:|\s+:/) !== -1) {
|
||||
match = line.match(/(.*?)(?:^:|\s+:)(.*)/);
|
||||
middle = match[1].trimRight();
|
||||
trailing = match[2];
|
||||
} else {
|
||||
middle = line;
|
||||
}
|
||||
|
||||
if (middle.length) {
|
||||
message.args = middle.split(/ +/);
|
||||
}
|
||||
|
||||
if (typeof trailing !== 'undefined' && trailing.length) {
|
||||
message.args.push(trailing);
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
function PASS() {
|
||||
this.log('Received PASS command, continue registering...');
|
||||
|
||||
this.registerSteps.push('PASS');
|
||||
}
|
||||
|
||||
function SERVER(parsedMessage) {
|
||||
this.log('Received SERVER command, waiting for first PING...');
|
||||
|
||||
this.serverPrefix = parsedMessage.prefix;
|
||||
|
||||
this.registerSteps.push('SERVER');
|
||||
}
|
||||
|
||||
function PING() {
|
||||
if (!this.isRegistered && this.registerSteps.length === 2) {
|
||||
this.log('Received first PING command, server is registered!');
|
||||
|
||||
this.isRegistered = true;
|
||||
|
||||
this.emit('registered');
|
||||
}
|
||||
|
||||
this.write({
|
||||
prefix: this.config.server.name,
|
||||
command: 'PONG',
|
||||
parameters: [this.config.server.name],
|
||||
});
|
||||
}
|
||||
|
||||
function NICK(parsedMessage) {
|
||||
let command;
|
||||
|
||||
// Check if the message comes from the server,
|
||||
// which means it is a new user
|
||||
if (parsedMessage.prefix === this.serverPrefix) {
|
||||
command = {
|
||||
identifier: 'userRegistered',
|
||||
args: {
|
||||
nick: parsedMessage.args[0],
|
||||
username: parsedMessage.args[2],
|
||||
host: parsedMessage.args[3],
|
||||
name: parsedMessage.args[6],
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// Otherwise, it is a nick change
|
||||
command = {
|
||||
identifier: 'nickChanged',
|
||||
args: {
|
||||
nick: parsedMessage.nick,
|
||||
newNick: parsedMessage.args[0],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
function JOIN(parsedMessage) {
|
||||
const command = {
|
||||
identifier: 'joinedChannel',
|
||||
args: {
|
||||
roomName: parsedMessage.args[0].substring(1),
|
||||
nick: parsedMessage.prefix,
|
||||
},
|
||||
};
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
function PART(parsedMessage) {
|
||||
const command = {
|
||||
identifier: 'leftChannel',
|
||||
args: {
|
||||
roomName: parsedMessage.args[0].substring(1),
|
||||
nick: parsedMessage.prefix,
|
||||
},
|
||||
};
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
function PRIVMSG(parsedMessage) {
|
||||
const command = {
|
||||
identifier: 'sentMessage',
|
||||
args: {
|
||||
nick: parsedMessage.prefix,
|
||||
message: parsedMessage.args[1],
|
||||
},
|
||||
};
|
||||
|
||||
if (parsedMessage.args[0][0] === '#') {
|
||||
command.args.roomName = parsedMessage.args[0].substring(1);
|
||||
} else {
|
||||
command.args.recipientNick = parsedMessage.args[0];
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
function QUIT(parsedMessage) {
|
||||
const command = {
|
||||
identifier: 'disconnected',
|
||||
args: {
|
||||
nick: parsedMessage.prefix,
|
||||
},
|
||||
};
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
export default { PASS, SERVER, PING, NICK, JOIN, PART, PRIVMSG, QUIT };
|
||||
3
apps/meteor/server/bridges/irc/servers/index.ts
Normal file
3
apps/meteor/server/bridges/irc/servers/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import RFC2813 from './RFC2813';
|
||||
|
||||
export { RFC2813 };
|
||||
Reference in New Issue
Block a user