Attachment 'PostLimit.py'
Download 1 # Copyright (C) 2013 by the Free Software Foundation, Inc.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
16 # USA.
17
18 """Handler to limit a member's posts to a list to M per calendar day or M per
19 time period and/or limit the total number of posts to the to the list to L in
20 the same period.
21
22 This handler should go in the pipeline before Moderate.
23
24 This file should be copied to Mailman/Handlers/PostLimit.py
25
26 To activate it for a particular list put the following code, edited for the
27 parameters you want, in lists/LISTNAME/extend.py
28
29 -------------------------- cut ------------
30 import copy
31 from Mailman import mm_cfg
32 def extend(mlist):
33 if not hasattr(mlist, 'pipeline'):
34 mlist.pipeline = copy.copy(mm_cfg.GLOBAL_PIPELINE)
35 if 'PostLimit' not in mlist.pipeline:
36 mlist.pipeline.insert(mlist.pipeline.index('Moderate'), 'PostLimit')
37 if not hasattr(mlist, 'post_member_limit'):
38 # To limit the number of member posts per period, set the following
39 # to the limit.
40 mlist.post_member_limit = 0
41 if not hasattr(mlist, 'post_list_limit'):
42 # To limit the number of list posts per period, set the following
43 # to the limit.
44 mlist.post_list_limit = 0
45 if not hasattr(mlist, 'post_period'):
46 # To set the time period, set the following.
47 # <=0 -> current day
48 # >0 -> number of hours
49 mlist.post_period = 0
50 -------------------------- cut ------------
51 """
52
53 import time
54
55 from Mailman import Errors
56 from Mailman.i18n import _
57
58 # L if > 0, is the maximum number of list posts allowed in the period
59 # M if > 0, is the maximum number of per member posts allowed in the period
60 # PERIOD is an integer that defines the period
61 # <=0 -> the current calendar day (local time)
62 # >0 -> the length of the period in hours
63
64 # Do not set these here. Set the corresponding list attributes in the list's
65 # extend.py or via withlist or config_list (see above).
66 L = 0
67 M = 0
68 PERIOD = 0
69
70
71
72 def process(mlist, msg, msgdata):
73 global L, M, PERIOD
74 if msgdata.get('approved'):
75 return
76 if hasattr(mlist, 'post_list_limit'):
77 L = mlist.post_list_limit
78 if hasattr(mlist, 'post_member_limit'):
79 M = mlist.post_member_limit
80 if hasattr(mlist, 'post_period'):
81 PERIOD = mlist.post_period
82 if L <= 0 and M <= 0:
83 return
84 # First of all, is the poster a member or not (same test as
85 # Moderate.py)?
86 for sender in msg.get_senders():
87 if mlist.isMember(sender):
88 break
89 else:
90 sender = None
91 if not sender and L <= 0:
92 # Sender is not a member and we're not limiting the list, let
93 # Moderate handle it.
94 return
95
96 # If this is the first time for this list, we need to create the
97 # dictionary for post counting
98 if not hasattr(mlist, 'post_counts'):
99 mlist.post_counts = {}
100 now = time.time()
101 lposts = mlist.post_counts.setdefault('list', [])
102 lposts = drop_old(lposts, now)
103 mposts = mlist.post_counts.setdefault(sender, [])
104 mposts = drop_old(mposts, now)
105 if (L <= 0 and len(mposts) < M or
106 M <= 0 and len(lposts) < L or
107 len(mposts) < M and len(lposts) < L):
108 lposts.append(now)
109 mlist.post_counts['list'] = lposts
110 mposts.append(now)
111 mlist.post_counts[sender] = mposts
112 return
113 if PERIOD <= 0:
114 period = _('today')
115 else:
116 period = _('in the last %(PERIOD)s hours')
117 if M > 0 and len(mposts) >= M:
118 what = _('You have already sent %(M)s')
119 else:
120 what = _('There have already been %(L)s')
121 rmsg = _('%(what)s posts to this list %(period)s.')
122 raise Errors.RejectMessage, rmsg
123
124
125
126 def drop_old(posts, now):
127 new_posts = []
128 for post in posts:
129 if PERIOD > 0:
130 if post + (PERIOD * 3600) > now:
131 new_posts.append(post)
132 else:
133 if (time.localtime(post)[7] == time.localtime(now)[7] and
134 time.localtime(post)[0] == time.localtime(now)[0]):
135 new_posts.append(post)
136 return new_posts
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.