Skip to content
This repository has been archived by the owner on Dec 5, 2021. It is now read-only.

GetFullChat + GetAllChats + MakeAuthBotAsync + Other methods #926

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions TLSharp.Core/TLSharp.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Network\Requests\AckRequest.cs" />
<Compile Include="Network\Requests\PingRequest.cs" />
<Compile Include="Types\ParticipantFilterTypes.cs" />
<Compile Include="Utils\UploadHelper.cs" />
<Compile Include="Session.cs" />
<Compile Include="TelegramClient.cs" />
Expand Down
243 changes: 242 additions & 1 deletion TLSharp.Core/TelegramClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using TeleSharp.TL;
using TeleSharp.TL.Account;
using TeleSharp.TL.Auth;
using TeleSharp.TL.Channels;
using TeleSharp.TL.Contacts;
using TeleSharp.TL.Help;
using TeleSharp.TL.Messages;
Expand All @@ -17,13 +18,20 @@
using TLSharp.Core.MTProto.Crypto;
using TLSharp.Core.Network;
using TLSharp.Core.Network.Exceptions;
using TLSharp.Core.Types;
using TLSharp.Core.Utils;
using TLAuthorization = TeleSharp.TL.Auth.TLAuthorization;
using TLRequestUpdateUsername = TeleSharp.TL.Account.TLRequestUpdateUsername;
Copy link
Contributor

@aarani aarani Apr 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reason behind this? just use it directly inside the code. there is hundreds of request used in this file. no need to add alias for just one use

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually TLRequestUpdateUsername is ambigous with as it's already present in TL.Channels. i can double check and report exactly where.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TLRequestUpdateUsername' is an ambiguous reference between 'TeleSharp.TL.Account.TLRequestUpdateUsername' and 'TeleSharp.TL.Channels.TLRequestUpdateUsername'

'TLAuthorization' is an ambiguous reference between 'TeleSharp.TL.Auth.TLAuthorization' and 'TeleSharp.TL.TLAuthorization' TLSharp.Core

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fair enough


namespace TLSharp.Core
{
public class TelegramClient : IDisposable
{
/// <summary>
/// When pagination is needed, this is the default page size
/// </summary>
public const int DEFAULT_PAGE_SIZE = 200;

private MtProtoSender sender;
private TcpTransport transport;
private string apiHash = String.Empty;
Expand Down Expand Up @@ -262,7 +270,7 @@ public bool IsUserAuthorized()

public async Task<bool> CheckUsernameAsync(string username, CancellationToken token = default(CancellationToken))
{
var req = new TLRequestCheckUsername { Username = username };
var req = new TeleSharp.TL.Account.TLRequestCheckUsername { Username = username };

return await SendAuthenticatedRequestAsync<bool>(req, token)
.ConfigureAwait(false);
Expand Down Expand Up @@ -406,6 +414,239 @@ await sender.SendPingAsync(token)
.ConfigureAwait(false);
}

/// <summary>
/// Authenticates a Bot
/// </summary>
/// <param name="botAuthToken">The token of the bot to authenticate</param>
/// <param name="token"></param>
/// <returns>The TLUser descriptor</returns>
public async Task<TLUser> MakeAuthBotAsync(string botAuthToken, CancellationToken token = default(CancellationToken))
{
if (String.IsNullOrWhiteSpace(botAuthToken))
{
throw new ArgumentNullException(nameof(botAuthToken));
}

var request = new TLRequestImportBotAuthorization() { BotAuthToken = botAuthToken, ApiId = apiId, ApiHash = apiHash };

await RequestWithDcMigration(request, token).ConfigureAwait(false);

OnUserAuthenticated(((TLUser)request.Response.User));

return ((TLUser)request.Response.User);
}

/// <summary>
/// Gets the full information of a specified chat
/// </summary>
/// <param name="chatId">The ID of the chat we want the info of</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TeleSharp.TL.Messages.TLChatFull> GetFullChat(int chatId, CancellationToken token = default(CancellationToken))
{
var req = new TLRequestGetFullChat() { ChatId = chatId };
var fchat = await SendRequestAsync<TeleSharp.TL.Messages.TLChatFull>(req, token).ConfigureAwait(false);

return fchat;
}

/// <summary>
/// Gets the list of chats and channels opened by the authenticated user.
/// Throws an exception if the authenticated user is a bot.
/// </summary>
/// <param name="token"></param>
/// <returns>The list of chats opened by the authenticated user</returns>
public async Task<TLChats> GetAllChats(CancellationToken token = default(CancellationToken))
{
return await GetAllChats(null, token);
}

/// <summary>
/// Gets the list of chats and channels opened by the authenticated user except the passed ones.
/// Throws an exception if the authenticated user is a bot.
/// </summary>
/// <param name="ids">The IDs of the chats to be returned</param>
/// <param name="token"></param>
/// <returns>The list of chats opened by the authenticated user</returns>
public async Task<TLChats> GetAllChats(int[] exceptdIds, CancellationToken token = default(CancellationToken))
{
var ichats = new TeleSharp.TL.TLVector<int>(); // we can't pass a null argument to the TLRequestGetChats
if (exceptdIds != null)
Array.ForEach(exceptdIds, x => ichats.Add(x));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of Array.ForEach because it hardcodes "Array"; isn't there an IEnumerable-esque way of doing this?

Copy link

@barrywimlett barrywimlett Dec 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// there is a handy constructor
var ichats = exceptdIds!=null ? new TeleSharp.TL.TLVector(exceptdIds) : new TeleSharp.TL.TLVector();

// if (exceptdIds != null)
// Array.ForEach(exceptdIds, x => ichats.Add(x));

var chats = await SendRequestAsync<TLChats>(new TLRequestGetAllChats() { ExceptIds = ichats }, token).ConfigureAwait(false);
return chats;
}

/// <summary>
/// Gets the information about a channel
/// </summary>
/// <param name="channel">The channel to get the info of</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TeleSharp.TL.Messages.TLChatFull> GetFullChannel(TLChannel channel, CancellationToken token = default(CancellationToken))
{
if (channel == null) return null;
return await GetFullChannel(channel.Id, (long)channel.AccessHash, token).ConfigureAwait(false);
}

/// <summary>
/// Gets the information about a channel
/// </summary>
/// <param name="channelId">The ID of the channel</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TeleSharp.TL.Messages.TLChatFull> GetFullChannel(int channelId, long accessHash, CancellationToken token = default(CancellationToken))
{
var req = new TLRequestGetFullChannel() { Channel = new TLInputChannel() { ChannelId = channelId, AccessHash = accessHash } };
var fchat = await SendRequestAsync<TeleSharp.TL.Messages.TLChatFull>(req, token).ConfigureAwait(false);

return fchat;
}

/// <summary>
/// Gets the channels having the supplied IDs
/// </summary>
/// <param name="channelIds">The IDs of the channels to be retrieved</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TeleSharp.TL.Messages.TLChats> GetChannels(int[] channelIds, CancellationToken token = default(CancellationToken))
{
var channels = new TLVector<TeleSharp.TL.TLAbsInputChannel>(); // we can't pass a null argument to the TLRequestGetChats
if (channelIds != null)
Array.ForEach(channelIds, x => channels.Add(new TLInputChannel() { ChannelId = x }));
var req = new TLRequestGetChannels() { Id = channels };
var fchat = await SendRequestAsync<TeleSharp.TL.Messages.TLChats>(req, token).ConfigureAwait(false);

return fchat;
}

/// <summary>
/// Gets the participants of the channel having the supplied type.
/// The method will auto-paginate results and return all the participants
/// </summary>
/// <param name="channel">The TLChannel whose participants are requested</param>
/// <param name="stIdx">The index to start fetching from. -1 will automatically fetch all the results</param>
/// <param name="pageSize">How many results to be fetch on each iteration.
/// Values smaller than 0 are ignored. If stIdx is set, a number of results smaller than pageSize might be returned by Telegram.</param>
/// <param name="partType">The type of the participants to get. Choose Recents not to filter</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TLChannelParticipants> GetParticipants(TLChannel channel, int stIdx = -1, int pageSize = -1, ParticipantFilterTypes partType = ParticipantFilterTypes.Recents, CancellationToken token = default(CancellationToken))
{
if (channel == null) return null;
return await GetParticipants(channel.Id, (long)channel.AccessHash, stIdx, pageSize, partType, token).ConfigureAwait(false);
}

/// <summary>
/// Gets the participants of the channel having the supplied type.
/// The method will auto-paginate results and return all the participants
/// </summary>
/// <param name="channelId">The id of the channel whose participants are requested</param>
/// <param name="accessHash">The access hash of the channel whose participants are requested</param>
/// <param name="stIdx">The index to start fetching from. -1 will automatically fetch all the results</param>
/// <param name="pageSize">How many results to be fetch on each iteration.
/// Values smaller than 0 are ignored. If stIdx is set, a number of results smaller than pageSize might be returned by Telegram.</param>
/// <param name="partType">The type of the participants to get. Choose Recents not to filter</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<TLChannelParticipants> GetParticipants(int channelId, long accessHash, int stIdx = -1, int pageSize = -1, ParticipantFilterTypes partType = ParticipantFilterTypes.Recents, CancellationToken token = default(CancellationToken))
{
TLAbsChannelParticipantsFilter filter;
switch (partType)
{
case ParticipantFilterTypes.Admins:
filter = new TLChannelParticipantsAdmins();
break;

case ParticipantFilterTypes.Kicked:
filter = new TLChannelParticipantsKicked();
break;

case ParticipantFilterTypes.Bots:
filter = new TLChannelParticipantsBots();
break;

case ParticipantFilterTypes.Recents:
filter = new TLChannelParticipantsRecent();
break;

case ParticipantFilterTypes.Banned:
case ParticipantFilterTypes.Restricted:
case ParticipantFilterTypes.Contacts:
case ParticipantFilterTypes.Search:
default:
throw new NotImplementedException($"{partType} not implemented yet");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not gonna be implemented please remove them from your enum as the only purpose of enum is for this filter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's gonna be implemented as soon as the new Classes are added to the TL framework

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should i drop them anyways or leave them?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are they present in the new layers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vote, then, for only merging this PR after we have updated the layer

}

int total = 0;
int found = stIdx < 0 ? 0 : stIdx;
pageSize = pageSize < 0 ? DEFAULT_PAGE_SIZE : pageSize;

TLChannelParticipants ret = new TLChannelParticipants();
ret.Participants = new TLVector<TLAbsChannelParticipant>();
ret.Users = new TLVector<TLAbsUser>();

do
{
var req = new TLRequestGetParticipants()
{
Channel = new TLInputChannel()
{
ChannelId = channelId,
AccessHash = accessHash
},
Filter = filter,
Offset = found,
Limit = pageSize
};
var fchat = await SendRequestAsync<TLChannelParticipants>(req, token).ConfigureAwait(false);
total = fchat.Count;
found += fchat.Participants.Count;
foreach (var p in fchat.Participants)
ret.Participants.Add(p);
foreach (var u in fchat.Users)
ret.Users.Add(u);
} while (found < total && stIdx == -1);
ret.Count = ret.Participants.Count;
return ret;
}

/// <summary>
/// Invites the passed users to the specified channel
/// </summary>
/// <param name="channel">The descriptor of the channel to invite the users to</param>
/// <param name="users"></param>
/// <returns></returns>
public async Task<TLUpdates> InviteToChannel(TLChannel channel, int[] users, CancellationToken token = default(CancellationToken))
{
return await InviteToChannel(channel.Id, (long)channel.AccessHash, users, token);
}
solarin marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Invites the passed users to the specified channel
/// </summary>
/// <param name="channelId">The id of the channel to invite the users to</param>
/// <param name="accessHash">The access hash of the channel to invite the users to</param>
/// <param name="users"></param>
/// <returns></returns>
public async Task<TLUpdates> InviteToChannel(int channelId, long accessHash, int[] users, CancellationToken token = default(CancellationToken))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use TLChannel or TLInputChannel as parameter here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I create an overload as for the other methods, ok?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure nice

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is not working, always return UserId_Invalid exception
You have to assign both UserId and Hash to TLInputUser.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamesjsc do you mind porting this PR to TgSharp?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@knocte ok

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@knocte What is the different between TLSharp and TgSharp?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL Layer update, Tg is the future, TL will just receive bug fixes, no new features.

{
TLVector<TLAbsInputUser> absUsers = new TLVector<TLAbsInputUser>();
Array.ForEach(users, u => absUsers.Add(new TLInputUser() { UserId = u }));
var req = new TLRequestInviteToChannel()
{
Channel = new TLInputChannel()
{
ChannelId = channelId,
AccessHash = accessHash
},
Users = absUsers
};
var updates = await SendRequestAsync<TLUpdates>(req, token).ConfigureAwait(false);

return updates;
}

/// <summary>
/// Serch user or chat. API: contacts.search#11f812d8 q:string limit:int = contacts.Found;
/// </summary>
Expand Down
16 changes: 16 additions & 0 deletions TLSharp.Core/Types/ParticipantFilterTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace TLSharp.Core.Types
{
public enum ParticipantFilterTypes
{
Recents,
Restricted,
Admins,
Bots,
Search,
Contacts,
Kicked,
Banned
}


}