wppconnect-team / WPP4Delphi

WPP4Delphi is an open-source project with the aim of exporting functions from WhatsApp Web for Delphi, which can be used to support the creation of any interaction.
Apache License 2.0
202 stars 66 forks source link

Determine OnGetQrCode parameters #91

Open mbnoimi opened 1 month ago

mbnoimi commented 1 month ago

Hi,

I'm building my first basic example but I couldn't figure out the correct parameters of OnGetQrCode. I tried to use:

procedure(Sender: TObject; const QrCode: string; AImage: TBitmap)

but didn't work. May you please help me to fix it?

unit MaintForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  uTWPPConnect;

type
  TMainForm = class(TForm)
    btnSendMessage: TButton;
    edtPhoneNumber: TEdit;
    memoMessage: TMemo;
    lblStatus: TLabel;
    imgQrCode: TImage;
    procedure btnSendMessageClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    WPP: uTWPPConnect.TWPPConnect;
    procedure UpdateStatus(Status: string);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  {$IFDEF CEFCurrentVersion}
  ShowMessage('CEFCurrentVersion is defined');
  {$ELSE}
  ShowMessage('CEFCurrentVersion is not defined');
  {$ENDIF}

  WPP := uTWPPConnect.TWPPConnect.Create(Self);

  //-----> [dcc32 Error] MaintForm.pas(48): E2009 Incompatible types: 'Parameter lists differ'
  WPP.OnGetQrCode := procedure(Sender: TObject; const QrCode: string; AImage: TBitmap)
  begin
    imgQrCode.Picture.Assign(AImage);
  end;

  UpdateStatus('Not Connected');
end;

procedure TMainForm.UpdateStatus(Status: string);
begin
  lblStatus.Caption := 'Status: ' + Status;
end;

procedure TMainForm.btnSendMessageClick(Sender: TObject);
var
  TargetNumber, MessageText: string;
begin
  TargetNumber := edtPhoneNumber.Text + '@c.us';
  MessageText := memoMessage.Lines.Text;

  if WPP.Auth(True) then
  begin
    UpdateStatus('Connected');
    WPP.Send(TargetNumber, MessageText);
  end
  else
  begin
    UpdateStatus('Authentication required. Please scan the QR code.');
    ShowMessage('Authentication failed. Please scan the QR code.');
  end;
end;

end.
DjotaHasse commented 1 month ago

OnGetQrCode is a component event. First you must call the qrcode like this:

if not WPPWhats.Auth(false) then
begin
   WPPWhats.FormQrCodeType := TFormQrCodeType(Ft_None);
   WPPWhats.FormQrCodeStart;
end;

then in the onGetQrCode event the image will be returned:

procedure TFPrincipal2.WPPWhatsGetQrCode(const Sender: TObject; const QrCode: TResultQRCodeClass);
begin
  imgQrCode.BeginUpdate;
  try
    imgQrCode.Bitmap := Base64ToBitmap(StrAfter(QrCode.AQrCode,'base64,'));
    sleep(500);
    imgQrCode.BringToFront;
    imgQrCode.Repaint;
  finally
    imgAguardeQrCode.Visible := imgQrCode.Bitmap.IsEmpty;
    lbAguardeQrCode.Visible  := imgQrCode.Bitmap.IsEmpty;
    AnimaAguardeQrCode.Stop;
    imgQrCode.EndUpdate;
  end;
end;
mbnoimi commented 1 month ago

OnGetQrCode is a component event. First you must call the qrcode like this:

if not WPPWhats.Auth(false) then
begin
   WPPWhats.FormQrCodeType := TFormQrCodeType(Ft_None);
   WPPWhats.FormQrCodeStart;
end;

then in the onGetQrCode event the image will be returned:

procedure TFPrincipal2.WPPWhatsGetQrCode(const Sender: TObject; const QrCode: TResultQRCodeClass);
begin
  imgQrCode.BeginUpdate;
  try
    imgQrCode.Bitmap := Base64ToBitmap(StrAfter(QrCode.AQrCode,'base64,'));
    sleep(500);
    imgQrCode.BringToFront;
    imgQrCode.Repaint;
  finally
    imgAguardeQrCode.Visible := imgQrCode.Bitmap.IsEmpty;
    lbAguardeQrCode.Visible  := imgQrCode.Bitmap.IsEmpty;
    AnimaAguardeQrCode.Stop;
    imgQrCode.EndUpdate;
  end;
