unit uFrmMain;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes, System.UITypes,
  System.Threading, System.Generics.Collections, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Imaging.pngimage,
  Vcl.Buttons, uTInject, uInjectDecryptFile, ShellApi,
  uTInject.Constant, uTInject.Classes, uDmMain, UTransacaoDb,

  //Rsc.Vcl.ShellObjHelper, ERA ESSE AQUI LÁ ERA SO UMA FIRULA

  Vcl.WinXPanels, Vcl.WinXCtrls, Data.DB, Vcl.Grids, Vcl.DBGrids,
  FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
  FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.Comp.DataSet,
  FireDAC.Comp.Client, FireDAC.UI.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Phys, FireDAC.Phys.FB, FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait,
  Vcl.DBCtrls, Vcl.Dialogs, REST.Types, REST.Client, Data.Bind.Components,
  Data.Bind.ObjectScope, System.JSON, REST.Authenticator.OAuth,
  System.NetEncoding, System.IOUtils, System.StrUtils, dxGDIPlusClasses,
  Vcl.AppEvnts, Vcl.Menus, System.ImageList, Vcl.ImgList, acPNG, ushldlg


  ;



type
  TFrmMain = class(TForm)
    pnl_Title: TPanel;
    Label1: TLabel;
    Panel3: TPanel;
    Panel4: TPanel;
    Label2: TLabel;
    Label3: TLabel;
    injct_1: TInject;
    Panel5: TPanel;
    CrdPnl_Main: TCardPanel;
    Crd_AutenticaWhatsApp: TCard;
    img_AutenticaQrCod: TImage;
    Crd_Principal: TCard;
    lbl_statusTinject: TLabel;
    lbl_NumerAutenticado: TLabel;
    Label5: TLabel;
    ActivityIndicator1: TActivityIndicator;
    tmr_MostarQrCod: TTimer;
    pnl_QrCodeAuth: TPanel;
    Crd_Atualizar_Contatos: TCard;
    Crd_CadastrarMensagem: TCard;
    SpeedButton3: TSpeedButton;
    DBGClientes: TDBGrid;
    DsClientes: TDataSource;
    FDQClientes: TFDQuery;
    img_Status: TImage;
    Panel2: TPanel;
    SpeedButton4: TSpeedButton;
    Panel6: TPanel;
    sbtn_MonitBanc: TSpeedButton;
    DBText1: TDBText;
    Label4: TLabel;
    mm_MsgSalvarBanco: TMemo;
    Label6: TLabel;
    SpeedButton2: TSpeedButton;
    CheckBox1: TCheckBox;
    lbl_camihoAnexo: TLabel;
    Label7: TLabel;
    sbtn_OpenCaminhoAnexo: TSpeedButton;
    OpenDialog1: TOpenDialog;
    SpeedButton5: TSpeedButton;
    tm_MonitoraBanco: TTimer;
    lbl_StatusEnvio: TLabel;
    Memo1: TMemo;
    RESTClient1: TRESTClient;
    RESTRequest1: TRESTRequest;
    RESTResponse1: TRESTResponse;
    tm_MonitoraAPI: TTimer;
    sbtn_MonitApi: TSpeedButton;
    Panel7: TPanel;
    sbtn_AtualizaContatosBanco: TSpeedButton;
    sbtn_CadMsgBanco: TSpeedButton;
    Panel8: TPanel;
    Panel9: TPanel;
    Panel10: TPanel;
    Label8: TLabel;
    Image1: TImage;
    FDQClientesID: TIntegerField;
    FDQClientesWBOTUSUARIO_ID: TIntegerField;
    FDQClientesNOME: TStringField;
    FDQClientesNOME_AGENDA: TStringField;
    FDQClientesTELEFONE: TStringField;
    FDQClientesULTIMA_ATUALIZACAO: TSQLTimeStampField;
    FDQClientesBOT_BLOQUEADO: TStringField;
    FDQClientesFOTO: TBlobField;
    FDQClientesAGUARDANDO_RESPOSTA: TStringField;
    FDQClientesFINALIZADO: TStringField;
    FDQClientesCONTATO: TStringField;
    ApplicationEvents1: TApplicationEvents;
    TrayIcon1: TTrayIcon;
    PopupMenu2: TPopupMenu;
    M1: TMenuItem;
    F1: TMenuItem;
    img_OFF: TImage;
    img_ON: TImage;
    tmrIniciar: TTimer;
    sbtn_LimparCache: TSpeedButton;
    ImageList1: TImageList;
    ChangeIconDialog1: TChangeIconDialog;
    Image2: TImage;
    Image3: TImage;
    procedure FormCreate(Sender: TObject);
    procedure injct_1GetUnReadMessages(const Chats: TChatList);
    procedure injct_1GetQrCode(const Sender: TObject;
      const QrCode: TResultQRCodeClass);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure injct_1GetStatus(Sender: TObject);
    procedure injct_1GetMyNumber(Sender: TObject);
    procedure injct_1Connected(Sender: TObject);
    procedure tmr_MostarQrCodTimer(Sender: TObject);
    procedure injct_1Disconnected(Sender: TObject);
    procedure injct_1DisconnectedBrute(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
    procedure injct_1GetAllContactList(const AllContacts: TRetornoAllContacts);
    procedure img_StatusClick(Sender: TObject);
    procedure SpeedButton4Click(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure SpeedButton5Click(Sender: TObject);
    procedure sbtn_OpenCaminhoAnexoClick(Sender: TObject);
    procedure DBGClientesKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure sbtn_MonitBancClick(Sender: TObject);
    procedure tm_MonitoraBancoTimer(Sender: TObject);
    procedure tm_MonitoraAPITimer(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure sbtn_MonitApiClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure sbtn_CadMsgBancoClick(Sender: TObject);
    procedure sbtn_AtualizaContatosBancoClick(Sender: TObject);
    procedure ApplicationEvents1Minimize(Sender: TObject);
    procedure M1Click(Sender: TObject);
    procedure F1Click(Sender: TObject);
    procedure tmrIniciarTimer(Sender: TObject);
    procedure sbtn_LimparCacheClick(Sender: TObject);
  private
    { Private declarations }
    TempoNotAuth  : Integer;
    AnimiActive,
    LimpaCache : Boolean;
    TempoMonitorApi:  string;
    MyNumFone:  string;

    arqBaseEnv: string;
    vPath : string;

    procedure CenterAnimLoading;
    procedure CenterQrCodeAuth;


    function RetiraEnter(aText: string): string;
    function RetirarEspacosExtras(sText: string): string;

    procedure ConvertFileToBase64(const AInFileName, AOutFileName: string);
    procedure ConvertBase64ToFile(const AInFileName, AOutFileName: string);

    function ConvertFileToDataBase64(const AInFileName: string): string;

    {================-----------------}
    procedure InteracaoBot(AMessage: TMessagesClass);

  public
    { Public declarations }
    bIniciado,
    bAutomatico: Boolean;
  end;
  function SomenteNumeros(Str: string): string;
var
  FrmMain: TFrmMain;

implementation

{$R *.dfm}

uses
  UMensagensEnviar, uConexao, uConexaoApi, Rsc.Vcl.Utils,
  uConstGlobais, uVariaveisGlobais
  ;

function SomenteNumeros(Str: string): string;
var
  I: SmallInt;
begin
  Result := EmptyStr;
  for I := 1 to Length(Str) do
  begin
    if CharInSet(Str[I], ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then
    begin
      Result := Result + Str[I];
    end;
  end;
end;

procedure TFrmMain.ApplicationEvents1Minimize(Sender: TObject);
begin
  if injct_1.Auth(False) then
  begin
    FrmMain.WindowState := wsMinimized;
    FrmMain.Hide;
  end;
end;

procedure TFrmMain.Button3Click(Sender: TObject);
begin
//  ConvertFileToBase64(arqTeste, 'C:\Users\Roniery\Desktop\base64.txt');
//  ConvertBase64ToFile('C:\Users\Roniery\Desktop\base64.txt', 'C:\Users\Roniery\Desktop\base64_T.jpg');
end;

procedure TFrmMain.CenterAnimLoading;
begin
  if not AnimiActive then
    begin
      img_AutenticaQrCod.Picture  :=  nil;
      AnimiActive :=  True;
      ActivityIndicator1.Animate  :=  True;
      ActivityIndicator1.Top :=  (TPanel(ActivityIndicator1.Parent).Height div 2) - (ActivityIndicator1.Height  div 2);
      ActivityIndicator1.Left :=  (TPanel(ActivityIndicator1.Parent).Width div 2) - (ActivityIndicator1.Width  div 2);
      tmr_MostarQrCod.Enabled :=  True;
    end;
end;

procedure TFrmMain.CenterQrCodeAuth;
begin
  pnl_QrCodeAuth.Top :=  (TPanel(pnl_QrCodeAuth.Parent).Height div 2) - (pnl_QrCodeAuth.Height  div 2);
  pnl_QrCodeAuth.Left :=  (TPanel(pnl_QrCodeAuth.Parent).Width div 2) - (pnl_QrCodeAuth.Width  div 2);
end;

procedure TFrmMain.CheckBox1Click(Sender: TObject);
begin
  sbtn_OpenCaminhoAnexo.Enabled :=  TCheckBox(Sender).Checked;

end;

procedure TFrmMain.ConvertBase64ToFile(const AInFileName, AOutFileName: string);
var
  inStream: TStream;
  outStream: TStream;
begin
  inStream := TFileStream.Create(AInFileName, fmOpenRead);
  try
    outStream := TFileStream.Create(AOutFileName, fmCreate);
    try
      TNetEncoding.Base64.Decode(inStream, outStream);
    finally
      outStream.Free;
    end;
  finally
    inStream.Free;
  end;
end;

procedure TFrmMain.ConvertFileToBase64(const AInFileName, AOutFileName: string);
var
  inStream: TStream;
  outStream: TStream;
begin
  inStream := TFileStream.Create(AInFileName, fmOpenRead);
  try
    outStream := TFileStream.Create(AOutFileName, fmCreate);
    try
      TNetEncoding.Base64.Encode(inStream, outStream);
    finally
      outStream.Free;
    end;
  finally
    inStream.Free;
  end;
end;

function TFrmMain.ConvertFileToDataBase64(const AInFileName: string): string;
var
  inStream: TStream;
  outStream: TStream;
  AOutFileName:  string;
  arq:  TFile;
begin
  AOutFileName  :=  ExtractFilePath(ParamStr(0) + 'FileBase.txt');
  inStream := TFileStream.Create(AInFileName, fmOpenRead);
  try
    outStream := TFileStream.Create(AOutFileName, fmCreate);
    try
      TNetEncoding.Base64.Encode(inStream, outStream);
    finally
      outStream.Free;
    end;
  finally
    inStream.Free;
  end;

  Result  :=  'data:image/jpg;base64,'  + arq.ReadAllText(AOutFileName);
  arq.Delete(AOutFileName);
end;

procedure TFrmMain.DBGClientesKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_RETURN then
    sbtn_CadMsgBancoClick(sbtn_CadMsgBanco);
end;

procedure TFrmMain.F1Click(Sender: TObject);
begin
  Close;
end;

procedure TFrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if not LimpaCache then
    injct_1.ShutDown()
  else
  begin
    try
      sbtn_LimparCache.Enabled:= False;
      injct_1.ShutDown(False);
      ShellExecute(handle,'open',PChar(ExtractFilePath(Application.ExeName)+'eFacilLimpaCache.exe'), '','',SW_SHOWNORMAL);
    finally
      sbtn_LimparCache.Enabled:= True;
    end;
  end;
end;

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  vPath:= ExtractFilePath(Application.ExeName);
  TrayIcon1.IconIndex:= 1;
  if FileExists(vPath+'IconeOn.ico') then
    DeleteFile(vPath+'IconeOn.ico');
  if FileExists(vPath+'IconeOff.ico') then
    DeleteFile(vPath+'IconeOff.ico');

  Image2.Picture.SaveToFile(vPath+'IconeOn.ico');
  Image3.Picture.SaveToFile(vPath+'IconeOff.ico');

  Application.Icon.LoadFromFile(vPath+'IconeOff.ico');

  LimpaCache:= False;
  bIniciado := False;
  bAutomatico :=False;

  if UpperCase(ParamStr(1)) = 'INICIAR' THEN
  begin
    bAutomatico:= True;
  end;

  TempoMonitorApi :=  '';
  FDQClientes.Connection  :=  DmMain.FDCon;
  CrdPnl_Main.ActiveCard  :=  Crd_Principal;
  if  GetIniExiste  then
  begin
    GetLerIniDB;
    SetConfigConexaoDB;
    GetLerIniAPI;
    if cid_ = EmptyStr then
    begin
      SetGravarIniAPIConfigDefaut;
      GetLerIniAPI;
    end;
  end
  else
  begin
    SetGravarIniAPIConfigDefaut;
    GetLerIniAPI;
    MessageDlg('Arquivo de configuração não encontrado!'  + #13 +
               'O sistema iniciarar usando as configurações default', TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
  end;

  SetConfigConAPI(RESTClient1);

  SetConfigConAPI(tm_MonitoraAPI);
  SetConfigConAPI(tm_MonitoraBanco);

  if Monit_ then
  begin
    sbtn_MonitBancClick(sbtn_MonitBanc);
    sbtn_MonitApiClick(sbtn_MonitApi);
  end;


  if SetActiveConexaoDB then
  begin
    Label2.Font.Color  :=  clLime;
    Label2.Caption     :=  'Conectado.';
  end
  else
  begin
    Label2.Font.Color  :=  clYellow;
    Label2.Caption     :=  'Sem Conexão.';
  end;

end;

procedure TFrmMain.FormShow(Sender: TObject);
begin
  Memo1.Clear;

  if bAutomatico then
  begin
    if not bIniciado then
      tmrIniciarTimer(sender);
  end;

end;

procedure TFrmMain.sbtn_MonitBancClick(Sender: TObject);
begin
  tm_MonitoraBanco.Enabled  :=  not tm_MonitoraBanco.Enabled;
  if tm_MonitoraBanco.Enabled then
  begin
    TSpeedButton(Sender).Caption :=  'Parar Monitoramento Banco';
  end
  else
  begin
    TSpeedButton(Sender).Caption :=  'Ativar Monitoramento Banco';
  end;
end;

procedure TFrmMain.SpeedButton2Click(Sender: TObject);
var
  FEQry: TFDQuery;
  vArquivo: TMemoryStream;
  vArquivoNome : string;
begin
  FEQry := TFDQuery.Create(Self);
  vArquivo:= TMemoryStream.Create;
  vArquivo.Position:= 0;
  vArquivoNome:= '';
  try
    try
      FEQry.Connection  :=  DmMain.FDCon;
      FEQry.Close;
      if CheckBox1.Checked and (lbl_camihoAnexo.Caption <> '...') then
      begin
        vArquivo.LoadFromFile(lbl_camihoAnexo.Caption);
        vArquivoNome:= ExtractFileName(lbl_camihoAnexo.Caption);
      end;

      with FEQry do
      begin
        close;
        sql.Clear;
        sql.Add('INSERT INTO                          ');
        sql.Add('  WBOTMENSAGEMAENVIAR                ');
        sql.Add('  (ARQUIVO, ARQUIVONOME,             ');
        sql.Add('  ENVIADA, ID, MENSAGEM, TELEFONE,   ');
        sql.Add('  WBOTCONTATO_ID)                    ');
        sql.Add('VALUES                               ');
        sql.Add('  (:ARQUIVO, :ARQUIVONOME, :ENVIADA, ');
        sql.Add('  :ID, :MENSAGEM, :TELEFONE,         ');
        sql.Add('  :WBOTCONTATO_ID)                   ');
        if CheckBox1.Checked and (lbl_camihoAnexo.Caption <> '...') then
          ParamByName('ARQUIVO').LoadFromStream(vArquivo,ftBlob)
        else ParamByName('ARQUIVO').DataType:= ftBlob;
        ParamByName('ARQUIVONOME').AsString:= vArquivoNome;
        ParamByName('ENVIADA').AsString:= 'N';
        ParamByName('MENSAGEM').AsString:= mm_MsgSalvarBanco.Text;
        ParamByName('TELEFONE').AsString:= '';
        ParamByName('WBOTCONTATO_ID').AsInteger:= FDQClientes.FieldByName('ID').AsInteger;
        ExecSQL;
      end;
      MessageDlg('Mensagem cadastrada com sucesso!', TMsgDlgType.mtInformation, [TMsgDlgBtn.mbOK], 0);
      mm_MsgSalvarBanco.Clear;
      lbl_camihoAnexo.Caption :=  '...';
    except on E: Exception do
      begin
        MessageDlg(e.Message, TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
      end;
    end;
  finally
    FEQry.Free;
  end;
end;

procedure TFrmMain.SpeedButton3Click(Sender: TObject);
begin
  CrdPnl_Main.ActiveCard  :=  Crd_Principal;
end;

procedure TFrmMain.SpeedButton4Click(Sender: TObject);
begin
  CrdPnl_Main.ActiveCard  :=  Crd_Atualizar_Contatos;
  FDQClientes.Open;
end;

procedure TFrmMain.SpeedButton5Click(Sender: TObject);
begin
  CrdPnl_Main.ActiveCard  :=  Crd_Atualizar_Contatos;
end;

procedure TFrmMain.sbtn_AtualizaContatosBancoClick(Sender: TObject);
begin
  injct_1.GetAllContacts;
end;

procedure TFrmMain.sbtn_CadMsgBancoClick(Sender: TObject);
begin
  if DBGClientes.SelectedRows.Count >= 0 then
    begin
      CrdPnl_Main.ActiveCard  :=  Crd_CadastrarMensagem;
    end
  else
    begin
      ShowMessage('Selecione um contato no grid');
    end;
end;

procedure TFrmMain.sbtn_LimparCacheClick(Sender: TObject);
begin
  LimpaCache:= True;
  close;
end;

procedure TFrmMain.sbtn_MonitApiClick(Sender: TObject);
begin
  tm_MonitoraAPI.Enabled  :=  not tm_MonitoraAPI.Enabled;
  if tm_MonitoraAPI.Enabled then
    begin
      TSpeedButton(Sender).Caption :=  'Parar Monitoramento API';
    end
  else
    begin
      TSpeedButton(Sender).Caption :=  'Ativar Monitoramento API';
    end;
end;

procedure TFrmMain.tmrIniciarTimer(Sender: TObject);
begin
  bIniciado :=  True;
  tmrIniciar.Enabled  :=  False;
  img_StatusClick(Self);
  bAutomatico:= True;
  {
  TrayIcon1.Visible := True;
  WindowState := wsMinimized;
  Self.Hide;}
end;

procedure TFrmMain.tmr_MostarQrCodTimer(Sender: TObject);
begin
  if TempoNotAuth = 0 then
    begin
      if img_AutenticaQrCod.Picture.Graphic  <>  nil then
        begin
          TempoNotAuth  :=  1;
          ActivityIndicator1.Top  :=  -100;
          ActivityIndicator1.Animate :=  False;

        end;
    end
  else
    begin
      TempoNotAuth  :=  TempoNotAuth  + 1;
      if TempoNotAuth > 120 then
        begin
          injct_1.FormQrCodeShowing := False;
          AnimiActive :=  False;
          img_AutenticaQrCod.Picture  :=  nil;
          tmr_MostarQrCod.Enabled  :=  False;
        end;
    end;
end;

procedure TFrmMain.tm_MonitoraAPITimer(Sender: TObject);
var
  JsOb  : TJsonObject;
  JsAryData:  TJSONArray;
  j:  integer;
begin
  tm_MonitoraAPI.Enabled  :=  False;

  if injct_1.Auth(false) then
    begin
      {$REGION 'Cosulta direferença tempo'}
      memo1.Lines.Add('======================================');
      Memo1.Lines.Add('Consultando TimesTemp');
      SetRequestGetTimesTemp(RESTRequest1);
      RESTRequest1.Execute;
//      Memo1.Lines.Add('TimesTemp Recebido: '  + RESTResponse1.Content);
      {$ENDREGION}

      {$REGION 'Consulta Mensagens para o envio'}
      if TempoMonitorApi <> RESTResponse1.Content then
        begin
          TempoMonitorApi :=  RESTResponse1.Content;
          Memo1.Lines.Add('Novo TimesTemp Recebido: '  + RESTResponse1.Content);
          memo1.Lines.Add('');
          Memo1.Lines.Add('Consultando Novas Mensagens a Enviar');
          memo1.Lines.Add('');
          SetRequestGetMsgData(RESTRequest1);
          RESTRequest1.Execute;
//          Memo1.Lines.Add('Novas Mensagens Recebidas: '  + RESTResponse1.Content);
          {===================================================================}
          JsOb := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(RESTResponse1.Content), 0) as TJSONObject;
          JsAryData := JsOb.GetValue<TJsonArray>('data');
          if JsOb.GetValue<Boolean>('success', False) = True  then
            begin
              Memo1.Lines.Add('Retornou Dados');
              Memo1.Lines.Add('Listando msgs a serem enviadas!');
              memo1.Lines.Add('---------------------------------');

              for j := 0 to JsAryData.Count - 1 do
                begin
                  memo1.Lines.Add('From: ' + JsAryData.Items[j].GetValue<string>('from', ''));
                  memo1.Lines.Add('To: ' + JsAryData.Items[j].GetValue<string>('to', ''));
                  memo1.Lines.Add('Mensagem: ' + JsAryData.Items[j].GetValue<string>('response_message', ''));
                  memo1.Lines.Add('***************************');
                  memo1.Lines.Add('Enviando Mensagem...');

                  EnviarMsgWhatsApp(injct_1,
                                    JsAryData.Items[j].GetValue<string>('to', '') + '@c.us',
                                    JsAryData.Items[j].GetValue<string>('response_message', ''),
                                    '');

                  memo1.Lines.Add('Mensagem Enviada...');
                  memo1.Lines.Add('***************************');
                end;

            end;
          JsOb.DisposeOf;
        end
      else
        Memo1.Lines.Add('TimesTemp Recebido: é o mesmo do anterior');
      {$ENDREGION}
    end
  else
    begin
      memo1.Lines.Add('');
      memo1.Lines.Add('Para proteção de recursos a consulta a api só é realisada se o whatsapp estiver autenticado.');
      memo1.Lines.Add('');
    end;

  tm_MonitoraAPI.Enabled  :=  True;
end;

procedure TFrmMain.tm_MonitoraBancoTimer(Sender: TObject);
var
  FDQry: TFDQuery;
  vStream : TMemoryStream;
  vTelefone, vMensagem,
  vContato, vArquivo, vPath : String;
begin

  if not GetConexaoDBConnected then
  begin
    sbtn_MonitBancClick(sbtn_MonitBanc);
  end;


  if injct_1.Auth(false) and GetConexaoDBConnected then
  begin
    vPath:= ExtractFilePath(ParamStr(0));

    if RightStr(vPath,1) <> PathDelim then   { Tem delimitador no final ? }
      vPath := vPath + PathDelim ;

    vStream := TMemoryStream.Create;
    FDQry := TFDQuery.Create(Self);
    try
      tm_MonitoraBanco.Enabled  :=  False;
      try
        FDQry.Connection  :=  DmMain.FDCon;
        FDQry.Close;
        FDQry.SQL.Text:= 'SELECT                                                ' +
                         '  A.ID,                                               ' +
                         '  A.MENSAGEM,                                         ' +
                         '  A.ARQUIVONOME,                                      ' +
                         '  A.ARQUIVO,                                          ' +
                         '  A.TELEFONE AS TELEFONEMENSAGEM,                     ' +
                         '  B.TELEFONE AS TELEFONECONTATO,                      ' +
                         '  B.NOME,                                             ' +
                         '  COALESCE(B.CONTATO,''S'') AS CONTATO                ' +
                         'FROM WBOTMENSAGEMAENVIAR A                            ' +
                         'INNER JOIN WBOTCONTATO B ON (B.ID = A.WBOTCONTATO_ID) ' +
                         'WHERE (A.ENVIADA = ''N'')                             ';
        FDQry.Open;
        if not FDQry.IsEmpty then
        begin
          FDQry.First;
          while not FDQry.eof do
          begin
    //                TTask.Run(procedure
    //                begin

            IF FDQry.FieldByName('TELEFONECONTATO').AsString <> '' then
              vTelefone:= SomenteNumeros(FDQry.FieldByName('TELEFONECONTATO').AsString)
            else vTelefone:= SomenteNumeros(FDQry.FieldByName('TELEFONEMENSAGEM').AsString);
            vMensagem:= FDQry.FieldByName('MENSAGEM').AsString;
            vArquivo := FDQry.FieldByName('ARQUIVONOME').AsString;
            vContato := FDQry.FieldByName('CONTATO').AsString;
            vContato:= '@c.us';

            if vArquivo <> '' then
            begin

              if not DirectoryExists(vPath+'Arq') then
                ForceDirectories(vPath+'Arq');
              vArquivo:= vPath+'Arq\'+vArquivo;
              TBlobField(FDQry.FieldByName('ARQUIVO')).SaveToFile(vArquivo);


              //vStream.Position:= 0;
              //TBlobField(vQr.FieldByName('ARQUIVO')).SaveToStream(vStream);

              EnviarMsgWhatsApp(injct_1,
                                vTelefone+'@c.us',
                                vMensagem,
                                vArquivo);
              SetUpdateMsgEnviada(FDQry.FieldByName('ID').AsInteger);
            end
            else
            begin
              EnviarMsgWhatsApp(injct_1,
                                vTelefone+'@c.us',
                                vMensagem,
                                '');
              SetUpdateMsgEnviada(FDQry.FieldByName('ID').AsInteger);
            end;

    //                end);
            FDQry.Next;
          end;
        end;

      except
        on E: Exception do
        begin
            MessageDlg(e.Message, TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
        end;
      end;
    finally
      FreeAndNil(vStream);
      FreeAndNil(FDQry);
      tm_MonitoraBanco.Enabled  :=  True;
    end;
  end;
end;


procedure TFrmMain.img_StatusClick(Sender: TObject);
begin
  if not injct_1.Auth(false) then
  begin
    CenterQrCodeAuth;
    CrdPnl_Main.ActiveCard  :=  Crd_AutenticaWhatsApp;
    injct_1.FormQrCodeType := TFormQrCodeType.Ft_None;
    injct_1.FormQrCodeStart;
    AnimiActive :=  False;
    CenterAnimLoading;
    img_AutenticaQrCod.Picture  :=  nil;
    TempoNotAuth  :=  0;
  end
  else
  begin
    injct_1.Logtout;
    injct_1.Disconnect;
  end;
end;

procedure TFrmMain.injct_1Connected(Sender: TObject);
begin
  AnimiActive                 :=  False;
  img_AutenticaQrCod.Picture  :=  nil;
  ActivityIndicator1.Animate  :=  False;
  tmr_MostarQrCod.Enabled     :=  False;
  img_Status.Picture:= img_ON.Picture;
  CrdPnl_Main.ActiveCard  :=  Crd_Principal;
  TrayIcon1.IconIndex:= 0;
  if bAutomatico then
  begin
    WindowState := wsMinimized;
    Application.Minimize;
  end;
end;

procedure TFrmMain.injct_1Disconnected(Sender: TObject);
begin
  pnl_Title.Color :=  clSilver;
  img_Status.Hint :=  'Autenticar WhatsApp';
  lbl_statusTinject.Caption :=  'Status WhatsApp: Desconectado';
  img_Status.Picture:= img_OFF.Picture;
  TrayIcon1.IconIndex:= 1;
  Application.Icon.LoadFromFile(vPath+'IconeOff.ico');
end;

procedure TFrmMain.injct_1DisconnectedBrute(Sender: TObject);
begin
  pnl_Title.Color :=  clSilver;
  img_Status.Hint :=  'Autenticar WhatsApp';
  lbl_statusTinject.Caption :=  'Status WhatsApp: Desconectado pelo usuário';
  img_Status.Picture:= img_OFF.Picture;
  TrayIcon1.IconIndex:= 1;
  Application.Icon.LoadFromFile(vPath+'IconeOff.ico');
end;

procedure TFrmMain.injct_1GetAllContactList(
  const AllContacts: TRetornoAllContacts);
var
  AContact: TContactClass;
  vTelefone : string;
begin

  FDQClientes.DisableControls;
  AContact  :=  nil;

  try
    for AContact in AllContacts.result do
    begin
      try
        //if AContact.isMyContact = True then
        begin
          vTelefone :=  Copy(AContact.id, 0, Pos('@', AContact.id) - 1);
          if not IfExitClient(vTelefone) then
          begin
            FDQClientes.Append;
            FDQClientes.FieldByName('ID').AsInteger           :=  NewIDCliente;
            //FDQClientes.FieldByName('IDNUMTELEFONE').AsString :=  AContact.id;
            FDQClientes.FieldByName('NOME').AsWideString :=  RetirarEspacosExtras(RetiraEnter(AContact.name));
            FDQClientes.FieldByName('NOME_AGENDA').AsWideString :=  FDQClientes.FieldByName('NOME').AsWideString;
            FDQClientes.FieldByName('TELEFONE').AsString :=  vTelefone;
            FDQClientes.FieldByName('CONTATO').AsString := 'S';
            FDQClientes.Post;
          end;
        end;
      except on E: Exception do
        begin
          MessageDlg('Erro ao inserir o cliente: '
                          + #13
  //                        + 'id comp: '  + AContact.id
  //                        + #13
                          + 'id compNOM: '  + AContact.name
                          + #13
  //                        + 'id compTel: '  + Copy(AContact.id, 0, Pos('@', AContact.id) - 1)
  //                        + #13
  //                        + #13
  //                        + 'id fdq: '  + FDQClientesID.AsString
  //                        + #13
  //                        + 'id fdqnum: '  + FDQClientesIDNUMTELEFONE.AsString
  //                        + #13
  //                        + 'id fdqtel: '  + FDQClientesTELEFONE.AsString
  //                        + #13
  //                        + 'id fdqNome: '  + FDQClientesNOME.AsString
  //                        + #13
                         + e.Message, TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
          FDQClientes.Cancel;
        end;
      end;
    end;

  finally
    AContact:= nil;
    FDQClientes.EnableControls;
    FDQClientes.close;
    FDQClientes.open;
  end;
  //ShowMessage('Contos do banco atualizados com sucesso!');
end;

procedure TFrmMain.injct_1GetMyNumber(Sender: TObject);
begin
  lbl_NumerAutenticado.Caption := 'Número Autenticado: '  +   TInject(Sender).MyNumber;
  MyNumFone :=  GetStrNumber(TInject(Sender).MyNumber);
end;

procedure TFrmMain.injct_1GetQrCode(const Sender: TObject;
  const QrCode: TResultQRCodeClass);
begin
  if not (Application.Terminated) and (TInject(Sender).Auth(false)) then
  begin
    if QrCode.AQrCode <> '' then
    begin
      Label5.Caption  :=  'Scaneie o QrCode';
      img_AutenticaQrCod.Picture.Assign(QrCode.AQrCodeImage);
    end
    else
    begin
      Label5.Caption  :=  'Aguardando o QrCode...';
    end;
  end;
end;

procedure TFrmMain.injct_1GetStatus(Sender: TObject);
begin
  if not (Application.Terminated)  then
  begin
    case TInject(Sender).Status of
      Inject_Initialized:
      begin
        lbl_statusTinject.Caption :=  'Status WhatsApp: Conectado';
      end;

      Server_Connected:
      begin
        CrdPnl_Main.ActiveCard  :=  Crd_Principal;
        pnl_Title.Color :=  clHighlight;
        img_Status.Hint :=  'Desconectar WhatsApp';
        lbl_statusTinject.Caption :=  'Status WhatsApp: Autenticado';
        img_Status.Picture:= img_ON.Picture;
        TrayIcon1.IconIndex:= 0;
        if bAutomatico then
        begin
          WindowState := wsMinimized;
          Application.Minimize;
        end;
      end;

      Inject_Initializing:
      begin
        lbl_statusTinject.Caption :=  'Status WhatsApp: Inicializando..';
      end;
      Inject_Destroying,
      Inject_Destroy,
      Server_Disconnected:
      begin
        pnl_Title.Color :=  clSilver;
        img_Status.Hint :=  'Autenticar WhatsApp';
        lbl_statusTinject.Caption :=  'Status WhatsApp: Desconectado';
        lbl_NumerAutenticado.Caption := 'Número Autenticado: ';
        img_Status.Picture:= img_OFF.Picture;
        TrayIcon1.IconIndex:= 1;
        Application.Icon.LoadFromFile(vPath+'IconeOff.ico');
      end;

      Server_Disconnecting:
      begin
        lbl_statusTinject.Caption :=  'Status WhatsApp: Desconectando..';
      end;

      Server_ConnectedDown:;

      Server_Connecting:
      begin
        lbl_statusTinject.Caption :=  'Status WhatsApp: Conectando...';
      end;

      Server_ConnectingNoPhone:;

      Server_ConnectingReaderCode:
      begin
        lbl_statusTinject.Caption :=  'Status WhatsApp: Obtendo o QrCode..';
      end;

      Server_TimeOut:;
    end;
  end;

end;

procedure TFrmMain.injct_1GetUnReadMessages(const Chats: TChatList);
var
  AChat   : TChatClass;
  AMessage: TMessagesClass;
  injectDecrypt: TInjectDecryptFile;
begin
  //Loop em todos os chats
  for AChat in Chats.result do
  begin
    //Não considerar chats de grupos
    if not AChat.isGroup then
    begin
      //Define que a mensagem ja foi lida,
      //para evitar recarrega-la novamente.
      injct_1.ReadMessages( AChat.id );

      //Pode haver mais de uma mensagem, pego a ultima
      AMessage := AChat.messages[ Low( AChat.messages ) ];

      //Não considerar mensagens enviadas por mim
      if not AMessage.sender.fromMe then
      begin
//        if UpperCase(AMessage.&type) <>  'CHAT' then
//          begin
//            injectDecrypt.downloadRsc(AMessage.clientUrl, AMessage.mediaKey,  AMessage.filename,  AMessage.&type, AMessage.mimetype);
//          end;
        {tratar o tipo de arquivo recebido e faz download para para pasta \bin\temp}
        case AnsiIndexStr(UpperCase(AMessage.&type), ['PTT', 'IMAGE', 'VIDEO', 'AUDIO', 'DOCUMENT']) of
          0: begin injectDecrypt.download(AMessage.deprecatedMms3Url, AMessage.mediaKey, 'mp3', AChat.id); end;
          1: begin injectDecrypt.download(AMessage.deprecatedMms3Url, AMessage.mediaKey, 'jpg', AChat.id); end;
          2: begin injectDecrypt.download(AMessage.deprecatedMms3Url, AMessage.mediaKey, 'mp4', AChat.id); end;
          3: begin injectDecrypt.download(AMessage.deprecatedMms3Url, AMessage.mediaKey, 'mp3', AChat.id); end;
          4: begin injectDecrypt.download(AMessage.deprecatedMms3Url, AMessage.mediaKey, 'pdf', AChat.id); end;
        end;

        //Carregar Conversa e passar a mensagem
        InteracaoBot( AMessage );
      end;
    end;
  end;
end;

procedure TFrmMain.InteracaoBot(AMessage: TMessagesClass);
var
  JsObResp,  JsObRet  : TJsonObject;
  JsAryData:  TJSONArray;
  JsObEnv  : TJsonObject;
  j:  integer;
begin
  if injct_1.Auth(false) then
  begin
    JsObEnv := TJSONObject.Create;
    JsObEnv.AddPair('from', Copy(AMessage.sender.id,1,Pos('@',AMessage.sender.id)-1));
    JsObEnv.AddPair('to', MyNumFone);
    JsObEnv.AddPair('message', AMessage.body);
    JsObEnv.AddPair('file_encoded', TJSONNull.Create);
    JsObEnv.AddPair('file_url', TJSONNull.Create);
    JsObEnv.AddPair('file_type', AMessage.mediaKey);

    {$REGION 'Consulta Mensagens para o envio'}
        Memo1.Lines.Add('Nova Mensagem no WhatsApp: ');
        memo1.Lines.Add('');
        Memo1.Lines.Add('Enviando Mensagem para a API');
        memo1.Lines.Add('');
        memo1.Lines.Add('Json do bory');
        memo1.Lines.Add(JsObEnv.ToString);
        memo1.Lines.Add('');


        memo1.Lines.Add('Configurando Rest');
        SetRequestPostMsgData(RESTRequest1);
        memo1.Lines.Add('Adicionando body');

        RESTRequest1.AddBody(JsObEnv.ToString, ctAPPLICATION_JSON);

        memo1.Lines.Add('lendo accept');
        memo1.Lines.Add(RESTRequest1.Accept);

        try
          memo1.Lines.Add('fazendo consulta');
          RESTRequest1.Execute;
        except on E: Exception do
          begin
            ShowMessage(e.Message);
            Exit;
          end;
        end;



        Memo1.Lines.Add('Response.Content: '  + RESTResponse1.Content);
        memo1.Lines.Add('');
        {===================================================================}
        try
          JsObResp := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(RESTResponse1.Content), 0) as TJSONObject;
        except on E: Exception do
          begin
            ShowMessage(e.Message);
            Exit;
          end;
        end;

        if JsObResp.GetValue<Boolean>('success', False) = True  then
          begin
            Memo1.Lines.Add('Retornou Dados');
            Memo1.Lines.Add('Listando msgs a serem enviadas!');
            memo1.Lines.Add('---------------------------------');
            JsAryData := JsObResp.GetValue<TJsonArray>('data');
            for j := 0 to JsAryData.Count - 1 do
              begin
                memo1.Lines.Add('From: ' + JsAryData.Items[j].GetValue<string>('from', ''));
                memo1.Lines.Add('To: ' + JsAryData.Items[j].GetValue<string>('to', ''));
                memo1.Lines.Add('Mensagem: ' + JsAryData.Items[j].GetValue<string>('response_message', ''));
                memo1.Lines.Add('***************************');
                memo1.Lines.Add('Enviando Mensagem...');

                EnviarMsgWhatsApp(injct_1,
                                  JsAryData.Items[j].GetValue<string>('to', '') + '@c.us',
                                  JsAryData.Items[j].GetValue<string>('response_message', ''),
                                  '');


                memo1.Lines.Add('Mensagem Enviada...');
                memo1.Lines.Add('***************************');
              end;
          end
        else
          Memo1.Lines.Add('Não Retornou Dados');
      JsObResp.DisposeOf;
      JsObEnv.DisposeOf;
      {$ENDREGION}
  end
  else
  begin
    memo1.Lines.Add('');
    memo1.Lines.Add('Para proteção de recursos a consulta a api só é realisada se o whatsapp estiver autenticado.');
    memo1.Lines.Add('');
  end;
end;


procedure TFrmMain.M1Click(Sender: TObject);
begin
  CrdPnl_Main.ActiveCard  :=  Crd_Principal;
  FrmMain.WindowState := wsNormal;
  FrmMain.Show;
end;

function TFrmMain.RetiraEnter(aText: string): string;
begin
  { Retirando as quebras de linha em campos blob }
  Result := StringReplace(aText, #$D#$A, '', [rfReplaceAll]);

  { Retirando as quebras de linha em campos blob }
  Result := StringReplace(Result, #13#10, '', [rfReplaceAll]);
end;


function TFrmMain.RetirarEspacosExtras(sText: string): string;
var
  nCont, nTamanhoDoTexto: integer;
begin
  // A função Leng1th vai retornar o tamanho total da string do
  //parâmetro sTexto e atribuir à variável nTamanhoDoTexto
  nTamanhoDoTexto := Length(sText);

  // Aqui será realizado um laço de repetições até atingir o tamanho
  // total de caracteres da string. Faz-se necessário o uso de
  // laços, pois a função StringReplace ao encontrar o primeiro
  // espaço duplo, vai trocar para apenas 1 e sairá do método
  for nCont := 0 to nTamanhoDoTexto - 1 do
    sText := StringReplace(sText, '  ', ' ', [rfReplaceAll]);

  result := sText;
end;

procedure TFrmMain.sbtn_OpenCaminhoAnexoClick(Sender: TObject);
begin
{
  if OpenDialog1.Execute then
    begin
      lbl_camihoAnexo.Caption :=  OpenDialog1.FileName;
      Image1.Picture.Graphic  :=  GetBitmapFromFile(OpenDialog1.FileName);
    end; }
end;

end.
