Remove deprecated CollectAccessHash system

This commit is contained in:
Wizou 2023-02-14 11:14:17 +01:00
parent 08a0802ed3
commit 7948dbd8e3
6 changed files with 23 additions and 75 deletions

View file

@ -15,49 +15,6 @@ namespace WTelegram
{
partial class Client
{
#region Collect Access Hash system
#pragma warning disable CS0618 // Type or member is obsolete
/// <summary>Enable the collection of id/access_hash pairs (deprecated)</summary>
[Obsolete("This system will be removed in a future version. You should use CollectUsersChats helper on API results or updates instead. See https://wiz0u.github.io/WTelegramClient/EXAMPLES#collect-users-chats")]
public bool CollectAccessHash { get; set; }
public IEnumerable<KeyValuePair<long, long>> AllAccessHashesFor<T>() where T : IObject => _accessHashes.GetValueOrDefault(typeof(T));
private readonly Dictionary<Type, Dictionary<long, long>> _accessHashes = new();
private static readonly FieldInfo userFlagsField = typeof(User).GetField("flags");
private static readonly FieldInfo channelFlagsField = typeof(Channel).GetField("flags");
/// <summary>Retrieve the access_hash associated with this id (for a TL class) if it was collected</summary>
/// <remarks>This requires <see cref="CollectAccessHash"/> to be set to <see langword="true"/> first.
/// <para>See <see href="https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_CollectAccessHash.cs?ts=4#L22">Examples/Program_CollectAccessHash.cs</see> for how to use this</para></remarks>
/// <typeparam name="T">a TL object class. For example User, Channel or Photo</typeparam>
public long GetAccessHashFor<T>(long id) where T : IObject
{
if (!CollectAccessHash) Helpers.Log(4, "GetAccessHashFor doesn't do what you think. See https://github.com/wiz0u/WTelegramClient/blob/master/FAQ.md#access-hash");
lock (_accessHashes)
return _accessHashes.GetOrCreate(typeof(T)).TryGetValue(id, out var access_hash) ? access_hash : 0;
}
public void SetAccessHashFor<T>(long id, long access_hash) where T : IObject
{
lock (_accessHashes)
_accessHashes.GetOrCreate(typeof(T))[id] = access_hash;
}
internal void CollectField(FieldInfo fieldInfo, object obj, object access_hash)
{
if (fieldInfo.Name != "access_hash") return;
if (access_hash is not long accessHash) return;
var type = fieldInfo.ReflectedType;
if ((type == typeof(User) && ((User.Flags)userFlagsField.GetValue(obj)).HasFlag(User.Flags.min)) ||
(type == typeof(Channel) && ((Channel.Flags)channelFlagsField.GetValue(obj)).HasFlag(Channel.Flags.min)))
return; // access_hash from Min constructors are mostly useless. see https://core.telegram.org/api/min
if (type.GetField("id") is not FieldInfo idField) return;
if (idField.GetValue(obj) is not long id)
if (idField.GetValue(obj) is not int idInt) return;
else id = idInt;
lock (_accessHashes)
_accessHashes.GetOrCreate(type)[id] = accessHash;
}
#pragma warning restore CS0618 // Type or member is obsolete
#endregion
#region Client TL Helpers
/// <summary>Used to indicate progression of file download/upload</summary>
/// <param name="transmitted">transmitted bytes</param>

View file

@ -384,7 +384,7 @@ namespace WTelegram
throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}");
if (authKeyId == 0) // Unencrypted message
{
using var reader = new TL.BinaryReader(new MemoryStream(data, 8, dataLen - 8), this);
using var reader = new BinaryReader(new MemoryStream(data, 8, dataLen - 8));
long msgId = _lastRecvMsgId = reader.ReadInt64();
if ((msgId & 1) == 0) throw new ApplicationException($"Invalid server msgId {msgId}");
int length = reader.ReadInt32();
@ -407,7 +407,7 @@ namespace WTelegram
if (!data.AsSpan(8, 16).SequenceEqual(_sha256Recv.Hash.AsSpan(8, 16)))
throw new ApplicationException("Mismatch between MsgKey & decrypted SHA256");
_sha256Recv.Initialize();
using var reader = new TL.BinaryReader(new MemoryStream(decrypted_data), this);
using var reader = new BinaryReader(new MemoryStream(decrypted_data));
var serverSalt = reader.ReadInt64(); // int64 salt
var sessionId = reader.ReadInt64(); // int64 session_id
var msgId = reader.ReadInt64(); // int64 message_id
@ -470,7 +470,7 @@ namespace WTelegram
};
}
internal MsgContainer ReadMsgContainer(TL.BinaryReader reader)
internal MsgContainer ReadMsgContainer(BinaryReader reader)
{
int count = reader.ReadInt32();
var array = new _Message[count];
@ -502,7 +502,7 @@ namespace WTelegram
return new MsgContainer { messages = array };
}
private RpcResult ReadRpcResult(TL.BinaryReader reader)
private RpcResult ReadRpcResult(BinaryReader reader)
{
long msgId = reader.ReadInt64();
var rpc = PullPendingRequest(msgId);
@ -519,7 +519,7 @@ namespace WTelegram
if (peek == Layer.RpcErrorCtor)
result = reader.ReadTLObject(Layer.RpcErrorCtor);
else if (peek == Layer.GZipedCtor)
using (var gzipReader = new TL.BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress), reader.Client))
using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress)))
result = gzipReader.ReadTLValue(rpc.type);
else
{

View file

@ -97,7 +97,7 @@ namespace WTelegram
var (tmp_aes_key, tmp_aes_iv) = ConstructTmpAESKeyIV(resPQ.server_nonce, pqInnerData.new_nonce);
var answer = AES_IGE_EncryptDecrypt(serverDHparamsOk.encrypted_answer, tmp_aes_key, tmp_aes_iv, false);
using var answerReader = new TL.BinaryReader(new MemoryStream(answer), client);
using var answerReader = new BinaryReader(new MemoryStream(answer));
var answerHash = answerReader.ReadBytes(20);
var answerObj = answerReader.ReadTLObject();
if (answerObj is not ServerDHInnerData serverDHinnerData) throw new ApplicationException("not server_DH_inner_data");

View file

@ -94,7 +94,7 @@ namespace WTelegram
}
public void Load(Stream input)
{
using var reader = new TL.BinaryReader(input, null, true);
using var reader = new BinaryReader(input, Encoding.UTF8, true);
if (reader.ReadInt32() != 0) throw new ApplicationException("Unrecognized Secrets format");
dh = (Messages_DhConfig)reader.ReadTLObject();
if (dh?.p != null) dh_prime = BigEndianInteger(dh.p);
@ -359,7 +359,7 @@ namespace WTelegram
}
if (!success) throw new ApplicationException("Could not decrypt message");
if (length % 4 != 0) throw new ApplicationException($"Invalid message_data_length: {length}");
using var reader = new TL.BinaryReader(new MemoryStream(decrypted_data, 4, length), null);
using var reader = new BinaryReader(new MemoryStream(decrypted_data, 4, length));
return reader.ReadTLObject();
}

