[
'name' => 'Короткое имя группы или профиля (из ссылки)',
'exampleValue' => 'goblin_oper_ru',
'required' => true
],
'hide_reposts' => [
'name' => 'Скрыть репосты',
'type' => 'checkbox',
]
]
];
const CONFIGURATION = [
'access_token' => [
'required' => true,
],
];
const TEST_DETECT_PARAMETERS = [
'https://vk.com/id1' => ['u' => 'id1'],
'https://vk.com/groupname' => ['u' => 'groupname'],
'https://m.vk.com/groupname' => ['u' => 'groupname'],
'https://vk.com/groupname/anythingelse' => ['u' => 'groupname'],
'https://vk.com/groupname?w=somethingelse' => ['u' => 'groupname'],
'https://vk.com/with_underscore' => ['u' => 'with_underscore'],
'https://vk.com/vk.cats' => ['u' => 'vk.cats'],
];
protected $ownerNames = [];
protected $pageName;
private $urlRegex = '/vk\.com\/([\w.]+)/';
private $rateLimitCacheKey = 'vk2_rate_limit';
public function getURI()
{
if (!is_null($this->getInput('u'))) {
return urljoin(static::URI, urlencode($this->getInput('u')));
}
return parent::getURI();
}
public function getName()
{
if ($this->pageName) {
return $this->pageName;
}
return parent::getName();
}
public function detectParameters($url)
{
if (preg_match($this->urlRegex, $url, $matches)) {
return ['u' => $matches[1]];
}
return null;
}
protected function getPostURI($post)
{
$r = 'https://vk.com/wall' . $post['owner_id'] . '_';
if (isset($post['reply_post_id'])) {
$r .= $post['reply_post_id'] . '?reply=' . $post['id'] . '&thread=' . $post['parents_stack'][0];
} else {
$r .= $post['id'];
}
return $r;
}
// This function is based on SlackCoyote's vkfeed2rss
// https://github.com/em92/vkfeed2rss
protected function generateContentFromPost($post)
{
// it's what we will return
$ret = $post['text'];
// html special characters convertion
$ret = htmlentities($ret, ENT_QUOTES | ENT_HTML401);
// change all linebreak to HTML compatible
$ret = nl2br($ret);
$ret = "
$ret
"; // find URLs $ret = preg_replace( '/((https?|ftp|gopher)\:\/\/[a-zA-Z0-9\-\.]+(:[a-zA-Z0-9]*)?\/?([@\w\-\+\.\?\,\'\/&%\$#\=~\x5C])*)/', "$1", $ret ); // find [id1|Pawel Durow] form links $ret = preg_replace('/\[(\w+)\|([^\]]+)\]/', "$2", $ret); // attachments if (isset($post['attachments'])) { // level 1 foreach ($post['attachments'] as $attachment) { if ($attachment['type'] == 'video') { // VK videos $title = e($attachment['video']['title']); $photo = e($this->getImageURLWithLargestWidth($attachment['video']['image'])); $href = "https://vk.com/video{$attachment['video']['owner_id']}_{$attachment['video']['id']}"; $ret .= ""; } elseif ($attachment['type'] == 'audio') { // VK audio $artist = e($attachment['audio']['artist']); $title = e($attachment['audio']['title']); $ret .= "Audio: {$artist} - {$title}
"; } elseif ($attachment['type'] == 'doc' and $attachment['doc']['ext'] != 'gif') { // any doc apart of gif $doc_url = e($attachment['doc']['url']); $title = e($attachment['doc']['title']); $ret .= ""; } } // level 2 foreach ($post['attachments'] as $attachment) { if ($attachment['type'] == 'photo') { // JPEG, PNG photos // GIF in vk is a document, so, not handled as photo $photo = e($this->getImageURLWithLargestWidth($attachment['photo']['sizes'])); $text = e($attachment['photo']['text']); $ret .= ""; } elseif ($attachment['type'] == 'doc' and $attachment['doc']['ext'] == 'gif') { // GIF docs $url = e($attachment['doc']['url']); $ret .= ""; } elseif ($attachment['type'] == 'link') { // links $url = e($attachment['link']['url']); $url = str_replace('https://m.vk.com', 'https://vk.com', $url); $title = e($attachment['link']['title']); if (isset($attachment['link']['photo'])) { $photo = $this->getImageURLWithLargestWidth($attachment['link']['photo']['sizes']); $ret .= ""; } else { $ret .= ""; } } elseif ($attachment['type'] == 'note') { // notes $title = e($attachment['note']['title']); $url = e($attachment['note']['view_url']); $ret .= ""; } elseif ($attachment['type'] == 'poll') { // polls $question = e($attachment['poll']['question']); $vote_count = $attachment['poll']['votes']; $answers = $attachment['poll']['answers']; $ret .= "Poll: {$question} ({$vote_count} votes)
";
foreach ($answers as $answer) {
$text = e($answer['text']);
$votes = $answer['votes'];
$rate = $answer['rate'];
$ret .= "* {$text}: {$votes} ({$rate}%)
";
}
$ret .= '
Unknown attachment type: {$attachment['type']}
"; } } } return $ret; } protected function getImageURLWithLargestWidth($items) { usort($items, function ($a, $b) { return $b['width'] - $a['width']; }); return $items[0]['url']; } public function collectData() { if ($this->cache->get($this->rateLimitCacheKey)) { throw new RateLimitException(); } $u = $this->getInput('u'); $ownerId = null; // getting ownerId from url $r = preg_match('/^(club|public)(\d+)$/', $u, $matches); if ($r) { $ownerId = -intval($matches[2]); } else { $r = preg_match('/^(id)(\d+)$/', $u, $matches); if ($r) { $ownerId = intval($matches[2]); } } // getting owner id from API if (is_null($ownerId)) { $r = $this->api('groups.getById', [ 'group_ids' => $u, ], [100]); if (isset($r['response'][0])) { $ownerId = -$r['response'][0]['id']; } else { $r = $this->api('users.get', [ 'user_ids' => $u, ]); if (count($r['response']) > 0) { $ownerId = $r['response'][0]['id']; } } } if (is_null($ownerId)) { returnServerError('Could not detect owner id'); } $r = $this->api('wall.get', [ 'owner_id' => $ownerId, 'extended' => '1', ]); // preparing ownerNames dictionary foreach ($r['response']['profiles'] as $profile) { $this->ownerNames[$profile['id']] = $profile['first_name'] . ' ' . $profile['last_name']; } foreach ($r['response']['groups'] as $group) { $this->ownerNames[-$group['id']] = $group['name']; } $this->generateFeed($r); } protected function generateFeed($r) { $ownerId = 0; foreach ($r['response']['items'] as $post) { if (!$ownerId) { $ownerId = $post['owner_id']; } $item = []; $content = $this->generateContentFromPost($post); if (isset($post['copy_history'])) { if ($this->getInput('hide_reposts')) { continue; } $originalPost = $post['copy_history'][0]; if ($originalPost['from_id'] < 0) { $originalPostAuthorScreenName = 'club' . (-$originalPost['owner_id']); } else { $originalPostAuthorScreenName = 'id' . $originalPost['owner_id']; } $originalPostAuthorURI = 'https://vk.com/' . $originalPostAuthorScreenName; $originalPostAuthorName = $this->ownerNames[$originalPost['from_id']]; $originalPostAuthor = "$originalPostAuthorName"; $content .= 'Репост (Пост от '; $content .= $originalPostAuthor; $content .= '):
'; $content .= $this->generateContentFromPost($originalPost); } $item['content'] = $content; $item['timestamp'] = $post['date']; $item['author'] = $this->ownerNames[$post['from_id']]; $item['title'] = $this->getTitle(strip_tags($content)); $item['uri'] = $this->getPostURI($post); $this->items[] = $item; } $this->pageName = $this->ownerNames[$ownerId]; } protected function getTitle($content) { $content = explode('