From a0741d99b80d7da1c063853382756b3a9689f6a7 Mon Sep 17 00:00:00 2001 From: Gary Kim Date: Sun, 30 Aug 2020 07:49:26 -0400 Subject: Add TLSConfig to nctalk (#1195) Signed-off-by: Gary Kim --- vendor/gomod.garykim.dev/nc-talk/.drone.yml | 4 + vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md | 37 ++++++++ vendor/gomod.garykim.dev/nc-talk/README.md | 5 + .../nc-talk/constants/constants.go | 5 + vendor/gomod.garykim.dev/nc-talk/go.mod | 5 +- vendor/gomod.garykim.dev/nc-talk/go.sum | 13 +++ vendor/gomod.garykim.dev/nc-talk/gonctalk.go | 4 + vendor/gomod.garykim.dev/nc-talk/ocs/message.go | 104 +++++++++++++++++++-- vendor/gomod.garykim.dev/nc-talk/ocs/ros.go | 38 ++++++++ vendor/gomod.garykim.dev/nc-talk/room/room.go | 53 ++++++++--- vendor/gomod.garykim.dev/nc-talk/user/user.go | 46 +++++++++ 11 files changed, 294 insertions(+), 20 deletions(-) create mode 100644 vendor/gomod.garykim.dev/nc-talk/ocs/ros.go (limited to 'vendor/gomod.garykim.dev') diff --git a/vendor/gomod.garykim.dev/nc-talk/.drone.yml b/vendor/gomod.garykim.dev/nc-talk/.drone.yml index c57fa083..f2367e4d 100644 --- a/vendor/gomod.garykim.dev/nc-talk/.drone.yml +++ b/vendor/gomod.garykim.dev/nc-talk/.drone.yml @@ -7,6 +7,10 @@ steps: image: golangci/golangci-lint:latest-alpine commands: - golangci-lint run + - name: test + image: golang:1.13 + commands: + - go test ./... - name: build-test image: golang:1.13 commands: diff --git a/vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md b/vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md index 40d50615..405a2112 100644 --- a/vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md +++ b/vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md @@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.1.1](https://github.com/gary-kim/go-nc-talk/tree/v0.1.1) - 2020-08-24 + +[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.1.0...v0.1.1) + +### Fixed + +- ROS type should be of ROST type [\#12](https://github.com/gary-kim/go-nc-talk/pull/12) ([@gary-kim](https://github.com/gary-kim)) +- Fix error when sending a message with no RCS data [\#10](https://github.com/gary-kim/go-nc-talk/pull/10) ([@gary-kim](https://github.com/gary-kim)) + +## [v0.1.0](https://github.com/gary-kim/go-nc-talk/tree/v0.1.0) - 2020-08-13 + +[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.0.2...v0.1.0) + +### Added + +- Add TLSConfig [\#9](https://github.com/gary-kim/go-nc-talk/pull/9) ([@gary-kim](https://github.com/gary-kim)) +- Add Software using this library in README [\#8](https://github.com/gary-kim/go-nc-talk/pull/8) ([@gary-kim](https://github.com/gary-kim)) +- Add some basic tests [\#7](https://github.com/gary-kim/go-nc-talk/pull/7) ([@gary-kim](https://github.com/gary-kim)) +- Add support for downloading files [\#1](https://github.com/gary-kim/go-nc-talk/pull/1) ([@gary-kim](https://github.com/gary-kim)) + +### Fixed + +- Return error on blank token [\#6](https://github.com/gary-kim/go-nc-talk/pull/6) ([@gary-kim](https://github.com/gary-kim)) +- Add v0.0.2 to changelog [\#4](https://github.com/gary-kim/go-nc-talk/pull/4) ([@gary-kim](https://github.com/gary-kim)) + +## [v0.0.2](https://github.com/gary-kim/go-nc-talk/tree/v0.0.2) - 2020-07-26 + +[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.0.1...v0.0.2) + +### Changed + +- Add installation instructions to README.md [\#2](https://github.com/gary-kim/go-nc-talk/pull/2) ([@gary-kim](https://github.com/gary-kim)) + +### Fixed + +- Fix Capabilities Request [\#3](https://github.com/gary-kim/go-nc-talk/pull/3) ([@gary-kim](https://github.com/gary-kim)) + ## [v0.0.1](https://github.com/gary-kim/riotchat/tree/v0.0.1) - 2020-07-10 * First release diff --git a/vendor/gomod.garykim.dev/nc-talk/README.md b/vendor/gomod.garykim.dev/nc-talk/README.md index 54300182..efa87c6c 100644 --- a/vendor/gomod.garykim.dev/nc-talk/README.md +++ b/vendor/gomod.garykim.dev/nc-talk/README.md @@ -15,6 +15,11 @@ GO111MODULE=on go get gomod.garykim.dev/nc-talk Check out the documentation for the package [here](https://pkg.go.dev/gomod.garykim.dev/nc-talk). + +### Software using this library + +* [Matterbridge](https://github.com/42wim/matterbridge) + ### License Copyright © 2020 Gary Kim <>, All Rights Reserved diff --git a/vendor/gomod.garykim.dev/nc-talk/constants/constants.go b/vendor/gomod.garykim.dev/nc-talk/constants/constants.go index de56f162..c70e4daa 100644 --- a/vendor/gomod.garykim.dev/nc-talk/constants/constants.go +++ b/vendor/gomod.garykim.dev/nc-talk/constants/constants.go @@ -18,3 +18,8 @@ const ( // BaseEndpoint is the api endpoint for Nextcloud Talk BaseEndpoint = "/ocs/v2.php/apps/spreed/api/v1/" ) + +// RemoteDavEndpoint returns the endpoint for the Dav API for Nextcloud +func RemoteDavEndpoint(username string, davType string) string { + return "/remote.php/dav/" + username + "/" + davType + "/" +} diff --git a/vendor/gomod.garykim.dev/nc-talk/go.mod b/vendor/gomod.garykim.dev/nc-talk/go.mod index f5a4afd9..1aa51ff7 100644 --- a/vendor/gomod.garykim.dev/nc-talk/go.mod +++ b/vendor/gomod.garykim.dev/nc-talk/go.mod @@ -2,4 +2,7 @@ module gomod.garykim.dev/nc-talk go 1.13 -require github.com/monaco-io/request v1.0.3 +require ( + github.com/monaco-io/request v1.0.4 + github.com/stretchr/testify v1.6.1 +) diff --git a/vendor/gomod.garykim.dev/nc-talk/go.sum b/vendor/gomod.garykim.dev/nc-talk/go.sum index 9f29c486..b4d32468 100644 --- a/vendor/gomod.garykim.dev/nc-talk/go.sum +++ b/vendor/gomod.garykim.dev/nc-talk/go.sum @@ -1,2 +1,15 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/monaco-io/request v1.0.3 h1:FsiIwXCCbHEyWx9A7lgg6JBTMHhHlEEsADsgAOvZ9HA= github.com/monaco-io/request v1.0.3/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ= +github.com/monaco-io/request v1.0.4 h1:AbogA+IvPOWqyGZIFU7kSb8YS2Jv5Dnl5ncMj8cQV+o= +github.com/monaco-io/request v1.0.4/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/gomod.garykim.dev/nc-talk/gonctalk.go b/vendor/gomod.garykim.dev/nc-talk/gonctalk.go index e334fef2..727d5006 100644 --- a/vendor/gomod.garykim.dev/nc-talk/gonctalk.go +++ b/vendor/gomod.garykim.dev/nc-talk/gonctalk.go @@ -21,6 +21,8 @@ import ( // NewUser returns a TalkUser instance // The url should be the full URL of the Nextcloud instance (e.g. https://cloud.mydomain.me) +// +// Deprecated: Use user.NewUser instead for more options and error checks func NewUser(url string, username string, password string) *user.TalkUser { return &user.TalkUser{ NextcloudURL: url, @@ -31,6 +33,8 @@ func NewUser(url string, username string, password string) *user.TalkUser { // NewRoom returns a new TalkRoom instance // Token should be the Nextcloud Room Token (e.g. "d6zoa2zs" if the room URL is https://cloud.mydomain.me/call/d6zoa2zs) +// +// Deprecated: Use room.NewRoom instead for extra error checks. func NewRoom(tuser *user.TalkUser, token string) *room.TalkRoom { tr := &room.TalkRoom{ User: tuser, diff --git a/vendor/gomod.garykim.dev/nc-talk/ocs/message.go b/vendor/gomod.garykim.dev/nc-talk/ocs/message.go index 6093e638..e23078de 100644 --- a/vendor/gomod.garykim.dev/nc-talk/ocs/message.go +++ b/vendor/gomod.garykim.dev/nc-talk/ocs/message.go @@ -14,6 +14,11 @@ package ocs +import ( + "encoding/json" + "strings" +) + // MessageType describes what kind of message a returned Nextcloud Talk message is type MessageType string @@ -30,23 +35,108 @@ const ( // TalkRoomMessageData describes the data part of a ocs response for a Talk room message type TalkRoomMessageData struct { - Message string `json:"message"` - ID int `json:"id"` - ActorID string `json:"actorId"` - ActorDisplayName string `json:"actorDisplayName"` - SystemMessage string `json:"systemMessage"` - Timestamp int `json:"timestamp"` - MessageType MessageType `json:"messageType"` + Message string `json:"message"` + ID int `json:"id"` + ActorID string `json:"actorId"` + ActorDisplayName string `json:"actorDisplayName"` + SystemMessage string `json:"systemMessage"` + Timestamp int `json:"timestamp"` + MessageType MessageType `json:"messageType"` + MessageParameters map[string]RichObjectString `json:"-"` +} + +// talkRoomMessageParameters is used to unmarshal only MessageParameters +type talkRoomMessageParameters struct { + MessageParameters map[string]RichObjectString `json:"messageParameters"` +} + +// PlainMessage returns the message string with placeholders replaced +// +// * User and group placeholders will be replaced with the name of the user or group respectively. +// +// * File placeholders will be replaced with the name of the file. +func (m *TalkRoomMessageData) PlainMessage() string { + tr := m.Message + for key, value := range m.MessageParameters { + tr = strings.ReplaceAll(tr, "{"+key+"}", value.Name) + } + return tr } // TalkRoomMessage describes an ocs response for a Talk room message type TalkRoomMessage struct { + OCS talkRoomMessage `json:"ocs"` +} + +type talkRoomMessage struct { ocs TalkRoomMessage []TalkRoomMessageData `json:"data"` } +// TalkRoomMessageDataUnmarshal unmarshals given ocs request data and returns a TalkRoomMessageData +func TalkRoomMessageDataUnmarshal(data *[]byte) (*TalkRoomMessage, error) { + message := &TalkRoomMessage{} + err := json.Unmarshal(*data, message) + if err != nil { + return nil, err + } + + // Get RCS + var rcs struct { + OCS struct { + ocs + TalkRoomMessage []talkRoomMessageParameters `json:"data"` + } `json:"ocs"` + } + err = json.Unmarshal(*data, &rcs) + // There is no RCS data + if err != nil { + for i := range message.OCS.TalkRoomMessage { + message.OCS.TalkRoomMessage[i].MessageParameters = map[string]RichObjectString{} + } + return message, nil + } + + // There is RCS data + for i := range message.OCS.TalkRoomMessage { + message.OCS.TalkRoomMessage[i].MessageParameters = rcs.OCS.TalkRoomMessage[i].MessageParameters + } + return message, nil +} + // TalkRoomSentResponse describes an ocs response for what is returned when a message is sent type TalkRoomSentResponse struct { + OCS talkRoomSentResponse `json:"ocs"` +} + +type talkRoomSentResponse struct { ocs TalkRoomMessage TalkRoomMessageData `json:"data"` } + +// TalkRoomSentResponseUnmarshal unmarshals given ocs request data and returns a TalkRoomMessageData +func TalkRoomSentResponseUnmarshal(data *[]byte) (*TalkRoomSentResponse, error) { + message := &TalkRoomSentResponse{} + err := json.Unmarshal(*data, message) + if err != nil { + return nil, err + } + + // Get RCS + var rcs struct { + OCS struct { + ocs + TalkRoomMessage talkRoomMessageParameters `json:"data"` + } `json:"ocs"` + } + err = json.Unmarshal(*data, &rcs) + // There is no RCS data + if err != nil { + message.OCS.TalkRoomMessage.MessageParameters = map[string]RichObjectString{} + return message, nil + } + + // There is RCS data + message.OCS.TalkRoomMessage.MessageParameters = rcs.OCS.TalkRoomMessage.MessageParameters + return message, nil +} diff --git a/vendor/gomod.garykim.dev/nc-talk/ocs/ros.go b/vendor/gomod.garykim.dev/nc-talk/ocs/ros.go new file mode 100644 index 00000000..82f72bb0 --- /dev/null +++ b/vendor/gomod.garykim.dev/nc-talk/ocs/ros.go @@ -0,0 +1,38 @@ +// Copyright (c) 2020 Gary Kim , All Rights Reserved +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// File describes Nextcloud's Rich Object Strings (https://github.com/nextcloud/server/issues/1706) + +package ocs + +// RichObjectString describes the content of placeholders in TalkRoomMessageData +type RichObjectString struct { + Type RichObjectStringType `json:"type"` + ID string `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + Link string `json:"link"` +} + +// RichObjectStringType describes what a rich object string is describing +type RichObjectStringType string + +const ( + // ROSTypeUser describes a rich object string that is a user + ROSTypeUser RichObjectStringType = "user" + // ROSTypeGroup describes a rich object string that is a group + ROSTypeGroup RichObjectStringType = "group" + // ROSTypeFile describes a rich object string that is a file + ROSTypeFile RichObjectStringType = "file" +) diff --git a/vendor/gomod.garykim.dev/nc-talk/room/room.go b/vendor/gomod.garykim.dev/nc-talk/room/room.go index d8faf7c4..5452993d 100644 --- a/vendor/gomod.garykim.dev/nc-talk/room/room.go +++ b/vendor/gomod.garykim.dev/nc-talk/room/room.go @@ -16,7 +16,6 @@ package room import ( "context" - "encoding/json" "errors" "io/ioutil" "time" @@ -28,12 +27,38 @@ import ( "gomod.garykim.dev/nc-talk/user" ) +var ( + // ErrEmptyToken is returned when the room token is empty + ErrEmptyToken = errors.New("given an empty token") + // ErrRoomNotFound is returned when a room with the given token could not be found + ErrRoomNotFound = errors.New("room could not be found") + // ErrNotModeratorInLobby is returned when the room is in lobby mode but the user is not a moderator + ErrNotModeratorInLobby = errors.New("room is in lobby mode but user is not a moderator") + // ErrUnexpectedReturnCode is returned when the server did not respond with an expected return code + ErrUnexpectedReturnCode = errors.New("unexpected return code") +) + // TalkRoom represents a room in Nextcloud Talk type TalkRoom struct { User *user.TalkUser Token string } +// NewTalkRoom returns a new TalkRoom instance +// Token should be the Nextcloud Room Token (e.g. "d6zoa2zs" if the room URL is https://cloud.mydomain.me/call/d6zoa2zs) +func NewTalkRoom(tuser *user.TalkUser, token string) (*TalkRoom, error) { + if token == "" { + return nil, ErrEmptyToken + } + if tuser == nil { + return nil, user.ErrUserIsNil + } + return &TalkRoom{ + User: tuser, + Token: token, + }, nil +} + // SendMessage sends a message in the Talk room func (t *TalkRoom) SendMessage(msg string) (*ocs.TalkRoomMessageData, error) { url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token @@ -51,18 +76,22 @@ func (t *TalkRoom) SendMessage(msg string) (*ocs.TalkRoomMessageData, error) { return nil, err } if res.StatusCode() != 201 { - return nil, errors.New("unexpected return code") + return nil, ErrUnexpectedReturnCode } - var msgInfo struct { - OCS ocs.TalkRoomSentResponse `json:"ocs"` + msgInfo, err := ocs.TalkRoomSentResponseUnmarshal(&res.Data) + if err != nil { + return nil, err } - err = json.Unmarshal(res.Data, &msgInfo) return &msgInfo.OCS.TalkRoomMessage, err } // ReceiveMessages starts watching for new messages func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessageData, error) { c := make(chan ocs.TalkRoomMessageData) + err := t.TestConnection() + if err != nil { + return nil, err + } url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token requestParam := map[string]string{ "lookIntoFuture": "1", @@ -99,14 +128,11 @@ func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessag } if res.StatusCode == 200 { lastKnown = res.Header.Get("X-Chat-Last-Given") - var message struct { - OCS ocs.TalkRoomMessage `json:"ocs"` - } data, err := ioutil.ReadAll(res.Body) if err != nil { continue } - err = json.Unmarshal(data, &message) + message, err := ocs.TalkRoomMessageDataUnmarshal(&data) if err != nil { continue } @@ -121,6 +147,9 @@ func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessag // TestConnection tests the connection with the Nextcloud Talk instance and returns an error if it could not connect func (t *TalkRoom) TestConnection() error { + if t.Token == "" { + return ErrEmptyToken + } url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token requestParam := map[string]string{ "lookIntoFuture": "0", @@ -142,9 +171,9 @@ func (t *TalkRoom) TestConnection() error { case 304: return nil case 404: - return errors.New("room could not be found") + return ErrRoomNotFound case 412: - return errors.New("room is in lobby mode but user is not a moderator") + return ErrNotModeratorInLobby } - return errors.New("unknown return code") + return ErrUnexpectedReturnCode } diff --git a/vendor/gomod.garykim.dev/nc-talk/user/user.go b/vendor/gomod.garykim.dev/nc-talk/user/user.go index 03d7ec8b..2f8a3c0a 100644 --- a/vendor/gomod.garykim.dev/nc-talk/user/user.go +++ b/vendor/gomod.garykim.dev/nc-talk/user/user.go @@ -15,11 +15,14 @@ package user import ( + "crypto/tls" "encoding/json" + "errors" "strings" "github.com/monaco-io/request" + "gomod.garykim.dev/nc-talk/constants" "gomod.garykim.dev/nc-talk/ocs" ) @@ -27,14 +30,25 @@ const ( ocsCapabilitiesEndpoint = "/ocs/v2.php/cloud/capabilities" ) +var ( + // ErrUserIsNil is returned when a funciton is called with an nil user. + ErrUserIsNil = errors.New("user is nil") +) + // TalkUser represents a user of Nextcloud Talk type TalkUser struct { User string Pass string NextcloudURL string + Config *TalkUserConfig capabilities *Capabilities } +// TalkUserConfig is configuration options for TalkUsers +type TalkUserConfig struct { + TLSConfig *tls.Config +} + // Capabilities describes the capabilities that the Nextcloud Talk instance is capable of. Visit https://nextcloud-talk.readthedocs.io/en/latest/capabilities/ for more info. type Capabilities struct { AttachmentsFolder string `ocscapability:"config => attachments => folder"` @@ -70,6 +84,17 @@ type Capabilities struct { ChatReferenceID bool `ocscapability:"chat-reference-id"` } +// NewUser returns a TalkUser instance +// The url should be the full URL of the Nextcloud instance (e.g. https://cloud.mydomain.me) +func NewUser(url string, username string, password string, config *TalkUserConfig) (*TalkUser, error) { + return &TalkUser{ + NextcloudURL: url, + User: username, + Pass: password, + Config: config, + }, nil +} + // RequestClient returns a monaco-io that is preconfigured to make OCS API calls func (t *TalkUser) RequestClient(client request.Client) *request.Client { if client.Header == nil { @@ -91,6 +116,11 @@ func (t *TalkUser) RequestClient(client request.Client) *request.Client { client.URL = t.NextcloudURL + "/" + client.URL } + // Set TLS Config + if t.Config != nil { + client.TLSConfig = t.Config.TLSConfig + } + return &client } @@ -166,3 +196,19 @@ func sliceContains(s []string, search string) bool { } return false } + +// DownloadFile downloads the file at the given path +// +// Meant to be used with rich object string's path. +func (t *TalkUser) DownloadFile(path string) (data *[]byte, err error) { + url := t.NextcloudURL + constants.RemoteDavEndpoint(t.User, "files") + path + c := t.RequestClient(request.Client{ + URL: url, + }) + res, err := c.Do() + if err != nil || res.StatusCode() != 200 { + return + } + data = &res.Data + return +} -- cgit v1.2.3