Explorar o código

GramJS: Remove loose console logs and replace them with logger (#242)

painor %!s(int64=5) %!d(string=hai) anos
pai
achega
f590cd3ef6

+ 7 - 3
src/lib/gramjs/client/TelegramClient.js

@@ -78,7 +78,6 @@ class TelegramClient {
             try {
                 throw new Error('not implemented')
             } catch (e) {
-                console.log(e)
                 session = new MemorySession()
             }
         } else if (!(session instanceof Session)) {
@@ -190,7 +189,7 @@ class TelegramClient {
                     pingId: rnd,
                 }))
             } catch (e) {
-                console.log('err is ', e)
+
             }
 
             // We need to send some content-related request at least hourly
@@ -202,7 +201,7 @@ class TelegramClient {
                 try {
                     await this.invoke(new requests.updates.GetStateRequest())
                 } catch (e) {
-                    console.log('err is ', e)
+
                 }
             }
         }
@@ -366,6 +365,11 @@ class TelegramClient {
             try {
                 sender = await this._borrowExportedSender(dcId)
             } catch (e) {
+<<<<<<< HEAD
+=======
+                // This should never raise
+                this._log.error(e)
+>>>>>>> e664f064... GramJS: Remove loose console logs and replace them with logger (#242)
                 if (e.message === 'DC_ID_INVALID') {
                     // Can't export a sender for the ID we are currently in
                     sender = this._sender

+ 217 - 0
src/lib/gramjs/client/auth.ts

@@ -0,0 +1,217 @@
+import { default as Api } from '../tl/api';
+import TelegramClient from './TelegramClient';
+import utils from '../Utils';
+import { computeCheck as computePasswordSrpCheck } from '../Password';
+
+export interface UserAuthParams {
+    phoneNumber: string | (() => Promise<string>);
+    phoneCode: () => Promise<string>;
+    password: () => Promise<string>;
+    firstAndLastNames: () => Promise<[string, string?]>;
+    onError: (err: Error) => void;
+    forceSMS?: boolean;
+}
+
+export interface BotAuthParams {
+    botAuthToken: string;
+}
+
+interface ApiCredentials {
+    apiId: number,
+    apiHash: string,
+}
+
+export async function authFlow(
+    client: TelegramClient,
+    apiCredentials: ApiCredentials,
+    authParams: UserAuthParams | BotAuthParams,
+) {
+    const me = 'phoneNumber' in authParams
+        ? await signInUser(client, apiCredentials, authParams)
+        : await signInBot(client, apiCredentials, authParams);
+
+    // TODO @logger
+    client._log.info('Signed in successfully as', utils.getDisplayName(me));
+}
+
+
+export async function checkAuthorization(client: TelegramClient) {
+    try {
+        await client.invoke(new Api.updates.GetState());
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+async function signInUser(
+    client: TelegramClient, apiCredentials: ApiCredentials, authParams: UserAuthParams,
+): Promise<Api.TypeUser> {
+    let me: Api.TypeUser;
+
+    let phoneNumber;
+    let phoneCodeHash;
+
+    while (1) {
+        try {
+            phoneNumber = typeof authParams.phoneNumber === 'function'
+                ? await authParams.phoneNumber()
+                : authParams.phoneNumber;
+            phoneCodeHash = await sendCode(client, apiCredentials, phoneNumber, authParams.forceSMS);
+
+            if (typeof phoneCodeHash !== 'string') {
+                throw new Error('Failed to retrieve phone code hash');
+            }
+
+            break;
+        } catch (err) {
+            if (typeof authParams.phoneNumber !== 'function') {
+                throw err;
+            }
+
+            authParams.onError(err);
+        }
+    }
+
+    let phoneCode;
+    let isPasswordRequired = false;
+    let isRegistrationRequired = false;
+    let termsOfService;
+
+    while (1) {
+        try {
+            try {
+                phoneCode = await authParams.phoneCode();
+            } catch (err) {
+                // This is the support for changing phone number from the phone code screen.
+                if (err.message === 'RESTART_AUTH') {
+                    return signInUser(client, apiCredentials, authParams);
+                }
+            }
+
+            if (!phoneCode) {
+                throw new Error('Code is empty');
+            }
+
+            // May raise PhoneCodeEmptyError, PhoneCodeExpiredError,
+            // PhoneCodeHashEmptyError or PhoneCodeInvalidError.
+            const result = await client.invoke(new Api.auth.SignIn({
+                phoneNumber,
+                phoneCodeHash,
+                phoneCode,
+            }));
+
+            if (result instanceof Api.auth.AuthorizationSignUpRequired) {
+                isRegistrationRequired = true;
+                termsOfService = result.termsOfService;
+            } else {
+                me = result.user;
+            }
+
+            break;
+        } catch (err) {
+            if (err.message === 'SESSION_PASSWORD_NEEDED') {
+                isPasswordRequired = true;
+                break;
+            } else {
+                authParams.onError(err);
+            }
+        }
+    }
+
+    if (isPasswordRequired) {
+        while (1) {
+            try {
+                const password = await authParams.password();
+                if (!password) {
+                    throw new Error('Password is empty');
+                }
+
+                const passwordSrpResult = await client.invoke(new Api.account.GetPassword());
+                const passwordSrpCheck = await computePasswordSrpCheck(passwordSrpResult, password);
+                const { user } = await client.invoke(new Api.auth.CheckPassword({
+                    password: passwordSrpCheck,
+                })) as Api.auth.Authorization;
+                me = user;
+
+                break;
+            } catch (err) {
+                authParams.onError(err);
+            }
+        }
+    }
+
+    if (isRegistrationRequired) {
+        while (1) {
+            try {
+                const [firstName, lastName] = await authParams.firstAndLastNames();
+                if (!firstName) {
+                    throw new Error('First name is required');
+                }
+
+                const { user } = await client.invoke(new Api.auth.SignUp({
+                    phoneNumber,
+                    phoneCodeHash,
+                    firstName,
+                    lastName,
+                })) as Api.auth.Authorization;
+
+                if (termsOfService) {
+                    // This is a violation of Telegram rules: the user should be presented with and accept TOS.
+                    await client.invoke(new Api.help.AcceptTermsOfService({ id: termsOfService.id }));
+                }
+
+                me = user;
+            } catch (err) {
+                authParams.onError(err);
+            }
+        }
+    }
+
+    return me!;
+}
+
+async function sendCode(
+    client: TelegramClient, apiCredentials: ApiCredentials, phoneNumber: string, forceSMS = false,
+): Promise<string | undefined> {
+    try {
+        const { apiId, apiHash } = apiCredentials;
+        const sendResult = await client.invoke(new Api.auth.SendCode({
+            phoneNumber,
+            apiId,
+            apiHash,
+            settings: new Api.CodeSettings(),
+        }));
+
+        // If we already sent a SMS, do not resend the phoneCode (hash may be empty)
+        if (!forceSMS || (sendResult.type instanceof Api.auth.SentCodeTypeSms)) {
+            return sendResult.phoneCodeHash;
+        }
+
+        const resendResult = await client.invoke(new Api.auth.ResendCode({
+            phoneNumber,
+            phoneCodeHash: sendResult.phoneCodeHash,
+        }));
+
+        return resendResult.phoneCodeHash;
+    } catch (err) {
+        if (err.message === 'AUTH_RESTART') {
+            return sendCode(client, apiCredentials, phoneNumber, forceSMS);
+        } else {
+            throw err;
+        }
+    }
+}
+
+async function signInBot(client: TelegramClient, apiCredentials: ApiCredentials, authParams: BotAuthParams) {
+    const { apiId, apiHash } = apiCredentials;
+    const { botAuthToken } = authParams;
+
+    const { user } = await client.invoke(new Api.auth.ImportBotAuthorization({
+        apiId,
+        apiHash,
+        botAuthToken,
+    })) as Api.auth.Authorization;
+
+    return user;
+}

+ 0 - 4
src/lib/gramjs/extensions/PromisedWebSockets.js

@@ -32,12 +32,10 @@ class PromisedWebSockets {
 
     async read(number) {
         if (this.closed) {
-            console.log('couldn\'t read')
             throw closeError
         }
         await this.canRead
         if (this.closed) {
-            console.log('couldn\'t read')
             throw closeError
         }
         const toReturn = this.stream.slice(0, number)
@@ -72,7 +70,6 @@ class PromisedWebSockets {
     }
 
     async connect(port, ip) {
-        console.log('trying to connect')
         this.stream = Buffer.alloc(0)
         this.canRead = new Promise((resolve) => {
             this.resolveRead = resolve
@@ -110,7 +107,6 @@ class PromisedWebSockets {
     }
 
     async close() {
-        console.log('something happened. closing')
         await this.client.close()
         this.closed = true
     }

+ 4 - 6
src/lib/gramjs/network/MTProtoSender.js

@@ -370,8 +370,6 @@ class MTProtoSender {
             try {
                 message = await this._state.decryptMessageData(body)
             } catch (e) {
-                console.log(e)
-
                 if (e instanceof TypeNotFoundError) {
                     // Received object which we don't know how to deserialize
                     this._log.info(`Type ${e.invalidConstructorId} not found, remaining data ${e.remaining}`)
@@ -392,7 +390,7 @@ class MTProtoSender {
                     return
                 } else {
                     this._log.error('Unhandled error while receiving data')
-                    console.log(e)
+                    this._log.error(e)
                     this._startReconnect()
                     return
                 }
@@ -400,8 +398,8 @@ class MTProtoSender {
             try {
                 await this._processMessage(message)
             } catch (e) {
-                console.log(e)
                 this._log.error('Unhandled error while receiving data')
+                this._log.error(e)
             }
         }
     }
@@ -495,7 +493,7 @@ class MTProtoSender {
                     throw new TypeNotFoundError('Not an upload.File')
                 }
             } catch (e) {
-                console.log(e)
+                this._log.error(e)
                 if (e instanceof TypeNotFoundError) {
                     this._log.info(`Received response without parent request: ${RPCResult.body}`)
                     return
@@ -764,7 +762,7 @@ class MTProtoSender {
         try {
             await this.disconnect()
         } catch (err) {
-            console.warn(err)
+            this._log.warn(err)
         }
         this._send_queue.append(null)
 

+ 1 - 3
src/lib/gramjs/network/connection/Connection.js

@@ -87,7 +87,6 @@ class Connection {
                 await this._send(data)
             }
         } catch (e) {
-            console.log(e)
             this._log.info('The server closed the connection while sending')
         }
     }
@@ -98,10 +97,9 @@ class Connection {
             try {
                 data = await this._recv()
                 if (!data) {
-                    throw new Error("no data recieved")
+                    throw new Error("no data received")
                 }
             } catch (e) {
-                console.log(e)
                 this._log.info('connection closed')
                 //await this._recvArray.push()