65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Telegram API 的 C# 远程文件夹浏览器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2023年8月29日

CPOL

6分钟阅读

viewsIcon

7254

downloadIcon

366

用于在控制计算机和目标设备之间通过 Telegram API 发送和接收命令的机器人程序和 API 程序

引言

第一个程序是 Bot(BotServiceApp),它的任务是实现将从控制计算机发送的命令。它将配备一个界面来显示和分析数据流量。此程序应在目标设备上运行。

程序 API(RemoteFolderExplorer)将在控制计算机上运行。此程序负责发送命令、接收响应以及分析它们,以便在用户界面上显示它们。

为了更容易理解工作机制,我制作了以下图示

假设我们在设备上的资源管理器程序中探索一个特定文件夹。此时,程序将创建一个新的命令实例(一组封装在类中的变量),并将该类转换为 JSON。然后,该命令将通过 Telegram 服务器发送到 Telegram Bot。此时,Bot程序会收到该命令,并将其再次转换回与其转换前相同的类。然后,该命令将在目标计算机上执行。之后,程序将创建一个响应,将其转换为 JSON,并将其发送回我们的设备。最后,它将被转换、分析并在控制计算机的资源管理器程序的用户界面上显示。

要让我们的程序正常工作,我们需要三样东西

  1. 创建一个 Telegram Bot,用于从中发送或接收命令
  2. 我们创建的Bot的令牌
  3. API ID 和 API Hash,使我们能够将 API 连接到服务器

在本文中,我们将学习如何获取所有这些信息。

我们开始吧。

创建 Telegram Bot 并获取其令牌

第一步

打开你的 Telegram。在搜索字段中,键入 @Botfather,然后点击搜索列表中的第一个Bot,如下图所示

第二步

点击Botfather后,Telegram中将打开一个新窗口,如下图所示

在此窗口中,在输入字段中输入 start 命令,如下图所示,然后将显示所有可用命令的列表,如下图所示

第三步

点击命令/newbotBotFather现在会询问你Bot的名称。选择Bot的名称并将其放入输入字段。然后Bot Father 会再次询问Bot的用户名,因此将用户名放入输入字段,不要忘记名称必须以 Bot 结尾。

以下显示了步骤

创建 Telegram API

定义:它是一个库,使我们能够完全控制我们的 Telegram 帐户,从发送消息到接收消息,再到控制我们的 Bot。

获取控制我们 Telegram 帐户的授权:要获得控制你 Telegram 帐户的授权,你必须按照以下步骤进行

  1. 我们打开以下链接 https://my.telegram.org/apps。我们输入我们的号码,然后点击Next,然后一条消息将到达我们的 Telegram 帐户,其中包含确认码。然后我们取走代码并将其放入输入字段,然后点击Next
  2. 我们进入面板以创建我们自己的Telegram应用程序,如下图所示

现在我们需要填写第一个和第二个字段,选择桌面平台,点击创建应用程序,然后将出现一个新窗口,其中包含我们的IDhash

创建 Explorer 程序

在我们获得控制Bot(令牌)和控制我们的 Telegram 帐户(IDhash)所需的必要信息后,我们就可以开始编程我们的程序集了。

我们将开始编程 explorer 程序,该程序将发送命令,从目标计算机接收响应,并在我们的设备上以可理解的方式显示数据。

首先,我们需要在项目中安装必要的库。以下库对于我们的程序正常工作是必需的

  • WTelegramClient

    使用Paket-Manager-Console,输入以下命令

    NuGet\Install-Package WTelegramClient -Version 3.5.3
  • Newtonsoft.Json

    使用 Paket-Manager-Console,输入以下命令

    NuGet\Install-Package Newtonsoft.Json -Version 13.0.3

现在我们已准备好开始编程。首先,我们需要连接到Telegram服务器。以下代码将负责建立与Telegram的连接

   .
   .
   .
   WTelegram.Client _client;
   .
   .

   private async void Connect(int ApiID, string ApiHash, string Phone) {

     _client = new WTelegram.Client(ApiID, ApiHash);
     await DoLogin(Phone);

   }

在上面的代码中,我们定义了Client类的新实例,作为输入,我们输入了我们的 telegram hash 和 telegram id,然后我们尝试使用我们的号码登录Telegram服务器。

      private async Task DoLogin(string loginInfo) {
        string what = await _client.Login(loginInfo);
        if (what != null) {
          Log.Debug(what + ", , is required to connect with telegram Server ");
          return;
        } else {
          Log.Info( " successfully connected with telegram Server ");
        }
      }

对于DoLogin方法,我们尝试使用我们客户端实例中的登录方法连接到Telegram服务器。如果我们已经有一个有效的会话文件,该方法将返回null,我们将成功连接到Telegram API,否则该方法将返回缺少或必需字段的名称(最常见的值是确认码),在您输入 API IDhash后,此代码将作为Telegram消息收到。

   await DoLogin(Confirm_Code);

