why
g.d.o is having problems with spam submission. A human spammer registers, writes spam content, and many people get the spam delivered by mail because of the og subscription feature.
If any module allows spammers to post content and have the content delivered by mail by ourselves to legitimate users, it is a great incentive to spammers to abuse the web site further.
Beside the captcha module that can stop spambots, the site should offer as little incentive as possible to human spammers.
what
Thus the following feature request is critical for a subscriptions.module on today's internet:
Have a delayed mail delivery feature that could ensure that no spam email is ever sent.
The delayed mail delivery would only kick in for untrusted/new users. A permission should be added so that known/trusted users can post and have the notification related to their post sent to the subscribers without delay.
For all other users, the content of the mail notification would have to be reviewed by one of a group of moderators (having the permission "moderate notifications" or something like that). The moderator would have 3 choices:
- the notification is full of spam. Don't send it. If the moderator has sufficient permission he can then deleted the actual node/comment with spam, and block the user.
- the notification is ok: apply a check mark and the notification is sent. If the moderator has sufficient permission, he can add the permission "don't review the content of the notification" to the user so further contributions won't need to be moderated.
- the notification is ok. check it and send it, but keep the user on the watch list for a little while longer.
After a while, all known users would have sufficient permission that no moderator review is necessary. Only new users would be monitored for a while.
Note: this feature is independent from the usual node/comment moderation workflow. I.e. a new comment could be set to be published on the web site straight away, without prior moderation, but the goal is not to send any notification by mail until we have a certain level of assurance that we are not helping spammers.
we don't get black listed
This feature is critical for another reason: if we send email notification that contain spam, and the mails get flaged, reported as such by the recipient, the web server's IP may be black listed and ALL email emanating from the site will be blocked.
modularity
og.module could very well benefit from a similar feature.
Subscriptions.module should implement this feature with modularity in mind.
The main features that subscriptions should implement, and delayed delivery for notification caused by the contributions of users without the proper permission.
Then, the delayed notification could be processed in different ways: put on a moderation list for human review, or passed on to a 3rd module (like spam.module) for automatic evaluation: is it spam? is it not? or is it border line and needs human review?
Thus the subscriptions / spam module would do part of the moderator's job.
| Comment | File | Size | Author |
|---|---|---|---|
| #53 | moderate_content_notifications.module.txt | 11.71 KB | salvis |
| #53 | moderate_content_notifications.install.txt | 1.79 KB | salvis |
| #53 | moderate_content_notifications.info_.txt | 183 bytes | salvis |
| #50 | moderate_content_mailing.info_.txt | 172 bytes | beginner |
| #50 | moderate_content_mailing.install.txt | 1.7 KB | beginner |
Comments
Comment #1
salvisThank you for the well thought-out feature request. I clearly see the need.
Previewing the notifications is not feasible. For example, comments are always merged with pending new or update notifications, so spam and non-spam could be in the same preview. For the same reason not all users get the same notifications in the same context, e.g. some users may already have received the new notification and will get the comment separately, and others with larger (or offset) Send Intervals would get them merged.
I'd rather see posts and comments getting links like
-- release notifications (where notifications are held)
-- hold notifications (where notifications are auto-released)
with the former going to a confirmation form with a checkbox like
[ ] auto-release notifications for this user
Is a notification moderation queue form needed?
Is auditing of moderator actions needed? history of poster qualifications?
Comment #2
beginner commentedIt sounds good.
When I said "Previewing the notifications", it was a shortcut for saying: don't send any notification that includes the content of a new comment or a new node by an untrusted member before review.
In case of batched notifications, the notification should only include the comments by trusted members, and exclude that of the untrusted one, until sending a notification about it has been approved.
What you propose sound good.
A moderation queue sounds necessary for the moderator's convenience: he would have a list of all comments and nodes (already published on the site) for which the notification is on hold.
The auditing of moderator action is not required, but it could be a nice additional touch. It could be a follow up feature request.
The history of the poster qualification should be obvious by looking at his tracker page (user/$nid/tracker), which a moderator would have access to. What would only be required is a direct link from the moderation queue to the user tracker page. Easy.
Comment #3
salvisI've been thinking about this and I found that my original idea was a bit too simple for various reasons, e.g. it doesn't provide a way to get items off the queue in all cases, and it's cumbersome to use because it involves reloads. Whatever interface it is, it will appear below every post and every comment that has notifications in the queue, so it really ought to work well!
You recently mentioned on the dev list that you're getting into JS/AJAX — maybe we can do something together here. I'm thinking of a dynamic interface like the following:
Notifications: discard | 0 | HELD | 0 | release auto-release
Clicking discard would turn it into
Notifications: | 1 | DISCARDED | 0 |
Clicking release or auto-release (the latter would need an additional permission) instead would turn it into either of
Notifications: recall | 0 | RELEASED | 1 | auto-release
Notifications: recall | 0 | AUTO-RELEASED | 1 |
A second post would then show up (depending on how the first one was treated) as either of
Notifications: discard | 1 | HELD | 0 | release auto-release
Notifications: discard | 0 | HELD | 1 | release auto-release
Notifications: recall | 0 | AUTO-RELEASED | 2 |
Clicking on recall would change it to
Notifications: | 1 | RECALLED | 2 |
If we could do this in place, without a reload, that'd be pretty neat!
So, can you write me a widget that fills a <div> with HTML, including a few links that perform some actions and refill the <div>? It'll have to work as multiple instances on the same page and needs to have an anchor and a fall-back non-JS interface. Keeping a constant width in the first column would be a nice touch.
Comment #4
beginner commentedHi,
You speak about the details about the UI, while I am still worrying about the inner implementation.
To reply quickly to your comments: I am certainly not an ajax guru. I wrote this for my own benefit, because I knew really little. A simple AHAH call is now easy for Drupal 6, though.
Coming back to the internal implementation. I am not yet familiar with how subscriptions.module works internally.
Imagine the following situation:
What happens
- in the current implementation of subscriptions.module ?
- after this feature is implemented ?
Is user U10 notified of C1 and C4, but not of C2 and C3?
Assuming everything is ok, is he notified of C2 and C3 after the moderation process?
Or is he notified of C1 only?
Or not at all, until the comments in this nodes are moderated?
Is U11 notified of anything at all?
How do you tag internally which change (new comment) has been notified to whom?
Do you use timestamps: check the last time the users were sent notifications, and see what content has been added since that time?
Before dealing with the details of the UI, can you explain the current internal process?
What changes would be required in the internal process for this feature to work?
I would be happy to help with preparing and testing a patch. I am very grateful that you are seriously considering this critical feature.
Comment #5
salvisBut you are way ahead of me. So, if you'll take care of the UI, I'll take care of the implementation.
Designing the details of the UI helps me find the use cases and thus the requirements for the inner workings.
The entries in {subscriptions_queue} are by recipient and by node/comment. When someone creates (or updates) a node or comment, then every matching subscription puts an entry into the queue for each subscribed user.
cron consumes the entries in FIFO manner. For every entry, when it loads a node, the queue is automatically scanned for comment entries for that node and user. From this information a notification is assembled (node + comments, for this user) and sent, and the comment entries as well as all other queue items with the same load_function and load_args (and user) are removed. The actual implementation is a little more involved, but these are the essential parts.
So, in the current implementation,
queue item U10/C1 is picked up, N loaded, queue items U10/C1..4 fetched, comments loaded, notification assembled and sent, and the queue items U10/C1..4 are removed.
Then
queue item U11/C2 is picked up, N loaded, queue items U10/C2..4 fetched, comments loaded, notification assembled and sent, and the queue items U11/C2..4 are removed. U11/C1 had already been removed during the previous cron run according to your set-up.
***
For the new implementation we have to decide whether moderators receive advance notification of unreleased posts. I tend to say no. Notification moderation needs to be organized so that it's done in a timely manner, and I think it can only work well when enough people patrol the site frequently enough.
The trust state needs to be stored with the author, i.e. in {subscriptions_user}. Before items (nodes as well as comments) are inserted into the queue they need to be checked against the trust state of the author. The trust state would be one of (AUTO-RELEASE, HOLD, and maybe DISCARD) and translates directly into initial actions taken when content is created. The count of good and bad posts would have to be stored there as well for efficient access. We'd have
U1: AUTO-RELEASE
U2: HOLD
U3: HOLD
U4: AUTO-RELEASE
To store the moderation state, we need a new table {subscriptions_moderate}:
nid,cid: primary key (cid=0 for the node)
state: RECALLED/DISCARDED/HELD
Items not in the table would be RELEASED (or AUTO-RELEASED, depending on the author).
At creation time, C1 and C4 would be queued and C2 and C3 entered into {subscriptions_moderate} as HELD. So, C1 and C4 would be notified as usual and C2 and C3 not. When the moderator releases C2 and C3, then they are entered into the queue and notified as usual. If he auto-releases C2, then {subscriptions_user} is updated and all held content of U2 is queued.
We might sort the comments that are assembled into one notification try to preserve chronological order as well as possible, but we can't avoid C4 being notified before C2 and C3, if cron runs in the meantime.
When the moderator discards C2, it's updated in {subscriptions_moderate} only. When he releases and recalls it, then queue entries are removed also. Notifications that have already gone out can't really be recalled, of course, but "recall" describes the intent.
It wouldn't make sense to notify comments for a node before that node's notifications are released. Thus all comments would need to be implicitly put on hold (and blocked from moderation) as long as the node needs moderation. When the node is released, its comments could be dealt with as if they had just been created.
yes
yes
no
no
yes, C4 right away, and C2 and C3 after release
No. As explained above, the queue works as a ToNotify list at the most granular (and redundant!) level. Every processed notification removes the items that would lead to duplicate notifications (to the same user). So this essentially takes care of itself. This design is due to chx, btw.
The timestamps are only used to delay processing, if a Send Interval > ASAP was selected. This automatically has the effect, that multiple comments may accumulate in the queue, and when the time has come, they'll be merged.
Good enough? This requires very little changes in the current code. A hook_queue_subscription() is probably all that's needed, so that a module can filter events before they are entered into the queue. Just about everything else can be handled externally.
There's plenty of data for administrative interfaces (moderation queue, etc.), and if anything else is needed, we can easily add a column somewhere.
Does this make sense? Have I missed anything?
***
Back to the UI:
The problem is that we need such a widget for every node and comment, which means there could be tens of them on a page, and if the same author has made multiple comments, then it would be nice to have some synchronization among that author's widgets. Reloading the page would automatically take care of that, but reloading the page for each and every comment just won't cut it. We need something better, and not just for D6.
Having all these widgets visible all of the time is not very attractive either, so if we could hide them behind a JS link (unless moderation is needed) and only pop them up on request, that would be really nice.
This could become an add-on module of its own or an optional component of the Subscriptions distribution. If you want to take a stab at it on your own we'll certainly help. Otherwise I can do the internal stuff, but I'd need you to do a usable JS UI. And I'd appreciate help with whatever administrative interface is needed.
P.S. I'll be away for a week starting Saturday and pretty busy in the week after that, so I won't be able to do much in the next few days, but I see the need to implement it and will work on it.
Comment #6
chx commentedHmm, i do not readily see the need for a new table, why not just add a hold flag to the subscriptions_queue table. The mail module could check that only hold = 0 mails are sent. A subscriptions_moderation module can update this flag accordingly. (subscriptions_content_node_load and subscriptions_content_comment_load tells us which entries are nodes / comments). We could add a module_invoke to subscriptions_queue calling subscriptions_moderation_queue which would conviniently deliver a 0 for us if the module is not on. This is backend and it's fairly easy. About the UI, no idea.
Comment #7
chx commentedAn alter like hook also works, pretty much the same as a dedicated module invoke.
Comment #8
salvisStoring the HELD state in {subscriptions_queue} would mean that you can't display moderation controls on comments, because retrieving the state would be very inefficient. chx sees no need for that, just a moderation queue with a list of subjects and links to the nodes/comments. If that is sufficient, then we can save a lot of effort.
Comment #9
beginner commentedFor the UI, I thing something like the comment approval queue would be enough: ?q=admin/content/comment/list/approval
So, we only need to add a field in {subscriptions_queue} as suggested above.
Comment #10
beginner commentedRe: #5, I forgot: thanks Salvis for the detailed explanation and comments. :)
I am working on a patch + new module.
I need some quick feedback here:
The second perm, '
moderate subscription mails' is for moderators. Their task is simple: keep an eye on spammers, and promote trusted users so the subscription mails do not need to be moderated in the future.The users who have the first perm, '
send subscription mails without moderation', won't have their content moderated by this module. It is a perm, so it must be associated to a role (e.g. "registered users" don't have this perm, but "trusted members" do have it).In order to use this perm efficiently within the module, I need to know which role has it. For this, I must have a setting page, where the role (e.g. "trusted members") is selected and saved in a variable. The role should have only this one, or few additional perms: it is a basic role only to differentiate new registered members from known, trusted members.
The subscriptions_moderation.module would add the said role to the trusted users.
=====
The other approach would be to create our own user table with the fields: uid (primary) + moderate (bool). It's simpler for the administrator, but requires more coding.
I prefer the first approach.
What do you think?
Comment #11
salvisSince we have to add 'hold' to {subscriptions_queue} (default 0), we may as well add 'moderate' to {subscriptions_user} (again default 0). The defaults ensure that everything runs normally if subscriptions_moderate is not enabled.
The benefit of having a permission would be that core could be used for administering it when you initially set this up. Later on, having a column in {subscriptions_user} seems much simpler and more compact, but at some point you'll probably want to know, which of your users have auto-release, so the role-based approach has the advantage again.
Besides, the admin might choose to give this perm to a few other roles (maybe even most roles) from the start.
So I prefer the first approach, too.
You'll have to provide some instructions and suggest a good (short) name for the role, ideally right on the setting page, so that admins who go there will know what to do.
Comment #12
beginner commentedHi,
Sorry for the delay. I went away for the New Year holiday. With the New Year celebration behind us, I come back here :)
The new subscriptions_moderation.module is currently almost empty. Most importantly, it implement the permission 'trusted not to spam' (which is much clearer than what I proposed above).
I added a 'moderate' column in {subscriptions_queue}. If the module is enabled and the the user doesn't have the permission 'trusted not to spam', the moderate flag is set to 1. Afterwards, all the other operations by the subscriptions modules ignore everything in {subscriptions_queue} where the flag is on.
The next step is obviously to complete the new module to perform the three following actions:
1 - list all the entries to moderate.
2 - for each entry, either set the flag to 0 (so it will be included in the next mailing) or delete it.
3 - offer to give a specific role (with the perm 'trusted not to spam') to the users as we go along the moderation process.
But here I run again into some implementation problems.
First, I misunderstood the meaning of the column 'author_uid' in {subscriptions_queue}. I thought I could use it to select all entries by the same author, but now I see that most of the time, the field has the value -1, and only the author's uid in specific circumstances.
Also, now that I understand a bit more the module, I see that a single comment / node will create dozens or more rows in the table, one per recipient and subscription method.
I am currently left wondering:
A - how to sort the list, group the rows that correspond to the same piece of content, and then group the pieces of content per actual author.
B- how to present this to the moderator (we are back to the UI problem discussed above. Knowing better the module, salvis foresaw the problem that I figure out only now).
So, we need to make a decission as this point:
C- Either carry on in this direction (see attached files), and find a way to go through the list of items to moderate in {subscriptions_queue} in a logical manner.
D- Or, decide that everything in {subscriptions_queue} is already pre-moderated (i.e. don't add the 'moderate' field). Thus, every new piece of content that requires moderation is first entered in different table. When the moderator goes through the items in this new table (better organized for this specific purpose), the {subscriptions_queue} is populated, i.e. hours after the fact.
I've got the feeling that this would be too complicated overall...
Comment #13
salvisNo problem, I'm not leaving. :-)
I see this more like
Then subscriptions_moderation or any other interested module can implement that hook and return a 1 to put on moderation the notifications that result from any event.
The rest will be pretty much as you prepared it (except that some of the
AND moderate = 0's aren't needed).I hope to have the next beta ready on Wednesday, including these changes (unless we decide something else, see below).
'author_uid' in {subscriptions_queue} is just a copy of 'author_uid' in {subscriptions}, which is either -1 (for any author) or a uid (for author-specific subscriptions). You'll have to load the node or comment to get the author, but you need to do that anyway, don't you?
Yes, that's part of what I tried to explain in #5.
Group by load_function and load_args. That's what subscriptions_mail() does to avoid sending duplicates. I think you're interested only in the 'subscriptions_content_node_load' and 'subscriptions_content_comment_load' load functions, and their load_args is nothing but nid and cid, respectively.
I don't think it's that bad. You can create the moderation list directly from the nids and cids, or if you want to get fancy, you can group them by author uids.
So far I see no obstacles to C. Until now we only deal with normal nodes and comments that can be fully assembled with 'subscriptions_content_node_load' and 'subscriptions_content_comment_load', and I assume that subscriptions_og will continue that tradition. I'm not sure what we may see in that area in the future, but we should be able to deal with it when it gets here.
D is also a possibility; this would mean snatching and serializing the event in hook_subscriptions_moderation_queue() and feeding it back into subscriptions_queue() upon approval.
Now that I think about it, I like this even better, because you'd be able to extract and store whatever information you want, right at the source (only for the events that do need moderation, of course), and Subscriptions would not be impacted at all, i.e. not have any held rows in {subscriptions_queue}.
We might even rename the hook to just hook_subscriptions_queue() — this would open up other interesting possibilities, including feeding back altered events immediately in a recursive call.
Or we might implement a hook_subscriptions_queue_alter() and allow unsetting the event, as chx suggested in #7. This might be more in line with expected behavior in Drupal.
What do you (or anyone) think of this?
Comment #14
beginner commentedI am not sure how a hook_?_alter() would work (I still deserve my handle), so no comment on that.
What I started implementing is what's described in #6 (i.e. no use for a separate table).
If we do D (#12), then we would need a whole new table just to make some things a bit easier (sorting through the content to moderate, etc.).
So, I am not too sure on this point.
For the rest, your comments re. hook_subscriptions_queue() are good. I forgot about that bit and I'll change that in the next patch... as soon as we decide on C/D.
Comment #15
beginner commentedMaybe I can try along the same route (C), and see how difficult it is to sort through the table.
Comment #16
chx commentedAfter some thought I am siding with salvis on D. Let's do that. Less overhead for subscriptions itself.
Comment #17
salvisThe only thing special about an alter hook is that you take your parameter(s) by reference and you're allowed to change the object of interest. (It's an array in our case.) IOW, you define your hook function as
and you can change the $event as you like (as long as you don't break Subscriptions, of course). Other alter hooks might not like this, but here we specifically allow you to even set the
$event = null, and Subscriptions will just forget about it.So, you get an $event, which includes absolutely all the information that Subscriptions has (including $node and possibly $comment). If it does not need moderation, you just let it pass. Otherwise
serialize($event)into a LONGTEXT database field, along with any other information that will be useful for the moderation queue, and set$event = null.When the moderator releases the notification, then you simply call
subscriptions_queue(unserialize($event))and Subscriptions will never know what happened in between. You're completely free to implement whatever you want, and your only point of contact with the rest of Subscriptions is the $event array.Obviously, when you call subscriptions_queue() yourself, your hook will also be called again, and you should let the $event pass this time. You could for example add an element like
$event['subscriptions_moderation'] = 1, so that you can recognize the situation.The next beta release will have hook_subscriptions_queue_alter(), but you can put it in yourself and start exploring this route right away:
No other change is needed.
Comment #18
salvisThe alter hook is in BETA11.
Comment #19
salvis@beginner: Have you had a chance to look at this?
Comment #20
beginner commentedNo, I haven't. But I am working on it today. I'll upload later in the day what I have.
Comment #21
beginner commentedThanks salvis for the alter hook in the main module.
I am attempting to create a first, bare bone moderation module. I am having some problems with the form with the list of content to moderate.
I copied from comment_admin() and comment_admin_overview(), hoping to get a result similar to ?q=admin/content/comment but the form layout is a disaster in my implementation. I've been stuck on this for a couple of hours and I don't see what's fundamentally different from the comment.module.
I"ll be busy/away tomorrow and the day after. Hopefully I can finish this off Sunday.
Comment #22
salvisLurkers: Don't try to install (and especially uninstall) this!!!
The moderate_mailings_uninstall() function will destroy your Subscriptions installation!
@beginner: Maybe you want to call it something like subscriptions_moderate, to make it clear that it's a Subscriptions add-on?
Comment #23
beginner commentedOops! re. hook_uninstall()!! It's a too hasty copy/paste.
I purposefully called the module something different. I did not want to call it subscriptions_something. I work a lot from the konsole, and use command line autocompletion a lot, and it is really a pain when there are so many files with similar names at the beginning.
Comment #24
beginner commentedWhat I still don't get is at what stage the $form output by comment_admin_overview() is put into a table.
I keep banging my head on this problem.
Comment #25
salvistheme_comment_admin_overview()
Comment #26
beginner commentedOh, that's it! :) Thanks.
This is a feature of FAPI that I didn't know existed (theme_hook() called on the name of the form).
Comment #27
beginner commentedOk, the basic functionality works (thanks salvis). I still need to polish a few things which I shall do in the next couple of days.
I post what I have just in case someone can't wait to have a look. The code still needs work.
Comment #28
beginner commentedThere you are. Nothing fancy, but it works.
.info is in #21
.install is in #27
Comment #29
zilla commentedbrilliant - and delighted to see this. in an effort to make it even more user-centric and directly benefit from user activity, would it be possible to incorporate the d6 implementation of the "flag content" module such that any "flagged content" is automatically removed from any subscription output?
this would be a great way to allow active site users to police content violations (particular in school sites or youth-oriented sites) and make sure that no flagged content goes out to subscribers of a node/item until the item has been unflagged...
just a thought. turns users 'optionally' into part of the clean-up for the spam problem...
Comment #30
beginner commentedThis is not how this module works. The new content by untrusted users is put aside as soon as the content is posted. By the time the members get to flag content, the content itself has already been either queued for the subscription mailing (and it's too late to retrieve it from there), or queued for human moderation.
And this is for D5. There is no D6 version of any subscription module yet.
Comment #31
zilla commentedokay, i follow you. perhaps a feature request (for flag content - not subscriptions - would be to change usertype if flagged, basically revert the person to 'untrusted' until a flagged item is unflagged)
as for d6, just saw this: http://ftp.drupal.org/files/projects/subscriptions-6.x-1.x-dev.tar.gz (direct link - or go to modules, filter by d6)
Comment #32
salvisI'm sorry about the confusion re: 6.x-1.x-dev. I was educated in http://drupal.org/node/231966 that the MAIN releases are supposed to be converted to -dev nodes and I needed this done for some other modules and thought it would be a good occasion to have subscriptions-MAIN converted, too, not realizing that this would change the versions tags here on the site...
There is no D6 version anywhere yet, not even on my local disk. Please ignore 6.x-1.x-dev, it's the same as the latest BETA for Drupal 5!
Comment #33
zilla commentedthanks salvis - i almost put it up and likely woulda been bombarding the support forums if it bugged! you may want to add that note above to the project page because when it showed up yesterday, probably tons of people downloaded it...
Comment #34
salvis@beginner: Thank you for your work! I'm sorry this 6.x mess erupted in your thread...
I haven't had time to take a look yet, but I will. However, moderate_mailings.install.txt is still unchanged.
Lurkers: Don't try to install this yet — #27 will still trash Subscriptions when you uninstall it!!!
Comment #35
beginner commentedOops! Very sorry about that. You told me already. Here the updated .install.
Comment #36
beginner commentedoops again. Wrong file.
Comment #37
beginner commentedcase 'pgsql' remains to be done. I'll do it after review if there is no objection to the DB schema.
Comment #38
beginner commentedSince we are still in beta releases, I hope this can be included in beta12, so that more users can test it. I'll follow up all bug reports (if any) with patches.
Also, it would be nice if you could update the component list, so that each module has its own component. Thus it will be easier for me to follow up on all issues related to this new module.
Comment #39
chx commentedFirst of all, let's decide whether it's a generic or a content-only solution. Never forget that subscription is a generic framework, you might subscribe to private messages for example. This solution is currently content focused.
Second, all this fiddling with roles is not necessary. You provide a permission , check the permission with user_access and that's it. Let core handle the rest.
Comment #40
zilla commentedi also agree (with #39 right above) - seems that moderation should be a separate module and could possibly grow to support other areas of notification (like other site messaging tools, notifications etc)...or maybe i'm missing something...perhaps include with subscriptions project page as 'suggested other modules: moderate mailings' so that people will clearly see it, but then on moderate mailings list specific dependencies and so on...that way people can isolate the workflow around moderation and hammer it out independent of larger 'subscriptions' module issues.
Comment #41
beginner commented@chx: If you had any objection about what I was trying to achieve with this module, you could have said so before I coded the bloody thing. The module does exactly what I set out to do, which I discussed and explained at length earlier in the thread.
About the roles and permission, see the earlier comments, and read the code.
Also, I fully took into consideration all the comments you made earlier and already changed the whole module accordingly.
Besides, a hook alter is already part of the main module: the idea was that any kind of module would be able to be plugged in and implement their own moderation strategy. This module is only the first one implementing this hook.
Again, the module does exactly what it was supposed to do.
@zilla: please read the whole thread. If you have another idea in mind, it is perfectly ok if you open a new feature request where you can provide your own patch. Please don't hijack this issue.
Comment #42
chx commentedI thought I have valid concerns -- I am not against this "bloody" thing, I just would like to see a few things fixed. I have re-read the code and the user-role is fine, after all, sorry -- you do check the permission with user_access as I asked where it's appropriate. On the same line, we have
empty($event['moderate_mailings_done']how is this supposed to work...? Who fills this key?Next up, this is minor but you can see in for eg. watchdog that we use auto_increment / serial instead of db_next_id when we do not care about the value of the id. Speaking of serial, a postgresql install would be nice.
After you unserialize, you are using content instead of data, $content['node'] ought to be $data->node, $content['comment'] ought to be $data->comment.
There is concern that still stands: subscriptions is a generic framework, you might subscribe to private messages for example. This solution is currently content focused. It is fine that it only deals with content, we have subscriptions_content.module too. But, then this module needs to be renamed and some sorts of checking added so it won't try to process anything but content.
Thanks for the hard work.
Comment #43
beginner commented@chx: thanks for your feedback. I completely misread your comment in #39. Apparently Zilla did, too, in #40, which didn't help. I thought you were speaking about a complete change of direction for this module, proposing to do something other, "more generic" than what was previously explained and, I though, agreed earlier in the thread. So, apparently, I misunderstood what you meant.
$event['moderate_mailings_done'] is set by this module for the reason correctly foreseen by salvis in #17.
About renaming the module, I am open to suggestions: any name that does not start with s.
This module targets only content, not private messages or anything else (at the very least not at the beginning). I am not too sure what check would be necessary to process any other content than the one targeted. Suggestions?
I'll update the module to take into account the other minor stuff your mention.
Comment #44
beginner commentedchanges done:
* removed db_next_id, using auto_increment.
* did pgsql.
* $content['node'] ought to be $data->node : very good catch, thanks. fixed.
I am not against extending this module to moderate private messages, too, but I fail to see how one could subscribe to PMs. Also, from a privacy point of view, it is trickier to ask moderators to read other people's PM... I don't have a good mental image of what could be done more, compared to moderating the content as I already do here.
Maybe this can be committed more or less as is, and follow up in a new issue, to see if it's feasible to extend the module.
Also, should this module only moderate normal content (nodes and comments), I am not sure what check to add so that it doesn't catch any other content. The check would go in moderate_mailings_subscriptions_queue_alter(&$event).
Currently, we have:
Am I supposed to put something like this?
Comment #45
salvisThank you for the fixes and for all your work.
I think limiting the module to content (nodes and comments) is just fine at this point, but I'll let chx answer the question on the best method to differentiate content from other subscription items.
It's hard to come up with an appropriate name — at first I thought, "Subscriptions" needed to be part of the name, but maybe not. I keep coming back to moderate_content_mailings ("Content Mail Moderation"). chx?
Is there a reason for not using l() in moderate_mailings_admin_settings_form()? The link is wrong.
Please add the dependency on subscriptions_content to the info file.
Comment #46
beginner commentedmailing_content_moderation.module ?
moderate_mailing_content.module ?
in moderate_mailings_admin_settings_form(), we cannot use l() because the link is part of a longer string. But I forgot to use url(). Fixed, thanks.
.info file updated.
I also added a check in moderate_mailings_admin_settings_form() to make sure that the roles listed in the form have the proper perm (trusted not to spam). If no role have this perm, a warning is displayed.
Comment #47
salvisWhat's wrong with l()? I'm using it on admin/settings/subscriptions, and it works just fine.
Comment #48
beginner commentedThe problem is with translation. Using url() gives more flexibility to the translators. I was told this was the way to insert a link in a long string.
Comment #49
chx commentedWhat this module does? Moderates content mailings. Hence, moderate_content_mailing. That one is good. Checking for node/comment, just check whether $event['node'] exists.
Comment #50
beginner commentedOk. Name changed, check added.
Comment #51
salvisOne more thought — sorry this comes in pieces...
The menu item keeps bothering me a bit:
# ...
# Site information
# Site maintenance
# Subscriptions
# Subscriptions (spam deterrent moderation)
This is only used once in the entire lifetime of the site and it takes up a lot of menu real estate. Could it either become a submenu item under "Subscriptions" or a subtab on admin/settings/subscriptions? As long as we don't have any other add-ins competing for the same name, I'd be fine with having a subtab "Moderation" with a heavy weight.
However, this would mean changing the admin/settings/moderate_mailings path to admin/settings/subscriptions/moderation.
Comment #52
salvisAh, you've changed the menu item in #50, but it's even longer now:
# Moderate content mailing (spam deterrent moderation)
It takes four lines now. I don't think we can do that...
Here's a grammar question: my strings use the term "subscriptions notifications" (= multiple mailings caused by multiple subscriptions, two times plural form). You use "subscription mailings" — should the first word be plural or singular?
At this point, Subscriptions only supports mail as medium, but the design is such that subscriptions_mail.module could be replaced by some other module. That's why I'm using "notifications" rather than "mailings," and your module is independent of subscriptions_mail, so it should follow the same terminology.
This means the module should be renamed again, to moderate_content_notifications. I realize that you've only just renamed it and I should have noticed that before, so I'll do the renaming for you...
Comment #53
salvisHere are the resulting files. We're planning to release RC1 tomorrow evening (European time) — let me know before then if you need any last-minute changes.
Comment #54
beginner commentedHi, Thanks for updating the module, and correcting the grammar and stuff...
About the setting page, I can't find it anymore, neither on the main admin panel, nor in the subscriptions setting page.
You argue that it is only used once in the entire lifetime of the site. Frankly, most of the elements in the Settings section are only used once. How often do you enable/disable clean urls? How often do you modify the Time and Date settings? What about most of the others? ;) So the argument is not valid.
Having said that, I don't mind having it in a tab if that's what you prefer... as long as it exists:
The title is a bit long to use in a tab title. In this context, I think "Spam deterrent settings" should be enough.
It is much shorter and also explicit.
Comment #55
beginner commented... Thinking about it a bit more, I personally still prefer to have the link to the setting page on the main admin panel. First, as I said, the argument about how often we need to access the setting page is not valid. That's why all the setting pages of most modules are grouped in the same section which is listed last. Once the web site set, the whole Settings section can be ignored.
The advantage of having the link on the main panel, is that it's much easier to find once the module is enabled. Too often, after enabling a module, I am left clicking around trying to find what setting pages there are. Why let the user have to guess where the setting page is... or whether there is any...?
But I won't insist further and let you take the final decision. At the end, I am happy either way. It's a fairly minor detail after all! :)
Comment #56
salvisYou can find it
The links you mention are one-time-use indeed, but they're part of Drupal core and thus privileged. We want people who install Drupal for the first time to find all the Site configuration pages, and in a logical sequence.
However, I don't think us lowly contrib developers are supposed to litter the menu with monster entries...
Comment #57
salvismoderate_content_notifications is included in RC1. Thank you, beginner!
I'd still like to get some feedback, if possible...
Comment #58
salvisOk, 2.0 is out and moderate_content_notifications along with it.
@beginner: Please keep an eye on the moderate_content_notifications subqueue.
Thanks again!
Comment #59
beginner commentedThanks.
ok, but I'm not subscribed to all issues. Contact me if a bug comes along...
Comment #60
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.