end;

I couldn't understand much from your suggestion because I couldn't install WPP4Delphi design-time components (couldn't find any document for installation steps and Google translate didn't help me much). For that the only option for me is trying to use it completely from the code (couldn't find suitable docs too for a quick start).

If I'm not wrong this suppose to get the benefit of component's event without the need to install it for design time.

  WPP.OnGetQrCode := procedure(Sender: TObject; const QrCode: string; AImage: TBitmap)
  begin
    imgQrCode.Picture.Assign(AImage);
  end;

But number of parameters is absolutely wrong.

So if you please try help me with my very basic example to be able run WPP4Delphi.

BTW, I couldn't run WPP4Delphi demo as well because it uses design-time components

mbnoimi commented 1 month ago

@DjotaHasse I modified my code based on your suggestion (without understand it well) but I get these errors:

Checking project dependencies...
Compiling hpcwhatsapp.dproj (Debug, Win32)
dcc32 command line for "hpcwhatsapp.dpr"
  c:\program files (x86)\embarcadero\studio\23.0\bin\dcc32.exe -$O- -$W+ -$R+ -$Q+ --no-config -M -Q -TX.exe 
  -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;
  DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;CEFCurrentVersion;;FRAMEWORK_VCL -E.\Win32\Debug -I"c:\program files 
  (x86)\embarcadero\studio\23.0\lib\Win32\debug";.\CEF4Delphi;.\CEF4Delphi\source;.\synapse;.\WPP4Delphi;.\WPP4Delphi\Source;.\WPP4Delphi\Source\JS;
  .\WPP4Delphi\Source\Model;.\WPP4Delphi\Source\Other;.\WPP4Delphi\Source\Services;.\WPP4Delphi\Source\View;.\WPP4Delphi\Packages\Compilados;
  .\WPP4Delphi\Packages\Compilados\VD29;"c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release";
  C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports;C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports\Win32;"c:\program 
  files (x86)\embarcadero\studio\23.0\Imports";C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp;"c:\program files 
  (x86)\embarcadero\studio\23.0\include" -LEC:\Users\Public\Documents\Embarcadero\Studio\23.0\Bpl 
  -LNC:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp -NU.\Win32\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;
  System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell; -O.\CEF4Delphi;.\CEF4Delphi\source;.\synapse;.\WPP4Delphi;
  .\WPP4Delphi\Source;.\WPP4Delphi\Source\JS;.\WPP4Delphi\Source\Model;.\WPP4Delphi\Source\Other;.\WPP4Delphi\Source\Services;.\WPP4Delphi\Source\View;
  .\WPP4Delphi\Packages\Compilados;.\WPP4Delphi\Packages\Compilados\VD29;"c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release";
  C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports;C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports\Win32;"c:\program 
  files (x86)\embarcadero\studio\23.0\Imports";C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp;"c:\program files 
  (x86)\embarcadero\studio\23.0\include" -R.\CEF4Delphi;.\CEF4Delphi\source;.\synapse;.\WPP4Delphi;.\WPP4Delphi\Source;.\WPP4Delphi\Source\JS;
  .\WPP4Delphi\Source\Model;.\WPP4Delphi\Source\Other;.\WPP4Delphi\Source\Services;.\WPP4Delphi\Source\View;.\WPP4Delphi\Packages\Compilados;
  .\WPP4Delphi\Packages\Compilados\VD29;"c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release";
  C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports;C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports\Win32;"c:\program 
  files (x86)\embarcadero\studio\23.0\Imports";C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp;"c:\program files 
  (x86)\embarcadero\studio\23.0\include" -U"c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\debug";.\CEF4Delphi;.\CEF4Delphi\source;.\synapse;
  .\WPP4Delphi;.\WPP4Delphi\Source;.\WPP4Delphi\Source\JS;.\WPP4Delphi\Source\Model;.\WPP4Delphi\Source\Other;.\WPP4Delphi\Source\Services;
  .\WPP4Delphi\Source\View;.\WPP4Delphi\Packages\Compilados;.\WPP4Delphi\Packages\Compilados\VD29;"c:\program files 
  (x86)\embarcadero\studio\23.0\lib\Win32\release";C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports;
  C:\Users\Administrator\Documents\Embarcadero\Studio\23.0\Imports\Win32;"c:\program files (x86)\embarcadero\studio\23.0\Imports";
  C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp;"c:\program files (x86)\embarcadero\studio\23.0\include" -V -VN 
  -NBC:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp -NHC:\Users\Public\Documents\Embarcadero\Studio\23.0\hpp\Win32 -NO.\Win32\Debug  
  hpcwhatsapp.dpr   
[dcc32 Error] MaintForm.pas(58): E2003 Undeclared identifier: 'BeginUpdate'
[dcc32 Error] MaintForm.pas(60): E2003 Undeclared identifier: 'Bitmap'
[dcc32 Error] MaintForm.pas(60): E2003 Undeclared identifier: 'StrAfter'
[dcc32 Error] MaintForm.pas(68): E2003 Undeclared identifier: 'EndUpdate'
[dcc32 Error] MaintForm.pas(70): E2010 Incompatible types: 'TOnGetQrCode' and 'Procedure'
[dcc32 Warning] MaintForm.pas(90): W1000 Symbol 'Send' is deprecated
[dcc32 Fatal Error] hpcwhatsapp.dpr(5): F2063 Could not compile used unit 'MaintForm.pas'
Failed
Elapsed time: 00:00:03.8

This is my modified code:

unit MaintForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
//   WPP4Delphi units
  uTWPPConnect.ConfigCEF, uTWPPConnect, uTWPPConnect.Constant, uTWPPConnect.JS,
  uWPPConnectDecryptFile, JsonDataObjects,
  uTWPPConnect.Console, uTWPPConnect.Diversos, uTWPPConnect.AdjustNumber,
  uTWPPConnect.Config, uTWPPConnect.Classes,
  uTWPPConnect.Emoticons;

type
  TMainForm = class(TForm)
    btnSendMessage: TButton;
    edtPhoneNumber: TEdit;
    memoMessage: TMemo;
    lblStatus: TLabel;
    imgQrCode: TImage;
    procedure btnSendMessageClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    WPP: uTWPPConnect.TWPPConnect;
    procedure UpdateStatus(Status: string);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  {$IFDEF CEFCurrentVersion}
  ShowMessage('CEFCurrentVersion is defined');
  {$ELSE}
  ShowMessage('CEFCurrentVersion is not defined');
  {$ENDIF}

  WPP := uTWPPConnect.TWPPConnect.Create(Self);

  if not WPP.Auth(false) then
  begin
     WPP.FormQrCodeType := TFormQrCodeType(Ft_None);
     WPP.FormQrCodeStart;
  end;

  WPP.OnGetQrCode := procedure(const Sender: TObject; const QrCode: TResultQRCodeClass)
  begin
//    imgQrCode.Picture.Assign(AImage);
    imgQrCode.BeginUpdate;
    try
      imgQrCode.Bitmap := Base64ToBitmap(StrAfter(QrCode.AQrCode,'base64,'));
      sleep(500);
      imgQrCode.BringToFront;
      imgQrCode.Repaint;
    finally
//      imgAguardeQrCode.Visible := imgQrCode.Bitmap.IsEmpty;
//      lbAguardeQrCode.Visible  := imgQrCode.Bitmap.IsEmpty;
//      AnimaAguardeQrCode.Stop;
      imgQrCode.EndUpdate;
    end;
  end;

  UpdateStatus('Not Connected');
end;

procedure TMainForm.UpdateStatus(Status: string);
begin
  lblStatus.Caption := 'Status: ' + Status;
end;

procedure TMainForm.btnSendMessageClick(Sender: TObject);
var
  TargetNumber, MessageText: string;
begin
  TargetNumber := edtPhoneNumber.Text + '@c.us';
  MessageText := memoMessage.Lines.Text;

  if WPP.Auth(True) then
  begin
    UpdateStatus('Connected');
    WPP.Send(TargetNumber, MessageText);
  end
  else
  begin
    UpdateStatus('Authentication required. Please scan the QR code.');
    ShowMessage('Authentication failed. Please scan the QR code.');
  end;
end;

end.
mbnoimi commented 1 month ago

I tried something silly too. I implemented Base64ToBitmap manually as I don't know the used unit in your suggestion but this lead to a new runtime error (didn't understand it):

