I have a comment section and a reply to comment section on my social network. We are having some trouble with manual spammers, and I was going to limit the amount of comments someone could post a day.
Here are the insert queries for comments and reply to comments:
//COMMENTS
$query = "INSERT INTO `CysticAirwaves` (
`FromUserID`,
`ToUserID`,
`comment`,
`status`,
`statusCommentAirwave`,
`date`,
`time`
) VALUES (
'" . $auth->id ."',
'" . $prof->id ."',
'" . mysql_real_escape_string($_POST['ProfileComment']) ."',
'active',
'active',
'" . date("Y-m-d") . "',
'" . date("G:i:s") . "')";
mysql_query($query,$connection);
if($auth->id == $prof->id) {
$just_inserted = mysql_insert_id();
$query = "UPDATE `CysticAirwaves` SET `status` = 'dead' WHERE `FromUserID` = '" . $auth->id . "' AND `ToUserID` = '" . $prof->id . "' AND `id` != '" . $just_inserted . "'";
$request = mysql_query($query,$connection);
}
//REPLIES
$query = "INSERT INTO `CysticAirwaves_replies` (
`AirwaveID`,
`FromUserID`,
`comment`,
`status`,
`date`,
`time`
) VALUES (
'" . mysql_real_escape_string($_POST['comment']) . "',
'" . $auth->id . "',
'" . mysql_real_escape_string($_POST['reply']) . "',
'active',
'" . date("Y-m-d") . "',
'" . date("G:i:s") . "'
)";
mysql_query($query,$connection);
$mailto = array();
/* get the person that wrote the inital comment */
$query = "SELECT `FromUserID` FROM `CysticAirwaves` WHERE `id` = '" . mysql_real_escape_string($_POST['comment']) . "' LIMIT 1";
$request = mysql_query($query,$connection);
$result = mysql_fetch_array($request);
$comment_author = new User($result['FromUserID']);
thanks in advance
You can perform a select to see how many entries are in the table already by that user for the current date:
SELECT COUNT(*)
FROM CysticAirwaves
WHERE userid = $auth->id
AND date = CURDATE()
Then only perform the INSERT
if the number is below your threshold. Alternatively, you can place a trigger on the INSERT
that does this check with every INSERT
and bounces the call as well. ("Best practice" would be to place it in the database as this would be a database-related limitation, but that's your call)
It's been a while since I've done MySQL triggers, but I think think is what you're after:
delimeter |
CREATE TRIGGER reply_threshold BEFORE INSERT ON CysticAirwaves_replies
FOR EACH ROW BEGIN
DECLARE reply_count INT;
SET reply_count = (SELECT COUNT(*) FROM CysticAirwaves_replies WHERE userid = NEW.userid AND `date` = CURDATE());
IF reply_count > 5 THEN
SIGNAL SQLSTATE SET MESSAGE_TEXT = 'Too many replies for today';
END IF;
END;
|
delimeter ;
Essentially, if you go to insert a reply in the table and the threshold has been exceeded, a sql error will be raised stopping the action. You can't "prevent" an insert per-say, but you can raise an exception that makes it fall-through.
You can only limit this by the ip address when you don't have a login system. But the ip can change and this is here the problem.
The best way is to secure the form by a login. That only user can post when they are logged in.
Last technique is to use a captcha like Recaptcha then at most time bots fill out your form and spam to your system.
When you have a login. Then make a table related to your usertable and count the INSERTS. Before you INSERT a new comment check the table if there was a INSERT today.
Before to insert the comment, you check if the user has posted more than 5 comments in the day. If yes, you don't insert the comment and you display a message.
SELECT COUNT(*) FROM CysticAirwaves_replies WHERE FromUserID = the_user_id AND date = CURDATE()
Besides counting before each insertion, you can store the number of comments made by an user somewhere directly, so you don't have to do the count(*) every time (which can be expensive if an user has lots of comments and the table you have is somewhat big).
Like, on commenting:
SELECT comment_count FROM comment_count_table WHERE user_id = ?
If that value is small enough, you do:
UPDATE comment_count_table SET comment_count = comment_count + 1 WHERE user_id = ?
Be careful with this since you'd need to reset that counter somehow. At my company we implemented this setting a "last modified field". When we do the SELECT, if the "last modified day" is not today, then we reset the counter.
Another option is to have a cron job that resets the counter for all users once every day, but that is way too expensive.