Cackle — индексация комментариев

    Данный топик будет полезен и интересен всем тем, кто использует виджет Cackle и хотел бы реализовать индексацию комментариев в поисковиках. Все что будет описано ниже, уже реализовано в плагине для WordPress версии 2.0 и выше. Если вы не используете данную CMS, то под катом подробное описание процесса синхронизации комментариев с примерами на php.

    Для индексации, комментарии должны находится в вашей локальной базе данных и отрисовываться на html страницах с помощью вашего сайта, без использования виджета Cackle. В общем виде процесс синхронизации выглядит так:
    • Необходимо создать таблицы для хранения комментариев
    • Добавить контроллер, которые будет получал комментарии через определенный интервал времени
    • Вывести комментарии из локальной базы данных на страницу в определенный div


    Создание таблицы


    Тут все просто, вам нужна структура данных, которая хранила бы комментарии и необходимы нам параметры(пример mysql):
    CREATE TABLE `comment` (
    	`comment_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    	`post_id` BIGINT(20) NULL DEFAULT NULL,
    	`url` VARCHAR(2000) NULL DEFAULT NULL,
    	`parent` VARCHAR(20) NULL DEFAULT NULL,
    	`message` TEXT NULL,
    	`media` VARCHAR(1000) NULL DEFAULT NULL,
    	`status` VARCHAR(11) NULL DEFAULT NULL,
    	`rating` INT(11) NULL DEFAULT NULL,
    	`user_agent` VARCHAR(1000) NULL DEFAULT NULL,
    	`ip` VARCHAR(39) NULL DEFAULT NULL,
    	`author_name` VARCHAR(60) NULL DEFAULT NULL,
    	`author_email` VARCHAR(100) NULL DEFAULT NULL,
    	`author_www` VARCHAR(200) NULL DEFAULT NULL,
    	`author_avatar` VARCHAR(200) NULL DEFAULT NULL,
    	`author_provider` VARCHAR(32) NULL DEFAULT NULL,
    	`anonym_name` VARCHAR(60) NULL DEFAULT NULL,
    	`anonym_email` VARCHAR(100) NULL DEFAULT NULL,
    	`created` DATETIME NULL DEFAULT NULL,
    	PRIMARY KEY (`comment_id`)
    );
    CREATE TABLE `common` (
    	`common_name` VARCHAR(50) NULL DEFAULT NULL,
    	`common_value` VARCHAR(50) NULL DEFAULT NULL
    )
    

    Небольшие ремарки:
    • post_id — идентификатор текущего поста, в самом простом случае url страницы
    • media — медиа контент, ссылки на изображения (png, jpg, gif), видео (youtube, vimeo, вконтакте, rutube), презентации (google, slideshare)
    • status — 0 на рассмотрении, 1 одобрено, 2 отклонено, 3 спам, 4 удалено
    • author_provider — социальная сеть (facebook, twitter, linkedin, ..)
    • created — дата создания
    • common — «утильная» таблица для хранения параметров

    PS: Для простоты я не стал разделять таблицу на сущности — post, author, anonym, хотя для быстродействия и нормализации это было бы не плохо сделать.

    Синхронизация комментариев


    Получить Cackle комментарии можно по следующему RESTful API сервису:
    http://cackle.me/api/comment/list?siteApiKey={siteApiKey}&accountApiKey={accountApiKey}&id={id}
    

    Где siteApiKey (Site API Key) и accountApiKey (Account API Key) можно найти в панели администрирования, на вкладке «Виджет», снизу выбрав WordPress, как показано на рисунках ниже:
    image
    image
    Необязательный параметр id служит курсором, то есть данный запрос вернет все комментарии id, которых больше чем id в запросе. Если параметр id отсутствует, будут переданы первые 100 комментариев.

    Синхронизация должна работать по схеме:
    • Проверяем прошло ли 5 минут с последнего вызова API, если да, то идем дальше
    • Берем максимальный Cackle ID комментария из локальной базы данных или 0, если комментариев нет
    • Вызываем API с ключами и полученным Cackle ID
    • Сохраняем комментарии
    • Получаем текущее время и сохраняем его как время последнего вызова API


    Интервал между вызовами API нужен из-за установленного лимита (1000 раз в час, на вызов любого API запроса).
    Код на php:
    Во — первых нам необходимо определить все константы для работы скрипты: подключение к БД, время крона, ключи к api Cackle
    //Define db connection settings
    define('CACKLE_DB_LOCALHOST', "localhost");
    define('CACKLE_DB_USER',  "root");
    define('CACKLE_DB_PASSWORD', "");
    define('CACKLE_DB_NAME', "cackle-php" );
    //Define timer
    define('CACKLE_TIMER', 60);
    //Define Cackle API
    define('ACCOUNT_API_KEY',  "");
    define('SITE_API_KEY', "");
    

    Нам понадобится функция для реализации кастомного крона:
    function time_is_over($cron_time){
            $sql="select common_value from common where `common_name` = 'last_time'";
            $get_last_time = $this->db_connect($sql, "common_value");
            $now=time();
            $establish_time_sql="insert into `common` (`common_name`,`common_value`) values ('last_time',$now)";
            $delete_time_sql="delete from `common` where `common_name` = 'last_time' and `common_value` > 0;";
            if ($get_last_time==null){
                $this->db_connect($establish_time_sql);
                return time();
            }
            else{
                if($get_last_time + $cron_time > $now){
                    return false;
                }
                if($get_last_time + $cron_time < $now){
                    $this->db_connect($delete_time_sql);
                    $this->db_connect($establish_time_sql);
                    return $cron_time;
                }
            }
        }
    

    Функция comment_sync реализует запрос к апи, и сохранит комментарии в бд.
    function comment_sync($accountApiKey,$siteApiKey,$cackle_last_comment=0){
            $params = "accountApiKey=$accountApiKey&siteApiKey=$siteApiKey&id=$cackle_last_comment";
            $host="cackle.me/api/comment/list?$params";
            $response = curl($host);
            $response = $this->cackle_json_decodes($response);
            $this->push_comments($response); //вызов for цикла пробегающего по всем комментариям функцией insert_comment()
    }
    

    Сама функция insert_comment() реализующая сохранение комментариев
    function insert_comm($comment){
    ...
        if ($comment['parentId']) { 
                $comment_parent_id = $comment['parentId'];
                $sql = "select comment_id from comment where user_agent='Cackle:$comment_parent_id';";
                $get_parent_local_id = $this->db_connect($sql, "comment_id"); //если у коммента есть родитель,то в локальную БД пишем локальный comment_id который находим по user_agent
            }
        $commentdata = array(
                    'url' => $url,
                    'author_name' =>  $author_name,
                    'author_email' =>  $author_email,
                    'author_www' =>  $author_www,
                    'author_avatar' =>  $author_avatar,
                    'author_provider' =>  $author_provider,
                    'anonym_name' =>  $author_anonym_name,
                    'anonym_email' =>  $anonym_email,
                    'rating' => $comment['rating'],
                    'created' => strftime("%Y-%m-%d %H:%M:%S", $comment['created']/1000),
                    'ip' => $comment['ip'],
                    'message' =>$comment['message'],
                    'status' => $status,
                    'user_agent' => 'Cackle:' . $comment['id'],
                    'parent' => $get_parent_local_id
                    
            );
            // в массив $commentdata необходимо добавить 'post_id' = > $post_id, который можно получить средствами вашего движка по url страницы с комментариями
            $this->db_connect($this->insCreate("comment",$commentdata)); //запись коммента в БД
    }
    

    Полный рабочий код синхронизации комментариев доступен здесь.

    Отрисовка комментариев на html


    Финальный пункт — отрисуйте комментарии на вашей странице, в следующем виде:
    <div id="mc-container">
        [... тут нужно вывести комментарии из локальной базы данных ...]
    </div>
    <script>
        [... код виджета Cackle ...]
    </script>
    

    Код на php:
    Получим все комментарии для данной страницы из локальной БД:
    function get_local_comments(){
            //getting all comments for special post_id from database. 
            //$post_id = 1;
            $get_all_comments = $this->db_connect("select * from `comment` where `post_id` = $post_id;");
            return $get_all_comments;
        }
    

    Создадим шаблон-функцию для отрисовки отдельного комментария
    <?php function cackle_comment( $comment) {?>
              <li  id="cackle-comment-<?php echo $comment['comment_id']; ?>">
                  <div id="cackle-comment-header-<?php echo $comment['comment_id']; ?>" class="cackle-comment-header">
                      <cite id="cackle-cite-<?php echo $comment['comment_id']; ?>">
                      <?php if($comment['author_name']) : ?>
                          <a id="cackle-author-user-<?php echo $comment['comment_id']; ?>" href="<?php echo $comment['author_www']; ?>" target="_blank" rel="nofollow"><?php echo $comment['author_name']; ?></a>
                      <?php else : ?>
                          <span id="cackle-author-user-<?php echo $comment['comment_id']; ?>"><?php echo $comment['anonym_name']; ?></span>
                      <?php endif; ?>
                      </cite>
                  </div>
                  <div id="cackle-comment-body-<?php echo $comment['comment_id']; ?>" class="cackle-comment-body">
                      <div id="cackle-comment-message-<?php echo $comment['comment_id']; ?>" class="cackle-comment-message">
                      <?php echo $comment['message']; ?>
                      </div>
                  </div>
              </li>
    <?php }
    

    Пробегаем по списку комментариев
    function list_comments(){
            $obj = $this->get_local_comments();
            foreach ($obj as $comment) {
                $this->cackle_comment($comment);
            }
        }
    

    Отображаем html комментариев вместе с виджетом
    function cackle_display_comments(){ ?>
             <div id="mc-container">
                <div id="mc-content">
                    <ul id="cackle-comments">
                    <?php $this->list_comments(); ?> 
                    </ul>
                </div>
            </div>
            <script type="text/javascript">
            var mcSite = '<?php echo $api_id?>';
            var mcChannel = '<?php echo $post->ID?>';
            document.getElementById('mc-container').innerHTML = '';
            (function() {
                var mc = document.createElement('script');
                mc.type = 'text/javascript';
                mc.async = true;
                mc.src = 'http://cackle.me/mc.widget-min.js';
                (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(mc);
            })();
            </script>
    <?php }
    

    Как видно из js мы очищаем mc-container, для того чтобы сгенеренный нами список комментариев не отображался на странице.
    В итоге на странице будет виден только виджет Cackle с комментариями, а в html коде будет список для индексации поисковыми системами.
    Cackle 24,38
    Компания
    Поделиться публикацией
    Похожие публикации
    Комментарии 10
    • 0
      Спасибо очень полезно. В подобных системах меня всегда беспокоило, что ты, как бы перестаешь владеть своими комментариями. А при таком подходе, жить можно :) Как раз думал какую систему ставить на сайт. Это, плюс то что вы поддерживайте русские соцсети, убеждает меня что стоит вас попробовать.

      В любом случае — удачи с проектом!
      • 0
        почему бы сразу не написать и функцию вывода в том же виде как и скриптом?
        • 0
          Обновили топик, добавили вывод комментариев.
          • 0
            В случае, если понадобится пагинация используйте соответствующие функции вашей cms, текущий вариант выводит все имеющиеся комментарии для данной страницы.
          • 0
            Где найти доки вашего API?
            • 0
              Просьба к Cackle.
              Лучше просто скопируйте текст поста к себе на страницу ru.cackle.me/help/comment-sync.
              Иначе получается, что в ваших доках очень урезанно всё описано.
              По крайней мере по части полноты описания таблицы комментариев.
              • 0
                Реализовал у себя (без CMS)
                http://it.sander.su/comments_system.php
                Могу поделиться подробностями, если интересно
                • 0
                  Каким образом можно синхронизировать поле:
                  >>`rating` INT(11) NULL DEFAULT NULL,
                  хотя бы с отставанием в сутки?
                  Суть: внутри системы есть желание поощрять пользователей за активность раз в месяц, для этого необходимо знать как относятся другие к комментариям какого то пользователя за текущий месяц. Но при заборе комментария мы будем иметь у себя в локальной копии только замороженное значение рейтинга на момент импорта.
                  Самое простое конечно отсрочить забор новой порции комментариев на сутки/неделю/месяц, но тогда мы
                  1) теряем в быстрой индексации поисковыми системами.
                  2) теряем из рейтинга плюсы/минусы за позавчерашние комментария

                  Поэтому вопрос: можно ли сделать получение рейтинга за определенную дату по аналогии с получением курса валют на любую дату из прошлого
                  www.cbr.ru/currency_base/D_print.aspx?date_req=23.03.2013
                  и урл для этого может быть например такой:
                  cackle.me/api/comment/rating?siteApiKey={siteApiKey}&accountApiKey={accountApiKey}&date={Y-m-d}
                  • 0
                    Добавить контроллер, которые будет получал комментарии
                    :))
                    • 0
                      Уважаемые, подскажите, как лучше решить вопрос, когда на странице уже более 300 комментариев? Хотелось бы и индексацию их в поисковых системах, и что бы пользователю не загромождать экран. Вариант с выводом копии все комментариев на другу страницу отпадает сразу.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое