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