# Copyright (C) 2013 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Handler to limit a member's posts to a list to M per calendar day or M per time period and/or limit the total number of posts to the to the list to L in the same period. This handler should go in the pipeline before Moderate. This file should be copied to Mailman/Handlers/PostLimit.py To activate it for a particular list put the following code, edited for the parameters you want, in lists/LISTNAME/extend.py -------------------------- cut ------------ import copy from Mailman import mm_cfg def extend(mlist): if not hasattr(mlist, 'pipeline'): mlist.pipeline = copy.copy(mm_cfg.GLOBAL_PIPELINE) if 'PostLimit' not in mlist.pipeline: mlist.pipeline.insert(mlist.pipeline.index('Moderate'), 'PostLimit') if not hasattr(mlist, 'post_member_limit'): # To limit the number of member posts per period, set the following # to the limit. mlist.post_member_limit = 0 if not hasattr(mlist, 'post_list_limit'): # To limit the number of list posts per period, set the following # to the limit. mlist.post_list_limit = 0 if not hasattr(mlist, 'post_period'): # To set the time period, set the following. # <=0 -> current day # >0 -> number of hours mlist.post_period = 0 -------------------------- cut ------------ """ import time from Mailman import Errors from Mailman.i18n import _ # L if > 0, is the maximum number of list posts allowed in the period # M if > 0, is the maximum number of per member posts allowed in the period # PERIOD is an integer that defines the period # <=0 -> the current calendar day (local time) # >0 -> the length of the period in hours # Do not set these here. Set the corresponding list attributes in the list's # extend.py or via withlist or config_list (see above). L = 0 M = 0 PERIOD = 0 def process(mlist, msg, msgdata): global L, M, PERIOD if msgdata.get('approved'): return if hasattr(mlist, 'post_list_limit'): L = mlist.post_list_limit if hasattr(mlist, 'post_member_limit'): M = mlist.post_member_limit if hasattr(mlist, 'post_period'): PERIOD = mlist.post_period if L <= 0 and M <= 0: return # First of all, is the poster a member or not (same test as # Moderate.py)? for sender in msg.get_senders(): if mlist.isMember(sender): break else: sender = None if not sender and L <= 0: # Sender is not a member and we're not limiting the list, let # Moderate handle it. return # If this is the first time for this list, we need to create the # dictionary for post counting if not hasattr(mlist, 'post_counts'): mlist.post_counts = {} now = time.time() lposts = mlist.post_counts.setdefault('list', []) lposts = drop_old(lposts, now) mposts = mlist.post_counts.setdefault(sender, []) mposts = drop_old(mposts, now) if (L <= 0 and len(mposts) < M or M <= 0 and len(lposts) < L or len(mposts) < M and len(lposts) < L): lposts.append(now) mlist.post_counts['list'] = lposts mposts.append(now) mlist.post_counts[sender] = mposts return if PERIOD <= 0: period = _('today') else: period = _('in the last %(PERIOD)s hours') if M > 0 and len(mposts) >= M: what = _('You have already sent %(M)s') else: what = _('There have already been %(L)s') rmsg = _('%(what)s posts to this list %(period)s.') raise Errors.RejectMessage, rmsg def drop_old(posts, now): new_posts = [] for post in posts: if PERIOD > 0: if post + (PERIOD * 3600) > now: new_posts.append(post) else: if (time.localtime(post)[7] == time.localtime(now)[7] and time.localtime(post)[0] == time.localtime(now)[0]): new_posts.append(post) return new_posts