Full Code of vladkens/VK for AI

master bab4b4763764 cached
11 files
18.4 KB
5.1k tokens
16 symbols
1 requests
Download .txt
Repository: vladkens/VK
Branch: master
Commit: bab4b4763764
Files: 11
Total size: 18.4 KB

Directory structure:
gitextract_smasmeo0/

├── .gitignore
├── ChangeLog
├── LICENSE
├── README.md
├── Samples/
│   ├── SearchPlayAndDownload/
│   │   └── script.js
│   ├── example-1.php
│   ├── example-2.php
│   └── example-3.php
├── composer.json
└── src/
    └── VK/
        ├── VK.php
        └── VKException.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.idea/
vendor/
composer.lock
index.php

================================================
FILE: ChangeLog
================================================
== 0.1.7
* Added ability to select the API version.
* Fixed bug #8.
* Update PHPDoc.

== 0.1.6
* Added namespace.

== 0.1.5
* Added Composer support.
* Connection to the api server in keep-alive mode.
* Added json and xml formats api's response (default php array).
* Rename and update some methods in VK class.

== 0.1.4
* Fixed bug changing the option "v" in API methods.
* Added sample use VK library (search, play and download music).

== 0.1.3
* Update example-1.php
* Update documentation.

== 0.1.2
* Added authorization in test mode.
* Update documentation.

== 0.1.1
* Added VKException class.
* Update documentation.

== 0.1.0
* First release.

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 Vlad Pronsky <vladkens@yandex.ru>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

================================================
FILE: README.md
================================================
# VK

## По-русски

Класс реализует VK API и авторизацию по OAuth протоколу.
По всем вопросам можно писать на <vladkens@yandex.ru>

### Использование
1. Подключите класс

        require('VK.php');

2. Создайте объект VK
    1. без авторизации

            $vk = new VK\VK('{APP_ID}', '{API_SECRET}');

    2. с авторизацией

            $vk = new VK\VK('{APP_ID}', '{API_SECRET}', '{ACCESS_TOKEN}');

3. Если нужна авторизация
    1. Получаем ссылку авторизации

            $vk->getAuthorizeURL('{API_SETTINGS}', '{CALLBACK_URL}');

    2. Получаем токен доступа по ключу из ссылки авторизации

            $vk->getAccessToken('{CODE}');
            
    3. Проверить авторизирован ли пользователь
            
            $vk->isAuth(); // return bool

4. Используем API

        $vk->api('{METHOD_NAME}', '{PARAMETERS}');
        
### Другие методы
* Установить версию API.
    `$vk->setApiVersion({NUBMER});`
    
