Задача в общих чертах: создать раздел с конкурсом, разбитый по регионам, с возможностью добавления работ зарегистрированными участниками, голосованием раз в сутки за каждую работу и подсчетом рейтинга, защитой голосования от накруток, комментированием работ, автоматическим определением финалистов каждую неделю. Теперь по подробней
Механизм голосования: каждый пользователь, как зарегистрированный, так и анонимный, может проголосовать за каждую работу не более одного раза в сутки, поставив баллы от 1 до 5. Рейтинг рассчитывается суммированием баллов. Отключение голосования за работы финалистов. [spoiler] Для оценки работ пользователями, использовались элементы, за которым в php скрывалось:
Функция select_star – отвечает за подмену изображения звездочки, с пустой на закрашенную при наведении мышки. Хотелось бы осуществлять это с помощью CSS и hover, но требуется подкрашивать все предшествующие звездочки, а не только ту, на которой мышка. Данная функция легким нажатием ctrl+c ctrl+v, была позаимствована из bitrix:iblock.vote.
Функция send_vote, вызываемая по нажатию на звездочке:
function send_vote(div){
$.jGrowl.defaults.closerTemplate = '<div>Закрыть все оповещения</div>';
$.jGrowl.defaults.position = 'center';
var r = div.id.match(/^vote_(\d+)_(\d+)$/);
var id = r[1];
var vote = r[2];
var status = getCookie("v"+id);
if (status != "y"){
var send_url = "/contests/vote.php/?VOTE="+vote+"&ID_VOTE="+id;
$.ajax({
type: "GET",
url: send_url,
dataType: "html",
success: function(out){
if(out.length < 5){
var votes = $('#wait_vote_'+id).html();
votes = (votes*1 + vote*1);
$('#wait_vote_'+id).html(votes);
var ws=new Date();
ws.setDate(1+ws.getDate());
document.cookie="v"+id+"=y; path=/; expires="+ ws.toGMTString();
$.jGrowl("Ваш голос принят");
}
else{
$.jGrowl(out);
}
}
});
}
else{
$.jGrowl("Сегодня с Вашего адреса уже голосовали");
}
}
Выполняет проверку установленных куков с помощью функции getCookie (код ниже), чтобы лишний раз не гонять запрос на сервер, если голосующий честен и не пытается мухлевать.
function getCookie(name) {
var cookie = " " + document.cookie;
var search = " " + name + "=";
var setStr = null;
var offset = 0;
var end = 0;
if (cookie.length > 0) {
offset = cookie.indexOf(search);
if (offset != -1) {
offset += search.length;
end = cookie.indexOf(";", offset)
if (end == -1) {
end = cookie.length;
}
setStr = unescape(cookie.substring(offset, end));
}
}
return(setStr);
}
Не смог удержаться, от использования jGrowl, для вывода приятных всплывающих окошек, с оповещением пользователя о результате его действий. Если пользователь еще не голосовал, или очистил куки, или еще чего, то с помощью функции jquery $.ajax , отправляем запрос к php скрипту, который еще раз проверит чистоту намерений и учтет голос Как видно из приведенного выше кода, в vote.php мы имеем в массиве $_GET элементы “VOTE” – поставленный балл и “ID_VOTE” – идентификатор работы. Так, как нам не требуется отображение страницы, но требуется API Битрикса, vote.php начинается с
Где 1839 - финальная работа, 1865 – не финальная, но принадлежащая финалисту. Если проверка пройдена, то считываем всех проголосовавших за данную работу:
Тут стоит отметить, что в качестве идентификации голосующего пользователя было решено использовать его ip адрес и user agent.
User agent был включен в идентификатор, из-за наличия сетей, где много пользователей выходят в интернет через NAT, и естественно имеют один ip адрес. Также не исключено желание людей голосовать с работы и агитировать своих коллег. А как известно, многие офисы сидят за одним вай-фай или простым маршрутизатором и имеют один внешний адрес. Не обижать же их всех .
Запускаем последний барьер, от накруток, который ищет пользователя среди проголосовавших и проверяет, прошли или нет сутки с момента голосования.
Далее либо регистрируем его голос, записывая наш $user_id голосующего + текущее время и дату сервера, прибавляем поставленный балл, либо возвращаем сообщение об ошибке.
Если vote.php отработал и не вернул ошибку, то в js функции send_vote, осуществляем прибавление балла визуально и выдаем с помощью jGrowl заветное «Ваш голос принят»
Для автоматического выбора финалистов были созданы агенты, вызывающие функцию check_finalist(), размещенную в init.php, раз в неделю.
Цикл for($i=2633; $i<=2637; $i++), предназначен для поиска финалистов во всех регионах. По правилам конкурса, выбирается по 1 финалисту из региона каждую неделю. Разбиение по регионам было осуществлено с помощью разделов инфоблока (2633..2637 – ID разделов). Чтобы отличать финалиста от других, было введено свойство FINALIST типа список, принимающее значения: «финалист» (id - 1839) и «работа этого ребенка уже есть в финале» (1865). Условие if($finalist['ID'] > 0) , на случай отсутствия финалистов в одном из регионов. Осталось добавить, что для вывода списка работ был использован bitrix:news, а для добавления работ использовался bitrix:iblock.element.add.form.
Вот вроде бы и все. Буду рад вопросам, критике и предложениям
Подойдет для простого конкурса, но не для Мисс Россия — там народ начнет юзерагентов скриптом перебирать да через анонимные прокси заходить (списки которых вроде публикуют.) Надо как то через sms что ли делать. Или хотябы только зарегистрированным разрешать голосовать ( старше месяца -- емайл тоже просто новый завести.)
лайки — хороший вариант, но есть два минуса: 1. логика: каждый голос — 1 балл. не сделаешь голосование по пятибальной системе, например. 2. внешнее представление не изменишь
Проходил уже все это в общем так: опустим воду, связанную с jquery jglow и прочим - это на любителя? это все уже фишки я вообще ajax родной битриксовский использую чаще чем что то другое для таких целей и в принципе он справляется И перейдем к сути то: Я сомневаюсь в объективности голосования как только будет повод накрутить - все накрутят что надо И все ваши алгоритмы полетят. IP - без проблем обходится. Достаточно просто имея подключение с дин. IP отключиться и снова подключиться к провайдеру или воспользоваться прокси. UserAgent... не уверен, что в компании сидящей на одном IP этот параметр "случайно не совпадет". Куки - после того, как понял, что пользователи в первую очередь ломают куки вообще на них забил. Вообще самая бесполезная с точки зрения секретности или обеспечения контроля штука. а вот про bxsessid () не забыли? http://dev.1c-bitrix.ru/api_help/main...%28%29.php и про рефферера? а то как наплодят вам прямых ссылок для голосований И еще момент рассматривали ли те механизмы, что в Битриксе зарыты в модуле опросов? Мое же мнение такое: Объективное голосование (точнее более-менее объективное) возможно, когда пользователю просто влом и очень влом или накладно будет результаты фальсифицировать а это возможно, когда: 1. Голос стоит денег 2. Требуется авторизация с уникальным емайл и с подтверждением регистрации по емайл 3. есть еще такой вид голосований как олосование по емайл. Типа дай адрес - получи секретный пароль на этот адрес. (не захламляется сайт пользователями одноразовыми)
и т.д. в общем когда за голос приходится платить потом, бабками или кровью (это уже черный юмор ) все остальное - детские игрушки пишу так, так как есть уже опыт аналогичных граблей. Что касается регионов - это так, частности В целом же скажу - что серьезнее надо быть, Роман, серьезнее Ну в инете, чес слово столько уже инфы по этим голосованиям накоплено и опыта описано. И вы как раз ничего нового не реализуете. Почему бы не воспользоваться уже прогрессивным опытом?
Согласен. Взломать все можно — вопрос времени (денег.) Думаю, что в каждом конкретном случае нужно оценивать соотношение трудозатрат на взлом к цели взлома и в соответствии с этим заморачиваться на защиту больше или меньше (дороже/дешевле).
куки были использованы, чтобы от честных пользователей лишний раз запрос не обрабатывать ни более того Про анализ реферала, это да, совсем вылетело что-то с головы, спасибо за замечание, учту
Эффективность bxsessid сомнительна, точнее при проверке реферала наверное избыточна.
Использование модуля опроса, возможна не для всех редакций.
Тут стоит отметить еще цели конкурса, в конкретном случае конкурс являлся инструментом привлечения пользователей на сайт, а не для объективного выбора победителей. Ценность призов, могла бы кого-то спровоцировать на анализ защиты и поиск методов обхода, но первые, самые ценные места, в итоге будет определять жюри.
Самое надежное наверное, или голосование для зарегистрированных пользователей, подтвердивших свою учетную запись кодом из смс с уникального номера сотового, либо голосование по смс через короткие номера. И конечно надежность конкурса, зависит от его бюджета Надеюсь, что когда нибудь доведется сделать более извращенно-защищенный
Остальное обходить намного проще, со списками бесплатных проксей, возможностью создания своего е-майл сервера, где будут генерироваться адреса и парситься потом ссылки из писем и т.д.
Эффективность bxsessid сомнительна, точнее при проверке реферала наверное избыточна.
реферер - это только чтобы удостовериться, что голос с сайта идентификатор сессии - это для того, чтобы ссылка работала реально только один раз. При этом никакие GET и POST переборы по истечении сессии уже не помогут. Возможно, что они друг друга и компенсируют. но в случаях когда несколько доменов, например, удобнее наверное сессии.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».