// Check for clicks vs votes // to avoid "cowboy votes" without reading the article if ($globals['click_counter'] && !$link->user_clicked()) { if ($link->votes > 3 && $link->negatives > 2 && $current_user->user_id > 0 && $link->votes / 10 < $link->negatives && $link->get_clicks() < $link->total_votes * 1.5) { error(_('enlace no leído, con muchos negativos')); } elseif ((empty($_GET['l']) || $_GET['l'] != $link->id) && $link->total_votes > $link->get_clicks()) { // Don't allow to vote if it has less clicks than votes error(_('no leído, y con más votos que lecturas') . ' (' . $link->get_clicks() . ' < ' . $link->total_votes . ')'); } } if ($votes_freq > $freq) { if ($current_user->user_id > 0 && $current_user->user_karma > 4 && $link->status != 'published') { // Crazy votes attack, decrease karma // she does not deserve it :-) $user = new User($current_user->user_id); $user->add_karma(-0.2, _('voto cowboy')); error(_('¡tranquilo cowboy!') . ', ' . _('tu karma ha bajado: ') . $user->karma); } else { error(_('¡tranquilo cowboy!')); } } if ($current_user->user_id > 0) { $value = $current_user->user_karma; } else { $value = $globals['anon_karma']; } if (!$link->insert_vote($value)) { if ($current_user->user_id > 0) { error(_('ya se votó antes con el mismo usuario o IP')); } else { error(_('ya se votó antes desde la misma IP'));
function depublish($site_id) { // send back to queue links with too many negatives global $db, $globals; $days = 4; echo "STARTING depublish for {$site_id}\n"; $site_info = SitesMgr::get_info($site_id); $links = $db->get_col("select SQL_NO_CACHE link_id as id from links, sub_statuses where id = {$site_id} and status = 'published' and date > date_sub(now(), interval {$days} day) and date < date_sub(now(), interval 14 minute) and link = link_id and link_negatives > link_votes / 5"); if ($links) { $votes_clicks = $db->get_col("select SQL_NO_CACHE link_votes/counter from links, sub_statuses, link_clicks where sub_statuses.id = {$site_id} and status = 'published' and date > date_sub(now(), interval {$days} day) and link = link_id and link_clicks.id = link"); sort($votes_clicks); foreach ($links as $link) { $l = Link::from_db($link); $vc = $l->votes / $l->clicks; $prob = cdf($votes_clicks, $vc); // Count only those votes with karma > 6 to avoid abuses with new accounts with new accounts $negatives = (int) $db->get_var("select SQL_NO_CACHE sum(user_karma) from votes, users where vote_type='links' and vote_link_id={$l->id} and vote_date > from_unixtime({$l->date}) and vote_date > date_sub(now(), interval 24 hour) and vote_value < 0 and vote_user_id > 0 and user_id = vote_user_id and user_karma > " . $globals['depublish_negative_karma']); $positives = (int) $db->get_var("select SQL_NO_CACHE sum(user_karma) from votes, users where vote_type='links' and vote_link_id={$l->id} and vote_date > from_unixtime({$l->date}) and vote_value > 0 and vote_date > date_sub(now(), interval 24 hour) and vote_user_id > 0 and user_id = vote_user_id and user_karma > " . $globals['depublish_positive_karma']); echo "Candidate {$l->uri}\n karma: {$l->sub_karma} ({$l->karma}) negative karma: {$negatives} positive karma: {$positives}\n"; // Adjust positives to the probability of votes/clicks $c = 1 + (1 - $prob) * 0.5; $positives = $positives * $c; echo " probability: {$prob} New positives: {$positives} ({$c})\n"; if ($negatives > 10 && $negatives > $c * $l->sub_karma / 6 && $l->negatives > $c * $l->votes / 6 && $l->negatives > 5 && ($negatives > $positives || $negatives > $c * $l->sub_karma / 2 && $negatives > $positives / 2)) { echo "Queued again: {$l->id} negative karma: {$negatives} positive karma: {$positives}\n"; $karma_old = $l->sub_karma; $karma_new = intval($l->sub_karma / $globals['depublish_karma_divisor']); $l->status = 'queued'; $l->sub_karma = $l->karma = $karma_new; $db->query("update links set link_status='queued', link_date = link_sent_date, link_karma={$karma_new} where link_id = {$l->id}"); SitesMgr::deploy($l); // Add an annotation to show it in the logs $l->karma_old = $karma_old; $l->karma = $karma_new; $l->annotation = _('Retirada de portada'); $l->save_annotation('link-karma'); Log::insert('link_depublished', $l->id, $l->author); if (!$site_info->sub) { // Add the discard to log/event $user = new User($l->author); if ($user->read) { echo "{$user->username}: {$user->karma}\n"; $user->add_karma(-$globals['instant_karma_per_depublished'], _('Retirada de portada')); } // Increase karma to users that voted negative $ids = $db->get_col("select vote_user_id from votes where vote_type = 'links' and vote_link_id = {$l->id} and vote_user_id > 0 and vote_value < 0"); foreach ($ids as $id) { $u = new User($id); if ($u->read) { // Avoid abuse of users voting negative just to get more karma $voted = $db->get_var("select count(*) from logs where log_type = 'user_depublished_vote' and log_user_id = {$id} and log_date > date_sub(now(), interval 48 hour)"); if ($voted < 5) { $u->add_karma(0.2, _('Negativo a retirada de portada')); Log::insert('user_depublished_vote', $l->id, $id); } } } } /*********** * TODO: call for every site (as in promote) if ($globals['twitter_token'] || $globals['jaiku_user']) { if ($globals['url_shortener']) { $short_url = $l->get_short_permalink(); } else { $short_url = fon_gs($l->get_permalink()); } $text = _('Retirada de portada') . ': ' . $l->title; if ($globals['twitter_user'] && $globals['twitter_token']) { twitter_post($text, $short_url); } if ($globals['jaiku_user'] && $globals['jaiku_key']) { jaiku_post($text, $short_url); } } *******/ } } } }
function publish($link) { global $globals, $db; //return; if (DEBUG) { return; } // Calculate votes average // it's used to calculate and check future averages $votes_avg = (double) $db->get_var("select SQL_NO_CACHE avg(vote_value) from votes, users where vote_type='links' AND vote_link_id={$link->id} and vote_user_id > 0 and vote_value > 0 and vote_user_id = user_id and user_level !='disabled'"); if ($votes_avg < $globals['users_karma_avg']) { $link->votes_avg = max($votes_avg, $globals['users_karma_avg'] * 0.97); } else { $link->votes_avg = $votes_avg; } $link->status = 'published'; $link->date = $link->published_date = time(); $db->query("update links set link_status='published', link_date=now(), link_votes_avg={$link->votes_avg} where link_id={$link->id}"); SitesMgr::deploy($link); // Increase user's karma $user = new User($link->author); if ($user->read) { $user->add_karma($globals['instant_karma_per_published'], _('noticia publicada')); } // Add the publish event/log Log::insert('link_publish', $link->id, $link->author); $link->annotation .= _('publicación') . "<br/>"; $link->save_annotation('link-karma'); // Publish to all sub sites: this and children who import the link category $my_id = SitesMgr::my_id(); // Get all sites that are "children" and try to post links // And that "import" the link->category $sites = array_intersect(SitesMgr::get_children($my_id), SitesMgr::get_receivers($link->category)); // Add my own $sites[] = $my_id; foreach ($sites as $s) { $server_name = SitesMgr::get_info($s)->server_name; syslog(LOG_INFO, "Meneame, calling: " . dirname(__FILE__) . "/post_link.php {$server_name} {$link->id}"); passthru(dirname(__FILE__) . "/post_link.php {$server_name} {$link->id}"); } }
static function save_from_post($link, $redirect = true) { global $db, $current_user, $globals; require_once mnminclude . 'ban.php'; if (check_ban_proxy()) { return _('dirección IP no permitida'); } // Check if is a POST of a comment if (!($link->votes > 0 && $link->date > $globals['now'] - $globals['time_enabled_comments'] * 1.01 && $link->comments < $globals['max_comments'] && intval($_POST['link_id']) == $link->id && $current_user->authenticated && intval($_POST['user_id']) == $current_user->user_id && intval($_POST['randkey']) > 0)) { return _('comentario o usuario incorrecto'); } if ($current_user->user_karma < $globals['min_karma_for_comments'] && $current_user->user_id != $link->author) { return _('karma demasiado bajo'); } $comment = new Comment(); $comment->link = $link->id; $comment->ip = $globals['user_ip']; $comment->randkey = intval($_POST['randkey']); $comment->author = intval($_POST['user_id']); $comment->karma = round($current_user->user_karma); $comment->content = clean_text_with_tags($_POST['comment_content'], 0, false, 10000); // Check if is an admin comment if ($current_user->user_level == 'god' && $_POST['type'] == 'admin') { $comment->type = 'admin'; } // Don't allow to comment with a clone $hours = intval($globals['user_comments_clon_interval']); if ($hours > 0) { $clones = $current_user->get_clones($hours + 1); if ($clones) { $l = implode(',', $clones); $c = (int) $db->get_var("select count(*) from comments where comment_date > date_sub(now(), interval {$hours} hour) and comment_user_id in ({$l})"); if ($c > 0) { syslog(LOG_NOTICE, "Meneame, clon comment ({$current_user->user_login}, {$comment->ip}) in {$link->uri}"); return _('ya hizo un comentario con usuarios clones'); } } } // Basic check to avoid abuses from same IP if (!$current_user->admin && $current_user->user_karma < 6.2) { // Don't check in case of admin comments or higher karma // Avoid astroturfing from the same link's author if ($link->status != 'published' && $link->ip == $globals['user_ip'] && $link->author != $comment->author) { UserAuth::insert_clon($comment->author, $link->author, $link->ip); syslog(LOG_NOTICE, "Meneame, comment-link astroturfing ({$current_user->user_login}, {$link->ip}): " . $link->get_permalink()); return _('no se puede comentar desde la misma IP del autor del envío'); } // Avoid floods with clones from the same IP if (intval($db->get_var("select count(*) from comments where comment_link_id = {$link->id} and comment_ip='{$comment->ip}' and comment_user_id != {$comment->author}")) > 1) { syslog(LOG_NOTICE, "Meneame, comment astroturfing ({$current_user->user_login}, {$comment->ip})"); return _('demasiados comentarios desde la misma IP con usuarios diferentes'); } } if (mb_strlen($comment->content) < 5 || !preg_match('/[a-zA-Z:-]/', $_POST['comment_content'])) { // Check there are at least a valid char return _('texto muy breve o caracteres no válidos'); } if (!$current_user->admin) { $comment->get_links(); if ($comment->banned && $current_user->Date() > $globals['now'] - 86400) { syslog(LOG_NOTICE, "Meneame: comment not inserted, banned link ({$current_user->user_login})"); return _('comentario no insertado, enlace a sitio deshabilitado (y usuario reciente)'); } // Lower karma to comments' spammers $comment_count = (int) $db->get_var("select count(*) from comments where comment_user_id = {$current_user->user_id} and comment_date > date_sub(now(), interval 3 minute)"); // Check the text is not the same $same_count = $comment->same_text_count(); $same_links_count = $comment->same_links_count(); if ($comment->banned) { $same_links_count *= 2; } $same_count += $same_links_count; } else { $comment_count = $same_count = 0; } $comment_limit = round(min($current_user->user_karma / 6, 2) * 2.5); $karma_penalty = 0; if ($comment_count > $comment_limit || $same_count > 2) { if ($comment_count > $comment_limit) { $karma_penalty += ($comment_count - 3) * 0.1; } if ($same_count > 1) { $karma_penalty += $same_count * 0.25; } } // Check image limits if (!empty($_FILES['image']['tmp_name'])) { $limit_exceded = Upload::current_user_limit_exceded($_FILES['image']['size']); if ($limit_exceded) { return $limit_exceded; } } $db->transaction(); // Check the comment wasn't already stored $r = intval($db->get_var("select count(*) from comments where comment_link_id = {$comment->link} and comment_user_id = {$comment->author} and comment_randkey = {$comment->randkey} FOR UPDATE")); $already_stored = intval($r); if ($already_stored) { $db->rollback(); return _('comentario duplicado'); } if ($karma_penalty > 0) { $db->rollback(); $user = new User($current_user->user_id); $user->add_karma(-$karma_penalty, _('texto repetido o abuso de enlaces en comentarios')); return _('penalización de karma por texto repetido o abuso de enlaces'); } if (!is_null($r) && $comment->store()) { $comment->insert_vote(); $link->update_comments(); $db->commit(); // Check image upload or delete if ($_POST['image_delete']) { $comment->delete_image(); } else { $comment->store_image_from_form('image'); } if ($redirect) { // Comment stored, just redirect to it page header('HTTP/1.1 303 Load'); header('Location: ' . $link->get_permalink() . '/c0' . $comment->order . '#c-' . $comment->order); die; } else { return $comment; } } $db->rollback(); return _('error insertando comentario'); //return $error; }
#! /usr/bin/env php <?php include dirname(__FILE__) . '/../www/config.php'; if (count($argv) != 4) { print_usage(); } $sdk = (double) $argv[2]; if ($sdk <= 0 || $sdk > 20) { print_usage("karma should be > 0 and < 20"); } $mess = $db->escape($argv[3]); if (empty($mess) || mb_strlen($mess) < 6) { print_usage("message is empty or too short"); } $user = new User(); $user->username = $argv[1]; if (!$user->read()) { print_usage('User not found'); } echo "karma: {$user->karma} "; $user->add_karma(-$sdk, $mess); $user->read(); echo "-> {$user->karma}\n"; function print_usage($mess = false) { if ($mess) { echo "Error: {$mess}\n"; } echo 'Usage: ' . basename(__FILE__) . ' username karma_to_discount message' . "\n"; die; }
function save_post($post_id) { global $link, $db, $post, $current_user, $globals, $site_key; $post = new Post(); $_POST['post'] = clean_text_with_tags($_POST['post'], 0, false, $globals['posts_len']); if (!empty($_FILES['image']['tmp_name'])) { $limit_exceded = Upload::current_user_limit_exceded($_FILES['image']['size']); if ($limit_exceded) { echo 'ERROR: ' . $limit_exceded; die; } } if (mb_strlen($_POST['post']) < 5) { echo 'ERROR: ' . _('texto muy corto'); die; } if ($post_id > 0) { $post->id = $post_id; if (!$post->read()) { die; } if ((intval($_POST['user_id']) == $current_user->user_id && $current_user->user_id == $post->author && time() - $post->date < 3600 || $current_user->user_level == 'god' && time() - $post->date < $globals['posts_edit_time_admin'] * 1.5) && $_POST['key'] == $post->randkey) { $post->content = $_POST['post']; if (strlen($post->content) > 0) { $post->store(); store_image($post); } } else { echo 'ERROR: ' . _('no tiene permisos para grabar'); die; } } else { if ($current_user->user_id != intval($_POST['user_id'])) { die; } if ($current_user->user_karma < $globals['min_karma_for_posts']) { echo 'ERROR: ' . _('el karma es muy bajo'); die; } // Check the post wasn't already stored $post->randkey = intval($_POST['key']); $post->author = $current_user->user_id; $post->content = $_POST['post']; // Verify that there are a period of 1 minute between posts. if (intval($db->get_var("select count(*) from posts where post_user_id = {$current_user->user_id} and post_date > date_sub(now(), interval " . $globals['posts_period'] . " second)")) > 0) { echo 'ERROR: ' . _('debe esperar entre notas'); die; } $same_text = $post->same_text_count(); $same_links = $post->same_links_count(10); $db->transaction(); $r = $db->get_var("select count(*) from posts where post_user_id = {$current_user->user_id} and post_date > date_sub(now(), interval 5 minute) and post_randkey = {$post->randkey} FOR UPDATE"); $dupe = intval($r); if (!is_null($r) && !$dupe && !$same_text) { if ($same_links > 2) { $reduction = $same_links * 0.2; $user = new User($current_user->user_id); $user->add_karma(-$reduction, _('demasiados enlaces al mismo dominio en las notas')); syslog(LOG_NOTICE, "Meneame: post_edit decreasing {$reduction} of karma to {$user->username} (now {$user->karma})"); } $post->store(); $db->commit(); store_image($post); } else { $db->commit(); echo 'ERROR: ' . _('comentario grabado previamente'); die; } } $post->print_summary(); }
if (UserAuth::check_clon_votes($current_user->user_id, $id, 5, 'comments') > 0) { error(_('no se puede votar con clones')); } if ($value > 0) { $votes_freq = intval($db->get_var("select count(*) from votes where vote_type='comments' and vote_user_id={$current_user->user_id} and vote_date > subtime(now(), '0:0:30') and vote_value > 0 and vote_ip_int = " . $globals['user_ip_int'])); $freq = 10; } else { $votes_freq = intval($db->get_var("select count(*) from votes where vote_type='comments' and vote_user_id={$current_user->user_id} and vote_date > subtime(now(), '0:0:30') and vote_value <= 0 and vote_ip_int = " . $globals['user_ip_int'])); $freq = 5; } if ($votes_freq > $freq) { if ($current_user->user_id > 0 && $current_user->user_karma > 4) { // Crazy votes attack, decrease karma // she does not deserve it :-) $user = new User($current_user->user_id); $user->add_karma(-0.2, _('Voto cowboy a comentarios')); error(_('¡tranquilo cowboy!, tu karma ha bajado: ') . $user->karma); } else { error(_('¡tranquilo cowboy!')); } } $value = round($value * $current_user->user_karma); if (!$comment->insert_vote($value)) { error(_('ya se votó antes con el mismo usuario o IP')); } $comment->votes++; $comment->karma += $value; $dict = array(); $dict['id'] = $id; $dict['votes'] = $comment->votes; $dict['value'] = $value;
error(_('ya no se puede votar negativo')); } $votes_freq = $db->get_var("select count(*) from votes where vote_type='links' and vote_user_id={$current_user->user_id} and vote_date > subtime(now(), '0:0:30')"); if ($current_user->user_id > 0) { if ($current_user->admin) { $freq = 5; } else { $freq = 2; } } else { $freq = 2; } if ($votes_freq > $freq && $current_user->user_karma > 4) { // Typical "negative votes" attack, decrease karma $user = new User($current_user->user_id); $user->add_karma(-1.0, _('Voto cowboy negativo')); error(_('¡tranquilo cowboy!, tu karma ha bajado: ') . $user->karma); } // Check the user is not a clon by cookie of others that voted the same link if ($current_user->user_id > 0) { if (UserAuth::check_clon_votes($current_user->user_id, $link->id, 5, 'links') > 0) { error(_('no se puede votar con clones')); } } if (!$link->insert_vote($value)) { error(_('ya se votó antes con el mismo usuario o IP')); } echo $link->json_votes_info(intval($value)); function error($mess) { $dict['error'] = $mess;
function publish($site, $link) { global $globals, $db; $site_info = SitesMgr::get_info($site); if (DEBUG) { return; } // Calculate votes average // it's used to calculate and check future averages $votes_avg = (double) $db->get_var("select SQL_NO_CACHE avg(vote_value) from votes, users where vote_type='links' AND vote_link_id={$link->id} and vote_user_id > 0 and vote_value > 0 and vote_user_id = user_id and user_level !='disabled'"); if ($votes_avg < $globals['users_karma_avg']) { $link->votes_avg = max($votes_avg, $globals['users_karma_avg'] * 0.97); } else { $link->votes_avg = $votes_avg; } $link->status = 'published'; $link->date = $link->published_date = time(); $db->transaction(); $db->query("update links set link_status='published', link_date=now(), link_votes_avg={$link->votes_avg} where link_id={$link->id}"); SitesMgr::deploy($link); $db->commit(); // Increase user's karma $user = new User($link->author); if ($site_info->sub) { $karma_bonus = $globals['instant_karma_per_published'] / 10; // currently these published don't receive extra karma $log = false; } else { $karma_bonus = $globals['instant_karma_per_published']; $log = _('noticia publicada'); } if ($user->read) { $user->add_karma($karma_bonus, $log); } // Add the publish event/log Log::insert('link_publish', $link->id, $link->author); $link->annotation .= _('publicación') . "<br/>"; $link->save_annotation('link-karma'); // read twitter and facebok configuration from subs' extended info if (!$site_info->sub || $site_info->visible) { // Only post if it's not a sub or it's visible (dmnm in mnm, f.e.) syslog(LOG_INFO, "Meneame, calling: " . dirname(__FILE__) . "/post_link.php {$site_info->name} {$link->id}"); passthru(dirname(__FILE__) . "/post_link.php {$site_info->name} {$link->id} published"); } // Publish the links of the source subs if ($site_info->meta && ($senders = SitesMgr::get_senders($site))) { if (in_array($link->sub_id, $senders) && $link->sub_status_origen == 'queued') { syslog(LOG_INFO, "Meneame, publishing for sender {$link->sub_name} ({$link->sub_id})"); // "Simulate" the other site, needed for deploy SitesMgr::__init($link->sub_id); publish($link->sub_id, $link); SitesMgr::__init($site); // Back to the original site } } return; }