How can I get channel messages from telegram channels with TLSharp?
Asked Answered
C

3

6

How can I get channel messages from telegram channels with TLSharp?

The following links haven't helped me:

Calcareous answered 12/5, 2016 at 14:26 Comment(0)
F
3

You can use this code

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;
        }
      }
    }
  }
}
Fenny answered 8/3, 2017 at 7:21 Comment(7)
you should explain why use it, i.e. describe your solutionDzungaria
the code is clear in tlsharp you can use GetHistoryAsync for get messages just send TLInputPeerChannel for first parameter and then you must cast the result for get the content :-)Fenny
@arashDehghan Is it possible to get updated channels list?so we read all new posts for each updated channel?Caribou
Every message has an id that it is unique, so you didn't need all messages and you just need read messages that their Id's are greater than your last message id, i hope it would be helpful.Fenny
I can't run the code. What's _resultMessages? Is it part of a longer code? please advice.Cushiony
In this approach the client calls the server to get the messages, Is there any approach which the client listens to server for new messages in channels?Divorce
Maybe this type? List<UserMessage> _resultMessages = new List<UserMessage>();Hoxha
E
1

To get channel messages you simply need to be receiving channel updates.

As at TL-schema-52 you could request:

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

however this has been dropped in TL-schema-53.

I'm guessing you can try one of the other channel.* functions,

I have not tried yet on TL-schema-53

What version of the TL-schema is your TLSharp using?

You could simply implement the relevant functions if they are not yet implemented in your TLSharp version

Enlarger answered 16/6, 2016 at 7:36 Comment(0)
S
1

Not sure if this works 100% without missing any messages, but this is what I have used in one of my projects:

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;
    }
}

}

Southernmost answered 14/7, 2021 at 6:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.