Pull to refresh

Facebook API: Как разрешить комментирование записи на стене всем [upd:25.09.2011]

Reading time 6 min
Views 7.3K
Продолжаю осваивать Facebook API [upd 25.09.2011]

На сей раз столкнулся с комментариями.

Требовалось: отправка сообщений на стену пользователя с последующим комментированием.

Задача: дать возможность комментировать запись всем пользователям Facebook, а не только друзьям.

И сразу разочарую: на сегодня (21.09.2011) человеческого способа дать доступ на комментирование всем напрямую через Graph api нет.

Т.е. способ комментирования есть, но по умолчанию комментирование разрешено только для друзей пользователя, у которого запись эта расположена. Если же кто-то «чужой» попытается оставить комментарий на ваше сообщение, то он получит сообщение об ошибке такого содержания:

(#100) Error finding the requested story // невозможно найти запрошенное сообщение



К слову сказать, что для того, чтобы комментировать скажем записи на стене приложения, нужно его предварительно одобрить нажатием на «Мне нравится», чтобы комментить сообщения на стене группы, нужно вступить в группу и т.д.

С другой стороны, если установить плагин комментариевна сайт и с его помощью отправить сообщение на стену пользователя, то его (сообщение) сможет прокомментировать любой посетитель этого сайта (если он уже вошел предварительно на Facebook).

Замечательно, значит способ есть, осталось только выяснить как все работает.

Только вот засада: в документации по плагину только рюшики — советы по настройке внешнего вида (скудные надо заметить) и прочая ненужная хрень. Никаких намеков, как и куда отправляются данные из плагина нет. Зато если получить записи стены через API:

{
   "data": [
      {
         "id": "100001957292289_178950362180206",
         "from": {
            "name": "\u0410\u043d\u0442\u043e\u043d \u0413\u043e\u0440\u043e\u0434\u0435\u0446\u043a\u0438\u0439",
            "id": "100001957292289"
         },
         "message": "Cats!",
         "actions": [
            {
               "name": "Comment",
               "link": "http://www.facebook.com/100001957292289/posts/178950362180206"
            },
            {
               "name": "Like",
               "link": "http://www.facebook.com/100001957292289/posts/178950362180206"
            }
         ],
         "privacy": {
            "description": "Friends of Friends",
            "value": "FRIENDS_OF_FRIENDS",
            "allow": "0",
            "deny": "0"
         },
         "type": "status",
         "application": {
            "name": "pilot",
            "id": "174611799256077"
         },
         "created_time": "2011-09-21T18:24:50+0000",
         "updated_time": "2011-09-21T18:24:50+0000",
         "comments": {
            "count": 0
         }
      },



То никакого следа свежеоставленной записи там не окажется. И не мудрено. Длительные исследования показывают, что записи на стене имеют type: status, в то время как записи на стене отправленные из плагина комментариев имеют type: link_stat.

Почитав глубокомысленно тем 70-80 на stackoverflow.com, в самом натуральном смысле получаю переполнение стека головного мозга и в преддверии лишения рассудка натыкаюсь на такую конструкцию:

graph.facebook.com/comments/?ids=http://example.org/post/35/

К тому времени с экспериментами наигрался, поэтому не отходя от кассы, пробую данную конструкцию в Facebook-explorere.

И о чудо — получаю заветный JSON с информацией об этом посте.

Кстати, если по тому же адресу (https://graph.facebook.com/DIGITS_MOREDIGITS/comments) сделать post-запрос, то отправится новый пост:
graph.facebook.com/comments/?ids=http://nadvoe.org.ua/stud.my/post/35/

Так вот, посылаю GET, из вернувшегося json-объекта выуживаю id поста и пытаюсь послать по этому id комментарий:

graph.facebook.com/DIGITS_MOREDIGITS/comments

На что получаю ответ от Facebook:
(#100) Invalid fbid. // эта ошибка говорит о неправильном идентификаторе

Путем таки опять сложных умственных махинаций, выясняю что комментарии свободно отправятся, если из id убрать все начиная с нижней черты:

graph.facebook.com/DIGITS_MOREDIGITS/comments

По такому адресу комментарии отправятся успешно, и от любых пользователей.


[upd 25.09.2011]

В идентификаторе DIGITS_MOREDIGITS, DIGITS является идентификатором объекта с типом type: website, вместе эти символы составляют значение поля id из таблицы comment

Ниже новые умозаключения по этому поводу.


Т.е. в принципе DIGITS_MOREDIGITS — правильный идентификатор сообщения, но если попытаться получить комментарии по этому адресу:
graph.facebook.com/DIGITS_MOREDIGITS/comments
facebook вернет пустоту в формате json.

Логичным было бы попробовать сделать FQL-запрос к таблице comment, поставив id=DIGITS_MOREDIGITS в условие. Но поле id в таблице comment (как бы это не было странно и загадочно!) не индексируется, о чем нам любезно напомнит facebook:
Your statement is not indexable. The WHERE clause must contain an indexable column. Such columns are marked with * in the tables


offtop: Я посылаю лучи ненависти разработчикам facebook за то что столбец, который канонически должен быть индексируемым, они таковым не сделали.

Кстати, идентификатор, по которому можно выудить комментарии к конкретному посту находится в столбце post_fbid (тоже, к слову сказать, не индексируемый).

Таким образом подзадача сводится к тому, чтобы выявить соответствие между этими идентификаторами. Правда в наличии у нас вообще может оказаться только URL к которому был привязан плагин комментариев. В таком случае из таблицы link_stat (как было сказано выше — это как раз тип тех постов, которые отправлены из плагина комментариев на стену) нам нужно извлечь идентификатор объекта (object_id) по url. А потом по этому идентификатору выбирать все fbid_post и id. Вобщем лучше запросом покажу (FQL):
SELECT post_fbid, id 
		FROM comment 
		WHERE object_id IN 
		  (SELECT comments_fbid 
		   FROM link_stat 
		   WHERE url ='".base_url()."')


Соответственно свое расширение класса facebook я пополнил функцией получения id_по_которому_можно_получить_или_отправить_комментарий по id_который_возвращается_после_создания_поста_через_плагин_комментариев:

/*
	** Получаем настоящий id сообщения, которое было отправлено через плагин комментариев facebook
	** поиск ведем по тому id, которое отдает facebook в ответ на POST-query по адресу /comments/?ids={$url}
	*/
	public function getRealPostId($given_post_id)
	{
		$fql ="
		SELECT post_fbid, id 
		FROM comment 
		WHERE object_id IN 
		  (SELECT comments_fbid 
		   FROM link_stat 
		   WHERE url ='".base_url()."')
		";
		
		$params = array(
			'query' => $fql,
			'method' => 'fql.query',
			'callback' => ''
		);
		$result = $this->api($params);
		
		foreach($result as $row)
		{
			if ($row['id']==$given_post_id)
				return $row['post_fbid'];
		}
		return false;
	}


[/upd]

В принципе все это чудесно работает, но тут же пытаюсь внедрить это себе на сайт, то получаю очередной неприятный сюрприз в виде ошибки:
"Unknown identifier, "

Facebook жалуется на то, что такой идентификатор ему не известен. Поиск по персональному разделу facebook на stackoverflow наводит меня на мысли о том, что каждый адрес перед тем как может быть использован, должен быть инициализирован.

Произвести это можно двумя способами (хотя по сути одним):

  1. Запускать плагин комментариев у себя на сайте
  2. Посмотреть источник iframe плагина комментариев и дергать этот источник «прозрачно» для пользователя и единожды для всех новых URL на сайте.


Вторым методом я и решил дело (использован расширенный класс facebook php sdk, функция писана под codeigniter):

public function add()
    {
       // получение нового URL по новому key-идентификатору
        $new_id = $this->base->add( array( 'key_post' => 'NULL' ) );
        $url = base_url().'post/'.$new_id.'/';
        
        // следующий запрос обязателен, он инициализирует комментарии для указанного урла
        $context = stream_context_create(array(
            'http' => array(
                'method' => 'GET',
                'header' =>
                    'User-Agent: Mozilla/5.0 (X11; Linux i686; rv:6.0.2) Gecko/20100101 Firefox/6.0.2 FirePHP/0.6'.
                    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'.
                    'Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3'.
                    'Accept-Encoding: gzip, deflate'.
                    'Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7'.
                    'Connection: keep-alive'.
                    'Referer: http://www.nadvoe.org.ua/stud.my/'.
                    'Cookie: '.implode(';',$_COOKIE),
            ),
        ));
        $w = file_get_contents('https://www.facebook.com/plugins/comments.php?href='.urlencode($url),false,$context);
 
        // делаем вид, что мы плагин комментариев и забираем последний созданный id
        $result = $this->facebook->postMessageByUrl($url,$this->fields['message_post']);
     
        // получаем полную информацию по комментарию
        $last_post = $this->facebook->getPost($result['id']);
 
        $this->fields['id_post'] = $last_post['id'];
        $this->fields['created_time_post'] = strtotime($last_post['created_time']);
        $this->fields['id_user_post'] = $this->session->myId();
         
        // заносим информацию в базу
        if ($this->base->edit($this->fields,$new_id,'key'))
        {
            $this->NOTIFY->success('Добавлена тема');
            $this->NOTIFY->returnNotify();
        }
        else
        {
            $this->NOTIFY->returnError('Ошибка сохранения');
        }
    }



Вот так вот можно добиться, чтобы любой мог комментировать ваши записи на стене facebook, оставленные через приложение.
Tags:
Hubs:
+4
Comments 0
Comments Leave a comment

Articles