├── .gitignore ├── README.md ├── app ├── Config-sample.php ├── I18N.php ├── Log.php ├── Manager.php ├── TelegramApi.php ├── TextManager.php ├── VkApi.php └── VkLinksParser.php ├── clear.php ├── composer.json ├── composer.lock ├── docs ├── config.md ├── examples │ ├── messageSend │ │ ├── disable_notification.md │ │ └── disable_web_page_preview.md │ ├── modes │ │ ├── extended-needlinktovkpost-false.md │ │ ├── extended-needlinktovkpost-true.md │ │ ├── simple-preview-false.md │ │ └── simple-preview-true.md │ ├── text-cutter │ │ ├── aggressive-false.md │ │ └── aggressive-true.md │ ├── vk-links │ │ ├── show-false.md │ │ └── show-true.md │ └── vop │ │ ├── 1vk-1t.md │ │ ├── 1vk-ft.md │ │ ├── fvk-1t.md │ │ └── fvk-ft.md ├── faq.md ├── install.md ├── readme.md └── updating.md ├── i18n ├── en.json ├── ru.json └── template.json └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | Config.php 2 | app/Config.php 3 | last.json 4 | log.txt 5 | /vendor/ 6 | /composer.bat 7 | 8 | 9 | # Created by .ignore support plugin (hsz.mobi) 10 | ### Windows template 11 | # Windows image file caches 12 | Thumbs.db 13 | ehthumbs.db 14 | 15 | # Folder config file 16 | Desktop.ini 17 | 18 | # Recycle Bin used on file shares 19 | $RECYCLE.BIN/ 20 | 21 | # Windows Installer files 22 | *.cab 23 | *.msi 24 | *.msm 25 | *.msp 26 | 27 | # Windows shortcuts 28 | *.lnk 29 | ### JetBrains template 30 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 31 | 32 | *.iml 33 | 34 | ## Directory-based project format: 35 | .idea/ 36 | # if you remove the above rule, at least ignore the following: 37 | 38 | # User-specific stuff: 39 | # .idea/workspace.xml 40 | # .idea/tasks.xml 41 | # .idea/dictionaries 42 | 43 | # Sensitive or high-churn files: 44 | # .idea/dataSources.ids 45 | # .idea/dataSources.xml 46 | # .idea/sqlDataSources.xml 47 | # .idea/dynamic.xml 48 | # .idea/uiDesigner.xml 49 | 50 | # Gradle: 51 | # .idea/gradle.xml 52 | # .idea/libraries 53 | 54 | # Mongo Explorer plugin: 55 | # .idea/mongoSettings.xml 56 | 57 | ## File-based project format: 58 | *.ipr 59 | *.iws 60 | 61 | ## Plugin-specific files: 62 | 63 | # IntelliJ 64 | /out/ 65 | 66 | # mpeltonen/sbt-idea plugin 67 | .idea_modules/ 68 | 69 | # JIRA plugin 70 | atlassian-ide-plugin.xml 71 | 72 | # Crashlytics plugin (for Android Studio and IntelliJ) 73 | com_crashlytics_export_strings.xml 74 | crashlytics.properties 75 | crashlytics-build.properties 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > ⚠️ Current code is a little but outdated, but it could still work ⚠️ 2 | 3 | --- 4 | 5 | ⬇️⬇️⬇️👇⬇️⬇️⬇️ 6 | 7 | **🆕 CHECK THIS NEW VERSION: 🆕** 8 | 9 | * **https://github.com/Bizordec/vk-to-tgm** 10 | * also it have a way more functions and supported media-types 11 | 12 | ⬆️⬆️⬆️👆⬆️⬆️⬆️ 13 | 14 | 15 | --- 16 | 17 | # VK to Telegram auto-posting Bot 18 | 19 | ## Info 20 | 21 | * Bot-manager for auto-reposting posts from VK user/group/public to Telegram channel 22 | 23 | ### Variations of posting 24 | 25 | * one VK source -> one Telegram channel 26 | * one VK source -> few Telegram channels 27 | * few VK sources -> one Telegram channel 28 | * few VK sources -> few Telegram channels 29 | 30 | For examples of configuration [check docs](./docs/config.md) 31 | 32 | ### Links 33 | 34 | * [Vote for next feature to release here](https://github.com/lgg/vk-to-telegram-bot/issues/1) 35 | * Also you can find answers and help [here](./docs/faq.md) 36 | 37 | ## Features 38 | 39 | * One script for many Telegram Bots, Telegram Channels, VK sources 40 | * Resend posts from users and groups 41 | * Resend text and photos 42 | * Few variations of behaviour 43 | * Flexible settings 44 | * Simple i18n 45 | 46 | ### Features to release 47 | 48 | *this will be implemented soon* 49 | 50 | * resend all attachment types 51 | * test coverage 52 | * variations of data storage(database, json, etc) 53 | 54 | ## Documentation 55 | 56 | * [Documentation](./docs/readme.md) 57 | * [FAQ](./docs/faq.md) 58 | * [Installation](./docs/install.md) 59 | * [Updating](./docs/updating.md) 60 | * [Configuration](./docs/config.md) 61 | 62 | ## Examples of channels with this bot 63 | 64 | | Telegram Channel | VK | 65 | | ------ | ------ | 66 | | [Hackathon list](https://t.me/hacklist) | [Hackathon list](https://vk.com/hacklist) | 67 | | [Frontend Raccoon](https://t.me/frontendraccoon) | [Frontend Raccoon](https://vk.com/jsraccoon) | 68 | 69 | ## Links and Copyrights: 70 | 71 | * LICENSE: MIT 72 | * Author: [lgg](https://github.com/lgg) and [awesome contributors](https://github.com/lgg/vk-to-telegram-bot/graphs/contributors) 73 | * Thanks to [akalongman](https://github.com/akalongman) for [php-telegram-bot](https://github.com/akalongman/php-telegram-bot) 74 | -------------------------------------------------------------------------------- /app/Config-sample.php: -------------------------------------------------------------------------------- 1 | "", 9 | "vk_token" => "", 10 | //Telegram 11 | "t_key" => "", 12 | "t_name" => "", 13 | "t_chat" => "", 14 | "messageSend" => [ 15 | "disable_web_page_preview" => false, 16 | "disable_notification" => false 17 | ], 18 | //Bot-manager settings 19 | //Bot-manager reposting params(modes) 20 | "extended" => [ 21 | "active" => true, 22 | "needLinkToVKPost" => true, 23 | "needFromText" => [ 24 | "withLink" => true, 25 | "prepend" => true, 26 | "customName" => "Nice Group" 27 | ], 28 | "resendAttachments" => true, 29 | ], 30 | "needPostPreview" => true, 31 | //Bot-manager internal functions params 32 | "language" => "ru", 33 | "textManager" => [ 34 | "aggressive" => false, 35 | "limit" => 3 36 | ], 37 | "vkLinks" => [ 38 | "show" => false, 39 | "symbols" => [ 40 | "open" => "[", 41 | "close" => "]" 42 | ] 43 | ] 44 | ], 45 | ]; 46 | 47 | //Files 48 | private static $file_log = "log.txt"; 49 | private static $file_last = "last.json"; 50 | 51 | public static function getConfigs() 52 | { 53 | return self::$configs; 54 | } 55 | 56 | public static function getVkParams($vk_id, $vk_token) 57 | { 58 | return [ 59 | "access_token" => $vk_token, 60 | "owner_id" => $vk_id, 61 | "count" => 5 62 | ]; 63 | } 64 | 65 | //Functions files 66 | public static function getFileLog() 67 | { 68 | return dirname($_SERVER['SCRIPT_NAME']).DIRECTORY_SEPARATOR.self::$file_log; 69 | } 70 | 71 | public static function getFileLast() 72 | { 73 | return dirname($_SERVER['SCRIPT_NAME']).DIRECTORY_SEPARATOR.self::$file_last; 74 | } 75 | } -------------------------------------------------------------------------------- /app/I18N.php: -------------------------------------------------------------------------------- 1 | langPath . $lang . ".json"), true); 21 | 22 | //add loaded lang to in-memory loaded array 23 | $this->loadedLangs[$lang] = $langArray; 24 | } 25 | 26 | /** 27 | * @param string $lang language to load/activate 28 | * loads language from file, if language is already loaded - activates it 29 | */ 30 | public function loadLang($lang) 31 | { 32 | //check if we have already load this lang to in-memory array 33 | if (!isset($this->loadedLangs[$lang])) { 34 | //load this lang to memory and activate it 35 | $this->loadLangFromFile($lang); 36 | } 37 | 38 | //set this lang to activeLang 39 | $this->activeLang = $lang; 40 | } 41 | 42 | /** 43 | * @param string $group group of phrase, check i18n/en.json for more or docs 44 | * @param string $phrase current phrase to return 45 | * @return string 46 | * returns phrase in active-language for group/phrase 47 | */ 48 | public function get($group, $phrase) 49 | { 50 | //@TODO add group/phrase existence check 51 | return $this->loadedLangs[$this->activeLang][$group][$phrase]; 52 | } 53 | } -------------------------------------------------------------------------------- /app/Log.php: -------------------------------------------------------------------------------- 1 | loadConfigs(); 16 | 17 | //Check last files 18 | $this->checkFileLast(); 19 | } 20 | 21 | /** 22 | * Loads configs from Config.php 23 | */ 24 | private function loadConfigs() 25 | { 26 | $this->configs = Config::getConfigs(); 27 | } 28 | 29 | /** 30 | * Checks last.json file, if error - close bot 31 | */ 32 | private function checkFileLast() 33 | { 34 | //Check if file exists 35 | if (!file_exists(Config::getFileLast())) { 36 | 37 | //Create new file with default name 38 | $content = [ 39 | $this->configs[0]["t_name"] . "_" . $this->configs[0]["vk"] => -1 40 | ]; 41 | $file = json_encode($content); 42 | file_put_contents(Config::getFileLast(), $file); 43 | } 44 | 45 | //Load file content 46 | $last = json_decode(file_get_contents(Config::getFileLast()), true); 47 | 48 | //Check if we have some troubles, while reading from last.json 49 | if (empty($last)) { 50 | Log::addLog("For some reason " . Config::getFileLast() . " is empty or we can't properly read from it"); 51 | 52 | //Close bot manager 53 | $this->close(); 54 | } 55 | 56 | //If okay write last posts to object 57 | $this->last = $last; 58 | } 59 | 60 | /** 61 | * Starts bot and run every config 62 | */ 63 | public function start() 64 | { 65 | //create i18n instance 66 | $this->i18n = new I18N(); 67 | 68 | //Run every config 69 | foreach ($this->configs as $configIndex => $config) { 70 | //Load language for this config 71 | $this->i18n->loadLang($config["language"]); 72 | 73 | //Get VK response 74 | $response = $this->getVk($config["vk"], $config["vk_token"]); 75 | 76 | //If we have good response 77 | if ($response) { 78 | 79 | //Create Telegram API 80 | $telegram = new TelegramApi($config["t_key"], $config["t_name"], $config["t_chat"]); 81 | 82 | //Load last.json 83 | $key_save = $config["t_chat"] . "_" . $config["vk"]; 84 | if (isset($this->last[$key_save])) { 85 | $last = $this->last[$key_save]; 86 | } else { 87 | $last = [-1]; 88 | } 89 | 90 | //Send messages 91 | $posted = $this->send($response, $telegram, $last, $config, $configIndex); 92 | 93 | //Save log 94 | if ($posted["counter"] > 0) { 95 | $log = "Add " . $posted["counter"] . " new posts: " . implode(",", $posted["ids"]) . " | from " . Config::getFileLast() . ": " . implode(",", $last); 96 | Log::addLog($log); 97 | 98 | //Update last 99 | $posts = array_merge($last, $posted["ids"]); 100 | $this->last[$key_save] = $posts; 101 | } 102 | } 103 | } 104 | 105 | //Save updated posts 106 | $this->savePosts(); 107 | } 108 | 109 | /** 110 | * @param $vk_id string - id of vk user/group 111 | * @param $vk_token string - vk service token 112 | * @return bool|mixed - return false if failed to load vk, return vk response if ok 113 | * Loads VK, if have errors - log them 114 | */ 115 | private function getVk($vk_id, $vk_token) 116 | { 117 | //Get vk response 118 | $vk_response = VkApi::request(VkApi::getMethodUrl("wall.get", Config::getVkParams($vk_id, $vk_token))); 119 | $response = $vk_response["response"]; 120 | 121 | //Check if we have no posts 122 | if (empty($response["items"])) { 123 | Log::addLog("Fail loading data from VK: " . $vk_id . " More info: " . json_encode($vk_response)); 124 | return false; 125 | } 126 | 127 | return $response; 128 | } 129 | 130 | /** 131 | * @param $config array - config for current entity 132 | * @return array - return $infoAboutVKSource with ["name"] and ["url"] 133 | * Parse info about original VK source object(name, url) 134 | */ 135 | private function getInfoAboutVkObjectById($config) 136 | { 137 | $vk_id = $config["vk"]; 138 | $vk_token = $config["vk_token"]; 139 | 140 | //Check if it is a group or a person 141 | $isGroup = ($vk_id[0] === "-"); 142 | $url = "https://vk.com/" . ($isGroup ? "public" . substr($vk_id, 1) : "id" . $vk_id); 143 | 144 | //Check if we need to parse real user/public name from VK 145 | if (isset($config["extended"]["needFromText"]["customName"])) { 146 | $name = $config["extended"]["needFromText"]["customName"]; 147 | } else { 148 | //Get vk response 149 | $vk_params = Config::getVkParams($vk_id, $vk_token); 150 | $isGroup ? $vk_params["group_ids"] = substr($vk_id, 1) : $vk_params["user_ids"] = $vk_id; 151 | $vk_response = VkApi::request(VkApi::getMethodUrl($isGroup ? "groups.getById" : "users.get", $vk_params)); 152 | $response = $vk_response["response"][0]; 153 | $name = $isGroup ? $response["name"] : $response["first_name"] . " " . $response["last_name"]; 154 | } 155 | 156 | return [ 157 | "name" => $name, 158 | "url" => $url 159 | ]; 160 | } 161 | 162 | /** 163 | * @param $response - response from VK 164 | * @param $telegram - telegram API object 165 | * @param $last - last posted ids 166 | * @param $config - config for this entity 167 | * @param $configIndex - index of current $config 168 | * @return array - $posted object(counter + posted ids array) 169 | * Sends messages to Telegram, if have new posts 170 | */ 171 | private function send($response, $telegram, $last, $config, $configIndex) 172 | { 173 | //Preload info about VK source 174 | if (isset($config["extended"]["needFromText"]) && $config["extended"]["needFromText"]) { 175 | $infoAboutVKSource = self::getInfoAboutVkObjectById($config); 176 | } 177 | 178 | //Check posts 179 | $key = count($response["items"]) - 1; 180 | $posted = [ 181 | "counter" => 0, 182 | "ids" => [] 183 | ]; 184 | while ($key >= 0) { 185 | $post = $response["items"][$key]; 186 | 187 | //If we have matches or post[id] equals 0 or -1(vk api bad responses) => ignore them 188 | if (!in_array($post["id"], $last) || $post["id"] == 0 || $post["id"] == -1) { 189 | 190 | $message = "https://vk.com/wall" . $config["vk"] . "_" . $post["id"]; 191 | 192 | // TODO optimize this 193 | $postText = false; 194 | if (isset($post["text"])) { 195 | $postText = VkLinksParser::parseInternalLinks($post["text"], $configIndex); 196 | } 197 | 198 | //Set sendMessage parameters 199 | $messageParams['disable_web_page_preview'] = isset($config["messageSend"]["disable_web_page_preview"]) ? $config["messageSend"]["disable_web_page_preview"] : false; 200 | $messageParams['disable_notification'] = isset($config["messageSend"]["disable_notification"]) ? $config["messageSend"]["disable_notification"] : false; 201 | $messageParams['parse_mode'] = isset($config["messageSend"]["parse_mode"]) ? $config["messageSend"]["parse_mode"] : 'HTML'; 202 | 203 | //Check what type of posting we need 204 | if (isset($config["extended"]["active"]) && $config["extended"]["active"]) { 205 | 206 | //If we have text in VK post - send it to Telegram 207 | if ($postText) { 208 | 209 | $message = $postText; 210 | 211 | //If we need to append link to original VK post 212 | if (isset($config["extended"]["needLinkToVKPost"]) && $config["extended"]["needLinkToVKPost"]) { 213 | $message = TextManager::appendLinkToVKPost($postText, $message, $this->i18n, "true"); 214 | } 215 | 216 | //If we need to add link to original VK group 217 | if (isset($config["extended"]["needFromText"]) && $config["extended"]["needFromText"]) { 218 | //If we need to add text about original VK Group 219 | $infoAboutVKSource["withLink"] = (isset($config["extended"]["needFromText"]["withLink"]) && $config["extended"]["needFromText"]["withLink"]); 220 | $message = TextManager::addFromText($postText, $infoAboutVKSource, $this->i18n, (isset($config["extended"]["needFromText"]["prepend"]) && $config["extended"]["needFromText"]["prepend"])); 221 | } 222 | 223 | //Send message 224 | $telegram->sendMessage($message, $messageParams); 225 | } 226 | 227 | 228 | //If we have attachments - check them 229 | if (isset($post["attachments"]) && $config["extended"]["resendAttachments"]) { 230 | 231 | //Scan all attachments for photos 232 | foreach ($post["attachments"] as $attach) { 233 | if ($attach["type"] == "photo") { 234 | $telegram->sendPhoto(VkApi::findMaxSizeLink($attach["photo"])); 235 | } elseif ($attach["type"] == "link" && isset($attach["link"]["photo"])) { 236 | $telegram->sendPhoto(VkApi::findMaxSizeLink($attach["link"]["photo"])); 237 | } elseif ($attach["type"] == "doc" && isset($attach["doc"]["preview"]["video"])) { 238 | $telegram->sendGIF($attach["doc"]["preview"]["video"]['src']); 239 | } 240 | } 241 | } 242 | } else { 243 | 244 | //Check if need to append post preview 245 | if (isset($config["needPostPreview"]) && $config["needPostPreview"]) { 246 | 247 | //If we have post text - send it 248 | if ($postText) { 249 | $message = TextManager::getTextPreview($postText, $message, $configIndex, $this->i18n); 250 | } 251 | } 252 | 253 | //Send message 254 | $telegram->sendMessage($message, $messageParams); 255 | } 256 | 257 | //Increase posted counter 258 | $posted["counter"]++; 259 | 260 | //Save posted id 261 | array_push($posted["ids"], $post["id"]); 262 | } 263 | 264 | $key--; 265 | } 266 | 267 | //Return posted info 268 | return $posted; 269 | } 270 | 271 | /** 272 | * Saves last posted ids to last.json 273 | */ 274 | private function savePosts() 275 | { 276 | Log::saveLast($this->last); 277 | } 278 | 279 | /** 280 | * Closes the script 281 | */ 282 | private function close() 283 | { 284 | die(); 285 | } 286 | } -------------------------------------------------------------------------------- /app/TelegramApi.php: -------------------------------------------------------------------------------- 1 | telegram = new Longman\TelegramBot\Telegram($key, $botName); 15 | $this->chat = "@" . $chat; 16 | } catch (Longman\TelegramBot\Exception\TelegramException $e) { 17 | // log telegram errors 18 | echo $e->getMessage(); 19 | } 20 | } 21 | 22 | /** 23 | * @param string $message 24 | * @param array $data 25 | * Send message with URL to the post 26 | */ 27 | public function sendMessage($message, $data) 28 | { 29 | //array of allowed parameters, see more: https://core.telegram.org/bots/api#sendmessage 30 | $allowed = [ 31 | 'disable_web_page_preview', // Bool, Disables link previews for links in this message 32 | 'disable_notification', // Bool, Sends the message silently. Users will receive a notification with no sound. 33 | 'parse_mode', // String 'HTML' or 'Markdown' 34 | ]; 35 | 36 | $params = [ 37 | 'chat_id' => $this->chat, 38 | 'text' => $message 39 | ]; 40 | 41 | foreach ($allowed as $a) { 42 | if (isset($data[$a])) { 43 | $params[$a] = $data[$a]; 44 | } 45 | } 46 | 47 | $result = Request::sendMessage($params); 48 | } 49 | 50 | /** 51 | * @param $link 52 | * Send photo to channel 53 | */ 54 | public function sendPhoto($link) 55 | { 56 | //Load file 57 | $filename = __DIR__ . DIRECTORY_SEPARATOR . uniqid() . ".jpg"; 58 | file_put_contents($filename, fopen($link, 'r')); 59 | 60 | //Send file 61 | $result = Request::sendPhoto( 62 | [ 63 | 'chat_id' => $this->chat, 64 | 'photo' => Request::encodeFile($filename), 65 | ] 66 | ); 67 | 68 | //Delete file 69 | unlink($filename); 70 | } 71 | } -------------------------------------------------------------------------------- /app/TextManager.php: -------------------------------------------------------------------------------- 1 | get("textManager", "comment")) . " " . $link; 27 | } 28 | 29 | /** 30 | * @param string $text 31 | * @param array $groupSource 32 | * @param I18N $i18n 33 | * @param bool $prepend 34 | * @return string 35 | * Prepend/Append "From [groupSource]:" to text 36 | */ 37 | public static function addFromText($text, $groupSource, $i18n, $prepend) 38 | { 39 | if (isset($groupSource["withLink"]) && $groupSource["withLink"]) { 40 | $fromText = self::createMarkdownLink($groupSource["name"], $groupSource["url"]); 41 | } else { 42 | $fromText = $groupSource["name"]; 43 | } 44 | $fromText = $i18n->get("textManager", "from") . " " . $fromText; 45 | $text = $prepend ? $fromText . "\n\n" . $text : $text . "\n\n" . $fromText; 46 | return trim($text); 47 | } 48 | 49 | /** 50 | * @param string $text 51 | * @param string $link 52 | * @param int $configIndex index number of config to use 53 | * @param I18N $i18n 54 | * @return string 55 | * Cuts text to 140 symbols or more till the space and add "Read more:" text 56 | */ 57 | public static function getTextPreview($text, $link, $configIndex, $i18n) 58 | { 59 | //check config 60 | $config = Config::getConfigs()[$configIndex]["textManager"]; 61 | 62 | //check if we have 140th symbol 63 | $i = 139; 64 | if (!isset($text[$i])) { 65 | return self::appendLinkToVKPost($text, $link, $i18n); 66 | } 67 | 68 | //check in which mode we are working 69 | if ($config["aggressive"]) { 70 | //139 + cutting letters limit 71 | $maxIndex = $i + $config["limit"] + 1; 72 | //check if we have symbols after last used symbol 73 | $needDots = isset($text[$maxIndex]); 74 | $text = substr($text, 0, $maxIndex); 75 | } else { 76 | //length of full text 77 | $maxIndex = strlen($text) - 1; 78 | //stop if we find space or last symbol 79 | while ($text[$i] != " " and $i < $maxIndex) { 80 | $i++; 81 | } 82 | $i++; 83 | //check if we have symbols after last used symbol 84 | $needDots = isset($text[$i]); 85 | $text = substr($text, 0, $i); 86 | } 87 | 88 | return trim($text) . ($needDots ? $i18n->get("textManager", "dots") : "") . " " . $i18n->get("textManager", "read-more") . " " . $link; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/VkApi.php: -------------------------------------------------------------------------------- 1 | $vk_link) { 85 | $text = str_replace($vk_link, self::$replace($vk_links, $key, $type, $config), $text); 86 | } 87 | } 88 | 89 | return $text; 90 | } 91 | } -------------------------------------------------------------------------------- /clear.php: -------------------------------------------------------------------------------- 1 | =5.5", 28 | "symfony/polyfill-intl-idn": "^1.17" 29 | }, 30 | "require-dev": { 31 | "ext-curl": "*", 32 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", 33 | "psr/log": "^1.1" 34 | }, 35 | "suggest": { 36 | "psr/log": "Required for using the Log middleware" 37 | }, 38 | "type": "library", 39 | "extra": { 40 | "branch-alias": { 41 | "dev-master": "6.5-dev" 42 | } 43 | }, 44 | "autoload": { 45 | "files": [ 46 | "src/functions_include.php" 47 | ], 48 | "psr-4": { 49 | "GuzzleHttp\\": "src/" 50 | } 51 | }, 52 | "notification-url": "https://packagist.org/downloads/", 53 | "license": [ 54 | "MIT" 55 | ], 56 | "authors": [ 57 | { 58 | "name": "Graham Campbell", 59 | "email": "hello@gjcampbell.co.uk", 60 | "homepage": "https://github.com/GrahamCampbell" 61 | }, 62 | { 63 | "name": "Michael Dowling", 64 | "email": "mtdowling@gmail.com", 65 | "homepage": "https://github.com/mtdowling" 66 | }, 67 | { 68 | "name": "Jeremy Lindblom", 69 | "email": "jeremeamia@gmail.com", 70 | "homepage": "https://github.com/jeremeamia" 71 | }, 72 | { 73 | "name": "George Mponos", 74 | "email": "gmponos@gmail.com", 75 | "homepage": "https://github.com/gmponos" 76 | }, 77 | { 78 | "name": "Tobias Nyholm", 79 | "email": "tobias.nyholm@gmail.com", 80 | "homepage": "https://github.com/Nyholm" 81 | }, 82 | { 83 | "name": "Márk Sági-Kazár", 84 | "email": "mark.sagikazar@gmail.com", 85 | "homepage": "https://github.com/sagikazarmark" 86 | }, 87 | { 88 | "name": "Tobias Schultze", 89 | "email": "webmaster@tubo-world.de", 90 | "homepage": "https://github.com/Tobion" 91 | } 92 | ], 93 | "description": "Guzzle is a PHP HTTP client library", 94 | "homepage": "http://guzzlephp.org/", 95 | "keywords": [ 96 | "client", 97 | "curl", 98 | "framework", 99 | "http", 100 | "http client", 101 | "rest", 102 | "web service" 103 | ], 104 | "support": { 105 | "issues": "https://github.com/guzzle/guzzle/issues", 106 | "source": "https://github.com/guzzle/guzzle/tree/6.5.8" 107 | }, 108 | "funding": [ 109 | { 110 | "url": "https://github.com/GrahamCampbell", 111 | "type": "github" 112 | }, 113 | { 114 | "url": "https://github.com/Nyholm", 115 | "type": "github" 116 | }, 117 | { 118 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 119 | "type": "tidelift" 120 | } 121 | ], 122 | "time": "2022-06-20T22:16:07+00:00" 123 | }, 124 | { 125 | "name": "guzzlehttp/promises", 126 | "version": "1.5.1", 127 | "source": { 128 | "type": "git", 129 | "url": "https://github.com/guzzle/promises.git", 130 | "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" 131 | }, 132 | "dist": { 133 | "type": "zip", 134 | "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", 135 | "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", 136 | "shasum": "" 137 | }, 138 | "require": { 139 | "php": ">=5.5" 140 | }, 141 | "require-dev": { 142 | "symfony/phpunit-bridge": "^4.4 || ^5.1" 143 | }, 144 | "type": "library", 145 | "extra": { 146 | "branch-alias": { 147 | "dev-master": "1.5-dev" 148 | } 149 | }, 150 | "autoload": { 151 | "files": [ 152 | "src/functions_include.php" 153 | ], 154 | "psr-4": { 155 | "GuzzleHttp\\Promise\\": "src/" 156 | } 157 | }, 158 | "notification-url": "https://packagist.org/downloads/", 159 | "license": [ 160 | "MIT" 161 | ], 162 | "authors": [ 163 | { 164 | "name": "Graham Campbell", 165 | "email": "hello@gjcampbell.co.uk", 166 | "homepage": "https://github.com/GrahamCampbell" 167 | }, 168 | { 169 | "name": "Michael Dowling", 170 | "email": "mtdowling@gmail.com", 171 | "homepage": "https://github.com/mtdowling" 172 | }, 173 | { 174 | "name": "Tobias Nyholm", 175 | "email": "tobias.nyholm@gmail.com", 176 | "homepage": "https://github.com/Nyholm" 177 | }, 178 | { 179 | "name": "Tobias Schultze", 180 | "email": "webmaster@tubo-world.de", 181 | "homepage": "https://github.com/Tobion" 182 | } 183 | ], 184 | "description": "Guzzle promises library", 185 | "keywords": [ 186 | "promise" 187 | ], 188 | "support": { 189 | "issues": "https://github.com/guzzle/promises/issues", 190 | "source": "https://github.com/guzzle/promises/tree/1.5.1" 191 | }, 192 | "funding": [ 193 | { 194 | "url": "https://github.com/GrahamCampbell", 195 | "type": "github" 196 | }, 197 | { 198 | "url": "https://github.com/Nyholm", 199 | "type": "github" 200 | }, 201 | { 202 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 203 | "type": "tidelift" 204 | } 205 | ], 206 | "time": "2021-10-22T20:56:57+00:00" 207 | }, 208 | { 209 | "name": "guzzlehttp/psr7", 210 | "version": "1.9.0", 211 | "source": { 212 | "type": "git", 213 | "url": "https://github.com/guzzle/psr7.git", 214 | "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318" 215 | }, 216 | "dist": { 217 | "type": "zip", 218 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", 219 | "reference": "e98e3e6d4f86621a9b75f623996e6bbdeb4b9318", 220 | "shasum": "" 221 | }, 222 | "require": { 223 | "php": ">=5.4.0", 224 | "psr/http-message": "~1.0", 225 | "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" 226 | }, 227 | "provide": { 228 | "psr/http-message-implementation": "1.0" 229 | }, 230 | "require-dev": { 231 | "ext-zlib": "*", 232 | "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" 233 | }, 234 | "suggest": { 235 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 236 | }, 237 | "type": "library", 238 | "extra": { 239 | "branch-alias": { 240 | "dev-master": "1.9-dev" 241 | } 242 | }, 243 | "autoload": { 244 | "files": [ 245 | "src/functions_include.php" 246 | ], 247 | "psr-4": { 248 | "GuzzleHttp\\Psr7\\": "src/" 249 | } 250 | }, 251 | "notification-url": "https://packagist.org/downloads/", 252 | "license": [ 253 | "MIT" 254 | ], 255 | "authors": [ 256 | { 257 | "name": "Graham Campbell", 258 | "email": "hello@gjcampbell.co.uk", 259 | "homepage": "https://github.com/GrahamCampbell" 260 | }, 261 | { 262 | "name": "Michael Dowling", 263 | "email": "mtdowling@gmail.com", 264 | "homepage": "https://github.com/mtdowling" 265 | }, 266 | { 267 | "name": "George Mponos", 268 | "email": "gmponos@gmail.com", 269 | "homepage": "https://github.com/gmponos" 270 | }, 271 | { 272 | "name": "Tobias Nyholm", 273 | "email": "tobias.nyholm@gmail.com", 274 | "homepage": "https://github.com/Nyholm" 275 | }, 276 | { 277 | "name": "Márk Sági-Kazár", 278 | "email": "mark.sagikazar@gmail.com", 279 | "homepage": "https://github.com/sagikazarmark" 280 | }, 281 | { 282 | "name": "Tobias Schultze", 283 | "email": "webmaster@tubo-world.de", 284 | "homepage": "https://github.com/Tobion" 285 | } 286 | ], 287 | "description": "PSR-7 message implementation that also provides common utility methods", 288 | "keywords": [ 289 | "http", 290 | "message", 291 | "psr-7", 292 | "request", 293 | "response", 294 | "stream", 295 | "uri", 296 | "url" 297 | ], 298 | "support": { 299 | "issues": "https://github.com/guzzle/psr7/issues", 300 | "source": "https://github.com/guzzle/psr7/tree/1.9.0" 301 | }, 302 | "funding": [ 303 | { 304 | "url": "https://github.com/GrahamCampbell", 305 | "type": "github" 306 | }, 307 | { 308 | "url": "https://github.com/Nyholm", 309 | "type": "github" 310 | }, 311 | { 312 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 313 | "type": "tidelift" 314 | } 315 | ], 316 | "time": "2022-06-20T21:43:03+00:00" 317 | }, 318 | { 319 | "name": "longman/telegram-bot", 320 | "version": "0.54.1", 321 | "source": { 322 | "type": "git", 323 | "url": "https://github.com/php-telegram-bot/core.git", 324 | "reference": "7701428356a70b0b5d88404248a060ca1c43c6ba" 325 | }, 326 | "dist": { 327 | "type": "zip", 328 | "url": "https://api.github.com/repos/php-telegram-bot/core/zipball/7701428356a70b0b5d88404248a060ca1c43c6ba", 329 | "reference": "7701428356a70b0b5d88404248a060ca1c43c6ba", 330 | "shasum": "" 331 | }, 332 | "require": { 333 | "ext-curl": "*", 334 | "ext-json": "*", 335 | "ext-mbstring": "*", 336 | "ext-pdo": "*", 337 | "guzzlehttp/guzzle": "^6.3", 338 | "monolog/monolog": "^1.23", 339 | "php": "^5.5|^7.0" 340 | }, 341 | "require-dev": { 342 | "phpunit/phpunit": "^4.8|^5.7|^6.5|^7.4", 343 | "squizlabs/php_codesniffer": "^3.3" 344 | }, 345 | "type": "library", 346 | "autoload": { 347 | "psr-4": { 348 | "Longman\\TelegramBot\\": "src/" 349 | } 350 | }, 351 | "notification-url": "https://packagist.org/downloads/", 352 | "license": [ 353 | "MIT" 354 | ], 355 | "authors": [ 356 | { 357 | "name": "Avtandil Kikabidze aka LONGMAN", 358 | "email": "akalongman@gmail.com", 359 | "homepage": "http://longman.me", 360 | "role": "Developer" 361 | }, 362 | { 363 | "name": "PHP Telegram Bot Team", 364 | "homepage": "https://github.com/php-telegram-bot/core/graphs/contributors", 365 | "role": "Developer" 366 | } 367 | ], 368 | "description": "PHP Telegram bot", 369 | "homepage": "https://github.com/php-telegram-bot/core", 370 | "keywords": [ 371 | "api", 372 | "bot", 373 | "telegram" 374 | ], 375 | "time": "2018-10-23T16:50:28+00:00" 376 | }, 377 | { 378 | "name": "monolog/monolog", 379 | "version": "1.24.0", 380 | "source": { 381 | "type": "git", 382 | "url": "https://github.com/Seldaek/monolog.git", 383 | "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266" 384 | }, 385 | "dist": { 386 | "type": "zip", 387 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", 388 | "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", 389 | "shasum": "" 390 | }, 391 | "require": { 392 | "php": ">=5.3.0", 393 | "psr/log": "~1.0" 394 | }, 395 | "provide": { 396 | "psr/log-implementation": "1.0.0" 397 | }, 398 | "require-dev": { 399 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 400 | "doctrine/couchdb": "~1.0@dev", 401 | "graylog2/gelf-php": "~1.0", 402 | "jakub-onderka/php-parallel-lint": "0.9", 403 | "php-amqplib/php-amqplib": "~2.4", 404 | "php-console/php-console": "^3.1.3", 405 | "phpunit/phpunit": "~4.5", 406 | "phpunit/phpunit-mock-objects": "2.3.0", 407 | "ruflin/elastica": ">=0.90 <3.0", 408 | "sentry/sentry": "^0.13", 409 | "swiftmailer/swiftmailer": "^5.3|^6.0" 410 | }, 411 | "suggest": { 412 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 413 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 414 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 415 | "ext-mongo": "Allow sending log messages to a MongoDB server", 416 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 417 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 418 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 419 | "php-console/php-console": "Allow sending log messages to Google Chrome", 420 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 421 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 422 | "sentry/sentry": "Allow sending log messages to a Sentry server" 423 | }, 424 | "type": "library", 425 | "extra": { 426 | "branch-alias": { 427 | "dev-master": "2.0.x-dev" 428 | } 429 | }, 430 | "autoload": { 431 | "psr-4": { 432 | "Monolog\\": "src/Monolog" 433 | } 434 | }, 435 | "notification-url": "https://packagist.org/downloads/", 436 | "license": [ 437 | "MIT" 438 | ], 439 | "authors": [ 440 | { 441 | "name": "Jordi Boggiano", 442 | "email": "j.boggiano@seld.be", 443 | "homepage": "http://seld.be" 444 | } 445 | ], 446 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 447 | "homepage": "http://github.com/Seldaek/monolog", 448 | "keywords": [ 449 | "log", 450 | "logging", 451 | "psr-3" 452 | ], 453 | "time": "2018-11-05T09:00:11+00:00" 454 | }, 455 | { 456 | "name": "psr/http-message", 457 | "version": "1.0.1", 458 | "source": { 459 | "type": "git", 460 | "url": "https://github.com/php-fig/http-message.git", 461 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 462 | }, 463 | "dist": { 464 | "type": "zip", 465 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 466 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 467 | "shasum": "" 468 | }, 469 | "require": { 470 | "php": ">=5.3.0" 471 | }, 472 | "type": "library", 473 | "extra": { 474 | "branch-alias": { 475 | "dev-master": "1.0.x-dev" 476 | } 477 | }, 478 | "autoload": { 479 | "psr-4": { 480 | "Psr\\Http\\Message\\": "src/" 481 | } 482 | }, 483 | "notification-url": "https://packagist.org/downloads/", 484 | "license": [ 485 | "MIT" 486 | ], 487 | "authors": [ 488 | { 489 | "name": "PHP-FIG", 490 | "homepage": "http://www.php-fig.org/" 491 | } 492 | ], 493 | "description": "Common interface for HTTP messages", 494 | "homepage": "https://github.com/php-fig/http-message", 495 | "keywords": [ 496 | "http", 497 | "http-message", 498 | "psr", 499 | "psr-7", 500 | "request", 501 | "response" 502 | ], 503 | "support": { 504 | "source": "https://github.com/php-fig/http-message/tree/master" 505 | }, 506 | "time": "2016-08-06T14:39:51+00:00" 507 | }, 508 | { 509 | "name": "psr/log", 510 | "version": "1.1.0", 511 | "source": { 512 | "type": "git", 513 | "url": "https://github.com/php-fig/log.git", 514 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" 515 | }, 516 | "dist": { 517 | "type": "zip", 518 | "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", 519 | "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", 520 | "shasum": "" 521 | }, 522 | "require": { 523 | "php": ">=5.3.0" 524 | }, 525 | "type": "library", 526 | "extra": { 527 | "branch-alias": { 528 | "dev-master": "1.0.x-dev" 529 | } 530 | }, 531 | "autoload": { 532 | "psr-4": { 533 | "Psr\\Log\\": "Psr/Log/" 534 | } 535 | }, 536 | "notification-url": "https://packagist.org/downloads/", 537 | "license": [ 538 | "MIT" 539 | ], 540 | "authors": [ 541 | { 542 | "name": "PHP-FIG", 543 | "homepage": "http://www.php-fig.org/" 544 | } 545 | ], 546 | "description": "Common interface for logging libraries", 547 | "homepage": "https://github.com/php-fig/log", 548 | "keywords": [ 549 | "log", 550 | "psr", 551 | "psr-3" 552 | ], 553 | "time": "2018-11-20T15:27:04+00:00" 554 | }, 555 | { 556 | "name": "ralouphie/getallheaders", 557 | "version": "3.0.3", 558 | "source": { 559 | "type": "git", 560 | "url": "https://github.com/ralouphie/getallheaders.git", 561 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 562 | }, 563 | "dist": { 564 | "type": "zip", 565 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 566 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 567 | "shasum": "" 568 | }, 569 | "require": { 570 | "php": ">=5.6" 571 | }, 572 | "require-dev": { 573 | "php-coveralls/php-coveralls": "^2.1", 574 | "phpunit/phpunit": "^5 || ^6.5" 575 | }, 576 | "type": "library", 577 | "autoload": { 578 | "files": [ 579 | "src/getallheaders.php" 580 | ] 581 | }, 582 | "notification-url": "https://packagist.org/downloads/", 583 | "license": [ 584 | "MIT" 585 | ], 586 | "authors": [ 587 | { 588 | "name": "Ralph Khattar", 589 | "email": "ralph.khattar@gmail.com" 590 | } 591 | ], 592 | "description": "A polyfill for getallheaders.", 593 | "support": { 594 | "issues": "https://github.com/ralouphie/getallheaders/issues", 595 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 596 | }, 597 | "time": "2019-03-08T08:55:37+00:00" 598 | }, 599 | { 600 | "name": "symfony/polyfill-intl-idn", 601 | "version": "v1.26.0", 602 | "source": { 603 | "type": "git", 604 | "url": "https://github.com/symfony/polyfill-intl-idn.git", 605 | "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8" 606 | }, 607 | "dist": { 608 | "type": "zip", 609 | "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8", 610 | "reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8", 611 | "shasum": "" 612 | }, 613 | "require": { 614 | "php": ">=7.1", 615 | "symfony/polyfill-intl-normalizer": "^1.10", 616 | "symfony/polyfill-php72": "^1.10" 617 | }, 618 | "suggest": { 619 | "ext-intl": "For best performance" 620 | }, 621 | "type": "library", 622 | "extra": { 623 | "branch-alias": { 624 | "dev-main": "1.26-dev" 625 | }, 626 | "thanks": { 627 | "name": "symfony/polyfill", 628 | "url": "https://github.com/symfony/polyfill" 629 | } 630 | }, 631 | "autoload": { 632 | "files": [ 633 | "bootstrap.php" 634 | ], 635 | "psr-4": { 636 | "Symfony\\Polyfill\\Intl\\Idn\\": "" 637 | } 638 | }, 639 | "notification-url": "https://packagist.org/downloads/", 640 | "license": [ 641 | "MIT" 642 | ], 643 | "authors": [ 644 | { 645 | "name": "Laurent Bassin", 646 | "email": "laurent@bassin.info" 647 | }, 648 | { 649 | "name": "Trevor Rowbotham", 650 | "email": "trevor.rowbotham@pm.me" 651 | }, 652 | { 653 | "name": "Symfony Community", 654 | "homepage": "https://symfony.com/contributors" 655 | } 656 | ], 657 | "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", 658 | "homepage": "https://symfony.com", 659 | "keywords": [ 660 | "compatibility", 661 | "idn", 662 | "intl", 663 | "polyfill", 664 | "portable", 665 | "shim" 666 | ], 667 | "support": { 668 | "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0" 669 | }, 670 | "funding": [ 671 | { 672 | "url": "https://symfony.com/sponsor", 673 | "type": "custom" 674 | }, 675 | { 676 | "url": "https://github.com/fabpot", 677 | "type": "github" 678 | }, 679 | { 680 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 681 | "type": "tidelift" 682 | } 683 | ], 684 | "time": "2022-05-24T11:49:31+00:00" 685 | }, 686 | { 687 | "name": "symfony/polyfill-intl-normalizer", 688 | "version": "v1.26.0", 689 | "source": { 690 | "type": "git", 691 | "url": "https://github.com/symfony/polyfill-intl-normalizer.git", 692 | "reference": "219aa369ceff116e673852dce47c3a41794c14bd" 693 | }, 694 | "dist": { 695 | "type": "zip", 696 | "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", 697 | "reference": "219aa369ceff116e673852dce47c3a41794c14bd", 698 | "shasum": "" 699 | }, 700 | "require": { 701 | "php": ">=7.1" 702 | }, 703 | "suggest": { 704 | "ext-intl": "For best performance" 705 | }, 706 | "type": "library", 707 | "extra": { 708 | "branch-alias": { 709 | "dev-main": "1.26-dev" 710 | }, 711 | "thanks": { 712 | "name": "symfony/polyfill", 713 | "url": "https://github.com/symfony/polyfill" 714 | } 715 | }, 716 | "autoload": { 717 | "files": [ 718 | "bootstrap.php" 719 | ], 720 | "psr-4": { 721 | "Symfony\\Polyfill\\Intl\\Normalizer\\": "" 722 | }, 723 | "classmap": [ 724 | "Resources/stubs" 725 | ] 726 | }, 727 | "notification-url": "https://packagist.org/downloads/", 728 | "license": [ 729 | "MIT" 730 | ], 731 | "authors": [ 732 | { 733 | "name": "Nicolas Grekas", 734 | "email": "p@tchwork.com" 735 | }, 736 | { 737 | "name": "Symfony Community", 738 | "homepage": "https://symfony.com/contributors" 739 | } 740 | ], 741 | "description": "Symfony polyfill for intl's Normalizer class and related functions", 742 | "homepage": "https://symfony.com", 743 | "keywords": [ 744 | "compatibility", 745 | "intl", 746 | "normalizer", 747 | "polyfill", 748 | "portable", 749 | "shim" 750 | ], 751 | "support": { 752 | "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" 753 | }, 754 | "funding": [ 755 | { 756 | "url": "https://symfony.com/sponsor", 757 | "type": "custom" 758 | }, 759 | { 760 | "url": "https://github.com/fabpot", 761 | "type": "github" 762 | }, 763 | { 764 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 765 | "type": "tidelift" 766 | } 767 | ], 768 | "time": "2022-05-24T11:49:31+00:00" 769 | }, 770 | { 771 | "name": "symfony/polyfill-php72", 772 | "version": "v1.26.0", 773 | "source": { 774 | "type": "git", 775 | "url": "https://github.com/symfony/polyfill-php72.git", 776 | "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2" 777 | }, 778 | "dist": { 779 | "type": "zip", 780 | "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2", 781 | "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2", 782 | "shasum": "" 783 | }, 784 | "require": { 785 | "php": ">=7.1" 786 | }, 787 | "type": "library", 788 | "extra": { 789 | "branch-alias": { 790 | "dev-main": "1.26-dev" 791 | }, 792 | "thanks": { 793 | "name": "symfony/polyfill", 794 | "url": "https://github.com/symfony/polyfill" 795 | } 796 | }, 797 | "autoload": { 798 | "files": [ 799 | "bootstrap.php" 800 | ], 801 | "psr-4": { 802 | "Symfony\\Polyfill\\Php72\\": "" 803 | } 804 | }, 805 | "notification-url": "https://packagist.org/downloads/", 806 | "license": [ 807 | "MIT" 808 | ], 809 | "authors": [ 810 | { 811 | "name": "Nicolas Grekas", 812 | "email": "p@tchwork.com" 813 | }, 814 | { 815 | "name": "Symfony Community", 816 | "homepage": "https://symfony.com/contributors" 817 | } 818 | ], 819 | "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", 820 | "homepage": "https://symfony.com", 821 | "keywords": [ 822 | "compatibility", 823 | "polyfill", 824 | "portable", 825 | "shim" 826 | ], 827 | "support": { 828 | "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0" 829 | }, 830 | "funding": [ 831 | { 832 | "url": "https://symfony.com/sponsor", 833 | "type": "custom" 834 | }, 835 | { 836 | "url": "https://github.com/fabpot", 837 | "type": "github" 838 | }, 839 | { 840 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 841 | "type": "tidelift" 842 | } 843 | ], 844 | "time": "2022-05-24T11:49:31+00:00" 845 | } 846 | ], 847 | "packages-dev": [], 848 | "aliases": [], 849 | "minimum-stability": "stable", 850 | "stability-flags": [], 851 | "prefer-stable": false, 852 | "prefer-lowest": false, 853 | "platform": [], 854 | "platform-dev": [], 855 | "plugin-api-version": "2.3.0" 856 | } 857 | -------------------------------------------------------------------------------- /docs/config.md: -------------------------------------------------------------------------------- 1 | # Config.php 2 | 3 | ## Content 4 | 5 | * [Variations of posting](#variations-of-posting) 6 | * [Basic info](#basic-info) 7 | * [VK parameters](#vk) 8 | * [Telegram parameters](#telegram) 9 | * [Telegram posting parameters](#telegram-posting) 10 | * [Bot modes](#bot-modes) 11 | * [Post cutting parameters](#post-cutting) 12 | * [Parsing internal VK links](#parsing-internal-vk-links) 13 | * [i18n](#i18n) 14 | * [Logging](#logging) 15 | 16 | ## Variations of posting 17 | 18 | * [one VK - one Telegram](./examples/vop/1vk-1t.md) 19 | * [one VK - few Telegram channels](./examples/vop/1vk-ft.md) 20 | * [few VK - one Telegram](./examples/vop/fvk-1t.md) 21 | * [few VK - few Telegram channels](./examples/vop/fvk-ft.md) 22 | 23 | ## Basic info 24 | 25 | * $configs - array of settings arrays 26 | * each array is group of settings for one pair/group of VK-to-Telegram sources and targets 27 | * Files: 28 | * $file_log - file to save logs 29 | * $file_last - file to save last posts 30 | 31 | ## VK 32 | 33 | | Parameter | Type | Description | 34 | | ------ | ------ | ------ | 35 | | vk | string | id of vk user or group to parse (**!IMPORTANT!** for users you should set `only numbers`, for groups `-numbers` (e.g. `1` is `id1`, `-1` is `club1`)) | 36 | | vk_token | string | VK service token([read more here](https://vk.com/dev/service_token)) | 37 | 38 | ## Telegram 39 | 40 | | Parameter | Type | Description | 41 | | ------ | ------ | ------ | 42 | | t_key | string | bot api key | 43 | | t_name | string | bot name | 44 | | t_chat | string | chat id/url **(without @)**, (e.g. `myawesomechannel`) | 45 | 46 | ## Telegram posting 47 | 48 | This config section is **optional**. If not set all these variables are equal to `false`. 49 | 50 | | Parameter | Type | Description | 51 | | ------ | ------ | ------ | 52 | | messageSend.disable_web_page_preview | boolean | Disables link previews for links in this message | 53 | | messageSend.disable_notification | boolean | Sends the message silently. Users will receive a notification with no sound | 54 | 55 | [see more](https://core.telegram.org/bots/api#sendmessage) 56 | 57 | ### Examples and explanations 58 | 59 | * [messageSend.disable_web_page_preview](./examples/messageSend/disable_web_page_preview.md) 60 | * [messageSend.disable_notification](./examples/messageSend/disable_notification.md) 61 | 62 | ## Bot modes 63 | 64 | *//add block scheme//* 65 | 66 | | Parameter | Type | Description | 67 | | ------ | ------ | ------ | 68 | | extended.active | boolean | use Extended(`true`) or Simple(`false`) version of bot | 69 | | extended.needLinkToVKPost | boolean | need to append link in extended mode | 70 | | extended.needFromText | boolean | need to add text "From original VK source(user/group)" | 71 | | extended.needFromText.withLink | boolean | paste fromText as text or as link to original VK source(user/group) | 72 | | extended.needFromText.prepend | boolean | prepend or append fromText | 73 | | extended.needFromText.customName | String | custom group name for fromText | 74 | | extended.resendAttachments | boolean | need to resend attachments | 75 | | needPostPreview | boolean | need to send text preview in simple mode | 76 | 77 | | extended.active | extended.needLinkToVKPost | extended.resendAttachments | needPostPreview | Result | 78 | | ------ | ------ | ------ | ------ | ------ | 79 | | true | false | true | *ignored* | full post text, all photos and other attachments will be sent to Telegram channel **without** original VK link | 80 | | true | false | false | *ignored* | only full post text, will be sent to Telegram channel | 81 | | true | true | true | *ignored* | full post text, all photos and other attachments will be sent to Telegram channel **with** original VK link | 82 | | true | true | false | *ignored* | full post text **with** original VK link and **without** all photos and other attachments will be sent to Telegram channel | 83 | | false | *ignored* | *ignored* | true | if text exists - text preview will be sent, plus link to original VK post | 84 | | false | *ignored* | *ignored* | false | only link to original VK post will be sent | 85 | 86 | ### Examples and explanations 87 | 88 | * Extended 89 | * [needLinkToVKPost = false](./examples/modes/extended-needlinktovkpost-false.md) 90 | * [needLinkToVKPost = true](./examples/modes/extended-needlinktovkpost-true.md) 91 | * Simple 92 | * [needPostPreview = false](./examples/modes/simple-preview-false.md) 93 | * [needPostPreview = true](./examples/modes/simple-preview-true.md) 94 | 95 | ## Post Cutting 96 | 97 | | Parameter | Type | Description | 98 | | ------ | ------ | ------ | 99 | | textManager.aggressive | boolean | defines TextPreview-cutting function behavior | 100 | | textManager.limit | integer | uncut letters limit | 101 | 102 | | textManager.aggressive | textManager.limit | Result | 103 | | ------ | ------ | ------ | 104 | | false | *ignored* | text will be cut on first space(` `) or till text end | 105 | | true | 3 | text will be cut on `140+limit` symbol | 106 | 107 | ### Examples and explanations 108 | 109 | * [textManager.aggressive = false](./examples/text-cutter/aggressive-false.md) 110 | * [textManager.aggressive = true](./examples/text-cutter/aggressive-true.md) 111 | 112 | ## Parsing internal VK links 113 | 114 | | Parameter | Type | Description | 115 | | ------ | ------ | ------ | 116 | | vkLinks.show | boolean | defines delete or convert internal VK links | 117 | | vkLinks.symbols.open | string | open symbol for full VK link | 118 | | vkLinks.symbols.close | string | close symbol for full VK link | 119 | 120 | | vkLinks.show | vkLinks.symbols.open | vkLinks.symbols.close | Result | 121 | | ------ | ------ | ------ | ------ | 122 | | false | *ignored* | *ignored* | internal VK link will be deleted from text | 123 | | true | [ | ] | internal VK link will be transformed to `text[full link]` | 124 | 125 | ### Examples and explanations 126 | 127 | * [vkLinks.show = false](./examples/vk-links/show-false.md) 128 | * [vkLinks.show = true](./examples/vk-links/show-true.md) 129 | 130 | ## i18n 131 | 132 | | Parameter | Type | Description | 133 | | ------ | ------ | ------ | 134 | | language | string | defines bot language | 135 | 136 | * available languages: 137 | * [en](../i18n/en.json) 138 | * [ru](../i18n/ru.json) 139 | * languages and phrases are stored in `/i18n/` 140 | * phrases are user for `TextManager` class: `getTextPreview()`, `read-more`, `comment in VK` 141 | * you can create your own language by copying `template.json` and changing it 142 | 143 | ## Logging 144 | 145 | *soon* 146 | -------------------------------------------------------------------------------- /docs/examples/messageSend/disable_notification.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/messageSend/disable_notification.md -------------------------------------------------------------------------------- /docs/examples/messageSend/disable_web_page_preview.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/messageSend/disable_web_page_preview.md -------------------------------------------------------------------------------- /docs/examples/modes/extended-needlinktovkpost-false.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/modes/extended-needlinktovkpost-false.md -------------------------------------------------------------------------------- /docs/examples/modes/extended-needlinktovkpost-true.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/modes/extended-needlinktovkpost-true.md -------------------------------------------------------------------------------- /docs/examples/modes/simple-preview-false.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/modes/simple-preview-false.md -------------------------------------------------------------------------------- /docs/examples/modes/simple-preview-true.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/modes/simple-preview-true.md -------------------------------------------------------------------------------- /docs/examples/text-cutter/aggressive-false.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/text-cutter/aggressive-false.md -------------------------------------------------------------------------------- /docs/examples/text-cutter/aggressive-true.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/text-cutter/aggressive-true.md -------------------------------------------------------------------------------- /docs/examples/vk-links/show-false.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vk-links/show-false.md -------------------------------------------------------------------------------- /docs/examples/vk-links/show-true.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vk-links/show-true.md -------------------------------------------------------------------------------- /docs/examples/vop/1vk-1t.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vop/1vk-1t.md -------------------------------------------------------------------------------- /docs/examples/vop/1vk-ft.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vop/1vk-ft.md -------------------------------------------------------------------------------- /docs/examples/vop/fvk-1t.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vop/fvk-1t.md -------------------------------------------------------------------------------- /docs/examples/vop/fvk-ft.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgg/vk-to-telegram-bot/8a12782fd31ccdf156414b9ec9cabe687d463605/docs/examples/vop/fvk-ft.md -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ## I have set my channel url, but I have an error with it 4 | 5 | * Make sure that you set channel name without @ 6 | 7 | ## I want to set parsing from VK user profile, not from group 8 | 9 | * For parsing VK user profile - use only id numbers(e.g. `1`), for parsing group - use `-` + id numbers(e.g. `-1`) 10 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## You will need 4 | 5 | * Server with installed SSL certificate 6 | * VK service token 7 | * Telegram bot and it's api key 8 | * Telegram Channel(of course you will need to add bot to administrators of your channel) 9 | 10 | ## About security 11 | 12 | * It's highly recommended to hide your bot from web. 13 | (e.g you site.com directory is /var/www/site.com, so don't place bot in that directory 14 | place it in /var/www/console/) 15 | 16 | ## Installation [production] 17 | 18 | * **!IMPORTANT!** you need SSL certificate on your server 19 | * `git clone https://github.com/lgg/vk-to-telegram-bot && cd vk-to-telegram-bot` 20 | * `composer install --no-dev --optimize-autoloader` 21 | * `composer dump-autoload` 22 | * rename Config-sample.php to Config.php 23 | * then configure Config.php 24 | * **!IMPORTANT!** watch repository for 'config' updates 25 | * add task to cron(usually you have crontab on your server) 26 | * if you have crontab - run `crontab -e` from web user(usually webadmin or www-data) 27 | * add `*/5 * * * * cd /var/www/console/vk-to-telegram-bot && php index.php >> /dev/null 2>&1` 28 | * you should change cd command to path where your bot is located 29 | * this will run bot every 5 minutes, if you need every minute check - replace `*/5` to `*` 30 | * if you want to clear your logs add task for clear.php with `php clear.php?clear` 31 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # Docs for vk-to-telegram-bot 2 | 3 | * [FAQ](./faq.md) 4 | * [Installation](./install.md) 5 | * [Updating](./updating.md) 6 | * [Configuration](./config.md) 7 | -------------------------------------------------------------------------------- /docs/updating.md: -------------------------------------------------------------------------------- 1 | # Updating bot 2 | 3 | ## Update steps 4 | 5 | * stop your cron job (comment it) 6 | * backup your `Config.php` 7 | * `git pull` 8 | * `composer dump-autoload` 9 | * `cp app/Config-sample.php app/Config.php` 10 | * edit `Config.php` for your settings 11 | 12 | **each time attentively check Config params names and structure, it may be changed** 13 | -------------------------------------------------------------------------------- /i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "textManager": { 3 | "comment": "Comment in VK:", 4 | "dots": "...", 5 | "from": "Message from", 6 | "read-more": "Read more:" 7 | } 8 | } -------------------------------------------------------------------------------- /i18n/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "textManager": { 3 | "comment": "Комментировать в ВК:", 4 | "dots": "...", 5 | "from": "Сообщение от", 6 | "read-more": "Подробнее:" 7 | } 8 | } -------------------------------------------------------------------------------- /i18n/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "textManager": { 3 | "comment": "", 4 | "dots": "", 5 | "from": "", 6 | "read-more": "" 7 | } 8 | } -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | start(); --------------------------------------------------------------------------------