mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Fix 444 trying to download from a media_only DC with unnegociated AuthKey
This commit is contained in:
parent
e1132f653b
commit
409cf25619
|
|
@ -58,7 +58,7 @@ static string Config(string what)
|
||||||
using var client = new WTelegram.Client(Config);
|
using var client = new WTelegram.Client(Config);
|
||||||
```
|
```
|
||||||
There are other configuration items that are queried to your method but returning `null` let WTelegramClient choose a default adequate value.
|
There are other configuration items that are queried to your method but returning `null` let WTelegramClient choose a default adequate value.
|
||||||
Those shown above are the only ones that have no default values and <u>should be provided</u> by your method.
|
Those shown above are the only ones that have no default values and should be provided by your method.
|
||||||
Returning `null` for verification_code or password will show a prompt for console apps, or an error otherwise.
|
Returning `null` for verification_code or password will show a prompt for console apps, or an error otherwise.
|
||||||
|
|
||||||
Another simple approach is to pass `Environment.GetEnvironmentVariable` as the config callback and define the configuration items as environment variables.
|
Another simple approach is to pass `Environment.GetEnvironmentVariable` as the config callback and define the configuration items as environment variables.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -343,6 +344,8 @@ namespace WTelegram
|
||||||
if (dcSession.Client != null || dcSession.DataCenter.flags == flags)
|
if (dcSession.Client != null || dcSession.DataCenter.flags == flags)
|
||||||
return dcSession; // if we have already a session with this DC and we are connected or it is a perfect match, use it
|
return dcSession; // if we have already a session with this DC and we are connected or it is a perfect match, use it
|
||||||
// try to find the most appropriate DcOption for this DC
|
// try to find the most appropriate DcOption for this DC
|
||||||
|
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 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 ApplicationException($"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 ??= new Session.DCSession { Id = Helpers.RandomLong() }; // create new session only if not already existing
|
||||||
|
|
@ -960,11 +963,7 @@ namespace WTelegram
|
||||||
_session.UserId = _dcSession.UserId = 0;
|
_session.UserId = _dcSession.UserId = 0;
|
||||||
}
|
}
|
||||||
var authorization = await this.Auth_ImportBotAuthorization(0, _apiId, _apiHash, botToken);
|
var authorization = await this.Auth_ImportBotAuthorization(0, _apiId, _apiHash, botToken);
|
||||||
if (authorization is not Auth_Authorization { user: User user })
|
return LoginAlreadyDone(authorization);
|
||||||
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
|
|
||||||
_session.UserId = _dcSession.UserId = user.id;
|
|
||||||
_session.Save();
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Login as a user (if not already logged-in).
|
/// <summary>Login as a user (if not already logged-in).
|
||||||
|
|
@ -1010,24 +1009,21 @@ namespace WTelegram
|
||||||
sentCode = await this.Auth_SendCode(phone_number, _apiId, _apiHash, settings ??= new());
|
sentCode = await this.Auth_SendCode(phone_number, _apiId, _apiHash, settings ??= new());
|
||||||
}
|
}
|
||||||
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
|
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
|
||||||
Auth_AuthorizationBase authorization;
|
Auth_AuthorizationBase authorization = null;
|
||||||
for (int retry = 1; ; retry++)
|
for (int retry = 1; authorization == null; retry++)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var verification_code = Config("verification_code");
|
var verification_code = Config("verification_code");
|
||||||
authorization = await this.Auth_SignIn(phone_number, sentCode.phone_code_hash, verification_code);
|
authorization = await this.Auth_SignIn(phone_number, sentCode.phone_code_hash, verification_code);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (RpcException e) when (e.Code == 401 && e.Message == "SESSION_PASSWORD_NEEDED")
|
catch (RpcException e) when (e.Code == 401 && e.Message == "SESSION_PASSWORD_NEEDED")
|
||||||
{
|
{
|
||||||
var accountPassword = await this.Account_GetPassword();
|
var accountPassword = await this.Account_GetPassword();
|
||||||
var checkPasswordSRP = Check2FA(accountPassword, () => Config("password"));
|
var checkPasswordSRP = Check2FA(accountPassword, () => Config("password"));
|
||||||
authorization = await this.Auth_CheckPassword(checkPasswordSRP);
|
authorization = await this.Auth_CheckPassword(checkPasswordSRP);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
catch (RpcException e) when (e.Code == 400 && e.Message == "PHONE_CODE_INVALID" && retry != 3)
|
catch (RpcException e) when (e.Code == 400 && e.Message == "PHONE_CODE_INVALID" && retry != 3)
|
||||||
{
|
{
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (authorization is Auth_AuthorizationSignUpRequired signUpRequired)
|
if (authorization is Auth_AuthorizationSignUpRequired signUpRequired)
|
||||||
{
|
{
|
||||||
|
|
@ -1040,6 +1036,18 @@ namespace WTelegram
|
||||||
if (wait > TimeSpan.Zero) await Task.Delay(wait); // we get a FLOOD_WAIT_3 if we SignUp too fast
|
if (wait > TimeSpan.Zero) await Task.Delay(wait); // we get a FLOOD_WAIT_3 if we SignUp too fast
|
||||||
authorization = await this.Auth_SignUp(phone_number, sentCode.phone_code_hash, first_name, last_name);
|
authorization = await this.Auth_SignUp(phone_number, sentCode.phone_code_hash, first_name, last_name);
|
||||||
}
|
}
|
||||||
|
return LoginAlreadyDone(authorization);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary><b>[Not recommended]</b> You can use this if you have already obtained a login authorization manually</summary>
|
||||||
|
/// <param name="authorization">if this was not a successful Auth_Authorization, an exception is thrown</param>
|
||||||
|
/// <returns>the User that was authorized</returns>
|
||||||
|
/// <remarks>This approach is not recommended because you likely didn't properly handle all aspects of the login process
|
||||||
|
/// <br/>(transient failures, unnecessary login, 2FA, sign-up required, slowness to respond, verification code resending, encryption key safety, etc..)
|
||||||
|
/// <br/>Methods <c>LoginUserIfNeeded</c> and <c>LoginBotIfNeeded</c> handle these automatically for you</remarks>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public User LoginAlreadyDone(Auth_AuthorizationBase authorization)
|
||||||
|
{
|
||||||
if (authorization is not Auth_Authorization { user: User user })
|
if (authorization is not Auth_Authorization { user: User user })
|
||||||
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
|
throw new ApplicationException("Failed to get Authorization: " + authorization.GetType().Name);
|
||||||
_session.UserId = _dcSession.UserId = user.id;
|
_session.UserId = _dcSession.UserId = user.id;
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,20 @@ using System.Net;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
#if NETCOREAPP2_1_OR_GREATER
|
||||||
namespace WTelegram
|
namespace WTelegram
|
||||||
{
|
{
|
||||||
static class Compat
|
static class Compat
|
||||||
{
|
{
|
||||||
#if NETCOREAPP2_1_OR_GREATER
|
|
||||||
internal static IPEndPoint IPEndPoint_Parse(string addr) => IPEndPoint.Parse(addr);
|
|
||||||
internal static BigInteger BigEndianInteger(byte[] value) => new(value, true, true);
|
internal static BigInteger BigEndianInteger(byte[] value) => new(value, true, true);
|
||||||
|
internal static IPEndPoint IPEndPoint_Parse(string addr) => IPEndPoint.Parse(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
namespace WTelegram
|
||||||
|
{
|
||||||
|
static class Compat
|
||||||
|
{
|
||||||
internal static BigInteger BigEndianInteger(byte[] value)
|
internal static BigInteger BigEndianInteger(byte[] value)
|
||||||
{
|
{
|
||||||
var data = new byte[value.Length + 1];
|
var data = new byte[value.Length + 1];
|
||||||
|
|
@ -68,20 +74,21 @@ namespace WTelegram
|
||||||
rsa.ImportParameters(new RSAParameters { Modulus = m.ToArray(), Exponent = e.ToArray() });
|
rsa.ImportParameters(new RSAParameters { Modulus = m.ToArray(), Exponent = e.ToArray() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class Convert
|
static class Convert
|
||||||
|
{
|
||||||
|
internal static string ToHexString(byte[] data) => BitConverter.ToString(data).Replace("-", "");
|
||||||
|
internal static byte[] FromHexString(string hex)
|
||||||
{
|
{
|
||||||
internal static byte[] FromHexString(string hex)
|
int NumberChars = hex.Length;
|
||||||
{
|
byte[] bytes = new byte[NumberChars / 2];
|
||||||
int NumberChars = hex.Length;
|
for (int i = 0; i < NumberChars; i += 2)
|
||||||
byte[] bytes = new byte[NumberChars / 2];
|
bytes[i / 2] = System.Convert.ToByte(hex.Substring(i, 2), 16);
|
||||||
for (int i = 0; i < NumberChars; i += 2)
|
return bytes;
|
||||||
bytes[i / 2] = System.Convert.ToByte(hex.Substring(i, 2), 16);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if NETSTANDARD2_0
|
||||||
namespace System.Runtime.CompilerServices
|
namespace System.Runtime.CompilerServices
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,7 @@ namespace TL
|
||||||
public static bool operator !=(Int128 left, Int128 right) { for (int i = 0; i < 16; i++) if (left.raw[i] != right.raw[i]) return true; return false; }
|
public static bool operator !=(Int128 left, Int128 right) { for (int i = 0; i < 16; i++) if (left.raw[i] != right.raw[i]) return true; return false; }
|
||||||
public override bool Equals(object obj) => obj is Int128 other && this == other;
|
public override bool Equals(object obj) => obj is Int128 other && this == other;
|
||||||
public override int GetHashCode() => HashCode.Combine(raw[0], raw[1]);
|
public override int GetHashCode() => HashCode.Combine(raw[0], raw[1]);
|
||||||
|
public override string ToString() => Convert.ToHexString(raw);
|
||||||
public static implicit operator byte[](Int128 int128) => int128.raw;
|
public static implicit operator byte[](Int128 int128) => int128.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,6 +350,7 @@ namespace TL
|
||||||
public static bool operator !=(Int256 left, Int256 right) { for (int i = 0; i < 32; i++) if (left.raw[i] != right.raw[i]) return true; return false; }
|
public static bool operator !=(Int256 left, Int256 right) { for (int i = 0; i < 32; i++) if (left.raw[i] != right.raw[i]) return true; return false; }
|
||||||
public override bool Equals(object obj) => obj is Int256 other && this == other;
|
public override bool Equals(object obj) => obj is Int256 other && this == other;
|
||||||
public override int GetHashCode() => HashCode.Combine(raw[0], raw[1]);
|
public override int GetHashCode() => HashCode.Combine(raw[0], raw[1]);
|
||||||
|
public override string ToString() => Convert.ToHexString(raw);
|
||||||
public static implicit operator byte[](Int256 int256) => int256.raw;
|
public static implicit operator byte[](Int256 int256) => int256.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue