1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
# -*- Python -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Pan-protocol chat client.
"""
from zope.interface import Attribute, Interface
# (Random musings, may not reflect on current state of code:)
#
# Accounts have Protocol components (clients)
# Persons have Conversation components
# Groups have GroupConversation components
# Persons and Groups are associated with specific Accounts
# At run-time, Clients/Accounts are slaved to a User Interface
# (Note: User may be a bot, so don't assume all UIs are built on gui toolkits)
class IAccount(Interface):
"""
I represent a user's account with a chat service.
"""
client = Attribute("The L{IClient} currently connecting to this account, if any.")
gatewayType = Attribute(
"A C{str} that identifies the protocol used by this account."
)
def __init__(accountName, autoLogin, username, password, host, port):
"""
@type accountName: string
@param accountName: A name to refer to the account by locally.
@type autoLogin: boolean
@type username: string
@type password: string
@type host: string
@type port: integer
"""
def isOnline():
"""
Am I online?
@rtype: boolean
"""
def logOn(chatui):
"""
Go on-line.
@type chatui: Implementor of C{IChatUI}
@rtype: L{Deferred} with an eventual L{IClient} result.
"""
def logOff():
"""
Sign off.
"""
def getGroup(groupName):
"""
@rtype: L{Group<IGroup>}
"""
def getPerson(personName):
"""
@rtype: L{Person<IPerson>}
"""
class IClient(Interface):
account = Attribute("The L{IAccount} I am a Client for")
def __init__(account, chatui, logonDeferred):
"""
@type account: L{IAccount}
@type chatui: L{IChatUI}
@param logonDeferred: Will be called back once I am logged on.
@type logonDeferred: L{Deferred<twisted.internet.defer.Deferred>}
"""
def joinGroup(groupName):
"""
@param groupName: The name of the group to join.
@type groupName: string
"""
def leaveGroup(groupName):
"""
@param groupName: The name of the group to leave.
@type groupName: string
"""
def getGroupConversation(name, hide=0):
pass
def getPerson(name):
pass
class IPerson(Interface):
def __init__(name, account):
"""
Initialize me.
@param name: My name, as the server knows me.
@type name: string
@param account: The account I am accessed through.
@type account: I{Account}
"""
def isOnline():
"""
Am I online right now?
@rtype: boolean
"""
def getStatus():
"""
What is my on-line status?
@return: L{locals.StatusEnum}
"""
def getIdleTime():
"""
@rtype: string (XXX: How about a scalar?)
"""
def sendMessage(text, metadata=None):
"""
Send a message to this person.
@type text: string
@type metadata: dict
"""
class IGroup(Interface):
"""
A group which you may have a conversation with.
Groups generally have a loosely-defined set of members, who may
leave and join at any time.
"""
name = Attribute("My C{str} name, as the server knows me.")
account = Attribute("The L{Account<IAccount>} I am accessed through.")
def __init__(name, account):
"""
Initialize me.
@param name: My name, as the server knows me.
@type name: str
@param account: The account I am accessed through.
@type account: L{Account<IAccount>}
"""
def setTopic(text):
"""
Set this Groups topic on the server.
@type text: string
"""
def sendGroupMessage(text, metadata=None):
"""
Send a message to this group.
@type text: str
@type metadata: dict
@param metadata: Valid keys for this dictionary include:
- C{'style'}: associated with one of:
- C{'emote'}: indicates this is an action
"""
def join():
"""
Join this group.
"""
def leave():
"""
Depart this group.
"""
class IConversation(Interface):
"""
A conversation with a specific person.
"""
def __init__(person, chatui):
"""
@type person: L{IPerson}
"""
def show():
"""
doesn't seem like it belongs in this interface.
"""
def hide():
"""
nor this neither.
"""
def sendText(text, metadata):
pass
def showMessage(text, metadata):
pass
def changedNick(person, newnick):
"""
@param person: XXX Shouldn't this always be Conversation.person?
"""
class IGroupConversation(Interface):
def show():
"""
doesn't seem like it belongs in this interface.
"""
def hide():
"""
nor this neither.
"""
def sendText(text, metadata):
pass
def showGroupMessage(sender, text, metadata):
pass
def setGroupMembers(members):
"""
Sets the list of members in the group and displays it to the user.
"""
def setTopic(topic, author):
"""
Displays the topic (from the server) for the group conversation window.
@type topic: string
@type author: string (XXX: Not Person?)
"""
def memberJoined(member):
"""
Adds the given member to the list of members in the group conversation
and displays this to the user,
@type member: string (XXX: Not Person?)
"""
def memberChangedNick(oldnick, newnick):
"""
Changes the oldnick in the list of members to C{newnick} and displays this
change to the user,
@type oldnick: string (XXX: Not Person?)
@type newnick: string
"""
def memberLeft(member):
"""
Deletes the given member from the list of members in the group
conversation and displays the change to the user.
@type member: string (XXX: Not Person?)
"""
class IChatUI(Interface):
def registerAccountClient(client):
"""
Notifies user that an account has been signed on to.
@type client: L{Client<IClient>}
"""
def unregisterAccountClient(client):
"""
Notifies user that an account has been signed off or disconnected.
@type client: L{Client<IClient>}
"""
def getContactsList():
"""
@rtype: L{ContactsList}
"""
# WARNING: You'll want to be polymorphed into something with
# intrinsic stoning resistance before continuing.
def getConversation(person, Class, stayHidden=0):
"""
For the given person object, returns the conversation window
or creates and returns a new conversation window if one does not exist.
@type person: L{Person<IPerson>}
@type Class: L{Conversation<IConversation>} class
@type stayHidden: boolean
@rtype: L{Conversation<IConversation>}
"""
def getGroupConversation(group, Class, stayHidden=0):
"""
For the given group object, returns the group conversation window or
creates and returns a new group conversation window if it doesn't exist.
@type group: L{Group<interfaces.IGroup>}
@type Class: L{Conversation<interfaces.IConversation>} class
@type stayHidden: boolean
@rtype: L{GroupConversation<interfaces.IGroupConversation>}
"""
def getPerson(name, client):
"""
Get a Person for a client.
Duplicates L{IAccount.getPerson}.
@type name: string
@type client: L{Client<IClient>}
@rtype: L{Person<IPerson>}
"""
def getGroup(name, client):
"""
Get a Group for a client.
Duplicates L{IAccount.getGroup}.
@type name: string
@type client: L{Client<IClient>}
@rtype: L{Group<IGroup>}
"""
def contactChangedNick(oldnick, newnick):
"""
For the given person, changes the person's name to newnick, and
tells the contact list and any conversation windows with that person
to change as well.
@type oldnick: string
@type newnick: string
"""
|