func TestSlackMeMessage(t *testing.T) {
	mockMatrixClient := &MockMatrixClient{}
	mockSlackClient := &MockSlackClient{}

	db := makeDB(t)
	rooms, err := NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}
	rooms.Link(matrix.NewRoom("!abc123:matrix.org"), "CANTINA")

	echoSuppresser := common.NewEchoSuppresser()
	users, err := NewUserMap(db, http.Client{}, rooms, echoSuppresser)
	if err != nil {
		t.Fatal(err)
	}
	matrixUser := matrix.NewUser("@nancy:st.andrews", mockMatrixClient)
	slackUser := &slack.User{"U34", mockSlackClient}
	users.Link(matrixUser, slackUser)

	bridge := Bridge{users, rooms, nil, nil, http.Client{}, echoSuppresser, Config{}}
	bridge.OnSlackMessage(slack.Message{
		Type:    "message",
		Channel: "CANTINA",
		User:    "******",
		Subtype: "me_message",
		Text:    "takes more chances",
	})

	want := []call{call{"SendEmote", []interface{}{"!abc123:matrix.org", "takes more chances"}}}
	if !reflect.DeepEqual(mockMatrixClient.calls, want) {
		t.Fatalf("Wrong Matrix calls, want %v got %v", want, mockMatrixClient.calls)
	}
}
func makeBridge(t *testing.T, db *sql.DB) *Bridge {
	mockMatrixClient := &MockMatrixClient{}
	mockSlackClient := &MockSlackClient{}

	rooms, err := NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}

	echoSuppresser := common.NewEchoSuppresser()
	users, err := NewUserMap(db, http.Client{}, rooms, echoSuppresser)
	if err != nil {
		t.Fatal(err)
	}
	matrixUser := matrix.NewUser("@nancy:st.andrews", mockMatrixClient)
	slackUser := &slack.User{"U34", mockSlackClient}
	users.Link(matrixUser, slackUser)

	// Subsequent calls should load link from database, but don't yet
	if err := rooms.Link(matrix.NewRoom("!abc123:matrix.org"), "CANTINA"); err != nil {
		t.Fatalf("Error linking rooms: %v", err)
	}

	return &Bridge{users, rooms, nil, nil, http.Client{}, echoSuppresser, Config{}}
}
func TestMatrixImageMessage(t *testing.T) {
	mockMatrixClient := &MockMatrixClient{}
	mockSlackClient := &MockSlackClient{}

	db := makeDB(t)
	rooms, err := NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}
	rooms.Link(matrix.NewRoom("!abc123:matrix.org"), "BOWLINGALLEY")

	echoSuppresser := common.NewEchoSuppresser()
	users, err := NewUserMap(db, http.Client{}, rooms, echoSuppresser)
	if err != nil {
		t.Fatal(err)
	}
	matrixUser := matrix.NewUser("@sean:st.andrews", mockMatrixClient)
	slackUser := &slack.User{"U35", mockSlackClient}
	users.Link(matrixUser, slackUser)

	bridge := Bridge{users, rooms, nil, nil, http.Client{}, echoSuppresser, Config{
		HomeserverBaseURL: "https://some.url:1234",
	}}
	bridge.OnMatrixRoomMessage(matrix.RoomMessage{
		Type:    "m.room.message",
		Content: []byte(`{"msgtype": "m.image", "body": "It's Nancy!", "url": "mxc://some.homeserver/abcDEF"}`),
		UserID:  "@sean:st.andrews",
		RoomID:  "!abc123:matrix.org",
	})

	want := []call{call{"SendImage", []interface{}{"BOWLINGALLEY", "It's Nancy!", "https://some.url:1234/_matrix/media/v1/download/some.homeserver/abcDEF"}}}
	if !reflect.DeepEqual(mockSlackClient.calls, want) {
		t.Fatalf("Wrong Slack calls, want %v got %v", want, mockSlackClient.calls)
	}
}
func TestSlackMessageWithImage(t *testing.T) {
	mockMatrixClient := &MockMatrixClient{}
	mockSlackClient := &MockSlackClient{}

	db := makeDB(t)
	rooms, err := NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}
	rooms.Link(matrix.NewRoom("!abc123:matrix.org"), "CANTINA")

	echoSuppresser := common.NewEchoSuppresser()
	users, err := NewUserMap(db, http.Client{}, rooms, echoSuppresser)
	if err != nil {
		t.Fatal(err)
	}
	matrixUser := matrix.NewUser("@nancy:st.andrews", mockMatrixClient)
	slackUser := &slack.User{"U34", mockSlackClient}
	users.Link(matrixUser, slackUser)

	bridge := Bridge{users, rooms, nil, nil, http.Client{}, echoSuppresser, Config{}}

	imageURL := "https://slack-files.com/files-pub/T02TMLW97-F0D2M81QA-38528eaf47/otters.jpg"
	bridge.OnSlackMessage(slack.Message{
		Type:    "message",
		Channel: "CANTINA",
		User:    "******",
		Text:    "Cute otter",
		File: &slack.File{
			MIMEType:       "image/jpeg",
			URL:            imageURL,
			OriginalHeight: 768,
			OriginalWidth:  1024,
			Size:           90,
			CommentsCount:  1,
			InitialComment: &slack.Comment{
				Comment: "omg",
				User:    "******",
			},
		},
	})

	want := []call{
		call{"SendImage", []interface{}{"!abc123:matrix.org", "otters.jpg", matrix.Image{
			URL: imageURL,
			Info: &matrix.ImageInfo{
				Width:    1024,
				Height:   768,
				MIMEType: "image/jpeg",
				Size:     90,
			},
		}}},
		call{"SendText", []interface{}{"!abc123:matrix.org", "omg"}},
	}
	if !reflect.DeepEqual(mockMatrixClient.calls, want) {
		t.Fatalf("Wrong Matrix calls, want:\n%v\ngot:\n%v", want, mockMatrixClient.calls)
	}
}
Exemple #5
0
func (b *Bridge) matrixUserFor(slackChannel, slackUserID string, matrixRoom *matrix.Room) *matrix.User {
	slackUserInRoom := b.SlackRoomMembers.Any(slackChannel)
	if slackUserInRoom == nil {
		return nil
	}
	resp, err := b.Client.Get(fmt.Sprintf("https://slack.com/api/users.info?token=%s&user=%s", slackUserInRoom.Client.AccessToken(), slackUserID))
	if err != nil {
		log.Printf("Error looking up user %q: %v", slackUserID, err)
		return nil
	}
	defer resp.Body.Close()
	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error reading user info response: %v", err)
		return nil
	}
	var r slackUserInfoResponse
	if err := json.Unmarshal(respBytes, &r); err != nil {
		log.Printf("Error unmarshaling user info response: %v (%s)", err, string(respBytes))
		return nil
	}

	if r.User == nil {
		log.Printf("Ignoring slack message from non-slack user - probably our own Matrix bot")
		return nil
	}

	b.MatrixUsers.Mu.Lock()
	matrixUserID := b.Config.UserPrefix + r.User.Name + ":" + b.Config.HomeserverName
	user := b.MatrixUsers.Get_Locked(matrixUserID)
	if user == nil {
		client := matrix.NewBotClient(b.Config.MatrixASAccessToken, matrixUserID, b.Client, b.Config.HomeserverBaseURL, b.MatrixEchoSuppresser)
		user = matrix.NewUser(matrixUserID, client)
		b.MatrixUsers.Save_Locked(user)
	}
	b.MatrixUsers.Mu.Unlock()

	if !user.Rooms(false)[matrixRoom.ID] {
		if err := b.matrixBotClient().JoinRoom(matrixRoom.ID); err != nil {
			log.Printf("Error joining bot to room: %v", err)
		}
		if err := b.matrixBotClient().Invite(matrixRoom.ID, matrixUserID); err != nil {
			log.Printf("Error inviting to room: %v", err)
		}
		if err := user.JoinRoom(matrixRoom.ID); err != nil {
			log.Printf("Error joining room: %v", err)
			return nil
		}
	}
	return user
}
Exemple #6
0
func NewUserMap(db *sql.DB, httpClient http.Client, rooms *RoomMap, matrixEchoSuppresser *common.EchoSuppresser) (*UserMap, error) {
	m := &UserMap{
		matrixToSlack:        make(map[string]*slack.User),
		slackToMatrix:        make(map[string]*matrix.User),
		db:                   db,
		matrixEchoSuppresser: matrixEchoSuppresser,
	}

	rows, err := db.Query("SELECT id, slack_user_id, slack_access_token, matrix_user_id, matrix_access_token, matrix_homeserver FROM users ORDER BY id ASC")
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		var id int32
		var slackID, matrixID string
		var slackToken, matrixToken, matrixHomeserver sql.NullString
		if err := rows.Scan(&id, &slackID, &slackToken, &matrixID, &matrixToken, &matrixHomeserver); err != nil {
			return nil, err
		}
		if !matrixToken.Valid {
			log.Printf("Skipping user matrix:%q = slack:%q because no matrix token", matrixID, slackID)
			continue
		}
		if !matrixHomeserver.Valid {
			log.Printf("Skipping user matrix:%q = slack:%q because no matrix homeserver", matrixID, slackID)
			continue
		}
		if !slackToken.Valid {
			log.Printf("Skipping user matrix:%q = slack:%q because no slack token", matrixID, slackID)
			continue
		}
		matrixClient := matrix.NewClient(matrixToken.String, httpClient, matrixHomeserver.String, m.matrixEchoSuppresser)
		matrixUser := matrix.NewUser(matrixID, matrixClient)

		slackClient := slack.NewClient(slackToken.String, httpClient, rooms.ShouldNotify)
		slackUser := &slack.User{slackID, slackClient}

		if err := m.Link(matrixUser, slackUser); err != nil {
			return nil, err
		}
	}
	if rows.Err() != nil {
		return nil, rows.Err()
	}
	return m, nil
}
func TestUserMapLoadsConfig(t *testing.T) {
	dir, err := ioutil.TempDir("", "testdb")
	if err != nil {
		t.Fatal(err)
	}
	file := path.Join(dir, "sqlite3.db")
	db := makeDBAt(t, file)
	rooms, err := NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}
	users, err := NewUserMap(db, http.Client{}, rooms, common.NewEchoSuppresser())
	if err != nil {
		t.Fatal(err)
	}
	matrixID := "@foo:somewhere.com"
	slackID := "bar"
	matrixUser := matrix.NewUser(matrixID, &MockMatrixClient{})
	users.Link(matrixUser, &slack.User{slackID, &MockSlackClient{}})
	db.Close()

	db, err = sql.Open("sqlite3", file)
	if err != nil {
		t.Fatal(err)
	}
	rooms, err = NewRoomMap(db)
	if err != nil {
		t.Fatal(err)
	}
	users, err = NewUserMap(db, http.Client{}, rooms, common.NewEchoSuppresser())
	if err != nil {
		t.Fatal(err)
	}
	got := users.SlackForMatrix(matrixID)
	if got == nil {
		t.Fatalf("got nil user, want user ID %q", slackID)
	}
	if got.UserID != slackID {
		t.Errorf("want %q got %q", slackID, got.UserID)
	}
}