|
@@ -0,0 +1,177 @@
|
|
|
|
+program sendmsg;
|
|
|
|
+
|
|
|
|
+{$mode objfpc}{$H+}
|
|
|
|
+
|
|
|
|
+uses
|
|
|
|
+ {$IFDEF UNIX}
|
|
|
|
+ cthreads,
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ Classes, SysUtils, CustApp, fpjson, jsonparser, fpfcmsender, opensslsockets, fpfcmtypes, fpwebclient, fphttpwebclient;
|
|
|
|
+
|
|
|
|
+type
|
|
|
|
+
|
|
|
|
+ { TFCMApplication }
|
|
|
|
+
|
|
|
|
+ TFCMApplication = class(TCustomApplication)
|
|
|
|
+ private
|
|
|
|
+ FAccessTokenFile : String;
|
|
|
|
+ procedure ConfigureClient(aClient: TFCMClient);
|
|
|
|
+ procedure ConfigureMessage(Msg: TNotificationMessage);
|
|
|
|
+ procedure DoHandleNewToken(Sender: TObject; const aToken: TBearerToken);
|
|
|
|
+ procedure LoadMessageFromFile(Msg: TNotificationMessage; const aFileName: string);
|
|
|
|
+ protected
|
|
|
|
+ procedure DoRun; override;
|
|
|
|
+ public
|
|
|
|
+ constructor Create(TheOwner: TComponent); override;
|
|
|
|
+ procedure Usage(Msg: String); virtual;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+{ TFCMApplication }
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.ConfigureClient(aClient : TFCMClient);
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ CfgFile : string;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ // Service account info
|
|
|
|
+ CfgFile:=GetOptionValue('s','service-account');
|
|
|
|
+ if CfgFile='' then
|
|
|
|
+ CfgFile:=ChangeFileExt(ParamStr(0),'-service-account.json');
|
|
|
|
+ if not FileExists(CfgFile) then
|
|
|
|
+ Raise EInOutError.CreateFmt('No service account configuration file found: %s',[CfgFile]);
|
|
|
|
+ aClient.InitServiceAccount(CfgFile,'');
|
|
|
|
+ // Access token reuse
|
|
|
|
+ if HasOption('a','access-token') then
|
|
|
|
+ begin
|
|
|
|
+ FAccessTokenFile:=GetOptionValue('a','access-token');
|
|
|
|
+ // Load initial token
|
|
|
|
+ if FileExists(FAccessTokenFile) then
|
|
|
|
+ aClient.BearerToken.LoadFromFile(FAccessTokenFile);
|
|
|
|
+ // Set handler so we save the token when it was fetched.
|
|
|
|
+ aClient.OnNewBearerToken:=@DoHandleNewToken;
|
|
|
|
+ end;
|
|
|
|
+ // Log file
|
|
|
|
+ if HasOption('l','log') then
|
|
|
|
+ aClient.LogFile:=GetOptionValue('l','log');
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.LoadMessageFromFile(Msg : TNotificationMessage; const aFileName : string);
|
|
|
|
+
|
|
|
|
+Var
|
|
|
|
+ F : TFileStream;
|
|
|
|
+ D : TJSONData;
|
|
|
|
+ Obj : TJSONObject absolute D;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ F:=TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
|
|
|
|
+ try
|
|
|
|
+ D:=GetJSON(F);
|
|
|
|
+ if not (D is TJSONObject) then
|
|
|
|
+ Raise EFCM.CreateFmt('Invalid JSON data in message file %s',[aFileName]);
|
|
|
|
+ Msg.Title:=Obj.Get('title',Msg.Title);
|
|
|
|
+ Msg.Body:=Obj.Get('body',Msg.Body);
|
|
|
|
+ Msg.Image:=Obj.Get('image',Msg.Image);
|
|
|
|
+ finally
|
|
|
|
+ F.Free;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.ConfigureMessage(Msg : TNotificationMessage);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ if HasOption('m','message') then
|
|
|
|
+ LoadMessageFromFile(Msg,GetOptionValue('m','message'));
|
|
|
|
+ if HasOption('t','title') then
|
|
|
|
+ Msg.Title:=GetoptionValue('t','title');
|
|
|
|
+ if HasOption('b','body') then
|
|
|
|
+ Msg.Body:=GetoptionValue('b','body');
|
|
|
|
+ if HasOption('i','image') then
|
|
|
|
+ Msg.Body:=GetoptionValue('i','image');
|
|
|
|
+
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.DoHandleNewToken(Sender: TObject; const aToken: TBearerToken);
|
|
|
|
+begin
|
|
|
|
+ aToken.SaveToFile(FAccessTokenFile);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.DoRun;
|
|
|
|
+
|
|
|
|
+const
|
|
|
|
+ Short = 'hm:b:t:r:s:i:l:a:';
|
|
|
|
+ Long : Array of string = ('help','message:','body:','title:','recipient:','service-account:','image:','log:','access-token:');
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ ErrorMsg: String;
|
|
|
|
+ Msg : TNotificationMessage;
|
|
|
|
+ Client : TFCMClient;
|
|
|
|
+ Recip : String;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Terminate;
|
|
|
|
+ // quick check parameters
|
|
|
|
+ ErrorMsg:=CheckOptions(Short,Long);
|
|
|
|
+ if (ErrorMsg<>'') or HasOption('h','help') then
|
|
|
|
+ begin
|
|
|
|
+ Usage(ErrorMsg);
|
|
|
|
+ Exit;
|
|
|
|
+ end;
|
|
|
|
+ Recip:=GetOptionValue('r','recipient');
|
|
|
|
+ if Recip='' then
|
|
|
|
+ begin
|
|
|
|
+ Usage('Need a recipient');
|
|
|
|
+ Exit;
|
|
|
|
+ end;
|
|
|
|
+ Msg:=nil;
|
|
|
|
+ Client:=TFCMClient.Create(Self);
|
|
|
|
+ Try
|
|
|
|
+ ConfigureClient(Client);
|
|
|
|
+ Msg:=TNotificationMessage.Create;
|
|
|
|
+ ConfigureMessage(Msg);
|
|
|
|
+ Client.Send(Msg,Recip);
|
|
|
|
+ Finally
|
|
|
|
+ Msg.Free;
|
|
|
|
+ Client.Free;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+constructor TFCMApplication.Create(TheOwner: TComponent);
|
|
|
|
+begin
|
|
|
|
+ inherited Create(TheOwner);
|
|
|
|
+ StopOnException:=True;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TFCMApplication.Usage(Msg : String);
|
|
|
|
+begin
|
|
|
|
+ Writeln('Error : ',Msg);
|
|
|
|
+ Writeln('Usage: ', ExeName, ' [options] ');
|
|
|
|
+ Writeln('where options is one or more of');
|
|
|
|
+ Writeln('-h --help This message');
|
|
|
|
+ Writeln('-a --access-token=FILE Save (and optionally load) received access token to FILE');
|
|
|
|
+ Writeln('-b --body=TEXT Set message body text. Overrides settings in -m');
|
|
|
|
+ Writeln('-i --image=URL Set message image URL. Overrides settings in -m');
|
|
|
|
+ Writeln('-l --log=FILE Set log file - all HTTP requests will be logged in this file');
|
|
|
|
+ writeln('-m --message=FILE Set message body, title and image from FILE, a json file with format:' );
|
|
|
|
+ writeln(' { "title" : "string", ');
|
|
|
|
+ Writeln(' "body" : "string", ');
|
|
|
|
+ Writeln(' "image" : "url" } ');
|
|
|
|
+ Writeln('-r --recipient=TOKEN Set message recipient token');
|
|
|
|
+ writeln('-s --service-account=FILE Read service account data from FILE (google service account data)');
|
|
|
|
+ Writeln('-t --title=TEXT Set message title text. Overrides settings in -m');
|
|
|
|
+ ExitCode:=Ord(Msg<>'');
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ Application: TFCMApplication;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ DefaultWebClientClass:=TFPHTTPWebClient;
|
|
|
|
+ Application:=TFCMApplication.Create(nil);
|
|
|
|
+ Application.Title:='FCM Test Application';
|
|
|
|
+ Application.Run;
|
|
|
|
+ Application.Free;
|
|
|
|
+end.
|
|
|
|
+
|