module.messaging.pp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. {
  2. This file is part of the Free Component Library
  3. Copyright (c) 2024 by Michael Van Canneyt [email protected]
  4. FCM (Firebase Cloud Messaging) - JSON-RPC interface for webclient
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit module.messaging;
  12. {$mode ObjFPC}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, fpjsonrpc, fpjson, fpfcmtypes, fpfcmclient;
  16. type
  17. { TdmMessaging }
  18. TdmMessaging = class(TDataModule)
  19. RegisterSubscription: TJSONRPCHandler;
  20. SendNotification: TJSONRPCHandler;
  21. procedure RegisterSubscriptionExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData);
  22. procedure SendNotificationExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData);
  23. private
  24. class function ConfigDir: String;
  25. function AccessTokenFile: string;
  26. function DeviceTokensFileName: String;
  27. procedure HandleNewAccessToken(Sender: TObject; const aToken: TBearerToken);
  28. function LoadLastToken: UTF8String;
  29. public
  30. procedure SendMessage(Msg: TNotificationmessage);
  31. procedure SaveToken(const aToken: UTF8String);
  32. end;
  33. var
  34. dmMessaging: TdmMessaging;
  35. implementation
  36. {$R *.lfm}
  37. { TdmMessaging }
  38. class Function TdmMessaging.ConfigDir : String;
  39. begin
  40. Result:=ExtractFilePath(ParamStr(0));
  41. end;
  42. Function TdmMessaging.DeviceTokensFileName : String;
  43. begin
  44. Result:=ConfigDir+'device-tokens.txt';
  45. end;
  46. Function TdmMessaging.AccessTokenFile : string;
  47. begin
  48. Result:=ConfigDir+'access-token.json';
  49. end;
  50. procedure TdmMessaging.HandleNewAccessToken(Sender: TObject; const aToken: TBearerToken);
  51. begin
  52. aToken.SaveToFile(AccessTokenFile);
  53. end;
  54. procedure TdmMessaging.SaveToken(const aToken : UTF8String);
  55. var
  56. L : TStrings;
  57. FN : String;
  58. begin
  59. FN:=DeviceTokensFileName;
  60. L:=TStringList.Create;
  61. try
  62. if FileExists(FN) then
  63. L.LoadFromFile(FN);
  64. L.Add(aToken);
  65. L.SaveToFile(FN);
  66. finally
  67. L.Free;
  68. end;
  69. end;
  70. function TdmMessaging.LoadLastToken : UTF8String;
  71. var
  72. L : TStrings;
  73. FN : String;
  74. begin
  75. FN:=DeviceTokensFileName;
  76. L:=TStringList.Create;
  77. try
  78. if fileExists(fn) then
  79. L.LoadFromFile(FN);
  80. if L.Count=0 then
  81. Raise Exception.Create('No tokens registered');
  82. Result:=L[L.Count-1];
  83. finally
  84. L.Free;
  85. end;
  86. end;
  87. procedure TdmMessaging.RegisterSubscriptionExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData);
  88. var
  89. Parms: TJSONArray absolute params;
  90. aToken : UTF8String;
  91. begin
  92. If Parms.Count<>1 then
  93. Raise Exception.Create('Invalid param count');
  94. if Parms[0].JSONType=JTString then
  95. // FCM token
  96. aToken:=Parms[0].AsString
  97. else if Parms[0].JSONType=jtObject then
  98. aToken:=Parms[0].AsJSON
  99. else
  100. Raise Exception.Create('Invalid param type for token');
  101. SaveToken(aToken);
  102. Res:=TJSONBoolean.Create(True);
  103. end;
  104. procedure TdmMessaging.SendMessage(Msg : TNotificationmessage);
  105. var
  106. Sender : TFCMClient;
  107. aConfig, aToken : String;
  108. begin
  109. aToken:=LoadLastToken;
  110. Sender:=TFCMClient.Create(Self);
  111. try
  112. aConfig:=ChangeFileExt(paramstr(0),'-serviceaccount.json');
  113. Sender.LogFile:=ChangeFileExt(paramstr(0),'.log');
  114. Sender.InitServiceAccount(aConfig,'');
  115. Sender.OnNewBearerToken:=@HandleNewAccessToken;
  116. if FileExists(AccessTokenFile) then
  117. Sender.BearerToken.LoadFromFile(AccessTokenFile);
  118. Sender.Send(Msg,aToken);
  119. finally
  120. Sender.Free;
  121. end;
  122. end;
  123. procedure TdmMessaging.SendNotificationExecute(Sender: TObject; const Params: TJSONData; out Res: TJSONData);
  124. var
  125. Parms: TJSONArray absolute params;
  126. Obj : TJSONObject;
  127. Msg : TNotificationMessage;
  128. begin
  129. If Parms.Count<>1 then
  130. Raise Exception.Create('Invalid param count');
  131. if Parms[0].JSONType<>jtObject then
  132. Raise Exception.Create('Invalid notification');
  133. Obj:=Parms.Objects[0];
  134. Msg:=TNotificationMessage.Create;
  135. try
  136. Msg.Title:=Obj.Get('title',Msg.Title);
  137. Msg.Body:=Obj.Get('body',Msg.Body);
  138. Msg.Image:=Obj.Get('image',Msg.Image);
  139. SendMessage(Msg);
  140. finally
  141. Msg.Free;
  142. end;
  143. end;
  144. initialization
  145. JSONRPCHandlerManager.RegisterDatamodule(TdmMessaging, 'Messaging');
  146. end.