Improved GetMessageByLink (topics, cache)

This commit is contained in:
Wizou 2024-02-25 03:09:49 +01:00
parent b9aad47c8e
commit 33f239fc8e
6 changed files with 36 additions and 20 deletions

View file

@ -238,6 +238,7 @@ var inputMedias = new List<InputMedia>
photoFromTelegram, // PhotoBase has implicit conversion to InputMediaPhoto
new InputMediaUploadedPhoto { file = uploadedFile },
new InputMediaPhotoExternal { url = photoUrl },
//or Document, InputMediaDocument, InputMediaUploadedDocument, InputMediaDocumentExternal...
};
await client.SendAlbumAsync(InputPeer.Self, inputMedias, "My first album");
```

View file

@ -769,7 +769,7 @@ namespace WTelegram
}
/// <summary>Return chat and message details based on a Message Link (URL)</summary>
/// <param name="url">Message Link, like https://t.me/c/1234567890/1234 or https://t.me/channelname/1234</param>
/// <param name="url">Message Link, like https://t.me/c/1234567890/1234 or t.me/channelname/1234</param>
/// <param name="chats">previously collected chats, to prevent unnecessary ResolveUsername</param>
/// <returns>Structure containing the message, chat and user details</returns>
/// <remarks>If link is for private group (<c>t.me/c/..</c>), user must have joined that group</remarks>
@ -778,17 +778,28 @@ namespace WTelegram
int start = url.IndexOf("//");
start = url.IndexOf('/', start + 2) + 1;
int slash = url.IndexOf('/', start + 2);
if (start == 0 || slash == -1) throw new ArgumentException("Invalid URL");
int end = url.IndexOfAny(UrlSeparator, slash + 1);
int msgStart = slash + 1;
int end = url.IndexOfAny(UrlSeparator, msgStart);
if (end == -1) end = url.Length;
int msgId = int.Parse(url[(slash + 1)..end]);
else if (url[end] == '/' && char.IsDigit(url[msgStart]) && url.Length > end + 1 && char.IsDigit(url[end + 1]))
{
end = url.IndexOfAny(UrlSeparator, msgStart = end + 1);
if (end == -1) end = url.Length;
}
if (start == 0 || slash == -1 || end <= slash + 1 || !char.IsDigit(url[msgStart])) throw new ArgumentException("Invalid URL");
int msgId = int.Parse(url[msgStart..end]);
ChatBase chat;
if (url[start] is 'c' or 'C' && url[start + 1] == '/')
{
long chatId = long.Parse(url[(start + 2)..slash]);
if (chats?.TryGetValue(chatId, out chat) != true)
{
var mc = await this.Channels_GetChannels(new InputChannel(chatId, 0));
if (!mc.chats.TryGetValue(chatId, out chat))
throw new WTException($"Channel {chatId} not found");
else if (chats != null)
chats[chatId] = chat;
}
}
else
chat = await CachedOrResolveUsername(url[start..slash], chats);

View file

@ -522,7 +522,7 @@ namespace WTelegram
for (int i = 0; i < count; i++)
{
var msg = array[i] = new _Message(reader.ReadInt64(), reader.ReadInt32(), null) { bytes = reader.ReadInt32() };
if ((msg.seqno & 1) != 0) lock (_msgsToAck) _msgsToAck.Add(msg.msg_id);
if ((msg.seq_no & 1) != 0) lock (_msgsToAck) _msgsToAck.Add(msg.msg_id);
var pos = reader.BaseStream.Position;
try
{
@ -535,7 +535,7 @@ namespace WTelegram
else
{
var obj = msg.body = reader.ReadTLObject(ctorNb);
Helpers.Log(1, $" → {obj.GetType().Name,-38} {MsgIdToStamp(msg.msg_id):u} {((msg.seqno & 1) != 0 ? "" : "(svc)")} {((msg.msg_id & 2) == 0 ? "" : "NAR")}");
Helpers.Log(1, $" → {obj.GetType().Name,-38} {MsgIdToStamp(msg.msg_id):u} {((msg.seq_no & 1) != 0 ? "" : "(svc)")} {((msg.msg_id & 2) == 0 ? "" : "NAR")}");
}
}
catch (Exception ex)

View file

@ -7,7 +7,7 @@ using System.Net;
using System.Security.Cryptography;
using System.Text.Json;
//( Don't change this code to lower the security. That's contrary to Telegram recommended practices. Read the official API documentation.
// Don't change this code to lower the security. It's following Telegram security recommendations https://corefork.telegram.org/mtproto/description
namespace WTelegram
{
@ -81,7 +81,7 @@ namespace WTelegram
public DateTime SessionStart => _sessionStart;
private readonly DateTime _sessionStart = DateTime.UtcNow;
private readonly SHA256 _sha256 = SHA256.Create(); // put
private readonly SHA256 _sha256 = SHA256.Create();
private Stream _store;
private byte[] _reuseKey; // used only if AES Encryptor.CanReuseTransform = false (Mono)
private byte[] _encrypted = new byte[16];
@ -95,7 +95,7 @@ namespace WTelegram
_store.Dispose();
_encryptor.Dispose();
_jsonWriter.Dispose();
_jsonStream.Dispose(); // this
_jsonStream.Dispose();
}
internal static Session LoadOrCreate(Stream store, byte[] rgbKey)
@ -107,7 +107,7 @@ namespace WTelegram
var length = (int)store.Length;
if (length > 0)
{
var input = new byte[length]; // code
var input = new byte[length];
if (store.Read(input, 0, length) != length)
throw new WTException($"Can't read session block ({store.Position}, {length})");
using var sha256 = SHA256.Create();
@ -141,7 +141,7 @@ namespace WTelegram
int encryptedLen = 64 + (utf8JsonLen & ~15);
lock (_store) // while updating _encrypted buffer and writing to store
{
if (encryptedLen > _encrypted.Length) // back
if (encryptedLen > _encrypted.Length)
Array.Copy(_encrypted, _encrypted = new byte[encryptedLen + 256], 16);
_encryptor.TransformBlock(_sha256.ComputeHash(utf8Json, 0, utf8JsonLen), 0, 32, _encrypted, 16);
_encryptor.TransformBlock(utf8Json, 0, encryptedLen - 64, _encrypted, 48);
@ -192,7 +192,6 @@ namespace WTelegram
}
}
// QWxp couldn't be bothered to write such a simple SessionStore, so here it is:
internal class ActionStore : MemoryStream
{
private readonly Action<byte[]> _save;

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -39,9 +40,13 @@ namespace TL
public static void CollectUsersChats(this IPeerResolver structure, IDictionary<long, User> users, IDictionary<long, ChatBase> chats)
=> structure.UserOrChat(new CollectorPeer { _users = users, _chats = chats });
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task<Messages_Chats> Messages_GetChats(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllChats");
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task<Messages_Chats> Channels_GetChannels(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllChats");
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task<UserBase[]> Users_GetUsers(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllDialogs");
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task<Messages_MessagesBase> Messages_GetMessages(this Client _) => throw new WTException("If you want to get all messages from a chat, use method Messages_GetHistory");
}

View file

@ -198,10 +198,10 @@ namespace TL
foreach (var msg in messages)
{
writer.Write(msg.msg_id);
writer.Write(msg.seqno);
writer.Write(msg.seq_no);
var patchPos = writer.BaseStream.Position;
writer.Write(0); // patched below
if ((msg.seqno & 1) != 0)
if ((msg.seq_no & 1) != 0)
WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38} #{(short)msg.msg_id.GetHashCode():X4}");
else
WTelegram.Helpers.Log(1, $" → {msg.body.GetType().Name.TrimEnd('_'),-38}");
@ -372,11 +372,11 @@ namespace TL
}
[TLDef(0x5BB8E511)] //message#5bb8e511 msg_id:long seqno:int bytes:int body:Object = Message
public class _Message
public class _Message : IObject
{
public _Message(long msgId, int seqNo, IObject obj) { msg_id = msgId; seqno = seqNo; body = obj; }
public _Message(long msgId, int seqNo, IObject obj) { msg_id = msgId; seq_no = seqNo; body = obj; }
public long msg_id;
public int seqno;
public int seq_no;
public int bytes;
public IObject body;
}