【问题标题】:How can I get channel messages from telegram channels with TLSharp?如何使用 TLSharp 从电报频道获取频道消息?
【发布时间】:2016-09-08 11:08:59
【问题描述】:

如何使用 TLSharp 从电报频道获取频道消息?

以下链接对我没有帮助:

【问题讨论】:

    标签: telegram


    【解决方案1】:

    不确定这是否 100% 有效而不会丢失任何消息,但这是我在我的一个项目中使用的:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using TeleSharp.TL;
    using TeleSharp.TL.Channels;
    using TeleSharp.TL.Messages;
    using TLSharp.Core;
    using TLSharp.Core.Utils;
    
    namespace NewsArchive.Telegram
    {
     /// <summary>
    /// Created to be used as a workaround of ref/out since they cannot be used in an async method => GetMessagesInternal
    /// </summary>
    public class RequestOffset
    {
        /// <summary>
        /// Value of the offset
        /// </summary>
        public int Id { get; set; }
    }
    
    
    public class TelegramNewsClient
    {
        #region Properties
        private TelegramClient _client;
        private int _apiId;
        private string _apiHash;
        private static readonly int RESULT_MAX = 100; 
        #endregion
    
        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="apiId"></param>
        /// <param name="apiHash"></param>
        public TelegramNewsClient(int apiId, string apiHash)
        {
            _apiId = apiId;
            _apiHash = apiHash;
    
            _client = new TelegramClient(_apiId, _apiHash);
            _client.ConnectAsync().Wait();
        }
    
        /// <summary>
        /// Authenticates the user with the phone number
        /// </summary>
        /// <param name="phone"></param>
        /// <returns></returns>
        public async Task Authenticate(string phone)
        {
            var hash = await  _client.SendCodeRequestAsync(phone);
            var code = "<code_from_telegram>"; // you can change code in debugger
    
            var user = await _client.MakeAuthAsync(phone, hash, code);
        }
    
        /// <summary>
        /// Gets all messages from a channel
        /// </summary>
        /// <param name="channelName"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TLMessage>> GetChannelMessages(string channelName)
        {
            var messages = new List<TLMessage>();
    
            var channel = await GetChannel(channelName);
    
            if(channel == null)
                throw new Exception($"The channel {channelName} was not found!");
    
            var offset = new RequestOffset(){Id = 1};
            var internalMessages = new List<TLMessage>();
    
            internalMessages = await GetMessagesInternal(channel.Id, channel.AccessHash.Value, offset);
    
            messages = messages.Concat(internalMessages)
                                .OrderBy(m => m.Id)
                                .ToList();
    
            while (internalMessages.Count > 0)
            {
                /*When you reach the last message, the API will keep returning the same last message over and over again,
                 that's why we stop making requests and return the result*/
                if ((internalMessages.Count == 1 && internalMessages.First().Id == messages.Max(m => m.Id)))
                    break;
    
                internalMessages = await GetMessagesInternal(channel.Id, channel.AccessHash.Value, offset);
    
                messages = messages.Concat(internalMessages)
                                    .OrderBy(m =>m.Id)
                                    .ToList();
    
                /*if you make too many requests you will be locked out of the API*/
                await Task.Delay(TimeSpan.FromSeconds(1));
    
            }
    
            return messages;
        }
    
        private async Task<List<TLMessage>> GetMessagesInternal(int channelId, long accessHash, RequestOffset offset)
        {
            /*Refer to https://core.telegram.org/api/offsets  for more info on how to use the offsets.
             Here we basically get the last RESULT_MAX (100 in this case) messages newer than the offset.Id aka offsetId*/
            var history = await _client.GetHistoryAsync(new TLInputPeerChannel
            {
                ChannelId = channelId,
                AccessHash = accessHash
            }, offset.Id, 0, -RESULT_MAX, RESULT_MAX, 0, 0) as TLChannelMessages;
    
            /*Some messages are service messages with no useful content, and if cast to TLMessage it will throw an exception*/
            var messages = history.Messages
                                    .Where(m => m is TLMessage)
                                    .Cast<TLMessage>()
                                    .ToList();
    
            /*Get the ID of the last message so it can be used in the next API call*/
            offset.Id = messages.Max(m => m.Id);
    
            
            return messages;
        }
    
        private async Task<TLChannel> GetChannel(string channelName)
        {
            var offset = new RequestOffset() { Id = RESULT_MAX };
    
            var channels = (await _client.GetUserDialogsAsync(0, offset.Id, null, RESULT_MAX) as TLDialogs)
                            ?.Chats
                            ?.Cast<TLChannel>()
                            ?.ToList();
    
            var channel = channels?.FirstOrDefault(c => c.Username.Equals(channelName, StringComparison.OrdinalIgnoreCase));
    
            offset.Id += RESULT_MAX - 1;
    
            while (channels.Count > 0 && channel == null)
            {
                channels = (await _client.GetUserDialogsAsync(0, offset.Id, null, RESULT_MAX) as TLDialogs)
                                ?.Chats
                                ?.Cast<TLChannel>()
                                ?.ToList();
    
                channel = channels?.FirstOrDefault(c => c.Username.Equals(channelName, StringComparison.OrdinalIgnoreCase));
    
                offset.Id += RESULT_MAX - 1;
    
                /*if you make too many requests you will be locked out of the API*/
                await Task.Delay(TimeSpan.FromSeconds(1));
            }
    
            return channel;
        }
    }
    

    }

    【讨论】:

      【解决方案2】:

      您可以使用此代码

              public async Task GatherChannelHistory(string channelName, int offset = 0, int maxId = -1, int limit = 50)
          {
              _resultMessages.Clear();
              await _client.ConnectAsync();
      
              var dialogs = (TLDialogsSlice)await _client.GetUserDialogsAsync();
              var chat = dialogs.Chats.ToList()
                  .OfType<TLChannel>()
                  .FirstOrDefault(c => c.Title == channelName);
      
              if (chat.AccessHash != null)
              {
                  var tlAbsMessages =
                      await _client.GetHistoryAsync(
                          new TLInputPeerChannel {ChannelId= chat.Id, AccessHash = chat.AccessHash.Value}, offset,
                          maxId, limit);
      
                  var tlChannelMessages = (TLChannelMessages) tlAbsMessages;
      
                  for (var index = 0; index < tlChannelMessages.Messages.Count-1; index++)
                  {
                      var tlAbsMessage = tlChannelMessages.Messages.ToList()[index];
                      var message = (TLMessage) tlAbsMessage;
                      //Now you have the message and you can do what you need with it
                      //the code below is an example of messages classification
                      if (message.media == null)
                      {
                          _resultMessages.Add(new ChannelMessage()
                          {
                              Id = message.id,
                              ChannelId = chat.id,
                              Content = message.message,
                              Type = EnChannelMessage.Message,
                              Views = message.views,
                          });
                      }
                      else
                      {
      
                          switch (message.media.GetType().ToString())
                          {
                              case "TeleSharp.TL.TLMessageMediaPhoto":
                                  var tLMessageMediaPhoto = (TLMessageMediaPhoto)message.media;
      
                                  _resultMessages.Add(new ChannelMessage()
                                  {
                                      Id = message.id,
                                      ChannelId = chat.id,
                                      Content = tLMessageMediaPhoto.caption,
                                      Type = EnChannelMessage.MediaPhoto,
                                      Views = message.views ?? 0,
                                  });
                                  break;
                              case "TeleSharp.TL.TLMessageMediaDocument":
                                  var tLMessageMediaDocument = (TLMessageMediaDocument)message.media;
      
                                  _resultMessages.Add(new ChannelMessage()
                                  {
                                      Id = message.id,
                                      ChannelId = chat.id,
                                      Content = tLMessageMediaDocument.caption,
                                      Type = EnChannelMessage.MediaDocument,
                                      Views = message.views ?? 0,
                                  });
                                  break;
                              case "TeleSharp.TL.TLMessageMediaWebPage":
                                  var tLMessageMediaWebPage = (TLMessageMediaWebPage)message.media;
                                  string url = string.Empty;
                                  if (tLMessageMediaWebPage.webpage.GetType().ToString() != "TeleSharp.TL.TLWebPageEmpty")
                                  {
                                      var webPage = (TLWebPage) tLMessageMediaWebPage.webpage;
                                      url = webPage.url;
                                  }
      
                                  _resultMessages.Add(new ChannelMessage
                                  {
                                      Id = message.id,
                                      ChannelId = chat.id,
                                      Content = message.message + @" : " + url,
                                      Type = EnChannelMessage.WebPage,
                                      Views = message.views ?? 0,
                                  });
                                  break;
                          }
                      }
                  }
              }
          }
      

      【讨论】:

      • 你应该解释为什么使用它,即描述你的解决方案
      • tlsharp 中的代码很清楚,您可以使用 GetHistoryAsync 获取消息,只需发送 TLInputPeerChannel 作为第一个参数,然后您必须转换结果才能获取内容:-)
      • @arashDehghan 是否可以获得更新的频道列表?所以我们会阅读每个更新频道的所有新帖子?
      • 每条消息都有一个唯一的 id,因此您不需要所有消息,您只需要阅读其 Id 大于您上一条消息 id 的消息,我希望它会有所帮助。
      • 我无法运行代码。 _resultMessages 是什么?它是更长代码的一部分吗?请指教。
      【解决方案3】:

      要获取频道消息,您只需接收频道更新。

      与 TL-schema-52 一样,您可以要求:

      channels.getDialogs#a9d3d249 offset:int limit:int = messages.Dialogs; 
      

      然而,这已在 TL-schema-53 中被删除。

      我猜你可以试试其他 channel.* 函数之一,

      我还没有尝试过 TL-schema-53

      您的 TLSharp 使用什么版本的 TL-schema?

      如果您的 TLSharp 版本中尚未实现相关功能,您可以简单地实现它们

      【讨论】:

        猜你喜欢
        • 2017-03-04
        • 2022-08-11
        • 1970-01-01
        • 2016-08-23
        • 1970-01-01
        • 2018-03-25
        • 1970-01-01
        • 2018-01-30
        • 1970-01-01
        相关资源
        最近更新 更多