获得确认码后,我们将再次使用DoLogin方法输入确认码,然后我们将成功连接到Telegram API。

重要的是要注意,在我们成功连接到Telegram后,我们不再需要输入确认码,因为该库将创建一个会话文件,用于在输入我们的IDhash和号码后自动连接到 Telegram。

现在,我们已连接到Telegram API,准备开始。下一步将是创建一个线程来组织传入的响应和传出的请求。像这样的东西会起作用

    public delegate void SetSignalWaitingForFile(CommandInfo Info);
    public delegate void SetSignalFileIsNowAvailable(bool Error, CommandInfo Info);
    public class WaitingForFileThread {

      private object syncRoot = new object();
      public CommandInfo CommandInfo {
        get;
        set;
      }
      public bool SignalSet {
        get;
        set;
      }
      public bool Error {
        get;
        set;
      }
      public Client _client {
        get;
        set;
      }
      public IPeerInfo TargetUser {
        get;
        set;
      }

      public event SetSignalWaitingForFile SetSignalWaitingForFile;

      public event SetSignalFileIsNowAvailable SetSignalFileIsNowAvailable;

      public void StartWaitingAsync() {

        lock(this.syncRoot)
        ThreadPool.QueueUserWorkItem(_ = > ThreadProc());
      }
      public void Set(bool _Error) {
        lock(this.syncRoot) {
          if (!this.SignalSet) {
            this.SignalSet = true;
            this.Error = _Error;
          }
        }
      }

      async void ThreadProc() {
        Error = false;
        this.SignalSet = false;
        SetSignalWaitingForFile(CommandInfo);
        string jsontxt = JsonConvert.SerializeObject(CommandInfo);
        await _client.SendMessageAsync(TargetUser.ToInputPeer(), jsontxt);
        while (!this.SignalSet) {}
        if (!Error)
          SetSignalFileIsNowAvailable(false, this.CommandInfo);
        else
          SetSignalFileIsNowAvailable(true, this.CommandInfo);
      }
    }

此类会将命令转换为 JSON 并将其发送到Telegram Bot,以便稍后由目标设备进行修订。此类还将创建一个线程,该线程将等待来自目标设备的响应,并在收到预期响应后触发一个事件。此事件将负责处理响应并将其显示在应用程序上。

创建 Bot 程序

正如我之前解释过的,对于Bot,我们创建了一个单独的程序,以便我们可以在目标 PC 上运行它。

首先,我们需要在项目中安装必要的库。

  • Telegram.Bot

    使用Paket-Manager-Console,输入以下命令

    NuGet\Install-Package Telegram.Bot -Version 19.0.0
  • Newtonsoft.Json

    使用Paket-Manager-Console,输入以下命令

    NuGet\Install-Package Newtonsoft.Json -Version 13.0.3
  • System.Management

    使用Paket-Manager-Console,输入以下命令

    NuGet\Install-Package System.Management -Version 7.0.2
  • SharpAESCrypt.dll

    使用Paket-Manager-Console,输入以下命令

    NuGet\Install-Package SharpAESCrypt.dll -Version 1.3.4

现在我们可以开始编程了。首先,我们需要连接到Telegram服务器。下面的代码负责连接到Telegram。请记住,我们现在使用的是 Bot API,而不是Telegram使用的 API。

      async Task HandleUpdateAsync(ITelegramBotClient Client, 
                 Update update, CancellationToken cancellationToken) {

        var chatId = update.Message.Chat.Id;

        try {
          string msg = update.Message.Text;
          if (msg == " Hi ")
            await BotClient.SendTextMessageAsync(chatId, " Hello World ");
        } catch (Exception exc) {

          await BotClient.SendTextMessageAsync(chatId, exc.Message);
        }
      }
  Task HandlePollingErrorAsync(ITelegramBotClient botClient, 
       Exception exception, CancellationToken cancellationToken) {
    return Task.CompletedTask;
  }
.
.
.

BotClient = new TelegramBotClient(tocken_tb.Text);
var receiverOptions = new ReceiverOptions {
  AllowedUpdates = Array.Empty <updatetype>()
};

BotClient.ReceiveAsync(
  updateHandler: HandleUpdateAsync,
  pollingErrorHandler: HandlePollingErrorAsync,
  receiverOptions: receiverOptions,
  cancellationToken: CTS.Token
);
.
.
. </updatetype>

在程序的结构中,我们严重依赖命令模式。这将极大地组织我们的代码并为我们节省大量工作。

注意:在 explorer 程序中,我禁用了加密和解密按钮。尽管它们功能齐全,但有时会触发错误,因此请自行决定启用它们。

在下面的视频中,我向你展示了如何使用该程序

历史

  • 2023 年 8 月 29 日:初始版本
© . All rights reserved.