Fixer to the Matrix ↔️ Facebook Messenger puppet bridge's handling of 1:1 chats

main.go 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. "config"
  7. "github.com/matrix-org/gomatrix"
  8. "github.com/sirupsen/logrus"
  9. )
  10. // Fixed variables
  11. var (
  12. // ErrEmptyRoomID is fired if no room ID localpart has been provided, and is
  13. // followed by the command's usage.
  14. ErrEmptyRoomID = fmt.Errorf("The room ID localpart cannot be empty")
  15. // ErrInvalidRoomMembersNb is fired if the number of joined members in the
  16. // room isn't 3 (i.e.: the user, their friend, and the Facebook bot).
  17. ErrInvalidRoomMembersNb = fmt.Errorf("Invalid number of members in the room: either the friend hasn't joined yet, or there's more than one friend in the room")
  18. // WarnNoAvatar is displayed if the friend doesn't have an avatar.
  19. WarnNoAvatar = "The friend doesn't have an avatar set"
  20. // WarnNoDisplayName is displayed if the friend doesn't have a display name.
  21. WarnNoDisplayName = "The friend doesn't have a display name set"
  22. // InfoAvatarUpdated is displayed if the room's avatar has been updated.
  23. InfoAvatarUpdated = "Room's avatar updated"
  24. // InfoNameUpdated is displayed if the room's name has been updated.
  25. InfoNameUpdated = "Room's name updated"
  26. // InfoProcessIsOver is displayed once the whole process is over, just before
  27. // exiting.
  28. InfoProcessIsOver = "The room has been fully updated. Don't forget to mark it as direct chat in Riot, and to edit its push rules."
  29. )
  30. // Command line flags
  31. var (
  32. localpart = flag.String("room-id-localpart", "", "Room ID localpart")
  33. configFile = flag.String("config", "config.yaml", "Configuration file")
  34. )
  35. // MRoomAvatarContent represents the content of the "m.room.avatar" state event.
  36. // https://matrix.org/docs/spec/client_server/r0.3.0.html#m-room-avatar
  37. type MRoomAvatarContent struct {
  38. URL string `json:"url"`
  39. }
  40. // MRoomNameContent represents the content of the "m.room.name" state event.
  41. // https://matrix.org/docs/spec/client_server/r0.3.0.html#m-room-name
  42. type MRoomNameContent struct {
  43. Name string `json:"name"`
  44. }
  45. func main() {
  46. logConfig()
  47. flag.Parse()
  48. if len(*localpart) == 0 {
  49. logrus.Error(ErrEmptyRoomID)
  50. flag.Usage()
  51. os.Exit(1)
  52. }
  53. cfg, err := config.Parse(*configFile)
  54. if err != nil {
  55. panic(err)
  56. }
  57. roomID := fmt.Sprintf("!%s:%s", *localpart, cfg.Matrix.ServerName)
  58. userID := fmt.Sprintf("@%s:%s", cfg.Matrix.Localpart, cfg.Matrix.ServerName)
  59. cli, err := gomatrix.NewClient(cfg.Matrix.HomeserverURL, userID, cfg.Matrix.AccessToken)
  60. if err != nil {
  61. logrus.Panic(err)
  62. }
  63. membersResp, err := cli.JoinedMembers(roomID)
  64. if err != nil {
  65. logrus.Panic(err)
  66. }
  67. displayNameResp, err := cli.GetOwnDisplayName()
  68. if err != nil {
  69. logrus.Panic(err)
  70. }
  71. if len(membersResp.Joined) != 3 {
  72. logrus.Error(ErrInvalidRoomMembersNb)
  73. os.Exit(1)
  74. }
  75. var avatarURL, displayName string
  76. for _, member := range membersResp.Joined {
  77. if member.DisplayName != nil && *(member.DisplayName) != displayNameResp.DisplayName {
  78. displayName = *(member.DisplayName)
  79. if member.AvatarURL != nil {
  80. avatarURL = *(member.AvatarURL)
  81. }
  82. }
  83. }
  84. logrus.WithFields(logrus.Fields{
  85. "display_name": displayName,
  86. "avatar_url": avatarURL,
  87. }).Info("Found the friend")
  88. if len(avatarURL) > 0 {
  89. if _, err := cli.SendStateEvent(
  90. roomID,
  91. "m.room.avatar",
  92. "",
  93. MRoomAvatarContent{
  94. URL: avatarURL,
  95. },
  96. ); err != nil {
  97. logrus.Panic(err)
  98. }
  99. logrus.Info(InfoAvatarUpdated)
  100. } else {
  101. logrus.Warn(WarnNoAvatar)
  102. }
  103. if len(displayName) > 0 {
  104. if _, err := cli.SendStateEvent(
  105. roomID,
  106. "m.room.name",
  107. "",
  108. MRoomNameContent{
  109. Name: displayName + " (Facebook)", // TODO: Allow custom suffix
  110. },
  111. ); err != nil {
  112. logrus.Panic(err)
  113. }
  114. logrus.Info(InfoNameUpdated)
  115. } else {
  116. logrus.Warn(WarnNoDisplayName)
  117. }
  118. logrus.Info(InfoProcessIsOver)
  119. }