View file

@ -37,21 +37,21 @@ namespace TL
public static void CollectUsersChats(this IPeerResolver structure, Dictionary<long, User> users, Dictionary<long, ChatBase> chats)
=> structure.UserOrChat(new CollectorPeer { _users = users, _chats = chats });
public static Task<Messages_Chats> Messages_GetChats(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats");
public static Task<Messages_Chats> Channels_GetChannels(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats");
public static Task<UserBase[]> Users_GetUsers(this WTelegram.Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllDialogs");
public static Task<Messages_MessagesBase> Messages_GetMessages(this WTelegram.Client _) => throw new ApplicationException("If you want to get the messages from a chat, use Messages_GetHistory");
public static Task<Messages_Chats> Messages_GetChats(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats");
public static Task<Messages_Chats> Channels_GetChannels(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllChats");
public static Task<UserBase[]> Users_GetUsers(this Client _) => throw new ApplicationException("The method you're looking for is Messages_GetAllDialogs");
public static Task<Messages_MessagesBase> Messages_GetMessages(this Client _) => throw new ApplicationException("If you want to get the messages from a chat, use Messages_GetHistory");
}
public static class Markdown
{
/// <summary>Converts a <a href="https://core.telegram.org/bots/api/#markdownv2-style">Markdown text</a> into the (plain text + entities) format used by Telegram messages</summary>
/// <param name="client">Client, used for getting access_hash for <c>tg://user?id=</c> URLs</param>
/// <param name="_">not used anymore, you can pass null</param>
/// <param name="text">[in] The Markdown text<br/>[out] The same (plain) text, stripped of all Markdown notation</param>
/// <param name="premium">Generate premium entities if any</param>
/// <param name="users">Dictionary used for <c>tg://user?id=</c> notation</param>
/// <returns>The array of formatting entities that you can pass (along with the plain text) to <see cref="WTelegram.Client.SendMessageAsync">SendMessageAsync</see> or <see cref="WTelegram.Client.SendMediaAsync">SendMediaAsync</see></returns>
public static MessageEntity[] MarkdownToEntities(this WTelegram.Client client, ref string text, bool premium = false, Dictionary<long, User> users = null)
/// <returns>The array of formatting entities that you can pass (along with the plain text) to <see cref="Client.SendMessageAsync">SendMessageAsync</see> or <see cref="Client.SendMediaAsync">SendMediaAsync</see></returns>
public static MessageEntity[] MarkdownToEntities(this Client _, ref string text, bool premium = false, Dictionary<long, User> users = null)
{
var entities = new List<MessageEntity>();
var sb = new StringBuilder(text);
@ -121,7 +121,7 @@ namespace TL
else if (c == ')') break;
}
textUrl.url = sb.ToString(offset + 2, offset2 - offset - 3);
if (textUrl.url.StartsWith("tg://user?id=") && long.TryParse(textUrl.url[13..], out var id) && (users?.GetValueOrDefault(id)?.access_hash ?? client.GetAccessHashFor<User>(id)) is long hash)
if (textUrl.url.StartsWith("tg://user?id=") && long.TryParse(textUrl.url[13..], out var id) && users?.GetValueOrDefault(id)?.access_hash is long hash)
entities[lastIndex] = new InputMessageEntityMentionName { offset = textUrl.offset, length = textUrl.length, user_id = new InputUser(id, hash) };
else if ((textUrl.url.StartsWith("tg://emoji?id=") || textUrl.url.StartsWith("emoji?id=")) && long.TryParse(textUrl.url[(textUrl.url.IndexOf('=') + 1)..], out id))
if (premium) entities[lastIndex] = new MessageEntityCustomEmoji { offset = textUrl.offset, length = textUrl.length, document_id = id };
@ -154,7 +154,7 @@ namespace TL
/// <param name="entities">The array of formatting entities, typically obtained from <see cref="Message.entities"/></param>
/// <param name="premium">Convert premium entities (might lead to non-standard markdown)</param>
/// <returns>The message text with MarkdownV2 formattings</returns>
public static string EntitiesToMarkdown(this WTelegram.Client client, string message, MessageEntity[] entities, bool premium = false)
public static string EntitiesToMarkdown(this Client client, string message, MessageEntity[] entities, bool premium = false)
{
if (entities == null || entities.Length == 0) return Escape(message);
var closings = new List<(int offset, string md)>();
@ -246,12 +246,12 @@ namespace TL
public static class HtmlText
{
/// <summary>Converts an <a href="https://core.telegram.org/bots/api/#html-style">HTML-formatted text</a> into the (plain text + entities) format used by Telegram messages</summary>
/// <param name="client">Client, used for getting access_hash for <c>tg://user?id=</c> URLs</param>
/// <param name="_">not used anymore, you can pass null</param>
/// <param name="text">[in] The HTML-formatted text<br/>[out] The same (plain) text, stripped of all HTML tags</param>
/// <param name="premium">Generate premium entities if any</param>
/// <param name="users">Dictionary used for <c>tg://user?id=</c> notation</param>
/// <returns>The array of formatting entities that you can pass (along with the plain text) to <see cref="WTelegram.Client.SendMessageAsync">SendMessageAsync</see> or <see cref="WTelegram.Client.SendMediaAsync">SendMediaAsync</see></returns>
public static MessageEntity[] HtmlToEntities(this WTelegram.Client client, ref string text, bool premium = false, Dictionary<long, User> users = null)
/// <returns>The array of formatting entities that you can pass (along with the plain text) to <see cref="Client.SendMessageAsync">SendMessageAsync</see> or <see cref="Client.SendMediaAsync">SendMediaAsync</see></returns>
public static MessageEntity[] HtmlToEntities(this Client _, ref string text, bool premium = false, Dictionary<long, User> users = null)
{
var entities = new List<MessageEntity>();
var sb = new StringBuilder(text);
@ -306,7 +306,7 @@ namespace TL
else if (tag.StartsWith("a href=\"") && tag.EndsWith("\""))
{
tag = tag[8..^1];
if (tag.StartsWith("tg://user?id=") && long.TryParse(tag[13..], out var user_id) && (users?.GetValueOrDefault(user_id)?.access_hash ?? client.GetAccessHashFor<User>(user_id)) is long hash)
if (tag.StartsWith("tg://user?id=") && long.TryParse(tag[13..], out var user_id) && users?.GetValueOrDefault(user_id)?.access_hash is long hash)
entities.Add(new InputMessageEntityMentionName { offset = offset, length = -1, user_id = new InputUser(user_id, hash) });
else
entities.Add(new MessageEntityTextUrl { offset = offset, length = -1, url = tag });
@ -342,7 +342,7 @@ namespace TL
/// <param name="entities">The array of formatting entities, typically obtained from <see cref="Message.entities"/></param>
/// <param name="premium">Convert premium entities</param>
/// <returns>The message text with HTML formatting tags</returns>
public static string EntitiesToHtml(this WTelegram.Client client, string message, MessageEntity[] entities, bool premium = false)
public static string EntitiesToHtml(this Client client, string message, MessageEntity[] entities, bool premium = false)
{
if (entities == null || entities.Length == 0) return Escape(message);
var closings = new List<(int offset, string tag)>();

View file

@ -42,12 +42,6 @@ namespace TL
public Exception Exception;
}
internal class BinaryReader : System.IO.BinaryReader
{
public readonly WTelegram.Client Client;
public BinaryReader(Stream stream, WTelegram.Client client, bool leaveOpen = false) : base(stream, Encoding.UTF8, leaveOpen) => Client = client;
}
internal static class Serialization
{
internal static void WriteTLObject<T>(this BinaryWriter writer, T obj) where T : IObject
@ -76,7 +70,7 @@ namespace TL
{
if (ctorNb == 0) ctorNb = reader.ReadUInt32();
if (ctorNb == Layer.GZipedCtor)
using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress), reader.Client))
using (var gzipReader = new BinaryReader(new GZipStream(new MemoryStream(reader.ReadTLBytes()), CompressionMode.Decompress)))
return ReadTLObject(gzipReader);
if (!Layer.Table.TryGetValue(ctorNb, out var type))
throw new ApplicationException($"Cannot find type for ctor #{ctorNb:x}");
@ -95,9 +89,6 @@ namespace TL
if (field.FieldType.IsEnum)
if (field.Name == "flags") flags = (uint)value;
else if (field.Name == "flags2") flags |= (ulong)(uint)value << 32;
#pragma warning disable CS0618 // Type or member is obsolete
if (reader.Client?.CollectAccessHash == true) reader.Client.CollectField(field, obj, value);
#pragma warning restore CS0618 // Type or member is obsolete
}
return (IObject)obj;
}