Мой первый написанный класс. На что он способен, написано в комментах к функциям. Просьба оценить слабые моменты в плане реализции. Что стоит улучшить и переделать? PHP: <?php class VkontakteAPI { public $email = ''; // Логин public $password = ''; // Пароль public $pageBody = ''; // страница с результатом действия public $mainBody = ''; // Главная страница public $userID = ''; // ID юзера public $activityhash = ''; // хэш юзера public $cookie = ''; // печеньки public $proxy = ''; // адрес прокси function __construct($email, $password,$cookie='',$proxy='') { $this->email = $email; $this->password = $password; if ($cookie!='') $this->cookie = $cookie; // М-м-м-м... печеньки... if ($proxy!='') $this->proxy = $proxy; } // Авторизация Вконтакте function auth() { $this->pageBody = $this->get('http://vkontakte.ru/login.php',0); $this->getCookies($this->pageBody); $this->pageBody = $this->post('http://vkontakte.ru/login.php','op=a_login_attempt',0); $this->pageBody = $this->post('http://login.vk.com/','act=login&success_url=&fail_url=&try_to_login=1&to=&vk='.'&email='.$this->email.'&pass='.$this->password.'&expire=',0); $this->getCookies($this->pageBody); preg_match_all("|<input\stype=\'hidden\'\sname=\'s\'\svalue=\'(.+)\'\s/>|U", $this->pageBody, $s); // Если нет заветной переменной, выдаём false if (!isset($s[1][0])) return false; $this->pageBody = $this->get('http://vkontakte.ru/login.php?op=slogin&redirect=1&expire=0&to=&s='.$s[1][0],0); $this->cookie = ''; $this->getCookies($this->pageBody); $this->pageBody = $this->get('http://vkontakte.ru/'); // Если есть запись о смене пароля, выдаём false if (strpos($this->pageBody,'Смена пароля') !== false) return false; $this->mainBody = $this->pageBody; preg_match_all('|<input type="hidden" id="mid" value="(.+)"|U', $this->pageBody, $arr); if (isset($arr[1][0])) $this->userID = $arr[1][0]; preg_match_all("|<input type='hidden' id='activityhash' value='(.+)'|U", $this->pageBody, $arr); if (isset($arr[1][0])) $this->activityhash = $arr[1][0]; return true; } function get($url, $follow=1) { $process = curl_init($url); curl_setopt($process, CURLOPT_HEADER, 1); curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.10) Gecko/20100914 MRA 5.6 (build 03402) Firefox/3.6.10'); curl_setopt($process, CURLOPT_COOKIE,$this->cookie); curl_setopt($process, CURLOPT_TIMEOUT, 15); curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); curl_setopt($process, CURLOPT_FOLLOWLOCATION, $follow); if ($this->proxy) curl_setopt($process, CURLOPT_PROXY, $this->proxy); $return = curl_exec($process); curl_close($process); return $return; } function post($url, $data, $follow=1) { $process = curl_init($url); curl_setopt($process, CURLOPT_HEADER, 1); curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.10) Gecko/20100914 MRA 5.6 (build 03402) Firefox/3.6.10'); curl_setopt($process, CURLOPT_COOKIE,$this->cookie); curl_setopt($process, CURLOPT_TIMEOUT, 15); curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); curl_setopt($process, CURLOPT_FOLLOWLOCATION, $follow); curl_setopt($process, CURLOPT_POSTFIELDS, $data); curl_setopt($process, CURLOPT_POST, 1); if ($this->proxy) curl_setopt($process, CURLOPT_PROXY, $this->proxy); $return = curl_exec($process); curl_close($process); return $return; } // Функция достаёт статус с главной страницы пользователя function getStatus() { preg_match_all('|this.style.textDecoration = \'none\';">(.+)<|U', $this->mainBody, $arr); if (isset($arr[1][0])) return substr($arr[1][0], 0, strlen($arr[1][0]) - 1); else return false; } // Функция достаёт количество друзей пользователя function getCountFriends() { preg_match('#<h2>Друзья <span>\((.*)\)</span></h2>#Us', $this->mainBody, $arr); if (isset($arr[1])) return ($arr[1]!='')? $arr[1] : 0; else return false; } // Функция возвращает пол пользователя function getSex() { preg_match('#\<a href=\'/gsearch.php\?from=people&c\[sex\]=\d\'\>(.*)\</a\>#Us', $this->mainBody, $arr); if (isset($arr[1])) return $arr[1]; else return false; } // Функция установки статуса текущему ID function setStatus($text) { $this->pageBody = $this->post('http://vkontakte.ru/profile.php','setactivity='.$this->utf($text).'&activityhash='.$this->activityhash); } // Функция заходит в группу по заданному ID группы function enterGroup($groupID) { $this->pageBody = $this->get('http://vkontakte.ru/club'.$groupID); sleep(1); preg_match('#enterGroup\('.$groupID.', "(.*)"#Us',$this->pageBody,$match); if (isset($match[1])) { $this->pageBody = $this->post('http://vkontakte.ru/groups_ajax.php','act=a_enter&gid='.$groupID.'&hash='.$match[1]); usleep(500); return true; } return false; } // Функция проверки домена. Если домен занесён в подозрительные, возвращает FALSE function checkDomain($domain) { $this->pageBody = $this->get('http://vkontakte.ru/away.php?to=http://'.$domain); if (strpos($this->pageBody, 'ВКонтакте | Ссылка на подозрительный сайт')) return FALSE; else return TRUE; } // Функция проверки группы по ID. Если группа заблокирована или удалена, возвращает FALSE function checkGroup($groupID) { $this->pageBody = $this->get('http://vkontakte.ru/club'.$groupID); if (strpos($this->pageBody, 'Страница заблокирована') || strpos($this->pageBody,'Группа не найдена')) return FALSE; else return TRUE; } // Пишем заданному ID текст на стену function addWallText($id,$text) { $this->pageBody = $this->get('http://vkontakte.ru/'.$id); sleep(1); // Если сообщение на стенку пользователя if (substr($id,0,2) == 'id') { preg_match('#postWall\((.*), \'(.*)\'\)#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody = $this->post('http://vkontakte.ru/wall.php','act=a_post_wall&hash='.$this->decodeHash($match[2]).'&message='.$this->utf($text).'&to_id='.$match[1].'&top_id=&type=0'); usleep(500); return true; } } // Если сообщение на стенку группы else if (substr($id,0,4) == 'club') { preg_match('#\{act\: \'a_post_wall\', hash\: decodehash\(\'(.*)\'\), message\: txt, to_id\:(.*)\}#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody = $this->post('http://vkontakte.ru/wall.php','act=a_post_wall&hash='.$this->decodeHash($match[1]).'&message='.$this->utf($text).'&to_id='.$match[2]); usleep(500); return true; } } return false; } // Отправка сообщений заданному ID function sendMessage($id,$text,$subject) { $this->pageBody = $this->get('http://vkontakte.ru/mail.php?act=write&to='.$id); usleep(500); preg_match('#id="chas" name="chas" value="(.*)"#Us',$this->pageBody,$match); if (isset($match[1])) { $this->pageBody = $this->post('http://vkontakte.ru/mail.php','act=sent&aid=&ajax=1&chas='.$this->decodeHash($match[1]).'&fid=&from_box=1&message='.$this->utf($text).'&oid=&title='.$this->utf($subject).'&to_id='.$id.'&vid='); usleep(500); return true; } return false; } // Добавляемся в друзья к указанному ID с заданным текстом function addToFriend($id,$text) { $this->pageBody = $this->post('http://vkontakte.ru/friends_ajax.php','act=request_form&fid='.$id); sleep(1); preg_match('#id=\\\"hash\\\" value=\\\"(.*)\\\"#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody = $this->post('http://vkontakte.ru/friends_ajax.php','act=accept_friend&fid='.$id.'&hash='.$this->decodeHash($match[1]).'&cats=&verbose=1&message='.$this->utf($text)); sleep(1); return true; } return false; } // Становимся поклонником выбранного ID function addFavorite($id) { $this->pageBody = $this->post('http://vkontakte.ru/rate.php','act=a_be_fan&mid='.$id); sleep(1); preg_match('#hash=(.*)\'#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody= $this->post('http://vkontakte.ru/rate.php','act=do_be_a_fan&mid='.$id.'&hash='.$match[1]); sleep(1); return true; } return false; } // Удаляемся из поклонников выбранного ID function deleteFavorite($id) { $this->pageBody = $this->post('http://vkontakte.ru/rate.php','act=a_not_fan&mid='.$id); sleep(1); preg_match('#hash=(.*)\'#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody= $this->post('http://vkontakte.ru/rate.php','act=do_not_fan&mid='.$id.'&hash='.$match[1]); sleep(1); return true; } return false; } // Декодер хэшей function decodeHash($hash) { $h = ''; $temp = substr($hash,strlen($hash)-5) . substr($hash,4,strlen($hash)-12); for ($i=0 , $l = strlen($temp); $i < $l; ++$i) $h .= substr($temp,$l-$i-1,1); return $h; } // Меняем кодировку, используется при запросах function utf($text) { return iconv('WINDOWS-1251','UTF-8',$text); } // Возвращает текст ответа сервера без заголовка function getBody($text) { return array_pop(explode(PHP_EOL.PHP_EOL,$text)); } // Достаем из запроса кукисы function getCookies($data) { preg_match_all('#Set-Cookie: (.*);#Us',$data,$match); if (isset($match[1])) $this->cookie .= implode('; ',$match[1]); } } ?>
В коде разные отступы, так как отступы в netbeans не в ладах с отступами в notepad++. Кто-нибудь знает решение этой проблемы?
В смысле "не в ладах?". Вообще в notepad++ отступы настраиваются. Думаю в NetBeans должно тоже что-то подобное быть.
В Notpad++ При нажатии таба, а затем стиралки, курсор встает на первоначальное положение. В нетбинсе при тех же манипуляциях курсор сдвигается лишь на одну позицию влево, как будто до этого я набирал пробелы, а не таб.
В нетбинсе табуляция - 5 пробелов. Или 6, не суть важно. По умолчанию. А в нотепаде++ табуляция - это табуляция. И там, и там всё настраивается.
Ensiferum В настройках Notepad++ есть "заменять табы пробелами". И где-то на форуме мелькали вопросы как это сделать.
1) А у вконтакта нет API? 2) Код (Text): preg_match('#<h2>Друзья <span>\((.*)\)</span></h2>#Us', $this->mainBody, $arr); А нельзя ли привязаться не к тексту, а к атрибутам элемента? А то завтра они решат назвать друзей "камрадами" и ой...
Volt(220) 1) Есть, но исползуется для другого. Мой класс для имитаций действий человека, то бишь для написания бота 2) М-м, не думал над этим. Сделаю
задается размер отступа + возможность использовать для этого либо пачки пробелов либо таб. так что тыкни пару раз в настройки - все должно будет ободинаковиться.
В чем преимущество такого класса перед тем же фукнционалом, написанным процедурным стилем? Тут неприменимо ни наследование, ни абстракция.
Из-за обновления, функция addWallText перестала работать. Исправил часть отвечающую за стену пользователя: PHP: <?php function addWallText($id,$text) { $this->pageBody = $this->get('http://vkontakte.ru/'.$id); sleep(1); // Если сообщение на стенку пользователя if (substr($id,0,2) == 'id') { preg_match('/"post_hash":"([0-9a-f]*?)"/si', $this->pageBody, $match); if (isset($match[1])) { $this->pageBody = $this->post('http://vkontakte.ru/al_wall.php', 'act=post&al=1&hash='.$match[1].'&message='.$this->utf($text) .'&to_id='.preg_replace('/^id/si', '', $id).'¬e_title=&status_export='); usleep(500); return true; } } // Если сообщение на стенку группы else if (substr($id,0,4) == 'club') { preg_match('#\{act\: \'a_post_wall\', hash\: decodehash\(\'(.*)\'\), message\: txt, to_id\:(.*)\}#Us',$this->pageBody,$match); if (isset($match[0])) { $this->pageBody = $this->post('http://vkontakte.ru/wall.php','act=a_post_wall&hash='.$this->decodeHash($match[1]).'&message='.$this->utf($text).'&to_id='.$match[2]); usleep(500); return true; } } return false; } Аналогична ситуация с setStatus: PHP: <? // Функция установки статуса текущему ID function setStatus($text) { $this->pageBody = $this->post('http://vkontakte.ru/al_profile.php', 'act=current_info&al=1&hash='.preg_replace('/.*"info_hash":"([0-9a-f]*?)".*/si', '$1', $this->mainBody) .'&info='.$this->utf($text)); }
Добавлялку в други они тоже переделали. PHP: <? // Добавляемся в друзья к указанному ID с заданным текстом public function addToFriend($id,$text) { $this->pageBody = $this->post('http://vkontakte.ru/al_friends.php','act=add_box&al=1&mid='.$id); sleep(1); if (preg_match('#hash: \'(.*)\'#Us',$this->pageBody,$match)) { $this->pageBody = $this->post('http://vkontakte.ru/al_friends.php','act=add&al=1&cats=&hash='.$match[1].'&message='.$this->utf($text).'&mid='.$id); $temp = explode('<!>',$this->pageBody); if ($temp[4] == '2') { if ($this->antigateHash) { $dir = dirname($_SERVER['SCRIPT_FILENAME']) . DIRECTORY_SEPARATOR . 'captcha' . DIRECTORY_SEPARATOR; $t = $this->getBody($this->get('http://m.vkontakte.ru/captcha?s=1&sid='.$temp[5])); file_put_contents($dir . $temp[5] . '.jpg', $t); $t = $this->captcha($dir . $temp[5] . '.jpg'); $this->pageBody = $this->post('http://vkontakte.ru/al_friends.php','act=add&al=1&cats=&hash='.$match[1].'&message='.$this->utf($text).'&mid='.$id.'&captcha_key='.$t.'&captcha_sid='.$temp[5]); } } $temp = explode('<!>',$this->pageBody); if ($temp[4] == '0') return true; else return false; } return false; } ?> так же сделал работу с антигейтом PHP: <?public function captcha($captchaFile) { $rtimeout = 5; $mtimeout = 90; $postdata = array( 'method' => 'post', 'key' => $this->antigateHash, 'file' => '@'.$captchaFile, 'phrase' => 0, 'regsense' => 1, 'numeric' => 0, 'min_len' => 4, 'max_len' => 7 ); $result = $this->post('http://www.antigate.com/in.php', $postdata); if (strpos($result, "ERROR")!==false) { $this->captchaDebug = $this->getBody($result); return false; } else { $ex = explode("|", $result); $captcha_id = $ex[1]; $waittime = 0; sleep($rtimeout); while(true) { $result = @file_get_contents('http://antigate.com/res.php?key='.$this->antigateHash.'&action=get&id='.$captcha_id); if (strpos($result, 'ERROR')!==false) { return false; } if ($result=="CAPCHA_NOT_READY") { $waittime += $rtimeout; if ($waittime>$mtimeout) { break; } sleep($rtimeout); } else { $ex = explode('|', $result); if (trim($ex[0])=='OK') { return trim($ex[1]); } } } return false; } } ?>
Ensiferum Невнимательно посмотрел =) Но случаев, когда использование приложения невозможно, по-моему очень мало
[vs] Ну вот допустим сейчас на основе класса сделал бекапер альбомов групп. За 10 минут сервер грабит ~ 1500 фоток, за то же время переносит альбомы в любую другую группу.
API, по-моему, для этого и нужно, но они зачем-то запретили использование всех методов, кроме имеющих префикс secure. с сервера. Сам кучу времени убил пока не нашёл обсуждение.