mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Now throwing WTException. Class hierarchy is TL.RpcException : WTelegram.WTException : ApplicationException
This commit is contained in:
parent
621a88bb9f
commit
9af6404eff
2
.github/dev.yml
vendored
2
.github/dev.yml
vendored
|
|
@ -2,7 +2,7 @@ pr: none
|
|||
trigger:
|
||||
- master
|
||||
|
||||
name: 3.3.4-dev.$(Rev:r)
|
||||
name: 3.4.1-dev.$(Rev:r)
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
|
|
|
|||
2
.github/release.yml
vendored
2
.github/release.yml
vendored
|
|
@ -1,7 +1,7 @@
|
|||
pr: none
|
||||
trigger: none
|
||||
|
||||
name: 3.3.$(Rev:r)
|
||||
name: 3.4.$(Rev:r)
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace WTelegram
|
|||
lock (tasks) tasks[file_part] = task;
|
||||
if (!isBig)
|
||||
md5.TransformBlock(bytes, 0, read, null, 0);
|
||||
if (read < FilePartSize && bytesLeft != 0) throw new ApplicationException($"Failed to fully read stream ({read},{bytesLeft})");
|
||||
if (read < FilePartSize && bytesLeft != 0) throw new WTException($"Failed to fully read stream ({read},{bytesLeft})");
|
||||
|
||||
async Task SavePart(int file_part, byte[] bytes)
|
||||
{
|
||||
|
|
@ -331,7 +331,7 @@ namespace WTelegram
|
|||
if (fileSize != 0 && fileOffset >= fileSize)
|
||||
{
|
||||
if (await task != ((fileSize - 1) % FilePartSize) + 1)
|
||||
throw new ApplicationException("Downloaded file size does not match expected file size");
|
||||
throw new WTException("Downloaded file size does not match expected file size");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ namespace WTelegram
|
|||
_parallelTransfers.Release();
|
||||
}
|
||||
if (fileBase is not Upload_File fileData)
|
||||
throw new ApplicationException("Upload_GetFile returned unsupported " + fileBase?.GetType().Name);
|
||||
throw new WTException("Upload_GetFile returned unsupported " + fileBase?.GetType().Name);
|
||||
if (fileData.bytes.Length != FilePartSize) abort = true;
|
||||
if (fileData.bytes.Length != 0)
|
||||
{
|
||||
|
|
@ -480,7 +480,7 @@ namespace WTelegram
|
|||
mds.messages = messageList.ToArray();
|
||||
return mds;
|
||||
case Messages_Dialogs md: return md;
|
||||
default: throw new ApplicationException("Messages_GetDialogs returned unexpected " + dialogs?.GetType().Name);
|
||||
default: throw new WTException("Messages_GetDialogs returned unexpected " + dialogs?.GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -762,13 +762,13 @@ namespace WTelegram
|
|||
long chatId = long.Parse(url[(start + 2)..slash]);
|
||||
var chats = await this.Channels_GetChannels(new InputChannel(chatId, 0));
|
||||
if (!chats.chats.TryGetValue(chatId, out chat))
|
||||
throw new ApplicationException($"Channel {chatId} not found");
|
||||
throw new WTException($"Channel {chatId} not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
var resolved = await this.Contacts_ResolveUsername(url[start..slash]);
|
||||
chat = resolved.Chat;
|
||||
if (chat is null) throw new ApplicationException($"@{url[start..slash]} is not a Chat/Channel");
|
||||
if (chat is null) throw new WTException($"@{url[start..slash]} is not a Chat/Channel");
|
||||
}
|
||||
int msgId = int.Parse(url[(slash + 1)..end]);
|
||||
return await this.Channels_GetMessages((Channel)chat, msgId) as Messages_ChannelMessages;
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace WTelegram
|
|||
|
||||
internal Task<string> ConfigAsync(string what) => Task.Run(() => Config(what));
|
||||
internal string Config(string what)
|
||||
=> _config(what) ?? DefaultConfig(what) ?? throw new ApplicationException("You must provide a config value for " + what);
|
||||
=> _config(what) ?? DefaultConfig(what) ?? throw new WTException("You must provide a config value for " + what);
|
||||
|
||||
/// <summary>Default config values, used if your Config callback returns <see langword="null"/></summary>
|
||||
public static string DefaultConfig(string what) => what switch
|
||||
|
|
@ -232,7 +232,7 @@ namespace WTelegram
|
|||
if ((dcSession?.AuthKeyID ?? 0) == 0) // we will need to negociate an AuthKey => can't use media_only DC
|
||||
flags &= ~DcOption.Flags.media_only;
|
||||
var dcOptions = _session.DcOptions.Where(dc => dc.id == dcId).OrderBy(dc => dc.flags ^ flags);
|
||||
var dcOption = dcOptions.FirstOrDefault() ?? throw new ApplicationException($"Could not find adequate dc_option for DC {dcId}");
|
||||
var dcOption = dcOptions.FirstOrDefault() ?? throw new WTException($"Could not find adequate dc_option for DC {dcId}");
|
||||
dcSession ??= new Session.DCSession { Id = Helpers.RandomLong() }; // create new session only if not already existing
|
||||
dcSession.DataCenter = dcOption;
|
||||
return _session.DCSessions[dcId] = dcSession;
|
||||
|
|
@ -267,7 +267,7 @@ namespace WTelegram
|
|||
{
|
||||
var authorization = await altSession.Client.Auth_ImportAuthorization(exported.id, exported.bytes);
|
||||
if (authorization is not Auth_Authorization { user: User user })
|
||||
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
|
||||
throw new WTException("Failed to get Authorization: " + authorization.GetType().Name);
|
||||
altSession.UserId = user.id;
|
||||
}
|
||||
}
|
||||
|
|
@ -289,19 +289,19 @@ namespace WTelegram
|
|||
try
|
||||
{
|
||||
if (await stream.FullReadAsync(data, 4, cts.Token) != 4)
|
||||
throw new ApplicationException(ConnectionShutDown);
|
||||
throw new WTException(ConnectionShutDown);
|
||||
#if OBFUSCATION
|
||||
_recvCtr.EncryptDecrypt(data, 4);
|
||||
#endif
|
||||
int payloadLen = BinaryPrimitives.ReadInt32LittleEndian(data);
|
||||
if (payloadLen <= 0)
|
||||
throw new ApplicationException("Could not read frame data : Invalid payload length");
|
||||
throw new WTException("Could not read frame data : Invalid payload length");
|
||||
else if (payloadLen > data.Length)
|
||||
data = new byte[payloadLen];
|
||||
else if (Math.Max(payloadLen, MinBufferSize) < data.Length / 4)
|
||||
data = new byte[Math.Max(payloadLen, MinBufferSize)];
|
||||
if (await stream.FullReadAsync(data, payloadLen, cts.Token) != payloadLen)
|
||||
throw new ApplicationException("Could not read frame data : Connection shut down");
|
||||
throw new WTException("Could not read frame data : Connection shut down");
|
||||
#if OBFUSCATION
|
||||
_recvCtr.EncryptDecrypt(data, payloadLen);
|
||||
#endif
|
||||
|
|
@ -310,7 +310,7 @@ namespace WTelegram
|
|||
catch (Exception ex) // an exception in RecvAsync is always fatal
|
||||
{
|
||||
if (cts.IsCancellationRequested) return;
|
||||
bool disconnectedAltDC = !IsMainDC && ex is ApplicationException { Message: ConnectionShutDown } or IOException { InnerException: SocketException };
|
||||
bool disconnectedAltDC = !IsMainDC && ex is WTException { Message: ConnectionShutDown } or IOException { InnerException: SocketException };
|
||||
if (disconnectedAltDC)
|
||||
Helpers.Log(3, $"{_dcSession.DcID}>Alt DC disconnected: {ex.Message}");
|
||||
else
|
||||
|
|
@ -378,35 +378,35 @@ namespace WTelegram
|
|||
throw new RpcException(error_code, TransportError(error_code));
|
||||
}
|
||||
if (dataLen < 24) // authKeyId+msgId+length+ctorNb | authKeyId+msgKey
|
||||
throw new ApplicationException($"Packet payload too small: {dataLen}");
|
||||
throw new WTException($"Packet payload too small: {dataLen}");
|
||||
|
||||
long authKeyId = BinaryPrimitives.ReadInt64LittleEndian(data);
|
||||
if (authKeyId != _dcSession.AuthKeyID)
|
||||
throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}");
|
||||
throw new WTException($"Received a packet encrypted with unexpected key {authKeyId:X}");
|
||||
if (authKeyId == 0) // Unencrypted message
|
||||
{
|
||||
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}");
|
||||
if ((msgId & 1) == 0) throw new WTException($"Invalid server msgId {msgId}");
|
||||
int length = reader.ReadInt32();
|
||||
dataLen -= 20;
|
||||
if (length > dataLen || length < dataLen - (_paddedMode ? 15 : 0))
|
||||
throw new ApplicationException($"Unexpected unencrypted/padding length {dataLen} - {length}");
|
||||
throw new WTException($"Unexpected unencrypted/padding length {dataLen} - {length}");
|
||||
|
||||
var obj = reader.ReadTLObject();
|
||||
Helpers.Log(1, $"{_dcSession.DcID}>Receiving {obj.GetType().Name,-40} {MsgIdToStamp(msgId):u} clear{((msgId & 2) == 0 ? "" : " NAR")}");
|
||||
if (_bareRpc == null) throw new ApplicationException("Shouldn't receive unencrypted packet at this point");
|
||||
if (_bareRpc == null) throw new WTException("Shouldn't receive unencrypted packet at this point");
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] decrypted_data = EncryptDecryptMessage(data.AsSpan(24, (dataLen - 24) & ~0xF), false, 8, _dcSession.AuthKey, data, 8, _sha256Recv);
|
||||
if (decrypted_data.Length < 36) // header below+ctorNb
|
||||
throw new ApplicationException($"Decrypted packet too small: {decrypted_data.Length}");
|
||||
throw new WTException($"Decrypted packet too small: {decrypted_data.Length}");
|
||||
_sha256Recv.TransformBlock(_dcSession.AuthKey, 96, 32, null, 0);
|
||||
_sha256Recv.TransformFinalBlock(decrypted_data, 0, decrypted_data.Length);
|
||||
if (!data.AsSpan(8, 16).SequenceEqual(_sha256Recv.Hash.AsSpan(8, 16)))
|
||||
throw new ApplicationException("Mismatch between MsgKey & decrypted SHA256");
|
||||
throw new WTException("Mismatch between MsgKey & decrypted SHA256");
|
||||
_sha256Recv.Initialize();
|
||||
using var reader = new BinaryReader(new MemoryStream(decrypted_data));
|
||||
var serverSalt = reader.ReadInt64(); // int64 salt
|
||||
|
|
@ -415,10 +415,10 @@ namespace WTelegram
|
|||
var seqno = reader.ReadInt32(); // int32 msg_seqno
|
||||
var length = reader.ReadInt32(); // int32 message_data_length
|
||||
|
||||
if (length < 0 || length % 4 != 0) throw new ApplicationException($"Invalid message_data_length: {length}");
|
||||
if (decrypted_data.Length - 32 - length is < 12 or > 1024) throw new ApplicationException($"Invalid message padding length: {decrypted_data.Length - 32}-{length}");
|
||||
if (sessionId != _dcSession.Id) throw new ApplicationException($"Unexpected session ID: {sessionId} != {_dcSession.Id}");
|
||||
if ((msgId & 1) == 0) throw new ApplicationException($"msg_id is not odd: {msgId}");
|
||||
if (length < 0 || length % 4 != 0) throw new WTException($"Invalid message_data_length: {length}");
|
||||
if (decrypted_data.Length - 32 - length is < 12 or > 1024) throw new WTException($"Invalid message padding length: {decrypted_data.Length - 32}-{length}");
|
||||
if (sessionId != _dcSession.Id) throw new WTException($"Unexpected session ID: {sessionId} != {_dcSession.Id}");
|
||||
if ((msgId & 1) == 0) throw new WTException($"msg_id is not odd: {msgId}");
|
||||
if (!_dcSession.CheckNewMsgId(msgId))
|
||||
{
|
||||
Helpers.Log(3, $"{_dcSession.DcID}>Ignoring duplicate or old msg_id {msgId}");
|
||||
|
|
@ -434,7 +434,7 @@ namespace WTelegram
|
|||
_dcSession.Salt = serverSalt;
|
||||
_saltChangeCounter += 1200; // counter is decreased by KeepAlive (we have margin of 10 min)
|
||||
if (_saltChangeCounter >= 1800)
|
||||
throw new ApplicationException("Server salt changed too often! Security issue?");
|
||||
throw new WTException("Server salt changed too often! Security issue?");
|
||||
}
|
||||
if ((seqno & 1) != 0) lock (_msgsToAck) _msgsToAck.Add(msgId);
|
||||
|
||||
|
|
@ -590,7 +590,7 @@ namespace WTelegram
|
|||
return;
|
||||
}
|
||||
else if (_dcSession.AuthKeyID == 0)
|
||||
throw new ApplicationException($"Received a {obj.GetType()} incompatible with expected bare {rpc?.type}");
|
||||
throw new WTException($"Received a {obj.GetType()} incompatible with expected bare {rpc?.type}");
|
||||
lock (_pendingRpcs)
|
||||
_pendingRpcs[_bareRpc.msgId] = _bareRpc;
|
||||
}
|
||||
|
|
@ -664,7 +664,7 @@ namespace WTelegram
|
|||
else if (PullPendingRequest(badMsgNotification.bad_msg_id) is Rpc rpc)
|
||||
{
|
||||
if (_bareRpc?.msgId == badMsgNotification.bad_msg_id) _bareRpc = null;
|
||||
rpc.tcs.SetException(new ApplicationException($"BadMsgNotification {badMsgNotification.error_code}"));
|
||||
rpc.tcs.SetException(new WTException($"BadMsgNotification {badMsgNotification.error_code}"));
|
||||
}
|
||||
else
|
||||
RaiseUpdate(obj);
|
||||
|
|
@ -879,7 +879,7 @@ namespace WTelegram
|
|||
/// <param name="loginInfo">First call should be with phone number<br/>Further calls should be with the requested configuration value</param>
|
||||
/// <returns>Configuration item requested to continue login, or <see langword="null"/> when login is successful<br/>
|
||||
/// Possible values: <b>verification_code</b>, <b>name</b> (signup), <b>password</b> (2FA), <b>email</b> & <b>email_verification_code</b> (email registration)</returns>
|
||||
/// <exception cref="ApplicationException"/><exception cref="RpcException"/>
|
||||
/// <exception cref="WTException"/><exception cref="RpcException"/>
|
||||
public async Task<string> Login(string loginInfo)
|
||||
{
|
||||
if (_loginCfg.request == default) RunLoginAsync(loginInfo);
|
||||
|
|
@ -997,7 +997,7 @@ namespace WTelegram
|
|||
}
|
||||
var mismatch = $"Current logged user {self.id} mismatched user_id or phone_number";
|
||||
Helpers.Log(3, mismatch);
|
||||
if (!reloginOnFailedResume) throw new ApplicationException(mismatch);
|
||||
if (!reloginOnFailedResume) throw new WTException(mismatch);
|
||||
}
|
||||
catch (RpcException ex) when (reloginOnFailedResume)
|
||||
{
|
||||
|
|
@ -1157,7 +1157,7 @@ namespace WTelegram
|
|||
public User LoginAlreadyDone(Auth_AuthorizationBase authorization)
|
||||
{
|
||||
if (authorization is not Auth_Authorization { user: User user })
|
||||
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
|
||||
throw new WTException("Failed to get Authorization: " + authorization.GetType().Name);
|
||||
_session.UserId = _dcSession.UserId = user.id;
|
||||
lock (_session) _session.Save();
|
||||
return User = user;
|
||||
|
|
@ -1190,7 +1190,7 @@ namespace WTelegram
|
|||
|
||||
private async Task SendAsync(IObject msg, bool isContent, Rpc rpc = null)
|
||||
{
|
||||
if (_reactorTask == null) throw new ApplicationException("You must connect to Telegram first");
|
||||
if (_reactorTask == null) throw new WTException("You must connect to Telegram first");
|
||||
isContent &= _dcSession.AuthKeyID != 0;
|
||||
(long msgId, int seqno) = NewMsgId(isContent);
|
||||
if (rpc != null)
|
||||
|
|
@ -1212,7 +1212,7 @@ namespace WTelegram
|
|||
|
||||
if (_dcSession.AuthKeyID == 0) // send unencrypted message
|
||||
{
|
||||
if (_bareRpc == null) throw new ApplicationException($"Shouldn't send a {msg.GetType().Name} unencrypted");
|
||||
if (_bareRpc == null) throw new WTException($"Shouldn't send a {msg.GetType().Name} unencrypted");
|
||||
writer.Write(0L); // int64 auth_key_id = 0 (Unencrypted)
|
||||
writer.Write(msgId); // int64 message_id
|
||||
writer.Write(0); // int32 message_data_length (to be patched)
|
||||
|
|
@ -1273,7 +1273,7 @@ namespace WTelegram
|
|||
|
||||
internal async Task<T> InvokeBare<T>(IMethod<T> request)
|
||||
{
|
||||
if (_bareRpc != null) throw new ApplicationException("A bare request is already undergoing");
|
||||
if (_bareRpc != null) throw new WTException("A bare request is already undergoing");
|
||||
retry:
|
||||
_bareRpc = new Rpc { type = typeof(T) };
|
||||
await SendAsync(request, false, _bareRpc);
|
||||
|
|
@ -1352,7 +1352,7 @@ namespace WTelegram
|
|||
case ReactorError:
|
||||
goto retry;
|
||||
default:
|
||||
throw new ApplicationException($"{query.GetType().Name} call got a result of type {result.GetType().Name} instead of {typeof(T).Name}");
|
||||
throw new WTException($"{query.GetType().Name} call got a result of type {result.GetType().Name} instead of {typeof(T).Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace WTelegram
|
|||
{
|
||||
AesECB.Mode = CipherMode.ECB;
|
||||
AesECB.Padding = PaddingMode.Zeros;
|
||||
if (AesECB.BlockSize != 128) throw new ApplicationException("AES Blocksize is not 16 bytes");
|
||||
if (AesECB.BlockSize != 128) throw new WTException("AES Blocksize is not 16 bytes");
|
||||
}
|
||||
|
||||
internal static async Task CreateAuthorizationKey(Client client, Session.DCSession session)
|
||||
|
|
@ -36,9 +36,9 @@ namespace WTelegram
|
|||
var nonce = new Int128(RNG);
|
||||
var resPQ = await client.ReqPqMulti(nonce);
|
||||
//2)
|
||||
if (resPQ.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (resPQ.nonce != nonce) throw new WTException("Nonce mismatch");
|
||||
var fingerprint = resPQ.server_public_key_fingerprints.FirstOrDefault(PublicKeys.ContainsKey);
|
||||
if (fingerprint == 0) throw new ApplicationException("Couldn't match any server_public_key_fingerprints");
|
||||
if (fingerprint == 0) throw new WTException("Couldn't match any server_public_key_fingerprints");
|
||||
var publicKey = PublicKeys[fingerprint];
|
||||
Helpers.Log(2, $"Selected public key with fingerprint {fingerprint:X}");
|
||||
//3)
|
||||
|
|
@ -73,7 +73,7 @@ namespace WTelegram
|
|||
clearStream.Write(aes_key, 0, 32); // write aes_key as prefix for initial Sha256 computation
|
||||
writer.WriteTLObject(pqInnerData);
|
||||
int clearLength = (int)clearStream.Position - 32; // length before padding
|
||||
if (clearLength > 144) throw new ApplicationException("PQInnerData too big");
|
||||
if (clearLength > 144) throw new WTException("PQInnerData too big");
|
||||
byte[] clearBuffer = clearStream.GetBuffer();
|
||||
RNG.GetBytes(clearBuffer, 32 + clearLength, 192 - clearLength);
|
||||
sha256.ComputeHash(clearBuffer, 0, 32 + 192).CopyTo(clearBuffer, 224); // append Sha256
|
||||
|
|
@ -91,22 +91,22 @@ namespace WTelegram
|
|||
var serverDHparams = await client.ReqDHParams(pqInnerData.nonce, pqInnerData.server_nonce, pqInnerData.p, pqInnerData.q, fingerprint, encrypted_data);
|
||||
//5)
|
||||
var localTime = DateTimeOffset.UtcNow;
|
||||
if (serverDHparams is not ServerDHParamsOk serverDHparamsOk) throw new ApplicationException("not server_DH_params_ok");
|
||||
if (serverDHparamsOk.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (serverDHparamsOk.server_nonce != resPQ.server_nonce) throw new ApplicationException("Server Nonce mismatch");
|
||||
if (serverDHparams is not ServerDHParamsOk serverDHparamsOk) throw new WTException("not server_DH_params_ok");
|
||||
if (serverDHparamsOk.nonce != nonce) throw new WTException("Nonce mismatch");
|
||||
if (serverDHparamsOk.server_nonce != resPQ.server_nonce) throw new WTException("Server Nonce mismatch");
|
||||
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 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");
|
||||
if (answerObj is not ServerDHInnerData serverDHinnerData) throw new WTException("not server_DH_inner_data");
|
||||
long padding = answerReader.BaseStream.Length - answerReader.BaseStream.Position;
|
||||
if (padding >= 16) throw new ApplicationException("Too much pad");
|
||||
if (padding >= 16) throw new WTException("Too much pad");
|
||||
if (!Enumerable.SequenceEqual(sha1.ComputeHash(answer, 20, answer.Length - (int)padding - 20), answerHash))
|
||||
throw new ApplicationException("Answer SHA1 mismatch");
|
||||
if (serverDHinnerData.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (serverDHinnerData.server_nonce != resPQ.server_nonce) throw new ApplicationException("Server Nonce mismatch");
|
||||
throw new WTException("Answer SHA1 mismatch");
|
||||
if (serverDHinnerData.nonce != nonce) throw new WTException("Nonce mismatch");
|
||||
if (serverDHinnerData.server_nonce != resPQ.server_nonce) throw new WTException("Server Nonce mismatch");
|
||||
var g_a = BigEndianInteger(serverDHinnerData.g_a);
|
||||
var dh_prime = BigEndianInteger(serverDHinnerData.dh_prime);
|
||||
CheckGoodPrime(dh_prime, serverDHinnerData.g);
|
||||
|
|
@ -149,15 +149,15 @@ namespace WTelegram
|
|||
var authKeyHash = sha1.ComputeHash(authKey);
|
||||
retry_id = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash); // (auth_key_aux_hash)
|
||||
//9)
|
||||
if (setClientDHparamsAnswer is not DhGenOk dhGenOk) throw new ApplicationException("not dh_gen_ok");
|
||||
if (dhGenOk.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (dhGenOk.server_nonce != resPQ.server_nonce) throw new ApplicationException("Server Nonce mismatch");
|
||||
if (setClientDHparamsAnswer is not DhGenOk dhGenOk) throw new WTException("not dh_gen_ok");
|
||||
if (dhGenOk.nonce != nonce) throw new WTException("Nonce mismatch");
|
||||
if (dhGenOk.server_nonce != resPQ.server_nonce) throw new WTException("Server Nonce mismatch");
|
||||
var expected_new_nonceN = new byte[32 + 1 + 8];
|
||||
pqInnerData.new_nonce.raw.CopyTo(expected_new_nonceN, 0);
|
||||
expected_new_nonceN[32] = 1;
|
||||
Array.Copy(authKeyHash, 0, expected_new_nonceN, 33, 8); // (auth_key_aux_hash)
|
||||
if (!Enumerable.SequenceEqual(dhGenOk.new_nonce_hash1.raw, sha1.ComputeHash(expected_new_nonceN).Skip(4)))
|
||||
throw new ApplicationException("setClientDHparamsAnswer.new_nonce_hashN mismatch");
|
||||
throw new WTException("setClientDHparamsAnswer.new_nonce_hashN mismatch");
|
||||
|
||||
session.AuthKeyID = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash.AsSpan(12));
|
||||
session.AuthKey = authKey;
|
||||
|
|
@ -188,7 +188,7 @@ namespace WTelegram
|
|||
{
|
||||
Helpers.Log(2, "Verifying encryption key safety... (this should happen only once per DC)");
|
||||
// check that 2^2047 <= p < 2^2048
|
||||
if (p.GetBitLength() != 2048) throw new ApplicationException("p is not 2048-bit number");
|
||||
if (p.GetBitLength() != 2048) throw new WTException("p is not 2048-bit number");
|
||||
// check that g generates a cyclic subgroup of prime order (p - 1) / 2, i.e. is a quadratic residue mod p.
|
||||
if (g switch
|
||||
{
|
||||
|
|
@ -200,11 +200,11 @@ namespace WTelegram
|
|||
7 => (int)(p % 7) is not 3 and not 5 and not 6,
|
||||
_ => true,
|
||||
})
|
||||
throw new ApplicationException("Bad prime mod 4g");
|
||||
throw new WTException("Bad prime mod 4g");
|
||||
// check whether p is a safe prime (meaning that both p and (p - 1) / 2 are prime)
|
||||
if (SafePrimes.Contains(p)) return;
|
||||
if (!p.IsProbablePrime()) throw new ApplicationException("p is not a prime number");
|
||||
if (!((p - 1) / 2).IsProbablePrime()) throw new ApplicationException("(p - 1) / 2 is not a prime number");
|
||||
if (!p.IsProbablePrime()) throw new WTException("p is not a prime number");
|
||||
if (!((p - 1) / 2).IsProbablePrime()) throw new WTException("(p - 1) / 2 is not a prime number");
|
||||
SafePrimes.Add(p);
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ namespace WTelegram
|
|||
// check that g, g_a and g_b are greater than 1 and less than dh_prime - 1.
|
||||
// We recommend checking that g_a and g_b are between 2^{2048-64} and dh_prime - 2^{2048-64} as well.
|
||||
if (g.GetBitLength() < 2048 - 64 || (dh_prime - g).GetBitLength() < 2048 - 64)
|
||||
throw new ApplicationException("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}");
|
||||
throw new WTException("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}");
|
||||
}
|
||||
|
||||
public static void LoadPublicKey(string pem)
|
||||
|
|
@ -298,7 +298,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
|
||||
internal static byte[] AES_IGE_EncryptDecrypt(Span<byte> input, byte[] aes_key, byte[] aes_iv, bool encrypt)
|
||||
{
|
||||
if (input.Length % 16 != 0) throw new ApplicationException("AES_IGE input size not divisible by 16");
|
||||
if (input.Length % 16 != 0) throw new WTException("AES_IGE input size not divisible by 16");
|
||||
|
||||
using var aesCrypto = encrypt ? AesECB.CreateEncryptor(aes_key, null) : AesECB.CreateDecryptor(aes_key, null);
|
||||
var output = new byte[input.Length];
|
||||
|
|
@ -396,7 +396,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
RNG.GetBytes(algo.salt1, salt1len, 32);
|
||||
}
|
||||
else
|
||||
throw new ApplicationException("2FA authentication uses an unsupported algo: " + accountPassword.current_algo?.GetType().Name);
|
||||
throw new WTException("2FA authentication uses an unsupported algo: " + accountPassword.current_algo?.GetType().Name);
|
||||
|
||||
var g = new BigInteger(algo.g);
|
||||
var p = BigEndianInteger(algo.p);
|
||||
|
|
|
|||
|
|
@ -253,4 +253,10 @@ namespace WTelegram
|
|||
protected override void Dispose(bool disposing) => _innerStream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public class WTException : ApplicationException
|
||||
{
|
||||
public WTException(string message) : base(message) { }
|
||||
public WTException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace WTelegram
|
|||
public void Load(Stream input)
|
||||
{
|
||||
using var reader = new BinaryReader(input, Encoding.UTF8, true);
|
||||
if (reader.ReadInt32() != 0) throw new ApplicationException("Unrecognized Secrets format");
|
||||
if (reader.ReadInt32() != 0) throw new WTException("Unrecognized Secrets format");
|
||||
dh = (Messages_DhConfig)reader.ReadTLObject();
|
||||
if (dh?.p != null) dh_prime = BigEndianInteger(dh.p);
|
||||
int count = reader.ReadInt32();
|
||||
|
|
@ -128,15 +128,15 @@ namespace WTelegram
|
|||
{
|
||||
var mdhcb = await client.Messages_GetDhConfig(dh?.version ?? 0, 256);
|
||||
if (mdhcb is Messages_DhConfigNotModified { random: var random })
|
||||
_ = dh ?? throw new ApplicationException("DhConfigNotModified on zero version");
|
||||
_ = dh ?? throw new WTException("DhConfigNotModified on zero version");
|
||||
else if (mdhcb is Messages_DhConfig dhc)
|
||||
{
|
||||
var p = BigEndianInteger(dhc.p);
|
||||
CheckGoodPrime(p, dhc.g);
|
||||
(dh, dh_prime, random, dh.random) = (dhc, p, dhc.random, null);
|
||||
}
|
||||
else throw new ApplicationException("Unexpected DHConfig response: " + mdhcb?.GetType().Name);
|
||||
if (random.Length != 256) throw new ApplicationException("Invalid DHConfig random");
|
||||
else throw new WTException("Unexpected DHConfig response: " + mdhcb?.GetType().Name);
|
||||
if (random.Length != 256) throw new WTException("Invalid DHConfig random");
|
||||
var salt = new byte[256];
|
||||
RNG.GetBytes(salt);
|
||||
for (int i = 0; i < 256; i++) salt[i] ^= random[i];
|
||||
|
|
@ -146,7 +146,7 @@ namespace WTelegram
|
|||
/// <summary>Initiate a secret chat with the given user.<br/>(chat must be acknowledged by remote user before being active)</summary>
|
||||
/// <param name="user">The remote user</param>
|
||||
/// <returns>Secret Chat ID</returns>
|
||||
/// <exception cref="ApplicationException"></exception>
|
||||
/// <exception cref="WTException"></exception>
|
||||
public async Task<int> Request(InputUserBase user)
|
||||
{
|
||||
int chat_id;
|
||||
|
|
@ -164,7 +164,7 @@ namespace WTelegram
|
|||
CheckGoodGaAndGb(g_a, dh_prime);
|
||||
var ecb = await client.Messages_RequestEncryption(user, chat_id, g_a.To256Bytes());
|
||||
if (ecb is not EncryptedChatWaiting ecw || ecw.id != chat_id || ecw.participant_id != chat.participant_id)
|
||||
throw new ApplicationException("Invalid " + ecb?.GetType().Name);
|
||||
throw new WTException("Invalid " + ecb?.GetType().Name);
|
||||
chat.peer.access_hash = ecw.access_hash;
|
||||
return chat_id;
|
||||
}
|
||||
|
|
@ -173,7 +173,7 @@ namespace WTelegram
|
|||
/// <remarks>If update.chat is <see cref="EncryptedChatRequested"/>, you might want to first make sure you want to accept this secret chat initiated by user <see cref="EncryptedChatRequested.admin_id"/></remarks>
|
||||
/// <param name="acceptChatRequests">Incoming requests for secret chats are automatically: accepted (<see langword="true"/>), rejected (<see langword="false"/>) or ignored (<see langword="null"/>)</param>
|
||||
/// <returns><see langword="true"/> if the update was handled successfully</returns>
|
||||
/// <exception cref="ApplicationException"></exception>
|
||||
/// <exception cref="WTException"></exception>
|
||||
public async Task<bool> HandleUpdate(UpdateEncryption update, bool? acceptChatRequests = true)
|
||||
{
|
||||
try
|
||||
|
|
@ -188,8 +188,8 @@ namespace WTelegram
|
|||
var gab = BigInteger.ModPow(g_b, a, dh_prime);
|
||||
chat.flags &= ~SecretChat.Flags.requestChat;
|
||||
SetAuthKey(chat, gab.To256Bytes());
|
||||
if (ec.key_fingerprint != chat.key_fingerprint) throw new ApplicationException("Invalid fingerprint on accepted secret chat");
|
||||
if (ec.access_hash != chat.peer.access_hash || ec.participant_id != chat.participant_id) throw new ApplicationException("Invalid peer on accepted secret chat");
|
||||
if (ec.key_fingerprint != chat.key_fingerprint) throw new WTException("Invalid fingerprint on accepted secret chat");
|
||||
if (ec.access_hash != chat.peer.access_hash || ec.participant_id != chat.participant_id) throw new WTException("Invalid peer on accepted secret chat");
|
||||
await SendNotifyLayer(chat);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -227,7 +227,7 @@ namespace WTelegram
|
|||
var ecb = await client.Messages_AcceptEncryption(chat.peer, g_b.ToByteArray(true, true), chat.key_fingerprint);
|
||||
if (ecb is not EncryptedChat ec || ec.id != ecr.id || ec.access_hash != ecr.access_hash ||
|
||||
ec.admin_id != ecr.admin_id || ec.key_fingerprint != chat.key_fingerprint)
|
||||
throw new ApplicationException("Inconsistent accepted secret chat");
|
||||
throw new WTException("Inconsistent accepted secret chat");
|
||||
await SendNotifyLayer(chat);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -274,7 +274,7 @@ namespace WTelegram
|
|||
/// <returns>Confirmation of sent message</returns>
|
||||
public async Task<Messages_SentEncryptedMessage> SendMessage(int chatId, DecryptedMessageBase msg, bool silent = false, InputEncryptedFileBase file = null)
|
||||
{
|
||||
if (!chats.TryGetValue(chatId, out var chat)) throw new ApplicationException("Secret chat not found");
|
||||
if (!chats.TryGetValue(chatId, out var chat)) throw new WTException("Secret chat not found");
|
||||
try
|
||||
{
|
||||
var dml = new TL.Layer23.DecryptedMessageLayer
|
||||
|
|
@ -336,14 +336,14 @@ namespace WTelegram
|
|||
private IObject Decrypt(SecretChat chat, byte[] data, int dataLen)
|
||||
{
|
||||
if (dataLen < 32) // authKeyId+msgKey+(length+ctorNb)
|
||||
throw new ApplicationException($"Encrypted packet too small: {data.Length}");
|
||||
throw new WTException($"Encrypted packet too small: {data.Length}");
|
||||
var authKey = chat.authKey;
|
||||
long authKeyId = BinaryPrimitives.ReadInt64LittleEndian(data);
|
||||
if (authKeyId == chat.key_fingerprint)
|
||||
if (!chat.flags.HasFlag(SecretChat.Flags.commitKey)) CheckPFS(chat);
|
||||
else { chat.flags &= ~SecretChat.Flags.commitKey; Array.Clear(chat.salt, 0, chat.salt.Length); }
|
||||
else if (chat.flags.HasFlag(SecretChat.Flags.commitKey) && authKeyId == BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12))) authKey = chat.salt;
|
||||
else throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}");
|
||||
else throw new WTException($"Received a packet encrypted with unexpected key {authKeyId:X}");
|
||||
int x = (int)(chat.flags & SecretChat.Flags.originator);
|
||||
byte[] decrypted_data = EncryptDecryptMessage(data.AsSpan(24, dataLen - 24), false, x, authKey, data, 8, sha256);
|
||||
var length = BinaryPrimitives.ReadInt32LittleEndian(decrypted_data);
|
||||
|
|
@ -354,11 +354,11 @@ namespace WTelegram
|
|||
sha256.TransformBlock(authKey, 88 + x, 32, null, 0);
|
||||
sha256.TransformFinalBlock(decrypted_data, 0, decrypted_data.Length);
|
||||
if (success = data.AsSpan(8, 16).SequenceEqual(sha256.Hash.AsSpan(8, 16)))
|
||||
if (decrypted_data.Length - 4 - length is < 12 or > 1024) throw new ApplicationException($"Invalid MTProto2 padding length: {decrypted_data.Length - 4}-{length}");
|
||||
if (decrypted_data.Length - 4 - length is < 12 or > 1024) throw new WTException($"Invalid MTProto2 padding length: {decrypted_data.Length - 4}-{length}");
|
||||
else if (chat.remoteLayer < Layer.MTProto2) chat.remoteLayer = Layer.MTProto2;
|
||||
}
|
||||
if (!success) throw new ApplicationException("Could not decrypt message");
|
||||
if (length % 4 != 0) throw new ApplicationException($"Invalid message_data_length: {length}");
|
||||
if (!success) throw new WTException("Could not decrypt message");
|
||||
if (length % 4 != 0) throw new WTException($"Invalid message_data_length: {length}");
|
||||
using var reader = new BinaryReader(new MemoryStream(decrypted_data, 4, length));
|
||||
return reader.ReadTLObject();
|
||||
}
|
||||
|
|
@ -370,16 +370,16 @@ namespace WTelegram
|
|||
/// You can use the generic properties to access their fields
|
||||
/// <para>May return an empty array if msg was already previously received or is not the next message in sequence.
|
||||
/// <br/>May return multiple messages if missing messages are finally received (using <paramref name="fillGaps"/> = true)</para></returns>
|
||||
/// <exception cref="ApplicationException"></exception>
|
||||
/// <exception cref="WTException"></exception>
|
||||
public ICollection<DecryptedMessageBase> DecryptMessage(EncryptedMessageBase msg, bool fillGaps = true)
|
||||
{
|
||||
if (!chats.TryGetValue(msg.ChatId, out var chat)) throw new ApplicationException("Secret chat not found");
|
||||
if (!chats.TryGetValue(msg.ChatId, out var chat)) throw new WTException("Secret chat not found");
|
||||
try
|
||||
{
|
||||
var obj = Decrypt(chat, msg.Bytes, msg.Bytes.Length);
|
||||
if (obj is not TL.Layer23.DecryptedMessageLayer dml) throw new ApplicationException("Decrypted object is not DecryptedMessageLayer");
|
||||
if (dml.random_bytes.Length < 15) throw new ApplicationException("Not enough random_bytes");
|
||||
if (((dml.out_seq_no ^ dml.in_seq_no) & 1) != 1 || ((dml.out_seq_no ^ chat.in_seq_no) & 1) != 0) throw new ApplicationException("Invalid seq_no parities");
|
||||
if (obj is not TL.Layer23.DecryptedMessageLayer dml) throw new WTException("Decrypted object is not DecryptedMessageLayer");
|
||||
if (dml.random_bytes.Length < 15) throw new WTException("Not enough random_bytes");
|
||||
if (((dml.out_seq_no ^ dml.in_seq_no) & 1) != 1 || ((dml.out_seq_no ^ chat.in_seq_no) & 1) != 0) throw new WTException("Invalid seq_no parities");
|
||||
if (dml.layer > chat.remoteLayer) chat.remoteLayer = dml.layer;
|
||||
//Debug.WriteLine($"<\t{dml.in_seq_no}\t{dml.out_seq_no}\t\t\t\t\t\texpected:{chat.out_seq_no}/{chat.in_seq_no + 2}");
|
||||
if (dml.out_seq_no <= chat.in_seq_no) return Array.Empty<DecryptedMessageBase>(); // already received message
|
||||
|
|
@ -510,7 +510,7 @@ namespace WTelegram
|
|||
}
|
||||
break; // we lost, process with the larger exchange_id RequestKey
|
||||
case 0: break;
|
||||
default: throw new ApplicationException("Invalid RequestKey");
|
||||
default: throw new WTException("Invalid RequestKey");
|
||||
}
|
||||
var g_a = BigEndianInteger(request.g_a);
|
||||
var salt = new byte[256];
|
||||
|
|
@ -529,9 +529,9 @@ namespace WTelegram
|
|||
break;
|
||||
case TL.Layer23.DecryptedMessageActionAcceptKey accept:
|
||||
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.renewKey)
|
||||
throw new ApplicationException("Invalid AcceptKey");
|
||||
throw new WTException("Invalid AcceptKey");
|
||||
if (accept.exchange_id != chat.exchange_id)
|
||||
throw new ApplicationException("AcceptKey: exchange_id mismatch");
|
||||
throw new WTException("AcceptKey: exchange_id mismatch");
|
||||
var a = BigEndianInteger(chat.salt);
|
||||
g_b = BigEndianInteger(accept.g_b);
|
||||
CheckGoodGaAndGb(g_b, dh_prime);
|
||||
|
|
@ -539,7 +539,7 @@ namespace WTelegram
|
|||
var authKey = gab.To256Bytes();
|
||||
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(authKey).AsSpan(12));
|
||||
if (accept.key_fingerprint != key_fingerprint)
|
||||
throw new ApplicationException("AcceptKey: key_fingerprint mismatch");
|
||||
throw new WTException("AcceptKey: key_fingerprint mismatch");
|
||||
_ = SendMessage(chat.ChatId, new TL.Layer23.DecryptedMessageService { random_id = Helpers.RandomLong(),
|
||||
action = new TL.Layer23.DecryptedMessageActionCommitKey { exchange_id = accept.exchange_id, key_fingerprint = accept.key_fingerprint } });
|
||||
chat.salt = chat.authKey; // A may only discard the previous key after a message encrypted with the new key has been received.
|
||||
|
|
@ -548,10 +548,10 @@ namespace WTelegram
|
|||
break;
|
||||
case TL.Layer23.DecryptedMessageActionCommitKey commit:
|
||||
if ((chat.flags & (SecretChat.Flags.requestChat | SecretChat.Flags.renewKey | SecretChat.Flags.acceptKey)) != SecretChat.Flags.acceptKey)
|
||||
throw new ApplicationException("Invalid RequestKey");
|
||||
throw new WTException("Invalid RequestKey");
|
||||
key_fingerprint = BinaryPrimitives.ReadInt64LittleEndian(sha1.ComputeHash(chat.salt).AsSpan(12));
|
||||
if (commit.exchange_id != chat.exchange_id | commit.key_fingerprint != key_fingerprint)
|
||||
throw new ApplicationException("CommitKey: data mismatch");
|
||||
throw new WTException("CommitKey: data mismatch");
|
||||
chat.flags &= ~SecretChat.Flags.acceptKey;
|
||||
authKey = chat.authKey;
|
||||
SetAuthKey(chat, chat.salt);
|
||||
|
|
@ -614,7 +614,7 @@ namespace WTelegram
|
|||
var res = md5.TransformFinalBlock(iv, 0, 32);
|
||||
long fingerprint = BinaryPrimitives.ReadInt64LittleEndian(md5.Hash);
|
||||
fingerprint ^= fingerprint >> 32;
|
||||
if (encryptedFile.key_fingerprint != (int)fingerprint) throw new ApplicationException("Encrypted file fingerprint mismatch");
|
||||
if (encryptedFile.key_fingerprint != (int)fingerprint) throw new WTException("Encrypted file fingerprint mismatch");
|
||||
|
||||
using var decryptStream = new AES_IGE_Stream(outputStream, size, key, iv);
|
||||
var fileLocation = encryptedFile.ToFileLocation();
|
||||
|
|
|
|||
|
|
@ -104,12 +104,12 @@ namespace WTelegram
|
|||
{
|
||||
var input = new byte[length];
|
||||
if (store.Read(input, 0, length) != length)
|
||||
throw new ApplicationException($"Can't read session block ({store.Position}, {length})");
|
||||
throw new WTException($"Can't read session block ({store.Position}, {length})");
|
||||
using var sha256 = SHA256.Create();
|
||||
using var decryptor = aes.CreateDecryptor(rgbKey, input[0..16]);
|
||||
var utf8Json = decryptor.TransformFinalBlock(input, 16, input.Length - 16);
|
||||
if (!sha256.ComputeHash(utf8Json, 32, utf8Json.Length - 32).SequenceEqual(utf8Json[0..32]))
|
||||
throw new ApplicationException("Integrity check failed in session loading");
|
||||
throw new WTException("Integrity check failed in session loading");
|
||||
session = JsonSerializer.Deserialize<Session>(utf8Json.AsSpan(32), Helpers.JsonOptions);
|
||||
Helpers.Log(2, "Loaded previous session");
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ namespace WTelegram
|
|||
catch (Exception ex)
|
||||
{
|
||||
store.Dispose();
|
||||
throw new ApplicationException($"Exception while reading session file: {ex.Message}\nUse the correct api_hash/id/key, or delete the file to start a new session", ex);
|
||||
throw new WTException($"Exception while reading session file: {ex.Message}\nUse the correct api_hash/id/key, or delete the file to start a new session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ 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 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 Task<Messages_Chats> Messages_GetChats(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllChats");
|
||||
public static Task<Messages_Chats> Channels_GetChannels(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllChats");
|
||||
public static Task<UserBase[]> Users_GetUsers(this Client _) => throw new WTException("The method you're looking for is Messages_GetAllDialogs");
|
||||
public static Task<Messages_MessagesBase> Messages_GetMessages(this Client _) => throw new WTException("If you want to get the messages from a chat, use Messages_GetHistory");
|
||||
}
|
||||
|
||||
public static class Markdown
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace TL
|
|||
public abstract class DecryptedMessageMedia : IObject
|
||||
{
|
||||
public virtual string MimeType { get; }
|
||||
internal virtual (long size, byte[] key, byte[] iv) SizeKeyIV { get => default; set => throw new ApplicationException("Incompatible DecryptedMessageMedia"); }
|
||||
internal virtual (long size, byte[] key, byte[] iv) SizeKeyIV { get => default; set => throw new WTelegram.WTException("Incompatible DecryptedMessageMedia"); }
|
||||
}
|
||||
|
||||
/// <summary>Object describes the action to which a service message is linked. <para>See <a href="https://corefork.telegram.org/type/DecryptedMessageAction"/></para></summary>
|
||||
|
|
|
|||
10
src/TL.cs
10
src/TL.cs
|
|
@ -28,7 +28,7 @@ namespace TL
|
|||
public IfFlagAttribute(int bit) => Bit = bit;
|
||||
}
|
||||
|
||||
public class RpcException : Exception
|
||||
public class RpcException : WTelegram.WTException
|
||||
{
|
||||
public readonly int Code;
|
||||
/// <summary>The value of X in the message, -1 if no variable X was found</summary>
|
||||
|
|
@ -73,7 +73,7 @@ namespace TL
|
|||
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}");
|
||||
throw new WTelegram.WTException($"Cannot find type for ctor #{ctorNb:x}");
|
||||
if (type == null) return null; // nullable ctor (class meaning is associated with null)
|
||||
var tlDef = type.GetCustomAttribute<TLDefAttribute>();
|
||||
var obj = Activator.CreateInstance(type, true);
|
||||
|
|
@ -153,7 +153,7 @@ namespace TL
|
|||
0x997275b5 => true,
|
||||
0xbc799737 => false,
|
||||
Layer.RpcErrorCtor => reader.ReadTLObject(Layer.RpcErrorCtor),
|
||||
var value => throw new ApplicationException($"Invalid boolean value #{value:x}")
|
||||
var value => throw new WTelegram.WTException($"Invalid boolean value #{value:x}")
|
||||
};
|
||||
case TypeCode.Object:
|
||||
if (type.IsArray)
|
||||
|
|
@ -235,7 +235,7 @@ namespace TL
|
|||
return array;
|
||||
}
|
||||
else
|
||||
throw new ApplicationException($"Cannot deserialize {type.Name} with ctor #{ctorNb:x}");
|
||||
throw new WTelegram.WTException($"Cannot deserialize {type.Name} with ctor #{ctorNb:x}");
|
||||
}
|
||||
|
||||
internal static Dictionary<long, T> ReadTLDictionary<T>(this BinaryReader reader, Func<T, long> getID) where T : class
|
||||
|
|
@ -243,7 +243,7 @@ namespace TL
|
|||
uint ctorNb = reader.ReadUInt32();
|
||||
var elementType = typeof(T);
|
||||
if (ctorNb != Layer.VectorCtor)
|
||||
throw new ApplicationException($"Cannot deserialize Vector<{elementType.Name}> with ctor #{ctorNb:x}");
|
||||
throw new WTelegram.WTException($"Cannot deserialize Vector<{elementType.Name}> with ctor #{ctorNb:x}");
|
||||
int count = reader.ReadInt32();
|
||||
var dict = new Dictionary<long, T>(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace WTelegram
|
|||
if (await _innerStream.FullReadAsync(_tlsReadHeader, 5, ct) != 5)
|
||||
return 0;
|
||||
if (_tlsReadHeader[0] != 0x17 || _tlsReadHeader[1] != 0x03 || _tlsReadHeader[2] != 0x03)
|
||||
throw new ApplicationException("Could not read frame data : Invalid TLS header");
|
||||
throw new WTException("Could not read frame data : Invalid TLS header");
|
||||
_tlsFrameleft = (_tlsReadHeader[3] << 8) + _tlsReadHeader[4];
|
||||
}
|
||||
var read = await _innerStream.ReadAsync(buffer, offset, Math.Min(count, _tlsFrameleft), ct);
|
||||
|
|
@ -82,7 +82,7 @@ namespace WTelegram
|
|||
}
|
||||
}
|
||||
}
|
||||
throw new ApplicationException("TLS Handshake failed");
|
||||
throw new WTException("TLS Handshake failed");
|
||||
}
|
||||
|
||||
static readonly byte[] TlsClientHello1 = new byte[11] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue