Всем привет.

Побродив в группе хабрахабр вк стала интересна идея постинга новых и полезных сообщений с форума но в отличии от хабра все что у меня было это админ права в группе форума и идея.

Что понадобиться:
  • Этот пост.
  • access_token пользователя вк.
  • Веб хостинг с поддержкой php и cron.
  • Собственно сам форум и аккаунт.
  • Группа вк и админ права в ней.

Как это работает: Форумный аккаунт (желательно новый) подписываем на нужные нам форумы (разделы), если администрация следит за форумом и все исправно работает, то при создании новой темы в нужных нам разделах мы будем получать письмо на e-mail. Собственно с этим письмом мы и будем работать.


Настройка форумного аккаунта


Движок форума: IPB 3.1.2

Подписываемся на интересующие нас разделы


Выбираем режим уведомления


Работа с форумом почти закончена, осталось настроить уведомления e-mail


С такими настройками на e-mail будут приходить уведомления лишь при создании новой темы как и надо :)

Перейдем к самому скрипту


Важно: скрипт писал под определенный форум и определенные разделы все подобрано индивидуально. В случае с другим форумом или другими разделами скрипт может работать некорректно.

Создадим файл constants.php с кодом:
<?php
/* E-Mail с которого производим авторизацию */
define("EMAIL_LOGIN", "have@gmail.com");
/* Пароль для E-Mail */
define("EMAIL_PASSWORD", "123456789password");
/* Адрес IMAP по которому авторизуемся и получаем почту */
define("EMAIL_URL","{imap.gmail.com:993/imap/ssl}INBOX");
/* ID группы или пользователя у которого постим сообщения (для групп добавить - к примеру: -123456789) */
define("VK_GROUP", "-1");
/* ACCESS_TOKEN VK */
define("VK_ACCESS", "ACCESS_TOKEN");
?>


Естественно вместо данных которые там есть нужно вставить свои.
Для получения ACCESS_TOKEN'a перейдем по адресу:
https://oauth.vk.com/token?grant_type=password&client_id=3140623&client_secret=VeWdmVclDCtn6ihuP1nt&username=YOUR_LOGIN
&password=YOUR_PASSWORD

YOUR_LOGIN — данные для входа (e-mail, номер мобильного).
YOUR_PASSWORD — пароль

В ответ Вы получите ACCESS_TOKEN и свой ID.
{"access_token":"fa07de3ce1592231b0b30basd23cea6984e7b722cd5d7c5695e6a1b5d372ef75de84aad1dc63f7b83b05",
"expires_in":0,"user_id":1}


Сохраняем и закрываем файл.

Создаем новый файл post.php с кодом:

<?php
include 'constants.php';

$inbox = imap_open(EMAIL_URL,EMAIL_LOGIN,EMAIL_PASSWORD) or die('Cannot connect to Gmail: ' . imap_last_error());

$emails = imap_search($inbox,'ALL');
if($emails) 
{
	$output = '';
	rsort($emails);
	foreach($emails as $email_number) 
	{	
		$mes = imap_utf8(imap_body($inbox, $email_number));
		echo "Текст сообщения: ".$mes."<br/><br/>";
	}
}
imap_close($inbox);
?>


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

Переходим к разбору сообщения и публикации в вк


Почти у каждого форумного движка есть свои шаблоны e-mail сообщений и изменяются они очень редко, к примеру лишь при установке.
Выходит что вся почта с форума о новых сообщениях будет иметь один и тот же вид, что впринципе поможет нам в написании скрипта…

Вот такого вида приходят сообщения с форума для которого писался скрипт:

Код ниже может быть написан не верно и не соответствовать общепринятым правилам программирования php, извините если это так.

Как было сказано выше у форума есть шаблоны для e-mail уведомлений, поэтому чтобы разбирать сообщение проверим на соответствие сообщения с шаблоном.
Разберем тело сообщения и название, для этого в код добавим следующее:


