7
7
8
8
from . import async
9
9
from . import connection
10
+ from . import models
10
11
from . import protocol
11
12
12
13
__all__ = [ 'Error' , 'AlreadyInChannel' , 'NotInChannel' , 'BasicClient' ]
@@ -29,7 +30,20 @@ def __init__(self, channel):
29
30
self .channel = channel
30
31
31
32
32
- class BasicClient :
33
+ class ClientMeta (type ):
34
+ @staticmethod
35
+ def _compose (name , cls , bases ):
36
+ return type (name , tuple ({base for base in bases if not issubclass (cls , base )}) + (cls ,), {})
37
+
38
+ def __new__ (cls , name , bases , attrs ):
39
+ if "User" in attrs :
40
+ attrs ["User" ] = cls ._compose ("_User" , attrs ["User" ], [base .User for base in bases ])
41
+ if "Channel" in attrs :
42
+ attrs ["Channel" ] = cls ._compose ("_Channel" , attrs ["Channel" ], [base .Channel for base in bases ])
43
+ return super ().__new__ (cls , name , bases , attrs )
44
+
45
+
46
+ class BasicClient (metaclass = ClientMeta ):
33
47
"""
34
48
Base IRC client class.
35
49
This class on its own is not complete: in order to be able to run properly, _has_message, _parse_message and _create_message have to be overloaded.
@@ -39,11 +53,13 @@ class BasicClient:
39
53
RECONNECT_DELAYED = True
40
54
RECONNECT_DELAYS = [0 , 5 , 10 , 30 , 120 , 600 ]
41
55
56
+ User = models .User
57
+ Channel = models .Channel
58
+
42
59
def __init__ (self , nickname , fallback_nicknames = [], username = None , realname = None , ** kwargs ):
43
60
""" Create a client. """
44
61
self ._nicknames = [nickname ] + fallback_nicknames
45
- self .username = username or nickname .lower ()
46
- self .realname = realname or nickname
62
+ self .user = models .User (self , nickname , realname or nickname , username or nickname .lower ())
47
63
self .eventloop = None
48
64
self .own_eventloop = True
49
65
self ._reset_connection_attributes ()
@@ -52,6 +68,18 @@ def __init__(self, nickname, fallback_nicknames=[], username=None, realname=None
52
68
if kwargs :
53
69
self .logger .warning ('Unused arguments: %s' , ', ' .join (kwargs .keys ()))
54
70
71
+ @property
72
+ def nickname (self ):
73
+ return self .user .nickname
74
+
75
+ @property
76
+ def username (self ):
77
+ return self .user .username
78
+
79
+ @property
80
+ def realname (self ):
81
+ return self .user .realname
82
+
55
83
def _reset_attributes (self ):
56
84
""" Reset attributes. """
57
85
# Record-keeping.
@@ -69,7 +97,7 @@ def _reset_attributes(self):
69
97
self .logger = logging .getLogger (__name__ )
70
98
71
99
# Public connection attributes.
72
- self .nickname = DEFAULT_NICKNAME
100
+ self .user . nickname = DEFAULT_NICKNAME
73
101
self .network = None
74
102
75
103
def _reset_connection_attributes (self ):
@@ -164,42 +192,28 @@ def _check_ping_timeout(self):
164
192
## Internal database management.
165
193
166
194
def _create_channel (self , channel ):
167
- self .channels [channel ] = {
168
- 'users' : set (),
169
- }
195
+ self .channels [channel ] = self .Channel (self , channel )
170
196
171
197
def _destroy_channel (self , channel ):
172
198
# Copy set to prevent a runtime error when destroying the user.
173
- for user in set (self .channels [channel ][ ' users' ] ):
199
+ for user in set (self .channels [channel ]. users ):
174
200
self ._destroy_user (user , channel )
175
201
del self .channels [channel ]
176
202
177
203
178
204
def _create_user (self , nickname ):
179
- # Servers are NOT users.
180
- if not nickname or '.' in nickname :
181
- return
205
+ self .users [nickname ] = self .User (self , nickname )
182
206
183
- self .users [nickname ] = {
184
- 'nickname' : nickname ,
185
- 'username' : None ,
186
- 'realname' : None ,
187
- 'hostname' : None
188
- }
189
-
190
- def _sync_user (self , nick , metadata ):
191
- # Create user in database.
192
- if nick not in self .users :
193
- self ._create_user (nick )
194
- if nick not in self .users :
195
- return
207
+ def _get_or_create_user (self , nickname ):
208
+ if nickname not in self .users :
209
+ self ._create_user (nickname )
196
210
197
- self .users [nick ]. update ( metadata )
211
+ return self .users [nickname ]
198
212
199
213
def _rename_user (self , user , new ):
200
214
if user in self .users :
201
215
self .users [new ] = self .users [user ]
202
- self .users [new ][ ' nickname' ] = new
216
+ self .users [new ]. nickname = new
203
217
del self .users [user ]
204
218
else :
205
219
self ._create_user (new )
@@ -208,9 +222,9 @@ def _rename_user(self, user, new):
208
222
209
223
for ch in self .channels .values ():
210
224
# Rename user in channel list.
211
- if user in ch [ ' users' ] :
212
- ch [ ' users' ] .discard (user )
213
- ch [ ' users' ] .add (new )
225
+ if user in ch . users :
226
+ ch . users .discard (user )
227
+ ch . users .add (new )
214
228
215
229
def _destroy_user (self , nickname , channel = None ):
216
230
if channel :
@@ -220,23 +234,23 @@ def _destroy_user(self, nickname, channel=None):
220
234
221
235
for ch in channels :
222
236
# Remove from nicklist.
223
- ch [ ' users' ] .discard (nickname )
237
+ ch . users .discard (nickname )
224
238
225
239
# If we're not in any common channels with the user anymore, we have no reliable way to keep their info up-to-date.
226
240
# Remove the user.
227
- if not channel or not any (nickname in ch [ ' users' ] for ch in self .channels .values ()):
241
+ if not channel or not any (nickname in ch . users for ch in self .channels .values ()):
228
242
del self .users [nickname ]
229
243
230
244
def _parse_user (self , data ):
231
245
""" Parse user and return nickname, metadata tuple. """
232
246
raise NotImplementedError ()
233
247
234
248
def _format_user_mask (self , nickname ):
235
- user = self .users . get ( nickname , { "nickname" : nickname , "username" : "*" , "hostname" : "*" })
236
- return self . _format_host_mask ( user [ 'nickname' ], user [ 'username' ] or '*' , user [ 'hostname' ] or '*' )
237
-
238
- def _format_host_mask ( self , nick , user , host ):
239
- return '{n}!{u}@{h}' . format ( n = nick , u = user , h = host )
249
+ if nickname in self .users :
250
+ user = self . users [ nickname ]
251
+ else :
252
+ user = self . User ( self , nickname )
253
+ return user . hostmask
240
254
241
255
242
256
## IRC helpers.
0 commit comments