3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-27 21:19:31 +01:00

Yet another documentation refresh (#113)

This commit is contained in:
James Lu 2015-12-26 14:45:28 -08:00
parent 9811df3dfc
commit 11adee9d78
9 changed files with 134 additions and 47 deletions

View File

@ -9,7 +9,7 @@
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>inspircd</strong></big></big></font></td <font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>inspircd</strong></big></big></font></td
><td align=right valign=bottom ><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/gl/pylink/protocols/inspircd.py">/home/gl/pylink/protocols/inspircd.py</a></font></td></tr></table> ><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/gl/pylink/protocols/inspircd.py">/home/gl/pylink/protocols/inspircd.py</a></font></td></tr></table>
<p></p> <p><tt>inspircd.py:&nbsp;InspIRCd&nbsp;2.x&nbsp;protocol&nbsp;module&nbsp;for&nbsp;PyLink.</tt></p>
<p> <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc"> <tr bgcolor="#aa55cc">
@ -111,8 +111,13 @@ This&nbsp;is&nbsp;used&nbsp;to&nbsp;keep&nbsp;track&nbsp;of&nbsp;whether&nbsp;th
internals&nbsp;-&nbsp;a&nbsp;server&nbsp;that&nbsp;fails&nbsp;to&nbsp;reply&nbsp;to&nbsp;our&nbsp;PINGs&nbsp;eventually<br> internals&nbsp;-&nbsp;a&nbsp;server&nbsp;that&nbsp;fails&nbsp;to&nbsp;reply&nbsp;to&nbsp;our&nbsp;PINGs&nbsp;eventually<br>
times&nbsp;out&nbsp;and&nbsp;is&nbsp;disconnected.</tt></dd></dl> times&nbsp;out&nbsp;and&nbsp;is&nbsp;disconnected.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_rsquit"><strong>handle_rsquit</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;the&nbsp;RSQUIT&nbsp;command,&nbsp;which&nbsp;is&nbsp;sent&nbsp;by&nbsp;opers&nbsp;to&nbsp;SQUIT&nbsp;remote<br>
servers.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_server"><strong>handle_server</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;SERVER&nbsp;commands&nbsp;(introduction&nbsp;of&nbsp;servers).</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-handle_server"><strong>handle_server</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;SERVER&nbsp;commands&nbsp;(introduction&nbsp;of&nbsp;servers).</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_svstopic"><strong>handle_svstopic</strong></a> = <a href="#InspIRCdProtocol-handle_ftopic">handle_ftopic</a>(self, numeric, command, args)</dt></dl>
<dl><dt><a name="InspIRCdProtocol-handle_uid"><strong>handle_uid</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;UID&nbsp;commands&nbsp;(user&nbsp;introduction).</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-handle_uid"><strong>handle_uid</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;UID&nbsp;commands&nbsp;(user&nbsp;introduction).</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-inviteClient"><strong>inviteClient</strong></a>(self, numeric, target, channel)</dt><dd><tt>Sends&nbsp;an&nbsp;INVITE&nbsp;from&nbsp;a&nbsp;PyLink&nbsp;client..</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-inviteClient"><strong>inviteClient</strong></a>(self, numeric, target, channel)</dt><dd><tt>Sends&nbsp;an&nbsp;INVITE&nbsp;from&nbsp;a&nbsp;PyLink&nbsp;client..</tt></dd></dl>
@ -151,10 +156,15 @@ Example&nbsp;uses:<br>
Note:&nbsp;No&nbsp;nick&nbsp;collision&nbsp;/&nbsp;valid&nbsp;nickname&nbsp;checks&nbsp;are&nbsp;done&nbsp;here;&nbsp;it&nbsp;is<br> Note:&nbsp;No&nbsp;nick&nbsp;collision&nbsp;/&nbsp;valid&nbsp;nickname&nbsp;checks&nbsp;are&nbsp;done&nbsp;here;&nbsp;it&nbsp;is<br>
up&nbsp;to&nbsp;plugins&nbsp;to&nbsp;make&nbsp;sure&nbsp;they&nbsp;don't&nbsp;introduce&nbsp;anything&nbsp;invalid.</tt></dd></dl> up&nbsp;to&nbsp;plugins&nbsp;to&nbsp;make&nbsp;sure&nbsp;they&nbsp;don't&nbsp;introduce&nbsp;anything&nbsp;invalid.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-spawnServer"><strong>spawnServer</strong></a>(self, name, sid=None, uplink=None, desc=None)</dt><dd><tt>Spawns&nbsp;a&nbsp;server&nbsp;off&nbsp;a&nbsp;PyLink&nbsp;server.&nbsp;desc&nbsp;(server&nbsp;description)<br> <dl><dt><a name="InspIRCdProtocol-spawnServer"><strong>spawnServer</strong></a>(self, name, sid=None, uplink=None, desc=None, endburst_delay=0)</dt><dd><tt>Spawns&nbsp;a&nbsp;server&nbsp;off&nbsp;a&nbsp;PyLink&nbsp;server.&nbsp;desc&nbsp;(server&nbsp;description)<br>
defaults&nbsp;to&nbsp;the&nbsp;one&nbsp;in&nbsp;the&nbsp;config.&nbsp;uplink&nbsp;defaults&nbsp;to&nbsp;the&nbsp;main&nbsp;PyLink<br> defaults&nbsp;to&nbsp;the&nbsp;one&nbsp;in&nbsp;the&nbsp;config.&nbsp;uplink&nbsp;defaults&nbsp;to&nbsp;the&nbsp;main&nbsp;PyLink<br>
server,&nbsp;and&nbsp;sid&nbsp;(the&nbsp;server&nbsp;ID)&nbsp;is&nbsp;automatically&nbsp;generated&nbsp;if&nbsp;not<br> server,&nbsp;and&nbsp;sid&nbsp;(the&nbsp;server&nbsp;ID)&nbsp;is&nbsp;automatically&nbsp;generated&nbsp;if&nbsp;not<br>
given.</tt></dd></dl> given.<br>
&nbsp;<br>
If&nbsp;endburst_delay&nbsp;is&nbsp;set&nbsp;greater&nbsp;than&nbsp;zero,&nbsp;the&nbsp;sending&nbsp;of&nbsp;ENDBURST<br>
will&nbsp;be&nbsp;delayed&nbsp;by&nbsp;the&nbsp;amount&nbsp;given.&nbsp;This&nbsp;can&nbsp;be&nbsp;used&nbsp;to&nbsp;prevent<br>
pseudoserver&nbsp;bursts&nbsp;from&nbsp;triggering&nbsp;IRCd&nbsp;join-flood&nbsp;preventions,<br>
and&nbsp;prevent&nbsp;connections&nbsp;from&nbsp;filling&nbsp;up&nbsp;the&nbsp;snomasks&nbsp;too&nbsp;much.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-squitServer"><strong>squitServer</strong></a>(self, source, target, text='No reason given')</dt><dd><tt>SQUITs&nbsp;a&nbsp;PyLink&nbsp;server.</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-squitServer"><strong>squitServer</strong></a>(self, source, target, text='No reason given')</dt><dd><tt>SQUITs&nbsp;a&nbsp;PyLink&nbsp;server.</tt></dd></dl>
@ -213,6 +223,8 @@ be&nbsp;used&nbsp;for&nbsp;multi-word&nbsp;arguments&nbsp;that&nbsp;last&nbsp;un
<dl><dt><a name="InspIRCdProtocol-removeClient"><strong>removeClient</strong></a>(self, numeric)</dt><dd><tt>Internal&nbsp;function&nbsp;to&nbsp;remove&nbsp;a&nbsp;client&nbsp;from&nbsp;our&nbsp;internal&nbsp;state.</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-removeClient"><strong>removeClient</strong></a>(self, numeric)</dt><dd><tt>Internal&nbsp;function&nbsp;to&nbsp;remove&nbsp;a&nbsp;client&nbsp;from&nbsp;our&nbsp;internal&nbsp;state.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-updateTS"><strong>updateTS</strong></a>(self, channel, their_ts)</dt></dl>
<hr> <hr>
Data descriptors inherited from <a href="classes.html#Protocol">classes.Protocol</a>:<br> Data descriptors inherited from <a href="classes.html#Protocol">classes.Protocol</a>:<br>
<dl><dt><strong>__dict__</strong></dt> <dl><dt><strong>__dict__</strong></dt>
@ -290,8 +302,13 @@ This&nbsp;is&nbsp;used&nbsp;to&nbsp;keep&nbsp;track&nbsp;of&nbsp;whether&nbsp;th
internals&nbsp;-&nbsp;a&nbsp;server&nbsp;that&nbsp;fails&nbsp;to&nbsp;reply&nbsp;to&nbsp;our&nbsp;PINGs&nbsp;eventually<br> internals&nbsp;-&nbsp;a&nbsp;server&nbsp;that&nbsp;fails&nbsp;to&nbsp;reply&nbsp;to&nbsp;our&nbsp;PINGs&nbsp;eventually<br>
times&nbsp;out&nbsp;and&nbsp;is&nbsp;disconnected.</tt></dd></dl> times&nbsp;out&nbsp;and&nbsp;is&nbsp;disconnected.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_rsquit"><strong>handle_rsquit</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;the&nbsp;RSQUIT&nbsp;command,&nbsp;which&nbsp;is&nbsp;sent&nbsp;by&nbsp;opers&nbsp;to&nbsp;SQUIT&nbsp;remote<br>
servers.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_server"><strong>handle_server</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;SERVER&nbsp;commands&nbsp;(introduction&nbsp;of&nbsp;servers).</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-handle_server"><strong>handle_server</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;SERVER&nbsp;commands&nbsp;(introduction&nbsp;of&nbsp;servers).</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-handle_svstopic"><strong>handle_svstopic</strong></a> = <a href="#InspIRCdProtocol-handle_ftopic">handle_ftopic</a>(self, numeric, command, args)</dt></dl>
<dl><dt><a name="InspIRCdProtocol-handle_uid"><strong>handle_uid</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;UID&nbsp;commands&nbsp;(user&nbsp;introduction).</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-handle_uid"><strong>handle_uid</strong></a>(self, numeric, command, args)</dt><dd><tt>Handles&nbsp;incoming&nbsp;UID&nbsp;commands&nbsp;(user&nbsp;introduction).</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-inviteClient"><strong>inviteClient</strong></a>(self, numeric, target, channel)</dt><dd><tt>Sends&nbsp;an&nbsp;INVITE&nbsp;from&nbsp;a&nbsp;PyLink&nbsp;client..</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-inviteClient"><strong>inviteClient</strong></a>(self, numeric, target, channel)</dt><dd><tt>Sends&nbsp;an&nbsp;INVITE&nbsp;from&nbsp;a&nbsp;PyLink&nbsp;client..</tt></dd></dl>
@ -330,10 +347,15 @@ Example&nbsp;uses:<br>
Note:&nbsp;No&nbsp;nick&nbsp;collision&nbsp;/&nbsp;valid&nbsp;nickname&nbsp;checks&nbsp;are&nbsp;done&nbsp;here;&nbsp;it&nbsp;is<br> Note:&nbsp;No&nbsp;nick&nbsp;collision&nbsp;/&nbsp;valid&nbsp;nickname&nbsp;checks&nbsp;are&nbsp;done&nbsp;here;&nbsp;it&nbsp;is<br>
up&nbsp;to&nbsp;plugins&nbsp;to&nbsp;make&nbsp;sure&nbsp;they&nbsp;don't&nbsp;introduce&nbsp;anything&nbsp;invalid.</tt></dd></dl> up&nbsp;to&nbsp;plugins&nbsp;to&nbsp;make&nbsp;sure&nbsp;they&nbsp;don't&nbsp;introduce&nbsp;anything&nbsp;invalid.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-spawnServer"><strong>spawnServer</strong></a>(self, name, sid=None, uplink=None, desc=None)</dt><dd><tt>Spawns&nbsp;a&nbsp;server&nbsp;off&nbsp;a&nbsp;PyLink&nbsp;server.&nbsp;desc&nbsp;(server&nbsp;description)<br> <dl><dt><a name="InspIRCdProtocol-spawnServer"><strong>spawnServer</strong></a>(self, name, sid=None, uplink=None, desc=None, endburst_delay=0)</dt><dd><tt>Spawns&nbsp;a&nbsp;server&nbsp;off&nbsp;a&nbsp;PyLink&nbsp;server.&nbsp;desc&nbsp;(server&nbsp;description)<br>
defaults&nbsp;to&nbsp;the&nbsp;one&nbsp;in&nbsp;the&nbsp;config.&nbsp;uplink&nbsp;defaults&nbsp;to&nbsp;the&nbsp;main&nbsp;PyLink<br> defaults&nbsp;to&nbsp;the&nbsp;one&nbsp;in&nbsp;the&nbsp;config.&nbsp;uplink&nbsp;defaults&nbsp;to&nbsp;the&nbsp;main&nbsp;PyLink<br>
server,&nbsp;and&nbsp;sid&nbsp;(the&nbsp;server&nbsp;ID)&nbsp;is&nbsp;automatically&nbsp;generated&nbsp;if&nbsp;not<br> server,&nbsp;and&nbsp;sid&nbsp;(the&nbsp;server&nbsp;ID)&nbsp;is&nbsp;automatically&nbsp;generated&nbsp;if&nbsp;not<br>
given.</tt></dd></dl> given.<br>
&nbsp;<br>
If&nbsp;endburst_delay&nbsp;is&nbsp;set&nbsp;greater&nbsp;than&nbsp;zero,&nbsp;the&nbsp;sending&nbsp;of&nbsp;ENDBURST<br>
will&nbsp;be&nbsp;delayed&nbsp;by&nbsp;the&nbsp;amount&nbsp;given.&nbsp;This&nbsp;can&nbsp;be&nbsp;used&nbsp;to&nbsp;prevent<br>
pseudoserver&nbsp;bursts&nbsp;from&nbsp;triggering&nbsp;IRCd&nbsp;join-flood&nbsp;preventions,<br>
and&nbsp;prevent&nbsp;connections&nbsp;from&nbsp;filling&nbsp;up&nbsp;the&nbsp;snomasks&nbsp;too&nbsp;much.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-squitServer"><strong>squitServer</strong></a>(self, source, target, text='No reason given')</dt><dd><tt>SQUITs&nbsp;a&nbsp;PyLink&nbsp;server.</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-squitServer"><strong>squitServer</strong></a>(self, source, target, text='No reason given')</dt><dd><tt>SQUITs&nbsp;a&nbsp;PyLink&nbsp;server.</tt></dd></dl>
@ -392,6 +414,8 @@ be&nbsp;used&nbsp;for&nbsp;multi-word&nbsp;arguments&nbsp;that&nbsp;last&nbsp;un
<dl><dt><a name="InspIRCdProtocol-removeClient"><strong>removeClient</strong></a>(self, numeric)</dt><dd><tt>Internal&nbsp;function&nbsp;to&nbsp;remove&nbsp;a&nbsp;client&nbsp;from&nbsp;our&nbsp;internal&nbsp;state.</tt></dd></dl> <dl><dt><a name="InspIRCdProtocol-removeClient"><strong>removeClient</strong></a>(self, numeric)</dt><dd><tt>Internal&nbsp;function&nbsp;to&nbsp;remove&nbsp;a&nbsp;client&nbsp;from&nbsp;our&nbsp;internal&nbsp;state.</tt></dd></dl>
<dl><dt><a name="InspIRCdProtocol-updateTS"><strong>updateTS</strong></a>(self, channel, their_ts)</dt></dl>
<hr> <hr>
Data descriptors inherited from <a href="classes.html#Protocol">classes.Protocol</a>:<br> Data descriptors inherited from <a href="classes.html#Protocol">classes.Protocol</a>:<br>
<dl><dt><strong>__dict__</strong></dt> <dl><dt><strong>__dict__</strong></dt>
@ -407,6 +431,6 @@ Data descriptors inherited from <a href="classes.html#Protocol">classes.Protocol
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr> <font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td> <tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>curdir</strong> = 'protocols'<br> <td width="100%"><strong>curdir</strong> = '../../protocols'<br>
<strong>log</strong> = &lt;logging.RootLogger object&gt;</td></tr></table> <strong>log</strong> = &lt;logging.RootLogger object&gt;</td></tr></table>
</body></html> </body></html>

View File

@ -1,42 +1,45 @@
# PyLink Protocol Module Specification # PyLink Protocol Module Specification
In PyLink, each protocol module is a single file consisting of a protocol class, and a global `Class` attribute that is set equal to it (e.g. `Class = InspIRCdProtocol`). These classes should be based off of either [`classes.Protocol`](https://github.com/GLolol/PyLink/blob/0.4.0-dev/classes.py#L404), a boilerplate class that only defines a few variables, or [`ts6_common.TS6BaseProtocol`](https://github.com/GLolol/PyLink/blob/0.4.0-dev/protocols/ts6_common.py#L10), which includes elements of the TS6 protocol that are shared by both the InspIRCd and TS6 protocols. IRC objects initialize protocol modules by creating an instance of its class, and passing it the IRC object itself. In PyLink, each protocol module is a single file consisting of a protocol class, and a global `Class` attribute that is set equal to it (e.g. `Class = InspIRCdProtocol`). These classes should be based off of either [`classes.Protocol`](https://github.com/GLolol/PyLink/blob/e4fb64aebaf542122c70a8f3a49061386a00b0ca/classes.py#L532), a boilerplate class that only defines a few basic things, or [`ts6_common.TS6BaseProtocol`](https://github.com/GLolol/PyLink/blob/0.5.0-dev/protocols/ts6_common.py), which includes elements of the TS6 protocol that are shared by the InspIRCd, UnrealIRCd, and TS6 protocols. IRC objects load protocol modules by creating an instance of its main class, and sends it commands accordingly.
See also: [inspircd.html](inspircd.html) for an auto-generated specification of the InspIRCd protocol module. See also: [inspircd.html](inspircd.html) for auto-generated documentation the InspIRCd protocol module.
## Tasks ## Tasks
Protocol modules have some *very* ***important*** jobs. If any of these aren't done correctly, you will be left with a very **broken, desynced** services server: Protocol modules have some very important jobs. If any of these aren't done correctly, you will be left with a broken, desynced services server:
1) Handle incoming commands from the uplink IRCd. 1) Handle incoming commands from the uplink IRCd.
2) Return [hook data](hooks-reference.md) for relevant commands, so that plugins can receive data from IRC. 2) Return [hook data](hooks-reference.md) for relevant commands, so that plugins can receive data from IRC.
3) Make sure channel/user states are kept correctly. Joins, quits, parts, kicks, mode changes, nick changes, etc. **must** be handled accurately. 3) Make sure channel/user states are kept correctly. Joins, quits, parts, kicks, mode changes, nick changes, etc. should all be handled accurately.
4) Respond to both pings *and* pongs - the `irc.lastping` attribute **must** be set to the current time whenever a `PONG` is received from the uplink, so PyLink's internals don't [lag out the uplink thinking it isn't responding to our `PING`s](https://github.com/GLolol/PyLink/blob/0.4.0-dev/classes.py#L202-L204). 4) Respond to both pings *and* pongs - the `irc.lastping` attribute **must** be set to the current time whenever a `PONG` is received from the uplink, so PyLink's doesn't [lag out the uplink thinking that it isn't responding to our pings](https://github.com/GLolol/PyLink/blob/e4fb64aebaf542122c70a8f3a49061386a00b0ca/classes.py#L309-L311).
5) Implement a series of camelCase `commandServer/Client` functions - plugins use these for sending outgoing commands. See the `Outbound commands` section below for a list of which ones are needed. 5) Implement a series of camelCase `commandServer/Client` functions - plugins use these for sending outgoing commands. See the `Outbound commands` section below for a list of which ones are needed.
6) Set the threaded event `irc.connected` (via `irc.connected.set()`) when the initial connection + burst phase is complete. This is important for plugins like relay that do state checking, and they will fail to work if this is not set. 6) Set the threading.Event object `irc.connected` (via `irc.connected.set()`) when the protocol negotiation with the uplink is complete. This is important for plugins like relay which must check that links are ready before spawning clients, and they will fail to work if this is not set.
## Core functions ## Core functions
The following functions *must* be implemented by any protocol module within its main class, since they are used by the IRC internals. The following functions *must* be implemented by any protocol module within its main class, since they are used by the IRC object internals.
- **`connect`**`(self)` - Initializes a connection to a server. - **`connect`**`(self)` - Initializes a connection to a server.
- **`handle_events`**`(self, line)` - Handles inbound data (lines of text) from the uplink IRC server. Normally, this will pass commands to other command handlers within the protocol module, dropping commands that are unrecognized (wildcard handling), but it's really up to you how to structure your modules. You will want to be able to parse command arguments properly into a list: many protocols send RFC1459-style commands that can be parsed using the [`self.parseArgs(line)` function within the `Protocol` class](https://github.com/GLolol/PyLink/blob/c77d170765d20b0ac55b945fba4a6257fb15cf43/classes.py#L411). - **`handle_events`**`(self, line)` - Handles inbound data (lines of text) from the uplink IRC server. Normally, this will pass commands to other command handlers within the protocol module, while dropping commands that are unrecognized (wildcard handling). But, it's really up to you how to structure your modules. You will want to be able to parse command arguments properly into a list: many protocols send RFC1459-style commands that can be parsed using the [`Protocol.parseArgs()`](https://github.com/GLolol/PyLink/blob/e4fb64aebaf542122c70a8f3a49061386a00b0ca/classes.py#L539) function.
- All of the outbound commands mentioned in the next section (minus raw numerics) should have their incoming version handled and [hook data](hooks-reference.md) returned.
### Outgoing command functions ### Outgoing command functions
- **`spawnClient`**`(self, nick, ident='null', host='null', realhost=None, modes=set(), server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None)` - Spawns a client on the given IRC connection. Note that no nick collision / valid nickname checks are done here, and it is up to plugins to make sure they don't introduce anything invalid. - **`spawnClient`**`(self, nick, ident='null', host='null', realhost=None, modes=set(), server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None, manipulatable=False)` - Spawns a client on the PyLink server. No nick collision / valid nickname checks are done by protocol modules, as it is up to plugins to make sure they don't introduce anything invalid.
- `modes` is a set of `(mode char, mode arg)` tuples in the form of [`utils.parseModes()` output](using-utils.md#parseModes). - `modes` is a set of `(mode char, mode arg)` tuples in the form of [`utils.parseModes()` output](using-utils.md#parseModes).
- `ident` and `host` default to "null", while `realhost` defaults to the same things as `host` if not defined. - `ident` and `host` default to "null", while `realhost` defaults to the same things as `host` if not defined.
- `realname` defaults to the real name specified in the PyLink config, if not given. `ts` defaults to the current time and `opertype` (the oper type name, if applicable) defaults to the simple text of `IRC Operator`. - `realname` defaults to the real name specified in the PyLink config, if not given.
- `ts` defaults to the current time if not given.
- `opertype` (the oper type name, if applicable) defaults to the simple text of `IRC Operator`.
- The `manipulatable` option toggles whether the client spawned should be considered protected. Currently, all this does is prevent commands from plugins like `bots` from modifying these clients, but future client protections (anti-kill flood, etc.) may also depend on this.
- The `server` option optionally takes a SID of any PyLink server, and spawns the client on the one given. It will default to the root PyLink server.
- **`joinClient`**`(self, client, channel)` - Joins the client UID given to a channel. - **`joinClient`**`(self, client, channel)` - Joins the given client UID given to a channel.
- **`awayClient`**`(self, source, text)` - Sends an AWAY message from a PyLink client. `text` can be an empty string to unset AWAY status. - **`awayClient`**`(self, source, text)` - Sends an AWAY message from a PyLink client. `text` can be an empty string to unset AWAY status.
@ -87,9 +90,10 @@ optional, and defaults to the one we've stored in the channel state if not given
- **`updateClient`**`(self, source, field, text)` - Updates the ident, host, or realname of a PyLink client. `field` should be either "IDENT", "HOST", "GECOS", or - **`updateClient`**`(self, source, field, text)` - Updates the ident, host, or realname of a PyLink client. `field` should be either "IDENT", "HOST", "GECOS", or
"REALNAME". If changing the field given on the IRCd isn't supported, `NotImplementedError` should be raised. "REALNAME". If changing the field given on the IRCd isn't supported, `NotImplementedError` should be raised.
## Variables to note ## Special variables
A protocol module should also set the following variables in their protocol class: A protocol module should also set the following variables in their protocol class:
- `self.casemapping`: set this to `rfc1459` (default) or `ascii` to determine which case mapping should be used. - `self.casemapping`: set this to `rfc1459` (default) or `ascii` to determine which case mapping the IRCd uses.
- `self.hook_map`: map a list of non-standard command names sent by the IRCd to those more commonly used: examples in the [TS6](https://github.com/GLolol/PyLink/blob/0.4.0-dev/protocols/ts6.py#L19) and [InspIRCd](https://github.com/GLolol/PyLink/blob/0.4.0-dev/protocols/inspircd.py#L24) modules. - `self.hook_map`: this is a `dict`, which maps non-standard command names sent by the IRCd to those that PyLink plugins use internally.
- Examples exist in the [UnrealIRCd](https://github.com/GLolol/PyLink/blob/0.5-dev/protocols/unreal.py#L22) and [InspIRCd](https://github.com/GLolol/PyLink/blob/0.5-dev/protocols/inspircd.py#L24) modules.

View File

@ -1 +1 @@
This page is under construction: see [utils.html ](utils.html) for autogenerated documentation for the utils module. See [utils.html](utils.html) for auto-generated documentation for the utils module.

View File

@ -9,7 +9,10 @@
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>utils</strong></big></big></font></td <font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>utils</strong></big></big></font></td
><td align=right valign=bottom ><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/gl/pylink/utils.py">/home/gl/pylink/utils.py</a></font></td></tr></table> ><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/gl/pylink/utils.py">/home/gl/pylink/utils.py</a></font></td></tr></table>
<p></p> <p><tt>utils.py&nbsp;-&nbsp;PyLink&nbsp;utilities&nbsp;module.<br>
&nbsp;<br>
This&nbsp;module&nbsp;contains&nbsp;various&nbsp;utility&nbsp;functions&nbsp;related&nbsp;to&nbsp;IRC&nbsp;and/or&nbsp;the&nbsp;PyLink<br>
framework.</tt></p>
<p> <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc"> <tr bgcolor="#aa55cc">
@ -17,12 +20,14 @@
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> <font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td> <tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="imp.html">imp</a><br> <td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="conf.html">conf</a><br>
<a href="inspect.html">inspect</a><br> <a href="importlib.html">importlib</a><br>
</td><td width="25%" valign=top><a href="inspect.html">inspect</a><br>
<a href="os.html">os</a><br>
</td><td width="25%" valign=top><a href="re.html">re</a><br> </td><td width="25%" valign=top><a href="re.html">re</a><br>
<a href="string.html">string</a><br> <a href="string.html">string</a><br>
</td><td width="25%" valign=top><a href="world.html">world</a><br> </td><td width="25%" valign=top><a href="world.html">world</a><br>
</td><td width="25%" valign=top></td></tr></table></td></tr></table><p> </td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa"> <tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br> <td colspan=3 valign=bottom>&nbsp;<br>
@ -51,7 +56,8 @@
<font color="#000000" face="helvetica, arial"><a name="NotAuthenticatedError">class <strong>NotAuthenticatedError</strong></a>(<a href="builtins.html#Exception">builtins.Exception</a>)</font></td></tr> <font color="#000000" face="helvetica, arial"><a name="NotAuthenticatedError">class <strong>NotAuthenticatedError</strong></a>(<a href="builtins.html#Exception">builtins.Exception</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td> <tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt>#&nbsp;This&nbsp;is&nbsp;separate&nbsp;from&nbsp;classes.py&nbsp;to&nbsp;prevent&nbsp;import&nbsp;loops.<br>&nbsp;</tt></td></tr> <td colspan=2><tt><a href="builtins.html#Exception">Exception</a>&nbsp;raised&nbsp;by&nbsp;<a href="#-checkAuthenticated">checkAuthenticated</a>()&nbsp;when&nbsp;a&nbsp;user&nbsp;fails&nbsp;authentication<br>
requirements.<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td> <tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt> <td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="utils.html#NotAuthenticatedError">NotAuthenticatedError</a></dd> <dd><a href="utils.html#NotAuthenticatedError">NotAuthenticatedError</a></dd>
@ -129,9 +135,9 @@ Example&nbsp;queries:<br>
<td width="100%">Methods defined here:<br> <td width="100%">Methods defined here:<br>
<dl><dt><a name="TS6SIDGenerator-__init__"><strong>__init__</strong></a>(self, irc)</dt></dl> <dl><dt><a name="TS6SIDGenerator-__init__"><strong>__init__</strong></a>(self, irc)</dt></dl>
<dl><dt><a name="TS6SIDGenerator-increment"><strong>increment</strong></a>(self, pos=2)</dt></dl> <dl><dt><a name="TS6SIDGenerator-increment"><strong>increment</strong></a>(self, pos=2)</dt><dd><tt>Increments&nbsp;the&nbsp;SID&nbsp;generator&nbsp;to&nbsp;the&nbsp;next&nbsp;available&nbsp;SID.</tt></dd></dl>
<dl><dt><a name="TS6SIDGenerator-next_sid"><strong>next_sid</strong></a>(self)</dt></dl> <dl><dt><a name="TS6SIDGenerator-next_sid"><strong>next_sid</strong></a>(self)</dt><dd><tt>Returns&nbsp;the&nbsp;next&nbsp;unused&nbsp;TS6&nbsp;SID&nbsp;for&nbsp;the&nbsp;server.</tt></dd></dl>
<hr> <hr>
Data descriptors defined here:<br> Data descriptors defined here:<br>
@ -148,15 +154,15 @@ Data descriptors defined here:<br>
<font color="#000000" face="helvetica, arial"><a name="TS6UIDGenerator">class <strong>TS6UIDGenerator</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr> <font color="#000000" face="helvetica, arial"><a name="TS6UIDGenerator">class <strong>TS6UIDGenerator</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td> <tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt>TS6&nbsp;UID&nbsp;Generator&nbsp;module,&nbsp;adapted&nbsp;from&nbsp;InspIRCd&nbsp;source<br> <td colspan=2><tt>TS6&nbsp;UID&nbsp;Generator&nbsp;module,&nbsp;adapted&nbsp;from&nbsp;InspIRCd&nbsp;source:<br>
https://github.com/inspircd/inspircd/blob/f449c6b296ab/src/server.cpp#L85-L156<br>&nbsp;</tt></td></tr> https://github.com/inspircd/inspircd/blob/f449c6b296ab/src/server.cpp#L85-L156<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td> <tr><td>&nbsp;</td>
<td width="100%">Methods defined here:<br> <td width="100%">Methods defined here:<br>
<dl><dt><a name="TS6UIDGenerator-__init__"><strong>__init__</strong></a>(self, sid)</dt></dl> <dl><dt><a name="TS6UIDGenerator-__init__"><strong>__init__</strong></a>(self, sid)</dt></dl>
<dl><dt><a name="TS6UIDGenerator-increment"><strong>increment</strong></a>(self, pos=5)</dt></dl> <dl><dt><a name="TS6UIDGenerator-increment"><strong>increment</strong></a>(self, pos=5)</dt><dd><tt>Increments&nbsp;the&nbsp;SID&nbsp;generator&nbsp;to&nbsp;the&nbsp;next&nbsp;available&nbsp;SID.</tt></dd></dl>
<dl><dt><a name="TS6UIDGenerator-next_uid"><strong>next_uid</strong></a>(self)</dt></dl> <dl><dt><a name="TS6UIDGenerator-next_uid"><strong>next_uid</strong></a>(self)</dt><dd><tt>Returns&nbsp;the&nbsp;next&nbsp;unused&nbsp;TS6&nbsp;UID&nbsp;for&nbsp;the&nbsp;server.</tt></dd></dl>
<hr> <hr>
Data descriptors defined here:<br> Data descriptors defined here:<br>
@ -173,17 +179,24 @@ Data descriptors defined here:<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr> <font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td> <tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-add_cmd"><strong>add_cmd</strong></a>(func, name=None)</dt></dl> <td width="100%"><dl><dt><a name="-add_cmd"><strong>add_cmd</strong></a>(func, name=None)</dt><dd><tt>Binds&nbsp;an&nbsp;IRC&nbsp;command&nbsp;function&nbsp;to&nbsp;the&nbsp;given&nbsp;command&nbsp;name.</tt></dd></dl>
<dl><dt><a name="-add_hook"><strong>add_hook</strong></a>(func, command)</dt><dd><tt>Add&nbsp;a&nbsp;hook&nbsp;&lt;func&gt;&nbsp;for&nbsp;command&nbsp;&lt;command&gt;.</tt></dd></dl> <dl><dt><a name="-add_hook"><strong>add_hook</strong></a>(func, command)</dt><dd><tt>Binds&nbsp;a&nbsp;hook&nbsp;function&nbsp;to&nbsp;the&nbsp;given&nbsp;command&nbsp;name.</tt></dd></dl>
<dl><dt><a name="-applyModes"><strong>applyModes</strong></a>(irc, target, changedmodes)</dt><dd><tt>Takes&nbsp;a&nbsp;list&nbsp;of&nbsp;parsed&nbsp;IRC&nbsp;modes,&nbsp;and&nbsp;applies&nbsp;them&nbsp;on&nbsp;the&nbsp;given&nbsp;target.<br> <dl><dt><a name="-applyModes"><strong>applyModes</strong></a>(irc, target, changedmodes)</dt><dd><tt>Takes&nbsp;a&nbsp;list&nbsp;of&nbsp;parsed&nbsp;IRC&nbsp;modes,&nbsp;and&nbsp;applies&nbsp;them&nbsp;on&nbsp;the&nbsp;given&nbsp;target.<br>
&nbsp;<br> &nbsp;<br>
The&nbsp;target&nbsp;can&nbsp;be&nbsp;either&nbsp;a&nbsp;channel&nbsp;or&nbsp;a&nbsp;user;&nbsp;this&nbsp;is&nbsp;handled&nbsp;automatically.</tt></dd></dl> The&nbsp;target&nbsp;can&nbsp;be&nbsp;either&nbsp;a&nbsp;channel&nbsp;or&nbsp;a&nbsp;user;&nbsp;this&nbsp;is&nbsp;handled&nbsp;automatically.</tt></dd></dl>
<dl><dt><a name="-checkAuthenticated"><strong>checkAuthenticated</strong></a>(irc, uid, allowAuthed=True, allowOper=True)</dt><dd><tt>Checks&nbsp;whetherthe&nbsp;given&nbsp;user&nbsp;has&nbsp;operator&nbsp;status&nbsp;on&nbsp;PyLink,&nbsp;raising<br> <dl><dt><a name="-checkAuthenticated"><strong>checkAuthenticated</strong></a>(irc, uid, allowAuthed=True, allowOper=True)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;given&nbsp;user&nbsp;has&nbsp;operator&nbsp;status&nbsp;on&nbsp;PyLink,&nbsp;raising<br>
<a href="#NotAuthenticatedError">NotAuthenticatedError</a>&nbsp;and&nbsp;logging&nbsp;the&nbsp;access&nbsp;denial&nbsp;if&nbsp;not.</tt></dd></dl> <a href="#NotAuthenticatedError">NotAuthenticatedError</a>&nbsp;and&nbsp;logging&nbsp;the&nbsp;access&nbsp;denial&nbsp;if&nbsp;not.</tt></dd></dl>
<dl><dt><a name="-clientToServer"><strong>clientToServer</strong></a>(irc, numeric)</dt><dd><tt>Finds&nbsp;the&nbsp;SID&nbsp;of&nbsp;the&nbsp;server&nbsp;a&nbsp;user&nbsp;is&nbsp;on.</tt></dd></dl> <dl><dt><a name="-clientToServer"><strong>clientToServer</strong></a>(irc, numeric)</dt><dd><tt>Finds&nbsp;the&nbsp;SID&nbsp;of&nbsp;the&nbsp;server&nbsp;a&nbsp;user&nbsp;is&nbsp;on.</tt></dd></dl>
<dl><dt><a name="-getHostmask"><strong>getHostmask</strong></a>(irc, user)</dt><dd><tt>Gets&nbsp;the&nbsp;hostmask&nbsp;of&nbsp;the&nbsp;given&nbsp;user,&nbsp;if&nbsp;present.</tt></dd></dl> <dl><dt><a name="-getDatabaseName"><strong>getDatabaseName</strong></a>(dbname)</dt><dd><tt>Returns&nbsp;a&nbsp;database&nbsp;filename&nbsp;with&nbsp;the&nbsp;given&nbsp;base&nbsp;DB&nbsp;name&nbsp;appropriate&nbsp;for&nbsp;the<br>
<dl><dt><a name="-getProtoModule"><strong>getProtoModule</strong></a>(protoname)</dt><dd><tt>Imports&nbsp;and&nbsp;returns&nbsp;the&nbsp;protocol&nbsp;module&nbsp;requested.</tt></dd></dl> current&nbsp;PyLink&nbsp;instance.<br>
<dl><dt><a name="-isChannel"><strong>isChannel</strong></a>(s)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;valid&nbsp;channel&nbsp;name.</tt></dd></dl> &nbsp;<br>
This&nbsp;returns&nbsp;'&lt;dbname&gt;.db'&nbsp;if&nbsp;the&nbsp;running&nbsp;config&nbsp;name&nbsp;is&nbsp;PyLink's&nbsp;default<br>
(config.yml),&nbsp;and&nbsp;'&lt;dbname&gt;-&lt;config&nbsp;name&gt;.db'&nbsp;for&nbsp;anything&nbsp;else.&nbsp;For&nbsp;example,<br>
if&nbsp;this&nbsp;is&nbsp;called&nbsp;from&nbsp;an&nbsp;instance&nbsp;running&nbsp;as&nbsp;'./pylink&nbsp;testing.yml',&nbsp;it<br>
would&nbsp;return&nbsp;'&lt;dbname&gt;-testing.db'.</tt></dd></dl>
<dl><dt><a name="-getHostmask"><strong>getHostmask</strong></a>(irc, user)</dt><dd><tt>Returns&nbsp;the&nbsp;hostmask&nbsp;of&nbsp;the&nbsp;given&nbsp;user,&nbsp;if&nbsp;present.</tt></dd></dl>
<dl><dt><a name="-getProtocolModule"><strong>getProtocolModule</strong></a>(protoname)</dt><dd><tt>Imports&nbsp;and&nbsp;returns&nbsp;the&nbsp;protocol&nbsp;module&nbsp;requested.</tt></dd></dl>
<dl><dt><a name="-isChannel"><strong>isChannel</strong></a>(s)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;valid&nbsp;channel&nbsp;name.</tt></dd></dl>
<dl><dt><a name="-isHostmask"><strong>isHostmask</strong></a>(text)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;given&nbsp;text&nbsp;is&nbsp;a&nbsp;valid&nbsp;hostmask.</tt></dd></dl> <dl><dt><a name="-isHostmask"><strong>isHostmask</strong></a>(text)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;given&nbsp;text&nbsp;is&nbsp;a&nbsp;valid&nbsp;hostmask.</tt></dd></dl>
<dl><dt><a name="-isInternalClient"><strong>isInternalClient</strong></a>(irc, numeric)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;given&nbsp;numeric&nbsp;is&nbsp;a&nbsp;PyLink&nbsp;Client,<br> <dl><dt><a name="-isInternalClient"><strong>isInternalClient</strong></a>(irc, numeric)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;given&nbsp;numeric&nbsp;is&nbsp;a&nbsp;PyLink&nbsp;Client,<br>
returning&nbsp;the&nbsp;SID&nbsp;of&nbsp;the&nbsp;server&nbsp;it's&nbsp;on&nbsp;if&nbsp;so.</tt></dd></dl> returning&nbsp;the&nbsp;SID&nbsp;of&nbsp;the&nbsp;server&nbsp;it's&nbsp;on&nbsp;if&nbsp;so.</tt></dd></dl>
@ -192,18 +205,18 @@ returning&nbsp;the&nbsp;SID&nbsp;of&nbsp;the&nbsp;server&nbsp;it's&nbsp;on&nbsp;
client.&nbsp;Usually,&nbsp;automatically&nbsp;spawned&nbsp;services&nbsp;clients&nbsp;should&nbsp;have&nbsp;this<br> client.&nbsp;Usually,&nbsp;automatically&nbsp;spawned&nbsp;services&nbsp;clients&nbsp;should&nbsp;have&nbsp;this<br>
set&nbsp;True&nbsp;to&nbsp;prevent&nbsp;interactions&nbsp;with&nbsp;opers&nbsp;(like&nbsp;mode&nbsp;changes)&nbsp;from<br> set&nbsp;True&nbsp;to&nbsp;prevent&nbsp;interactions&nbsp;with&nbsp;opers&nbsp;(like&nbsp;mode&nbsp;changes)&nbsp;from<br>
causing&nbsp;desyncs.</tt></dd></dl> causing&nbsp;desyncs.</tt></dd></dl>
<dl><dt><a name="-isNick"><strong>isNick</strong></a>(s, nicklen=None)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;valid&nbsp;nick.</tt></dd></dl> <dl><dt><a name="-isNick"><strong>isNick</strong></a>(s, nicklen=None)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;valid&nbsp;nick.</tt></dd></dl>
<dl><dt><a name="-isOper"><strong>isOper</strong></a>(irc, uid, allowAuthed=True, allowOper=True)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;given&nbsp;user&nbsp;has&nbsp;operator&nbsp;status&nbsp;on&nbsp;PyLink.&nbsp;This&nbsp;can&nbsp;be&nbsp;achieved<br> <dl><dt><a name="-isOper"><strong>isOper</strong></a>(irc, uid, allowAuthed=True, allowOper=True)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;given&nbsp;user&nbsp;has&nbsp;operator&nbsp;status&nbsp;on&nbsp;PyLink.&nbsp;This&nbsp;can&nbsp;be&nbsp;achieved<br>
by&nbsp;either&nbsp;identifying&nbsp;to&nbsp;PyLink&nbsp;as&nbsp;admin&nbsp;(if&nbsp;allowAuthed&nbsp;is&nbsp;True),<br> by&nbsp;either&nbsp;identifying&nbsp;to&nbsp;PyLink&nbsp;as&nbsp;admin&nbsp;(if&nbsp;allowAuthed&nbsp;is&nbsp;True),<br>
or&nbsp;having&nbsp;user&nbsp;mode&nbsp;+o&nbsp;set&nbsp;(if&nbsp;allowOper&nbsp;is&nbsp;True).&nbsp;At&nbsp;least&nbsp;one&nbsp;of<br> or&nbsp;having&nbsp;user&nbsp;mode&nbsp;+o&nbsp;set&nbsp;(if&nbsp;allowOper&nbsp;is&nbsp;True).&nbsp;At&nbsp;least&nbsp;one&nbsp;of<br>
allowAuthed&nbsp;or&nbsp;allowOper&nbsp;must&nbsp;be&nbsp;True&nbsp;for&nbsp;this&nbsp;to&nbsp;give&nbsp;any&nbsp;meaningful<br> allowAuthed&nbsp;or&nbsp;allowOper&nbsp;must&nbsp;be&nbsp;True&nbsp;for&nbsp;this&nbsp;to&nbsp;give&nbsp;any&nbsp;meaningful<br>
results.</tt></dd></dl> results.</tt></dd></dl>
<dl><dt><a name="-isServerName"><strong>isServerName</strong></a>(s)</dt><dd><tt>Checks&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;server&nbsp;name.</tt></dd></dl> <dl><dt><a name="-isServerName"><strong>isServerName</strong></a>(s)</dt><dd><tt>Returns&nbsp;whether&nbsp;the&nbsp;string&nbsp;given&nbsp;is&nbsp;a&nbsp;valid&nbsp;IRC&nbsp;server&nbsp;name.</tt></dd></dl>
<dl><dt><a name="-joinModes"><strong>joinModes</strong></a>(modes)</dt><dd><tt>Takes&nbsp;a&nbsp;list&nbsp;of&nbsp;(mode,&nbsp;arg)&nbsp;tuples&nbsp;in&nbsp;<a href="#-parseModes">parseModes</a>()&nbsp;format,&nbsp;and<br> <dl><dt><a name="-joinModes"><strong>joinModes</strong></a>(modes)</dt><dd><tt>Takes&nbsp;a&nbsp;list&nbsp;of&nbsp;(mode,&nbsp;arg)&nbsp;tuples&nbsp;in&nbsp;<a href="#-parseModes">parseModes</a>()&nbsp;format,&nbsp;and<br>
joins&nbsp;them&nbsp;into&nbsp;a&nbsp;string.<br> joins&nbsp;them&nbsp;into&nbsp;a&nbsp;string.<br>
&nbsp;<br> &nbsp;<br>
See&nbsp;testJoinModes&nbsp;in&nbsp;tests/test_utils.py&nbsp;for&nbsp;some&nbsp;examples.</tt></dd></dl> See&nbsp;testJoinModes&nbsp;in&nbsp;tests/test_utils.py&nbsp;for&nbsp;some&nbsp;examples.</tt></dd></dl>
<dl><dt><a name="-loadModuleFromFolder"><strong>loadModuleFromFolder</strong></a>(name, folder)</dt><dd><tt>Attempts&nbsp;an&nbsp;import&nbsp;of&nbsp;name&nbsp;from&nbsp;a&nbsp;specific&nbsp;folder,&nbsp;returning&nbsp;the&nbsp;resulting&nbsp;module.</tt></dd></dl> <dl><dt><a name="-loadModuleFromFolder"><strong>loadModuleFromFolder</strong></a>(name, folder)</dt><dd><tt>Imports&nbsp;and&nbsp;returns&nbsp;a&nbsp;module,&nbsp;if&nbsp;existing,&nbsp;from&nbsp;a&nbsp;specific&nbsp;folder.</tt></dd></dl>
<dl><dt><a name="-nickToUid"><strong>nickToUid</strong></a>(irc, nick)</dt><dd><tt>Returns&nbsp;the&nbsp;UID&nbsp;of&nbsp;a&nbsp;user&nbsp;named&nbsp;nick,&nbsp;if&nbsp;present.</tt></dd></dl> <dl><dt><a name="-nickToUid"><strong>nickToUid</strong></a>(irc, nick)</dt><dd><tt>Returns&nbsp;the&nbsp;UID&nbsp;of&nbsp;a&nbsp;user&nbsp;named&nbsp;nick,&nbsp;if&nbsp;present.</tt></dd></dl>
<dl><dt><a name="-parseModes"><strong>parseModes</strong></a>(irc, target, args)</dt><dd><tt>Parses&nbsp;a&nbsp;modestring&nbsp;list&nbsp;into&nbsp;a&nbsp;list&nbsp;of&nbsp;(mode,&nbsp;argument)&nbsp;tuples.<br> <dl><dt><a name="-parseModes"><strong>parseModes</strong></a>(irc, target, args)</dt><dd><tt>Parses&nbsp;a&nbsp;modestring&nbsp;list&nbsp;into&nbsp;a&nbsp;list&nbsp;of&nbsp;(mode,&nbsp;argument)&nbsp;tuples.<br>
['+mitl-o',&nbsp;'3',&nbsp;'person']&nbsp;=&gt;&nbsp;[('+m',&nbsp;None),&nbsp;('+i',&nbsp;None),&nbsp;('+t',&nbsp;None),&nbsp;('+l',&nbsp;'3'),&nbsp;('-o',&nbsp;'person')]</tt></dd></dl> ['+mitl-o',&nbsp;'3',&nbsp;'person']&nbsp;=&gt;&nbsp;[('+m',&nbsp;None),&nbsp;('+i',&nbsp;None),&nbsp;('+t',&nbsp;None),&nbsp;('+l',&nbsp;'3'),&nbsp;('-o',&nbsp;'person')]</tt></dd></dl>

View File

@ -1,3 +1,7 @@
"""
inspircd.py: InspIRCd 2.x protocol module for PyLink.
"""
import time import time
import sys import sys
import os import os

View File

@ -1,3 +1,7 @@
"""
ts6.py: PyLink protocol module for TS6-based IRCds (charybdis, elemental-ircd).
"""
import time import time
import sys import sys
import os import os

View File

@ -1,8 +1,14 @@
"""
ts6_common.py: Common base protocol class with functions shared by the UnrealIRCd, InspIRCd, and TS6 protocol modules.
"""
import sys import sys
import os import os
# Import hacks to access utils and classes...
curdir = os.path.dirname(__file__) curdir = os.path.dirname(__file__)
sys.path += [curdir, os.path.dirname(curdir)] sys.path += [curdir, os.path.dirname(curdir)]
import utils import utils
from log import log from log import log
from classes import * from classes import *

View File

@ -1,3 +1,7 @@
"""
unreal.py: UnrealIRCd 4.0 protocol module for PyLink.
"""
import time import time
import sys import sys
import os import os
@ -5,8 +9,10 @@ import codecs
import socket import socket
import re import re
# Import hacks to access utils and classes...
curdir = os.path.dirname(__file__) curdir = os.path.dirname(__file__)
sys.path += [curdir, os.path.dirname(curdir)] sys.path += [curdir, os.path.dirname(curdir)]
import utils import utils
from log import log from log import log
from classes import * from classes import *

View File

@ -16,10 +16,15 @@ import world
import conf import conf
class NotAuthenticatedError(Exception): class NotAuthenticatedError(Exception):
"""
Exception raised by checkAuthenticated() when a user fails authentication
requirements.
"""
pass pass
class TS6UIDGenerator(): class TS6UIDGenerator():
"""TS6 UID Generator module, adapted from InspIRCd source """
TS6 UID Generator module, adapted from InspIRCd source:
https://github.com/inspircd/inspircd/blob/f449c6b296ab/src/server.cpp#L85-L156 https://github.com/inspircd/inspircd/blob/f449c6b296ab/src/server.cpp#L85-L156
""" """
@ -32,6 +37,9 @@ class TS6UIDGenerator():
self.sid = sid self.sid = sid
def increment(self, pos=5): def increment(self, pos=5):
"""
Increments the SID generator to the next available SID.
"""
# If we're at the last character in the list of allowed ones, reset # If we're at the last character in the list of allowed ones, reset
# and increment the next level above. # and increment the next level above.
if self.uidchars[pos] == self.allowedchars[-1]: if self.uidchars[pos] == self.allowedchars[-1]:
@ -44,6 +52,9 @@ class TS6UIDGenerator():
self.uidchars[pos] = self.allowedchars[idx+1] self.uidchars[pos] = self.allowedchars[idx+1]
def next_uid(self): def next_uid(self):
"""
Returns the next unused TS6 UID for the server.
"""
uid = self.sid + ''.join(self.uidchars) uid = self.sid + ''.join(self.uidchars)
self.increment() self.increment()
return uid return uid
@ -71,13 +82,18 @@ class TS6SIDGenerator():
self.query = query = list(irc.serverdata["sidrange"]) self.query = query = list(irc.serverdata["sidrange"])
except KeyError: except KeyError:
raise RuntimeError('(%s) "sidrange" is missing from your server configuration block!' % irc.name) raise RuntimeError('(%s) "sidrange" is missing from your server configuration block!' % irc.name)
self.iters = self.query.copy() self.iters = self.query.copy()
self.output = self.query.copy() self.output = self.query.copy()
self.allowedchars = {} self.allowedchars = {}
qlen = len(query) qlen = len(query)
assert qlen == 3, 'Incorrect length for a SID (must be 3, got %s)' % qlen assert qlen == 3, 'Incorrect length for a SID (must be 3, got %s)' % qlen
assert '#' in query, "Must be at least one wildcard (#) in query" assert '#' in query, "Must be at least one wildcard (#) in query"
for idx, char in enumerate(query): for idx, char in enumerate(query):
# Iterate over each character in the query string we got, along
# with its index in the string.
assert char in (string.digits+string.ascii_uppercase+"#"), \ assert char in (string.digits+string.ascii_uppercase+"#"), \
"Invalid character %r found." % char "Invalid character %r found." % char
if char == '#': if char == '#':
@ -91,6 +107,9 @@ class TS6SIDGenerator():
def increment(self, pos=2): def increment(self, pos=2):
"""
Increments the SID generator to the next available SID.
"""
if pos < 0: if pos < 0:
# Oh no, we've wrapped back to the start! # Oh no, we've wrapped back to the start!
raise RuntimeError('No more available SIDs!') raise RuntimeError('No more available SIDs!')
@ -106,7 +125,11 @@ class TS6SIDGenerator():
self.increment(pos-1) self.increment(pos-1)
def next_sid(self): def next_sid(self):
"""
Returns the next unused TS6 SID for the server.
"""
while ''.join(self.output) in self.irc.servers: while ''.join(self.output) in self.irc.servers:
# Increment until the SID we have doesn't already exist.
self.increment() self.increment()
sid = ''.join(self.output) sid = ''.join(self.output)
return sid return sid
@ -474,7 +497,7 @@ def isOper(irc, uid, allowAuthed=True, allowOper=True):
def checkAuthenticated(irc, uid, allowAuthed=True, allowOper=True): def checkAuthenticated(irc, uid, allowAuthed=True, allowOper=True):
""" """
Checks whetherthe given user has operator status on PyLink, raising Checks whether the given user has operator status on PyLink, raising
NotAuthenticatedError and logging the access denial if not. NotAuthenticatedError and logging the access denial if not.
""" """
lastfunc = inspect.stack()[1][3] lastfunc = inspect.stack()[1][3]
@ -494,7 +517,7 @@ def isManipulatableClient(irc, uid):
return isInternalClient(irc, uid) and irc.users[uid].manipulatable return isInternalClient(irc, uid) and irc.users[uid].manipulatable
def getHostmask(irc, user): def getHostmask(irc, user):
"""Gets the hostmask of the given user, if present.""" """Returns the hostmask of the given user, if present."""
userobj = irc.users.get(user) userobj = irc.users.get(user)
if userobj is None: if userobj is None:
return '<user object not found>' return '<user object not found>'
@ -513,14 +536,17 @@ def getHostmask(irc, user):
return '%s!%s@%s' % (nick, ident, host) return '%s!%s@%s' % (nick, ident, host)
def loadModuleFromFolder(name, folder): def loadModuleFromFolder(name, folder):
"""Attempts and returns an import of the given module name from a specific """
folder.""" Imports and returns a module, if existing, from a specific folder.
"""
fullpath = os.path.join(folder, '%s.py' % name) fullpath = os.path.join(folder, '%s.py' % name)
m = importlib.machinery.SourceFileLoader(name, fullpath).load_module() m = importlib.machinery.SourceFileLoader(name, fullpath).load_module()
return m return m
def getProtocolModule(protoname): def getProtocolModule(protoname):
"""Imports and returns the protocol module requested.""" """
Imports and returns the protocol module requested.
"""
return loadModuleFromFolder(protoname, world.protocols_folder) return loadModuleFromFolder(protoname, world.protocols_folder)
def getDatabaseName(dbname): def getDatabaseName(dbname):