浏览代码

GramJS: Implement signup

painor 5 年之前
父节点
当前提交
3280583cbd

+ 5 - 1
src/api/gramjs/client.ts

@@ -9,7 +9,7 @@ import { Logger as GramJsLogger } from '../../lib/gramjs/extensions';
 
 import { DEBUG } from '../../config';
 import {
-  onAuthReady, onRequestCode, onRequestPassword, onRequestPhoneNumber,
+  onAuthReady, onRequestCode, onRequestPassword, onRequestPhoneNumber, onRequestRegistration,
 } from './connectors/auth';
 import { onGramJsUpdate } from './onGramJsUpdate';
 <<<<<<< HEAD
@@ -28,7 +28,10 @@ GramJsLogger.getLogger().level = 'debug';
 import queuedDownloadMedia from './connectors/media';
 
 GramJsLogger.setLevel(DEBUG ? 'debug' : 'warn');
+<<<<<<< HEAD
 >>>>>>> ddb2a0ed... GramJS: Fix downloading images of uncommon (small) size
+=======
+>>>>>>> 073c3e12... GramJS: Implement signup
 
 let client: TelegramClient;
 
@@ -53,6 +56,7 @@ export async function init(sessionId: string) {
       phone: onRequestPhoneNumber,
       code: onRequestCode,
       password: onRequestPassword,
+      firstAndLastNames: onRequestRegistration,
     } as any);
 
     const newSessionId = session.save();

+ 24 - 0
src/api/gramjs/connectors/auth.ts

@@ -5,10 +5,12 @@ const authPromiseResolvers: {
   resolvePhoneNumber: null | Function;
   resolveCode: null | Function;
   resolvePassword: null | Function;
+  resolveRegistration: null | Function;
 } = {
   resolvePhoneNumber: null,
   resolveCode: null,
   resolvePassword: null,
+  resolveRegistration: null,
 };
 
 let onUpdate: OnApiUpdate;
@@ -53,6 +55,18 @@ export function onRequestPassword() {
   });
 }
 
+export function onRequestRegistration() {
+  if (!onUpdate) {
+    return null;
+  }
+
+  onUpdate(buildAuthState('authorizationStateWaitRegistration'));
+
+  return new Promise((resolve) => {
+    authPromiseResolvers.resolveRegistration = resolve;
+  });
+}
+
 export function onAuthReady(sessionId: string) {
   if (!onUpdate) {
     return;
@@ -96,3 +110,13 @@ export function provideAuthPassword(password: string) {
 
   authPromiseResolvers.resolvePassword(password);
 }
+
+export function provideAuthRegistration(registration: { firstName: string; lastName: string }) {
+  const { firstName, lastName } = registration;
+
+  if (!authPromiseResolvers.resolveRegistration) {
+    return;
+  }
+
+  authPromiseResolvers.resolveRegistration([firstName, lastName]);
+}

+ 17 - 0
src/api/gramjs/sdk.ts

@@ -0,0 +1,17 @@
+import {
+  provideAuthPhoneNumber, provideAuthCode, provideAuthPassword, provideAuthRegistration,
+} from './connectors/auth';
+import { fetchChats } from './connectors/chats';
+import { fetchMessages, sendMessage } from './connectors/messages';
+import { downloadMedia } from './client';
+
+export default {
+  provideAuthPhoneNumber,
+  provideAuthCode,
+  provideAuthPassword,
+  provideAuthRegistration,
+  fetchChats,
+  fetchMessages,
+  sendMessage,
+  downloadMedia,
+};

+ 51 - 9
src/lib/gramjs/client/TelegramClient.js

@@ -759,9 +759,17 @@ class TelegramClient {
     }
 
     async getMe() {
+<<<<<<< HEAD
         const me = (await this.invoke(new requests.users
             .GetUsersRequest({ id: [new constructors.InputUserSelf()] })))[0]
         return me
+=======
+        try {
+            return (await this.invoke(new requests.users
+                .GetUsers({ id: [new constructors.InputUserSelf()] })))[0]
+        } catch (e) {
+        }
+>>>>>>> 073c3e12... GramJS: Implement signup
     }
 
 
@@ -771,8 +779,7 @@ class TelegramClient {
         password: null,
         botToken: null,
         forceSMS: null,
-        firstName: null,
-        lastName: null,
+        firstAndLastNames: null,
         maxAttempts: 5,
     }) {
         args.maxAttempts = args.maxAttempts || 5
@@ -814,18 +821,25 @@ class TelegramClient {
         await this.sendCodeRequest(args.phone, args.forceSMS)
 
         let signUp = false
+        let value
         while (attempts < args.maxAttempts) {
             try {
-                const value = await args.code()
+                if (!signUp) {
+                    value = await args.code()
+                }
                 if (!value) {
                     throw new Error('the phone code is empty')
                 }
 
                 if (signUp) {
+                    const [firstName, lastName] = await args.firstAndLastNames()
+                    if (!firstName) {
+                        throw new Error("first name can't be empty")
+                    }
                     me = await this.signUp({
                         code: value,
-                        firstName: args.firstName,
-                        lastName: args.lastName,
+                        firstName: firstName,
+                        lastName: lastName || '',
                     })
                 } else {
                     // this throws SessionPasswordNeededError if 2FA enabled
@@ -840,7 +854,7 @@ class TelegramClient {
                     twoStepDetected = true
                     break
                 } else if (e.message === 'PHONE_NUMBER_OCCUPIED') {
-                    signUp = true
+                    signUp = false
                 } else if (e.message === 'PHONE_NUMBER_UNOCCUPIED') {
                     signUp = true
                 } else if (e.message === 'PHONE_CODE_EMPTY' ||
@@ -939,12 +953,21 @@ class TelegramClient {
             throw new Error('You must provide a phone and a code the first time, ' +
                 'and a password only if an RPCError was raised before.')
         }
+        if (result instanceof constructors.auth.AuthorizationSignUpRequired) {
+            this._tos = result.termsOfService
+            throw new Error('PHONE_NUMBER_UNOCCUPIED')
+        }
+
         return this._onLogin(result.user)
     }
 
 
     _parsePhoneAndHash(phone, phoneHash) {
-        phone = utils.parsePhone(phone) || this._phone
+        if (!phone) {
+            phone = this._phone
+        } else {
+            phone = utils.parsePhone(phone)
+        }
         if (!phone) {
             throw new Error('Please make sure to call send_code_request first.')
         }
@@ -1329,8 +1352,27 @@ class TelegramClient {
         return false
     }
 
-    async signUp() {
-
+    async signUp(args) {
+        const me = await this.getMe()
+        if (me) {
+            return me
+        }
+        if (this._tos && this._tos.text) {
+            console.log(this._tos.text)
+            // The user should click accept if he wants to continue
+        }
+        const [phone, phoneCodeHash] =
+            this._parsePhoneAndHash(args.phone, args.phoneCodeHash)
+        const result = await this.invoke(new requests.auth.SignUp({
+            phoneNumber: phone,
+            phoneCodeHash: phoneCodeHash,
+            firstName: args.firstName,
+            lastName: args.lastName,
+        }))
+        if (this._tos) {
+            await this.invoke(new requests.help.AcceptTermsOfService({ id: this._tos.id }))
+        }
+        return this._onLogin(result.user)
     }
 }
 

+ 13 - 11
src/lib/gramjs/sessions/Memory.js

@@ -79,7 +79,7 @@ class MemorySession extends Session {
     }
 
     _entityToRow(e) {
-        if (!(e.classType==="constructor")) {
+        if (!(e.classType === "constructor")) {
             return
         }
         let p
@@ -114,18 +114,20 @@ class MemorySession extends Session {
 
     _entitiesToRows(tlo) {
         let entities = []
-        if (tlo.classType==="constructor" && utils.isListLike(tlo)) {
+        if (tlo.classType === "constructor" && utils.isListLike(tlo)) {
             // This may be a list of users already for instance
             entities = tlo
         } else {
-            if ('user' in tlo) {
-                entities.push(tlo.user)
-            }
-            if ('chats' in tlo && utils.isListLike(tlo.chats)) {
-                entities.concat(tlo.chats)
-            }
-            if ('users' in tlo && utils.isListLike(tlo.users)) {
-                entities.concat(tlo.users)
+            if (tlo instanceof Object) {
+                if ('user' in tlo) {
+                    entities.push(tlo.user)
+                }
+                if ('chats' in tlo && utils.isListLike(tlo.chats)) {
+                    entities.concat(tlo.chats)
+                }
+                if ('users' in tlo && utils.isListLike(tlo.users)) {
+                    entities.concat(tlo.users)
+                }
             }
         }
         const rows = [] // Rows to add (id, hash, username, phone, name)
@@ -201,7 +203,7 @@ class MemorySession extends Session {
             return utils.getInputPeer(key)
         } else {
             // Not a TLObject or can't be cast into InputPeer
-            if (key.classType==='constructor') {
+            if (key.classType === 'constructor') {
                 key = utils.getPeerId(key)
                 exact = true
             } else {

+ 77 - 0
src/modules/gramjs/actions/system.ts

@@ -0,0 +1,77 @@
+import { addReducer, getDispatch } from '../../../lib/teactn';
+
+import { GlobalState } from '../../../store/types';
+import { GRAMJS_SESSION_ID_KEY } from '../../../config';
+import { initSdk, callSdk } from '../../../api/gramjs';
+import onUpdate from '../updaters';
+
+addReducer('init', (global: GlobalState) => {
+  const sessionId = localStorage.getItem(GRAMJS_SESSION_ID_KEY) || undefined;
+  void initSdk(onUpdate, sessionId);
+
+  return {
+    ...global,
+    isInitialized: true,
+    authIsSessionRemembered: Boolean(sessionId),
+  };
+});
+
+addReducer('setAuthPhoneNumber', (global, actions, payload) => {
+  const { phoneNumber } = payload!;
+
+  void callSdk('provideAuthPhoneNumber', phoneNumber);
+
+  return {
+    ...global,
+    authIsLoading: true,
+  };
+});
+
+addReducer('setAuthCode', (global, actions, payload) => {
+  const { code } = payload!;
+
+  void callSdk('provideAuthCode', code);
+
+  return {
+    ...global,
+    authIsLoading: true,
+  };
+});
+
+addReducer('setAuthPassword', (global, actions, payload) => {
+  const { password } = payload!;
+
+  void callSdk('provideAuthPassword', password);
+
+  return {
+    ...global,
+    authIsLoading: true,
+  };
+});
+
+addReducer('signUp', (global, actions, payload) => {
+  const { firstName, lastName } = payload!;
+
+  void callSdk('provideAuthRegistration', { firstName, lastName });
+
+  return {
+    ...global,
+    authIsLoading: true,
+  };
+});
+
+addReducer('saveSession', (global, actions, payload) => {
+  const { sessionId } = payload!;
+  localStorage.setItem(GRAMJS_SESSION_ID_KEY, sessionId);
+});
+
+
+addReducer('signOut', () => {
+  const sessionId = localStorage.getItem(GRAMJS_SESSION_ID_KEY);
+  if (sessionId) {
+    localStorage.removeItem(sessionId);
+    localStorage.removeItem(GRAMJS_SESSION_ID_KEY);
+  }
+
+  getDispatch().init();
+});

+ 4 - 0
static/api.tl

@@ -1329,6 +1329,7 @@ upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<Fil
 
 help.getConfig#c4f9186b = Config;
 help.getNearestDc#1fb33026 = NearestDc;
+<<<<<<< HEAD
 help.getAppUpdate#522d5a7d source:string = help.AppUpdate;
 help.getInviteText#4d392343 = help.InviteText;
 help.getSupport#9cdf08cd = help.Support;
@@ -1347,6 +1348,9 @@ help.getSupportName#d360e72c = help.SupportName;
 help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
 help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
 
+=======
+help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
+>>>>>>> 073c3e12... GramJS: Implement signup
 channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
 channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
 channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory;