@@ 1,15 @@
+This repository is dedicated entirely to the public domain. The creator
+waives all intellectual property rights to the work as much as is
+possible in the given jurisdiction.
+
+In other words, do whatever.
+
+THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+and these are the docs, so if you hurt yourself that's pretty funny tbh
@@ 1,264 @@
+# irc.tcl
+
+The core protocol library. `irc.tcl` *exclusively* handles the raw
+stream protocol and event dispatch. All other responsibilities are
+out-of-scope for it.
+
+It exposes the **`irc`** namespace, which contains the logic for
+message-parsing, message validation, channel management, event
+dispatch, and various utilities listed below.
+
+
+## Getting a channel
+
+`irc.tcl` provides 2 ways to connect to an IRC server.
+
+
+### `irc::connect `*`hostname port ?usetls?`*
+
+Connects to `hostname:port`, and sets up all the necessary state. If
+usetls is set to true, the **`tls`** module will be used to connect,
+instead of the builtin **`socket`** command. If unset, **`socket`**
+will be used.
+
+
+### `irc::enroll `*`chan ?meta?`*
+
+Sets up the internal state necessary for `chan` to be
+used as an IRC socket. It is called internally by **`irc::connect`**. This
+command is exposed for the use-case where an IRC channel might have a
+more bespoke acquisition process than a simple socket connection.
+
+
+## Listening to it
+
+`irc.tcl` provides an event dispatch system, via a **`fileevent`**
+script registered on the IRC channel. Events are dispatched by matching
+their [patterns](#message-pattern-lists) against incoming messages.
+
+
+### `irc::listen `*`subcommand chan`*
+
+Enable or disable the **`fileevent`** script for the dispatch system.
+
+#### `irc::listen` `on `*`chan`*
+
+Apply the **`fileevent`** wrapper to `chan`. Returns the previous
+**`fileevent`** wrapper.
+
+#### `irc::listen` `off `*`chan`*
+
+Remove the **`fileevent`** wrapper from `chan`. Errors if it is not the
+irc wrapper.
+
+
+### `irc::listener `*`subcommand chan ?args ...?`*
+
+Configure listener-type event handlers.
+
+Listener-type handlers are scripts, executed in a sub-interpreter.
+The script is executed as part of event handling, and is expected to
+return to the main interpreter via **`after`** periodically. For
+application responsiveness and stability reasons, it is expected that
+listener scripts will not take longer than 100ms to execute, though
+this is not enforced. If consistent long-running computations are
+required, consider using **`irc::extern`**.
+
+`listener`-type scripts are spawned with the variable `chan` set to the
+channel they recieve dispatches over. This will be a **`dict`** with
+contents as described in
+[Event Dispatch Contents](#event-dispatch-contents).
+They are given access to the
+[Dispatch-aliased IRC commands](dispatch-aliased-irc-commands).
+
+When a listener is removed, it will recieve a message of just `end`. It
+should perform necessary cleanup quickly, and return, as the
+application is likely exiting, and it may not be re-executed if it
+yields.
+
+#### `irc::listener add `*`chan patlist script`*
+
+Registers `script` as a listener-type handler on `chan`, matching
+`patlist` as [described below](#message-pattern-lists). Returns an id
+that can be passed to **`irc::listener remove`** or **`irc::patlist`**.
+
+#### `irc::listener remove `*`chan id`*
+
+Unregisters the listener identified by `id` from `chan`.
+
+
+### `irc::handler `*`subcommand chan ?args ...?`*
+
+Configure handler-type event handlers.
+
+Handler-type event handlers execute a script everytime a message is
+matched. For application responsiveness and stability reasons, it is
+expected that handler scripts will not take longer than 100ms to
+execute, though this is not enforced.
+
+Handlers can be created with or without a stored interpreter. If
+created without, they will be spawned with a new interpreter for each
+message, and clean scope.
+
+`handler`-type scripts are spawned with the variable `dispatch` set as
+described in
+[Event Dispatch Contents](#event-dispatch-contents).
+They are given access to the
+[Dispatch-aliased `irc` commands](dispatch-aliased-codeirccode-commands).
+
+When a handler is removed, if it has a stored interpreter, it will be
+deleted. Applications with persistent state should take care to store
+it to disk after each command, or use one of the other dispatch types.
+
+#### `irc::handler add `*`chan patlist script ?interp?`*
+
+Registers `script` as a handler-type handler on `chan`, matching
+`patlist` as [described below](#message-pattern-lists). Returns an id
+that can be passed to **`irc::extern remove`** or **`irc::patlist`**.
+
+If `interp` is supplied, `script` will be added as a stored-interpreter
+handler, with `interp` as the stored-interpreter. The same alias setup
+performed on internally created interpreters will be performed, once, on
+the supplied interpreter, and `dispatch` will be set just before
+executing `script`.
+
+#### `irc::extern remove `*`chan id`*
+
+Unregisters the extern handler identified by `id` from `chan`.
+
+
+### `irc::extern `*`subcommand chan ?args ...?`*
+
+Configure extern-type event handlers.
+
+Extern-type event handlers are backed by a pair of channels. One is for
+message dispatch, one is for message replying. Dispatch comes in pairs
+of lines, the first being the source channel and the second being the
+raw IRC message. Replies are just single IRC messages. Due to this
+asymmetry, it is OK to reuse a dispatch channel for multiple `extern`
+handlers, but not OK to reuse a reply channel. You will need to make
+use of FIFOs or pipes for I/O multiplexing.
+
+When an extern-type handler is removed, the channel id and `end` will
+be written to it. The dispatch pipe is never closed by `irc.tcl`. The
+reply pipe will be closed immediately. Ensure code that uses multiple
+handlers accounts for this.
+
+#### `irc::handler add `*`chan patlist ochan ichan`*
+
+Registers `ochan` and `ichan` as the dispatch and reply pipes of a
+extern-type handler on `chan`, matching `patlist` as
+[described below](#message-pattern-lists). Returns an id that can
+be passed to **`irc::extern remove`** or **`irc::patlist`**.
+
+#### `irc::extern remove `*`chan id`*
+
+Unregisters the extern handler identified by `id` from `chan`.
+
+
+### `irc::patlist `*`chan id ?patlist?`*
+
+Get or set the [message pattern list](message-pattern-list) for handler
+`id` on `chan`. If `patlist` is supplied, it will override the current
+one and return `patlist`, otherwise it will return the current pattern
+list.
+
+
+### Message Pattern Lists
+
+Message pattern lists are lists of lists of **`string match`**
+patterns. Messages are matched on the command and the first N-1 params,
+where N is the length of the message pattern. If the first N segments
+all match, the match succeeds. If a message is shorter than a pattern,
+the match fails. If any of the message patterns in the message pattern
+list for a handler match, the handler is called.
+
+#### Message Pattern List Examples:
+
+```tcl
+# pattern:
+*
+
+# messages:
+PRIVMSG #general :what's up gamers
+# matches
+PRIVMSG #amehut :bot, do something
+# matches
+PRIVMSG #bot :do something
+# matches
+PING foo
+# matches
+
+
+# pattern:
+{{}}
+
+# messages:
+PRIVMSG #general :what's up gamers
+# doesn't match
+PRIVMSG #amehut :bot, do something
+# doesn't match
+PRIVMSG #bot :do something
+# doesn't match
+PING foo
+# doesn't match
+
+
+# pattern:
+{{PRIVMSG * {bot, *}} {PRIVMSG #bot}}
+
+# messages:
+PRIVMSG #general :what's up gamers
+# doesn't match
+PRIVMSG #amehut :bot, do something
+# matches
+PRIVMSG #bot :do something
+# matches
+PING foo
+# doesn't match
+
+
+# pattern:
+PING
+
+# messages:
+PRIVMSG #general :what's up gamers
+# doesn't match
+PRIVMSG #amehut :bot, do something
+# doesn't match
+PRIVMSG #bot :do something
+# doesn't match
+PING foo
+# matches
+```
+
+### Event Dispatch Contents
+
+The event dispatch dictionary contains the following properties:
+
+- `rawmsg`: the raw IRC message
+- `chan`: the source channel
+- `tags`: the tags portion of the message
+- `src`: the source portion of the message
+- `srctype`: the type of message source, either `servername` or `user`
+- `srcparts`: the `srcparts` dict, returned from **`irc::src parse`**
+- `cmd`: the command of the message
+- `params`: the params of the message
+- `meta`: channel metadata, such as server hostname
+
+### Dispatch-aliased `irc` Comands
+
+In `listener` and `handlers`, the following commands are aliased:
+
+- `irc::esc`
+- `irc::extern`
+- `irc::handler`
+- `irc::is`
+- `irc::listener`
+- `irc::msg`
+- `irc::patlist`
+- `irc::src`
+- `irc::tags`
+- `irc::unesc`
+
+Additionally, the relevant channel is `share`d.