• R/O
  • SSH
  • HTTPS

instalikes: Commit


Commit MetaInfo

Revision6 (tree)
Zeit2019-06-10 10:49:56
Autorderekwildstar

Log Message

- Limpeza geral do código
- Melhoria no uso de headers
- Remoção da lógica que trabalhava com cookies, pois eles são gerenciados pelo WinInet automaticamente <3
- Criadas funções de parser para retornos específicos
- Aplicado flag para não guardar cache em nenhuma requisição
- Criada a pripriedade LoggedUser para guardar no DAMO as informações do usuário logado
- Agora é possível seguir todos os usuários marcados

Ändern Zusammenfassung

Diff

--- trunk/src/UDAMOPrincipal.pas (revision 5)
+++ trunk/src/UDAMOPrincipal.pas (revision 6)
@@ -45,6 +45,7 @@
4545
4646 TRelation = (rUnknown,rMoreThan,rLessThan);
4747 TBusinessAccount = (baDontCare,baInclude,baExclude);
48+ TFollowResult = (frFail,frFollowing,frRequested);
4849
4950 TAddFollowersParams = record
5051 UsersToRegister: Cardinal;
@@ -128,10 +129,19 @@
128129 FQueryHash: String;
129130 FWaitSeconds: Byte;
130131 FAddFollowersParams: TAddFollowersParams;
132+ FRolloutHash: String;
133+ FCSRFToken: String;
134+ FLoggedUser: TInstagramUser;
135+ FStopProcessing: Boolean;
131136 function UserExists(AUserName: String): Boolean;
132137 procedure LoadProfilePicture(AUserId: String; APictureURL: String; AImage: TImage);
133138 procedure DownloadProfilePicture(AUserId: String; APictureURL: String);
134139 procedure UpdateRequestsSoFar;
140+ function ParseSharedData(AResponse: TStringStream; out ASharedData: TJSONObject): Boolean;
141+ function ParseFollowersPage(AResponse: TStringStream; out AFollowersData: TJSONObject): Boolean;
142+ function ParseFollowResult(AResponse: TStringStream): TFollowResult;
143+ function ParseLoginResult(AResponse: TStringStream; out AInstagramUser: TInstagramUser): Boolean;
144+ procedure BuildRequestHeaders(AHeaders: TStrings);
135145 // Adiciona o usuário de forma completa, com as últimas mídias postadas
136146 // sendo salvas na tabela medias. Este método NÃO adiciona os seguidores do
137147 // usuário
@@ -145,62 +155,25 @@
145155 procedure SelectFollowers(AUserId: String; AKRKDBGrid: TKRKDBGrid);
146156 procedure LikeLastMedia(const AKRKDBGridUser: TKRKDBGrid);
147157 procedure FollowUsers(const AKRKDBGridUser: TKRKDBGrid);
158+ function Follow(AUserId: String): TFollowResult;
148159 procedure HandleModalResult(AInternalForm: TForm);
149-
150- { Não revisadas }
151- procedure UpdateCSRFToken(AHeaders: String);
152- procedure UpdateHeaders(AHeaders: String);
153- procedure UpdateRUR(AHeaders: String);
154- procedure UpdateSessionId(AHeaders: String);
155- procedure UpdateURLGen(AHeaders: String);
156- { Revisados }
160+ function LikeMedia(AMediaId: String; ALike: Boolean = True): Boolean;
161+ procedure GetFollowersPage(AUserId: String; var ANextPageToken: String; out AInstagramUsers: TInstagramUsers; out ATotalFollowers: Cardinal; AUsersPerPage: Byte = 50);
162+ // Obtém os dados atualizados do usuário, atualizando também as últimas
163+ // mídias do mesmo!
164+ procedure UpdateUser(const AUserName: String); overload;
165+ procedure AddFollowers(const AUserId: String; AParams: TAddFollowersParams);
157166 public
158167 { Public declarations }
159- { Lixo }
160- FSessionId: String;
161- FRUR: String;
162- FURLGen: String;
163- FCSRFToken: String;
164- FSHBID: String;
165- FSHBTS: String;
166- FDSUserId: String;
167- FMyID: String;
168- FOtherId: String;
169- FMyRealName: String;
170- FOtherRealName: String;
171- FNextPageAfter: String;
172- FFollowingCounting: Cardinal;
173- FFollowingPublicCounting: Cardinal;
174- FFollowingPrivateCounting: Cardinal;
175- FInstagramUsers: TInstagramUsers;
176- FStopProcessing: Boolean;
177168 procedure ConfigureErrorHint(ATitle, AText: String; AWinControl: TWinControl; AShowHint: Boolean);
178-
179- { Colocar como privado Revisadas }
180169 function Login(AUserName, APassword: String; out AInstagramUser: TInstagramUser): Boolean;
181- function HeaderValue(AValue: String): String;
182170 function UserInfo(AUserName: String; var AInstagramUser: TInstagramUser): Boolean;
183171 procedure Wait; { isso é gambi }
184- function LoggedUser(out AInstagramUser: TInstagramUser): Boolean;
185- function LikeMedia(AMediaId: String; ALike: Boolean = True): Boolean;
186- function Follow(AUserId: String): Boolean;
187-
188- { Colocar como privado não revisados }
189- procedure GetFollowersPage(AUserId: String;
190- var ANextPageToken: String;
191- out AInstagramUsers: TInstagramUsers;
192- out ATotalFollowers: Cardinal;
193- AUsersPerPage: Byte = 50);
172+ function GetLoggedUser(out AInstagramUser: TInstagramUser): Boolean;
194173 function Logout: Boolean;
195-
196- { Coisas revisadas }
197- // Obtém os dados atualizados do usuário, atualizando também as últimas
198- // mídias do mesmo!
199- procedure UpdateUser(const AUserName: String); overload;
200- procedure AddFollowers(const AUserId: String; AParams: TAddFollowersParams);
201174 procedure ConnectSQLite;
202-
203175 property WaitSeconds: Byte write FWaitSeconds;
176+ property LoggedUser: TInstagramUser read FLoggedUser write FLoggedUser;
204177 end;
205178
206179 var
@@ -258,6 +231,21 @@
258231 end;
259232 end;
260233
234+procedure TDAMOPrincipal.BuildRequestHeaders(AHeaders: TStrings);
235+begin
236+ AHeaders.Clear;
237+
238+ if FCSRFToken <> '' then
239+ AHeaders.Add('x-csrftoken: ' + FCSRFToken);
240+
241+ AHeaders.Add('x-ig-app-id: 936619743392459');
242+
243+ if FRolloutHash <> '' then
244+ AHeaders.Add('x-instagram-ajax: ' + FRolloutHash);
245+
246+ AHeaders.Add('x-requested-with: XMLHttpRequest');
247+end;
248+
261249 procedure TDAMOPrincipal.ACTNAddUserExecute(Sender: TObject);
262250 begin
263251 if Trim(FORMPrincipal.EDITProfile.Text) <> '' then
@@ -448,11 +436,13 @@
448436 RO.HttpOpenRequestParams.AcceptTypes := TStringList.Create;
449437 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
450438 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
439+ RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
451440 { HttpSendRequest }
452441 RO.HttpSendRequestParams.IgnoreInvalidCertificateCA := True;
453442 RE.Content := TStringStream.Create('');
454443 try
455444 Request(RO, RE);
445+ UpdateRequestsSoFar;
456446 RE.Content.Seek(0, soFromBeginning);
457447
458448 // JI := TJPEGImage.Create;
@@ -519,6 +509,7 @@
519509 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
520510 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
521511 RO.HttpOpenRequestParams.Headers := TStringList.Create;
512+ RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
522513
523514 { HttpSendRequest }
524515 RO.HttpSendRequestParams.IgnoreInvalidCertificateCA := True;
@@ -535,74 +526,66 @@
535526 RO.InternetConnectParams.ServerName := Url;
536527
537528 RO.HttpOpenRequestParams.Verb := 'GET';
538- RO.HttpOpenRequestParams.Headers.Add('sessionid: ' + HeaderValue(FSessionId));
539-// RO.HttpOpenRequestParams.Headers.Add('rur: ' + HeaderValue(FRUR));
540-// RO.HttpOpenRequestParams.Headers.Add('urlgen: ' + HeaderValue(FURLGen));
541- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
529+ BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
530+// RO.HttpOpenRequestParams.Headers.Add('sessionid: ' + HeaderValue(FSessionId));
531+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
542532
543533 try
544534 Request(RO, RE);
545535 UpdateRequestsSoFar;
546536
547- JO := TJSONObject.ParseJSONValue(TStringStream(RE.Content).DataString) as TJSONObject;
548- try
549- {"message": "rate limited", "status": "fail"}
550- if not Assigned(JO.GetValue('data')) then // para testar com assigned, não use <TJSONObject>, pois imagino que isso tentaria gerar um cast de nil, caso o nó 'data' não exista
551- begin
552- if Assigned(JO.GetValue('message')) then
553- raise Exception.Create('Não foi possível obter os dados: ' + JO.GetValue<String>('message'))
554- else
555- raise Exception.Create('Não foi possível obter os dados: Erro desconhecido')
556- end;
537+// ParseSharedData(TStringStream(RE.Content),JO);
557538
558- Followers := JO.GetValue<TJSONObject>('data').
559- GetValue<TJSONObject>('user').
560- GetValue<TJSONObject>('edge_followed_by').
561- GetValue<TJSONArray>('edges');
562- ATotalFollowers := JO.GetValue<TJSONObject>('data').
563- GetValue<TJSONObject>('user').
564- GetValue<TJSONObject>('edge_followed_by').
565- GetValue<Integer>('count');
539+ if ParseFollowersPage(TStringStream(RE.Content),JO) then
540+ try
541+ // JO := TJSONObject.ParseJSONValue(TStringStream(RE.Content).DataString) as TJSONObject;
542+ Followers := JO.GetValue<TJSONObject>('data').
543+ GetValue<TJSONObject>('user').
544+ GetValue<TJSONObject>('edge_followed_by').
545+ GetValue<TJSONArray>('edges');
546+ ATotalFollowers := JO.GetValue<TJSONObject>('data').
547+ GetValue<TJSONObject>('user').
548+ GetValue<TJSONObject>('edge_followed_by').
549+ GetValue<Integer>('count');
566550
567- if Followers.Count > 0 then
568- begin
569- if JO.GetValue<TJSONObject>('data').
570- GetValue<TJSONObject>('user').
571- GetValue<TJSONObject>('edge_followed_by').
572- GetValue<TJSONObject>('page_info').
573- GetValue<Boolean>('has_next_page') then
574- ANextPageToken := JO.GetValue<TJSONObject>('data').
575- GetValue<TJSONObject>('user').
576- GetValue<TJSONObject>('edge_followed_by').
577- GetValue<TJSONObject>('page_info').
578- GetValue<String>('end_cursor');
579-
580- for Follower in Followers do
551+ if Followers.Count > 0 then
581552 begin
582- SetLength(AInstagramUsers,Length(AInstagramUsers) + 1);
553+ if JO.GetValue<TJSONObject>('data').
554+ GetValue<TJSONObject>('user').
555+ GetValue<TJSONObject>('edge_followed_by').
556+ GetValue<TJSONObject>('page_info').
557+ GetValue<Boolean>('has_next_page') then
558+ ANextPageToken := JO.GetValue<TJSONObject>('data').
559+ GetValue<TJSONObject>('user').
560+ GetValue<TJSONObject>('edge_followed_by').
561+ GetValue<TJSONObject>('page_info').
562+ GetValue<String>('end_cursor');
583563
584- AInstagramUsers[High(AInstagramUsers)].id := Follower.GetValue<TJSONObject>('node').
585- GetValue<String>('id');
586- AInstagramUsers[High(AInstagramUsers)].IsPrivate := Follower.GetValue<TJSONObject>('node').
587- GetValue<Boolean>('is_private');
588- AInstagramUsers[High(AInstagramUsers)].IsVerified := Follower.GetValue<TJSONObject>('node').
589- GetValue<Boolean>('is_verified');
590- AInstagramUsers[High(AInstagramUsers)].PictureURL := Follower.GetValue<TJSONObject>('node').
591- GetValue<String>('profile_pic_url');
592- AInstagramUsers[High(AInstagramUsers)].RealName := Follower.GetValue<TJSONObject>('node').
593- GetValue<String>('full_name');
594- AInstagramUsers[High(AInstagramUsers)].UserName := Follower.GetValue<TJSONObject>('node').
595- GetValue<String>('username');
596- AInstagramUsers[High(AInstagramUsers)].FollowedByViewer := Follower.GetValue<TJSONObject>('node').
597- GetValue<Boolean>('followed_by_viewer');
564+ for Follower in Followers do
565+ begin
566+ SetLength(AInstagramUsers,Length(AInstagramUsers) + 1);
567+
568+ AInstagramUsers[High(AInstagramUsers)].id := Follower.GetValue<TJSONObject>('node').
569+ GetValue<String>('id');
570+ AInstagramUsers[High(AInstagramUsers)].IsPrivate := Follower.GetValue<TJSONObject>('node').
571+ GetValue<Boolean>('is_private');
572+ AInstagramUsers[High(AInstagramUsers)].IsVerified := Follower.GetValue<TJSONObject>('node').
573+ GetValue<Boolean>('is_verified');
574+ AInstagramUsers[High(AInstagramUsers)].PictureURL := Follower.GetValue<TJSONObject>('node').
575+ GetValue<String>('profile_pic_url');
576+ AInstagramUsers[High(AInstagramUsers)].RealName := Follower.GetValue<TJSONObject>('node').
577+ GetValue<String>('full_name');
578+ AInstagramUsers[High(AInstagramUsers)].UserName := Follower.GetValue<TJSONObject>('node').
579+ GetValue<String>('username');
580+ AInstagramUsers[High(AInstagramUsers)].FollowedByViewer := Follower.GetValue<TJSONObject>('node').
581+ GetValue<Boolean>('followed_by_viewer');
582+ end;
583+
584+ //ParseResponseHeaders(RE.Headers);
598585 end;
599-
600- UpdateHeaders(RE.Headers);
586+ finally
587+ JO.Free;
601588 end;
602-
603- finally
604- JO.Free;
605- end;
606589 except
607590 on E: Exception do
608591 raise EInstagram.Create(E.Message);
@@ -620,12 +603,12 @@
620603 FAddFollowersParams := TFORMAddUserParams(AInternalForm).AddFollowersParams;
621604 end;
622605
623-function TDAMOPrincipal.HeaderValue(AValue: String): String;
624-begin
625- Result := AValue;
626- if Result = '' then
627- Result := '""';
628-end;
606+//function TDAMOPrincipal.HeaderValue(AValue: String): String;
607+//begin
608+// Result := AValue;
609+// if Result = '' then
610+// Result := '""';
611+//end;
629612
630613 procedure TDAMOPrincipal.ACTNAddFollowersExecute(Sender: TObject);
631614 begin
@@ -675,7 +658,7 @@
675658 Text := Sender.AsString;
676659 end;
677660
678-function TDAMOPrincipal.Follow(AUserId: String): Boolean;
661+function TDAMOPrincipal.Follow(AUserId: String): TFollowResult;
679662 var
680663 RO: TRequestOptions;
681664 RE: TResponse;
@@ -704,9 +687,9 @@
704687 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
705688 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
706689 RO.HttpOpenRequestParams.Headers := TStringList.Create;
690+ BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
707691 RO.HttpOpenRequestParams.Headers.Add('content-type: application/x-www-form-urlencoded');
708- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
709-// RO.HttpOpenRequestParams.Headers.Add('referer: https://www.instagram.com/neymarjr');
692+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
710693 RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
711694
712695 { HttpSendRequest }
@@ -716,9 +699,9 @@
716699 try
717700 Request(RO, RE);
718701 UpdateRequestsSoFar;
702+ //ParseSharedData(TStringStream(RE.Content),JO);
719703
720- Result := True;
721-// Result := TStringStream(RE.Content).DataString = '{"result": "requested", "status": "ok"}';
704+ Result := ParseFollowResult(TStringStream(RE.Content));
722705 finally
723706 RE.Content.Free;
724707 RO.HttpOpenRequestParams.Headers.Free;
@@ -731,7 +714,7 @@
731714 var
732715 NPT: String;
733716 Followers: TInstagramUsers;
734- RT: Cardinal;
717+ TotalFollowers: Cardinal;
735718 i: Byte;
736719 UseExtendedFilters: Boolean;
737720 FB: TKRKFormBlender;
@@ -767,7 +750,7 @@
767750 Break;
768751
769752 // Obtém uma página de seguidores com 50 seguidores no máximo
770- GetFollowersPage(AUserId,NPT,Followers,RT);
753+ GetFollowersPage(AUserId,NPT,Followers,TotalFollowers);
771754
772755 // Caso haja seguidores, faz algo
773756 if Length(Followers) > 0 then
@@ -862,11 +845,20 @@
862845 if AParams.UsersToRegister = 0 then
863846 Break;
864847 end;
865- end;
848+ end
849+ // Quando nenhum seguidor é retornado, mas o usuário possui seguidores,
850+ // significa que ele tem uma conta privada e nós não o seguimos
851+ else if TotalFollowers > 0 then
852+ Break;
853+
854+
866855 Inc(Page);
867856 until (NPT = '') or (AParams.UsersToRegister = 0);
868857 // - ///////////////////////////////////////////////////////////////////////
869- Application.MessageBox('Operation finalized!','Success!',MB_ICONINFORMATION);
858+ if Length(Followers) > 0 then
859+ Application.MessageBox('Operation finalized!','Success!',MB_ICONINFORMATION)
860+ else if TotalFollowers > 0 then
861+ Application.MessageBox('The user has followers but its followers list is hidden probably because this user has a private account and you do not follow him. Consider follow him before acquiring his followers','Fail!',MB_ICONWARNING)
870862 finally
871863 FB.Close;
872864 FB.Free; // O FormBlender não é autodestrutível. Veja comentário sobre o Action := caFree;
@@ -883,7 +875,6 @@
883875 var
884876 RO: TRequestOptions;
885877 RE: TResponse;
886- JS: String;
887878 JO: TJSONObject;
888879 JA: TJSONArray;
889880 i: Byte;
@@ -914,7 +905,8 @@
914905 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
915906 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
916907 RO.HttpOpenRequestParams.Headers := TStringList.Create;
917- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
908+ BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
909+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
918910 RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
919911
920912 { HttpSendRequest }
@@ -925,17 +917,20 @@
925917 try
926918 Request(RO, RE);
927919 UpdateRequestsSoFar;
920+ // ParseSharedData(TStringStream(RE.Content),JO);
928921
922+ //Result := RegExMatch(TStringStream(RE.Content).DataString,'window\._sharedData = ({.*})',1,1,False,[],JS);
923+
929924 // Aparentemente isso não é bom para detectar se a função como um todo
930925 // retorna true, pois o fato de haver este JSON pode não ser condição para
931926 // dados foram obtidos. As chamadas JSON ali adiante, podem levantar exceções
932927 // Mais do que nunca, crie uma exceção personalizada para resolver este problema
933928 // e escolha ao menos um atributo do JSON para indicar o sucesso desta função
934- Result := RegExMatch(TStringStream(RE.Content).DataString,'window\._sharedData = ({.*})',1,1,False,[],JS);
929+ Result := ParseSharedData(TStringStream(RE.Content),JO);
935930
936931 if Result then
937932 begin
938- JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
933+// JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
939934 try
940935 AInstagramUser.id := JO.GetValue('entry_data').
941936 GetValue<TJSONArray>('ProfilePage').Items[0].
@@ -1041,51 +1036,88 @@
10411036 end;
10421037 end;
10431038
1044-procedure TDAMOPrincipal.UpdateCSRFToken(AHeaders: String);
1039+function TDAMOPrincipal.ParseSharedData(AResponse: TStringStream; out ASharedData: TJSONObject): Boolean;
10451040 var
1046- Value: String;
1041+ JS: String;
10471042 begin
1048- if RegExMatch(AHeaders,'csrftoken="?([^"]*)"?;',1,1,True,[preUnGreedy],Value) then
1049- FCSRFToken := Value;
1043+ ASharedData := nil;
1044+ Result := RegExMatch(AResponse.DataString,'window\._sharedData = ({.*})',1,1,False,[],JS);
1045+ if Result then
1046+ begin
1047+ ASharedData := TJSONObject.ParseJSONValue(JS) as TJSONObject;
1048+ FRolloutHash := ASharedData.GetValue('rollout_hash').Value;
1049+ FCSRFToken := ASharedData.GetValue('config').GetValue<String>('csrf_token');
1050+ end;
10501051 end;
10511052
1052-procedure TDAMOPrincipal.UpdateHeaders(AHeaders: String);
1053+function TDAMOPrincipal.ParseFollowersPage(AResponse: TStringStream; out AFollowersData: TJSONObject): Boolean;
1054+var
1055+ JS: String;
10531056 begin
1054- UpdateSessionId(AHeaders);
1055- UpdateRUR(AHeaders);
1056- UpdateURLGen(AHeaders);
1057- UpdateCSRFToken(AHeaders);
1058-// UpdateRolloutHash()
1059-end;
1057+ AFollowersData := nil;
1058+ Result := RegExMatch(AResponse.DataString,'({.*})',1,1,False,[],JS);
1059+ if Result then
1060+ begin
1061+ AFollowersData := TJSONObject.ParseJSONValue(JS) as TJSONObject;
10601062
1061-procedure TDAMOPrincipal.UpdateRequestsSoFar;
1062-begin
1063- Inc(FRequestsSoFar);
1064- FORMPrincipal.STBA.Panels[0].Text := FRequestsSoFar.ToString + ' requests so far...';
1063+ {"message": "rate limited", "status": "fail"}
1064+ if not Assigned(AFollowersData.GetValue('data')) then // para testar com assigned, não use <TJSONObject>, pois imagino que isso tentaria gerar um cast de nil, caso o nó 'data' não exista
1065+ begin
1066+ if Assigned(AFollowersData.GetValue('message')) then
1067+ raise Exception.Create('Não foi possível obter os dados: ' + AFollowersData.GetValue<String>('message'))
1068+ else
1069+ raise Exception.Create('Não foi possível obter os dados: Erro desconhecido')
1070+ end;
1071+ end;
10651072 end;
10661073
1067-procedure TDAMOPrincipal.UpdateRUR(AHeaders: String);
1074+function TDAMOPrincipal.ParseFollowResult(AResponse: TStringStream): TFollowResult;
10681075 var
1069- Value: String;
1076+ JS: String;
1077+ JO: TJSONObject;
10701078 begin
1071- if RegExMatch(AHeaders,'rur="?([^"]*)"?;',1,1,True,[preUnGreedy],Value) then
1072- FRUR := Value;
1079+ Result := frFail;
1080+
1081+ if RegExMatch(AResponse.DataString,'({.*})',1,1,False,[],JS) then
1082+ begin
1083+ JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
1084+
1085+ if JO.GetValue('status').Value = 'ok' then
1086+ begin
1087+ if JO.GetValue('result').Value = 'requested' then
1088+ Result := frRequested
1089+ else if JO.GetValue('result').Value = 'following' then
1090+ Result := frFollowing;
1091+ end
1092+ end;
10731093 end;
10741094
1075-procedure TDAMOPrincipal.UpdateSessionId(AHeaders: String);
1095+function TDAMOPrincipal.ParseLoginResult(AResponse: TStringStream; out AInstagramUser: TInstagramUser): Boolean;
10761096 var
1077- Value: String;
1097+ JS: String;
1098+ JO: TJSONObject;
10781099 begin
1079- if RegExMatch(AHeaders,'sessionid="?([^"]*)"?;',1,1,True,[preUnGreedy],Value) then
1080- FSessionId := Value;
1100+ Result := False;
1101+
1102+ if RegExMatch(AResponse.DataString,'({.*})',1,1,False,[],JS) then
1103+ begin
1104+ JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
1105+ Result := (not (JO.GetValue('authenticated') is TJSONNull)) and (JO.GetValue('authenticated').Value = 'true') and GetLoggedUser(AInstagramUser);
1106+ end;
1107+
1108+ // O resultado de um login bem sucedido é
1109+ // {"authenticated": true, "user": true, "userId": "1355122894", "oneTapPrompt": false, "fr": "ASBX8CUusfR8ZedI3ByKovdcVXKVCbBUYAXaXAMqtuMdFO87yXixmQ0FLtK5LkkCz9AvlyfP5EIsEsADY1WTJqBaaEwuT0r0Asq2kVccC9NPVAZDKrGYGAXXbtZi1RmjI29uIQ", "reactivated": true, "status": "ok"}
1110+ // user = true significa que o usuario informado existe
1111+
1112+ // Caso o login seja chamado e o usuário já esteja logado (já possua cookies
1113+ // salvos no WinInet), o retorno será
1114+ // {"authenticated": true, "status": "ok"}
10811115 end;
10821116
1083-procedure TDAMOPrincipal.UpdateURLGen(AHeaders: String);
1084-var
1085- Value: String;
1117+procedure TDAMOPrincipal.UpdateRequestsSoFar;
10861118 begin
1087- if RegExMatch(AHeaders,'urlgen=(".*");',1,1,True,[preUnGreedy],Value) then
1088- FURLGen := Value;
1119+ Inc(FRequestsSoFar);
1120+ FORMPrincipal.STBA.Panels[0].Text := FRequestsSoFar.ToString + ' requests so far...';
10891121 end;
10901122
10911123 procedure TDAMOPrincipal.UpdateUser(const AInstagramUser: TInstagramUser);
@@ -1125,11 +1157,10 @@
11251157 // Todas as chamadas que usam JSON sabem quem é o usuário que está executando a
11261158 // ação, que é o usuário logado. O nó, config.viewer tem esta informação. A
11271159 // função abaixo serve apenas para verificar de forma exclusiva esta informação
1128-function TDAMOPrincipal.LoggedUser(out AInstagramUser: TInstagramUser): Boolean;
1160+function TDAMOPrincipal.GetLoggedUser(out AInstagramUser: TInstagramUser): Boolean;
11291161 var
11301162 RO: TRequestOptions;
11311163 RE: TResponse;
1132- JS: String;
11331164 JO: TJSONObject;
11341165 begin
11351166 ZeroMemory(@AInstagramUser,SizeOf(TInstagramUser));
@@ -1165,13 +1196,16 @@
11651196 UpdateRequestsSoFar;
11661197 // Precisa UpdateHeaders porque esta função é usada ao iniciar o programa
11671198 // para pegar os cabeçalhos de quem estiver logado
1168- UpdateHeaders(RE.Headers);
1199+ // ParseResponseHeaders(RE.Headers);
1200+ //ParseSharedData(TStringStream(RE.Content),JO);
11691201
1170- Result := RegExMatch(TStringStream(RE.Content).DataString,'window\._sharedData = ({.*})',1,1,False,[],JS);
1202+ //Result := RegExMatch(TStringStream(RE.Content).DataString,'window\._sharedData = ({.*})',1,1,False,[],JS);
11711203
1204+ Result := ParseSharedData(TStringStream(RE.Content),JO);
1205+
11721206 if Result then
11731207 begin
1174- JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
1208+// JO := TJSONObject.ParseJSONValue(JS) as TJSONObject;
11751209 try
11761210 Result := not (JO.GetValue('config').GetValue<TJSONValue>('viewer') is TJSONNull);
11771211
@@ -1252,7 +1286,8 @@
12521286 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
12531287 RO.HttpOpenRequestParams.Headers := TStringList.Create;
12541288 // RO.HttpOpenRequestParams.Headers.Add('content-type: application/x-www-form-urlencoded');
1255- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
1289+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
1290+ BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
12561291 RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
12571292
12581293 { HttpSendRequest }
@@ -1262,6 +1297,7 @@
12621297 try
12631298 Request(RO, RE);
12641299 UpdateRequestsSoFar;
1300+ // ParseSharedData(TStringStream(RE.Content),JO);
12651301
12661302 Result := TStringStream(RE.Content).DataString = '{"status": "ok"}';
12671303 finally
@@ -1299,6 +1335,7 @@
12991335 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
13001336 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
13011337 RO.HttpOpenRequestParams.Headers := TStringList.Create;
1338+ RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
13021339
13031340 { HttpSendRequest }
13041341 RO.HttpSendRequestParams.IgnoreInvalidCertificateCA := True;
@@ -1305,47 +1342,33 @@
13051342
13061343 RE.Content := TStringStream.Create('');
13071344 try
1308- // Acessa a página inicial deslogado e obtém alguns headers
1345+ { TODO : Substituir o abaixo por islogged? }
1346+ // Acessa a página inicial deslogado e obtém alguns headers ================
13091347 RO.InternetConnectParams.ServerName := 'https://www.instagram.com';
13101348 RO.HttpOpenRequestParams.Verb := 'GET';
13111349 Request(RO, RE);
13121350 UpdateRequestsSoFar;
1313- UpdateHeaders(RE.Headers);
1351+ //ParseResponseHeaders(RE.Headers);
1352+ ParseSharedData(TStringStream(RE.Content),JO); // Só precisa disso para preencher configurar FRolloutHash e FCSRFToken
13141353 TStringStream(RE.Content).Clear;
1354+ // =========================================================================
13151355
1316- // Acessa a página de login
1356+ // Acessa a página de login ================================================
13171357 RO.InternetConnectParams.ServerName := 'https://www.instagram.com/accounts/login/ajax/';
13181358 RO.HttpOpenRequestParams.Verb := 'POST';
1359+ BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
13191360 RO.HttpOpenRequestParams.Headers.Add('Content-Type: application/x-www-form-urlencoded; charset=utf-8');
13201361 // RO.HttpOpenRequestParams.Headers.Add('sessionid: ' + HeaderValue(FSessionId));
13211362 // RO.HttpOpenRequestParams.Headers.Add('rur: ' + HeaderValue(FRUR));
13221363 // RO.HttpOpenRequestParams.Headers.Add('urlgen: ' + HeaderValue(FURLGen));
1323- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
1364+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken));
13241365 RO.Content := TStringStream.Create('username=' + AUserName +'&password=' + APassword + '&queryParams=%7B%7D');
13251366
13261367 Request(RO,RE);
1368+ UpdateRequestsSoFar;
1369+ //ParseSharedData(TStringStream(RE.Content),JO);
13271370
1328- (*
1329- O resultado de um login bem sucedido é
1330-
1331- {"authenticated": true, "user": true, "userId": "1355122894", "oneTapPrompt": false, "fr": "ASBX8CUusfR8ZedI3ByKovdcVXKVCbBUYAXaXAMqtuMdFO87yXixmQ0FLtK5LkkCz9AvlyfP5EIsEsADY1WTJqBaaEwuT0r0Asq2kVccC9NPVAZDKrGYGAXXbtZi1RmjI29uIQ", "reactivated": true, "status": "ok"}
1332-
1333- user = true significa que o usuario informado existe
1334- *)
1335-
1336- JO := TJSONObject.ParseJSONValue(TStringStream(RE.Content).DataString) as TJSONObject;
1337- try
1338- Result := (not (JO.GetValue('authenticated') is TJSONNull)) and (JO.GetValue<String>('authenticated') = 'true');
1339-
1340- if Result then
1341- begin
1342- UpdateHeaders(RE.Headers);
1343-
1344- AInstagramUser.id := JO.GetValue<String>('userId');
1345- end;
1346- finally
1347- JO.Free;
1348- end;
1371+ Result := ParseLoginResult(TStringStream(RE.Content),AInstagramUser);
13491372 finally
13501373 RE.Content.Free;
13511374 RO.HttpOpenRequestParams.Headers.Free;
@@ -1383,14 +1406,16 @@
13831406 RO.HttpOpenRequestParams.AcceptTypes.Text := '*/*';
13841407 RO.HttpOpenRequestParams.AutoDetectHTTPS := True;
13851408 RO.HttpOpenRequestParams.Headers := TStringList.Create;
1409+// BuildRequestHeaders(RO.HttpOpenRequestParams.Headers);
13861410 RO.HttpOpenRequestParams.Headers.Add('content-type: application/x-www-form-urlencoded');
1387- RO.HttpOpenRequestParams.Headers.Add('shbid: ' + HeaderValue(FSHBID));
1388- RO.HttpOpenRequestParams.Headers.Add('shbts: ' + HeaderValue(FSHBTS));
1389- RO.HttpOpenRequestParams.Headers.Add('rur: ' + HeaderValue(FRUR));
1390- RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken)); { X- ??}
1391- RO.HttpOpenRequestParams.Headers.Add('ds_user_id: ' + HeaderValue(FDSUserId));
1392- RO.HttpOpenRequestParams.Headers.Add('sessionid: ' + HeaderValue(FSessionId));
1393- RO.HttpOpenRequestParams.Headers.Add('urlgen: ' + HeaderValue(FURLGEN));
1411+// RO.HttpOpenRequestParams.Headers.Add('shbid: ' + HeaderValue(FSHBID));
1412+// RO.HttpOpenRequestParams.Headers.Add('shbts: ' + HeaderValue(FSHBTS));
1413+// RO.HttpOpenRequestParams.Headers.Add('rur: ' + HeaderValue(FRUR));
1414+// RO.HttpOpenRequestParams.Headers.Add('x-csrftoken: ' + HeaderValue(FCSRFToken)); { X- ??}
1415+// RO.HttpOpenRequestParams.Headers.Add('ds_user_id: ' + HeaderValue(FDSUserId));
1416+// RO.HttpOpenRequestParams.Headers.Add('sessionid: ' + HeaderValue(FSessionId));
1417+// RO.HttpOpenRequestParams.Headers.Add('urlgen: ' + HeaderValue(FURLGEN));
1418+ RO.HttpOpenRequestParams.Flags := INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE;
13941419
13951420 { HttpSendRequest }
13961421 RO.HttpSendRequestParams.IgnoreInvalidCertificateCA := True;
@@ -1399,8 +1424,14 @@
13991424 try
14001425 Request(RO, RE);
14011426 UpdateRequestsSoFar;
1402- UpdateHeaders(RE.Headers);
1403- Result := not LoggedUser(Dummy);
1427+ //ParseResponseHeaders(RE.Headers);
1428+ //ParseSharedData(TStringStream(RE.Content),JO);
1429+ Result := not GetLoggedUser(Dummy);
1430+
1431+ // Limpa os valores dos headers principais! Tem que ser depois de
1432+ // LoggedUser, porque esta função preenche novamente estas duas variáveis
1433+ FRolloutHash := '';
1434+ FCSRFToken := '';
14041435 finally
14051436 RE.Content.Free;
14061437 RO.HttpOpenRequestParams.Headers.Free;
@@ -1535,7 +1566,7 @@
15351566 begin
15361567 if AKRKDBGridUser.SelectedRows.CurrentRowSelected then
15371568 begin
1538- if Follow(FDTAUserid.AsString) then
1569+ if Follow(FDTAUserid.AsString) in [frRequested,frFollowing] then
15391570 Inc(Followed);
15401571
15411572 FS.LABEStatus.Caption := Followed.ToString + ' / ' + AKRKDBGridUser.SelectedRows.Count.ToString;
@@ -1634,30 +1665,70 @@
16341665 end;
16351666 end;
16361667
1637-//neymarjr
1638-//https://www.instagram.com/web/friendships/26669533/follow/
1639-//
1640-//_nakedwitch_
1641-//https://www.instagram.com/web/friendships/10178708069/follow/
1642-//
1643-//:authority: www.instagram.com
1644-//:method: POST
1645-//:path: /web/friendships/10178708069/follow/
1646-//:scheme: https
1647-//accept: */*
1648-//accept-encoding: gzip, deflate, br
1649-//accept-language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7
1650-//cache-control: no-cache
1651-//content-length: 0
1652-//content-type: application/x-www-form-urlencoded
1653-//cookie: mid=WTwgTAALAAEG3-DlXp-Pl-AT1OYz; mcd=3; fbm_124024574287414=base_domain=.instagram.com; shbid=10819; shbts=1559698631.3146431; rur=FRC; fbsr_124024574287414=nDFI1WH5k3vX8pSxqrpCHTRHS4g5ef_ZoqAOQCMMQ44.eyJjb2RlIjoiQVFENjloLW5VWFlEOWhoV24wMWdsYkY1T25kazV3V0kwNEN5MTkyYVBheERDamZsR0REYXRsaXVISEduSmJzNXI4SEJJXzBpd1dVQ1BVSEJTTmRXU25lckZfbGQyR2xtWHpBWlhabnRrQzg3cmpBYXNBRWU1XzZNUlZsRFl5N1p4S3FjRFJRclZGLTBTa0l2Skh3Y0FwU211NDFIVDBNUjNCWDQ5eU56NkN4Wkc1dTNfQVBmT2o2RG9FbzNsOVYwZEs5dHJXZmhnYkZjVDB4SzRyWVI0bkg4Q2VoY1J3Z0VnM0pid1VQb0tuY0xLUDBvVHNDOUwxOVA4blJReWxKUFZuYXhrb1cyTS1wMzlTTm9tZWNGb2hySU9pMHdVZzNvc0g0SURyUXA4NDBSRzhGTEJKUlJsY0Zqamd6U254eHQzanciLCJ1c2VyX2lkIjoiNjg0NDcxOTIzIiwiYWxnb3JpdGhtIjoiSE1BQy1TSEEyNTYiLCJpc3N1ZWRfYXQiOjE1NTk2OTg4NzJ9; csrftoken=z0AWYYAIcu40OcpltZqtq9FHsF5TrIyN; ds_user_id=1355122894; sessionid=1355122894%3Alp0w7wSzJNayEy%3A17; urlgen="{\"187.112.20.96\": 10429\054 \"177.207.5.72\": 18881\054 \"187.113.108.57\": 18881}:1hYKw7:spYTfWoyH5Hzy8HkKFZdUGRYOD4"
1654-//origin: https://www.instagram.com
1655-//pragma: no-cache
1656-//referer: https://www.instagram.com/_nakedwitch_/
1657-//user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.109
1658-//x-csrftoken: z0AWYYAIcu40OcpltZqtq9FHsF5TrIyN
1659-//x-ig-app-id: 936619743392459
1660-//x-instagram-ajax: e6864ac8b8b5
1661-//x-requested-with: XMLHttpRequest
1668+(*
16621669
1670+Comentários são feitos em mídias. Obtenha as midias do usuário. cada uma delas
1671+tem um id. use este id para acessar enviar um comentário para a a midia
1672+A pagina da midia mostra todos os comentários e também mostra se existem mais
1673+comentários ou não. A linha abaixo está em end_cursor.
1674+
1675+
1676+{\"cached_comments_cursor\": \"17893719769327605\", \"bifilter_token\": \"KDABDABQACAAEAAIAAgACAAr__ntnf_f_y_np1_t3GZmVO__7f23_8t9-3iv31bBSAQA\"}"
1677+
1678+Não sei o que significa ao certo mas esta linha aparece de forma codificada no
1679+url que é chamado para obter a próxima leva de comentários, que pode ser visto
1680+abaixo
1681+
1682+https://www.instagram.com/graphql/query/?query_hash=97b41c52301f77ce508f55e66d17620e&variables=%7B%22shortcode%22%3A%22ByV7HcxAhiQ%22%2C%22first%22%3A12%2C%22after%22%3A%22%7B%5C%22cached_comments_cursor%5C%22%3A+%5C%2217893719769327605%5C%22%2C+%5C%22bifilter_token%5C%22%3A+%5C%22KDABDABQACAAEAAIAAgACAAr__ntnf_f_y_np1_t3GZmVO__7f23_8t9-3iv31bBSAQA%5C%22%7D%22%7D
1683+
1684+acima, variables é a parte codificada da requisição, e que é:
1685+
1686+%7B%22shortcode%22%3A%22ByV7HcxAhiQ%22%2C%22first%22%3A12%2C%22after%22%3A%22%7B%5C%22cached_comments_cursor%5C%22%3A+%5C%2217893719769327605%5C%22%2C+%5C%22bifilter_token%5C%22%3A+%5C%22KDABDABQACAAEAAIAAgACAAr__ntnf_f_y_np1_t3GZmVO__7f23_8t9-3iv31bBSAQA%5C%22%7D%22%7D
1687+
1688+O texto está codificado, e ao decodificar, temos um JSON escapado, com o
1689+shortcode da midia. First deve ser para mostrar os 12 primeiros comentários.
1690+after contém exatamente o valor do end_cursor!
1691+
1692+{"shortcode":"ByV7HcxAhiQ","first":12,"after":"{\"cached_comments_cursor\": \"17893719769327605\", \"bifilter_token\": \"KDABDABQACAAEAAIAAgACAAr__ntnf_f_y_np1_t3GZmVO__7f23_8t9-3iv31bBSAQA\"}"}
1693+
1694+A resposta a chamada do url anterior é um JSON que contém outros nós de
1695+comentários e outro end_cursor para repetir o ciclo. Acredito que seja possível
1696+chamar de primeira a página
1697+
1698+https://www.instagram.com/graphql/query/
1699+
1700+e obter o que se precisa sem precisar parsear uma página antes
1701+
1702+A PÁGINA ABAIXO É CAPAZ DE OBTER A PRIMEIRA PÁGINA!!
1703+
1704+https://www.instagram.com/graphql/query/?query_hash=97b41c52301f77ce508f55e66d17620e&variables=%7B%22shortcode%22%3A%22ByV7HcxAhiQ%22%2C%22first%22%3A12%7D
1705+
1706+acima, variables={"shortcode":"ByV7HcxAhiQ","first":12}, para ir pra próxima
1707+página basta incluir "after" e conteúdo de end_cursor
1708+
1709+funciona da mesma forma que GetFollowersPage :)
1710+
1711+
1712+-----
1713+Para comentar, enviar um post para https://www.instagram.com/web/comments/2056887849973920214/add/
1714+o numero deve ser o mediaid
1715+
1716+usar este header
1717+
1718+content-type: application/x-www-form-urlencoded
1719+
1720+com este conteudo
1721+
1722+comment_text=mais+um&replied_to_comment_id=
1723+
1724+replied_to_comment_id pode ser vazio, para um comentário puro ou ter o id de um comentário anterior para o qual se quer responder
1725+
1726+A resposta bem sucedida é um JSON como abaixo
1727+
1728+{"id": "17848137289461955", "from": {"id": "1355122894", "username": "sauroneye", "full_name": "Sauron Eye", "profile_picture": "https://instagram.frec3-1.fna.fbcdn.net/vp/f80e9ecaa9f79803065451c09c764a92/5D9F39F4/t51.2885-19/10268826_621796717905448_121416242_a.jpg?_nc_ht=instagram.frec3-1.fna.fbcdn.net"}, "text": "mais um", "created_time": 1560126906, "status": "ok"}
1729+
1730+*)
1731+
16631732 end.
1733+
1734+
--- trunk/src/UFORMPrincipal.pas (revision 5)
+++ trunk/src/UFORMPrincipal.pas (revision 6)
@@ -94,26 +94,28 @@
9494
9595 procedure TFORMPrincipal.BUTNLogarClick(Sender: TObject);
9696 var
97- UI: TInstagramUser;
97+ IU: TInstagramUser;
9898 begin
99- TASHLogado.TabVisible := DAMOPrincipal.Login(LAEDUserName1.Text,LAEDPassword.Text, UI);
99+ TASHLogado.TabVisible := DAMOPrincipal.Login(LAEDUserName1.Text,LAEDPassword.Text, IU);
100+ TASHUser.TabVisible := TASHLogado.TabVisible;
101+ TASHConfigurations.TabVisible := not TASHLogado.TabVisible;
102+ DAMOPrincipal.LoggedUser := IU;
100103
101104 if TASHLogado.TabVisible then
102105 begin
103- DAMOPrincipal.UserInfo(LAEDUserName1.Text,UI);
104- DAMOPrincipal.FMyId := UI.id;
105- DAMOPrincipal.FMyRealName := UI.RealName;
106- LABEId.Caption := DAMOPrincipal.FMyID;
107- LABEUserName.Caption := UI.UserName;
108- LABERealName.Caption := DAMOPrincipal.FMyRealName;
109- LABEBiography.Caption := UI.Biography;
110- LABEProfilePicURL.Caption := UI.PictureURL;
106+ LABEId.Caption := DAMOPrincipal.LoggedUser.id;
107+ LABEUserName.Caption := DAMOPrincipal.LoggedUser.UserName;
108+ LABERealName.Caption := DAMOPrincipal.LoggedUser.RealName;
109+ LABEBiography.Caption := DAMOPrincipal.LoggedUser.Biography;
110+ LABEProfilePicURL.Caption := DAMOPrincipal.LoggedUser.PictureURL;
111111 end;
112112 end;
113113
114114 procedure TFORMPrincipal.BUTNLogoutClick(Sender: TObject);
115115 begin
116- TASHLogado.TabVisible := DAMOPrincipal.Logout;
116+ TASHLogado.TabVisible := not DAMOPrincipal.Logout;
117+ TASHUser.TabVisible := TASHLogado.TabVisible;
118+ TASHConfigurations.TabVisible := not TASHLogado.TabVisible;
117119
118120 if TASHLogado.TabVisible then
119121 Application.MessageBox('Não foi possível deslogar','Algo errado não está certo',MB_ICONERROR);
@@ -134,17 +136,20 @@
134136 var
135137 IU: TInstagramUser;
136138 begin
137- TASHLogado.TabVisible := DAMOPrincipal.LoggedUser(IU);
139+ // O usuário pode já estar logado por conta dos Cookies que o WinInet gerencia
140+ // automaticamente!
141+ TASHLogado.TabVisible := DAMOPrincipal.GetLoggedUser(IU);
142+ TASHUser.TabVisible := TASHLogado.TabVisible;
143+ TASHConfigurations.TabVisible := not TASHLogado.TabVisible;
144+ DAMOPrincipal.LoggedUser := IU;
138145
139146 if TASHLogado.TabVisible then
140147 begin
141- DAMOPrincipal.FMyID := IU.id;
142- DAMOPrincipal.FMyRealName := IU.RealName;
143- LABEId.Caption := DAMOPrincipal.FMyID;
144- LABEUserName.Caption := IU.UserName;
145- LABERealName.Caption := DAMOPrincipal.FMyRealName;
146- LABEBiography.Caption := IU.Biography;
147- LABEProfilePicURL.Caption := Iu.PictureURL;
148+ LABEId.Caption := DAMOPrincipal.LoggedUser.id;
149+ LABEUserName.Caption := DAMOPrincipal.LoggedUser.UserName;
150+ LABERealName.Caption := DAMOPrincipal.LoggedUser.RealName;
151+ LABEBiography.Caption := DAMOPrincipal.LoggedUser.Biography;
152+ LABEProfilePicURL.Caption := DAMOPrincipal.LoggedUser.PictureURL;
148153 end;
149154 end;
150155
--- trunk/src/UFORMStatus.pas (revision 5)
+++ trunk/src/UFORMStatus.pas (revision 6)
@@ -22,3 +22,4 @@
2222 {$R *.dfm}
2323
2424 end.
25+
Show on old repository browser