mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2026-01-31 12:44:18 +01:00
added Channels_GetAllParticipants helper
This commit is contained in:
parent
d22628918c
commit
0351ad027f
|
|
@ -1056,7 +1056,7 @@ namespace WTelegram
|
|||
return user;
|
||||
}
|
||||
|
||||
#region TL-Helpers
|
||||
#region TL-Helpers
|
||||
/// <summary>Helper function to upload a file to Telegram</summary>
|
||||
/// <param name="pathname">Path to the file to upload</param>
|
||||
/// <param name="progress">(optional) Callback for tracking the progression of the transfer</param>
|
||||
|
|
@ -1336,7 +1336,67 @@ namespace WTelegram
|
|||
outputStream.Seek(streamStartPos + maxOffsetSeen, SeekOrigin.Begin);
|
||||
return fileType;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Helper method that tries to fetch all participants from a Channel (beyond Telegram server-side limitations)</summary>
|
||||
/// <param name="channel">The channel to query</param>
|
||||
/// <param name="includeKickBan">Also detch the kicked/banned members?</param>
|
||||
/// <returns>Field count indicates the total count of members. Field participants contains those that were successfully fetched</returns>
|
||||
/// <remarks>This method can take a few minutes to complete on big channels. It likely won't be able to obtain the full total count of members</remarks>
|
||||
public async Task<Channels_ChannelParticipants> Channels_GetAllParticipants(InputChannelBase channel, bool includeKickBan = false)
|
||||
{
|
||||
var result = new Channels_ChannelParticipants { chats = new(), users = new() };
|
||||
|
||||
var sem = new SemaphoreSlim(10); // prevents flooding Telegram with requests
|
||||
var user_ids = new HashSet<long>();
|
||||
var participants = new List<ChannelParticipantBase>();
|
||||
|
||||
var tasks = new List<Task>
|
||||
{
|
||||
GetWithFilter(new ChannelParticipantsAdmins()),
|
||||
GetWithFilter(new ChannelParticipantsBots()),
|
||||
GetWithFilter(new ChannelParticipantsSearch { q = "" }, (f, c) => new ChannelParticipantsSearch { q = f.q + c }),
|
||||
};
|
||||
var mcf = this.Channels_GetFullChannel(channel);
|
||||
tasks.Add(mcf);
|
||||
if (includeKickBan)
|
||||
{
|
||||
tasks.Add(GetWithFilter(new ChannelParticipantsKicked { q = "" }, (f, c) => new ChannelParticipantsKicked { q = f.q + c }));
|
||||
tasks.Add(GetWithFilter(new ChannelParticipantsBanned { q = "" }, (f, c) => new ChannelParticipantsBanned { q = f.q + c }));
|
||||
}
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
result.count = ((ChannelFull)mcf.Result.full_chat).participants_count;
|
||||
result.participants = participants.ToArray();
|
||||
return result;
|
||||
|
||||
async Task GetWithFilter<T>(T filter, Func<T, char, T> recurse = null) where T : ChannelParticipantsFilter
|
||||
{
|
||||
Channels_ChannelParticipants ccp;
|
||||
for (int offset = 0; ;)
|
||||
{
|
||||
await sem.WaitAsync();
|
||||
try
|
||||
{
|
||||
ccp = await this.Channels_GetParticipants(channel, filter, offset, 2000, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
sem.Release();
|
||||
}
|
||||
foreach (var kvp in ccp.chats) result.chats[kvp.Key] = kvp.Value;
|
||||
foreach (var kvp in ccp.users) result.users[kvp.Key] = kvp.Value;
|
||||
lock (participants)
|
||||
foreach (var participant in ccp.participants)
|
||||
if (user_ids.Add(participant.UserID))
|
||||
participants.Add(participant);
|
||||
offset += ccp.participants.Length;
|
||||
if (offset >= ccp.count) break;
|
||||
}
|
||||
if (recurse != null && (ccp.count == 200 || ccp.count == 1000))
|
||||
await Task.WhenAll(Enumerable.Range('a', 26).Select(c => GetWithFilter(recurse(filter, (char)c), recurse)));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Enable the collection of id/access_hash pairs (experimental)</summary>
|
||||
public bool CollectAccessHash { get; set; }
|
||||
|
|
|
|||
|
|
@ -316,9 +316,25 @@ namespace TL
|
|||
public override int Timeout => timeout;
|
||||
}
|
||||
|
||||
partial class ChannelParticipantBase { public virtual bool IsAdmin => false; }
|
||||
partial class ChannelParticipantCreator { public override bool IsAdmin => true; }
|
||||
partial class ChannelParticipantAdmin { public override bool IsAdmin => true; }
|
||||
partial class ChannelParticipantBase
|
||||
{
|
||||
public virtual bool IsAdmin => false;
|
||||
public abstract long UserID { get; }
|
||||
}
|
||||
partial class ChannelParticipantCreator
|
||||
{
|
||||
public override bool IsAdmin => true;
|
||||
public override long UserID => user_id;
|
||||
}
|
||||
partial class ChannelParticipantAdmin
|
||||
{
|
||||
public override bool IsAdmin => true;
|
||||
public override long UserID => user_id;
|
||||
}
|
||||
partial class ChannelParticipant { public override long UserID => user_id; }
|
||||
partial class ChannelParticipantSelf { public override long UserID => user_id; }
|
||||
partial class ChannelParticipantBanned { public override long UserID => peer is PeerUser pu ? pu.user_id : 0; }
|
||||
partial class ChannelParticipantLeft { public override long UserID => peer is PeerUser pu ? pu.user_id : 0; }
|
||||
|
||||
partial class UpdatesBase
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6328,7 +6328,7 @@ namespace TL
|
|||
public abstract partial class ChannelParticipantBase : IObject { }
|
||||
/// <summary>Channel/supergroup participant <para>See <a href="https://corefork.telegram.org/constructor/channelParticipant"/></para></summary>
|
||||
[TLDef(0xC00C07C0)]
|
||||
public class ChannelParticipant : ChannelParticipantBase
|
||||
public partial class ChannelParticipant : ChannelParticipantBase
|
||||
{
|
||||
/// <summary>Pariticipant user ID</summary>
|
||||
public long user_id;
|
||||
|
|
@ -6337,7 +6337,7 @@ namespace TL
|
|||
}
|
||||
/// <summary>Myself <para>See <a href="https://corefork.telegram.org/constructor/channelParticipantSelf"/></para></summary>
|
||||
[TLDef(0x35A8BFA7)]
|
||||
public class ChannelParticipantSelf : ChannelParticipantBase
|
||||
public partial class ChannelParticipantSelf : ChannelParticipantBase
|
||||
{
|
||||
public Flags flags;
|
||||
/// <summary>User ID</summary>
|
||||
|
|
@ -6402,7 +6402,7 @@ namespace TL
|
|||
}
|
||||
/// <summary>Banned/kicked user <para>See <a href="https://corefork.telegram.org/constructor/channelParticipantBanned"/></para></summary>
|
||||
[TLDef(0x6DF8014E)]
|
||||
public class ChannelParticipantBanned : ChannelParticipantBase
|
||||
public partial class ChannelParticipantBanned : ChannelParticipantBase
|
||||
{
|
||||
/// <summary>Flags, see <a href="https://corefork.telegram.org/mtproto/TL-combinators#conditional-fields">TL conditional fields</a></summary>
|
||||
public Flags flags;
|
||||
|
|
@ -6423,7 +6423,7 @@ namespace TL
|
|||
}
|
||||
/// <summary>A participant that left the channel/supergroup <para>See <a href="https://corefork.telegram.org/constructor/channelParticipantLeft"/></para></summary>
|
||||
[TLDef(0x1B03F006)]
|
||||
public class ChannelParticipantLeft : ChannelParticipantBase
|
||||
public partial class ChannelParticipantLeft : ChannelParticipantBase
|
||||
{
|
||||
/// <summary>The peer that left</summary>
|
||||
public Peer peer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue