call.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright (c) 2021 Tulir Asokan
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package whatsmeow
  7. import (
  8. "context"
  9. waBinary "go.mau.fi/whatsmeow/binary"
  10. "go.mau.fi/whatsmeow/types"
  11. "go.mau.fi/whatsmeow/types/events"
  12. )
  13. func (cli *Client) handleCallEvent(ctx context.Context, node *waBinary.Node) {
  14. defer cli.maybeDeferredAck(ctx, node)()
  15. if len(node.GetChildren()) != 1 {
  16. cli.dispatchEvent(&events.UnknownCallEvent{Node: node})
  17. return
  18. }
  19. ag := node.AttrGetter()
  20. child := node.GetChildren()[0]
  21. cag := child.AttrGetter()
  22. basicMeta := types.BasicCallMeta{
  23. From: ag.JID("from"),
  24. Timestamp: ag.UnixTime("t"),
  25. CallCreator: cag.JID("call-creator"),
  26. CallID: cag.String("call-id"),
  27. GroupJID: cag.OptionalJIDOrEmpty("group-jid"),
  28. }
  29. if basicMeta.CallCreator.Server == types.HiddenUserServer {
  30. basicMeta.CallCreatorAlt = cag.OptionalJIDOrEmpty("caller_pn")
  31. } else {
  32. // This may not actually exist
  33. basicMeta.CallCreatorAlt = cag.OptionalJIDOrEmpty("caller_lid")
  34. }
  35. switch child.Tag {
  36. case "offer":
  37. cli.dispatchEvent(&events.CallOffer{
  38. BasicCallMeta: basicMeta,
  39. CallRemoteMeta: types.CallRemoteMeta{
  40. RemotePlatform: ag.String("platform"),
  41. RemoteVersion: ag.String("version"),
  42. },
  43. Data: &child,
  44. })
  45. case "offer_notice":
  46. cli.dispatchEvent(&events.CallOfferNotice{
  47. BasicCallMeta: basicMeta,
  48. Media: cag.String("media"),
  49. Type: cag.String("type"),
  50. Data: &child,
  51. })
  52. case "relaylatency":
  53. cli.dispatchEvent(&events.CallRelayLatency{
  54. BasicCallMeta: basicMeta,
  55. Data: &child,
  56. })
  57. case "accept":
  58. cli.dispatchEvent(&events.CallAccept{
  59. BasicCallMeta: basicMeta,
  60. CallRemoteMeta: types.CallRemoteMeta{
  61. RemotePlatform: ag.String("platform"),
  62. RemoteVersion: ag.String("version"),
  63. },
  64. Data: &child,
  65. })
  66. case "preaccept":
  67. cli.dispatchEvent(&events.CallPreAccept{
  68. BasicCallMeta: basicMeta,
  69. CallRemoteMeta: types.CallRemoteMeta{
  70. RemotePlatform: ag.String("platform"),
  71. RemoteVersion: ag.String("version"),
  72. },
  73. Data: &child,
  74. })
  75. case "transport":
  76. cli.dispatchEvent(&events.CallTransport{
  77. BasicCallMeta: basicMeta,
  78. CallRemoteMeta: types.CallRemoteMeta{
  79. RemotePlatform: ag.String("platform"),
  80. RemoteVersion: ag.String("version"),
  81. },
  82. Data: &child,
  83. })
  84. case "terminate":
  85. cli.dispatchEvent(&events.CallTerminate{
  86. BasicCallMeta: basicMeta,
  87. Reason: cag.String("reason"),
  88. Data: &child,
  89. })
  90. case "reject":
  91. cli.dispatchEvent(&events.CallReject{
  92. BasicCallMeta: basicMeta,
  93. Data: &child,
  94. })
  95. default:
  96. cli.dispatchEvent(&events.UnknownCallEvent{Node: node})
  97. }
  98. }
  99. // RejectCall reject an incoming call.
  100. func (cli *Client) RejectCall(ctx context.Context, callFrom types.JID, callID string) error {
  101. ownID := cli.getOwnID()
  102. if ownID.IsEmpty() {
  103. return ErrNotLoggedIn
  104. }
  105. ownID, callFrom = ownID.ToNonAD(), callFrom.ToNonAD()
  106. return cli.sendNode(ctx, waBinary.Node{
  107. Tag: "call",
  108. Attrs: waBinary.Attrs{"id": cli.GenerateMessageID(), "from": ownID, "to": callFrom},
  109. Content: []waBinary.Node{{
  110. Tag: "reject",
  111. Attrs: waBinary.Attrs{"call-id": callID, "call-creator": callFrom, "count": "0"},
  112. Content: nil,
  113. }},
  114. })
  115. }