@@ -2,12 +2,15 @@ package handlers
22
33import (
44 "bytes"
5+ "context"
56 "crypto/ed25519"
67 "encoding/hex"
78 "encoding/json"
89 "fmt"
910 "os"
1011
12+ "github.com/NdoleStudio/httpsms/pkg/entities"
13+
1114 "github.com/google/uuid"
1215
1316 "github.com/NdoleStudio/httpsms/pkg/repositories"
@@ -23,10 +26,13 @@ import (
2326// DiscordHandler handles discord events
2427type DiscordHandler struct {
2528 handler
26- logger telemetry.Logger
27- tracer telemetry.Tracer
28- validator * validators.DiscordHandlerValidator
29- service * services.DiscordService
29+ logger telemetry.Logger
30+ tracer telemetry.Tracer
31+ billingService * services.BillingService
32+ messageValidator * validators.MessageHandlerValidator
33+ validator * validators.DiscordHandlerValidator
34+ service * services.DiscordService
35+ messageService * services.MessageService
3036}
3137
3238// NewDiscordHandler creates a new DiscordHandler
@@ -35,12 +41,18 @@ func NewDiscordHandler(
3541 tracer telemetry.Tracer ,
3642 validator * validators.DiscordHandlerValidator ,
3743 service * services.DiscordService ,
44+ messageService * services.MessageService ,
45+ billingService * services.BillingService ,
46+ messageValidator * validators.MessageHandlerValidator ,
3847) (h * DiscordHandler ) {
3948 return & DiscordHandler {
40- logger : logger .WithService (fmt .Sprintf ("%T" , h )),
41- tracer : tracer ,
42- validator : validator ,
43- service : service ,
49+ logger : logger .WithService (fmt .Sprintf ("%T" , h )),
50+ tracer : tracer ,
51+ validator : validator ,
52+ service : service ,
53+ messageService : messageService ,
54+ billingService : billingService ,
55+ messageValidator : messageValidator ,
4456 }
4557}
4658
@@ -244,7 +256,7 @@ func (h *DiscordHandler) Store(c *fiber.Ctx) error {
244256// @Failure 500 {object} responses.InternalServerError
245257// @Router /discord/event [post]
246258func (h * DiscordHandler ) Event (c * fiber.Ctx ) error {
247- _ , span , ctxLogger := h .tracer .StartFromFiberCtxWithLogger (c , h .logger )
259+ ctx , span , ctxLogger := h .tracer .StartFromFiberCtxWithLogger (c , h .logger )
248260 defer span .End ()
249261
250262 if verified := h .verifyInteraction (ctxLogger , c ); ! verified {
@@ -265,48 +277,147 @@ func (h *DiscordHandler) Event(c *fiber.Ctx) error {
265277 }
266278
267279 if payload ["type" ].(float64 ) == 2 {
280+ return h .sendSMS (ctx , c , payload )
281+ }
282+
283+ return h .responseBadRequest (c , stacktrace .NewError (fmt .Sprintf ("unknown type [%d]" , payload ["type" ])))
284+ }
285+
286+ func (h * DiscordHandler ) createRequest (payload map [string ]any ) requests.MessageSend {
287+ getOption := func (name string ) string {
288+ for _ , option := range payload ["data" ].(map [string ]any )["options" ].([]any ) {
289+ if option .(map [string ]any )["name" ].(string ) == name {
290+ return option .(map [string ]any )["value" ].(string )
291+ }
292+ }
293+ return ""
294+ }
295+ return requests.MessageSend {
296+ From : getOption ("from" ),
297+ To : getOption ("to" ),
298+ Content : getOption ("message" ),
299+ SIM : entities .SIMDefault ,
300+ }
301+ }
302+
303+ func (h * DiscordHandler ) sendSMS (ctx context.Context , c * fiber.Ctx , payload map [string ]any ) error {
304+ _ , span , ctxLogger := h .tracer .StartWithLogger (ctx , h .logger )
305+ defer span .End ()
306+
307+ discord , err := h .service .GetByServerID (ctx , payload ["guild_id" ].(string ))
308+ if err != nil {
309+ msg := fmt .Sprintf ("cannot get discord integration by server ID [%s]" , payload ["guild_id" ].(string ))
310+ ctxLogger .Error (h .tracer .WrapErrorSpan (span , stacktrace .Propagate (err , msg )))
268311 return c .JSON (
269312 fiber.Map {
270313 "type" : 4 ,
271- //"data": fiber.Map{
272- // "content": "✔ sending sms*",
273- //},
274314 "data" : fiber.Map {
275- "content" : "*⚠ could not send SMS message*" ,
315+ "content" : "**⚠️ error while sending message* *" ,
276316 "embeds" : []fiber.Map {
277317 {
278- "title" : "The to field is not a valid phone number " ,
318+ "title" : "We cannot find the link to your discord server to an account on [httpsms.com](https://httpsms.com/settings). " ,
279319 "color" : 14681092 ,
280320 },
321+ },
322+ },
323+ },
324+ )
325+ }
326+
327+ request := h .createRequest (payload )
328+ messageEmbed := fiber.Map {
329+ "fields" : []fiber.Map {
330+ {
331+ "name" : "From:" ,
332+ "value" : request .From ,
333+ "inline" : true ,
334+ },
335+ {
336+ "name" : "To:" ,
337+ "value" : request .To ,
338+ "inline" : true ,
339+ },
340+ {
341+ "name" : "Content:" ,
342+ "value" : request .Content ,
343+ },
344+ },
345+ }
346+
347+ if errors := h .messageValidator .ValidateMessageSend (ctx , discord .UserID , request .Sanitize ()); len (errors ) != 0 {
348+ msg := fmt .Sprintf ("validation errors [%s], while sending payload [%s]" , spew .Sdump (errors ), c .Body ())
349+ ctxLogger .Warn (stacktrace .NewError (msg ))
350+
351+ var embeds []fiber.Map
352+ for _ , value := range errors {
353+ embeds = append (embeds , fiber.Map {
354+ "title" : value [0 ],
355+ "color" : 14681092 ,
356+ })
357+ }
358+
359+ return c .JSON (
360+ fiber.Map {
361+ "type" : 4 ,
362+ "data" : fiber.Map {
363+ "content" : "**⚠️ error while sending message**" ,
364+ "embeds" : append (embeds , messageEmbed ),
365+ },
366+ },
367+ )
368+ }
369+
370+ if msg := h .billingService .IsEntitled (ctx , discord .UserID ); msg != nil {
371+ ctxLogger .Warn (stacktrace .NewError (fmt .Sprintf ("user with ID [%s] can't send a message" , discord .UserID )))
372+ return c .JSON (
373+ fiber.Map {
374+ "type" : 4 ,
375+ "data" : fiber.Map {
376+ "content" : "**⚠️ error while sending message**" ,
377+ "embeds" : append ([]fiber.Map {
281378 {
282- "title" : "The from field is not a valid phone number" ,
379+ "title" : msg ,
283380 "color" : 14681092 ,
284381 },
382+ }, messageEmbed ),
383+ },
384+ },
385+ )
386+ }
387+
388+ message , err := h .messageService .SendMessage (ctx , request .ToMessageSendParams (discord .UserID , c .OriginalURL ()))
389+ if err != nil {
390+ msg := fmt .Sprintf ("cannot send message with paylod [%s] from discord server [%s]" , c .Body (), discord .ServerID )
391+ ctxLogger .Error (stacktrace .Propagate (err , msg ))
392+ return c .JSON (
393+ fiber.Map {
394+ "type" : 4 ,
395+ "data" : fiber.Map {
396+ "content" : "**Could not send the message⚠️**" ,
397+ "embeds" : append ([]fiber.Map {
285398 {
286- "fields" : []fiber.Map {
287- {
288- "name" : "From:" ,
289- "value" : "+37259139660" ,
290- "inline" : true ,
291- },
292- {
293- "name" : "To:" ,
294- "value" : "+37259139661" ,
295- "inline" : true ,
296- },
297- {
298- "name" : "Content:" ,
299- "value" : "Hello World" ,
300- },
301- },
399+ "title" : "Internal server error while sending SMS. Please try again later or contact support." ,
400+ "color" : 14681092 ,
302401 },
303- },
402+ }, messageEmbed ),
304403 },
305404 },
306405 )
307406 }
308407
309- return h .responseBadRequest (c , stacktrace .NewError (fmt .Sprintf ("unknown type [%d]" , payload ["type" ])))
408+ messageEmbed ["fields" ] = append (messageEmbed ["fields" ].([]fiber.Map ), fiber.Map {
409+ "name" : "MessageID:" ,
410+ "value" : message .ID ,
411+ })
412+ return c .JSON (
413+ fiber.Map {
414+ "type" : 4 ,
415+ "data" : fiber.Map {
416+ "content" : "✔ sending sms" ,
417+ "embeds" : []fiber.Map {messageEmbed },
418+ },
419+ },
420+ )
310421}
311422
312423// verifyInteraction implements message verification of the discord interactions api
0 commit comments