image

unit MaintForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  uTWPPConnect.ConfigCEF, uTWPPConnect, uTWPPConnect.Constant, uTWPPConnect.JS,
  uWPPConnectDecryptFile, JsonDataObjects,
  uTWPPConnect.Console, uTWPPConnect.Diversos, uTWPPConnect.AdjustNumber,
  uTWPPConnect.Config, uTWPPConnect.Classes,
  uTWPPConnect.Emoticons, System.NetEncoding;

type
  TMainForm = class(TForm)
    btnSendMessage: TButton;
    edtPhoneNumber: TEdit;
    memoMessage: TMemo;
    lblStatus: TLabel;
    imgQrCode: TImage;
    procedure btnSendMessageClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure WPPGetQrCode(const Sender: TObject; const QrCode: TResultQRCodeClass);
    function Base64ToBitmap(const Base64: string): TBitmap;
  private
    { Private declarations }
    WPP: uTWPPConnect.TWPPConnect;
    procedure UpdateStatus(Status: string);
    function ExtractBase64(const Input: string): string;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.FormCreate(Sender: TObject);
begin
  {$IFDEF CEFCurrentVersion}
  ShowMessage('CEFCurrentVersion is defined');
  {$ELSE}
  ShowMessage('CEFCurrentVersion is not defined');
  {$ENDIF}
