summaryrefslogtreecommitdiffstats
path: root/bridge/nctalk/nctalk.go
blob: 40836a4f4a24b6ae2b09a5451fd9eedaf922002e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package nctalk

import (
	"context"
	"crypto/tls"
	"strconv"

	"github.com/42wim/matterbridge/bridge"
	"github.com/42wim/matterbridge/bridge/config"

	talk "gomod.garykim.dev/nc-talk"
	"gomod.garykim.dev/nc-talk/ocs"
	"gomod.garykim.dev/nc-talk/room"
	"gomod.garykim.dev/nc-talk/user"
)

type Btalk struct {
	user  *user.TalkUser
	rooms []Broom
	*bridge.Config
}

func New(cfg *bridge.Config) bridge.Bridger {
	return &Btalk{Config: cfg}
}

type Broom struct {
	room      *room.TalkRoom
	ctx       context.Context
	ctxCancel context.CancelFunc
}

func (b *Btalk) Connect() error {
	b.Log.Info("Connecting")
	tconfig := &user.TalkUserConfig{
		TLSConfig: &tls.Config{
			InsecureSkipVerify: b.GetBool("SkipTLSVerify"), //nolint:gosec
		},
	}
	var err error
	b.user, err = user.NewUser(b.GetString("Server"), b.GetString("Login"), b.GetString("Password"), tconfig)
	if err != nil {
		b.Log.Error("Config could not be used")
		return err
	}
	_, err = b.user.Capabilities()
	if err != nil {
		b.Log.Error("Cannot Connect")
		return err
	}
	b.Log.Info("Connected")
	return nil
}

func (b *Btalk) Disconnect() error {
	for _, r := range b.rooms {
		r.ctxCancel()
	}
	return nil
}

func (b *Btalk) JoinChannel(channel config.ChannelInfo) error {
	newRoom := Broom{
		room: talk.NewRoom(b.user, channel.Name),
	}
	newRoom.ctx, newRoom.ctxCancel = context.WithCancel(context.Background())
	c, err := newRoom.room.ReceiveMessages(newRoom.ctx)
	if err != nil {
		return err
	}
	b.rooms = append(b.rooms, newRoom)
	go func() {
		for msg := range c {
			// ignore messages that are one of the following
			// * not a message from a user
			// * from ourselves
			if msg.MessageType != ocs.MessageComment || msg.ActorID == b.user.User {
				continue
			}
			remoteMessage := config.Message{
				Text:     msg.Message,
				Channel:  newRoom.room.Token,
				Username: msg.ActorDisplayName,
				UserID:   msg.ActorID,
				Account:  b.Account,
			}
			// It is possible for the ID to not be set on older versions of Talk so we only set it if
			// the ID is not blank
			if msg.ID != 0 {
				remoteMessage.ID = strconv.Itoa(msg.ID)
			}
			b.Log.Debugf("<= Message is %#v", remoteMessage)
			b.Remote <- remoteMessage
		}
	}()
	return nil
}

func (b *Btalk) Send(msg config.Message) (string, error) {
	r := b.getRoom(msg.Channel)
	if r == nil {
		b.Log.Errorf("Could not find room for %v", msg.Channel)
		return "", nil
	}

	// Talk currently only supports sending normal messages
	if msg.Event != "" {
		return "", nil
	}
	sentMessage, err := r.room.SendMessage(msg.Username + msg.Text)
	if err != nil {
		b.Log.Errorf("Could not send message to room %v from %v: %v", msg.Channel, msg.Username, err)
		return "", nil
	}
	return strconv.Itoa(sentMessage.ID), nil
}

func (b *Btalk) getRoom(token string) *Broom {
	for _, r := range b.rooms {
		if r.room.Token == token {
			return &r
		}
	}
	return nil
}