Building a C# Remote Directory Explorer with Telegram Integration
System Architecture
The solution consists of two distinct C# applications: a Controller application running on the local machine, and a Bot agent executing on the remote target machine. The Controller issues commands serialized as JSON, transmits them through the Telegram cloud, and waits for the Bot agent to execute the operation on the target file system and return the result.
Prerequisites
- Bot Token: Obtain a new bot token by interacting with the
@BotFatherbot on Telegram. Use the/newbotcommand, assign a display name, and set a username ending in "bot". - API Credentials: Visit
https://my.telegram.org/appsto register a new application. After verifying your phone number, fill out the form to generate theApp api_idandApp api_hash.
Implementing the Controller Application
The Controller requires the WTelegramClient and Newtonsoft.Json packages.
Install-Package WTelegramClient
Install-Package Newtonsoft.Json
Establish a session with the Telegram API using the credentials and phone number. The client persists the session, so subsequent runs won't require the verification code.
private WTelegram.Client telegramClient;
private async Task InitializeClientAsync(int apiId, string apiHash, string phoneNumber)
{
telegramClient = new WTelegram.Client(apiId, apiHash);
await AuthenticateAsync(phoneNumber);
}
private async Task AuthenticateAsync(string credential)
{
string requiredAction = await telegramClient.Login(credential);
if (string.IsNullOrEmpty(requiredAction))
{
Console.WriteLine("Telegram API connection established.");
}
else
{
Console.WriteLine($"Pending action: {requiredAction}");
}
}
// Upon receiving the verification code via Telegram:
// await AuthenticateAsync(verificationCode);
To manage outbound requests and inbound responses, implement an asynchronous orchestrator. This component sends the serialized command and halts execution until the target machine replies or a timeout occurs.
public class CommandOrchestrator
{
private readonly object _syncLock = new object();
private readonly WTelegram.Client _messenger;
private readonly IPeerInfo _destination;
public CommandPayload Payload { get; set; }
public bool IsCompleted { get; set; }
public bool HasFailed { get; set; }
public event Action<CommandPayload> OnRequestDispatched;
public event Action<bool, CommandPayload> OnResponseReceived;
public CommandOrchestrator(WTelegram.Client messenger, IPeerInfo destination)
{
_messenger = messenger;
_destination = destination;
}
public void Dispatch()
{
ThreadPool.QueueUserWorkItem(_ => ProcessCommand());
}
public void Complete(bool failed)
{
lock (_syncLock)
{
if (!IsCompleted)
{
IsCompleted = true;
HasFailed = failed;
}
}
}
private async void ProcessCommand()
{
IsCompleted = false;
HasFailed = false;
OnRequestDispatched?.Invoke(Payload);
string Data = JsonConvert.SerializeObject(Payload);
await _messenger.SendMessageAsync(_destination.ToInputPeer(), Data);
while (!IsCompleted) { /* Wait for signal */ }
OnResponseReceived?.Invoke(HasFailed, Payload);
}
}
Implementing the Bot Agent
The remote agent requires the Telegram.Bot, Newtonsoft.Json, System.Management, and SharpAESCrypt libraries.
Install-Package Telegram.Bot
Install-Package Newtonsoft.Json
Install-Package System.Management
Install-Package SharpAESCrypt
Initialize the bot using the token obtained from BotFather and set up a polling mechanism to listen for incoming commands.
private TelegramBotClient botAgent;
private async Task StartBotAsync(string token, CancellationToken cancellationToken)
{
botAgent = new TelegramBotClient(token);
var options = new ReceiverOptions { AllowedUpdates = Array.Empty<UpdateType>() };
await botAgent.ReceiveAsync(
updateHandler: ProcessIncomingUpdate,
pollingErrorHandler: HandlePollingException,
receiverOptions: options,
cancellationToken: cancellationToken
);
}
private async Task ProcessIncomingUpdate(ITelegramBotClient client, Update update, CancellationToken token)
{
var conversationId = update.Message.Chat.Id;
try
{
string payload = update.Message.Text;
if (payload == "PING")
{
await client.SendTextMessageAsync(conversationId, "PONG", cancellationToken: token);
}
// Deserialize payload and execute file system operations
}
catch (Exception ex)
{
await client.SendTextMessageAsync(conversationId, $"Error: {ex.Message}", cancellationToken: token);
}
}
private Task HandlePollingException(ITelegramBotClient client, Exception ex, CancellationToken token)
{
Console.WriteLine($"Polling error: {ex.Message}");
return Task.CompletedTask;
}
The system relies heavily on the Command Pattern to encapsulate all file system operations within structured payloads, ensuring consistent serialization and execution logic across the network boundary.