end;

procedure TMainForm.WPPGetQrCode(const Sender: TObject; const QrCode: TResultQRCodeClass);
begin
  imgQrCode.Picture.Bitmap.Canvas.Lock;
  try
    imgQrCode.Picture.Bitmap := Base64ToBitmap(ExtractBase64(QrCode.AQrCode));
    Sleep(500);
    imgQrCode.BringToFront;
    imgQrCode.Repaint;
  finally
    imgQrCode.Picture.Bitmap.Canvas.Unlock;
  end;
end;

function TMainForm.Base64ToBitmap(const Base64: string): TBitmap;
var
  InputStream: TStringStream;
  OutputStream: TMemoryStream;
begin
  Result := TBitmap.Create;
  InputStream := TStringStream.Create(Base64);
  OutputStream := TMemoryStream.Create;
  try
    TNetEncoding.Base64.Decode(InputStream, OutputStream);
    OutputStream.Position := 0;
    Result.LoadFromStream(OutputStream);
  finally
    InputStream.Free;
    OutputStream.Free;
  end;
end;

procedure TMainForm.UpdateStatus(Status: string);
begin
  lblStatus.Caption := 'Status: ' + Status;
end;

procedure TMainForm.btnSendMessageClick(Sender: TObject);
var
  TargetNumber, MessageText: string;
begin
//                             ShowMessage('hi');
 WPP := uTWPPConnect.TWPPConnect.Create(Self);

  if not WPP.Auth(false) then
  begin
    WPP.FormQrCodeType := TFormQrCodeType(Ft_None);
    WPP.FormQrCodeStart;
  end;

  WPP.OnGetQrCode := WPPGetQrCode;

  UpdateStatus('Not Connected');

  TargetNumber := edtPhoneNumber.Text + '@c.us';
  MessageText := memoMessage.Lines.Text;

  if WPP.Auth(True) then
  begin
    UpdateStatus('Connected');
    WPP.Send(TargetNumber, MessageText);
  end
  else
  begin
    UpdateStatus('Authentication required. Please scan the QR code.');
    ShowMessage('Authentication failed. Please scan the QR code.');
  end;
end;

function TMainForm.ExtractBase64(const Input: string): string;
begin
  Result := Copy(Input, Pos('base64,', Input) + 7, Length(Input));
end;

end.
DjotaHasse commented 1 month ago

In Project >> View Sorce, add:

if not GlobalCEFApp.StartMainProcess then
    Exit;
mbnoimi commented 1 month ago

In Project >> View Sorce, add:

Where can I find this config?

image

DjotaHasse commented 1 month ago

It's not inside options, it's Project >> View Source

mbnoimi commented 1 month ago

Thanks. Got another runtime error message: image

OnGetQrCode to be defined in this procedure! What's wrong?

procedure TMainForm.WPPGetQrCode(const Sender: TObject; const QrCode: TResultQRCodeClass);
begin
  imgQrCode.Picture.Bitmap.Canvas.Lock;
  try
    imgQrCode.Picture.Bitmap := Base64ToBitmap(ExtractBase64(QrCode.AQrCode));
    Sleep(500);
    imgQrCode.BringToFront;
    imgQrCode.Repaint;
  finally
    imgQrCode.Picture.Bitmap.Canvas.Unlock;
  end;
end;
DjotaHasse commented 1 month ago

Create the component and set OnGetQrcode in the create form to test