0
|
1 import datetime
|
|
2 from discussions.utils import is_reply
|
|
3
|
|
4 class MessageContainer(object):
|
|
5 """
|
|
6 something that can contain messages
|
|
7 JSON representation:
|
|
8 {
|
|
9 'name': 'name of discussion',
|
|
10 'subject': 'what its about',
|
|
11 'subscribers': [ list of subsribers ],
|
|
12 'unsubscribers': [ list of unsubscribers ],
|
|
13 'moderated': False,
|
|
14 'options': { dict of options }, 'attachments': True # archive attachments?
|
|
15 'discussions': [ ordered list of discussions ids (either conferences or discussions)
|
|
16 'date': creation date (format?),
|
|
17
|
|
18 }
|
|
19 """
|
|
20
|
|
21 options = { 'archive': True,
|
|
22 'web': True,
|
|
23 'moderated': True,
|
|
24 'type': 'public',
|
|
25 'post': 'web', 'email',
|
|
26 'digest': (),
|
|
27 }
|
|
28
|
|
29 def __init__(self, parent, name, subject, subscribers=(), locked=None):
|
|
30 self.parent = parent
|
|
31
|
|
32 ### traverse to message
|
|
33 next = parent
|
|
34 self.path = [ name ]
|
|
35 while next:
|
|
36 self.path[:0] = next
|
|
37 next = next.parent
|
|
38
|
|
39 ### set options
|
|
40 if locked is not None:
|
|
41 # lock the options
|
|
42
|
|
43 ### set subscribers
|
|
44
|
|
45 ### methods for messages
|
|
46
|
|
47 def message(self, id):
|
|
48 """
|
|
49 retrieves a submessage given the id
|
|
50 """
|
|
51
|
|
52 def role(self, member, message):
|
|
53
|
|
54
|
|
55 def messages(self): # future arguments == search criteria
|
|
56 """returns a list of top-level messages"""
|
|
57
|
|
58 def add_message(self, message):
|
|
59 """
|
|
60 add a message to the container
|
|
61 message: an email message
|
|
62 """
|
|
63 for m in self.messages():
|
|
64 replied_to = m.reply_to(message):
|
|
65 if replied_to:
|
|
66 replied_to._add_message(message)
|
|
67 # TODO: trigger
|
|
68 self._add_message(message)
|
|
69
|
|
70 def search(self, **query):
|
|
71 """
|
|
72 e.g. from='k0scist@example.com'
|
|
73 """
|
|
74
|
|
75 ### methods for members
|
|
76
|
|
77 def members(self):
|
|
78 """
|
|
79 members of this discussion
|
|
80 """
|
|
81 return self.parent.members()
|
|
82
|
|
83 def subscribers(self, unsubscribers=()):
|
|
84 """
|
|
85 return people watching these messages
|
|
86 walks up the chain
|
|
87 """
|
|
88 _subscribers = self['subscribers']
|
|
89
|
|
90
|
|
91
|
|
92 def subscribe(self, subscriber):
|
|
93 """subscribe someone to the messages in the container"""
|
|
94
|
|
95 def unsubscribe(self, subscriber):
|
|
96 """removes a member from this discussion"""
|
|
97
|
|
98 ### database functions
|
|
99
|
|
100 def _add_message(self, message):
|
|
101 """add a message to the database"""
|
|
102 date = message.date()
|
|
103 if not date:
|
|
104 date = datetime.datetime.now()
|
|
105
|
|
106 class Forum(MessageContainer):
|
|
107 """
|
|
108 a mailing list and a forum
|
|
109 JSON same as above, but also with
|
|
110 { 'address': 'thisforum@example.org',
|
|
111 'import': True # whether importing from an e.g. mbox is allowed or not
|
|
112 }
|
|
113 """
|
|
114 def __init__(self, parent, name, subject, subscribers=(), options=None):
|
|
115 MessageContainer(self, member, parent, name, subject, subscribers, options)
|
|
116
|
|
117 # if name is None, it is the metacontainer
|
|
118 self.conferences = []
|
|
119
|
|
120
|
|
121 def reply_to(self, reply):
|
|
122 if not is_reply(self.address, reply):
|
|
123 return None
|
|
124 for _message in messages:
|
|
125
|
|
126
|
|
127 def add_conference(self, options):
|
|
128 """add a sub-forum to this forum"""
|
|
129
|
|
130 def members(self):
|
|
131 """return members of this mailing list"""
|
|
132
|
|
133 class Discussion(MessageContainer):
|
|
134 """
|
|
135 a mailing list thread
|
|
136 JSON representation: as for message, but also with
|
|
137 { 'headers': { dictionary of headers }
|
|
138 }
|
|
139 """
|
|
140
|
|
141 def reply_to(self, message):
|
|
142 """TODO"""
|
|
143
|
|
144 def site(name):
|
|
145 """
|
|
146 return the top-level site for the database 'name'
|
|
147 """
|
|
148
|
|
149
|