commit c154c9f438f26499a5a64e4effc1835ba520ed24 Author: RedHood Date: Sat Jun 6 18:27:31 2020 +1000 Первый коммит diff --git a/Auth.php b/Auth.php new file mode 100644 index 0000000..08e7167 --- /dev/null +++ b/Auth.php @@ -0,0 +1,331 @@ +useragent = $other['useragent']; + if (isset($other['id_app'])) + $this->id_app = $other['id_app']; + } + if (isset($pass)) { + $this->login = $login; + $this->pass = $pass; + $this->method = 'pass'; + if (!$mobile) + $this->auth_method = 1; + } else { + $this->method = 'cookie'; + $this->cookie = json_decode($login, true); + $this->auth_method = 1; + } + } + + /** + * @throws VkApiException + */ + public function auth() + { + if ($this->auth_method == 0) + throw new VkApiException("Только для авторизации через приложение"); + $this->loginInVK(); + } + + /** + * @throws VkApiException + */ + private function loginInVK() + { + $query_main_page = $this->getCURL('https://vk.com/'); + preg_match('/name=\"ip_h\" value=\"(.*?)\"/s', $query_main_page['body'], $ip_h); + preg_match('/name=\"lg_h\" value=\"(.*?)\"/s', $query_main_page['body'], $lg_h); + + $values_auth = [ + 'act' => 'login', + 'role' => 'al_frame', + '_origin' => 'https://vk.com', + 'utf8' => '1', + 'email' => $this->login, + 'pass' => $this->pass, + 'lg_h' => $lg_h[1], + 'ig_h' => $ip_h[1] + ]; + $get_url_redirect_auch = $this->getCURL('https://login.vk.com/?act=login', $values_auth); + + if (!isset($get_url_redirect_auch['header']['location'])) + throw new VkApiException("Ошибка, ссылка редиректа не получена"); + + $auth_page = $this->getCURL($get_url_redirect_auch['header']['location'][0]); + + if (!isset($auth_page['header']['set-cookie'])) + throw new VkApiException("Ошибка, куки пользователя не получены"); + + $this->is_auth = 1; + } + + /** + * @param $url + * @param null $post_values + * @param bool $cookie + * @return array + */ + private function getCURL($url, $post_values = null, $cookie = true) + { + if ($curl = curl_init()) { + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_USERAGENT, $this->useragent); + if (isset($post_values)) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $post_values); + } +// +// curl_setopt($curl, CURLOPT_HTTPHEADER, [ +// "Content-Type: application/x-www-form-urlencoded", +// "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", +// "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36" +// ]); + + if ($cookie and isset($this->cookie)) { + $send_cookie = []; + foreach ($this->cookie as $cookie_name => $cookie_val) { + $send_cookie[] = "$cookie_name=$cookie_val"; + } + curl_setopt($curl, CURLOPT_COOKIE, join('; ', $send_cookie)); + } + + curl_setopt($curl, CURLOPT_HEADERFUNCTION, + function ($curl, $header) use (&$headers) { + $len = strlen($header); + $header = explode(':', $header, 2); + if (count($header) < 2) // ignore invalid headers + return $len; + + $name = strtolower(trim($header[0])); + if (isset($headers) and !array_key_exists($name, $headers)) + $headers[$name] = [trim($header[1])]; + else + $headers[$name][] = trim($header[1]); + + return $len; + } + ); + + $out = curl_exec($curl); + curl_close($curl); + if (isset($headers['set-cookie'])) + $this->parseCookie($headers['set-cookie']); + return ['header' => $headers, 'body' => $out]; + } + } + + /** + * @param $new_cookie + */ + private function parseCookie($new_cookie) + { + foreach ($new_cookie as $cookie) { + preg_match("!(.*?)=(.*?);(.*)!s", $cookie, $preger); + if ($preger[2] == 'DELETED') + unset($this->cookie[$preger[1]]); + else + $this->cookie[$preger[1]] = $preger[2] . ';' . $preger[3]; + } + } + + /** + * @return false|string + */ + public function dumpCookie() + { + return json_encode($this->cookie); + } + + /** + * @return bool + */ + public function isAuth() + { + $header = $this->getCURL("https://vk.com/feed")['header']; + if (isset($header['location'][0]) and strpos($header['location'][0], 'login.vk.com')) + return False; + return True; + } + + /** + * @param null $captcha_key + * @param null $captcha_sid + * @return string + * @throws VkApiException + */ + public function getAccessToken($captcha_key = null, $captcha_sid = null) + { + if ($this->access_token != '') + return $this->access_token; + if ($this->auth_method) { + if ($this->is_auth == 0) + $this->loginInVK(); + if ($this->access_token == '') + $this->access_token = $this->generateAccessToken(); + } else { + if (isset($this->captcha_sid)) + $captcha_sid = $this->captcha_sid; + $this->access_token = $this->generateAccessTokenMobile($captcha_key, $captcha_sid); + } + return $this->access_token; + } + + /** + * @param null $scope + * @param bool $resend + * @return mixed + * @throws VkApiException + */ + private function generateAccessToken($scope = null, $resend = false) + { + $this->scope = []; + if (!isset($scope)) { + $scope = $this->default_scope; + } + foreach (preg_split("!,!", $scope) as $one_scope) + $this->scope[] = $one_scope; + $scope = "&scope=$scope"; + + if ($resend) + $scope .= "&revoke=1"; + + $token_url = 'https://oauth.vk.com/authorize?client_id=' . $this->id_app . + $scope . + '&response_type=token'; + + $get_url_token = $this->getCURL($token_url); + + if (isset($get_url_token['header']['location'][0])) + $url_token = $get_url_token['header']['location'][0]; + else { + preg_match('!location.href = "(.*)"\+addr!s', $get_url_token['body'], $url_token); + + if (!isset($url_token[1])) { + throw new VkApiException("Не получилось получить токен на этапе получения ссылки подтверждения"); + } + $url_token = $url_token[1]; + } + + $access_token_location = $this->getCURL($url_token)['header']['location'][0]; + + if (preg_match("!access_token=(.*?)&!s", $access_token_location, $access_token) != 1) + throw new VkApiException("Не удалось найти access_token в строке ридеректа, ошибка:" . $this->getCURL($access_token_location, null, false)['body']); + return $access_token[1]; + } + + /** + * @param $captcha_key + * @param $captcha_sid + * @return mixed + * @throws VkApiException + */ + private function generateAccessTokenMobile($captcha_key, $captcha_sid) + { + if (!isset($this->pass)) + throw new VkApiException("Метод работает только с логином и паролем"); + + $captcha = ''; + $this->scope = []; + $scope = $this->default_scope; + foreach (preg_split("!,!", $scope) as $one_scope) + $this->scope[] = $one_scope; + $scope = "&scope=$scope"; + + if (isset($captcha_sid) and isset($captcha_key)) + $captcha = "&captcha_sid=$captcha_sid&captcha_key=$captcha_key"; + + $token_url = 'https://oauth.vk.com/token?grant_type=password&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH' . + '&username=' . $this->login . + '&password=' . $this->pass . + $scope . + $captcha; + $response_auth = $this->getCURL($token_url, null, false)['body']; + $response_auth = json_decode($response_auth, true); + + if (isset($response_auth['access_token'])) + return $response_auth['access_token']; + else + throw new VkApiException(json_encode($response_auth)); + } +} diff --git a/Base.php b/Base.php new file mode 100644 index 0000000..3b094fe --- /dev/null +++ b/Base.php @@ -0,0 +1,210 @@ +vk_api = $vk_api; + } + + /** + * @throws VkApiException + */ + public function addImage() + { + $this->addMedia(func_get_args(), 'images'); + } + + /** + * @param $media + * @param $selector + * @throws VkApiException + */ + protected function addMedia($media, $selector) + { + if ($this->countMedia() + count($media) > 10) + throw new VkApiException('Вы превысили максимальный лимит в 10 файлов'); + else { + if (is_array($media)) + foreach ($media as $val) { + if (is_array($val) and $selector != 'docs') { + if (isset($this->media[$selector])) + $this->media[$selector] = array_merge($this->media[$selector], $val); + else + $this->media[$selector] = $val; + } else + $this->media[$selector][] = $val; + } + else + $this->media[$selector][] = $media; + } + + } + + /** + * @return int + */ + private function countMedia() + { + $count = 0; + foreach ($this->media as $kye => $var) { + $count += count($var); + } + return $count; + } + + /** + * @param $prop + * @param $value + * @return int + */ + public function addProp($prop, $value) + { + if (!in_array($prop, $this->prop_list)) + return 0; + $this->props += [$prop => $value]; + return $prop; + } + + /** + * @param $docs + * @param null $title + * @throws VkApiException + */ + public function addDocs($docs, $title = null) + { + if (is_string($docs)) + $docs = [0 => ['path' => $docs, 'title' => $title]]; + else + foreach ($docs as $id => $file) { + if (is_string($file)) + $docs[$id] = ['path' => $file, 'title' => null]; + } + $this->addMedia($docs, 'docs'); + } + + /** + * @param $images + * @return int + */ + public function removeImages($images) + { + return $this->removeMedia($images, 'images'); + } + + /** + * @param $media + * @param $selector + * @return int + */ + protected function removeMedia($media, $selector) + { + $search = array_search($media, $this->media[$selector]); + if ($search) { + $remove_val = $this->media[$selector][$search]; + unset($this->media[$selector][$search]); + return $remove_val; + } + if (is_numeric($media) and ($media >= 0 and $media <= count($this->media[$selector]) - 1)) { + $remove_val = $this->media[$selector][$media]; + unset($this->media[$selector][$media]); + return $remove_val; + } + return 0; + } + + /** + * @param $docs + * @return int + */ + public function removeDocs($docs) + { + return $this->removeMedia($docs, 'docs'); + } + + /** + * @param $prop + * @return int|mixed + */ + public function removeProp($prop) + { + $search = array_search($prop, $this->props); + if ($search) { + $remove_val = $this->props[$search]; + unset($this->props[$search]); + return $remove_val; + } + if (is_numeric($prop) and ($prop >= 0 and $prop <= count($this->props) - 1)) { + $remove_val = $this->props[$prop]; + unset($this->props[$prop]); + return $remove_val; + } + return 0; + } + + /** + * @return array + */ + public function getMedia() + { + if (isset($this->media)) + return $this->media; + else return []; + } + + /** + * @return array + */ + public function getMessage() + { + return $this->message; + } + + /** + * @param $message + */ + public function setMessage($message) + { + $this->message = $message; + } + + /** + * @return array + */ + public function getProps() + { + return $this->props; + } + +} \ No newline at end of file diff --git a/Coin.php b/Coin.php new file mode 100644 index 0000000..9812141 --- /dev/null +++ b/Coin.php @@ -0,0 +1,301 @@ +merchant_key = $token; + $this->merchant_id = $merchant_id; + } + + /** + * @param $token + * @param $merchant_id + * @return Coin + */ + public static function create($token, $merchant_id) { + return new self($token, $merchant_id); + } + + /** + * @param $user_id + * @param int $amount + * @return array|bool + */ + public function sendCoins($user_id, $amount) { + try { + $amount = $this->request('send', ['amount' => $amount * 1000, 'toId' => $user_id]); + if (isset($amount['amount']) && isset($amount['current'])) { + $amount['amount'] /= 1000; + $amount['current'] /= 1000; + } + return 1; + } catch (VkApiException $e) { + return 0; + } + } + + + /** + * @param array $user_ids + * @return array|bool + * @throws VkApiException + */ + public function getBalance($user_ids = []) { + if (empty($user_ids) or !is_array($user_ids)) + $user_ids = empty($user_ids) ? [$this->merchant_id] : [$user_ids]; + $results = $this->request('score', ['userIds' => $user_ids]); + if (count($results) < count($user_ids)) { + $nonexistent_id = join(',', (array_diff($user_ids, array_keys($results)))); + throw new VkApiException("Попытка получить баланс следущих несуществующих пользователей:\n$nonexistent_id"); + } + $this->_toCoin($results); + $results = array_combine($user_ids, array_values($results)); + if (is_array($user_ids) && count($user_ids) == 1) + return $results[current($user_ids)]; + else + return $results; + } + + /** + * @param string $name + * @return array|bool + * @throws VkApiException + */ + public function setName($name) { + return $this->request('set', ['name' => $name]); + } + + + /** + * @param string $url + * @return array|bool + * @throws VkApiException + */ + public function setCallBack($url = null) { + return $this->request('set', ['callback' => $url]); + } + + + /** + * @return array|bool + * @throws VkApiException + */ + public function deleteCallBack() { + return $this->request('set', ['callback' => null]); + } + + + /** + * @return array|bool + * @throws VkApiException + */ + public function getLogs() { + return $this->request('set', ['status' => 1]); + } + + /** + * @param int $sum + * @param int $payload + * @param bool $fixed_sum + * @param bool $to_hex + * @return array|string + */ + public function getLink($sum = 0, $fixed_sum = true, $payload = 0, $to_hex = false) { + $payload = ($payload !== 0) ? $payload : rand(-2000000000, 2000000000); + $fixed_sum = $fixed_sum ? '' : '_1'; + if ($sum === 0) + return 'vk.com/coin#t' . $this->merchant_id; + $sum = (int)($sum * 1000); + if ($to_hex) { + $merchant_id = dechex($this->merchant_id); + $sum = dechex($sum); + $payload = dechex($payload); + return ['url' => "vk.com/coin#m{$merchant_id}_{$sum}_{$payload}{$fixed_sum}", 'payload' => $payload]; + } else { + $merchant_id = $this->merchant_id; + return ['url' => "vk.com/coin#x{$merchant_id}_{$sum}_{$payload}{$fixed_sum}", 'payload' => $payload]; + } + } + + /** + * @param array $last_tx + * @return bool|mixed + * @throws VkApiException + */ + public function getStoryShop($last_tx = []) { + return $this->getTransaction(1, $last_tx); + } + + /** + * @param array $last_tx + * @return bool|mixed + * @throws VkApiException + */ + public function getStoryAccount($last_tx = []) { + return $this->getTransaction(2, $last_tx); + } + + /** + * @param array $transaction + * @return bool|mixed + * @throws VkApiException + */ + public function getInfoTransactions($id_transactions) { + if (is_array($id_transactions)) + return $this->getTransaction($id_transactions); + else if (is_numeric($id_transactions)) + return $this->getTransaction([$id_transactions]); + return 0; + } + + /** + * @param $from_id + * @param $amount + * @param $payloadа + * @param $verify + * @param $data + */ + public function initVars(&$from_id, &$amount, &$payload, &$verify, &$data) { + print 'OK'; + $data_request = json_decode(file_get_contents('php://input')); + $data = $this->data_request = $data_request; + if (is_object($this->data_request) && + isset($this->data_request->id) && + isset($this->data_request->from_id) && + isset($this->data_request->amount) && + isset($this->data_request->payload) && + isset($this->data_request->key)) { + $from_id = $data_request->from_id; + $payload = $data_request->payload; + $amount = $data_request->amount; + $verify = $this->verifyKeys(); + } + } + + /** + * @return bool + */ + private function verifyKeys() { + $parameters = [ + $this->data_request->id, + $this->data_request->from_id, + $this->data_request->amount, + $this->data_request->payload, + $this->data_request->merchant_key, + ]; + $key = md5(implode(';', $parameters)); + return $this->data_request->key === $key; + } + + /** + * @param $tx + * @param array $last_tx + * @return bool|mixed + * @throws VkApiException + */ + private function getTransaction($tx, $last_tx = []) { + if (!empty($last_tx)) + $last_tx = ['lastTx' => $last_tx]; + if (!is_array($tx)) + $tx = [$tx]; + $request = $this->request('tx', ['tx' => $tx] + $last_tx); + $this->_toCoin($request); + return $request; + } + + /** + * @param $results + */ + private function _toCoin(&$results) { + if (is_array($results)) + foreach ($results as $key => $value) { + if (is_array($value) && isset($results[$key]['amount'])) + @$results[$key]['amount'] = is_int($results[$key]['amount']) ? + (float)($value['amount'] / 1000) : + $results[$key]['amount']; + else + $results[$key] = (float)($value / 1000); + } + } + + /** + * @param $method + * @param array $params + * @return bool|mixed + * @throws VkApiException + */ + private function request($method, $params = []) { + $params['merchantId'] = $this->merchant_id; + $params['key'] = $this->merchant_key; + + $url = 'https://coin-without-bugs.vkforms.ru/merchant/' . $method . '/'; + try { + return $this->request_core($url, $params); + } catch (VkApiException $e) { + $exception = json_decode($e->getMessage(), true); + if (in_array($exception['error']['code'], [500, 422])) + throw new VkApiException($exception['error']['message']); + else + throw new VkApiException($e->getMessage()); + } + } + + /** + * @param $url + * @param array $params + * @return mixed + * @throws VkApiException + */ + private function request_core($url, $params = []) { + if (function_exists('curl_init')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json' + ]); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params, JSON_UNESCAPED_UNICODE)); + $result = json_decode(curl_exec($ch), True); + curl_close($ch); + } else { + $result = json_decode(file_get_contents($url, true, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => "Content-Type: application/json\r\n", + 'content' => http_build_query($params) + ] + ])), true); + } + if (!isset($result) or isset($result['error'])) + throw new VkApiException('Вк вернул ошибку:' . json_encode($result)); + if (isset($result['response'])) + return $result['response']; + else + return $result; + } +} diff --git a/Execute.php b/Execute.php new file mode 100644 index 0000000..d6dc1ca --- /dev/null +++ b/Execute.php @@ -0,0 +1,272 @@ +copyAllDataclass()); + $this->vk = $vk; + } + + public function __destruct() { + $this->exec(); + } + + /** + * @param null $id + * @param null $message + * @param null $payload + * @param null $user_id + * @param null $type + * @param null $data + * @return array|mixed|null + */ + public function initVars(&$id = null, &$message = null, &$payload = null, &$user_id = null, &$type = null, &$data = null) { + if (!$this->vk->debug_mode) + $this->vk->sendOK(); + $data = $this->vk->data; + $data_backup = $this->vk->data; + $type = isset($data->type) ? $data->type : null; + if($type == 'message_new' && isset($data->object->message)) { + $data->object = $data->object->message; + } + $id = isset($data->object->peer_id) ? $data->object->peer_id : null; + $message = isset($data->object->text) ? $data->object->text : null; + $payload = isset($data->object->payload) ? json_decode($data->object->payload, true) : null; + $user_id = isset($data->object->from_id) ? $data->object->from_id : null; + $data = $data_backup; + return $data_backup; + } + + public function sendMessage($id, $message, $props = []) { + $message = $this->vk->placeholders($id, $message); + $this->messages[] = ['peer_id' => $id, 'message' => $message, "random_id" => rand(-2147483648, 2147483647)] + $props; + $this->counter += 1; + $this->checkExec(); + } + + public function sendButton($id, $message, $buttons = [], $inline = false, $one_time = False, $params = []) { + $keyboard = $this->generateKeyboard($buttons, $inline, $one_time); + $message = $this->vk->placeholders($id, $message); + $this->messages[] = ['message' => $message, 'peer_id' => $id, 'keyboard' => $keyboard, "random_id" => rand(-2147483648, 2147483647)] + $params; + $this->counter += 1; + $this->checkExec(); + } + + public function reply($message, $params = []) { + if ($this->vk->data != []) { + return $this->sendMessage($this->vk->data->object->peer_id, $message, $params); + } else { + throw new VkApiException('Вк не прислал callback, возможно вы пытаетесь запустить скрипт с локалки'); + } + } + + private function generateUrlPhotos($id, $count) { + $code = []; + for ($i = 0; $i < $count; ++$i) + $code[] = "API.photos.getMessagesUploadServer({\"peer_id\" : $id})"; + return $this->request("execute", ["code" => "return [".join(',', $code). "];"]); + } + + private function generateUrlDocs($id, $count) { + $code = []; + for ($i = 0; $i < $count; ++$i) + $code[] = "API.docs.getMessagesUploadServer({\"peer_id\" : $id, \"type\": \"doc\"})"; + return $this->request("execute", ["code" => "return [".join(',', $code). "];"]); + } + + public function createMessages($id, $message = [], $props = [], $media = [], $keyboard = []) { + + if (!isset($media['images'])) + $media['images'] = []; + if (!isset($media['docs'])) + $media['docs'] = []; + + if (count($media['docs']) + count($media['images']) + 1 + $this->counter > Execute::$max_counter) + $this->exec(); + + if (count($media['images']) != 0) + $photo_urls = $this->generateUrlPhotos($id, count($media['images'])); + + if (count($media['docs']) != 0) + $doc_urls = $this->generateUrlDocs($id, count($media['docs'])); + + if ($keyboard != []) + $object = [ + 'id' => $id, + 'message' => $message, + 'keyboard_content' => $this->generateKeyboard($keyboard['keyboard'], $keyboard['inline'], $keyboard['one_time']), + 'images_content' => [], + 'docs_content' => [] + ]; + else + $object = [ + 'id' => $id, + 'message' => $message, + 'keyboard_content' => [], + 'images_content' => [], + 'docs_content' => [] + ]; + + foreach ($media as $selector => $massiv) { + switch ($selector) { + case "images": + foreach ($massiv as $key => $image) { + for ($i = 0; $i < $this->try_count_resend_file; ++$i) { + try { + $answer_vk = json_decode($this->sendFiles($photo_urls[$key]['upload_url'], $image, 'photo'), true); + $object['images_content'][] = ['photo' => $answer_vk['photo'], 'server' => $answer_vk['server'], 'hash' => $answer_vk['hash']]; + $this->counter += 1; + break; + } catch (VkApiException $e) { + sleep(1); + $exception = json_decode($e->getMessage(), true); + if ($exception['error']['error_code'] != 121) + throw new VkApiException($e->getMessage()); + } + } + } + break; + case "docs": + foreach ($massiv as $key => $document) { + for ($i = 0; $i < $this->try_count_resend_file; ++$i) { + try { + $title = isset($document['title']) ? $document['title'] : preg_replace("!.*?/!", '', $document); + $answer_vk = json_decode($this->sendFiles($doc_urls[$key]['upload_url'], $document['path']), true); + $object['docs_content'][] = ['file' => $answer_vk['file'], 'title' => $title]; + $this->counter += 1; + break; + } catch (VkApiException $e) { + sleep(1); + $exception = json_decode($e->getMessage(), true); + if ($exception['error']['error_code'] != 121) + throw new VkApiException($e->getMessage()); + } + } + } + break; + case "other": + break; + } + } + $this->counter += 1; + $this->constructors_messages[] = $object; + $this->checkExec(); + return true; + } + + private function getConversationsExec($offset) { + $code = 'var count = API.messages.getConversations({"count": 200, "offset": 0})["count"]; +var start_offset = '. $offset .'; +var temp_count = 0; +var count_apis = 1; +var result = []; +var write_allowed = []; +var ids = []; +while ((temp_count + start_offset) < count && count_apis < 25) { + result = API.messages.getConversations({"count": 200, "offset": (temp_count + start_offset)})["items"]@.conversation; + write_allowed = write_allowed + result@.can_write@.allowed; + ids = ids + result@.peer@.id; + temp_count = temp_count + 200; + count_apis = count_apis + 1; +} +return {"count": count, "offset_ok": (temp_count + start_offset),"write_allowed": write_allowed, "ids": ids};'; +// $code = 'return API.messages.getConversations({"count": 200, "offset": 0})["count"];'; + return $this->request("execute", ["code" => $code]); + } + + private function getConversationsIds() { + $ids = []; + + $exec_result = [ + "count" => 1, + "offset_ok" => 0 + ]; + while ($exec_result['count'] > $exec_result['offset_ok']) { + $exec_result = $this->getConversationsExec($exec_result['offset_ok']); + echo "{$exec_result['offset_ok']} / {$exec_result['count']}, "; + foreach ($exec_result['write_allowed'] as $key => $var) + if ($var) + $ids [] = $exec_result['ids'][$key]; + } + $count = count($ids); + $ids = array_unique($ids); + echo "Complete!\nВсего id: ".$count."\nДубликатов: ".($count - count($ids))."\n"; + return $ids; + } + +// public function sendAllDialogs($message) { +// $ids = $this->getConversationsIds(); +// $ids = array_chunk($ids, 100); +// foreach ($ids as $ids_chunk) { +// $this->messages[] = ['user_ids' => join(',', $ids_chunk), 'message' => $message, "random_id" => rand(-2147483648, 2147483647)]; +// $this->counter += 1; +// $this->checkExec(); +// } +// echo "COUNT = ".$this->counter."\n"; +// } + + private function checkExec() { + if ($this->counter >= Execute::$max_counter) + return $this->exec(); + return false; + } + + public function exec() { + if ($this->counter == 0) + return false; + $this->counter = 0; + $code = 'var query = '. json_encode($this->constructors_messages, JSON_UNESCAPED_UNICODE) .'; +var query_message = '. json_encode($this->messages, JSON_UNESCAPED_UNICODE) .'; + +var count = 0; +var count_image = 0; +var text_attach_photo = ""; +var resulter = []; + +var data_result = []; + +while (query[count] != null) { + text_attach_photo = ""; + resulter = []; + count_image = 0; + while (query[count]["images_content"][count_image] != null) { + resulter = API.photos.saveMessagesPhoto(query[count]["images_content"][count_image]); + if (text_attach_photo == "") { + text_attach_photo = "photo" + resulter[0]["owner_id"] + "_" + resulter[0]["id"]; + } else { + text_attach_photo = text_attach_photo + ",photo" + resulter[0]["owner_id"] + "_" + resulter[0]["id"]; + } + count_image = count_image + 1; + } + count_image = 0; + while (query[count]["docs_content"][count_image] != null) { + resulter = API.docs.save(query[count]["docs_content"][count_image]); + if (text_attach_photo == "") { + text_attach_photo = "doc" + resulter["doc"]["owner_id"] + "_" + resulter["doc"]["id"]; + } else { + text_attach_photo = text_attach_photo + ",doc" + resulter["doc"]["owner_id"] + "_" + resulter["doc"]["id"]; + } + count_image = count_image + 1; + } + data_result.push(API.messages.send({"peer_id": query[count]["id"], "message": query[count]["message"], "random_id": 0, "attachment": text_attach_photo, "keyboard": query[count]["keyboard_content"]})); + count = count + 1; +} + +count = 0; +while (query_message[count] != null) { + data_result.push(API.messages.send(query_message[count])); + count = count + 1; +} + +return data_result;'; + $this->messages = []; + $this->constructors_messages = []; + return $this->request("execute", ["code" => $code]); + } +} diff --git a/Group.php b/Group.php new file mode 100644 index 0000000..1891d40 --- /dev/null +++ b/Group.php @@ -0,0 +1,45 @@ +groupID = $groupID; + parent::setAllDataclass($vk_api->copyAllDataclass()); + } + + /** + * @param $method + * @param $params + * @return array + */ + protected function editRequestParams($method, $params) + { +// if ($method == 'messages.send' or $method == 'photos.saveMessagesPhoto') + $params['group_id'] = $this->groupID; + return [$method, $params]; + } +} \ No newline at end of file diff --git a/LongPoll.php b/LongPoll.php new file mode 100644 index 0000000..bd0a9ee --- /dev/null +++ b/LongPoll.php @@ -0,0 +1,219 @@ +copyAllDataclass()); + $this->vk = $vk; + $data = $this->vk->userInfo(); + if ($data != false) { + $this->vk->auth_type = 'user'; + $this->user_id = $data['id']; + } else { + $this->vk->auth_type = 'group'; + $this->group_id = $this->vk->request('groups.getById', [])[0]['id']; + $this->vk->request('groups.setLongPollSettings', [ + 'group_id' => $this->group_id, + 'enabled' => 1, + 'api_version' => $this->vk->version, + 'message_new' => 1, + ]); + } + $this->getLongPollServer(); + } + + /** + * + */ + public function getLongPollServer() + { + if ($this->vk->auth_type == 'user') + $data = $this->vk->request('messages.getLongPollServer', ['need_pts' => 1, 'lp_version' => 3]); + else + $data = $this->vk->request('groups.getLongPollServer', ['group_id' => $this->group_id]); + unset($this->key); + unset($this->server); + unset($this->ts); + list($this->key, $this->server, $this->ts) = [$data['key'], $data['server'], $data['ts']]; + } + + /** + * @param $anon + * @throws VkApiException + */ + public function listen($anon) + { + while ($data = $this->processingData()) { + foreach ($data->updates as $event) { + unset($this->vk->data); + $this->vk->data = $event; + $anon($event); + } + if ($this->vk instanceof Execute) { + $this->vk->exec(); + } + } + } + + /** + * @return mixed + * @throws VkApiException + */ + public function processingData() + { + $data = $this->getData(); + if (isset($data->failed)) { + if ($data->failed == 1) { + unset($this->ts); + $this->ts = $data->ts; + } + else { + $this->getLongPollServer(); + $data = $this->getData(); + } + } + unset($this->ts); + $this->ts = $data->ts; + return $data; + } + + /** + * @return mixed + * @throws VkApiException + */ + public function getData() + { + $defult_params = ['act' => 'a_check', 'key' => $this->key, 'ts' => $this->ts, 'wait' => 55]; + if($this->vk->auth_type == 'user') { + $params = ['mode' => 32, 'version' => 3]; + $data = $this->request_core('https://' . $this->server . '?', $defult_params + $params); + } else { + $data = $this->request_core($this->server . '?', $defult_params); + } + return $data; + } + + /** + * @param $type + * @param $anon + */ + public function on($type, $anon) + { + $summands = []; + $data = json_decode(json_encode($this->vk->data), true); + switch ($type) { + case 'message_new': + { + if ($data[0] == 4) { + foreach ([1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 65536] as $key) { + if ($data[2] & $key) + $summands[] = $key; + } + if (!in_array(2, $summands)) { //только входящие сообщения + $this->vk->data = []; + $this->vk->data['object']['peer_id'] = $data[3]; + $this->vk->data['object']['text'] = $data[5]; + $this->vk->data = json_decode(json_encode($this->vk->data)); + $anon($data); + } + } + break; + } + } + } + + /** + * @param $id + * @param null $message + * @param null $payload + * @param null $user_id + * @param null $type + * @param null $data + * @return |null + */ + public function initVars(&$id = null, &$message = null, &$payload = null, &$user_id = null, &$type = null, &$data = null) + { + $data = $this->vk->data; + $data_backup = $this->vk->data; + $type = isset($data->type) ? $data->type : null; + if($type == 'message_new' && isset($data->object->message)) { + $data->object = $data->object->message; + } + $id = isset($data->object->peer_id) ? $data->object->peer_id : null; + $message = isset($data->object->text) ? $data->object->text : null; + $payload = isset($data->object->payload) ? json_decode($data->object->payload, true) : null; + $user_id = isset($data->object->from_id) ? $data->object->from_id : null; + $data = $data_backup; + return $data_backup; + } + + public function reply($message, $params = []) { + $message = $this->vk->placeholders($this->vk->data->object->peer_id, $message); + return $this->vk->request('messages.send', ['message' => $message, 'peer_id' => $this->vk->data->object->peer_id] + $params); + } + + /** + * @param $url + * @param array $params + * @return mixed + * @throws VkApiException + */ + private function request_core($url, $params = []) + { + if (function_exists('curl_init')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url.http_build_query($params)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + $result = json_decode(curl_exec($ch)); + curl_close($ch); + } else { + $result = json_decode(file_get_contents($url, true, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'content' => http_build_query($params) + ] + ]))); + } + if (!isset($result) or isset($result->error)) + throw new VkApiException(json_encode($result)); + return $result; + } +} diff --git a/Message.php b/Message.php new file mode 100644 index 0000000..87c5fb2 --- /dev/null +++ b/Message.php @@ -0,0 +1,64 @@ +prop_list = ['random_id', 'domain', 'chat_id', 'user_ids', 'lat', 'long', 'forward_messages', + 'sticker_id', 'payload']; + parent::__construct($vk_api); + } + + /** + * @return array + */ + public function getKeyboard() + { + return $this->keyboard; + } + + /** + * @param array $keyboard + * @param bool $inline + * @param bool $one_time + */ + public function setKeyboard($keyboard = [], $inline = false, $one_time = false) + { + $this->keyboard = ['keyboard' => $keyboard, 'inline' => $inline, 'one_time' => $one_time]; + } + + public function addVoice() + { + $this->addMedia(func_get_args(), 'voice'); + } + + public function removeVoice($voice) + { + return $this->removeMedia($voice, 'voice'); + } + + /** + * @param $id + * @return mixed + */ + public function send($id) + { + return $this->vk_api->createMessages($id, $this->message, $this->props, $this->media, $this->keyboard); + } +} diff --git a/Post.php b/Post.php new file mode 100644 index 0000000..c36687e --- /dev/null +++ b/Post.php @@ -0,0 +1,39 @@ +prop_list = ['friends_only', 'from_group', 'services', 'signed', 'publish_date', 'lat', 'long', 'place_id', + 'post_id', 'guid', 'mark_as_ads', 'close_comments']; + parent::__construct($vk_api); + } + + /** + * @param $id + * @param null $publish_date + * @return mixed + * @throws VkApiException + */ + public function send($id, $publish_date = null) + { + if ($publish_date >= time()) + $this->props['publish_date'] = $publish_date; + else if ($publish_date == null) + $this->props['publish_date'] = time(); + else + throw new VkApiException('Неверно указан $publish_date'); + return $this->vk_api->createPost($id, $this->message, $this->props, $this->media); + } +} \ No newline at end of file diff --git a/SiteAuth.php b/SiteAuth.php new file mode 100644 index 0000000..060c69f --- /dev/null +++ b/SiteAuth.php @@ -0,0 +1,42 @@ +settings = $settings; + } + } + + public function auth() { + if (isset($_GET['code'])) { + $query = urldecode(http_build_query($this->settings + ["code" => $_GET['code']])); + $token = json_decode(file_get_contents("https://oauth.vk.com/access_token?" . $query), true); + if (isset($token["access_token"])) { + $this->data = $token; + return true; + } + } + return false; + } + + public function get_link() { + $query = urldecode(http_build_query([ + "client_id" => $this->settings["client_id"], + "redirect_uri" => $this->settings["redirect_uri"], + "response_type" => "code" + ])); + return "https://oauth.vk.com/authorize?" . $query; + } +} diff --git a/VkApiException.php b/VkApiException.php new file mode 100644 index 0000000..2687c77 --- /dev/null +++ b/VkApiException.php @@ -0,0 +1,29 @@ +__toString()."\n"; + parent::__construct($message, $code, $previous); + } + + public function __toString() { + $error = "[Exception]: возникла ошибка:"; + $error .= "\r\n[Exception]: текст: {$this->getMessage()}"; + $error .= "\r\n[Exception]: код ошибки: {$this->getCode()}"; + $error .= "\r\n[Exception]: файл: {$this->getFile()}:{$this->getLine()}"; + $error .= "\r\n[Exception]: путь ошибки: {$this->getTraceAsString()}\r\n"; + if (!is_dir('error')) + mkdir('error'); + $file = fopen('error/error_log' . date('d-m-Y_h') . ".log", 'a'); + fwrite($file, $error); + fclose($file); +// exit(); + return $error; + // parent::__toString(); // TODO: Change the autogenerated stub + } +} diff --git a/config_library.php b/config_library.php new file mode 100644 index 0000000..df128ec --- /dev/null +++ b/config_library.php @@ -0,0 +1,20 @@ +auth = $token; + $this->version = $version; + $this->token = $this->auth->getAccessToken(); + } else if (isset($also_version)) { + $this->auth = new Auth($token, $version); + $this->token = $this->auth->getAccessToken(); + $this->version = $also_version; + } else { + $this->token = $token; + $this->version = $version; + } + $this->data = json_decode(file_get_contents('php://input')); + } + + /** + * @param $token + * @param $version + * @param null $also_version + * @return vk_api + * + * @throws VkApiException + */ + public static function create($token, $version, $also_version = null) { + return new self($token, $version, $also_version); + } + + /** + * @param $str + * @return vk_api + */ + public function setConfirm($str) { + if (isset($this->data->type) && $this->data->type == 'confirmation') { //Если vk запрашивает ключ + exit($str); //Завершаем скрипт отправкой ключа + } + return $this; + } + + /** + * @param null $id + * @param null $message + * @param null $payload + * @param null $user_id + * @param null $type + * @param null $data + * @return array|mixed|null + */ + public function initVars(&$id = null, &$message = null, &$payload = null, &$user_id = null, &$type = null, &$data = null) { + if (!$this->debug_mode) + $this->sendOK(); + $data = $this->data; + $data_backup = $this->data; + $type = isset($data->type) ? $data->type : null; + if(isset($data->object->message) and $type == 'message_new') { + $data->object = $data->object->message; //какая-то дичь с ссылками, но $this->data теперь тоже переопределился + } + $id = isset($data->object->peer_id) ? $data->object->peer_id : null; + $message = isset($data->object->text) ? $data->object->text : null; + $payload = isset($data->object->payload) ? json_decode($data->object->payload, true) : null; + $user_id = isset($data->object->from_id) ? $data->object->from_id : null; + $data = $data_backup; + return $data_backup; + } + + /** + * @return bool + */ + protected function sendOK() { + set_time_limit(0); + ini_set('display_errors', 'Off'); + + // для Nginx + if (is_callable('fastcgi_finish_request')) { + echo 'ok'; + session_write_close(); + fastcgi_finish_request(); + return True; + } + // для Apache + ignore_user_abort(true); + + ob_start(); + header('Content-Encoding: none'); + header('Content-Length: 2'); + header('Connection: close'); + echo 'ok'; + ob_end_flush(); + flush(); + return True; + } + + /** + * @param $message + * @param array $params + * @return bool|mixed + * @throws VkApiException + */ + public function reply($message, $params = []) { + if ($this->data != []) { + $message = $this->placeholders($this->data->object->peer_id, $message); + return $this->request('messages.send', ['message' => $message, 'peer_id' => $this->data->object->peer_id] + $params); + } else { + throw new VkApiException('Вк не прислал callback, возможно вы пытаетесь запустить скрипт с локалки'); + } + } + + public function forward($id, $id_messages, $params = []) { + $forward_messages = (is_array($id_messages)) ? join(',', $id_messages) : $id_messages; + return $this->request('messages.send', ['peer_id' => $id, 'forward_messages' => $forward_messages] + $params); + } + + public function sendAllChats($message, $params = []) { + unset($this->request_ignore_error[array_search(10, $this->request_ignore_error)]); //убираем код 10 из исключений + $i = 0; + $count = 0; + print "Начинаю перебор всех бесед...\n"; + while (true) { + print(++$i . " "); + try { + $this->sendMessage(2000000000 + $i, $message, $params); + $count++; + } catch (VkApiException $e) { + if ($e->getCode() == 10) { + print "\nВсего было разослано в $count бесед"; + break; + } + } + } + } + + protected function placeholders($id, $message) { + if($id >= 2000000000) { + $id = isset($this->data->object->from_id) ? $this->data->object->from_id : null; + } + if($id == null) { + print "Попытка использовать заполнители при передаче id беседы"; + return $message; + } else { + if (strpos($message, '%') !== false) { + $data = $this->userInfo($id); + $f = $data['first_name']; + $l = $data['last_name']; + $tag = ['%fn%', '%ln%', '%full%', '%a_fn%', '%a_ln%', '%a_full%']; + $replace = [$f, $l, "$f $l", "@id{$id}($f)", "@id{$id}($l)", "@id{$id}($f $l)"]; + return str_replace($tag, $replace, $message); + } else + return $message; + } + } + + /** + * @param $method + * @param array $params + * @return bool|mixed + * @throws VkApiException + */ + public function request($method, $params = []) { + list($method, $params) = $this->editRequestParams($method, $params); + $url = 'https://api.vk.com/method/' . $method; + $params['access_token'] = $this->token; + $params['v'] = $this->version; + $params['random_id'] = rand(-2147483648, 2147483647); + + while (True) { + try { + return $this->request_core($url, $params); + } catch (VkApiException $e) { + if (in_array($e->getCode(), $this->request_ignore_error)) { + sleep(1); + continue; + } + else + throw new VkApiException($e->getMessage(), $e->getCode()); + } + } + return false; + } + + /** + * @param $method + * @param $params + * @return array + */ + protected function editRequestParams($method, $params) { + return [$method, $params]; + } + + /** + * @param $url + * @param array $params + * @return mixed + * @throws VkApiException + */ + private function request_core($url, $params = []) { + if (function_exists('curl_init')) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type:multipart/form-data" + ]); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + $result = json_decode(curl_exec($ch), True); + curl_close($ch); + } else { + $result = json_decode(file_get_contents($url, true, stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'content' => http_build_query($params) + ] + ])), true); + } + if (!isset($result)) + $this->request_core($url, $params); + if (isset($result['error'])) { + throw new VkApiException(json_encode($result), $result['error']['error_code']); + } + if (isset($result['response'])) + return $result['response']; + else + return $result; + } + + /** + * @param $message + * @param null $keyboard + * @param string $filter + * @param array $params + * @throws VkApiException + */ + public function sendAllDialogs($message, $keyboard = null, $filter = 'all', $params = []) { + $ids = []; + for ($count_all = 1, $offset = 0; $offset <= $count_all; $offset += 200) { + $members = $this->request('messages.getConversations', ['count' => 200, 'offset' => $offset, 'filter' => $filter]);//'filter' => 'unread' + if ($count_all != 1) + $offset += $members['count'] - $count_all; + $count_all = $members['count']; + + foreach ($members["items"] as $user) + if ($user['conversation']["can_write"]["allowed"] == true) + $ids [] = $user['conversation']['peer']['id']; + } + $ids = array_chunk($ids, 100); + foreach ($ids as $ids_chunk) { + try { + $this->request('messages.send', ['user_ids' => join(',', $ids_chunk), 'message' => $message, 'keyboard' => $keyboard] + $params); + } catch (Exception $e) { + continue; + } + } + } + + /** + * @param $id + * @param null $n + * @return string + * @throws VkApiException + */ + public function getAlias($id, $n = null) { //получить обращение к юзеру или группе + if (!is_numeric($id)) { //если короткая ссылка + $obj = $this->request('utils.resolveScreenName', ['screen_name' => $id]); //узнаем, кому принадлежит, сообществу или юзеру + $id = ($obj["type"] == 'group') ? -$obj['object_id'] : $obj['object_id']; + } + if (isset($n)) { + if (is_string($n)) { + if ($id < 0) + return "@club" . ($id * -1) . "($n)"; + else + return "@id{$id}($n)"; + } else { + if ($id < 0) { + $id = -$id; + $group_name = $this->request('groups.getById', ['group_id' => $id])[0]['name']; + return "@club{$id}({$group_name})"; + } else { + $info = $this->userInfo($id); + if ($n) + return "@id{$id}($info[first_name] $info[last_name])"; + else + return "@id{$id}($info[first_name])"; + } + } + } else { + if ($id < 0) + return "@club" . ($id * -1); + else + return "@id{$id}"; + } + } + + /** + * @param null $user_url + * @param array $scope + * @return mixed + * @throws VkApiException + */ + public function userInfo($user_url = '', $scope = []) { + $scope = ["fields" => join(",", $scope)]; + if (isset($user_url)) { + $user_url = preg_replace("!.*?/!", '', $user_url); + $user_url = ($user_url == '') ? [] : ["user_ids" => $user_url]; + } + try { + return current($this->request('users.get', $user_url + $scope)); + } catch (Exception $e) { + return false; + } + } + + + /** + * @param $chat_id + * @param $user_id + * @return bool|null|string + * @throws VkApiException + */ + public function isAdmin($user_id, $chat_id) { //возвращает привелегию по id + try { + $members = $this->request('messages.getConversationMembers', ['peer_id' => $chat_id])['items']; + } catch (\Exception $e) { + throw new VkApiException('Бот не админ в этой беседе, или бота нет в этой беседе'); + } + foreach ($members as $key) { + if ($key['member_id'] == $user_id) + return (isset($key["is_owner"])) ? 'owner' : ((isset($key["is_admin"])) ? 'admin' : false); + } + return null; + } + + /** + * @param $id + * @param $message + * @param array $params + * @return bool|mixed + * @throws VkApiException + */ + public function sendMessage($id, $message, $params = []) { + if ($id < 1) + return 0; + $message = $this->placeholders($id, $message); + return $this->request('messages.send', ['message' => $message, 'peer_id' => $id] + $params); + } + + /** + * + */ + public function debug() { + ini_set('error_reporting', E_ALL); + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + echo 'ok'; + $this->debug_mode = 1; + } + + /** + * @param $id + * @param $message + * @param array $buttons + * @param bool $inline + * @param bool $one_time + * @param array $params + * @return mixed + * @throws VkApiException + */ + public function sendButton($id, $message, $buttons = [], $inline = false, $one_time = False, $params = []) { + $keyboard = $this->generateKeyboard($buttons, $inline, $one_time); + $message = $this->placeholders($id, $message); + return $this->request('messages.send', ['message' => $message, 'peer_id' => $id, 'keyboard' => $keyboard] + $params); + } + + public function buttonLocation($payload = null) { + return ['location', $payload]; + } + + public function buttonPayToGroup($group_id, $amount, $description = null, $data = null, $payload = null) { + return ['vkpay', $payload, 'pay-to-group', $group_id, $amount, $description, $data]; + } + + public function buttonPayToUser($user_id, $amount, $description = null, $payload = null) { + return ['vkpay', $payload, 'pay-to-user', $user_id, $amount, $description]; + } + + public function buttonDonateToGroup($group_id, $payload = null) { + return ['vkpay', $payload, 'transfer-to-group', $group_id]; + } + + public function buttonDonateToUser($user_id, $payload = null) { + return ['vkpay', $payload, 'transfer-to-user', $user_id]; + } + + public function buttonApp($text, $app_id, $owner_id = null, $hash = null, $payload = null) { + return ['open_app', $payload, $text, $app_id, $owner_id, $hash]; + } + + public function buttonText($text, $color, $payload = null) { + return ['text', $payload, $text, $color]; + } + + /** + * @param array $buttons + * @param bool $inline + * @param bool $one_time + * @return array|false|string + */ + public function generateKeyboard($buttons = [], $inline = false, $one_time = False) { + $keyboard = []; + $i = 0; + foreach ($buttons as $button_str) { + $j = 0; + foreach ($button_str as $button) { + $keyboard[$i][$j]["action"]["type"] = $button[0]; + if ($button[1] != null) + $keyboard[$i][$j]["action"]["payload"] = json_encode($button[1], JSON_UNESCAPED_UNICODE); + switch ($button[0]) { + case 'text': { + $color = $this->replaceColor($button[3]); + $keyboard[$i][$j]["color"] = $color; + $keyboard[$i][$j]["action"]["label"] = $button[2]; + break; + } + case 'vkpay': { + $keyboard[$i][$j]["action"]["hash"] = "action={$button[2]}"; + $keyboard[$i][$j]["action"]["hash"] .= ($button[3] < 0) ? "&group_id=".$button[3]*-1 : "&user_id={$button[3]}"; + $keyboard[$i][$j]["action"]["hash"] .= (isset($button[4])) ? "&amount={$button[4]}" : ''; + $keyboard[$i][$j]["action"]["hash"] .= (isset($button[5])) ? "&description={$button[5]}" : ''; + $keyboard[$i][$j]["action"]["hash"] .= (isset($button[6])) ? "&data={$button[6]}" : ''; + $keyboard[$i][$j]["action"]["hash"] .= "&aid=1"; + break; + } + case 'open_app': { + $keyboard[$i][$j]["action"]["label"] = $button[2]; + $keyboard[$i][$j]["action"]["app_id"] = $button[3]; + if(isset($button[4])) + $keyboard[$i][$j]["action"]["owner_id"] = $button[4]; + if(isset($button[5])) + $keyboard[$i][$j]["action"]["hash"] = $button[5]; + break; + } + } + $j++; + } + $i++; + } + $keyboard = ["one_time" => $one_time, "buttons" => $keyboard, 'inline' => $inline]; + $keyboard = json_encode($keyboard, JSON_UNESCAPED_UNICODE); + return $keyboard; + } + + /** + * @param $color + * @return string + */ + private function replaceColor($color) { + switch ($color) { + case 'red': + $color = 'negative'; + break; + case 'green': + $color = 'positive'; + break; + case 'white': + $color = 'default'; + break; + case 'blue': + $color = 'primary'; + break; + } + return $color; + } + + /** + * @param $group_url + * @return mixed + * @throws VkApiException + */ + public function groupInfo($group_url) { + $group_url = preg_replace("!.*?/!", '', $group_url); + return current($this->request('groups.getById', ["group_ids" => $group_url])); + } + + /** + * @param $id + * @param $local_file_path + * @param array $params + * @return mixed + * @throws VkApiException + */ + public function sendImage($id, $local_file_path, $params = []) { + $upload_file = $this->uploadImage($id, $local_file_path); + return $this->request('messages.send', ['attachment' => "photo" . $upload_file[0]['owner_id'] . "_" . $upload_file[0]['id'], 'peer_id' => $id] + $params); + } + + /** + * @param $id + * @param $local_file_path + * @return mixed + * @throws VkApiException + */ + private function uploadImage($id, $local_file_path) { + $upload_url = $this->getUploadServerMessages($id, 'photo')['upload_url']; + for ($i = 0; $i < $this->try_count_resend_file; ++$i) { + try { + $answer_vk = json_decode($this->sendFiles($upload_url, $local_file_path, 'photo'), true); + return $this->savePhoto($answer_vk['photo'], $answer_vk['server'], $answer_vk['hash']); + } catch (VkApiException $e) { + sleep(1); + $exception = json_decode($e->getMessage(), true); + if ($exception['error']['error_code'] != 121) + throw new VkApiException($e->getMessage(), $exception['error']['error_code']); + } + } + $answer_vk = json_decode($this->sendFiles($upload_url, $local_file_path, 'photo'), true); + return $this->savePhoto($answer_vk['photo'], $answer_vk['server'], $answer_vk['hash']); + } + + /** + * @param $peer_id + * @param string $selector + * @return mixed|null + * @throws VkApiException + */ + private function getUploadServerMessages($peer_id, $selector = 'doc') { + $result = null; + if ($selector == 'doc') + $result = $this->request('docs.getMessagesUploadServer', ['type' => 'doc', 'peer_id' => $peer_id]); + else if ($selector == 'photo') + $result = $this->request('photos.getMessagesUploadServer', ['peer_id' => $peer_id]); + else if ($selector == 'audio_message') + $result = $this->request('docs.getMessagesUploadServer', ['type' => 'audio_message', 'peer_id' => $peer_id]); + return $result; + } + + private function uploadVoice($id, $local_file_path) { + $upload_url = $this->getUploadServerMessages($id, 'audio_message')['upload_url']; + $answer_vk = json_decode($this->sendFiles($upload_url, $local_file_path, 'file'), true); + return $this->saveDocuments($answer_vk['file'], 'voice'); + } + + public function sendVoice($id, $local_file_path, $params = []) { + $upload_file = $this->uploadVoice($id, $local_file_path); + return $this->request('messages.send', ['attachment' => "doc" . $upload_file['audio_message']['owner_id'] . "_" . $upload_file['audio_message']['id'], 'peer_id' => $id] + $params); + } + + /** + * @param $url + * @param $local_file_path + * @param string $type + * @return mixed + * @throws VkApiException + */ + protected function sendFiles($url, $local_file_path, $type = 'file') { + $post_fields = [ + $type => new CURLFile(realpath($local_file_path)) + ]; + + for ($i = 0; $i < $this->try_count_resend_file; ++$i) { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type:multipart/form-data" + ]); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields); + $output = curl_exec($ch); + if ($output != '') + break; + else + sleep(1); + } + if ($output == '') + throw new VkApiException('Не удалось загрузить файл на сервер'); + return $output; + } + + /** + * @param $photo + * @param $server + * @param $hash + * @return mixed + * @throws VkApiException + */ + private function savePhoto($photo, $server, $hash) { + return $this->request('photos.saveMessagesPhoto', ['photo' => $photo, 'server' => $server, 'hash' => $hash]); + } + + /** + * @param $groupID + * @param $local_file_path + * @param null $title + * @return mixed + * + * @throws VkApiException + */ + public function uploadDocsGroup($groupID, $local_file_path, $title = null) { + return $this->uploadDocs($groupID, $local_file_path, $title); + } + + /** + * @param $id + * @param $local_file_path + * @param null $title + * @return mixed + * @throws VkApiException + */ + private function uploadDocs($id, $local_file_path, $title = null) { + if (!isset($title)) + $title = preg_replace("!.*?/!", '', $local_file_path); + $upload_url = $this->getUploadServerPost($id)['upload_url']; + $answer_vk = json_decode($this->sendFiles($upload_url, $local_file_path), true); + $upload_file = $this->saveDocuments($answer_vk['file'], $title); + return $upload_file; + } + + /** + * @param array $peer_id + * @return mixed + * @throws VkApiException + */ + private function getUploadServerPost($peer_id = []) { + if ($peer_id < 0) + $peer_id = ['group_id' => $peer_id * -1]; + else + $peer_id = []; + $result = $this->request('docs.getUploadServer', $peer_id); + return $result; + } + + /** + * @param $file + * @param $title + * @return mixed + * @throws VkApiException + */ + private function saveDocuments($file, $title) { + return $this->request('docs.save', ['file' => $file, 'title' => $title]); + } + + /** + * @param $id + * @param $local_file_path + * @param null $title + * @param array $params + * @return bool|mixed + * @throws VkApiException + */ + public function sendDocMessage($id, $local_file_path, $title = null, $params = []) { + $upload_file = current($this->uploadDocsMessages($id, $local_file_path, $title)); + if ($id != 0 and $id != '0') { + return $this->request('messages.send', ['attachment' => "doc" . $upload_file['owner_id'] . "_" . $upload_file['id'], 'peer_id' => $id] + $params); + } else { + return true; + } + } + + /** + * @param $id + * @param $local_file_path + * @param null $title + * @return mixed + * @throws VkApiException + */ + private function uploadDocsMessages($id, $local_file_path, $title = null) { + if (!isset($title)) + $title = preg_replace("!.*?/!", '', $local_file_path); + $upload_url = $this->getUploadServerMessages($id)['upload_url']; + $answer_vk = json_decode($this->sendFiles($upload_url, $local_file_path), true); + $upload_file = $this->saveDocuments($answer_vk['file'], $title); + return $upload_file; + } + + /** + * @param $id + * @param array $message + * @param array $props + * @param array $media + * @return mixed + * @throws VkApiException + */ + public function createPost($id, $message = [], $props = [], $media = []) { + $send_attachment = []; + + foreach ($media as $selector => $massive) { + switch ($selector) { + case "images": + foreach ($massive as $image) { + $upload_url = $this->getWallUploadServer($id); + for ($i = 0; $i <= $this->try_count_resend_file; ++$i) { + try { + $answer_vk = json_decode($this->sendFiles($upload_url['upload_url'], $image, 'photo'), true); + $upload_file = $this->savePhotoWall($answer_vk['photo'], $answer_vk['server'], $answer_vk['hash'], $id); + $send_attachment[] = "photo" . $upload_file[0]['owner_id'] . "_" . $upload_file[0]['id']; + break; + } catch (VkApiException $e) { + if ($i == $this->try_count_resend_file) + throw new VkApiException($e->getMessage(), $e->getCode()); + sleep(1); + $exception = json_decode($e->getMessage(), true); + if ($exception['error']['error_code'] != 121) + throw new VkApiException($e->getMessage(), $e->getCode()); + } + } + } + break; + case "docs": + foreach ($massive as $docs) { + $upload_file = $this->uploadDocsUser($docs); + if (isset($upload_file['type'])) + $upload_file = $upload_file[$upload_file['type']]; + else + $upload_file = current($upload_file); + $send_attachment[] = "doc" . $upload_file['owner_id'] . "_" . $upload_file['id']; + } + break; + case "other": + break; + } + } + if (count($send_attachment) != 0) + $send_attachment = ["attachment" => join(',', $send_attachment)]; + if (is_string($message)) + $message = ['message' => $message]; + return $this->request('wall.post', ['owner_id' => $id] + $message + $props + $send_attachment); + } + + /** + * @param $owner_id , $post_id, $message + * @param $post_id + * @param $message + * @return mixed + * @throws VkApiException + */ + public function sendWallComment($owner_id, $post_id, $message) { + return $this->request('wall.createComment', ['owner_id' => $owner_id, 'post_id' => $post_id, 'message' => $message]); + } + + /** + * @param $id + * @return mixed + * @throws VkApiException + */ + private function getWallUploadServer($id) { + if ($id < 0) { + $id *= -1; + return $this->request('photos.getWallUploadServer', ['group_id' => $id]); + } else { + return $this->request('photos.getWallUploadServer', ['user_id' => $id]); + } + } + + /** + * @param $photo + * @param $server + * @param $hash + * @param $id + * @return mixed + * @throws VkApiException + */ + private function savePhotoWall($photo, $server, $hash, $id) { + if ($id < 0) { + $id *= -1; + return $this->request('photos.saveWallPhoto', ['photo' => $photo, 'server' => $server, 'hash' => $hash, 'group_id' => $id]); + } else { + return $this->request('photos.saveWallPhoto', ['photo' => $photo, 'server' => $server, 'hash' => $hash, 'user_id' => $id]); + } + } + + /** + * @param $local_file_path + * @param null $title + * @return mixed + * + * @throws VkApiException + */ + public function uploadDocsUser($local_file_path, $title = null) { + return $this->uploadDocs([], $local_file_path, $title); + } + + /** + * @param $id + * @param array $message + * @param array $props + * @param array $media + * @param array $keyboard + * @return mixed + * @throws VkApiException + */ + public function createMessages($id, $message = [], $props = [], $media = [], $keyboard = []) { + if ($id < 1) + return 0; + $send_attachment = []; + + foreach ($media as $selector => $massiv) { + switch ($selector) { + case "images": + foreach ($massiv as $image) { + $upload_file = $upload_file = $this->uploadImage($id, $image); + $send_attachment[] = "photo" . $upload_file[0]['owner_id'] . "_" . $upload_file[0]['id']; + } + break; + case "docs": + foreach ($massiv as $document) { + $upload_file = $this->uploadDocsMessages($id, $document['path'], $document['title']); + if (isset($upload_file['type'])) + $upload_file = $upload_file[$upload_file['type']]; + else + $upload_file = current($upload_file); + $send_attachment[] = "doc" . $upload_file['owner_id'] . "_" . $upload_file['id']; + } + break; + case "voice": + foreach ($massiv as $voice) { + $upload_file = $this->uploadVoice($id, $voice); + $send_attachment[] = "doc" . $upload_file['audio_message']['owner_id'] . "_" . $upload_file['audio_message']['id']; + } + break; + case "other": + break; + } + } + if (count($send_attachment) != 0) + $send_attachment = ["attachment" => join(',', $send_attachment)]; + if (is_string($message)) + $message = ['message' => $message]; + if ($keyboard != []) + $keyboard = ['keyboard' => $this->generateKeyboard($keyboard['keyboard'], $keyboard['inline'], $keyboard['one_time'])]; + return $this->request('messages.send', ['peer_id' => $id] + $message + $props + $send_attachment + $keyboard); + } + + /** + * @param array $id + * @param int $extended + * @param array $props + * @return mixed + * @throws VkApiException + */ + public function getGroupsUser($id = [], $extended = 1, $props = []) { + if (is_numeric($id)) + $id = ['user_id' => $id]; + if (!is_array($props)) + $props = []; + if ($extended == 1) + $extended = ['extended' => 1]; + else + $extended = []; + return $this->request('groups.get', $id + $props + $extended); + } + + /** + * @param $var + * @throws VkApiException + */ + public function setTryCountResendFile($var) { + if (is_integer($var)) + $this->try_count_resend_file = $var; + else + throw new VkApiException("Параметр должен быть числовым"); + } + + /** + * @param $var + * @throws VkApiException + */ + public function setRequestIgnoreError($var) { + if (is_array($var)) + $this->request_ignore_error = $var; + else if (is_integer($var)) + $this->request_ignore_error = [$var]; + else + throw new VkApiException("Параметр должен быть числовым либо массивом"); + } + + /** + * @param $id + * @return mixed + */ + public function dateRegistration($id) { + $site = file_get_contents("https://vk.com/foaf.php?id={$id}"); + preg_match('', $site, $data); + $data = explode('T', $data[1]); + $date = date("d.m.Y", strtotime($data[0])); + $time = mb_substr($data[1], 0, 8); + return "$time $date"; + } + + /** + * @return array + */ + protected function copyAllDataclass() { + return [$this->token, $this->version, $this->auth, $this->request_ignore_error, $this->try_count_resend_file]; + } + + /** + * @param $id_vk_vars + */ + protected function setAllDataclass($id_vk_vars) { + list($this->token, $this->version, $this->auth, $this->request_ignore_error, $this->try_count_resend_file) = $id_vk_vars; + } +}