$overview = imap_fetch_overview($inbox,$email_number,0);
		$message = imap_fetchbody($inbox,$email_number,2);
		$mes = imap_utf8(imap_body($inbox, $email_number));
		$sub = imap_utf8($overview[0]->subject);
		$topic = imap_utf8($overview[0]->from);

		$mini_str = "Адрес темы: ";
		$i_message = strpos($mes, $mini_str);
		$s_mini_str = "создал тему";
		$i_subject = strpos($sub, $s_mini_str);
		$t_mini_str = "Pawn-Wiki.Ru";
		$i_topic = strpos($topic, $t_mini_str);
		// если часто встречаемые слова найдены в тексте сообщения и в названии то продолжим
		if($i_message == true && $i_subject == true && $i_topic == true)
		{
		}


Что понадобится мы будем доставать из сообщения: имя новой темы, имя раздела форума в котором создана тема, небольшое описание, и ссылка.

Достанем имя форума и имя темы:

 $text = explode(" ",$mes);
      $forum_name = substr($text[8], 1);
      $ll_pos = strripos($sub, " создал тему ");
      $topic_name = substr($sub, $ll_pos+strlen(" создал тему "));


Можем проверить как работает код:

echo "Имя форума: ".$forum_name."<br/>";
echo "Имя темы: ".$topic_name."<br/>";

Вот и результат:


Но как мы видим название форума не полное я решил сильно не париться и добавил сам название разделов:

switch($forum_name)
      {
        case 'Готовые':         $forum_name .= " решения"; break;
        case 'Стандартные':     $forum_name .= " и полезные функции"; break;
        case 'Уроки':           $forum_name .= " Pawno"; break;
        case 'Интересные':      $forum_name .= " Команды"; break;
        default:                $forum_name .= " UNKNOWN"; break;
      } 


Проверим теперь:


Пора доставать ссылку на тему и описание новой темы:

$cuttext = substr($mes, strripos($mes, $mini_str)+strlen($mini_str));
      $text_2 = explode(" ",$cuttext);
      $topic_url = $text_2[0];
      $text_3 = explode("----------------------------------------------------------------------",$mes);
      if(strlen($text_3[1]) > 300)
      {
        $len = strlen($text_3[1])-50;
        $topic_desc = substr($text_3[1], 0, strlen($text_3[1])-$len);
      }
      else if(strlen($text_3[1]) > 100)
      {
        $topic_desc = substr($text_3[1], 0, strlen($text_3[1])-50);
      }
      $topic_desc = rtrim($topic_desc, "!,.-");
      $topic_desc = substr($topic_desc, 0, strrpos($topic_desc, ' '));
      $topic_desc .= "...";


Сохраним и проверим как все получилось:

			echo "Имя форума: ".$forum_name."<br/>";
			echo "Имя темы: ".$topic_name."<br/>";
			echo "Небольшое описание: ".$topic_desc."<br/>";
			echo "Ссылка: ".$topic_url."<br/>";


Отправляем все в группу


Перед отправкой приведем в порядок текст:

$vk_message = "В разделе ".$forum_name." создана новая тема ".$topic_name.".\n";
$vk_message .= $topic_desc;
SendVK($vk_message, $topic_url);


Теперь добавим функции:

function SendVK($text,$link)
{
  $url = 'https://api.vk.com/method/wall.post?owner_id='. VK_GROUP .'&attachments='.trim($link).'&message='.urlencode($text).'&access_token='. VK_ACCESS;
  $wall_post = curl($url);
}

function curl($url) 
{
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      
  $response = curl_exec($ch);
  curl_close($ch);
  return $response;
}


Перед сохранением найдем строчку добавленную ранее:

$emails = imap_search($inbox,'ALL');


И заменим на:

$emails = imap_search($inbox,'UNSEEN');


Так будут загружаться не прочитанные сообщения.

Теперь все сохраняем, добавляем в cron с разницей в 10-15 минут и проверяем работоспособность.


А вот и новость в группе:


Подведем итог


Минусы данного способа
  • Значок Apple на новости в группе.
  • Если злоумышленник узнает e-mail есть вариант что он сможет заспамить группу отправив сообщение по шаблону.
  • Сообщение о новой теме опубликуется даже если темы уже нет.


Спасибо за внимание, буду рад критике и новым решениям подобного.

Скачать готовый скрипт с Яндекс Диск.