]>
Commit | Line | Data |
---|---|---|
1 | # Erebus IRC bot - Author: Erebus Team | |
2 | # vim: fileencoding=utf-8 | |
3 | # Configurable sockets module. DO NOT USE without understanding the risks | |
4 | # This file is released into the public domain; see http://unlicense.org/ | |
5 | ||
6 | # Note: this module doesn't do any kind of authentication, so anyone who can connect to the bound port can spam you. | |
7 | ||
8 | """ | |
9 | To use - add in bot.config something like: | |
10 | ||
11 | [sockets] | |
12 | 127.0.0.1:1337 = #example | |
13 | ||
14 | The left side is the address to listen on and the right side is the channel to send to. | |
15 | The exmaple will send incoming lines/packets on localhost, port 1337 to channel #example | |
16 | ||
17 | The full syntax for the address is: | |
18 | [unix:]</path/to/socket> | |
19 | [udp|tcp:][<ip>:]<port> | |
20 | ||
21 | ||
22 | Address examples: | |
23 | ||
24 | Unix domain socket: /path | |
25 | Unix domain socket: unix:/path | |
26 | TCP socket (all interfaces): 1337 | |
27 | TCP socket (one interface): 127.0.0.1:1337 | |
28 | UDP socket (all interfaces): udp:1337 | |
29 | UDP socket (one interface): udp:127.0.0.1:1337 | |
30 | """ | |
31 | ||
32 | # module info | |
33 | modinfo = { | |
34 | 'author': 'Erebus Team', | |
35 | 'license': 'public domain', | |
36 | 'compatible': [0], | |
37 | 'depends': [], | |
38 | 'softdeps': [], | |
39 | } | |
40 | ||
41 | # preamble | |
42 | import modlib | |
43 | lib = modlib.modlib(__name__) | |
44 | def modstart(parent, *args, **kwargs): | |
45 | gotParent(parent) | |
46 | return lib.modstart(parent, *args, **kwargs) | |
47 | modstop = lib.modstop | |
48 | ||
49 | # module code | |
50 | class BasicServer(lib.Socketlike): | |
51 | def __init__(self, sock, data): | |
52 | super(BasicServer, self).__init__(sock, data) | |
53 | # NB neither directly referencing `channel`, nor trying to pass it through a default-arg-to-a-lambda like the python docs suggest, works here. | |
54 | # Yay python. At least passing it via bind works. | |
55 | self.chan = data | |
56 | ||
57 | # default getdata() and send() methods are defined by lib.Socketlike | |
58 | # suitable for line-based protocols like IRC | |
59 | ||
60 | def parse(self, line): | |
61 | try: | |
62 | bot = lib.parent.channel(self.chan).bot | |
63 | except AttributeError: # <class 'AttributeError'> 'NoneType' object has no attribute 'bot' | |
64 | bot = lib.parent.randbot() | |
65 | maxlen = bot.maxmsglen() - len("PRIVMSG :") - len(self.chan) | |
66 | while len(line) > maxlen: | |
67 | cutat = line.rfind(' ', 0, maxlen) | |
68 | if cutat == -1: | |
69 | cutat = maxlen | |
70 | bot.msg(self.chan, line[0:cutat]) | |
71 | line = line[cutat:].strip() | |
72 | bot.msg(self.chan, line) | |
73 | ||
74 | # default __str__() and __repr__() methods are defined by lib.Socketlike | |
75 | ||
76 | def gotParent(parent): | |
77 | for bindto, channel in parent.cfg.items('sockets'): | |
78 | lib.bind(bindto, data=channel)(BasicServer) |