{"id":48600853,"url":"https://github.com/neandrake/spirc","last_synced_at":"2026-04-08T22:02:37.166Z","repository":{"id":2790705,"uuid":"3790720","full_name":"neandrake/spirc","owner":"neandrake","description":"IRC Library","archived":false,"fork":false,"pushed_at":"2017-11-14T22:55:48.000Z","size":81,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-09T08:39:59.317Z","etag":null,"topics":["irc-library"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neandrake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-03-21T19:54:15.000Z","updated_at":"2019-07-15T12:09:42.000Z","dependencies_parsed_at":"2022-08-23T20:10:23.979Z","dependency_job_id":null,"html_url":"https://github.com/neandrake/spirc","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/neandrake/spirc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neandrake%2Fspirc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neandrake%2Fspirc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neandrake%2Fspirc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neandrake%2Fspirc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neandrake","download_url":"https://codeload.github.com/neandrake/spirc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neandrake%2Fspirc/sbom","scorecard":{"id":677981,"data":{"date":"2025-08-11","repo":{"name":"github.com/neandrake/spirc","commit":"7b827622f68db8d7523322761c535e7e29048f9d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T22:09:32.018Z","repository_id":2790705,"created_at":"2025-08-21T22:09:32.018Z","updated_at":"2025-08-21T22:09:32.018Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31575755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["irc-library"],"created_at":"2026-04-08T22:02:20.942Z","updated_at":"2026-04-08T22:02:37.154Z","avatar_url":"https://github.com/neandrake.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"spirc\n=====\nIRC Library\n\nThis library is intended to be the building blocks for IRC utilities requiring little or no dependencies. It is developed as a personal project to learn the IRC protocol as well as JavaScript library development.\n\n### Contents\n- [News](#news)\n- [Status](#status)\n- [Roadmap](#roadmap)\n- [Install](#install)\n\t- [NPM](#npm)\n\t- [Source](#source)\n- [API](#api)\n\t- [Overview](#overview)\n\t- [Client](#client)\n\t- [Targets](#targets)\n\t- [Events](#events)\n\t- [Examples](#examples)\n\t- [Client Options](#client-options)\n- [Resources](#resources)\n\n\n#### News\nVersion 0.1.5 released October 31st, 2017. See [release notes](https://github.com/neandrake/spirc/releases/tag/v0.1.5) for details.\n\nPull Requests are welcome, as well as discussions using Issues.\n\n#### Status\nOnly the Client API is only functional.\n- [x] Connect/Disconnect to server\n- [x] Register User\n- [x] Alternate nick registration when preferred is taken\n- [x] Join/Part Channels\n- [x] Send/Receive messages (PRIVMSG on channels or pm)\n- [x] Auto-PONG when PING is received from server\n- [x] Pipe stream data over PRIVMSG to target. Currently requires stream to be text and `\\r\\n` delimited, and does not limit the PRIVMSG length.\n- [x] Outbound throttling, to avoid spamming, defaults to 4 outbound/sec\n\nConnecting via SSL had been working, but an update to node-js has currently broken this functionality, as it would require accepting self-signed certificates from user. Have looked into workarounds but need to research SSL certificate management for IRC nodes.\n\n### Roadmap\n- [ ] Promise-ish - Some manner of promises would be useful not only for basic async i/o handling, but at the IRC message level of request/response.\n- [ ] Consistent and Simplified API - Have been working on this some with project layout and API naming and such, once the project expands this will be easier to identify and document. ex: Outbound requests must always be directed at a Target which is currently all managed through convenience methods.\n- [ ] Additional IRC Support - Proper state tracking of IRC specifics, such as modes, targets in a channel, etc. Also any extended info from IRC RFCs.\n- [ ] JSDoc Documentation/Comments - Would like to supply some form of publishable documentation that is inlined in the code, for API exposure.\n- [ ] CTCP - XDCC, etc.\n- [ ] IRC Server API - Large project not in the near future.\n\n### Install\n#### NPM\nIn your project directory, install spirc\n```\n$ npm install spirc\n```\nThen in your project source, require the spirc library.\n```javascript\nvar ircclient = require('spirc').Client;\n```\nVersions will be marked as release on GitHub, then published to npm.\n\n#### Source\nIf you prefer to not use npm, you can use spirc by cloning the repository.\n```\n$ git clone https://github.com/neandrake/spirc.git\n```\nThen in your project, to require the library you should use a relative path to `main.js`. See `examples/example1.js` for reference.\n```javascript\nvar irclient = require('../lib/main.js').Client;\n```\nIf you are using spirc for a project in this manner, using git submodules is recommended.\n\n### API\n#### Overview\n- After connecting successfully to a server, a `register` event is emitted on the client, which is the appropriate time to auto-join channels.\n- Messages received are `Inbound` objects.\n- Messages sent are `Outbound` objects.\n- Messages are emitted from `Target`s, which can either be `Host`s, `Channel`s, or `User`s.\n- IRC Message events emitted from targets are directly named from the message command, but are prefixed with ':' character in order to differentiate from other events emitted from the target. Examples are ':PRIVMSG' or ':433'.\n\n#### Client\nThe `Client` object contains a method `send` for sending an `Outbound` request, which is used by all the convenience methods.\n```javascript\nvar req = require('spirc').Requests;\nclient.send(new req.Names('#channel'));\n```\n\nThe `Client` object is what is used to manage a connection to a single server, emitting connection-related events.\n- `send` - sends an `Outbound` message, or more accurately queues an outbound message.\n- `connect` - connects to the server specified in the options set on client - a `connected` event is emitted once this has completed.\n- `disconnect` - disconnect from server, sending PARTs to all known channels, followed by a QUIT to the server - the socket is then closed and a `disconnected` event is emitted.\n- `registered` event - fired when it's been determined that the client's user credentials were successfully registered - by default the client will attempt to register with the provided user credentials after a connection has been made.\n- `error` event - fired when a connection error occurs or if an IRC inbound message indicates an error.\n\nThe `Client` object also provides methods for registering listeners for when any inbound event is received, regardless of target. These events are fired before the specified target has its events fired.\n- `onInboundEvent` - receives inbounds for a specific event\n- `onceInboundEvent` - receives inbounds for a specific event, but is only fired once\n\nThe client's socket reading, as well as the target's `pipe` method use `TokenReader` object. This is a simple object that emits `token` events with data based on a given delimiter. The default delimiter is the newline character.\n\n#### Targets\n__Target__ defines several convenience methods\n- `say` - sends a PRIVMSG command to the target.\n- `onSaid` - register a listener for PRIVMSG messages directed at this target.\n- `onInbound` - register a listener for all inbound messages directed at this target.\n- `pipe` - pipe data from a stream to the target via PRIVMSG commands.\n- IRC Message Events - targets will emit events for IRC messages directed at them. These events will contain the inbound message as the only parameter. The event name is the IRC command prefixed by a colon - ex: `.on(':PRIVMSG', cb)`\n\n__Channel__ is a Target and also contains these convenience methods\n- `join` - join the channel\n- `part` - leave the channel, can provide leaving message.\n\n__Host__ is a Target and also contains these convenience methods\n- `quit` - disconnect from the irc server, can provide leaving message.\n- `onPing` - convenience for registering a listener whena PING message is received\n\n#### Events\nWhen an inbound message is received these events are fired:\n- If the inbound message could not properly be parsed as an IRC message, an `error` event is fired.\n- The `_allTargets` emits an `inbound` event with the inbound message.\n- The target the message is directed to emits an `inbound` event with the inbound message.\n- The `_allTargets` emits an event named after the parsed command, with the inbound message.\n- The target the message is directed to emits an event named after the parsed command, with the inbound message.\n\nWhen an outbound message is sent, the client emits an `outbound` event with the outbound message.\n\n#### Examples\nSimple example of a bot that connects to a server, joins a channel, then echoes all messages received from the channel or PM back to the channel.\n```javascript\nvar Client = require('spirc').Client;\nvar client = new Client({\n    nick: 'spircbot',\n    altnicks: ['spircbot_'],\n    server: 'irc.freenode.net'\n});\n\nvar chan = client.getTarget('#spirc');\nvar user = client.user;\n\n// this method is added as a listener to targets,\n// and will be invoked with a Response when PRIVMSG events are emitted\nfunction respond(response) {\n    // the sender name and message are located in the response object, which\n    // may differ depending on the response type, since it's PM, these are always the case\n    // get a target object from client keyed on the sender's name\n    var sayer = client.getTarget(response.prefix.target);\n    var message = response.trailing;\n\n    // echo back to the channel\n    chan.say('I just received a message from: ' + sayer.name);\n};\n\n// graceful shutdown on ctrl+c\nprocess.on('SIGINT', function onInterrupt() {\n    client.disconnect('time to go');\n});\n\n// after conecting + registering user with server, join a channel\nclient.on('registered', function onClientRegistered() {\n    chan.join();\n});\n\n// register the respond callback\nuser.onSaid(respond);\nchan.onSaid(respond);\n\n// start connection to server\nclient.connect();\n```\n\n#### Client Options\n`Client` constructor parses the object parameter as a `ClientOpts`, and can specify:\n```javascript\n{\n\t// traditional setup\n\t\"server\": 'irc.freenode.net',\n\t\"port\": 6667,\n\t\"nick\": null,\n\t\"pass\": null,\n\t\"altnicks\": [],\n\n\t// additional details \n\t\"username\": 'username',\n\t\"hostname\": '127.0.0.1',\n\t\"servername\": '127.0.0.1',\n\t\"realname\": 'realname',\n\n\t// use SSL connection\n\t\"secure\": false,\n\n\t// some additional options\n\t\"autoPong\": true,\t\t\t\t// most servers will kick if PINGs are not replied to\n\t\"autoAltNick\": true,\t\t\t// automatically loop through registering the nicks under the 'altnicks' option\n\t\"autoRegister\": true,\t\t\t// auto-register the user after client connects to server\n\t\"sendsPerSec\": 4\t\t\t\t// throttling commands sent per sec\n\t\"log\": new Log(process.stdout),\t// log for output, this will like be removed altogether\n}\n```\n\n### Resources\n- [RFC 1459: Internet Relay Chat Protocol (pdf)](http://tools.ietf.org/pdf/rfc1459.pdf)\n- [RFC 2810: Internet Relay Chat: Architecture (pdf)](http://tools.ietf.org/pdf/rfc2810.pdf)\n- [RFC 2811: Internet Relay Chat: Channel Management (pdf)](http://tools.ietf.org/pdf/rfc2811.pdf) \n- [RFC 2812: Internet Relay Chat: Client Protocol (pdf)](http://tools.ietf.org/pdf/rfc2812.pdf)\n- [RFC 2813: Internet Relay Chat: Server Protocol (pdf)](http://tools.ietf.org/pdf/rfc2813.pdf)\n- [CTCP Specification (html)](http://www.irchelp.org/irchelp/rfc/ctcpspec.html)\n- [IRCv3 Working Group (html)](http://ircv3.atheme.org/)\n- [EFnet Docs: Protocols (html)](http://www.efnet.org/?module=docs)\n- [irc.org Techie Docs (html)](http://www.irc.org/techie.html)\n- [irclib: Python IRC Library (bitbucket)](https://bitbucket.org/jaraco/irc/src)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneandrake%2Fspirc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneandrake%2Fspirc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneandrake%2Fspirc/lists"}