### Переменные
* `{APP_ID}` — ID приложения вконтакте.
* `{API_SECRET}` — Секретный код приложения.
* `{ACCESS_TOKEN}` — Токен доступа.
* `{API_SETTINGS}` — Запрашиваемые [права доступа](http://vk.com/developers.php?oid=-1&p=Права_доступа_приложений) приложения (через запятую).
* `{CALLBACK_URL}` — Адрес, на который будет передан `{CODE}`.
* `{CODE}` — Код для получения токена доступа.
* `{METHOD_NAME}` — Имя API метода. [Все методы](http://vk.com/developers.php?oid=-1&p=Описание_методов_API).
* `{PARAMETERS}` — Параметры соответствующего метода API.

\* Если нужно получить бесконечный токен, используете параметр `offline` в `{API_SETTINGS}`.

### Лицензия
[MIT](https://raw.github.com/vladkens/VK/master/LICENSE)

## English

The PHP class for vk.com API and to support OAuth.
You can ask me any questions by e-mail: <vladkens@yandex.ru>

### Use
1. Connect class

        require('VK.php');
        
2. Create VK object
    1. without authorization

            $vk = new VK\VK('{APP_ID}', '{API_SECRET}');

    2. with authorization

            $vk = new VK\VK('{APP_ID}', '{API_SECRET}', '{ACCESS_TOKEN}');

3. If need authorization
    1. Get authoriz link

            $vk->getAuthorizeURL('{API_SETTINGS}', '{CALLBACK_URL}');

    2. Get the token access by code from the authoriz link

            $vk->getAccessToken('{CODE}');
            
    3. Check the status of authorization
            
            $vk->isAuth(); // return bool
            
4. Usage API

        $vk->api('{METHOD_NAME}', '{PARAMETERS}');

### Other methods
* Set version of API.
    `$vk->setApiVersion({NUBMER});`
    
### Variables
* `{APP_ID}` — Your application's identifier.
* `{API_SECRET}` — Secret application key.
* `{ACCESS_TOKEN}` — Access token.
* `{API_SETTINGS}` —  Access [rights requested](http://vk.com/developers.php?oid=-17680044&p=Application_Access_Rights) by your app (through comma).
* `{CALLBACK_URL}` —  Address to which `{CODE}` will be rendered.
* `{CODE}` — The code to get access token.
* `{METHOD_NAME}` — Name of the API method. [All methods.](http://vk.com/developers.php?oid=-17680044&p=API_Method_Description)
* `{PARAMETERS}` — Parameters of the corresponding API methods.

\* If you need infinite token use key `offline` in `{API_SETTINGS}`.

### License
[MIT](https://raw.github.com/vladkens/VK/master/LICENSE)

================================================
FILE: Samples/SearchPlayAndDownload/script.js
================================================
// Ajax
function ScriptRequest(url, callback) {
    ScriptRequest.handler = function(data) {
        callback(data);
    }
    
    url += (url.indexOf('?') > -1 ? '&' : '?') + 'callback=ScriptRequest.handler';
    var script = document.createElement('script');
    script.onload = script.onerror = function() {
        document.body.removeChild(script);
    }
    
    document.body.appendChild(script);
    script.src = url;
}

function play_audio(aid) {
    if (typeof play_audio.now != 'undefined') {
        if (play_audio.now == aid) return;
        
        var el = document.querySelector('[data-id="'+play_audio.now+'"] audio');
        el.pause();
        el.currentTime = 0;
        el.style.display = "none";
        el.parentElement.style.backgroundColor = "#fff";
    }
    
    var audio = document.querySelector('[data-id="'+aid+'"] audio')
    if (audio != null) {
        audio.style.display = "block";
        audio.play();
    } else {
        var url = 'https://api.vk.com//method/audio.getById.json?audios='+aid+'&access_token='+vk_access_token;
        ScriptRequest(url, function(data) {
            audio = document.createElement('audio');
            audio.controls = audio.autoplay = true;
            document.querySelector('[data-id="'+aid+'"]').appendChild(audio);
            audio.setAttribute('src', data.response[0].url);
            
            audio.addEventListener('ended', function() {
                var el = document.querySelector('[data-id="'+aid+'"]').nextElementSibling;
                if (el != null) {
                    play_audio(el.getAttribute('data-id'));
                }
            }, true);
        });
    }
    document.querySelector('[data-id="'+aid+'"]').style.backgroundColor = "#efefef";
    play_audio.now = aid;
}

// Set events to play link
window.onload = function() {
    var links = document.querySelectorAll('.search-result a.play');
    for (var i = 0, il = links.length; i < il; ++i) {
        links[i].addEventListener('click', function(event) {
            play_audio((this.parentElement).getAttribute('data-id'));
            event.preventDefault();
        }, true);
    }
}

================================================
FILE: Samples/example-1.php
================================================
<!doctype html>
    <meta charset="utf-8" />
    <style>
    html, body { font-family: monospace; }
    </style>
    
<?php

/**
 * Example 1.
 * Usage VK API without authorization.
 * Some calls are not available.
 * @link http://vk.com/developers.php VK API
 */

error_reporting(E_ALL);
require_once('../src/VK/VK.php');
require_once('../src/VK/VKException.php');

try {
    $vk = new VK\VK('{YOUR_APP_ID}', '{YOUR_API_SECRET}'); // Use your app_id and api_secret
    
    $users = $vk->api('users.get', array(
        'uids'   => '1234,4321',
        'fields' => 'first_name,last_name,sex'));
        
    foreach ($users['response'] as $user) {
        echo $user['first_name'] . ' ' . $user['last_name'] . ' (' .
            ($user['sex'] == 1 ? 'Girl' : 'Man') . ')<br />';
    }
    
} catch (VK\VKException $error) {
    echo $error->getMessage();
}


================================================
FILE: Samples/example-2.php
================================================
<!doctype html>
    <meta charset="utf-8" />
    <style>
    html, body { font-family: monospace; }
    </style>

<?php

/**
 * Example 2.
 * Get access token via OAuth and usage VK API.
 * @link http://vk.com/developers.php VK API
 */

error_reporting(E_ALL);
require_once('../src/VK/VK.php');
require_once('../src/VK/VKException.php');

$vk_config = array(
    'app_id'        => '{YOUR_APP_ID}',
    'api_secret'    => '{YOUR_API_SECRET}',
    'callback_url'  => 'http://{YOUR_DOMAIN}/samples/example-2.php',
    'api_settings'  => '{ACCESS_RIGHTS_THROUGH_COMMA}' // In this example use 'friends'.
    // If you need infinite token use key 'offline'.
);

try {
    $vk = new VK\VK($vk_config['app_id'], $vk_config['api_secret']);
    
    if (!isset($_REQUEST['code'])) {
        /**
         * If you need switch the application in test mode,
         * add another parameter "true". Default value "false".
         * Ex. $vk->getAuthorizeURL($api_settings, $callback_url, true);
         */
        $authorize_url = $vk->getAuthorizeURL(
            $vk_config['api_settings'], $vk_config['callback_url']);
            
        echo '<a href="' . $authorize_url . '">Sign in with VK</a>';
    } else {
        $access_token = $vk->getAccessToken($_REQUEST['code'], $vk_config['callback_url']);
        
        echo 'access token: ' . $access_token['access_token']
            . '<br />expires: ' . $access_token['expires_in'] . ' sec.'
            . '<br />user id: ' . $access_token['user_id'] . '<br /><br />';
            
        $user_friends = $vk->api('friends.get', array(
            'uid'       => '12345',
            'fields'    => 'uid,first_name,last_name',
            'order'     => 'name'
        ));
        
        foreach ($user_friends['response'] as $key => $value) {
            echo $value['first_name'] . ' ' . $value['last_name'] . ' ('
                . $value['uid'] . ')<br />';
        }
    }
} catch (VK\VKException $error) {
    echo $error->getMessage();
}


================================================
FILE: Samples/example-3.php
================================================
<!doctype html>
    <meta charset="utf-8" />
    <style>
    html, body { font-family: monospace; }
    </style>

<?php

/**
 * Example 3.
 * Usage VK API having access token.
 * @link http://vk.com/developers.php VK API
 */

error_reporting(E_ALL);
require_once('../src/VK/VK.php');
require_once('../src/VK/VKException.php');

$vk_config = array(
    'app_id'        => '{YOUR_APP_ID}',
    'api_secret'    => '{YOUR_API_SECRET}',
    'access_token'  => '{YOUR_ACCESS_TOKEN}'
);

try {
    $vk = new VK\VK($vk_config['app_id'], $vk_config['api_secret'], $vk_config['access_token']);
    
    $user_friends = $vk->api('friends.get', array(
        'uid'       => '12345',
        'fields'    => 'uid,first_name,last_name',
        'order'     => 'name'
    ));
    
    foreach ($user_friends['response'] as $key => $value) {
        echo $value['first_name'] . ' ' . $value['last_name'] . ' ('
            . $value['uid'] . ')<br />';
    }
    
} catch (VK\VKException $error) {
    echo $error->getMessage();
}

?>

================================================
FILE: composer.json
================================================
{
    "name": "vladkens/vk",
    "type": "library",
    "description": "The PHP class for vk.com API with support OAuth.",
    "keywords": ["vk", "vk.com", "api", "oauth"],
    "license": "MIT",
    "authors": [
        {
            "name": "Vlad Pronsky",
            "email": "vladkens@yandex.ru"
        }
    ],
    "support": {
        "email": "vladkens@yandex.ru",
        "issues": "https://github.com/vladkens/VK/issues",
        "source": "https://github.com/vladkens/VK"
    },
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": {
            "VK": "src"
        }
    }
}

================================================
FILE: src/VK/VK.php
================================================
<?php

/**
 * The PHP class for vk.com API and to support OAuth.
 * @author Vlad Pronsky <vladkens@yandex.ru>
 * @license https://raw.github.com/vladkens/VK/master/LICENSE MIT
 */

namespace VK;

class VK
{
    /**
     * VK application id.
     * @var string
     */
    private $app_id;

    /**
     * VK application secret key.
     * @var string
     */
    private $api_secret;

    /**
     * API version. If null uses latest version.
     * @var int
     */
    private $api_version;

    /**
     * VK access token.
     * @var string
     */
    private $access_token;

    /**
     * Authorization status.
     * @var bool
     */
    private $auth = false;

    /**
     * Instance curl.
     * @var Resource
     */
    private $ch;

    const AUTHORIZE_URL = 'https://oauth.vk.com/authorize';
    const ACCESS_TOKEN_URL = 'https://oauth.vk.com/access_token';

    /**
     * Constructor.
     * @param   string $app_id
     * @param   string $api_secret
     * @param   string $access_token
     * @throws  VKException
     */
    public function __construct($app_id, $api_secret, $access_token = null)
    {
        $this->app_id = $app_id;
        $this->api_secret = $api_secret;
        $this->setAccessToken($access_token);

        $this->ch = curl_init();
    }

    /**
     * Destructor.
     */
    public function __destruct()
    {
        curl_close($this->ch);
    }

    /**
     * Set special API version.
     * @param   int $version
     * @return  void
     */
    public function setApiVersion($version)
    {
        $this->api_version = $version;
    }

    /**
     * Set Access Token.
     * @param   string $access_token
     * @throws  VKException
     * @return  void
     */
    public function setAccessToken($access_token)
    {
        $this->access_token = $access_token;
    }

    /**
     * Returns base API url.
     * @param   string $method
     * @param   string $response_format
     * @return  string
     */
    public function getApiUrl($method, $response_format = 'json')
    {
        return 'https://api.vk.com/method/' . $method . '.' . $response_format;
    }

    /**
     * Returns authorization link with passed parameters.
     * @param   string $api_settings
     * @param   string $callback_url
     * @param   bool $test_mode
     * @return  string
     */
    public function getAuthorizeUrl($api_settings = '',
                                    $callback_url = 'https://api.vk.com/blank.html', $test_mode = false)
    {
        $parameters = array(
            'client_id' => $this->app_id,
            'scope' => $api_settings,
            'redirect_uri' => $callback_url,
            'response_type' => 'code'
        );

        if ($test_mode)
            $parameters['test_mode'] = 1;

        return $this->createUrl(self::AUTHORIZE_URL, $parameters);
    }

    /**
     * Returns access token by code received on authorization link.
     * @param   string $code
     * @param   string $callback_url
     * @throws  VKException
     * @return  array
     */
    public function getAccessToken($code, $callback_url = 'https://api.vk.com/blank.html')
    {
        if (!is_null($this->access_token) && $this->auth) {
            throw new VKException('Already authorized.');
        }

        $parameters = array(
            'client_id' => $this->app_id,
            'client_secret' => $this->api_secret,
            'code' => $code,
            'redirect_uri' => $callback_url
        );

        $rs = json_decode($this->request(
            $this->createUrl(self::ACCESS_TOKEN_URL, $parameters)), true);

        if (isset($rs['error'])) {
            throw new VKException($rs['error'] .
                (!isset($rs['error_description']) ?: ': ' . $rs['error_description']));
        } else {
            $this->auth = true;
            $this->access_token = $rs['access_token'];
            return $rs;
        }
    }

    /**
     * Return user authorization status.
     * @return  bool
     */
    public function isAuth()
    {
        return !is_null($this->access_token);
    }

    /**
     * Check for validity access token.
     * @param   string $access_token
     * @return  bool
     */
    public function checkAccessToken($access_token = null)
    {
        $token = is_null($access_token) ? $this->access_token : $access_token;
        if (is_null($token)) return false;

        $rs = $this->api('getUserSettings', array('access_token' => $token));
        return isset($rs['response']);
    }

    /**
     * Execute API method with parameters and return result.
     * @param   string $method
     * @param   array $parameters
     * @param   string $format
     * @param   string $requestMethod
     * @return  mixed
     */
    public function api($method, $parameters = array(), $format = 'array', $requestMethod = 'get')
    {
        $parameters['timestamp'] = time();
        $parameters['api_id'] = $this->app_id;
        $parameters['random'] = rand(0, 10000);

        if (!array_key_exists('access_token', $parameters) && !is_null($this->access_token)) {
            $parameters['access_token'] = $this->access_token;
        }

        if (!array_key_exists('v', $parameters) && !is_null($this->api_version)) {
            $parameters['v'] = $this->api_version;
        }

        ksort($parameters);

        $sig = '';
        foreach ($parameters as $key => $value) {
            $sig .= $key . '=' . $value;
        }
        $sig .= $this->api_secret;

        $parameters['sig'] = md5($sig);

        if ($method == 'execute' || $requestMethod == 'post') {
            $rs = $this->request(
                $this->getApiUrl($method, $format == 'array' ? 'json' : $format), "POST", $parameters);
        } else {
            $rs = $this->request($this->createUrl(
                $this->getApiUrl($method, $format == 'array' ? 'json' : $format), $parameters));
        }
        return $format == 'array' ? json_decode($rs, true) : $rs;
    }

    /**
     * Concatenate keys and values to url format and return url.
     * @param   string $url
     * @param   array $parameters
     * @return  string
     */
    private function createUrl($url, $parameters)
    {
        $url .= '?' . http_build_query($parameters);
        return $url;
    }

    /**
     * Executes request on link.
     * @param   string $url
     * @param   string $method
     * @param   array $postfields
     * @return  string
     */
    private function request($url, $method = 'GET', $postfields = array())
    {
        curl_setopt_array($this->ch, array(
            CURLOPT_USERAGENT => 'VK/1.0 (+https://github.com/vladkens/VK))',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_POST => ($method == 'POST'),
            CURLOPT_POSTFIELDS => $postfields,
            CURLOPT_URL => $url
        ));

        return curl_exec($this->ch);
    }

}

;



================================================
FILE: src/VK/VKException.php
================================================
<?php

/**
 * The exception class for VK library.
 * @author Vlad Pronsky <vladkens@yandex.ru>
 * @license https://raw.github.com/vladkens/VK/master/LICENSE MIT
 */

namespace VK;
 
class VKException extends \Exception {  }

Download .txt
gitextract_smasmeo0/

├── .gitignore
├── ChangeLog
├── LICENSE
├── README.md
├── Samples/
│   ├── SearchPlayAndDownload/
│   │   └── script.js
│   ├── example-1.php
│   ├── example-2.php
│   └── example-3.php
├── composer.json
└── src/
    └── VK/
        ├── VK.php
        └── VKException.php
Download .txt
SYMBOL INDEX (16 symbols across 3 files)

FILE: Samples/SearchPlayAndDownload/script.js
  function ScriptRequest (line 2) | function ScriptRequest(url, callback) {
  function play_audio (line 17) | function play_audio(aid) {

FILE: src/VK/VK.php
  class VK (line 11) | class VK
    method __construct (line 59) | public function __construct($app_id, $api_secret, $access_token = null)
    method __destruct (line 71) | public function __destruct()
    method setApiVersion (line 81) | public function setApiVersion($version)
    method setAccessToken (line 92) | public function setAccessToken($access_token)
    method getApiUrl (line 103) | public function getApiUrl($method, $response_format = 'json')
    method getAuthorizeUrl (line 115) | public function getAuthorizeUrl($api_settings = '',
    method getAccessToken (line 138) | public function getAccessToken($code, $callback_url = 'https://api.vk....
    method isAuth (line 168) | public function isAuth()
    method checkAccessToken (line 178) | public function checkAccessToken($access_token = null)
    method api (line 195) | public function api($method, $parameters = array(), $format = 'array',...
    method createUrl (line 235) | private function createUrl($url, $parameters)
    method request (line 248) | private function request($url, $method = 'GET', $postfields = array())

FILE: src/VK/VKException.php
  class VKException (line 11) | class VKException extends \Exception {  }
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (21K chars).
[
  {
    "path": ".gitignore",
    "chars": 38,
    "preview": ".idea/\nvendor/\ncomposer.lock\nindex.php"
  },
  {
    "path": "ChangeLog",
    "chars": 653,
    "preview": "== 0.1.7\n* Added ability to select the API version.\n* Fixed bug #8.\n* Update PHPDoc.\n\n== 0.1.6\n* Added namespace.\n\n== 0."
  },
  {
    "path": "LICENSE",
    "chars": 1099,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Vlad Pronsky <vladkens@yandex.ru>\n\nPermission is hereby granted, free of charg"
  },
  {
    "path": "README.md",
    "chars": 3261,
    "preview": "# VK\n\n## По-русски\n\nКласс реализует VK API и авторизацию по OAuth протоколу.\nПо всем вопросам можно писать на <vladkens@"
  },
  {
    "path": "Samples/SearchPlayAndDownload/script.js",
    "chars": 2153,
    "preview": "// Ajax\nfunction ScriptRequest(url, callback) {\n    ScriptRequest.handler = function(data) {\n        callback(data);\n   "
  },
  {
    "path": "Samples/example-1.php",
    "chars": 858,
    "preview": "<!doctype html>\n    <meta charset=\"utf-8\" />\n    <style>\n    html, body { font-family: monospace; }\n    </style>\n    \n<?"
  },
  {
    "path": "Samples/example-2.php",
    "chars": 1998,
    "preview": "<!doctype html>\n    <meta charset=\"utf-8\" />\n    <style>\n    html, body { font-family: monospace; }\n    </style>\n\n<?php\n"
  },
  {
    "path": "Samples/example-3.php",
    "chars": 1017,
    "preview": "<!doctype html>\n    <meta charset=\"utf-8\" />\n    <style>\n    html, body { font-family: monospace; }\n    </style>\n\n<?php\n"
  },
  {
    "path": "composer.json",
    "chars": 617,
    "preview": "{\n    \"name\": \"vladkens/vk\",\n    \"type\": \"library\",\n    \"description\": \"The PHP class for vk.com API with support OAuth."
  },
  {
    "path": "src/VK/VK.php",
    "chars": 6915,
    "preview": "<?php\n\n/**\n * The PHP class for vk.com API and to support OAuth.\n * @author Vlad Pronsky <vladkens@yandex.ru>\n * @licens"
  },
  {
    "path": "src/VK/VKException.php",
    "chars": 225,
    "preview": "<?php\n\n/**\n * The exception class for VK library.\n * @author Vlad Pronsky <vladkens@yandex.ru>\n * @license https://raw.g"
  }
]

About this extraction

This page contains the full source code of the vladkens/VK GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (18.4 KB), approximately 5.1k tokens, and a symbol index with 16 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!