summaryrefslogtreecommitdiffstats
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go5
-rw-r--r--vendor/github.com/disintegration/imaging/.travis.yml12
-rw-r--r--vendor/github.com/disintegration/imaging/LICENSE21
-rw-r--r--vendor/github.com/disintegration/imaging/README.md226
-rw-r--r--vendor/github.com/disintegration/imaging/adjust.go253
-rw-r--r--vendor/github.com/disintegration/imaging/convolution.go148
-rw-r--r--vendor/github.com/disintegration/imaging/doc.go7
-rw-r--r--vendor/github.com/disintegration/imaging/effects.go169
-rw-r--r--vendor/github.com/disintegration/imaging/go.mod3
-rw-r--r--vendor/github.com/disintegration/imaging/go.sum3
-rw-r--r--vendor/github.com/disintegration/imaging/histogram.go52
-rw-r--r--vendor/github.com/disintegration/imaging/io.go444
-rw-r--r--vendor/github.com/disintegration/imaging/resize.go595
-rw-r--r--vendor/github.com/disintegration/imaging/scanner.go285
-rw-r--r--vendor/github.com/disintegration/imaging/tools.go249
-rw-r--r--vendor/github.com/disintegration/imaging/transform.go268
-rw-r--r--vendor/github.com/disintegration/imaging/utils.go167
-rw-r--r--vendor/github.com/google/gops/agent/agent.go15
-rw-r--r--vendor/github.com/google/gops/agent/sockopt_unix.go36
-rw-r--r--vendor/github.com/google/gops/agent/sockopt_unsupported.go13
-rw-r--r--vendor/github.com/google/uuid/README.md2
-rw-r--r--vendor/github.com/google/uuid/marshal.go7
-rw-r--r--vendor/github.com/google/uuid/version1.go12
-rw-r--r--vendor/github.com/google/uuid/version4.go7
-rw-r--r--vendor/github.com/hashicorp/errwrap/errwrap.go9
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt545
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go12
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go1
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/client4.go209
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go114
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/config.go533
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go18
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go19
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/group.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go13
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/job.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go6
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go4
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/migration.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/permission.go25
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/role.go14
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/serialized_gen.go157
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/system.go4
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/thread.go36
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/user.go8
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/utils.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/version.go1
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/websocket_client.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/model/websocket_message.go18
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/autolink.go12
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/blocks.go13
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/inlines.go2
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/lines.go7
-rw-r--r--vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/markdown.go3
-rw-r--r--vendor/github.com/mattn/go-colorable/colorable_windows.go4
-rw-r--r--vendor/github.com/mattn/godown/godown.go4
-rw-r--r--vendor/github.com/pelletier/go-toml/azure-pipelines.yml40
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.json164
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.sh4
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.toml244
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.yml121
-rw-r--r--vendor/github.com/pelletier/go-toml/go.mod6
-rw-r--r--vendor/github.com/pelletier/go-toml/lexer.go100
-rw-r--r--vendor/github.com/pelletier/go-toml/marshal.go35
-rw-r--r--vendor/github.com/pelletier/go-toml/toml.go132
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_create.go13
-rw-r--r--vendor/github.com/pelletier/go-toml/tomltree_write.go2
-rw-r--r--vendor/github.com/slack-go/slack/.golangci.yml14
-rw-r--r--vendor/github.com/slack-go/slack/.travis.yml41
-rw-r--r--vendor/github.com/slack-go/slack/attachments.go2
-rw-r--r--vendor/github.com/slack-go/slack/block_action.go4
-rw-r--r--vendor/github.com/slack-go/slack/channels.go233
-rw-r--r--vendor/github.com/slack-go/slack/conversation.go22
-rw-r--r--vendor/github.com/slack-go/slack/files.go20
-rw-r--r--vendor/github.com/slack-go/slack/groups.go198
-rw-r--r--vendor/github.com/slack-go/slack/im.go66
-rw-r--r--vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go9
-rw-r--r--vendor/github.com/slack-go/slack/logger.go2
-rw-r--r--vendor/github.com/slack-go/slack/misc.go22
-rw-r--r--vendor/github.com/slack-go/slack/reminders.go15
-rw-r--r--vendor/github.com/slack-go/slack/security.go12
-rw-r--r--vendor/github.com/slack-go/slack/users.go16
82 files changed, 5399 insertions, 938 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go b/vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go
index 070a6896..8fd28f31 100644
--- a/vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go
+++ b/vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go
@@ -24,7 +24,10 @@ var SingleByteTokens = [...]string{"", "", "", "200", "400", "404", "500", "501"
"invite", "gif", "vcard", "frequent", "privacy", "blacklist", "whitelist",
"verify", "location", "document", "elapsed", "revoke_invite", "expiration",
"unsubscribe", "disable", "vname", "old_jid", "new_jid", "announcement",
- "locked", "prop", "label", "color", "call", "offer", "call-id"}
+ "locked", "prop", "label", "color", "call", "offer", "call-id",
+ "quick_reply", "sticker", "pay_t", "accept", "reject", "sticker_pack",
+ "invalid", "canceled", "missed", "connected", "result", "audio",
+ "video", "recent"}
var doubleByteTokens = [...]string{}
diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml
new file mode 100644
index 00000000..7ae5e4b2
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/.travis.yml
@@ -0,0 +1,12 @@
+language: go
+go:
+ - "1.10.x"
+ - "1.11.x"
+ - "1.12.x"
+
+before_install:
+ - go get github.com/mattn/goveralls
+
+script:
+ - go test -v -race -cover
+ - $GOPATH/bin/goveralls -service=travis-ci
diff --git a/vendor/github.com/disintegration/imaging/LICENSE b/vendor/github.com/disintegration/imaging/LICENSE
new file mode 100644
index 00000000..a4144a9d
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2012 Grigory Dryapak
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/disintegration/imaging/README.md
new file mode 100644
index 00000000..a1fd764d
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/README.md
@@ -0,0 +1,226 @@
+# Imaging
+
+[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging)
+[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging)
+[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master)
+[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging)
+
+Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
+
+All the image processing functions provided by the package accept any image type that implements `image.Image` interface
+as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha).
+
+## Installation
+
+ go get -u github.com/disintegration/imaging
+
+## Documentation
+
+http://godoc.org/github.com/disintegration/imaging
+
+## Usage examples
+
+A few usage examples can be found below. See the documentation for the full list of supported functions.
+
+### Image resizing
+
+```go
+// Resize srcImage to size = 128x128px using the Lanczos filter.
+dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
+
+// Resize srcImage to width = 800px preserving the aspect ratio.
+dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
+
+// Scale down srcImage to fit the 800x600px bounding box.
+dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
+
+// Resize and crop the srcImage to fill the 100x100px area.
+dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
+```
+
+Imaging supports image resizing using various resampling filters. The most notable ones:
+- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results.
+- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
+- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
+- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
+- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
+- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
+
+The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.
+
+**Resampling filters comparison**
+
+Original image:
+
+![srcImage](testdata/branches.png)
+
+The same image resized from 600x400px to 150x100px using different resampling filters.
+From faster (lower quality) to slower (higher quality):
+
+Filter | Resize result
+--------------------------|---------------------------------------------
+`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png)
+`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png)
+`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png)
+`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png)
+
+
+### Gaussian Blur
+
+```go
+dstImage := imaging.Blur(srcImage, 0.5)
+```
+
+Sigma parameter allows to control the strength of the blurring effect.
+
+Original image | Sigma = 0.5 | Sigma = 1.5
+-----------------------------------|----------------------------------------|---------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
+
+### Sharpening
+
+```go
+dstImage := imaging.Sharpen(srcImage, 0.5)
+```
+
+`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
+
+Original image | Sigma = 0.5 | Sigma = 1.5
+-----------------------------------|-------------------------------------------|------------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
+
+### Gamma correction
+
+```go
+dstImage := imaging.AdjustGamma(srcImage, 0.75)
+```
+
+Original image | Gamma = 0.75 | Gamma = 1.25
+-----------------------------------|------------------------------------------|-----------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
+
+### Contrast adjustment
+
+```go
+dstImage := imaging.AdjustContrast(srcImage, 20)
+```
+
+Original image | Contrast = 15 | Contrast = -15
+-----------------------------------|--------------------------------------------|-------------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png)
+
+### Brightness adjustment
+
+```go
+dstImage := imaging.AdjustBrightness(srcImage, 20)
+```
+
+Original image | Brightness = 10 | Brightness = -10
+-----------------------------------|----------------------------------------------|---------------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
+
+### Saturation adjustment
+
+```go
+dstImage := imaging.AdjustSaturation(srcImage, 20)
+```
+
+Original image | Saturation = 30 | Saturation = -30
+-----------------------------------|----------------------------------------------|---------------------------------------------
+![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png)
+
+## FAQ
+
+### Incorrect image orientation after processing (e.g. an image appears rotated after resizing)
+
+Most probably, the given image contains the EXIF orientation tag.
+The stadard `image/*` packages do not support loading and saving
+this kind of information. To fix the issue, try opening images with
+the `AutoOrientation` decode option. If this option is set to `true`,
+the image orientation is changed after decoding, according to the
+orientation tag (if present). Here's the example:
+
+```go
+img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
+```
+
+### What's the difference between `imaging` and `gift` packages?
+
+[imaging](https://github.com/disintegration/imaging)
+is designed to be a lightweight and simple image manipulation package.
+It provides basic image processing functions and a few helper functions
+such as `Open` and `Save`. It consistently returns *image.NRGBA image
+type (8 bits per channel, RGBA).
+
+[gift](https://github.com/disintegration/gift)
+supports more advanced image processing, for example, sRGB/Linear color
+space conversions. It also supports different output image types
+(e.g. 16 bits per channel) and provides easy-to-use API for chaining
+multiple processing steps together.
+
+## Example code
+
+```go
+package main
+
+import (
+ "image"
+ "image/color"
+ "log"
+
+ "github.com/disintegration/imaging"
+)
+
+func main() {
+ // Open a test image.
+ src, err := imaging.Open("testdata/flowers.png")
+ if err != nil {
+ log.Fatalf("failed to open image: %v", err)
+ }
+
+ // Crop the original image to 300x300px size using the center anchor.
+ src = imaging.CropAnchor(src, 300, 300, imaging.Center)
+
+ // Resize the cropped image to width = 200px preserving the aspect ratio.
+ src = imaging.Resize(src, 200, 0, imaging.Lanczos)
+
+ // Create a blurred version of the image.
+ img1 := imaging.Blur(src, 5)
+
+ // Create a grayscale version of the image with higher contrast and sharpness.
+ img2 := imaging.Grayscale(src)
+ img2 = imaging.AdjustContrast(img2, 20)
+ img2 = imaging.Sharpen(img2, 2)
+
+ // Create an inverted version of the image.
+ img3 := imaging.Invert(src)
+
+ // Create an embossed version of the image using a convolution filter.
+ img4 := imaging.Convolve3x3(
+ src,
+ [9]float64{
+ -1, -1, 0,
+ -1, 1, 1,
+ 0, 1, 1,
+ },
+ nil,
+ )
+
+ // Create a new image and paste the four produced images into it.
+ dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
+ dst = imaging.Paste(dst, img1, image.Pt(0, 0))
+ dst = imaging.Paste(dst, img2, image.Pt(0, 200))
+ dst = imaging.Paste(dst, img3, image.Pt(200, 0))
+ dst = imaging.Paste(dst, img4, image.Pt(200, 200))
+
+ // Save the resulting image as JPEG.
+ err = imaging.Save(dst, "testdata/out_example.jpg")
+ if err != nil {
+ log.Fatalf("failed to save image: %v", err)
+ }
+}
+```
+
+Output:
+
+![dstImage](testdata/out_example.jpg)
diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/disintegration/imaging/adjust.go
new file mode 100644
index 00000000..daaf1de8
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/adjust.go
@@ -0,0 +1,253 @@
+package imaging
+
+import (
+ "image"
+ "image/color"
+ "math"
+)
+
+// Grayscale produces a grayscale version of the image.
+func Grayscale(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ parallel(0, src.h, func(ys <-chan int) {
+ for y := range ys {
+ i := y * dst.Stride
+ src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
+ for x := 0; x < src.w; x++ {
+ d := dst.Pix[i : i+3 : i+3]
+ r := d[0]
+ g := d[1]
+ b := d[2]
+ f := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
+ y := uint8(f + 0.5)
+ d[0] = y
+ d[1] = y
+ d[2] = y
+ i += 4
+ }
+ }
+ })
+ return dst
+}
+
+// Invert produces an inverted (negated) version of the image.
+func Invert(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ parallel(0, src.h, func(ys <-chan int) {
+ for y := range ys {
+ i := y * dst.Stride
+ src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
+ for x := 0; x < src.w; x++ {
+ d := dst.Pix[i : i+3 : i+3]
+ d[0] = 255 - d[0]
+ d[1] = 255 - d[1]
+ d[2] = 255 - d[2]
+ i += 4
+ }
+ }
+ })
+ return dst
+}
+
+// AdjustSaturation changes the saturation of the image using the percentage parameter and returns the adjusted image.
+// The percentage must be in the range (-100, 100).
+// The percentage = 0 gives the original image.
+// The percentage = 100 gives the image with the saturation value doubled for each pixel.
+// The percentage = -100 gives the image with the saturation value zeroed for each pixel (grayscale).
+//
+// Examples:
+// dstImage = imaging.AdjustSaturation(srcImage, 25) // Increase image saturation by 25%.
+// dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%.
+//
+func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA {
+ percentage = math.Min(math.Max(percentage, -100), 100)
+ multiplier := 1 + percentage/100
+
+ return AdjustFunc(img, func(c color.NRGBA) color.NRGBA {
+ h, s, l := rgbToHSL(c.R, c.G, c.B)
+ s *= multiplier
+ if s > 1 {
+ s = 1
+ }
+ r, g, b := hslToRGB(h, s, l)
+ return color.NRGBA{r, g, b, c.A}
+ })
+}
+
+// AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image.
+// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
+// The percentage = -100 gives solid gray image.
+//
+// Examples:
+//
+// dstImage = imaging.AdjustContrast(srcImage, -10) // Decrease image contrast by 10%.
+// dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%.
+//
+func AdjustContrast(img image.Image, percentage float64) *image.NRGBA {
+ percentage = math.Min(math.Max(percentage, -100.0), 100.0)
+ lut := make([]uint8, 256)
+
+ v := (100.0 + percentage) / 100.0
+ for i := 0; i < 256; i++ {
+ switch {
+ case 0 <= v && v <= 1:
+ lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0)
+ case 1 < v && v < 2:
+ lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0)
+ default:
+ lut[i] = uint8(float64(i)/255.0+0.5) * 255
+ }
+ }
+
+ return adjustLUT(img, lut)
+}
+
+// AdjustBrightness changes the brightness of the image using the percentage parameter and returns the adjusted image.
+// The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
+// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.
+//
+// Examples:
+//
+// dstImage = imaging.AdjustBrightness(srcImage, -15) // Decrease image brightness by 15%.
+// dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%.
+//
+func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA {
+ percentage = math.Min(math.Max(percentage, -100.0), 100.0)
+ lut := make([]uint8, 256)
+
+ shift := 255.0 * percentage / 100.0
+ for i := 0; i < 256; i++ {
+ lut[i] = clamp(float64(i) + shift)
+ }
+
+ return adjustLUT(img, lut)
+}
+
+// AdjustGamma performs a gamma correction on the image and returns the adjusted image.
+// Gamma parameter must be positive. Gamma = 1.0 gives the original image.
+// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
+//
+// Example:
+//
+// dstImage = imaging.AdjustGamma(srcImage, 0.7)
+//
+func AdjustGamma(img image.Image, gamma float64) *image.NRGBA {
+ e := 1.0 / math.Max(gamma, 0.0001)
+ lut := make([]uint8, 256)
+
+ for i := 0; i < 256; i++ {
+ lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0)
+ }
+
+ return adjustLUT(img, lut)
+}
+
+// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image.
+// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
+// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
+// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
+// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
+//
+// Examples:
+//
+// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // Increase the contrast.
+// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // Decrease the contrast.
+//
+func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA {
+ if factor == 0 {
+ return Clone(img)
+ }
+
+ lut := make([]uint8, 256)
+ a := math.Min(math.Max(midpoint, 0.0), 1.0)
+ b := math.Abs(factor)
+ sig0 := sigmoid(a, b, 0)
+ sig1 := sigmoid(a, b, 1)
+ e := 1.0e-6
+
+ if factor > 0 {
+ for i := 0; i < 256; i++ {
+ x := float64(i) / 255.0
+ sigX := sigmoid(a, b, x)
+ f := (sigX - sig0) / (sig1 - sig0)
+ lut[i] = clamp(f * 255.0)
+ }
+ } else {
+ for i := 0; i < 256; i++ {
+ x := float64(i) / 255.0
+ arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e)
+ f := a - math.Log(1.0/arg-1.0)/b
+ lut[i] = clamp(f * 255.0)
+ }
+ }
+
+ return adjustLUT(img, lut)
+}
+
+func sigmoid(a, b, x float64) float64 {
+ return 1 / (1 + math.Exp(b*(a-x)))
+}
+
+// adjustLUT applies the given lookup table to the colors of the image.
+func adjustLUT(img image.Image, lut []uint8) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ lut = lut[0:256]
+ parallel(0, src.h, func(ys <-chan int) {
+ for y := range ys {
+ i := y * dst.Stride
+ src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
+ for x := 0; x < src.w; x++ {
+ d := dst.Pix[i : i+3 : i+3]
+ d[0] = lut[d[0]]
+ d[1] = lut[d[1]]
+ d[2] = lut[d[2]]
+ i += 4
+ }
+ }
+ })
+ return dst
+}
+
+// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image.
+//
+// Example:
+//
+// dstImage = imaging.AdjustFunc(
+// srcImage,
+// func(c color.NRGBA) color.NRGBA {
+// // Shift the red channel by 16.
+// r := int(c.R) + 16
+// if r > 255 {
+// r = 255
+// }
+// return color.NRGBA{uint8(r), c.G, c.B, c.A}
+// }
+// )
+//
+func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ parallel(0, src.h, func(ys <-chan int) {
+ for y := range ys {
+ i := y * dst.Stride
+ src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4])
+ for x := 0; x < src.w; x++ {
+ d := dst.Pix[i : i+4 : i+4]
+ r := d[0]
+ g := d[1]
+ b := d[2]
+ a := d[3]
+ c := fn(color.NRGBA{r, g, b, a})
+ d[0] = c.R
+ d[1] = c.G
+ d[2] = c.B
+ d[3] = c.A
+ i += 4
+ }
+ }
+ })
+ return dst
+}
diff --git a/vendor/github.com/disintegration/imaging/convolution.go b/vendor/github.com/disintegration/imaging/convolution.go
new file mode 100644
index 00000000..11eddc16
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/convolution.go
@@ -0,0 +1,148 @@
+package imaging
+
+import (
+ "image"
+)
+
+// ConvolveOptions are convolution parameters.
+type ConvolveOptions struct {
+ // If Normalize is true the kernel is normalized before convolution.
+ Normalize bool
+
+ // If Abs is true the absolute value of each color channel is taken after convolution.
+ Abs bool
+
+ // Bias is added to each color channel value after convolution.
+ Bias int
+}
+
+// Convolve3x3 convolves the image with the specified 3x3 convolution kernel.
+// Default parameters are used if a nil *ConvolveOptions is passed.
+func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA {
+ return convolve(img, kernel[:], options)
+}
+
+// Convolve5x5 convolves the image with the specified 5x5 convolution kernel.
+// Default parameters are used if a nil *ConvolveOptions is passed.
+func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA {
+ return convolve(img, kernel[:], options)
+}
+
+func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA {
+ src := toNRGBA(img)
+ w := src.Bounds().Max.X
+ h := src.Bounds().Max.Y
+ dst := image.NewNRGBA(image.Rect(0, 0, w, h))
+
+ if w < 1 || h < 1 {
+ return dst
+ }
+
+ if options == nil {
+ options = &ConvolveOptions{}
+ }
+
+ if options.Normalize {
+ normalizeKernel(kernel)
+ }
+
+ type coef struct {
+ x, y int
+ k float64
+ }
+ var coefs []coef
+ var m int
+
+ switch len(kernel) {
+ case 9:
+ m = 1
+ case 25:
+ m = 2
+ }
+
+ i := 0
+ for y := -m; y <= m; y++ {
+ for x := -m; x <= m; x++ {
+ if kernel[i] != 0 {
+ coefs = append(coefs, coef{x: x, y: y, k: kernel[i]})
+ }
+ i++
+ }
+ }
+
+ parallel(0, h, func(ys <-chan int) {
+ for y := range ys {
+ for x := 0; x < w; x++ {
+ var r, g, b float64
+ for _, c := range coefs {
+ ix := x + c.x
+ if ix < 0 {
+ ix = 0
+ } else if ix >= w {
+ ix = w - 1
+ }
+
+ iy := y + c.y
+ if iy < 0 {
+ iy = 0
+ } else if iy >= h {
+ iy = h - 1
+ }
+
+ off := iy*src.Stride + ix*4
+ s := src.Pix[off : off+3 : off+3]
+ r += float64(s[0]) * c.k
+ g += float64(s[1]) * c.k
+ b += float64(s[2]) * c.k
+ }
+
+ if options.Abs {
+ if r < 0 {
+ r = -r
+ }
+ if g < 0 {
+ g = -g
+ }
+ if b < 0 {
+ b = -b
+ }
+ }
+
+ if options.Bias != 0 {
+ r += float64(options.Bias)
+ g += float64(options.Bias)
+ b += float64(options.Bias)
+ }
+
+ srcOff := y*src.Stride + x*4
+ dstOff := y*dst.Stride + x*4
+ d := dst.Pix[dstOff : dstOff+4 : dstOff+4]
+ d[0] = clamp(r)
+ d[1] = clamp(g)
+ d[2] = clamp(b)
+ d[3] = src.Pix[srcOff+3]
+ }
+ }
+ })
+
+ return dst
+}
+
+func normalizeKernel(kernel []float64) {
+ var sum, sumpos float64
+ for i := range kernel {
+ sum += kernel[i]
+ if kernel[i] > 0 {
+ sumpos += kernel[i]
+ }
+ }
+ if sum != 0 {
+ for i := range kernel {
+ kernel[i] /= sum
+ }
+ } else if sumpos != 0 {
+ for i := range kernel {
+ kernel[i] /= sumpos
+ }
+ }
+}
diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/disintegration/imaging/doc.go
new file mode 100644
index 00000000..c98c9125
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/doc.go
@@ -0,0 +1,7 @@
+/*
+Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
+
+All the image processing functions provided by the package accept any image type that implements image.Image interface
+as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha).
+*/
+package imaging
diff --git a/vendor/github.com/disintegration/imaging/effects.go b/vendor/github.com/disintegration/imaging/effects.go
new file mode 100644
index 00000000..47316b70
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/effects.go
@@ -0,0 +1,169 @@
+package imaging
+
+import (
+ "image"
+ "math"
+)
+
+func gaussianBlurKernel(x, sigma float64) float64 {
+ return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi))
+}
+
+// Blur produces a blurred version of the image using a Gaussian function.
+// Sigma parameter must be positive and indicates how much the image will be blurred.
+//
+// Example:
+//
+// dstImage := imaging.Blur(srcImage, 3.5)
+//
+func Blur(img image.Image, sigma float64) *image.NRGBA {
+ if sigma <= 0 {
+ return Clone(img)
+ }
+
+ radius := int(math.Ceil(sigma * 3.0))
+ kernel := make([]float64, radius+1)
+
+ for i := 0; i <= radius; i++ {
+ kernel[i] = gaussianBlurKernel(float64(i), sigma)
+ }
+
+ return blurVertical(blurHorizontal(img, kernel), kernel)
+}
+
+func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ radius := len(kernel) - 1
+
+ parallel(0, src.h, func(ys <-chan int) {
+ scanLine := make([]uint8, src.w*4)
+ scanLineF := make([]float64, len(scanLine))
+ for y := range ys {
+ src.scan(0, y, src.w, y+1, scanLine)
+ for i, v := range scanLine {
+ scanLineF[i] = float64(v)
+ }
+ for x := 0; x < src.w; x++ {
+ min := x - radius
+ if min < 0 {
+ min = 0
+ }
+ max := x + radius
+ if max > src.w-1 {
+ max = src.w - 1
+ }
+ var r, g, b, a, wsum float64
+ for ix := min; ix <= max; ix++ {
+ i := ix * 4
+ weight := kernel[absint(x-ix)]
+ wsum += weight
+ s := scanLineF[i : i+4 : i+4]
+ wa := s[3] * weight
+ r += s[0] * wa
+ g += s[1] * wa
+ b += s[2] * wa
+ a += wa
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := y*dst.Stride + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a / wsum)
+ }
+ }
+ }
+ })
+
+ return dst
+}
+
+func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ radius := len(kernel) - 1
+
+ parallel(0, src.w, func(xs <-chan int) {
+ scanLine := make([]uint8, src.h*4)
+ scanLineF := make([]float64, len(scanLine))
+ for x := range xs {
+ src.scan(x, 0, x+1, src.h, scanLine)
+ for i, v := range scanLine {
+ scanLineF[i] = float64(v)
+ }
+ for y := 0; y < src.h; y++ {
+ min := y - radius
+ if min < 0 {
+ min = 0
+ }
+ max := y + radius
+ if max > src.h-1 {
+ max = src.h - 1
+ }
+ var r, g, b, a, wsum float64
+ for iy := min; iy <= max; iy++ {
+ i := iy * 4
+ weight := kernel[absint(y-iy)]
+ wsum += weight
+ s := scanLineF[i : i+4 : i+4]
+ wa := s[3] * weight
+ r += s[0] * wa
+ g += s[1] * wa
+ b += s[2] * wa
+ a += wa
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := y*dst.Stride + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a / wsum)
+ }
+ }
+ }
+ })
+
+ return dst
+}
+
+// Sharpen produces a sharpened version of the image.
+// Sigma parameter must be positive and indicates how much the image will be sharpened.
+//
+// Example:
+//
+// dstImage := imaging.Sharpen(srcImage, 3.5)
+//
+func Sharpen(img image.Image, sigma float64) *image.NRGBA {
+ if sigma <= 0 {
+ return Clone(img)
+ }
+
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ blurred := Blur(img, sigma)
+
+ parallel(0, src.h, func(ys <-chan int) {
+ scanLine := make([]uint8, src.w*4)
+ for y := range ys {
+ src.scan(0, y, src.w, y+1, scanLine)
+ j := y * dst.Stride
+ for i := 0; i < src.w*4; i++ {
+ val := int(scanLine[i])<<1 - int(blurred.Pix[j])
+ if val < 0 {
+ val = 0
+ } else if val > 0xff {
+ val = 0xff
+ }
+ dst.Pix[j] = uint8(val)
+ j++
+ }
+ }
+ })
+
+ return dst
+}
diff --git a/vendor/github.com/disintegration/imaging/go.mod b/vendor/github.com/disintegration/imaging/go.mod
new file mode 100644
index 00000000..a870810e
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/go.mod
@@ -0,0 +1,3 @@
+module github.com/disintegration/imaging
+
+require golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
diff --git a/vendor/github.com/disintegration/imaging/go.sum b/vendor/github.com/disintegration/imaging/go.sum
new file mode 100644
index 00000000..17bf7381
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/go.sum
@@ -0,0 +1,3 @@
+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
+golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/disintegration/imaging/histogram.go
new file mode 100644
index 00000000..c547fe82
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/histogram.go
@@ -0,0 +1,52 @@
+package imaging
+
+import (
+ "image"
+ "sync"
+)
+
+// Histogram returns a normalized histogram of an image.
+//
+// Resulting histogram is represented as an array of 256 floats, where
+// histogram[i] is a probability of a pixel being of a particular luminance i.
+func Histogram(img image.Image) [256]float64 {
+ var mu sync.Mutex
+ var histogram [256]float64
+ var total float64
+
+ src := newScanner(img)
+ if src.w == 0 || src.h == 0 {
+ return histogram
+ }
+
+ parallel(0, src.h, func(ys <-chan int) {
+ var tmpHistogram [256]float64
+ var tmpTotal float64
+ scanLine := make([]uint8, src.w*4)
+ for y := range ys {
+ src.scan(0, y, src.w, y+1, scanLine)
+ i := 0
+ for x := 0; x < src.w; x++ {
+ s := scanLine[i : i+3 : i+3]
+ r := s[0]
+ g := s[1]
+ b := s[2]
+ y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b)
+ tmpHistogram[int(y+0.5)]++
+ tmpTotal++
+ i += 4
+ }
+ }
+ mu.Lock()
+ for i := 0; i < 256; i++ {
+ histogram[i] += tmpHistogram[i]
+ }
+ total += tmpTotal
+ mu.Unlock()
+ })
+
+ for i := 0; i < 256; i++ {
+ histogram[i] = histogram[i] / total
+ }
+ return histogram
+}
diff --git a/vendor/github.com/disintegration/imaging/io.go b/vendor/github.com/disintegration/imaging/io.go
new file mode 100644
index 00000000..f6c6da86
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/io.go
@@ -0,0 +1,444 @@
+package imaging
+
+import (
+ "encoding/binary"
+ "errors"
+ "image"
+ "image/draw"
+ "image/gif"
+ "image/jpeg"
+ "image/png"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "golang.org/x/image/bmp"
+ "golang.org/x/image/tiff"
+)
+
+type fileSystem interface {
+ Create(string) (io.WriteCloser, error)
+ Open(string) (io.ReadCloser, error)
+}
+
+type localFS struct{}
+
+func (localFS) Create(name string) (io.WriteCloser, error) { return os.Create(name) }
+func (localFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) }
+
+var fs fileSystem = localFS{}
+
+type decodeConfig struct {
+ autoOrientation bool
+}
+
+var defaultDecodeConfig = decodeConfig{
+ autoOrientation: false,
+}
+
+// DecodeOption sets an optional parameter for the Decode and Open functions.
+type DecodeOption func(*decodeConfig)
+
+// AutoOrientation returns a DecodeOption that sets the auto-orientation mode.
+// If auto-orientation is enabled, the image will be transformed after decoding
+// according to the EXIF orientation tag (if present). By default it's disabled.
+func AutoOrientation(enabled bool) DecodeOption {
+ return func(c *decodeConfig) {
+ c.autoOrientation = enabled
+ }
+}
+
+// Decode reads an image from r.
+func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error) {
+ cfg := defaultDecodeConfig
+ for _, option := range opts {
+ option(&cfg)
+ }
+
+ if !cfg.autoOrientation {
+ img, _, err := image.Decode(r)
+ return img, err
+ }
+
+ var orient orientation
+ pr, pw := io.Pipe()
+ r = io.TeeReader(r, pw)
+ done := make(chan struct{})
+ go func() {
+ defer close(done)
+ orient = readOrientation(pr)
+ io.Copy(ioutil.Discard, pr)
+ }()
+
+ img, _, err := image.Decode(r)
+ pw.Close()
+ <-done
+ if err != nil {
+ return nil, err
+ }
+
+ return fixOrientation(img, orient), nil
+}
+
+// Open loads an image from file.
+//
+// Examples:
+//
+// // Load an image from file.
+// img, err := imaging.Open("test.jpg")
+//
+// // Load an image and transform it depending on the EXIF orientation tag (if present).
+// img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
+//
+func Open(filename string, opts ...DecodeOption) (image.Image, error) {
+ file, err := fs.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+ return Decode(file, opts...)
+}
+
+// Format is an image file format.
+type Format int
+
+// Image file formats.
+const (
+ JPEG Format = iota
+ PNG
+ GIF
+ TIFF
+ BMP
+)
+
+var formatExts = map[string]Format{
+ "jpg": JPEG,
+ "jpeg": JPEG,
+ "png": PNG,
+ "gif": GIF,
+ "tif": TIFF,
+ "tiff": TIFF,
+ "bmp": BMP,
+}
+
+var formatNames = map[Format]string{
+ JPEG: "JPEG",
+ PNG: "PNG",
+ GIF: "GIF",
+ TIFF: "TIFF",
+ BMP: "BMP",
+}
+
+func (f Format) String() string {
+ return formatNames[f]
+}
+
+// ErrUnsupportedFormat means the given image format is not supported.
+var ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
+
+// FormatFromExtension parses image format from filename extension:
+// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
+func FormatFromExtension(ext string) (Format, error) {
+ if f, ok := formatExts[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok {
+ return f, nil
+ }
+ return -1, ErrUnsupportedFormat
+}
+
+// FormatFromFilename parses image format from filename:
+// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
+func FormatFromFilename(filename string) (Format, error) {
+ ext := filepath.Ext(filename)
+ return FormatFromExtension(ext)
+}
+
+type encodeConfig struct {
+ jpegQuality int
+ gifNumColors int
+ gifQuantizer draw.Quantizer
+ gifDrawer draw.Drawer
+ pngCompressionLevel png.CompressionLevel
+}
+
+var defaultEncodeConfig = encodeConfig{
+ jpegQuality: 95,
+ gifNumColors: 256,
+ gifQuantizer: nil,
+ gifDrawer: nil,
+ pngCompressionLevel: png.DefaultCompression,
+}
+
+// EncodeOption sets an optional parameter for the Encode and Save functions.
+type EncodeOption func(*encodeConfig)
+
+// JPEGQuality returns an EncodeOption that sets the output JPEG quality.
+// Quality ranges from 1 to 100 inclusive, higher is better. Default is 95.
+func JPEGQuality(quality int) EncodeOption {
+ return func(c *encodeConfig) {
+ c.jpegQuality = quality
+ }
+}
+
+// GIFNumColors returns an EncodeOption that sets the maximum number of colors
+// used in the GIF-encoded image. It ranges from 1 to 256. Default is 256.
+func GIFNumColors(numColors int) EncodeOption {
+ return func(c *encodeConfig) {
+ c.gifNumColors = numColors
+ }
+}
+
+// GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce
+// a palette of the GIF-encoded image.
+func GIFQuantizer(quantizer draw.Quantizer) EncodeOption {
+ return func(c *encodeConfig) {
+ c.gifQuantizer = quantizer
+ }
+}
+
+// GIFDrawer returns an EncodeOption that sets the drawer that is used to convert
+// the source image to the desired palette of the GIF-encoded image.
+func GIFDrawer(drawer draw.Drawer) EncodeOption {
+ return func(c *encodeConfig) {
+ c.gifDrawer = drawer
+ }
+}
+
+// PNGCompressionLevel returns an EncodeOption that sets the compression level
+// of the PNG-encoded image. Default is png.DefaultCompression.
+func PNGCompressionLevel(level png.CompressionLevel) EncodeOption {
+ return func(c *encodeConfig) {
+ c.pngCompressionLevel = level
+ }
+}
+
+// Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP).
+func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error {
+ cfg := defaultEncodeConfig
+ for _, option := range opts {
+ option(&cfg)
+ }
+
+ switch format {
+ case JPEG:
+ if nrgba, ok := img.(*image.NRGBA); ok && nrgba.Opaque() {
+ rgba := &image.RGBA{
+ Pix: nrgba.Pix,
+ Stride: nrgba.Stride,
+ Rect: nrgba.Rect,
+ }
+ return jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality})
+ }
+ return jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality})
+
+ case PNG:
+ encoder := png.Encoder{CompressionLevel: cfg.pngCompressionLevel}
+ return encoder.Encode(w, img)
+
+ case GIF:
+ return gif.Encode(w, img, &gif.Options{
+ NumColors: cfg.gifNumColors,
+ Quantizer: cfg.gifQuantizer,
+ Drawer: cfg.gifDrawer,
+ })
+
+ case TIFF:
+ return tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
+
+ case BMP:
+ return bmp.Encode(w, img)
+ }
+
+ return ErrUnsupportedFormat
+}
+
+// Save saves the image to file with the specified filename.
+// The format is determined from the filename extension:
+// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
+//
+// Examples:
+//
+// // Save the image as PNG.
+// err := imaging.Save(img, "out.png")
+//
+// // Save the image as JPEG with optional quality parameter set to 80.
+// err := imaging.Save(img, "out.jpg", imaging.JPEGQuality(80))
+//
+func Save(img image.Image, filename string, opts ...EncodeOption) (err error) {
+ f, err := FormatFromFilename(filename)
+ if err != nil {
+ return err
+ }
+ file, err := fs.Create(filename)
+ if err != nil {
+ return err
+ }
+ err = Encode(file, img, f, opts...)
+ errc := file.Close()
+ if err == nil {
+ err = errc
+ }
+ return err
+}
+
+// orientation is an EXIF flag that specifies the transformation
+// that should be applied to image to display it correctly.
+type orientation int
+
+const (
+ orientationUnspecified = 0
+ orientationNormal = 1
+ orientationFlipH = 2
+ orientationRotate180 = 3
+ orientationFlipV = 4
+ orientationTranspose = 5
+ orientationRotate270 = 6
+ orientationTransverse = 7
+ orientationRotate90 = 8
+)
+
+// readOrientation tries to read the orientation EXIF flag from image data in r.
+// If the EXIF data block is not found or the orientation flag is not found
+// or any other error occures while reading the data, it returns the
+// orientationUnspecified (0) value.
+func readOrientation(r io.Reader) orientation {
+ const (
+ markerSOI = 0xffd8
+ markerAPP1 = 0xffe1
+ exifHeader = 0x45786966
+ byteOrderBE = 0x4d4d
+ byteOrderLE = 0x4949
+ orientationTag = 0x0112
+ )
+
+ // Check if JPEG SOI marker is present.
+ var soi uint16
+ if err := binary.Read(r, binary.BigEndian, &soi); err != nil {
+ return orientationUnspecified
+ }
+ if soi != markerSOI {
+ return orientationUnspecified // Missing JPEG SOI marker.
+ }
+
+ // Find JPEG APP1 marker.
+ for {
+ var marker, size uint16
+ if err := binary.Read(r, binary.BigEndian, &marker); err != nil {
+ return orientationUnspecified
+ }
+ if err := binary.Read(r, binary.BigEndian, &size); err != nil {
+ return orientationUnspecified
+ }
+ if marker>>8 != 0xff {
+ return orientationUnspecified // Invalid JPEG marker.
+ }
+ if marker == markerAPP1 {
+ break
+ }
+ if size < 2 {
+ return orientationUnspecified // Invalid block size.
+ }
+ if _, err := io.CopyN(ioutil.Discard, r, int64(size-2)); err != nil {
+ return orientationUnspecified
+ }
+ }
+
+ // Check if EXIF header is present.
+ var header uint32
+ if err := binary.Read(r, binary.BigEndian, &header); err != nil {
+ return orientationUnspecified
+ }
+ if header != exifHeader {
+ return orientationUnspecified
+ }
+ if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
+ return orientationUnspecified
+ }
+
+ // Read byte order information.
+ var (
+ byteOrderTag uint16
+ byteOrder binary.ByteOrder
+ )
+ if err := binary.Read(r, binary.BigEndian, &byteOrderTag); err != nil {
+ return orientationUnspecified
+ }
+ switch byteOrderTag {
+ case byteOrderBE:
+ byteOrder = binary.BigEndian
+ case byteOrderLE:
+ byteOrder = binary.LittleEndian
+ default:
+ return orientationUnspecified // Invalid byte order flag.
+ }
+ if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil {
+ return orientationUnspecified
+ }
+
+ // Skip the EXIF offset.
+ var offset uint32
+ if err := binary.Read(r, byteOrder, &offset); err != nil {
+ return orientationUnspecified
+ }
+ if offset < 8 {
+ return orientationUnspecified // Invalid offset value.
+ }
+ if _, err := io.CopyN(ioutil.Discard, r, int64(offset-8)); err != nil {
+ return orientationUnspecified
+ }
+
+ // Read the number of tags.
+ var numTags uint16
+ if err := binary.Read(r, byteOrder, &numTags); err != nil {
+ return orientationUnspecified
+ }
+
+ // Find the orientation tag.
+ for i := 0; i < int(numTags); i++ {
+ var tag uint16
+ if err := binary.Read(r, byteOrder, &tag); err != nil {
+ return orientationUnspecified
+ }
+ if tag != orientationTag {
+ if _, err := io.CopyN(ioutil.Discard, r, 10); err != nil {
+ return orientationUnspecified
+ }
+ continue
+ }
+ if _, err := io.CopyN(ioutil.Discard, r, 6); err != nil {
+ return orientationUnspecified
+ }
+ var val uint16
+ if err := binary.Read(r, byteOrder, &val); err != nil {
+ return orientationUnspecified
+ }
+ if val < 1 || val > 8 {
+ return orientationUnspecified // Invalid tag value.
+ }
+ return orientation(val)
+ }
+ return orientationUnspecified // Missing orientation tag.
+}
+
+// fixOrientation applies a transform to img corresponding to the given orientation flag.
+func fixOrientation(img image.Image, o orientation) image.Image {
+ switch o {
+ case orientationNormal:
+ case orientationFlipH:
+ img = FlipH(img)
+ case orientationFlipV:
+ img = FlipV(img)
+ case orientationRotate90:
+ img = Rotate90(img)
+ case orientationRotate180:
+ img = Rotate180(img)
+ case orientationRotate270:
+ img = Rotate270(img)
+ case orientationTranspose:
+ img = Transpose(img)
+ case orientationTransverse:
+ img = Transverse(img)
+ }
+ return img
+}
diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go
new file mode 100644
index 00000000..706435e3
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/resize.go
@@ -0,0 +1,595 @@
+package imaging
+
+import (
+ "image"
+ "math"
+)
+
+type indexWeight struct {
+ index int
+ weight float64
+}
+
+func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight {
+ du := float64(srcSize) / float64(dstSize)
+ scale := du
+ if scale < 1.0 {
+ scale = 1.0
+ }
+ ru := math.Ceil(scale * filter.Support)
+
+ out := make([][]indexWeight, dstSize)
+ tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2)
+
+ for v := 0; v < dstSize; v++ {
+ fu := (float64(v)+0.5)*du - 0.5
+
+ begin := int(math.Ceil(fu - ru))
+ if begin < 0 {
+ begin = 0
+ }
+ end := int(math.Floor(fu + ru))
+ if end > srcSize-1 {
+ end = srcSize - 1
+ }
+
+ var sum float64
+ for u := begin; u <= end; u++ {
+ w := filter.Kernel((float64(u) - fu) / scale)
+ if w != 0 {
+ sum += w
+ tmp = append(tmp, indexWeight{index: u, weight: w})
+ }
+ }
+ if sum != 0 {
+ for i := range tmp {
+ tmp[i].weight /= sum
+ }
+ }
+
+ out[v] = tmp
+ tmp = tmp[len(tmp):]
+ }
+
+ return out
+}
+
+// Resize resizes the image to the specified width and height using the specified resampling
+// filter and returns the transformed image. If one of width or height is 0, the image aspect
+// ratio is preserved.
+//
+// Example:
+//
+// dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos)
+//
+func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
+ dstW, dstH := width, height
+ if dstW < 0 || dstH < 0 {
+ return &image.NRGBA{}
+ }
+ if dstW == 0 && dstH == 0 {
+ return &image.NRGBA{}
+ }
+
+ srcW := img.Bounds().Dx()
+ srcH := img.Bounds().Dy()
+ if srcW <= 0 || srcH <= 0 {
+ return &image.NRGBA{}
+ }
+
+ // If new width or height is 0 then preserve aspect ratio, minimum 1px.
+ if dstW == 0 {
+ tmpW := float64(dstH) * float64(srcW) / float64(srcH)
+ dstW = int(math.Max(1.0, math.Floor(tmpW+0.5)))
+ }
+ if dstH == 0 {
+ tmpH := float64(dstW) * float64(srcH) / float64(srcW)
+ dstH = int(math.Max(1.0, math.Floor(tmpH+0.5)))
+ }
+
+ if filter.Support <= 0 {
+ // Nearest-neighbor special case.
+ return resizeNearest(img, dstW, dstH)
+ }
+
+ if srcW != dstW && srcH != dstH {
+ return resizeVertical(resizeHorizontal(img, dstW, filter), dstH, filter)
+ }
+ if srcW != dstW {
+ return resizeHorizontal(img, dstW, filter)
+ }
+ if srcH != dstH {
+ return resizeVertical(img, dstH, filter)
+ }
+ return Clone(img)
+}
+
+func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, width, src.h))
+ weights := precomputeWeights(width, src.w, filter)
+ parallel(0, src.h, func(ys <-chan int) {
+ scanLine := make([]uint8, src.w*4)
+ for y := range ys {
+ src.scan(0, y, src.w, y+1, scanLine)
+ j0 := y * dst.Stride
+ for x := range weights {
+ var r, g, b, a float64
+ for _, w := range weights[x] {
+ i := w.index * 4
+ s := scanLine[i : i+4 : i+4]
+ aw := float64(s[3]) * w.weight
+ r += float64(s[0]) * aw
+ g += float64(s[1]) * aw
+ b += float64(s[2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := j0 + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a)
+ }
+ }
+ }
+ })
+ return dst
+}
+
+func resizeVertical(img image.Image, height int, filter ResampleFilter) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, height))
+ weights := precomputeWeights(height, src.h, filter)
+ parallel(0, src.w, func(xs <-chan int) {
+ scanLine := make([]uint8, src.h*4)
+ for x := range xs {
+ src.scan(x, 0, x+1, src.h, scanLine)
+ for y := range weights {
+ var r, g, b, a float64
+ for _, w := range weights[y] {
+ i := w.index * 4
+ s := scanLine[i : i+4 : i+4]
+ aw := float64(s[3]) * w.weight
+ r += float64(s[0]) * aw
+ g += float64(s[1]) * aw
+ b += float64(s[2]) * aw
+ a += aw
+ }
+ if a != 0 {
+ aInv := 1 / a
+ j := y*dst.Stride + x*4
+ d := dst.Pix[j : j+4 : j+4]
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a)
+ }
+ }
+ }
+ })
+ return dst
+}
+
+// resizeNearest is a fast nearest-neighbor resize, no filtering.
+func resizeNearest(img image.Image, width, height int) *image.NRGBA {
+ dst := image.NewNRGBA(image.Rect(0, 0, width, height))
+ dx := float64(img.Bounds().Dx()) / float64(width)
+ dy := float64(img.Bounds().Dy()) / float64(height)
+
+ if dx > 1 && dy > 1 {
+ src := newScanner(img)
+ parallel(0, height, func(ys <-chan int) {
+ for y := range ys {
+ srcY := int((float64(y) + 0.5) * dy)
+ dstOff := y * dst.Stride
+ for x := 0; x < width; x++ {
+ srcX := int((float64(x) + 0.5) * dx)
+ src.scan(srcX, srcY, srcX+1, srcY+1, dst.Pix[dstOff:dstOff+4])
+ dstOff += 4
+ }
+ }
+ })
+ } else {
+ src := toNRGBA(img)
+ parallel(0, height, func(ys <-chan int) {
+ for y := range ys {
+ srcY := int((float64(y) + 0.5) * dy)
+ srcOff0 := srcY * src.Stride
+ dstOff := y * dst.Stride
+ for x := 0; x < width; x++ {
+ srcX := int((float64(x) + 0.5) * dx)
+ srcOff := srcOff0 + srcX*4
+ copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4])
+ dstOff += 4
+ }
+ }
+ })
+ }
+
+ return dst
+}
+
+// Fit scales down the image using the specified resample filter to fit the specified
+// maximum width and height and returns the transformed image.
+//
+// Example:
+//
+// dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
+//
+func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
+ maxW, maxH := width, height
+
+ if maxW <= 0 || maxH <= 0 {
+ return &image.NRGBA{}
+ }
+
+ srcBounds := img.Bounds()
+ srcW := srcBounds.Dx()
+ srcH := srcBounds.Dy()
+
+ if srcW <= 0 || srcH <= 0 {
+ return &image.NRGBA{}
+ }
+
+ if srcW <= maxW && srcH <= maxH {
+ return Clone(img)
+ }
+
+ srcAspectRatio := float64(srcW) / float64(srcH)
+ maxAspectRatio := float64(maxW) / float64(maxH)
+
+ var newW, newH int
+ if srcAspectRatio > maxAspectRatio {
+ newW = maxW
+ newH = int(float64(newW) / srcAspectRatio)
+ } else {
+ newH = maxH
+ newW = int(float64(newH) * srcAspectRatio)
+ }
+
+ return Resize(img, newW, newH, filter)
+}
+
+// Fill creates an image with the specified dimensions and fills it with the scaled source image.
+// To achieve the correct aspect ratio without stretching, the source image will be cropped.
+//
+// Example:
+//
+// dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos)
+//
+func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
+ dstW, dstH := width, height
+
+ if dstW <= 0 || dstH <= 0 {
+ return &image.NRGBA{}
+ }
+
+ srcBounds := img.Bounds()
+ srcW := srcBounds.Dx()
+ srcH := srcBounds.Dy()
+
+ if srcW <= 0 || srcH <= 0 {
+ return &image.NRGBA{}
+ }
+
+ if srcW == dstW && srcH == dstH {
+ return Clone(img)
+ }
+
+ if srcW >= 100 && srcH >= 100 {
+ return cropAndResize(img, dstW, dstH, anchor, filter)
+ }
+ return resizeAndCrop(img, dstW, dstH, anchor, filter)
+}
+
+// cropAndResize crops the image to the smallest possible size that has the required aspect ratio using
+// the given anchor point, then scales it to the specified dimensions and returns the transformed image.
+//
+// This is generally faster than resizing first, but may result in inaccuracies when used on small source images.
+func cropAndResize(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
+ dstW, dstH := width, height
+
+ srcBounds := img.Bounds()
+ srcW := srcBounds.Dx()
+ srcH := srcBounds.Dy()
+ srcAspectRatio := float64(srcW) / float64(srcH)
+ dstAspectRatio := float64(dstW) / float64(dstH)
+
+ var tmp *image.NRGBA
+ if srcAspectRatio < dstAspectRatio {
+ cropH := float64(srcW) * float64(dstH) / float64(dstW)
+ tmp = CropAnchor(img, srcW, int(math.Max(1, cropH)+0.5), anchor)
+ } else {
+ cropW := float64(srcH) * float64(dstW) / float64(dstH)
+ tmp = CropAnchor(img, int(math.Max(1, cropW)+0.5), srcH, anchor)
+ }
+
+ return Resize(tmp, dstW, dstH, filter)
+}
+
+// resizeAndCrop resizes the image to the smallest possible size that will cover the specified dimensions,
+// crops the resized image to the specified dimensions using the given anchor point and returns
+// the transformed image.
+func resizeAndCrop(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA {
+ dstW, dstH := width, height
+
+ srcBounds := img.Bounds()
+ srcW := srcBounds.Dx()
+ srcH := srcBounds.Dy()
+ srcAspectRatio := float64(srcW) / float64(srcH)
+ dstAspectRatio := float64(dstW) / float64(dstH)
+
+ var tmp *image.NRGBA
+ if srcAspectRatio < dstAspectRatio {
+ tmp = Resize(img, dstW, 0, filter)
+ } else {
+ tmp = Resize(img, 0, dstH, filter)
+ }
+
+ return CropAnchor(tmp, dstW, dstH, anchor)
+}
+
+// Thumbnail scales the image up or down using the specified resample filter, crops it
+// to the specified width and hight and returns the transformed image.
+//
+// Example:
+//
+// dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos)
+//
+func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA {
+ return Fill(img, width, height, Center, filter)
+}
+
+// ResampleFilter specifies a resampling filter to be used for image resizing.
+//
+// General filter recommendations:
+//
+// - Lanczos
+// A high-quality resampling filter for photographic images yielding sharp results.
+//
+// - CatmullRom
+// A sharp cubic filter that is faster than Lanczos filter while providing similar results.
+//
+// - MitchellNetravali
+// A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
+//
+// - Linear
+// Bilinear resampling filter, produces a smooth output. Faster than cubic filters.
+//
+// - Box
+// Simple and fast averaging filter appropriate for downscaling.
+// When upscaling it's similar to NearestNeighbor.
+//
+// - NearestNeighbor
+// Fastest resampling filter, no antialiasing.
+//
+type ResampleFilter struct {
+ Support float64
+ Kernel func(float64) float64
+}
+
+// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).
+var NearestNeighbor ResampleFilter
+
+// Box filter (averaging pixels).
+var Box ResampleFilter
+
+// Linear filter.
+var Linear ResampleFilter
+
+// Hermite cubic spline filter (BC-spline; B=0; C=0).
+var Hermite ResampleFilter
+
+// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
+var MitchellNetravali ResampleFilter
+
+// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
+var CatmullRom ResampleFilter
+
+// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
+var BSpline ResampleFilter
+
+// Gaussian is a Gaussian blurring filter.
+var Gaussian ResampleFilter
+
+// Bartlett is a Bartlett-windowed sinc filter (3 lobes).
+var Bartlett ResampleFilter
+
+// Lanczos filter (3 lobes).
+var Lanczos ResampleFilter
+
+// Hann is a Hann-windowed sinc filter (3 lobes).
+var Hann ResampleFilter
+
+// Hamming is a Hamming-windowed sinc filter (3 lobes).
+var Hamming ResampleFilter
+
+// Blackman is a Blackman-windowed sinc filter (3 lobes).
+var Blackman ResampleFilter
+
+// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).
+var Welch ResampleFilter
+
+// Cosine is a Cosine-windowed sinc filter (3 lobes).
+var Cosine ResampleFilter
+
+func bcspline(x, b, c float64) float64 {
+ var y float64
+ x = math.Abs(x)
+ if x < 1.0 {
+ y = ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6
+ } else if x < 2.0 {
+ y = ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6
+ }
+ return y
+}
+
+func sinc(x float64) float64 {
+ if x == 0 {
+ return 1
+ }
+ return math.Sin(math.Pi*x) / (math.Pi * x)
+}
+
+func init() {
+ NearestNeighbor = ResampleFilter{
+ Support: 0.0, // special case - not applying the filter
+ }
+
+ Box = ResampleFilter{
+ Support: 0.5,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x <= 0.5 {
+ return 1.0
+ }
+ return 0
+ },
+ }
+
+ Linear = ResampleFilter{
+ Support: 1.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 1.0 {
+ return 1.0 - x
+ }
+ return 0
+ },
+ }
+
+ Hermite = ResampleFilter{
+ Support: 1.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 1.0 {
+ return bcspline(x, 0.0, 0.0)
+ }
+ return 0
+ },
+ }
+
+ MitchellNetravali = ResampleFilter{
+ Support: 2.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 2.0 {
+ return bcspline(x, 1.0/3.0, 1.0/3.0)
+ }
+ return 0
+ },
+ }
+
+ CatmullRom = ResampleFilter{
+ Support: 2.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 2.0 {
+ return bcspline(x, 0.0, 0.5)
+ }
+ return 0
+ },
+ }
+
+ BSpline = ResampleFilter{
+ Support: 2.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 2.0 {
+ return bcspline(x, 1.0, 0.0)
+ }
+ return 0
+ },
+ }
+
+ Gaussian = ResampleFilter{
+ Support: 2.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 2.0 {
+ return math.Exp(-2 * x * x)
+ }
+ return 0
+ },
+ }
+
+ Bartlett = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * (3.0 - x) / 3.0
+ }
+ return 0
+ },
+ }
+
+ Lanczos = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * sinc(x/3.0)
+ }
+ return 0
+ },
+ }
+
+ Hann = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * (0.5 + 0.5*math.Cos(math.Pi*x/3.0))
+ }
+ return 0
+ },
+ }
+
+ Hamming = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * (0.54 + 0.46*math.Cos(math.Pi*x/3.0))
+ }
+ return 0
+ },
+ }
+
+ Blackman = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * (0.42 - 0.5*math.Cos(math.Pi*x/3.0+math.Pi) + 0.08*math.Cos(2.0*math.Pi*x/3.0))
+ }
+ return 0
+ },
+ }
+
+ Welch = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * (1.0 - (x * x / 9.0))
+ }
+ return 0
+ },
+ }
+
+ Cosine = ResampleFilter{
+ Support: 3.0,
+ Kernel: func(x float64) float64 {
+ x = math.Abs(x)
+ if x < 3.0 {
+ return sinc(x) * math.Cos((math.Pi/2.0)*(x/3.0))
+ }
+ return 0
+ },
+ }
+}
diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/disintegration/imaging/scanner.go
new file mode 100644
index 00000000..37d92cef
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/scanner.go
@@ -0,0 +1,285 @@
+package imaging
+
+import (
+ "image"
+ "image/color"
+)
+
+type scanner struct {
+ image image.Image
+ w, h int
+ palette []color.NRGBA
+}
+
+func newScanner(img image.Image) *scanner {
+ s := &scanner{
+ image: img,
+ w: img.Bounds().Dx(),
+ h: img.Bounds().Dy(),
+ }
+ if img, ok := img.(*image.Paletted); ok {
+ s.palette = make([]color.NRGBA, len(img.Palette))
+ for i := 0; i < len(img.Palette); i++ {
+ s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
+ }
+ }
+ return s
+}
+
+// scan scans the given rectangular region of the image into dst.
+func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
+ switch img := s.image.(type) {
+ case *image.NRGBA:
+ size := (x2 - x1) * 4
+ j := 0
+ i := y1*img.Stride + x1*4
+ if size == 4 {
+ for y := y1; y < y2; y++ {
+ d := dst[j : j+4 : j+4]
+ s := img.Pix[i : i+4 : i+4]
+ d[0] = s[0]
+ d[1] = s[1]
+ d[2] = s[2]
+ d[3] = s[3]
+ j += size
+ i += img.Stride
+ }
+ } else {
+ for y := y1; y < y2; y++ {
+ copy(dst[j:j+size], img.Pix[i:i+size])
+ j += size
+ i += img.Stride
+ }
+ }
+
+ case *image.NRGBA64:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*8
+ for x := x1; x < x2; x++ {
+ s := img.Pix[i : i+8 : i+8]
+ d := dst[j : j+4 : j+4]
+ d[0] = s[0]
+ d[1] = s[2]
+ d[2] = s[4]
+ d[3] = s[6]
+ j += 4
+ i += 8
+ }
+ }
+
+ case *image.RGBA:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*4
+ for x := x1; x < x2; x++ {
+ d := dst[j : j+4 : j+4]
+ a := img.Pix[i+3]
+ switch a {
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ d[3] = a
+ case 0xff:
+ s := img.Pix[i : i+4 : i+4]
+ d[0] = s[0]
+ d[1] = s[1]
+ d[2] = s[2]
+ d[3] = a
+ default:
+ s := img.Pix[i : i+4 : i+4]
+ r16 := uint16(s[0])
+ g16 := uint16(s[1])
+ b16 := uint16(s[2])
+ a16 := uint16(a)
+ d[0] = uint8(r16 * 0xff / a16)
+ d[1] = uint8(g16 * 0xff / a16)
+ d[2] = uint8(b16 * 0xff / a16)
+ d[3] = a
+ }
+ j += 4
+ i += 4
+ }
+ }
+
+ case *image.RGBA64:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*8
+ for x := x1; x < x2; x++ {
+ s := img.Pix[i : i+8 : i+8]
+ d := dst[j : j+4 : j+4]
+ a := s[6]
+ switch a {
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ case 0xff:
+ d[0] = s[0]
+ d[1] = s[2]
+ d[2] = s[4]
+ default:
+ r32 := uint32(s[0])<<8 | uint32(s[1])
+ g32 := uint32(s[2])<<8 | uint32(s[3])
+ b32 := uint32(s[4])<<8 | uint32(s[5])
+ a32 := uint32(s[6])<<8 | uint32(s[7])
+ d[0] = uint8((r32 * 0xffff / a32) >> 8)
+ d[1] = uint8((g32 * 0xffff / a32) >> 8)
+ d[2] = uint8((b32 * 0xffff / a32) >> 8)
+ }
+ d[3] = a
+ j += 4
+ i += 8
+ }
+ }
+
+ case *image.Gray:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1
+ for x := x1; x < x2; x++ {
+ c := img.Pix[i]
+ d := dst[j : j+4 : j+4]
+ d[0] = c
+ d[1] = c
+ d[2] = c
+ d[3] = 0xff
+ j += 4
+ i++
+ }
+ }
+
+ case *image.Gray16:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1*2
+ for x := x1; x < x2; x++ {
+ c := img.Pix[i]
+ d := dst[j : j+4 : j+4]
+ d[0] = c
+ d[1] = c
+ d[2] = c
+ d[3] = 0xff
+ j += 4
+ i += 2
+ }
+ }
+
+ case *image.YCbCr:
+ j := 0
+ x1 += img.Rect.Min.X
+ x2 += img.Rect.Min.X
+ y1 += img.Rect.Min.Y
+ y2 += img.Rect.Min.Y
+
+ hy := img.Rect.Min.Y / 2
+ hx := img.Rect.Min.X / 2
+ for y := y1; y < y2; y++ {
+ iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
+
+ var yBase int
+ switch img.SubsampleRatio {
+ case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422:
+ yBase = (y - img.Rect.Min.Y) * img.CStride
+ case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440:
+ yBase = (y/2 - hy) * img.CStride
+ }
+
+ for x := x1; x < x2; x++ {
+ var ic int
+ switch img.SubsampleRatio {
+ case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440:
+ ic = yBase + (x - img.Rect.Min.X)
+ case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420:
+ ic = yBase + (x/2 - hx)
+ default:
+ ic = img.COffset(x, y)
+ }
+
+ yy1 := int32(img.Y[iy]) * 0x10101
+ cb1 := int32(img.Cb[ic]) - 128
+ cr1 := int32(img.Cr[ic]) - 128
+
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 16
+ } else {
+ r = ^(r >> 31)
+ }
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 16
+ } else {
+ g = ^(g >> 31)
+ }
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 16
+ } else {
+ b = ^(b >> 31)
+ }
+
+ d := dst[j : j+4 : j+4]
+ d[0] = uint8(r)
+ d[1] = uint8(g)
+ d[2] = uint8(b)
+ d[3] = 0xff
+
+ iy++
+ j += 4
+ }
+ }
+
+ case *image.Paletted:
+ j := 0
+ for y := y1; y < y2; y++ {
+ i := y*img.Stride + x1
+ for x := x1; x < x2; x++ {
+ c := s.palette[img.Pix[i]]
+ d := dst[j : j+4 : j+4]
+ d[0] = c.R
+ d[1] = c.G
+ d[2] = c.B
+ d[3] = c.A
+ j += 4
+ i++
+ }
+ }
+
+ default:
+ j := 0
+ b := s.image.Bounds()
+ x1 += b.Min.X
+ x2 += b.Min.X
+ y1 += b.Min.Y
+ y2 += b.Min.Y
+ for y := y1; y < y2; y++ {
+ for x := x1; x < x2; x++ {
+ r16, g16, b16, a16 := s.image.At(x, y).RGBA()
+ d := dst[j : j+4 : j+4]
+ switch a16 {
+ case 0xffff:
+ d[0] = uint8(r16 >> 8)
+ d[1] = uint8(g16 >> 8)
+ d[2] = uint8(b16 >> 8)
+ d[3] = 0xff
+ case 0:
+ d[0] = 0
+ d[1] = 0
+ d[2] = 0
+ d[3] = 0
+ default:
+ d[0] = uint8(((r16 * 0xffff) / a16) >> 8)
+ d[1] = uint8(((g16 * 0xffff) / a16) >> 8)
+ d[2] = uint8(((b16 * 0xffff) / a16) >> 8)
+ d[3] = uint8(a16 >> 8)
+ }
+ j += 4
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/disintegration/imaging/tools.go b/vendor/github.com/disintegration/imaging/tools.go
new file mode 100644
index 00000000..0ec19a03
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/tools.go
@@ -0,0 +1,249 @@
+package imaging
+
+import (
+ "bytes"
+ "image"
+ "image/color"
+ "math"
+)
+
+// New creates a new image with the specified width and height, and fills it with the specified color.
+func New(width, height int, fillColor color.Color) *image.NRGBA {
+ if width <= 0 || height <= 0 {
+ return &image.NRGBA{}
+ }
+
+ c := color.NRGBAModel.Convert(fillColor).(color.NRGBA)
+ if (c == color.NRGBA{0, 0, 0, 0}) {
+ return image.NewNRGBA(image.Rect(0, 0, width, height))
+ }
+
+ return &image.NRGBA{
+ Pix: bytes.Repeat([]byte{c.R, c.G, c.B, c.A}, width*height),
+ Stride: 4 * width,
+ Rect: image.Rect(0, 0, width, height),
+ }
+}
+
+// Clone returns a copy of the given image.
+func Clone(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h))
+ size := src.w * 4
+ parallel(0, src.h, func(ys <-chan int) {
+ for y := range ys {
+ i := y * dst.Stride
+ src.scan(0, y, src.w, y+1, dst.Pix[i:i+size])
+ }
+ })
+ return dst
+}
+
+// Anchor is the anchor point for image alignment.
+type Anchor int
+
+// Anchor point positions.
+const (
+ Center Anchor = iota
+ TopLeft
+ Top
+ TopRight
+ Left
+ Right
+ BottomLeft
+ Bottom
+ BottomRight
+)
+
+func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point {
+ var x, y int
+ switch anchor {
+ case TopLeft:
+ x = b.Min.X
+ y = b.Min.Y
+ case Top:
+ x = b.Min.X + (b.Dx()-w)/2
+ y = b.Min.Y
+ case TopRight:
+ x = b.Max.X - w
+ y = b.Min.Y
+ case Left:
+ x = b.Min.X
+ y = b.Min.Y + (b.Dy()-h)/2
+ case Right:
+ x = b.Max.X - w
+ y = b.Min.Y + (b.Dy()-h)/2
+ case BottomLeft:
+ x = b.Min.X
+ y = b.Max.Y - h
+ case Bottom:
+ x = b.Min.X + (b.Dx()-w)/2
+ y = b.Max.Y - h
+ case BottomRight:
+ x = b.Max.X - w
+ y = b.Max.Y - h
+ default:
+ x = b.Min.X + (b.Dx()-w)/2
+ y = b.Min.Y + (b.Dy()-h)/2
+ }
+ return image.Pt(x, y)
+}
+
+// Crop cuts out a rectangular region with the specified bounds
+// from the image and returns the cropped image.
+func Crop(img image.Image, rect image.Rectangle) *image.NRGBA {
+ r := rect.Intersect(img.Bounds()).Sub(img.Bounds().Min)
+ if r.Empty() {
+ return &image.NRGBA{}
+ }
+ src := newScanner(img)
+ dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy()))
+ rowSize := r.Dx() * 4
+ parallel(r.Min.Y, r.Max.Y, func(ys <-chan int) {
+ for y := range ys {
+ i := (y - r.Min.Y) * dst.Stride
+ src.scan(r.Min.X, y, r.Max.X, y+1, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// CropAnchor cuts out a rectangular region with the specified size
+// from the image using the specified anchor point and returns the cropped image.
+func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA {
+ srcBounds := img.Bounds()
+ pt := anchorPt(srcBounds, width, height, anchor)
+ r := image.Rect(0, 0, width, height).Add(pt)
+ b := srcBounds.Intersect(r)
+ return Crop(img, b)
+}
+
+// CropCenter cuts out a rectangular region with the specified size
+// from the center of the image and returns the cropped image.
+func CropCenter(img image.Image, width, height int) *image.NRGBA {
+ return CropAnchor(img, width, height, Center)
+}
+
+// Paste pastes the img image to the background image at the specified position and returns the combined image.
+func Paste(background, img image.Image, pos image.Point) *image.NRGBA {
+ dst := Clone(background)
+ pos = pos.Sub(background.Bounds().Min)
+ pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
+ interRect := pasteRect.Intersect(dst.Bounds())
+ if interRect.Empty() {
+ return dst
+ }
+ src := newScanner(img)
+ parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
+ for y := range ys {
+ x1 := interRect.Min.X - pasteRect.Min.X
+ x2 := interRect.Max.X - pasteRect.Min.X
+ y1 := y - pasteRect.Min.Y
+ y2 := y1 + 1
+ i1 := y*dst.Stride + interRect.Min.X*4
+ i2 := i1 + interRect.Dx()*4
+ src.scan(x1, y1, x2, y2, dst.Pix[i1:i2])
+ }
+ })
+ return dst
+}
+
+// PasteCenter pastes the img image to the center of the background image and returns the combined image.
+func PasteCenter(background, img image.Image) *image.NRGBA {
+ bgBounds := background.Bounds()
+ bgW := bgBounds.Dx()
+ bgH := bgBounds.Dy()
+ bgMinX := bgBounds.Min.X
+ bgMinY := bgBounds.Min.Y
+
+ centerX := bgMinX + bgW/2
+ centerY := bgMinY + bgH/2
+
+ x0 := centerX - img.Bounds().Dx()/2
+ y0 := centerY - img.Bounds().Dy()/2
+
+ return Paste(background, img, image.Pt(x0, y0))
+}
+
+// Overlay draws the img image over the background image at given position
+// and returns the combined image. Opacity parameter is the opacity of the img
+// image layer, used to compose the images, it must be from 0.0 to 1.0.
+//
+// Examples:
+//
+// // Draw spriteImage over backgroundImage at the given position (x=50, y=50).
+// dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0)
+//
+// // Blend two opaque images of the same size.
+// dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5)
+//
+func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA {
+ opacity = math.Min(math.Max(opacity, 0.0), 1.0) // Ensure 0.0 <= opacity <= 1.0.
+ dst := Clone(background)
+ pos = pos.Sub(background.Bounds().Min)
+ pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())}
+ interRect := pasteRect.Intersect(dst.Bounds())
+ if interRect.Empty() {
+ return dst
+ }
+ src := newScanner(img)
+ parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) {
+ scanLine := make([]uint8, interRect.Dx()*4)
+ for y := range ys {
+ x1 := interRect.Min.X - pasteRect.Min.X
+ x2 := interRect.Max.X - pasteRect.Min.X
+ y1 := y - pasteRect.Min.Y
+ y2 := y1 + 1
+ src.scan(x1, y1, x2, y2, scanLine)
+ i := y*dst.Stride + interRect.Min.X*4
+ j := 0
+ for x := interRect.Min.X; x < interRect.Max.X; x++ {
+ d := dst.Pix[i : i+4 : i+4]
+ r1 := float64(d[0])
+ g1 := float64(d[1])
+ b1 := float64(d[2])
+ a1 := float64(d[3])
+
+ s := scanLine[j : j+4 : j+4]
+ r2 := float64(s[0])
+ g2 := float64(s[1])
+ b2 := float64(s[2])
+ a2 := float64(s[3])
+
+ coef2 := opacity * a2 / 255
+ coef1 := (1 - coef2) * a1 / 255
+ coefSum := coef1 + coef2
+ coef1 /= coefSum
+ coef2 /= coefSum
+
+ d[0] = uint8(r1*coef1 + r2*coef2)
+ d[1] = uint8(g1*coef1 + g2*coef2)
+ d[2] = uint8(b1*coef1 + b2*coef2)
+ d[3] = uint8(math.Min(a1+a2*opacity*(255-a1)/255, 255))
+
+ i += 4
+ j += 4
+ }
+ }
+ })
+ return dst
+}
+
+// OverlayCenter overlays the img image to the center of the background image and
+// returns the combined image. Opacity parameter is the opacity of the img
+// image layer, used to compose the images, it must be from 0.0 to 1.0.
+func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA {
+ bgBounds := background.Bounds()
+ bgW := bgBounds.Dx()
+ bgH := bgBounds.Dy()
+ bgMinX := bgBounds.Min.X
+ bgMinY := bgBounds.Min.Y
+
+ centerX := bgMinX + bgW/2
+ centerY := bgMinY + bgH/2
+
+ x0 := centerX - img.Bounds().Dx()/2
+ y0 := centerY - img.Bounds().Dy()/2
+
+ return Overlay(background, img, image.Point{x0, y0}, opacity)
+}
diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go
new file mode 100644
index 00000000..fe4a92f9
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/transform.go
@@ -0,0 +1,268 @@
+package imaging
+
+import (
+ "image"
+ "image/color"
+ "math"
+)
+
+// FlipH flips the image horizontally (from left to right) and returns the transformed image.
+func FlipH(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstY
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// FlipV flips the image vertically (from top to bottom) and returns the transformed image.
+func FlipV(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstH - dstY - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Transpose flips the image horizontally and rotates 90 degrees counter-clockwise.
+func Transpose(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstY
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Transverse flips the image vertically and rotates 90 degrees counter-clockwise.
+func Transverse(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstH - dstY - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image.
+func Rotate90(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstH - dstY - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image.
+func Rotate180(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstH - dstY - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image.
+func Rotate270(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstY
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate rotates an image by the given angle counter-clockwise .
+// The angle parameter is the rotation angle in degrees.
+// The bgColor parameter specifies the color of the uncovered zone after the rotation.
+func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
+ angle = angle - math.Floor(angle/360)*360
+
+ switch angle {
+ case 0:
+ return Clone(img)
+ case 90:
+ return Rotate90(img)
+ case 180:
+ return Rotate180(img)
+ case 270:
+ return Rotate270(img)
+ }
+
+ src := toNRGBA(img)
+ srcW := src.Bounds().Max.X
+ srcH := src.Bounds().Max.Y
+ dstW, dstH := rotatedSize(srcW, srcH, angle)
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+
+ if dstW <= 0 || dstH <= 0 {
+ return dst
+ }
+
+ srcXOff := float64(srcW)/2 - 0.5
+ srcYOff := float64(srcH)/2 - 0.5
+ dstXOff := float64(dstW)/2 - 0.5
+ dstYOff := float64(dstH)/2 - 0.5
+
+ bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA)
+ sin, cos := math.Sincos(math.Pi * angle / 180)
+
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ for dstX := 0; dstX < dstW; dstX++ {
+ xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos)
+ xf, yf = xf+srcXOff, yf+srcYOff
+ interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA)
+ }
+ }
+ })
+
+ return dst
+}
+
+func rotatePoint(x, y, sin, cos float64) (float64, float64) {
+ return x*cos - y*sin, x*sin + y*cos
+}
+
+func rotatedSize(w, h int, angle float64) (int, int) {
+ if w <= 0 || h <= 0 {
+ return 0, 0
+ }
+
+ sin, cos := math.Sincos(math.Pi * angle / 180)
+ x1, y1 := rotatePoint(float64(w-1), 0, sin, cos)
+ x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos)
+ x3, y3 := rotatePoint(0, float64(h-1), sin, cos)
+
+ minx := math.Min(x1, math.Min(x2, math.Min(x3, 0)))
+ maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0)))
+ miny := math.Min(y1, math.Min(y2, math.Min(y3, 0)))
+ maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0)))
+
+ neww := maxx - minx + 1
+ if neww-math.Floor(neww) > 0.1 {
+ neww++
+ }
+ newh := maxy - miny + 1
+ if newh-math.Floor(newh) > 0.1 {
+ newh++
+ }
+
+ return int(neww), int(newh)
+}
+
+func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) {
+ j := dstY*dst.Stride + dstX*4
+ d := dst.Pix[j : j+4 : j+4]
+
+ x0 := int(math.Floor(xf))
+ y0 := int(math.Floor(yf))
+ bounds := src.Bounds()
+ if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) {
+ d[0] = bgColor.R
+ d[1] = bgColor.G
+ d[2] = bgColor.B
+ d[3] = bgColor.A
+ return
+ }
+
+ xq := xf - float64(x0)
+ yq := yf - float64(y0)
+ points := [4]image.Point{
+ {x0, y0},
+ {x0 + 1, y0},
+ {x0, y0 + 1},
+ {x0 + 1, y0 + 1},
+ }
+ weights := [4]float64{
+ (1 - xq) * (1 - yq),
+ xq * (1 - yq),
+ (1 - xq) * yq,
+ xq * yq,
+ }
+
+ var r, g, b, a float64
+ for i := 0; i < 4; i++ {
+ p := points[i]
+ w := weights[i]
+ if p.In(bounds) {
+ i := p.Y*src.Stride + p.X*4
+ s := src.Pix[i : i+4 : i+4]
+ wa := float64(s[3]) * w
+ r += float64(s[0]) * wa
+ g += float64(s[1]) * wa
+ b += float64(s[2]) * wa
+ a += wa
+ } else {
+ wa := float64(bgColor.A) * w
+ r += float64(bgColor.R) * wa
+ g += float64(bgColor.G) * wa
+ b += float64(bgColor.B) * wa
+ a += wa
+ }
+ }
+ if a != 0 {
+ aInv := 1 / a
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a)
+ }
+}
diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/disintegration/imaging/utils.go
new file mode 100644
index 00000000..6c7af1a5
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/utils.go
@@ -0,0 +1,167 @@
+package imaging
+
+import (
+ "image"
+ "math"
+ "runtime"
+ "sync"
+)
+
+// parallel processes the data in separate goroutines.
+func parallel(start, stop int, fn func(<-chan int)) {
+ count := stop - start
+ if count < 1 {
+ return
+ }
+
+ procs := runtime.GOMAXPROCS(0)
+ if procs > count {
+ procs = count
+ }
+
+ c := make(chan int, count)
+ for i := start; i < stop; i++ {
+ c <- i
+ }
+ close(c)
+
+ var wg sync.WaitGroup
+ for i := 0; i < procs; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ fn(c)
+ }()
+ }
+ wg.Wait()
+}
+
+// absint returns the absolute value of i.
+func absint(i int) int {
+ if i < 0 {
+ return -i
+ }
+ return i
+}
+
+// clamp rounds and clamps float64 value to fit into uint8.
+func clamp(x float64) uint8 {
+ v := int64(x + 0.5)
+ if v > 255 {
+ return 255
+ }
+ if v > 0 {
+ return uint8(v)
+ }
+ return 0
+}
+
+func reverse(pix []uint8) {
+ if len(pix) <= 4 {
+ return
+ }
+ i := 0
+ j := len(pix) - 4
+ for i < j {
+ pi := pix[i : i+4 : i+4]
+ pj := pix[j : j+4 : j+4]
+ pi[0], pj[0] = pj[0], pi[0]
+ pi[1], pj[1] = pj[1], pi[1]
+ pi[2], pj[2] = pj[2], pi[2]
+ pi[3], pj[3] = pj[3], pi[3]
+ i += 4
+ j -= 4
+ }
+}
+
+func toNRGBA(img image.Image) *image.NRGBA {
+ if img, ok := img.(*image.NRGBA); ok {
+ return &image.NRGBA{
+ Pix: img.Pix,
+ Stride: img.Stride,
+ Rect: img.Rect.Sub(img.Rect.Min),
+ }
+ }
+ return Clone(img)
+}
+
+// rgbToHSL converts a color from RGB to HSL.
+func rgbToHSL(r, g, b uint8) (float64, float64, float64) {
+ rr := float64(r) / 255
+ gg := float64(g) / 255
+ bb := float64(b) / 255
+
+ max := math.Max(rr, math.Max(gg, bb))
+ min := math.Min(rr, math.Min(gg, bb))
+
+ l := (max + min) / 2
+
+ if max == min {
+ return 0, 0, l
+ }
+
+ var h, s float64
+ d := max - min
+ if l > 0.5 {
+ s = d / (2 - max - min)
+ } else {
+ s = d / (max + min)
+ }
+
+ switch max {
+ case rr:
+ h = (gg - bb) / d
+ if g < b {
+ h += 6
+ }
+ case gg:
+ h = (bb-rr)/d + 2
+ case bb:
+ h = (rr-gg)/d + 4
+ }
+ h /= 6
+
+ return h, s, l
+}
+
+// hslToRGB converts a color from HSL to RGB.
+func hslToRGB(h, s, l float64) (uint8, uint8, uint8) {
+ var r, g, b float64
+ if s == 0 {
+ v := clamp(l * 255)
+ return v, v, v
+ }
+
+ var q float64
+ if l < 0.5 {
+ q = l * (1 + s)
+ } else {
+ q = l + s - l*s
+ }
+ p := 2*l - q
+
+ r = hueToRGB(p, q, h+1/3.0)
+ g = hueToRGB(p, q, h)
+ b = hueToRGB(p, q, h-1/3.0)
+
+ return clamp(r * 255), clamp(g * 255), clamp(b * 255)
+}
+
+func hueToRGB(p, q, t float64) float64 {
+ if t < 0 {
+ t++
+ }
+ if t > 1 {
+ t--
+ }
+ if t < 1/6.0 {
+ return p + (q-p)*6*t
+ }
+ if t < 1/2.0 {
+ return q
+ }
+ if t < 2/3.0 {
+ return p + (q-p)*(2/3.0-t)*6
+ }
+ return p
+}
diff --git a/vendor/github.com/google/gops/agent/agent.go b/vendor/github.com/google/gops/agent/agent.go
index 59a03cf5..441814c9 100644
--- a/vendor/github.com/google/gops/agent/agent.go
+++ b/vendor/github.com/google/gops/agent/agent.go
@@ -8,6 +8,7 @@ package agent
import (
"bufio"
+ "context"
"encoding/binary"
"fmt"
"io"
@@ -55,6 +56,13 @@ type Options struct {
// can call Close before shutting down.
// Optional.
ShutdownCleanup bool
+
+ // ReuseSocketAddrAndPort determines whether the SO_REUSEADDR and
+ // SO_REUSEADDR socket options should be set on the listening socket of
+ // the agent. This option is only effective on unix-like OSes and if
+ // Addr is set to a fixed host:port.
+ // Optional.
+ ReuseSocketAddrAndPort bool
}
// Listen starts the gops agent on a host process. Once agent started, users
@@ -96,11 +104,14 @@ func Listen(opts Options) error {
if addr == "" {
addr = defaultAddr
}
- ln, err := net.Listen("tcp", addr)
+ var lc net.ListenConfig
+ if opts.ReuseSocketAddrAndPort {
+ lc.Control = setsockoptReuseAddrAndPort
+ }
+ listener, err = lc.Listen(context.Background(), "tcp", addr)
if err != nil {
return err
}
- listener = ln
port := listener.Addr().(*net.TCPAddr).Port
portfile = fmt.Sprintf("%s/%d", gopsdir, os.Getpid())
err = ioutil.WriteFile(portfile, []byte(strconv.Itoa(port)), os.ModePerm)
diff --git a/vendor/github.com/google/gops/agent/sockopt_unix.go b/vendor/github.com/google/gops/agent/sockopt_unix.go
new file mode 100644
index 00000000..7edaf209
--- /dev/null
+++ b/vendor/github.com/google/gops/agent/sockopt_unix.go
@@ -0,0 +1,36 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !js,!plan9,!windows
+
+package agent
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+// setsockoptReuseAddrAndPort sets the SO_REUSEADDR and SO_REUSEPORT socket
+// options on c's underlying socket in order to increase the chance to re-bind()
+// to the same address and port upon agent restart.
+func setsockoptReuseAddrAndPort(network, address string, c syscall.RawConn) error {
+ var soerr error
+ if err := c.Control(func(su uintptr) {
+ sock := int(su)
+ // Allow reuse of recently-used addresses. This socket option is
+ // set by default on listeners in Go's net package, see
+ // net.setDefaultSockopts.
+ soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
+ if soerr != nil {
+ return
+ }
+ // Allow reuse of recently-used ports. This gives the agent a
+ // better chance to re-bind upon restarts.
+ soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
+ }); err != nil {
+ return err
+ }
+ return soerr
+}
diff --git a/vendor/github.com/google/gops/agent/sockopt_unsupported.go b/vendor/github.com/google/gops/agent/sockopt_unsupported.go
new file mode 100644
index 00000000..df3223bd
--- /dev/null
+++ b/vendor/github.com/google/gops/agent/sockopt_unsupported.go
@@ -0,0 +1,13 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build js,wasm plan9 windows
+
+package agent
+
+import "syscall"
+
+func setsockoptReuseAddrAndPort(network, address string, c syscall.RawConn) error {
+ return nil
+}
diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md
index 9d92c11f..f765a46f 100644
--- a/vendor/github.com/google/uuid/README.md
+++ b/vendor/github.com/google/uuid/README.md
@@ -16,4 +16,4 @@ change is the ability to represent an invalid UUID (vs a NIL UUID).
Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
-http://godoc.org/github.com/google/uuid
+http://pkg.go.dev/github.com/google/uuid
diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go
index 7f9e0c6c..14bd3407 100644
--- a/vendor/github.com/google/uuid/marshal.go
+++ b/vendor/github.com/google/uuid/marshal.go
@@ -16,10 +16,11 @@ func (uuid UUID) MarshalText() ([]byte, error) {
// UnmarshalText implements encoding.TextUnmarshaler.
func (uuid *UUID) UnmarshalText(data []byte) error {
id, err := ParseBytes(data)
- if err == nil {
- *uuid = id
+ if err != nil {
+ return err
}
- return err
+ *uuid = id
+ return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go
index 199a1ac6..46310962 100644
--- a/vendor/github.com/google/uuid/version1.go
+++ b/vendor/github.com/google/uuid/version1.go
@@ -17,12 +17,6 @@ import (
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
- nodeMu.Lock()
- if nodeID == zeroID {
- setNodeInterface("")
- }
- nodeMu.Unlock()
-
var uuid UUID
now, seq, err := GetTime()
if err != nil {
@@ -38,7 +32,13 @@ func NewUUID() (UUID, error) {
binary.BigEndian.PutUint16(uuid[4:], timeMid)
binary.BigEndian.PutUint16(uuid[6:], timeHi)
binary.BigEndian.PutUint16(uuid[8:], seq)
+
+ nodeMu.Lock()
+ if nodeID == zeroID {
+ setNodeInterface("")
+ }
copy(uuid[10:], nodeID[:])
+ nodeMu.Unlock()
return uuid, nil
}
diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go
index 84af91c9..c110465d 100644
--- a/vendor/github.com/google/uuid/version4.go
+++ b/vendor/github.com/google/uuid/version4.go
@@ -27,8 +27,13 @@ func New() UUID {
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
+ return NewRandomFromReader(rander)
+}
+
+// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
+func NewRandomFromReader(r io.Reader) (UUID, error) {
var uuid UUID
- _, err := io.ReadFull(rander, uuid[:])
+ _, err := io.ReadFull(r, uuid[:])
if err != nil {
return Nil, err
}
diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go
index a733bef1..44e368e5 100644
--- a/vendor/github.com/hashicorp/errwrap/errwrap.go
+++ b/vendor/github.com/hashicorp/errwrap/errwrap.go
@@ -44,6 +44,8 @@ func Wrap(outer, inner error) error {
//
// format is the format of the error message. The string '{{err}}' will
// be replaced with the original error message.
+//
+// Deprecated: Use fmt.Errorf()
func Wrapf(format string, err error) error {
outerMsg := "<nil>"
if err != nil {
@@ -148,6 +150,9 @@ func Walk(err error, cb WalkFunc) {
for _, err := range e.WrappedErrors() {
Walk(err, cb)
}
+ case interface{ Unwrap() error }:
+ cb(err)
+ Walk(e.Unwrap(), cb)
default:
cb(err)
}
@@ -167,3 +172,7 @@ func (w *wrappedError) Error() string {
func (w *wrappedError) WrappedErrors() []error {
return []error{w.Outer, w.Inner}
}
+
+func (w *wrappedError) Unwrap() error {
+ return w.Inner
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt b/vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt
index c067c12f..c438d93c 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt
+++ b/vendor/github.com/mattermost/mattermost-server/v5/NOTICE.txt
@@ -864,7 +864,7 @@ Mozilla Public License Version 2.0
means any form of the work other than Source Code Form.
1.7. "Larger Work"
- means a work that combines Covered Software with other material, in
+ means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
@@ -1387,7 +1387,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains 'durafmt' by Wesley Hill.
-:clock8: Better time duration formatting in Go!
+:clock8: Better time duration formatting in Go!
* HOMEPAGE:
* https://github.com/hako/durafmt
@@ -3657,7 +3657,7 @@ lumberjack is a log rolling package for Go
The MIT License (MIT)
-Copyright (c) 2014 Nate Finch
+Copyright (c) 2014 Nate Finch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -4206,6 +4206,220 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+## AWS SDK for Go
+
+This product contains 'aws-sdk' by Amazon.
+
+AWS-SDK support for the Go language.
+
+* HOMEPAGE:
+ * https://github.com/aws/aws-sdk-go
+
+* LICENSE:
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
+
---
## semver
@@ -4274,3 +4488,328 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+---
+
+## Archiver
+
+This product contains 'archiver' by Matthew Holt
+
+A library to handle direferen archive files (zip, rar, tar.gz...)
+
+* HOMEPAGE:
+ * https://github.com/mholt/archiver
+
+* LICENSE:
+
+MIT License
+
+Copyright (c) 2016 Matthew Holt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+---
+
+## PDF Reader library
+
+This product contains 'pdf' by the Go team and modified by Thuc Le
+
+A library to provide pdf reading support
+
+* HOMEPAGE:
+ * https://github.com/ledongthuc/pdf
+
+* LICENSE:
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---
+
+## GoOse
+
+This product contains 'GoOse' by Antonio Linari
+
+A library to provide html text extraction support
+
+* HOMEPAGE:
+ * https://github.com/advancedlogic/GoOse
+
+* LICENSE:
+
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
+
+---
+
+## Docconv
+
+This product contains 'docconv' by Sajari Pty Ltd
+
+A library to provide text extraction support for different documents
+
+* HOMEPAGE:
+ * https://github.com/sajari/docconv
+
+* LICENSE:
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Sajari Pty Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go
index e38bfffe..d7a76e2d 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_member.go
@@ -164,6 +164,18 @@ func (o *ChannelMember) GetRoles() []string {
return strings.Fields(o.Roles)
}
+func (o *ChannelMember) SetChannelMuted(muted bool) {
+ if o.IsChannelMuted() {
+ o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] = CHANNEL_MARK_UNREAD_ALL
+ } else {
+ o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] = CHANNEL_MARK_UNREAD_MENTION
+ }
+}
+
+func (o *ChannelMember) IsChannelMuted() bool {
+ return o.NotifyProps[MARK_UNREAD_NOTIFY_PROP] == CHANNEL_MARK_UNREAD_MENTION
+}
+
func IsChannelNotifyLevelValid(notifyLevel string) bool {
return notifyLevel == CHANNEL_NOTIFY_DEFAULT ||
notifyLevel == CHANNEL_NOTIFY_ALL ||
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go
index d05c6c9d..033432c9 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/channel_sidebar.go
@@ -46,6 +46,7 @@ type SidebarCategory struct {
Sorting SidebarCategorySorting `json:"sorting"`
Type SidebarCategoryType `json:"type"`
DisplayName string `json:"display_name"`
+ Muted bool `json:"muted"`
}
// SidebarCategoryWithChannels combines data from SidebarCategory table with the Channel IDs that belong to that category
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/client4.go b/vendor/github.com/mattermost/mattermost-server/v5/model/client4.go
index b3c34c39..8ebf0da1 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/client4.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/client4.go
@@ -189,6 +189,14 @@ func (c *Client4) GetUserRoute(userId string) string {
return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
}
+func (c *Client4) GetUserThreadsRoute(userId string) string {
+ return fmt.Sprintf(c.GetUsersRoute()+"/%v/threads", userId)
+}
+
+func (c *Client4) GetUserThreadRoute(userId, threadId string) string {
+ return fmt.Sprintf(c.GetUserThreadsRoute(userId)+"/%v", threadId)
+}
+
func (c *Client4) GetUserCategoryRoute(userID, teamID string) string {
return c.GetUserRoute(userID) + c.GetTeamRoute(teamID) + "/channels/categories"
}
@@ -334,6 +342,10 @@ func (c *Client4) GetSystemRoute() string {
return "/system"
}
+func (c *Client4) GetCloudRoute() string {
+ return "/cloud"
+}
+
func (c *Client4) GetTestEmailRoute() string {
return "/email/test"
}
@@ -3268,6 +3280,21 @@ func (c *Client4) GetPingWithServerStatus() (string, *Response) {
return MapFromJson(r.Body)["status"], BuildResponse(r)
}
+// GetPingWithFullServerStatus will return the full status if several basic server
+// health checks all pass successfully.
+func (c *Client4) GetPingWithFullServerStatus() (map[string]string, *Response) {
+ r, err := c.DoApiGet(c.GetSystemRoute()+"/ping?get_server_status="+c.boolString(true), "")
+ if r != nil && r.StatusCode == 500 {
+ defer r.Body.Close()
+ return map[string]string{"status": STATUS_UNHEALTHY}, BuildErrorResponse(r, err)
+ }
+ if err != nil {
+ return nil, BuildErrorResponse(r, err)
+ }
+ defer closeBody(r)
+ return MapFromJson(r.Body), BuildResponse(r)
+}
+
// TestEmail will attempt to connect to the configured SMTP server.
func (c *Client4) TestEmail(config *Config) (bool, *Response) {
r, err := c.DoApiPost(c.GetTestEmailRoute(), config.ToJson())
@@ -4090,7 +4117,7 @@ func (c *Client4) MigrateAuthToSaml(fromAuthService string, usersMap map[string]
// UploadLdapPublicCertificate will upload a public certificate for LDAP and set the config to use it.
func (c *Client4) UploadLdapPublicCertificate(data []byte) (bool, *Response) {
- body, writer, err := fileToMultipart(data, LDAP_PUBIC_CERTIFICATE_NAME)
+ body, writer, err := fileToMultipart(data, LDAP_PUBLIC_CERTIFICATE_NAME)
if err != nil {
return false, &Response{Error: NewAppError("UploadLdapPublicCertificate", "model.client.upload_ldap_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
}
@@ -5616,3 +5643,183 @@ func (c *Client4) UpdatePassword(userId, currentPassword, newPassword string) *R
defer closeBody(r)
return BuildResponse(r)
}
+
+// Cloud Section
+
+func (c *Client4) GetCloudProducts() ([]*Product, *Response) {
+ r, appErr := c.DoApiGet(c.GetCloudRoute()+"/products", "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var cloudProducts []*Product
+ json.NewDecoder(r.Body).Decode(&cloudProducts)
+
+ return cloudProducts, BuildResponse(r)
+}
+
+func (c *Client4) CreateCustomerPayment() (*StripeSetupIntent, *Response) {
+ r, appErr := c.DoApiPost(c.GetCloudRoute()+"/payment", "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var setupIntent *StripeSetupIntent
+ json.NewDecoder(r.Body).Decode(&setupIntent)
+
+ return setupIntent, BuildResponse(r)
+}
+
+func (c *Client4) ConfirmCustomerPayment(confirmRequest *ConfirmPaymentMethodRequest) *Response {
+ json, _ := json.Marshal(confirmRequest)
+
+ r, appErr := c.doApiPostBytes(c.GetCloudRoute()+"/payment/confirm", json)
+ if appErr != nil {
+ return BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ return BuildResponse(r)
+}
+
+func (c *Client4) GetCloudCustomer() (*CloudCustomer, *Response) {
+ r, appErr := c.DoApiGet(c.GetCloudRoute()+"/customer", "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var cloudCustomer *CloudCustomer
+ json.NewDecoder(r.Body).Decode(&cloudCustomer)
+
+ return cloudCustomer, BuildResponse(r)
+}
+
+func (c *Client4) GetSubscription() (*Subscription, *Response) {
+ r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription", "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var subscription *Subscription
+ json.NewDecoder(r.Body).Decode(&subscription)
+
+ return subscription, BuildResponse(r)
+}
+
+func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response) {
+ r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/invoices", "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var invoices []*Invoice
+ json.NewDecoder(r.Body).Decode(&invoices)
+
+ return invoices, BuildResponse(r)
+}
+
+func (c *Client4) UpdateCloudCustomer(customerInfo *CloudCustomerInfo) (*CloudCustomer, *Response) {
+ customerBytes, _ := json.Marshal(customerInfo)
+
+ r, appErr := c.doApiPutBytes(c.GetCloudRoute()+"/customer", customerBytes)
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var customer *CloudCustomer
+ json.NewDecoder(r.Body).Decode(&customer)
+
+ return customer, BuildResponse(r)
+}
+
+func (c *Client4) UpdateCloudCustomerAddress(address *Address) (*CloudCustomer, *Response) {
+ addressBytes, _ := json.Marshal(address)
+
+ r, appErr := c.doApiPutBytes(c.GetCloudRoute()+"/customer/address", addressBytes)
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var customer *CloudCustomer
+ json.NewDecoder(r.Body).Decode(&customer)
+
+ return customer, BuildResponse(r)
+}
+
+func (c *Client4) GetUserThreads(userId string, options GetUserThreadsOpts) (*Threads, *Response) {
+ v := url.Values{}
+ if options.Since != 0 {
+ v.Set("since", fmt.Sprintf("%d", options.Since))
+ }
+ if options.Page != 0 {
+ v.Set("page", fmt.Sprintf("%d", options.Page))
+ }
+ if options.PageSize != 0 {
+ v.Set("pageSize", fmt.Sprintf("%d", options.PageSize))
+ }
+ if options.Extended {
+ v.Set("extended", "true")
+ }
+ if options.Deleted {
+ v.Set("deleted", "true")
+ }
+
+ url := c.GetUserThreadsRoute(userId)
+ if len(v) > 0 {
+ url += "?" + v.Encode()
+ }
+
+ r, appErr := c.DoApiGet(url, "")
+ if appErr != nil {
+ return nil, BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ var threads Threads
+ json.NewDecoder(r.Body).Decode(&threads)
+
+ return &threads, BuildResponse(r)
+}
+
+func (c *Client4) UpdateThreadsReadForUser(userId string, timestamp int64) *Response {
+ r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadsRoute(userId), timestamp), "")
+ if appErr != nil {
+ return BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ return BuildResponse(r)
+}
+
+func (c *Client4) UpdateThreadReadForUser(userId, threadId string, timestamp int64) *Response {
+ r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadRoute(userId, threadId), timestamp), "")
+ if appErr != nil {
+ return BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ return BuildResponse(r)
+}
+
+func (c *Client4) UpdateThreadFollowForUser(userId, threadId string, state bool) *Response {
+ var appErr *AppError
+ var r *http.Response
+ if state {
+ r, appErr = c.DoApiPut(c.GetUserThreadRoute(userId, threadId)+"/following", "")
+ } else {
+ r, appErr = c.DoApiDelete(c.GetUserThreadRoute(userId, threadId) + "/following")
+ }
+ if appErr != nil {
+ return BuildErrorResponse(r, appErr)
+ }
+ defer closeBody(r)
+
+ return BuildResponse(r)
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go b/vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go
new file mode 100644
index 00000000..e4fddbcd
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/cloud.go
@@ -0,0 +1,114 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package model
+
+// Product model represents a product on the cloud system.
+type Product struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ PricePerSeat float64 `json:"price_per_seat"`
+ AddOns []*AddOn `json:"add_ons"`
+}
+
+// AddOn represents an addon to a product.
+type AddOn struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ DisplayName string `json:"display_name"`
+ PricePerSeat float64 `json:"price_per_seat"`
+}
+
+// StripeSetupIntent represents the SetupIntent model from Stripe for updating payment methods.
+type StripeSetupIntent struct {
+ ID string `json:"id"`
+ ClientSecret string `json:"client_secret"`
+}
+
+// ConfirmPaymentMethodRequest contains the fields for the customer payment update API.
+type ConfirmPaymentMethodRequest struct {
+ StripeSetupIntentID string `json:"stripe_setup_intent_id"`
+}
+
+// Customer model represents a customer on the system.
+type CloudCustomer struct {
+ CloudCustomerInfo
+ ID string `json:"id"`
+ CreatorID string `json:"creator_id"`
+ CreateAt int64 `json:"create_at"`
+ BillingAddress *Address `json:"billing_address"`
+ CompanyAddress *Address `json:"company_address"`
+ PaymentMethod *PaymentMethod `json:"payment_method"`
+}
+
+// CloudCustomerInfo represents editable info of a customer.
+type CloudCustomerInfo struct {
+ Name string `json:"name"`
+ Email string `json:"email,omitempty"`
+ ContactFirstName string `json:"contact_first_name,omitempty"`
+ ContactLastName string `json:"contact_last_name,omitempty"`
+ NumEmployees int `json:"num_employees"`
+}
+
+// Address model represents a customer's address.
+type Address struct {
+ City string `json:"city"`
+ Country string `json:"country"`
+ Line1 string `json:"line1"`
+ Line2 string `json:"line2"`
+ PostalCode string `json:"postal_code"`
+ State string `json:"state"`
+}
+
+// PaymentMethod represents methods of payment for a customer.
+type PaymentMethod struct {
+ Type string `json:"type"`
+ LastFour int `json:"last_four"`
+ ExpMonth int `json:"exp_month"`
+ ExpYear int `json:"exp_year"`
+ CardBrand string `json:"card_brand"`
+ Name string `json:"name"`
+}
+
+// Subscription model represents a subscription on the system.
+type Subscription struct {
+ ID string `json:"id"`
+ CustomerID string `json:"customer_id"`
+ ProductID string `json:"product_id"`
+ AddOns []string `json:"add_ons"`
+ StartAt int64 `json:"start_at"`
+ EndAt int64 `json:"end_at"`
+ CreateAt int64 `json:"create_at"`
+ Seats int `json:"seats"`
+ Status string `json:"status"`
+ DNS string `json:"dns"`
+ IsPaidTier string `json:"is_paid_tier"`
+ LastInvoice *Invoice `json:"last_invoice"`
+}
+
+// Invoice model represents a cloud invoice
+type Invoice struct {
+ ID string `json:"id"`
+ Number string `json:"number"`
+ CreateAt int64 `json:"create_at"`
+ Total int64 `json:"total"`
+ Tax int64 `json:"tax"`
+ Status string `json:"status"`
+ Description string `json:"description"`
+ PeriodStart int64 `json:"period_start"`
+ PeriodEnd int64 `json:"period_end"`
+ SubscriptionID string `json:"subscription_id"`
+ Items []*InvoiceLineItem `json:"line_items"`
+}
+
+// InvoiceLineItem model represents a cloud invoice lineitem tied to an invoice.
+type InvoiceLineItem struct {
+ PriceID string `json:"price_id"`
+ Total int64 `json:"total"`
+ Quantity int64 `json:"quantity"`
+ PricePerUnit int64 `json:"price_per_unit"`
+ Description string `json:"description"`
+ Type string `json:"type"`
+ Metadata map[string]interface{} `json:"metadata"`
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/config.go b/vendor/github.com/mattermost/mattermost-server/v5/model/config.go
index 42863ead..cbdf0f55 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/config.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/config.go
@@ -12,12 +12,14 @@ import (
"net/http"
"net/url"
"os"
+ "reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/mattermost/ldap"
+ "github.com/mattermost/mattermost-server/v5/mlog"
)
const (
@@ -107,7 +109,7 @@ const (
TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT = ""
TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT = 300
- SQL_SETTINGS_DEFAULT_DATA_SOURCE = "mmuser:mostest@tcp(localhost:3306)/mattermost_test?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s"
+ SQL_SETTINGS_DEFAULT_DATA_SOURCE = "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable&connect_timeout=10"
FILE_SETTINGS_DEFAULT_DIRECTORY = "./data/"
@@ -220,6 +222,8 @@ const (
OFFICE365_SETTINGS_DEFAULT_TOKEN_ENDPOINT = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
OFFICE365_SETTINGS_DEFAULT_USER_API_ENDPOINT = "https://graph.microsoft.com/v1.0/me"
+ CLOUD_SETTINGS_DEFAULT_CWS_URL = "https://customers.mattermost.com"
+
LOCAL_MODE_SOCKET_PATH = "/var/tmp/mattermost_local.socket"
)
@@ -250,26 +254,26 @@ var ServerTLSSupportedCiphers = map[string]uint16{
type ServiceSettings struct {
SiteURL *string `access:"environment,authentication,write_restrictable"`
- WebsocketURL *string `access:"write_restrictable"`
- LicenseFileLocation *string `access:"write_restrictable"`
- ListenAddress *string `access:"environment,write_restrictable"`
- ConnectionSecurity *string `access:"environment,write_restrictable"`
- TLSCertFile *string `access:"environment,write_restrictable"`
- TLSKeyFile *string `access:"environment,write_restrictable"`
- TLSMinVer *string `access:"write_restrictable"`
- TLSStrictTransport *bool `access:"write_restrictable"`
- TLSStrictTransportMaxAge *int64 `access:"write_restrictable"`
- TLSOverwriteCiphers []string `access:"write_restrictable"`
- UseLetsEncrypt *bool `access:"environment,write_restrictable"`
- LetsEncryptCertificateCacheFile *string `access:"environment,write_restrictable"`
- Forward80To443 *bool `access:"environment,write_restrictable"`
- TrustedProxyIPHeader []string `access:"write_restrictable"`
- ReadTimeout *int `access:"environment,write_restrictable"`
- WriteTimeout *int `access:"environment,write_restrictable"`
- IdleTimeout *int `access:"write_restrictable"`
- MaximumLoginAttempts *int `access:"authentication,write_restrictable"`
- GoroutineHealthThreshold *int `access:"write_restrictable"`
- GoogleDeveloperKey *string `access:"site,write_restrictable"`
+ WebsocketURL *string `access:"write_restrictable,cloud_restrictable"`
+ LicenseFileLocation *string `access:"write_restrictable,cloud_restrictable"`
+ ListenAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
+ ConnectionSecurity *string `access:"environment,write_restrictable,cloud_restrictable"`
+ TLSCertFile *string `access:"environment,write_restrictable,cloud_restrictable"`
+ TLSKeyFile *string `access:"environment,write_restrictable,cloud_restrictable"`
+ TLSMinVer *string `access:"write_restrictable,cloud_restrictable"`
+ TLSStrictTransport *bool `access:"write_restrictable,cloud_restrictable"`
+ TLSStrictTransportMaxAge *int64 `access:"write_restrictable,cloud_restrictable"`
+ TLSOverwriteCiphers []string `access:"write_restrictable,cloud_restrictable"`
+ UseLetsEncrypt *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ LetsEncryptCertificateCacheFile *string `access:"environment,write_restrictable,cloud_restrictable"`
+ Forward80To443 *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ TrustedProxyIPHeader []string `access:"write_restrictable,cloud_restrictable"`
+ ReadTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
+ WriteTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
+ IdleTimeout *int `access:"write_restrictable,cloud_restrictable"`
+ MaximumLoginAttempts *int `access:"authentication,write_restrictable,cloud_restrictable"`
+ GoroutineHealthThreshold *int `access:"write_restrictable,cloud_restrictable"`
+ GoogleDeveloperKey *string `access:"site,write_restrictable,cloud_restrictable"`
EnableOAuthServiceProvider *bool `access:"integrations"`
EnableIncomingWebhooks *bool `access:"integrations"`
EnableOutgoingWebhooks *bool `access:"integrations"`
@@ -278,29 +282,29 @@ type ServiceSettings struct {
EnablePostUsernameOverride *bool `access:"integrations"`
EnablePostIconOverride *bool `access:"integrations"`
EnableLinkPreviews *bool `access:"site"`
- EnableTesting *bool `access:"environment,write_restrictable"`
- EnableDeveloper *bool `access:"environment,write_restrictable"`
- EnableOpenTracing *bool `access:"write_restrictable"`
- EnableSecurityFixAlert *bool `access:"environment,write_restrictable"`
- EnableInsecureOutgoingConnections *bool `access:"environment,write_restrictable"`
- AllowedUntrustedInternalConnections *string `access:"environment,write_restrictable"`
+ EnableTesting *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableDeveloper *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableOpenTracing *bool `access:"write_restrictable,cloud_restrictable"`
+ EnableSecurityFixAlert *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableInsecureOutgoingConnections *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AllowedUntrustedInternalConnections *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableMultifactorAuthentication *bool `access:"authentication"`
EnforceMultifactorAuthentication *bool `access:"authentication"`
EnableUserAccessTokens *bool `access:"integrations"`
- AllowCorsFrom *string `access:"integrations,write_restrictable"`
- CorsExposedHeaders *string `access:"integrations,write_restrictable"`
- CorsAllowCredentials *bool `access:"integrations,write_restrictable"`
- CorsDebug *bool `access:"integrations,write_restrictable"`
- AllowCookiesForSubdomains *bool `access:"write_restrictable"`
- ExtendSessionLengthWithActivity *bool `access:"environment,write_restrictable"`
- SessionLengthWebInDays *int `access:"environment,write_restrictable"`
- SessionLengthMobileInDays *int `access:"environment,write_restrictable"`
- SessionLengthSSOInDays *int `access:"environment,write_restrictable"`
- SessionCacheInMinutes *int `access:"environment,write_restrictable"`
- SessionIdleTimeoutInMinutes *int `access:"environment,write_restrictable"`
- WebsocketSecurePort *int `access:"write_restrictable"`
- WebsocketPort *int `access:"write_restrictable"`
- WebserverMode *string `access:"environment,write_restrictable"`
+ AllowCorsFrom *string `access:"integrations,write_restrictable,cloud_restrictable"`
+ CorsExposedHeaders *string `access:"integrations,write_restrictable,cloud_restrictable"`
+ CorsAllowCredentials *bool `access:"integrations,write_restrictable,cloud_restrictable"`
+ CorsDebug *bool `access:"integrations,write_restrictable,cloud_restrictable"`
+ AllowCookiesForSubdomains *bool `access:"write_restrictable,cloud_restrictable"`
+ ExtendSessionLengthWithActivity *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ SessionLengthWebInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
+ SessionLengthMobileInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
+ SessionLengthSSOInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
+ SessionCacheInMinutes *int `access:"environment,write_restrictable,cloud_restrictable"`
+ SessionIdleTimeoutInMinutes *int `access:"environment,write_restrictable,cloud_restrictable"`
+ WebsocketSecurePort *int `access:"write_restrictable,cloud_restrictable"`
+ WebsocketPort *int `access:"write_restrictable,cloud_restrictable"`
+ WebserverMode *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableCustomEmoji *bool `access:"site"`
EnableEmojiPicker *bool `access:"site"`
EnableGifPicker *bool `access:"integrations"`
@@ -310,14 +314,14 @@ type ServiceSettings struct {
DEPRECATED_DO_NOT_USE_RestrictPostDelete *string `json:"RestrictPostDelete" mapstructure:"RestrictPostDelete"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_AllowEditPost *string `json:"AllowEditPost" mapstructure:"AllowEditPost"` // This field is deprecated and must not be used.
PostEditTimeLimit *int `access:"user_management_permissions"`
- TimeBetweenUserTypingUpdatesMilliseconds *int64 `access:"experimental,write_restrictable"`
- EnablePostSearch *bool `access:"write_restrictable"`
- MinimumHashtagLength *int `access:"environment,write_restrictable"`
- EnableUserTypingMessages *bool `access:"experimental,write_restrictable"`
- EnableChannelViewedMessages *bool `access:"experimental,write_restrictable"`
- EnableUserStatuses *bool `access:"write_restrictable"`
- ExperimentalEnableAuthenticationTransfer *bool `access:"experimental,write_restrictable"`
- ClusterLogTimeoutMilliseconds *int `access:"write_restrictable"`
+ TimeBetweenUserTypingUpdatesMilliseconds *int64 `access:"experimental,write_restrictable,cloud_restrictable"`
+ EnablePostSearch *bool `access:"write_restrictable,cloud_restrictable"`
+ MinimumHashtagLength *int `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableUserTypingMessages *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ EnableChannelViewedMessages *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ EnableUserStatuses *bool `access:"write_restrictable,cloud_restrictable"`
+ ExperimentalEnableAuthenticationTransfer *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ ClusterLogTimeoutMilliseconds *int `access:"write_restrictable,cloud_restrictable"`
CloseUnusedDirectMessages *bool `access:"experimental"`
EnablePreviewFeatures *bool `access:"experimental"`
EnableTutorial *bool `access:"experimental"`
@@ -332,10 +336,10 @@ type ServiceSettings struct {
EnableAPITeamDeletion *bool
EnableAPIUserDeletion *bool
ExperimentalEnableHardenedMode *bool `access:"experimental"`
- DisableLegacyMFA *bool `access:"write_restrictable"`
- ExperimentalStrictCSRFEnforcement *bool `access:"experimental,write_restrictable"`
+ DisableLegacyMFA *bool `access:"write_restrictable,cloud_restrictable"`
+ ExperimentalStrictCSRFEnforcement *bool `access:"experimental,write_restrictable,cloud_restrictable"`
EnableEmailInvitations *bool `access:"authentication"`
- DisableBotsWhenOwnerIsDeactivated *bool `access:"integrations,write_restrictable"`
+ DisableBotsWhenOwnerIsDeactivated *bool `access:"integrations,write_restrictable,cloud_restrictable"`
EnableBotAccountCreation *bool `access:"integrations"`
EnableSVGs *bool `access:"site"`
EnableLatex *bool `access:"site"`
@@ -343,6 +347,9 @@ type ServiceSettings struct {
EnableLocalMode *bool
LocalModeSocketLocation *string
EnableAWSMetering *bool
+ SplitKey *string `access:"environment,write_restrictable"`
+ FeatureFlagSyncIntervalSeconds *int `access:"environment,write_restrictable"`
+ DebugSplit *bool `access:"environment,write_restrictable"`
ThreadAutoFollow *bool `access:"experimental"`
ManagedResourcePaths *string `access:"environment,write_restrictable,cloud_restrictable"`
}
@@ -763,6 +770,18 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) {
s.EnableAWSMetering = NewBool(false)
}
+ if s.SplitKey == nil {
+ s.SplitKey = NewString("")
+ }
+
+ if s.FeatureFlagSyncIntervalSeconds == nil {
+ s.FeatureFlagSyncIntervalSeconds = NewInt(30)
+ }
+
+ if s.DebugSplit == nil {
+ s.DebugSplit = NewBool(false)
+ }
+
if s.ThreadAutoFollow == nil {
s.ThreadAutoFollow = NewBool(true)
}
@@ -774,20 +793,20 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) {
type ClusterSettings struct {
Enable *bool `access:"environment,write_restrictable"`
- ClusterName *string `access:"environment,write_restrictable"`
- OverrideHostname *string `access:"environment,write_restrictable"`
- NetworkInterface *string `access:"environment,write_restrictable"`
- BindAddress *string `access:"environment,write_restrictable"`
- AdvertiseAddress *string `access:"environment,write_restrictable"`
- UseIpAddress *bool `access:"environment,write_restrictable"`
- UseExperimentalGossip *bool `access:"environment,write_restrictable"`
- EnableExperimentalGossipEncryption *bool `access:"environment,write_restrictable"`
- ReadOnlyConfig *bool `access:"environment,write_restrictable"`
- GossipPort *int `access:"environment,write_restrictable"`
- StreamingPort *int `access:"environment,write_restrictable"`
- MaxIdleConns *int `access:"environment,write_restrictable"`
- MaxIdleConnsPerHost *int `access:"environment,write_restrictable"`
- IdleConnTimeoutMilliseconds *int `access:"environment,write_restrictable"`
+ ClusterName *string `access:"environment,write_restrictable,cloud_restrictable"`
+ OverrideHostname *string `access:"environment,write_restrictable,cloud_restrictable"`
+ NetworkInterface *string `access:"environment,write_restrictable,cloud_restrictable"`
+ BindAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AdvertiseAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
+ UseIpAddress *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ UseExperimentalGossip *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableExperimentalGossipEncryption *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ ReadOnlyConfig *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ GossipPort *int `access:"environment,write_restrictable,cloud_restrictable"`
+ StreamingPort *int `access:"environment,write_restrictable,cloud_restrictable"`
+ MaxIdleConns *int `access:"environment,write_restrictable,cloud_restrictable"`
+ MaxIdleConnsPerHost *int `access:"environment,write_restrictable,cloud_restrictable"`
+ IdleConnTimeoutMilliseconds *int `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *ClusterSettings) SetDefaults() {
@@ -853,9 +872,9 @@ func (s *ClusterSettings) SetDefaults() {
}
type MetricsSettings struct {
- Enable *bool `access:"environment,write_restrictable"`
- BlockProfileRate *int `access:"environment,write_restrictable"`
- ListenAddress *string `access:"environment,write_restrictable"`
+ Enable *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ BlockProfileRate *int `access:"environment,write_restrictable,cloud_restrictable"`
+ ListenAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *MetricsSettings) SetDefaults() {
@@ -873,14 +892,15 @@ func (s *MetricsSettings) SetDefaults() {
}
type ExperimentalSettings struct {
- ClientSideCertEnable *bool `access:"experimental"`
- ClientSideCertCheck *string `access:"experimental"`
- EnableClickToReply *bool `access:"experimental,write_restrictable"`
- LinkMetadataTimeoutMilliseconds *int64 `access:"experimental,write_restrictable"`
+ ClientSideCertEnable *bool `access:"experimental,cloud_restrictable"`
+ ClientSideCertCheck *string `access:"experimental,cloud_restrictable"`
+ EnableClickToReply *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ LinkMetadataTimeoutMilliseconds *int64 `access:"experimental,write_restrictable,cloud_restrictable"`
RestrictSystemAdmin *bool `access:"experimental,write_restrictable"`
- UseNewSAMLLibrary *bool `access:"experimental"`
+ UseNewSAMLLibrary *bool `access:"experimental,cloud_restrictable"`
CloudUserLimit *int64 `access:"experimental,write_restrictable"`
CloudBilling *bool `access:"experimental,write_restrictable"`
+ EnableSharedChannels *bool `access:"experimental"`
}
func (s *ExperimentalSettings) SetDefaults() {
@@ -916,10 +936,14 @@ func (s *ExperimentalSettings) SetDefaults() {
if s.UseNewSAMLLibrary == nil {
s.UseNewSAMLLibrary = NewBool(false)
}
+
+ if s.EnableSharedChannels == nil {
+ s.EnableSharedChannels = NewBool(false)
+ }
}
type AnalyticsSettings struct {
- MaxUsersForStatistics *int `access:"write_restrictable"`
+ MaxUsersForStatistics *int `access:"write_restrictable,cloud_restrictable"`
}
func (s *AnalyticsSettings) SetDefaults() {
@@ -1026,22 +1050,22 @@ func (s *Office365Settings) SSOSettings() *SSOSettings {
}
type SqlSettings struct {
- DriverName *string `access:"environment,write_restrictable"`
- DataSource *string `access:"environment,write_restrictable"`
- DataSourceReplicas []string `access:"environment,write_restrictable"`
- DataSourceSearchReplicas []string `access:"environment,write_restrictable"`
- MaxIdleConns *int `access:"environment,write_restrictable"`
- ConnMaxLifetimeMilliseconds *int `access:"environment,write_restrictable"`
- MaxOpenConns *int `access:"environment,write_restrictable"`
- Trace *bool `access:"environment,write_restrictable"`
- AtRestEncryptKey *string `access:"environment,write_restrictable"`
- QueryTimeout *int `access:"environment,write_restrictable"`
- DisableDatabaseSearch *bool `access:"environment,write_restrictable"`
+ DriverName *string `access:"environment,write_restrictable,cloud_restrictable"`
+ DataSource *string `access:"environment,write_restrictable,cloud_restrictable"`
+ DataSourceReplicas []string `access:"environment,write_restrictable,cloud_restrictable"`
+ DataSourceSearchReplicas []string `access:"environment,write_restrictable,cloud_restrictable"`
+ MaxIdleConns *int `access:"environment,write_restrictable,cloud_restrictable"`
+ ConnMaxLifetimeMilliseconds *int `access:"environment,write_restrictable,cloud_restrictable"`
+ MaxOpenConns *int `access:"environment,write_restrictable,cloud_restrictable"`
+ Trace *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AtRestEncryptKey *string `access:"environment,write_restrictable,cloud_restrictable"`
+ QueryTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
+ DisableDatabaseSearch *bool `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *SqlSettings) SetDefaults(isUpdate bool) {
if s.DriverName == nil {
- s.DriverName = NewString(DATABASE_DRIVER_MYSQL)
+ s.DriverName = NewString(DATABASE_DRIVER_POSTGRES)
}
if s.DataSource == nil {
@@ -1092,17 +1116,17 @@ func (s *SqlSettings) SetDefaults(isUpdate bool) {
}
type LogSettings struct {
- EnableConsole *bool `access:"environment,write_restrictable"`
- ConsoleLevel *string `access:"environment,write_restrictable"`
- ConsoleJson *bool `access:"environment,write_restrictable"`
- EnableFile *bool `access:"environment,write_restrictable"`
- FileLevel *string `access:"environment,write_restrictable"`
- FileJson *bool `access:"environment,write_restrictable"`
- FileLocation *string `access:"environment,write_restrictable"`
- EnableWebhookDebugging *bool `access:"environment,write_restrictable"`
- EnableDiagnostics *bool `access:"environment,write_restrictable"`
- EnableSentry *bool `access:"environment,write_restrictable"`
- AdvancedLoggingConfig *string `access:"environment,write_restrictable"`
+ EnableConsole *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ ConsoleLevel *string `access:"environment,write_restrictable,cloud_restrictable"`
+ ConsoleJson *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableFile *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ FileLevel *string `access:"environment,write_restrictable,cloud_restrictable"`
+ FileJson *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ FileLocation *string `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableWebhookDebugging *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableDiagnostics *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableSentry *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AdvancedLoggingConfig *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *LogSettings) SetDefaults() {
@@ -1152,14 +1176,14 @@ func (s *LogSettings) SetDefaults() {
}
type ExperimentalAuditSettings struct {
- FileEnabled *bool `access:"experimental,write_restrictable"`
- FileName *string `access:"experimental,write_restrictable"`
- FileMaxSizeMB *int `access:"experimental,write_restrictable"`
- FileMaxAgeDays *int `access:"experimental,write_restrictable"`
- FileMaxBackups *int `access:"experimental,write_restrictable"`
- FileCompress *bool `access:"experimental,write_restrictable"`
- FileMaxQueueSize *int `access:"experimental,write_restrictable"`
- AdvancedLoggingConfig *string `access:"experimental,write_restrictable"`
+ FileEnabled *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileName *string `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileMaxSizeMB *int `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileMaxAgeDays *int `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileMaxBackups *int `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileCompress *bool `access:"experimental,write_restrictable,cloud_restrictable"`
+ FileMaxQueueSize *int `access:"experimental,write_restrictable,cloud_restrictable"`
+ AdvancedLoggingConfig *string `access:"experimental,write_restrictable,cloud_restrictable"`
}
func (s *ExperimentalAuditSettings) SetDefaults() {
@@ -1197,14 +1221,14 @@ func (s *ExperimentalAuditSettings) SetDefaults() {
}
type NotificationLogSettings struct {
- EnableConsole *bool `access:"write_restrictable"`
- ConsoleLevel *string `access:"write_restrictable"`
- ConsoleJson *bool `access:"write_restrictable"`
- EnableFile *bool `access:"write_restrictable"`
- FileLevel *string `access:"write_restrictable"`
- FileJson *bool `access:"write_restrictable"`
- FileLocation *string `access:"write_restrictable"`
- AdvancedLoggingConfig *string `access:"write_restrictable"`
+ EnableConsole *bool `access:"write_restrictable,cloud_restrictable"`
+ ConsoleLevel *string `access:"write_restrictable,cloud_restrictable"`
+ ConsoleJson *bool `access:"write_restrictable,cloud_restrictable"`
+ EnableFile *bool `access:"write_restrictable,cloud_restrictable"`
+ FileLevel *string `access:"write_restrictable,cloud_restrictable"`
+ FileJson *bool `access:"write_restrictable,cloud_restrictable"`
+ FileLocation *string `access:"write_restrictable,cloud_restrictable"`
+ AdvancedLoggingConfig *string `access:"write_restrictable,cloud_restrictable"`
}
func (s *NotificationLogSettings) SetDefaults() {
@@ -1272,25 +1296,25 @@ func (s *PasswordSettings) SetDefaults() {
}
type FileSettings struct {
- EnableFileAttachments *bool `access:"site"`
- EnableMobileUpload *bool `access:"site"`
- EnableMobileDownload *bool `access:"site"`
- MaxFileSize *int64 `access:"environment"`
- DriverName *string `access:"environment,write_restrictable"`
- Directory *string `access:"environment,write_restrictable"`
- EnablePublicLink *bool `access:"site"`
- PublicLinkSalt *string `access:"site"`
- InitialFont *string `access:"environment"`
- AmazonS3AccessKeyId *string `access:"environment,write_restrictable"`
- AmazonS3SecretAccessKey *string `access:"environment,write_restrictable"`
- AmazonS3Bucket *string `access:"environment,write_restrictable"`
- AmazonS3PathPrefix *string `access:"environment,write_restrictable"`
- AmazonS3Region *string `access:"environment,write_restrictable"`
- AmazonS3Endpoint *string `access:"environment,write_restrictable"`
- AmazonS3SSL *bool `access:"environment,write_restrictable"`
- AmazonS3SignV2 *bool `access:"environment,write_restrictable"`
- AmazonS3SSE *bool `access:"environment,write_restrictable"`
- AmazonS3Trace *bool `access:"environment,write_restrictable"`
+ EnableFileAttachments *bool `access:"site,cloud_restrictable"`
+ EnableMobileUpload *bool `access:"site,cloud_restrictable"`
+ EnableMobileDownload *bool `access:"site,cloud_restrictable"`
+ MaxFileSize *int64 `access:"environment,cloud_restrictable"`
+ DriverName *string `access:"environment,write_restrictable,cloud_restrictable"`
+ Directory *string `access:"environment,write_restrictable,cloud_restrictable"`
+ EnablePublicLink *bool `access:"site,cloud_restrictable"`
+ PublicLinkSalt *string `access:"site,cloud_restrictable"`
+ InitialFont *string `access:"environment,cloud_restrictable"`
+ AmazonS3AccessKeyId *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3SecretAccessKey *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3Bucket *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3PathPrefix *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3Region *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3Endpoint *string `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3SSL *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3SignV2 *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3SSE *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ AmazonS3Trace *bool `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *FileSettings) SetDefaults(isUpdate bool) {
@@ -1388,16 +1412,16 @@ type EmailSettings struct {
UseChannelInEmailNotifications *bool `access:"experimental"`
RequireEmailVerification *bool `access:"authentication"`
FeedbackName *string `access:"site"`
- FeedbackEmail *string `access:"site"`
- ReplyToAddress *string `access:"site"`
+ FeedbackEmail *string `access:"site,cloud_restrictable"`
+ ReplyToAddress *string `access:"site,cloud_restrictable"`
FeedbackOrganization *string `access:"site"`
- EnableSMTPAuth *bool `access:"environment,write_restrictable"`
- SMTPUsername *string `access:"environment,write_restrictable"`
- SMTPPassword *string `access:"environment,write_restrictable"`
- SMTPServer *string `access:"environment,write_restrictable"`
- SMTPPort *string `access:"environment,write_restrictable"`
- SMTPServerTimeout *int
- ConnectionSecurity *string `access:"environment,write_restrictable"`
+ EnableSMTPAuth *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ SMTPUsername *string `access:"environment,write_restrictable,cloud_restrictable"`
+ SMTPPassword *string `access:"environment,write_restrictable,cloud_restrictable"`
+ SMTPServer *string `access:"environment,write_restrictable,cloud_restrictable"`
+ SMTPPort *string `access:"environment,write_restrictable,cloud_restrictable"`
+ SMTPServerTimeout *int `access:"cloud_restrictable"`
+ ConnectionSecurity *string `access:"environment,write_restrictable,cloud_restrictable"`
SendPushNotifications *bool `access:"environment"`
PushNotificationServer *string `access:"environment"`
PushNotificationContents *string `access:"site"`
@@ -1406,7 +1430,7 @@ type EmailSettings struct {
EmailBatchingBufferSize *int `access:"experimental"`
EmailBatchingInterval *int `access:"experimental"`
EnablePreviewModeBanner *bool `access:"site"`
- SkipServerCertificateVerification *bool `access:"environment,write_restrictable"`
+ SkipServerCertificateVerification *bool `access:"environment,write_restrictable,cloud_restrictable"`
EmailNotificationContentsType *string `access:"site"`
LoginButtonColor *string `access:"experimental"`
LoginButtonBorderColor *string `access:"experimental"`
@@ -1556,13 +1580,13 @@ func (s *EmailSettings) SetDefaults(isUpdate bool) {
}
type RateLimitSettings struct {
- Enable *bool `access:"environment,write_restrictable"`
- PerSec *int `access:"environment,write_restrictable"`
- MaxBurst *int `access:"environment,write_restrictable"`
- MemoryStoreSize *int `access:"environment,write_restrictable"`
- VaryByRemoteAddr *bool `access:"environment,write_restrictable"`
- VaryByUser *bool `access:"environment,write_restrictable"`
- VaryByHeader string `access:"environment,write_restrictable"`
+ Enable *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ PerSec *int `access:"environment,write_restrictable,cloud_restrictable"`
+ MaxBurst *int `access:"environment,write_restrictable,cloud_restrictable"`
+ MemoryStoreSize *int `access:"environment,write_restrictable,cloud_restrictable"`
+ VaryByRemoteAddr *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ VaryByUser *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ VaryByHeader string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *RateLimitSettings) SetDefaults() {
@@ -1607,11 +1631,11 @@ func (s *PrivacySettings) setDefaults() {
}
type SupportSettings struct {
- TermsOfServiceLink *string `access:"site,write_restrictable"`
- PrivacyPolicyLink *string `access:"site,write_restrictable"`
- AboutLink *string `access:"site,write_restrictable"`
- HelpLink *string `access:"site,write_restrictable"`
- ReportAProblemLink *string `access:"site,write_restrictable"`
+ TermsOfServiceLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ PrivacyPolicyLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ AboutLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ HelpLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ ReportAProblemLink *string `access:"site,write_restrictable,cloud_restrictable"`
SupportEmail *string `access:"site"`
CustomTermsOfServiceEnabled *bool `access:"compliance"`
CustomTermsOfServiceReAcceptancePeriod *int `access:"compliance"`
@@ -1938,12 +1962,12 @@ func (s *TeamSettings) SetDefaults() {
}
type ClientRequirements struct {
- AndroidLatestVersion string `access:"write_restrictable"`
- AndroidMinVersion string `access:"write_restrictable"`
- DesktopLatestVersion string `access:"write_restrictable"`
- DesktopMinVersion string `access:"write_restrictable"`
- IosLatestVersion string `access:"write_restrictable"`
- IosMinVersion string `access:"write_restrictable"`
+ AndroidLatestVersion string `access:"write_restrictable,cloud_restrictable"`
+ AndroidMinVersion string `access:"write_restrictable,cloud_restrictable"`
+ DesktopLatestVersion string `access:"write_restrictable,cloud_restrictable"`
+ DesktopMinVersion string `access:"write_restrictable,cloud_restrictable"`
+ IosLatestVersion string `access:"write_restrictable,cloud_restrictable"`
+ IosMinVersion string `access:"write_restrictable,cloud_restrictable"`
}
type LdapSettings struct {
@@ -2189,6 +2213,7 @@ type SamlSettings struct {
Enable *bool `access:"authentication"`
EnableSyncWithLdap *bool `access:"authentication"`
EnableSyncWithLdapIncludeAuth *bool `access:"authentication"`
+ IgnoreGuestsLdapSync *bool `access:"authentication"`
Verify *bool `access:"authentication"`
Encrypt *bool `access:"authentication"`
@@ -2243,6 +2268,10 @@ func (s *SamlSettings) SetDefaults() {
s.EnableSyncWithLdapIncludeAuth = NewBool(false)
}
+ if s.IgnoreGuestsLdapSync == nil {
+ s.IgnoreGuestsLdapSync = NewBool(false)
+ }
+
if s.EnableAdminAttribute == nil {
s.EnableAdminAttribute = NewBool(false)
}
@@ -2367,9 +2396,9 @@ func (s *SamlSettings) SetDefaults() {
}
type NativeAppSettings struct {
- AppDownloadLink *string `access:"site,write_restrictable"`
- AndroidAppDownloadLink *string `access:"site,write_restrictable"`
- IosAppDownloadLink *string `access:"site,write_restrictable"`
+ AppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ AndroidAppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
+ IosAppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
}
func (s *NativeAppSettings) SetDefaults() {
@@ -2387,27 +2416,27 @@ func (s *NativeAppSettings) SetDefaults() {
}
type ElasticsearchSettings struct {
- ConnectionUrl *string `access:"environment,write_restrictable"`
- Username *string `access:"environment,write_restrictable"`
- Password *string `access:"environment,write_restrictable"`
- EnableIndexing *bool `access:"environment,write_restrictable"`
- EnableSearching *bool `access:"environment,write_restrictable"`
- EnableAutocomplete *bool `access:"environment,write_restrictable"`
- Sniff *bool `access:"environment,write_restrictable"`
- PostIndexReplicas *int `access:"environment,write_restrictable"`
- PostIndexShards *int `access:"environment,write_restrictable"`
- ChannelIndexReplicas *int `access:"environment,write_restrictable"`
- ChannelIndexShards *int `access:"environment,write_restrictable"`
- UserIndexReplicas *int `access:"environment,write_restrictable"`
- UserIndexShards *int `access:"environment,write_restrictable"`
- AggregatePostsAfterDays *int `access:"environment,write_restrictable"`
- PostsAggregatorJobStartTime *string `access:"environment,write_restrictable"`
- IndexPrefix *string `access:"environment,write_restrictable"`
- LiveIndexingBatchSize *int `access:"environment,write_restrictable"`
- BulkIndexingTimeWindowSeconds *int `access:"environment,write_restrictable"`
- RequestTimeoutSeconds *int `access:"environment,write_restrictable"`
- SkipTLSVerification *bool `access:"environment,write_restrictable"`
- Trace *string `access:"environment,write_restrictable"`
+ ConnectionUrl *string `access:"environment,write_restrictable,cloud_restrictable"`
+ Username *string `access:"environment,write_restrictable,cloud_restrictable"`
+ Password *string `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableIndexing *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableSearching *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ EnableAutocomplete *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ Sniff *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ PostIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
+ PostIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
+ ChannelIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
+ ChannelIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
+ UserIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
+ UserIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
+ AggregatePostsAfterDays *int `access:"environment,write_restrictable,cloud_restrictable"`
+ PostsAggregatorJobStartTime *string `access:"environment,write_restrictable,cloud_restrictable"`
+ IndexPrefix *string `access:"environment,write_restrictable,cloud_restrictable"`
+ LiveIndexingBatchSize *int `access:"environment,write_restrictable,cloud_restrictable"`
+ BulkIndexingTimeWindowSeconds *int `access:"environment,write_restrictable,cloud_restrictable"`
+ RequestTimeoutSeconds *int `access:"environment,write_restrictable,cloud_restrictable"`
+ SkipTLSVerification *bool `access:"environment,write_restrictable,cloud_restrictable"`
+ Trace *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *ElasticsearchSettings) SetDefaults() {
@@ -2557,8 +2586,8 @@ func (s *DataRetentionSettings) SetDefaults() {
}
type JobSettings struct {
- RunJobs *bool `access:"write_restrictable"`
- RunScheduler *bool `access:"write_restrictable"`
+ RunJobs *bool `access:"write_restrictable,cloud_restrictable"`
+ RunScheduler *bool `access:"write_restrictable,cloud_restrictable"`
}
func (s *JobSettings) SetDefaults() {
@@ -2571,25 +2600,35 @@ func (s *JobSettings) SetDefaults() {
}
}
+type CloudSettings struct {
+ CWSUrl *string `access:"environment,write_restrictable"`
+}
+
+func (s *CloudSettings) SetDefaults() {
+ if s.CWSUrl == nil {
+ s.CWSUrl = NewString(CLOUD_SETTINGS_DEFAULT_CWS_URL)
+ }
+}
+
type PluginState struct {
Enable bool
}
type PluginSettings struct {
- Enable *bool `access:"plugins"`
- EnableUploads *bool `access:"plugins,write_restrictable"`
- AllowInsecureDownloadUrl *bool `access:"plugins,write_restrictable"`
- EnableHealthCheck *bool `access:"plugins,write_restrictable"`
- Directory *string `access:"plugins,write_restrictable"`
- ClientDirectory *string `access:"plugins,write_restrictable"`
+ Enable *bool `access:"plugins,write_restrictable"`
+ EnableUploads *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ AllowInsecureDownloadUrl *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ EnableHealthCheck *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ Directory *string `access:"plugins,write_restrictable,cloud_restrictable"`
+ ClientDirectory *string `access:"plugins,write_restrictable,cloud_restrictable"`
Plugins map[string]map[string]interface{} `access:"plugins"`
PluginStates map[string]*PluginState `access:"plugins"`
- EnableMarketplace *bool `access:"plugins"`
- EnableRemoteMarketplace *bool `access:"plugins"`
- AutomaticPrepackagedPlugins *bool `access:"plugins"`
- RequirePluginSignature *bool `access:"plugins"`
- MarketplaceUrl *string `access:"plugins"`
- SignaturePublicKeyFiles []string `access:"plugins"`
+ EnableMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ EnableRemoteMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ AutomaticPrepackagedPlugins *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ RequirePluginSignature *bool `access:"plugins,write_restrictable,cloud_restrictable"`
+ MarketplaceUrl *string `access:"plugins,write_restrictable,cloud_restrictable"`
+ SignaturePublicKeyFiles []string `access:"plugins,write_restrictable,cloud_restrictable"`
}
func (s *PluginSettings) SetDefaults(ls LogSettings) {
@@ -2630,6 +2669,16 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) {
s.PluginStates["com.mattermost.nps"] = &PluginState{Enable: ls.EnableDiagnostics == nil || *ls.EnableDiagnostics}
}
+ if s.PluginStates["com.mattermost.plugin-incident-management"] == nil && BuildEnterpriseReady == "true" {
+ // Enable the incident management plugin by default
+ s.PluginStates["com.mattermost.plugin-incident-management"] = &PluginState{Enable: true}
+ }
+
+ if s.PluginStates["com.mattermost.plugin-channel-export"] == nil && BuildEnterpriseReady == "true" {
+ // Enable the channel export plugin by default
+ s.PluginStates["com.mattermost.plugin-channel-export"] = &PluginState{Enable: true}
+ }
+
if s.EnableMarketplace == nil {
s.EnableMarketplace = NewBool(PLUGIN_SETTINGS_DEFAULT_ENABLE_MARKETPLACE)
}
@@ -2808,7 +2857,9 @@ func (s *ImageProxySettings) SetDefaults(ss ServiceSettings) {
type ConfigFunc func() *Config
+const ConfigAccessTagType = "access"
const ConfigAccessTagWriteRestrictable = "write_restrictable"
+const ConfigAccessTagCloudRestrictable = "cloud_restrictable"
// Config fields support the 'access' tag with the following values corresponding to the suffix of the associated
// PERMISSION_SYSCONSOLE_*_* permission Id: 'about', 'reporting', 'user_management_users',
@@ -2822,6 +2873,9 @@ const ConfigAccessTagWriteRestrictable = "write_restrictable"
//
// PERMISSION_MANAGE_SYSTEM always grants read access.
//
+// Config values with the access tag 'cloud_restrictable' mean that are marked to be filtered when it's used in a cloud licensed
+// environment with ExperimentalSettings.RestrictedSystemAdmin set to true.
+//
// Example:
// type HairSettings struct {
// // Colour is writeable with either PERMISSION_SYSCONSOLE_WRITE_REPORTING or PERMISSION_SYSCONSOLE_WRITE_USER_MANAGEMENT_GROUPS.
@@ -2874,6 +2928,8 @@ type Config struct {
DisplaySettings DisplaySettings
GuestAccountsSettings GuestAccountsSettings
ImageProxySettings ImageProxySettings
+ CloudSettings CloudSettings
+ FeatureFlags *FeatureFlags `json:",omitempty"`
}
func (o *Config) Clone() *Config {
@@ -2889,6 +2945,18 @@ func (o *Config) ToJson() string {
return string(b)
}
+func (o *Config) ToJsonFiltered(tagType, tagValue string) string {
+ filteredConfigMap := structToMapFilteredByTag(*o, tagType, tagValue)
+ for key, value := range filteredConfigMap {
+ v, ok := value.(map[string]interface{})
+ if ok && len(v) == 0 {
+ delete(filteredConfigMap, key)
+ }
+ }
+ b, _ := json.Marshal(filteredConfigMap)
+ return string(b)
+}
+
func (o *Config) GetSSOService(service string) *SSOSettings {
switch service {
case SERVICE_GITLAB:
@@ -2960,6 +3028,11 @@ func (o *Config) SetDefaults() {
o.DisplaySettings.SetDefaults()
o.GuestAccountsSettings.SetDefaults()
o.ImageProxySettings.SetDefaults(o.ServiceSettings)
+ o.CloudSettings.SetDefaults()
+ if o.FeatureFlags == nil {
+ o.FeatureFlags = &FeatureFlags{}
+ o.FeatureFlags.SetDefaults()
+ }
}
func (o *Config) IsValid() *AppError {
@@ -3588,4 +3661,66 @@ func (o *Config) Sanitize() {
if o.ServiceSettings.GfycatApiSecret != nil && len(*o.ServiceSettings.GfycatApiSecret) > 0 {
*o.ServiceSettings.GfycatApiSecret = FAKE_SETTING
}
+
+ *o.ServiceSettings.SplitKey = FAKE_SETTING
+}
+
+// structToMapFilteredByTag converts a struct into a map removing those fields that has the tag passed
+// as argument
+func structToMapFilteredByTag(t interface{}, typeOfTag, filterTag string) map[string]interface{} {
+ defer func() {
+ if r := recover(); r != nil {
+ mlog.Error("Panicked in structToMapFilteredByTag. This should never happen.", mlog.Any("recover", r))
+ }
+ }()
+
+ val := reflect.ValueOf(t)
+ elemField := reflect.TypeOf(t)
+
+ if val.Kind() != reflect.Struct {
+ return nil
+ }
+
+ out := map[string]interface{}{}
+
+ for i := 0; i < val.NumField(); i++ {
+ field := val.Field(i)
+
+ structField := elemField.Field(i)
+ tagPermissions := strings.Split(structField.Tag.Get(typeOfTag), ",")
+ if isTagPresent(filterTag, tagPermissions) {
+ continue
+ }
+
+ var value interface{}
+
+ switch field.Kind() {
+ case reflect.Struct:
+ value = structToMapFilteredByTag(field.Interface(), typeOfTag, filterTag)
+ case reflect.Ptr:
+ indirectType := field.Elem()
+ if indirectType.Kind() == reflect.Struct {
+ value = structToMapFilteredByTag(indirectType.Interface(), typeOfTag, filterTag)
+ } else if indirectType.Kind() != reflect.Invalid {
+ value = indirectType.Interface()
+ }
+ default:
+ value = field.Interface()
+ }
+
+ out[val.Type().Field(i).Name] = value
+ }
+
+ return out
+}
+
+func isTagPresent(tag string, tags []string) bool {
+ for _, val := range tags {
+ tagValue := strings.TrimSpace(val)
+ if tagValue != "" && tagValue == tag {
+ return true
+ }
+ }
+
+ return false
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go b/vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go
new file mode 100644
index 00000000..316c7ffb
--- /dev/null
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/feature_flags.go
@@ -0,0 +1,18 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package model
+
+type FeatureFlags struct {
+ // Exists only for unit and manual testing.
+ // When set to a value, will be returned by the ping endpoint.
+ TestFeature string
+
+ // Toggle on and off scheduled jobs for cloud user limit emails see MM-29999
+ CloudDelinquentEmailJobsEnabled bool
+}
+
+func (f *FeatureFlags) SetDefaults() {
+ f.TestFeature = "off"
+ f.CloudDelinquentEmailJobsEnabled = false
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go b/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go
index aded5be9..c622b8f2 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/file_info.go
@@ -4,14 +4,19 @@
package model
import (
+ "bytes"
"encoding/json"
"image"
"image/gif"
+ "image/jpeg"
"io"
"mime"
"net/http"
"path/filepath"
"strings"
+
+ "github.com/disintegration/imaging"
+ "github.com/mattermost/mattermost-server/v5/mlog"
)
const (
@@ -53,6 +58,7 @@ type FileInfo struct {
Height int `json:"height,omitempty"`
HasPreviewImage bool `json:"has_preview_image,omitempty"`
MiniPreview *[]byte `json:"mini_preview"` // declared as *[]byte to avoid postgres/mysql differences in deserialization
+ Content string `json:"-"`
}
func (fi *FileInfo) ToJson() string {
@@ -151,6 +157,19 @@ func NewInfo(name string) *FileInfo {
return info
}
+func GenerateMiniPreviewImage(img image.Image) *[]byte {
+ preview := imaging.Resize(img, 16, 16, imaging.Lanczos)
+
+ buf := new(bytes.Buffer)
+
+ if err := jpeg.Encode(buf, preview, &jpeg.Options{Quality: 90}); err != nil {
+ mlog.Error("Unable to encode image as mini preview jpg", mlog.Err(err))
+ return nil
+ }
+ data := buf.Bytes()
+ return &data
+}
+
func GetInfoForBytes(name string, data io.ReadSeeker, size int) (*FileInfo, *AppError) {
info := &FileInfo{
Name: name,
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/group.go b/vendor/github.com/mattermost/mattermost-server/v5/model/group.go
index 2eda1184..49783c83 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/group.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/group.go
@@ -157,7 +157,7 @@ func (group *Group) requiresRemoteId() bool {
func (group *Group) IsValidForUpdate() *AppError {
if !IsValidId(group.Id) {
- return NewAppError("Group.IsValidForUpdate", "model.group.id.app_error", nil, "", http.StatusBadRequest)
+ return NewAppError("Group.IsValidForUpdate", "app.group.id.app_error", nil, "", http.StatusBadRequest)
}
if group.CreateAt == 0 {
return NewAppError("Group.IsValidForUpdate", "model.group.create_at.app_error", nil, "", http.StatusBadRequest)
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go b/vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go
index 3f362d64..a572c9de 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/integration_action.go
@@ -16,6 +16,7 @@ import (
"io"
"math/big"
"net/http"
+ "reflect"
"strconv"
"strings"
)
@@ -124,13 +125,19 @@ func (p *PostAction) Equals(input *PostAction) bool {
for key, value := range p.Integration.Context {
inputValue, ok := input.Integration.Context[key]
-
if !ok {
return false
}
- if value != inputValue {
- return false
+ switch inputValue.(type) {
+ case string, bool, int, float64:
+ if value != inputValue {
+ return false
+ }
+ default:
+ if !reflect.DeepEqual(value, inputValue) {
+ return false
+ }
}
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/job.go b/vendor/github.com/mattermost/mattermost-server/v5/model/job.go
index a4bb30a1..072bfb2b 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/job.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/job.go
@@ -22,6 +22,7 @@ const (
JOB_TYPE_EXPIRY_NOTIFY = "expiry_notify"
JOB_TYPE_PRODUCT_NOTICES = "product_notices"
JOB_TYPE_ACTIVE_USERS = "active_users"
+ JOB_TYPE_CLOUD = "cloud"
JOB_STATUS_PENDING = "pending"
JOB_STATUS_IN_PROGRESS = "in_progress"
@@ -65,6 +66,7 @@ func (j *Job) IsValid() *AppError {
case JOB_TYPE_PRODUCT_NOTICES:
case JOB_TYPE_EXPIRY_NOTIFY:
case JOB_TYPE_ACTIVE_USERS:
+ case JOB_TYPE_CLOUD:
default:
return NewAppError("Job.IsValid", "model.job.is_valid.type.app_error", nil, "id="+j.Id, http.StatusBadRequest)
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go b/vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go
index 4e19c5b1..1262dfb8 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/ldap.go
@@ -4,7 +4,7 @@
package model
const (
- USER_AUTH_SERVICE_LDAP = "ldap"
- LDAP_PUBIC_CERTIFICATE_NAME = "ldap-public.crt"
- LDAP_PRIVATE_KEY_NAME = "ldap-private.key"
+ USER_AUTH_SERVICE_LDAP = "ldap"
+ LDAP_PUBLIC_CERTIFICATE_NAME = "ldap-public.crt"
+ LDAP_PRIVATE_KEY_NAME = "ldap-private.key"
)
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go b/vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go
index 47644513..cccfb7f6 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/marketplace_plugin.go
@@ -80,7 +80,9 @@ type MarketplacePluginFilter struct {
ServerVersion string
BuildEnterpriseReady bool
EnterprisePlugins bool
+ Cloud bool
LocalOnly bool
+ Platform string
}
// ApplyToURL modifies the given url to include query string parameters for the request.
@@ -94,7 +96,9 @@ func (filter *MarketplacePluginFilter) ApplyToURL(u *url.URL) {
q.Add("server_version", filter.ServerVersion)
q.Add("build_enterprise_ready", strconv.FormatBool(filter.BuildEnterpriseReady))
q.Add("enterprise_plugins", strconv.FormatBool(filter.EnterprisePlugins))
+ q.Add("cloud", strconv.FormatBool(filter.Cloud))
q.Add("local_only", strconv.FormatBool(filter.LocalOnly))
+ q.Add("platform", filter.Platform)
u.RawQuery = q.Encode()
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/migration.go b/vendor/github.com/mattermost/mattermost-server/v5/model/migration.go
index 2e7a0f71..f552d168 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/migration.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/migration.go
@@ -21,4 +21,6 @@ const (
MIGRATION_KEY_ADD_SYSTEM_CONSOLE_PERMISSIONS = "add_system_console_permissions"
MIGRATION_KEY_SIDEBAR_CATEGORIES_PHASE_2 = "migration_sidebar_categories_phase_2"
MIGRATION_KEY_ADD_CONVERT_CHANNEL_PERMISSIONS = "add_convert_channel_permissions"
+ MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS = "add_system_roles_permissions"
+ MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS = "manage_shared_channel_permissions"
)
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/permission.go b/vendor/github.com/mattermost/mattermost-server/v5/model/permission.go
index cf05c281..d982962f 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/permission.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/permission.go
@@ -99,6 +99,7 @@ var PERMISSION_USE_CHANNEL_MENTIONS *Permission
var PERMISSION_USE_GROUP_MENTIONS *Permission
var PERMISSION_READ_OTHER_USERS_TEAMS *Permission
var PERMISSION_EDIT_BRAND *Permission
+var PERMISSION_MANAGE_SHARED_CHANNELS *Permission
var PERMISSION_SYSCONSOLE_READ_ABOUT *Permission
var PERMISSION_SYSCONSOLE_WRITE_ABOUT *Permission
@@ -121,6 +122,9 @@ var PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS *Permission
var PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS *Permission
var PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS *Permission
+var PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES *Permission
+var PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES *Permission
+
var PERMISSION_SYSCONSOLE_READ_ENVIRONMENT *Permission
var PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT *Permission
@@ -516,6 +520,12 @@ func initializePermissions() {
"authentication.permissions.delete_others_posts.description",
PermissionScopeChannel,
}
+ PERMISSION_MANAGE_SHARED_CHANNELS = &Permission{
+ "manage_shared_channels",
+ "authentication.permissions.manage_shared_channels.name",
+ "authentication.permissions.manage_shared_channels.description",
+ PermissionScopeSystem,
+ }
PERMISSION_REMOVE_USER_FROM_TEAM = &Permission{
"remove_user_from_team",
"authentication.permissions.remove_user_from_team.name",
@@ -750,6 +760,18 @@ func initializePermissions() {
"authentication.permissions.use_group_mentions.description",
PermissionScopeSystem,
}
+ PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES = &Permission{
+ "sysconsole_read_user_management_system_roles",
+ "authentication.permissions.use_group_mentions.name",
+ "authentication.permissions.use_group_mentions.description",
+ PermissionScopeSystem,
+ }
+ PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES = &Permission{
+ "sysconsole_write_user_management_system_roles",
+ "authentication.permissions.use_group_mentions.name",
+ "authentication.permissions.use_group_mentions.description",
+ PermissionScopeSystem,
+ }
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT = &Permission{
"sysconsole_read_environment",
"authentication.permissions.use_group_mentions.name",
@@ -855,6 +877,7 @@ func initializePermissions() {
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_TEAMS,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS,
+ PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_SYSTEM_ROLES,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT,
PERMISSION_SYSCONSOLE_READ_SITE,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION,
@@ -872,6 +895,7 @@ func initializePermissions() {
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_TEAMS,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS,
+ PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_SYSTEM_ROLES,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT,
PERMISSION_SYSCONSOLE_WRITE_SITE,
PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION,
@@ -912,6 +936,7 @@ func initializePermissions() {
PERMISSION_PROMOTE_GUEST,
PERMISSION_DEMOTE_TO_GUEST,
PERMISSION_EDIT_BRAND,
+ PERMISSION_MANAGE_SHARED_CHANNELS,
}
TeamScopedPermissions := []*Permission{
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/role.go b/vendor/github.com/mattermost/mattermost-server/v5/model/role.go
index e880a1d8..271e295b 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/role.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/role.go
@@ -133,6 +133,7 @@ func init() {
PERMISSION_SYSCONSOLE_READ_SITE.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id,
PERMISSION_SYSCONSOLE_READ_PLUGINS.Id,
+ PERMISSION_SYSCONSOLE_READ_COMPLIANCE.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id,
PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL.Id,
}
@@ -482,15 +483,16 @@ func (r *Role) IsValidWithoutId() bool {
return false
}
- for _, permission := range r.Permissions {
- permissionValidated := false
- for _, p := range append(AllPermissions, DeprecatedPermissions...) {
+ check := func(perms []*Permission, permission string) bool {
+ for _, p := range perms {
if permission == p.Id {
- permissionValidated = true
- break
+ return true
}
}
-
+ return false
+ }
+ for _, permission := range r.Permissions {
+ permissionValidated := check(AllPermissions, permission) || check(DeprecatedPermissions, permission)
if !permissionValidated {
return false
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/serialized_gen.go b/vendor/github.com/mattermost/mattermost-server/v5/model/serialized_gen.go
index c64d88de..1f16f1cb 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/serialized_gen.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/serialized_gen.go
@@ -1620,3 +1620,160 @@ func (z *User) Msgsize() (s int) {
s += msgp.BoolSize + msgp.StringPrefixSize + len(z.MfaSecret) + msgp.Int64Size + msgp.BoolSize + msgp.StringPrefixSize + len(z.BotDescription) + msgp.Int64Size + msgp.StringPrefixSize + len(z.TermsOfServiceId) + msgp.Int64Size
return
}
+
+// DecodeMsg implements msgp.Decodable
+func (z *UserMap) DecodeMsg(dc *msgp.Reader) (err error) {
+ var zb0003 uint32
+ zb0003, err = dc.ReadMapHeader()
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if (*z) == nil {
+ (*z) = make(UserMap, zb0003)
+ } else if len((*z)) > 0 {
+ for key := range *z {
+ delete((*z), key)
+ }
+ }
+ for zb0003 > 0 {
+ zb0003--
+ var zb0001 string
+ var zb0002 *User
+ zb0001, err = dc.ReadString()
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if dc.IsNil() {
+ err = dc.ReadNil()
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ zb0002 = nil
+ } else {
+ if zb0002 == nil {
+ zb0002 = new(User)
+ }
+ err = zb0002.DecodeMsg(dc)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ (*z)[zb0001] = zb0002
+ }
+ return
+}
+
+// EncodeMsg implements msgp.Encodable
+func (z UserMap) EncodeMsg(en *msgp.Writer) (err error) {
+ err = en.WriteMapHeader(uint32(len(z)))
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ for zb0004, zb0005 := range z {
+ err = en.WriteString(zb0004)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if zb0005 == nil {
+ err = en.WriteNil()
+ if err != nil {
+ return
+ }
+ } else {
+ err = zb0005.EncodeMsg(en)
+ if err != nil {
+ err = msgp.WrapError(err, zb0004)
+ return
+ }
+ }
+ }
+ return
+}
+
+// MarshalMsg implements msgp.Marshaler
+func (z UserMap) MarshalMsg(b []byte) (o []byte, err error) {
+ o = msgp.Require(b, z.Msgsize())
+ o = msgp.AppendMapHeader(o, uint32(len(z)))
+ for zb0004, zb0005 := range z {
+ o = msgp.AppendString(o, zb0004)
+ if zb0005 == nil {
+ o = msgp.AppendNil(o)
+ } else {
+ o, err = zb0005.MarshalMsg(o)
+ if err != nil {
+ err = msgp.WrapError(err, zb0004)
+ return
+ }
+ }
+ }
+ return
+}
+
+// UnmarshalMsg implements msgp.Unmarshaler
+func (z *UserMap) UnmarshalMsg(bts []byte) (o []byte, err error) {
+ var zb0003 uint32
+ zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if (*z) == nil {
+ (*z) = make(UserMap, zb0003)
+ } else if len((*z)) > 0 {
+ for key := range *z {
+ delete((*z), key)
+ }
+ }
+ for zb0003 > 0 {
+ var zb0001 string
+ var zb0002 *User
+ zb0003--
+ zb0001, bts, err = msgp.ReadStringBytes(bts)
+ if err != nil {
+ err = msgp.WrapError(err)
+ return
+ }
+ if msgp.IsNil(bts) {
+ bts, err = msgp.ReadNilBytes(bts)
+ if err != nil {
+ return
+ }
+ zb0002 = nil
+ } else {
+ if zb0002 == nil {
+ zb0002 = new(User)
+ }
+ bts, err = zb0002.UnmarshalMsg(bts)
+ if err != nil {
+ err = msgp.WrapError(err, zb0001)
+ return
+ }
+ }
+ (*z)[zb0001] = zb0002
+ }
+ o = bts
+ return
+}
+
+// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
+func (z UserMap) Msgsize() (s int) {
+ s = msgp.MapHeaderSize
+ if z != nil {
+ for zb0004, zb0005 := range z {
+ _ = zb0005
+ s += msgp.StringPrefixSize + len(zb0004)
+ if zb0005 == nil {
+ s += msgp.NilSize
+ } else {
+ s += zb0005.Msgsize()
+ }
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/system.go b/vendor/github.com/mattermost/mattermost-server/v5/model/system.go
index f826276f..4e76c959 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/system.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/system.go
@@ -31,6 +31,10 @@ const (
SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500 = "warn_metric_number_of_active_users_500"
SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M = "warn_metric_number_of_posts_2M"
SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY = "LastWarnMetricRunTimestamp"
+ AWS_METERING_REPORT_INTERVAL = 1
+ AWS_METERING_DIMENSION_USAGE_HRS = "UsageHrs"
+ USER_LIMIT_OVERAGE_CYCLE_END_DATE = "UserLimitOverageCycleEndDate"
+ OVER_USER_LIMIT_FORGIVEN_COUNT = "OverUserLimitForgivenCount"
)
const (
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go b/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go
index 71bf74f4..ec091c00 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/thread.go
@@ -15,6 +15,42 @@ type Thread struct {
Participants StringArray `json:"participants"`
}
+type ThreadResponse struct {
+ PostId string `json:"id"`
+ ReplyCount int64 `json:"reply_count"`
+ LastReplyAt int64 `json:"last_reply_at"`
+ LastViewedAt int64 `json:"last_viewed_at"`
+ Participants []*User `json:"participants"`
+ Post *Post `json:"post"`
+}
+
+type Threads struct {
+ Total int64 `json:"total"`
+ Threads []*ThreadResponse `json:"threads"`
+}
+
+type GetUserThreadsOpts struct {
+ // Page specifies which part of the results to return, by PageSize. Default = 0
+ Page uint64
+
+ // PageSize specifies the size of the returned chunk of results. Default = 30
+ PageSize uint64
+
+ // Extended will enrich the response with participant details. Default = false
+ Extended bool
+
+ // Deleted will specify that even deleted threads should be returned (For mobile sync). Default = false
+ Deleted bool
+
+ // Since filters the threads based on their LastUpdateAt timestamp.
+ Since uint64
+}
+
+func (o *Threads) ToJson() string {
+ b, _ := json.Marshal(o)
+ return string(b)
+}
+
func (o *Thread) ToJson() string {
b, _ := json.Marshal(o)
return string(b)
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/user.go b/vendor/github.com/mattermost/mattermost-server/v5/model/user.go
index 4e4d067c..dd4e2ba8 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/user.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/user.go
@@ -98,6 +98,12 @@ type User struct {
TermsOfServiceCreateAt int64 `db:"-" json:"terms_of_service_create_at,omitempty"`
}
+//msgp UserMap
+
+// UserMap is a map from a userId to a user object.
+// It is used to generate methods which can be used for fast serialization/de-serialization.
+type UserMap map[string]*User
+
type UserUpdate struct {
Old *User
New *User
@@ -540,11 +546,11 @@ func (u *User) SanitizeInput(isAdmin bool) {
if !isAdmin {
u.AuthData = NewString("")
u.AuthService = ""
+ u.EmailVerified = false
}
u.LastPasswordUpdate = 0
u.LastPictureUpdate = 0
u.FailedAttempts = 0
- u.EmailVerified = false
u.MfaActive = false
u.MfaSecret = ""
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go b/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go
index 9a7ab229..3aed19da 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go
@@ -516,7 +516,7 @@ func IsValidHttpUrl(rawUrl string) bool {
return false
}
- if _, err := url.ParseRequestURI(rawUrl); err != nil {
+ if u, err := url.ParseRequestURI(rawUrl); err != nil || u.Scheme == "" || u.Host == "" {
return false
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/version.go b/vendor/github.com/mattermost/mattermost-server/v5/model/version.go
index aba587f7..63145660 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/version.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/version.go
@@ -13,6 +13,7 @@ import (
// It should be maintained in chronological order with most current
// release at the front of the list.
var versions = []string{
+ "5.30.0",
"5.29.0",
"5.28.0",
"5.27.0",
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_client.go b/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_client.go
index 72ca4a8f..cd89e2d8 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_client.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_client.go
@@ -35,7 +35,7 @@ const avgReadMsgSizeBytes = 1024
// WebSocketClient stores the necessary information required to
// communicate with a WebSocket endpoint.
// A client must read from PingTimeoutChannel, EventChannel and ResponseChannel to prevent
-// deadlocks from occuring in the program.
+// deadlocks from occurring in the program.
type WebSocketClient struct {
Url string // The location of the server like "ws://localhost:8065"
ApiUrl string // The API location of the server like "ws://localhost:8065/api/v3"
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_message.go b/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_message.go
index 281b50cf..a4f92f80 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_message.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/model/websocket_message.go
@@ -57,6 +57,7 @@ const (
WEBSOCKET_EVENT_CONFIG_CHANGED = "config_changed"
WEBSOCKET_EVENT_OPEN_DIALOG = "open_dialog"
WEBSOCKET_EVENT_GUESTS_DEACTIVATED = "guests_deactivated"
+ WEBSOCKET_EVENT_USER_ACTIVATION_STATUS_CHANGE = "user_activation_status_change"
WEBSOCKET_EVENT_RECEIVED_GROUP = "received_group"
WEBSOCKET_EVENT_RECEIVED_GROUP_ASSOCIATED_TO_TEAM = "received_group_associated_to_team"
WEBSOCKET_EVENT_RECEIVED_GROUP_NOT_ASSOCIATED_TO_TEAM = "received_group_not_associated_to_team"
@@ -68,6 +69,7 @@ const (
WEBSOCKET_EVENT_SIDEBAR_CATEGORY_ORDER_UPDATED = "sidebar_category_order_updated"
WEBSOCKET_WARN_METRIC_STATUS_RECEIVED = "warn_metric_status_received"
WEBSOCKET_WARN_METRIC_STATUS_REMOVED = "warn_metric_status_removed"
+ WEBSOCKET_EVENT_CLOUD_PAYMENT_STATUS_UPDATED = "cloud_payment_status_updated"
)
type WebSocketMessage interface {
@@ -201,6 +203,22 @@ func (ev *WebSocketEvent) ToJson() string {
return string(b)
}
+// Encode encodes the event to the given encoder.
+func (ev *WebSocketEvent) Encode(enc *json.Encoder) error {
+ if ev.precomputedJSON != nil {
+ return enc.Encode(json.RawMessage(
+ fmt.Sprintf(`{"event": %s, "data": %s, "broadcast": %s, "seq": %d}`, ev.precomputedJSON.Event, ev.precomputedJSON.Data, ev.precomputedJSON.Broadcast, ev.Sequence),
+ ))
+ }
+
+ return enc.Encode(webSocketEventJSON{
+ ev.Event,
+ ev.Data,
+ ev.Broadcast,
+ ev.Sequence,
+ })
+}
+
func WebSocketEventFromJson(data io.Reader) *WebSocketEvent {
var ev WebSocketEvent
var o webSocketEventJSON
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/autolink.go b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/autolink.go
index 14180836..d06ada66 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/autolink.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/autolink.go
@@ -14,6 +14,7 @@ import (
var (
DefaultUrlSchemes = []string{"http", "https", "ftp", "mailto", "tel"}
+ wwwAutoLinkRegex = regexp.MustCompile(`^www\d{0,3}\.`)
)
// Given a string with a w at the given position, tries to parse and return a range containing a www link.
@@ -30,7 +31,7 @@ func parseWWWAutolink(data string, position int) (Range, bool) {
}
// Check that this starts with www
- if len(data)-position < 4 || !regexp.MustCompile(`^www\d{0,3}\.`).MatchString(data[position:]) {
+ if len(data)-position < 4 || !wwwAutoLinkRegex.MatchString(data[position:]) {
return Range{}, false
}
@@ -59,9 +60,8 @@ func isAllowedBeforeWWWLink(c byte) bool {
switch c {
case '*', '_', '~', ')':
return true
- default:
- return false
}
+ return false
}
// Given a string with a : at the given position, tried to parse and return a range containing a URL scheme
@@ -153,9 +153,8 @@ func checkDomain(data string, allowShort bool) int {
// this is called from parseWWWAutolink
if foundPeriod {
return i
- } else {
- return 0
}
+ return 0
}
// Returns true if the provided link starts with a valid character for a domain name. Equivalent to
@@ -251,7 +250,6 @@ func canEndAutolink(c rune) bool {
switch c {
case '?', '!', '.', ',', ':', '*', '_', '~', '\'', '"':
return false
- default:
- return true
}
+ return true
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/blocks.go b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/blocks.go
index 44ee178d..607356e0 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/blocks.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/blocks.go
@@ -37,13 +37,14 @@ type Range struct {
End int
}
-func closeBlocks(blocks []Block, referenceDefinitions *[]*ReferenceDefinition) {
+func closeBlocks(blocks []Block, referenceDefinitions []*ReferenceDefinition) []*ReferenceDefinition {
for _, block := range blocks {
block.Close()
if p, ok := block.(*Paragraph); ok && len(p.ReferenceDefinitions) > 0 {
- *referenceDefinitions = append(*referenceDefinitions, p.ReferenceDefinitions...)
+ referenceDefinitions = append(referenceDefinitions, p.ReferenceDefinitions...)
}
}
+ return referenceDefinitions
}
func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefinition) {
@@ -78,7 +79,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti
for i := lastMatchIndex; i >= 0; i-- {
if container, ok := openBlocks[i].(ContainerBlock); ok {
if addedBlocks := container.AddChild(newBlocks); addedBlocks != nil {
- closeBlocks(openBlocks[i+1:], &referenceDefinitions)
+ referenceDefinitions = closeBlocks(openBlocks[i+1:], referenceDefinitions)
openBlocks = openBlocks[:i+1]
openBlocks = append(openBlocks, addedBlocks...)
didAdd = true
@@ -98,7 +99,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti
continue
}
- closeBlocks(openBlocks[lastMatchIndex+1:], &referenceDefinitions)
+ referenceDefinitions = closeBlocks(openBlocks[lastMatchIndex+1:], referenceDefinitions)
openBlocks = openBlocks[:lastMatchIndex+1]
if openBlocks[lastMatchIndex].AddLine(indentation, r) {
@@ -109,7 +110,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti
for i := lastMatchIndex; i >= 0; i-- {
if container, ok := openBlocks[i].(ContainerBlock); ok {
if newBlocks := container.AddChild([]Block{paragraph}); newBlocks != nil {
- closeBlocks(openBlocks[i+1:], &referenceDefinitions)
+ referenceDefinitions = closeBlocks(openBlocks[i+1:], referenceDefinitions)
openBlocks = openBlocks[:i+1]
openBlocks = append(openBlocks, newBlocks...)
break
@@ -119,7 +120,7 @@ func ParseBlocks(markdown string, lines []Line) (*Document, []*ReferenceDefiniti
}
}
- closeBlocks(openBlocks, &referenceDefinitions)
+ referenceDefinitions = closeBlocks(openBlocks, referenceDefinitions)
return document, referenceDefinitions
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/inlines.go b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/inlines.go
index 4303607f..a67f2f04 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/inlines.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/inlines.go
@@ -595,7 +595,7 @@ func ParseInlines(markdown string, ranges []Range, referenceDefinitions []*Refer
}
func MergeInlineText(inlines []Inline) []Inline {
- var ret []Inline
+ ret := inlines[:0]
for i, v := range inlines {
// always add first node
if i == 0 {
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/lines.go b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/lines.go
index a0a64491..a67ec976 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/lines.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/lines.go
@@ -3,13 +3,16 @@
package markdown
+import "strings"
+
type Line struct {
Range
}
-func ParseLines(markdown string) (lines []Line) {
+func ParseLines(markdown string) []Line {
lineStartPosition := 0
isAfterCarriageReturn := false
+ lines := make([]Line, 0, strings.Count(markdown, "\n"))
for position, r := range markdown {
if r == '\n' {
lines = append(lines, Line{Range{lineStartPosition, position + 1}})
@@ -23,5 +26,5 @@ func ParseLines(markdown string) (lines []Line) {
if lineStartPosition < len(markdown) {
lines = append(lines, Line{Range{lineStartPosition, len(markdown)}})
}
- return
+ return lines
}
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/markdown.go b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/markdown.go
index a9879cee..5ccdad8c 100644
--- a/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/markdown.go
+++ b/vendor/github.com/mattermost/mattermost-server/v5/utils/markdown/markdown.go
@@ -23,9 +23,8 @@ func isWhitespace(c rune) bool {
switch c {
case ' ', '\t', '\n', '\u000b', '\u000c', '\r':
return true
- default:
- return false
}
+ return false
}
func isWhitespaceByte(c byte) bool {
diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go
index 04c4229c..41215d7f 100644
--- a/vendor/github.com/mattn/go-colorable/colorable_windows.go
+++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go
@@ -719,7 +719,7 @@ loop:
n256setup()
}
attr &= backgroundMask
- attr |= n256foreAttr[n256]
+ attr |= n256foreAttr[n256%len(n256foreAttr)]
i += 2
}
} else if len(token) == 5 && token[i+1] == "2" {
@@ -761,7 +761,7 @@ loop:
n256setup()
}
attr &= foregroundMask
- attr |= n256backAttr[n256]
+ attr |= n256backAttr[n256%len(n256backAttr)]
i += 2
}
} else if len(token) == 5 && token[i+1] == "2" {
diff --git a/vendor/github.com/mattn/godown/godown.go b/vendor/github.com/mattn/godown/godown.go
index 5aae9690..12f59882 100644
--- a/vendor/github.com/mattn/godown/godown.go
+++ b/vendor/github.com/mattn/godown/godown.go
@@ -303,10 +303,10 @@ func walk(node *html.Node, w io.Writer, nest int, option *Option) {
walk(c, &buf, 1, option)
if lines := strings.Split(strings.TrimSpace(buf.String()), "\n"); len(lines) > 0 {
for i, l := range lines {
- if i > 0 || nest > 0 {
+ if i > 0 {
fmt.Fprint(w, "\n")
}
- fmt.Fprint(w, strings.Repeat(" ", nest)+strings.TrimSpace(l))
+ fmt.Fprint(w, strings.Repeat(" ", nest)+l)
}
fmt.Fprint(w, "\n")
}
diff --git a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml
index 242b5b54..ff5376b0 100644
--- a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml
+++ b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml
@@ -13,9 +13,9 @@ stages:
vmImage: ubuntu-latest
steps:
- task: GoTool@0
- displayName: "Install Go 1.14"
+ displayName: "Install Go 1.15"
inputs:
- version: "1.14"
+ version: "1.15"
- script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/"
- script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml
- script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml
@@ -36,9 +36,9 @@ stages:
vmImage: ubuntu-latest
steps:
- task: GoTool@0
- displayName: "Install Go 1.14"
+ displayName: "Install Go 1.15"
inputs:
- version: "1.14"
+ version: "1.15"
- task: Go@0
displayName: "go fmt ./..."
inputs:
@@ -51,9 +51,9 @@ stages:
vmImage: ubuntu-latest
steps:
- task: GoTool@0
- displayName: "Install Go 1.14"
+ displayName: "Install Go 1.15"
inputs:
- version: "1.14"
+ version: "1.15"
- task: Go@0
displayName: "Generate coverage"
inputs:
@@ -71,9 +71,9 @@ stages:
vmImage: ubuntu-latest
steps:
- task: GoTool@0
- displayName: "Install Go 1.14"
+ displayName: "Install Go 1.15"
inputs:
- version: "1.14"
+ version: "1.15"
- script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/"
- task: Bash@3
inputs:
@@ -86,9 +86,9 @@ stages:
vmImage: ubuntu-latest
steps:
- task: GoTool@0
- displayName: "Install Go 1.14"
+ displayName: "Install Go 1.15"
inputs:
- version: "1.14"
+ version: "1.15"
- script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/"
- script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml
- script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml
@@ -102,6 +102,15 @@ stages:
displayName: "unit tests"
strategy:
matrix:
+ linux 1.15:
+ goVersion: '1.15'
+ imageName: 'ubuntu-latest'
+ mac 1.15:
+ goVersion: '1.15'
+ imageName: 'macOS-latest'
+ windows 1.15:
+ goVersion: '1.15'
+ imageName: 'windows-latest'
linux 1.14:
goVersion: '1.14'
imageName: 'ubuntu-latest'
@@ -111,15 +120,6 @@ stages:
windows 1.14:
goVersion: '1.14'
imageName: 'windows-latest'
- linux 1.13:
- goVersion: '1.13'
- imageName: 'ubuntu-latest'
- mac 1.13:
- goVersion: '1.13'
- imageName: 'macOS-latest'
- windows 1.13:
- goVersion: '1.13'
- imageName: 'windows-latest'
pool:
vmImage: $(imageName)
steps:
@@ -155,7 +155,7 @@ stages:
- task: GoTool@0
displayName: "Install Go"
inputs:
- version: 1.14
+ version: 1.15
- task: Bash@3
inputs:
targetType: inline
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.json b/vendor/github.com/pelletier/go-toml/benchmark.json
deleted file mode 100644
index 86f99c6a..00000000
--- a/vendor/github.com/pelletier/go-toml/benchmark.json
+++ /dev/null
@@ -1,164 +0,0 @@
-{
- "array": {
- "key1": [
- 1,
- 2,
- 3
- ],
- "key2": [
- "red",
- "yellow",
- "green"
- ],
- "key3": [
- [
- 1,
- 2
- ],
- [
- 3,
- 4,
- 5
- ]
- ],
- "key4": [
- [
- 1,
- 2
- ],
- [
- "a",
- "b",
- "c"
- ]
- ],
- "key5": [
- 1,
- 2,
- 3
- ],
- "key6": [
- 1,
- 2
- ]
- },
- "boolean": {
- "False": false,
- "True": true
- },
- "datetime": {
- "key1": "1979-05-27T07:32:00Z",
- "key2": "1979-05-27T00:32:00-07:00",
- "key3": "1979-05-27T00:32:00.999999-07:00"
- },
- "float": {
- "both": {
- "key": 6.626e-34
- },
- "exponent": {
- "key1": 5e+22,
- "key2": 1000000,
- "key3": -0.02
- },
- "fractional": {
- "key1": 1,
- "key2": 3.1415,
- "key3": -0.01
- },
- "underscores": {
- "key1": 9224617.445991227,
- "key2": 1e+100
- }
- },
- "fruit": [{
- "name": "apple",
- "physical": {
- "color": "red",
- "shape": "round"
- },
- "variety": [{
- "name": "red delicious"
- },
- {
- "name": "granny smith"
- }
- ]
- },
- {
- "name": "banana",
- "variety": [{
- "name": "plantain"
- }]
- }
- ],
- "integer": {
- "key1": 99,
- "key2": 42,
- "key3": 0,
- "key4": -17,
- "underscores": {
- "key1": 1000,
- "key2": 5349221,
- "key3": 12345
- }
- },
- "products": [{
- "name": "Hammer",
- "sku": 738594937
- },
- {},
- {
- "color": "gray",
- "name": "Nail",
- "sku": 284758393
- }
- ],
- "string": {
- "basic": {
- "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
- },
- "literal": {
- "multiline": {
- "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n",
- "regex2": "I [dw]on't need \\d{2} apples"
- },
- "quoted": "Tom \"Dubs\" Preston-Werner",
- "regex": "\u003c\\i\\c*\\s*\u003e",
- "winpath": "C:\\Users\\nodejs\\templates",
- "winpath2": "\\\\ServerX\\admin$\\system32\\"
- },
- "multiline": {
- "continued": {
- "key1": "The quick brown fox jumps over the lazy dog.",
- "key2": "The quick brown fox jumps over the lazy dog.",
- "key3": "The quick brown fox jumps over the lazy dog."
- },
- "key1": "One\nTwo",
- "key2": "One\nTwo",
- "key3": "One\nTwo"
- }
- },
- "table": {
- "inline": {
- "name": {
- "first": "Tom",
- "last": "Preston-Werner"
- },
- "point": {
- "x": 1,
- "y": 2
- }
- },
- "key": "value",
- "subtable": {
- "key": "another value"
- }
- },
- "x": {
- "y": {
- "z": {
- "w": {}
- }
- }
- }
-}
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh
index 7914fff4..a69d3040 100644
--- a/vendor/github.com/pelletier/go-toml/benchmark.sh
+++ b/vendor/github.com/pelletier/go-toml/benchmark.sh
@@ -20,11 +20,15 @@ git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null
pushd ${ref_tempdir} >/dev/null
git checkout ${reference_ref} >/dev/null 2>/dev/null
go test -bench=. -benchmem | tee ${ref_benchmark}
+cd benchmark
+go test -bench=. -benchmem | tee -a ${ref_benchmark}
popd >/dev/null
echo ""
echo "=== local"
go test -bench=. -benchmem | tee ${local_benchmark}
+cd benchmark
+go test -bench=. -benchmem | tee -a ${local_benchmark}
echo ""
echo "=== diff"
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml
deleted file mode 100644
index dfd77e09..00000000
--- a/vendor/github.com/pelletier/go-toml/benchmark.toml
+++ /dev/null
@@ -1,244 +0,0 @@
-################################################################################
-## Comment
-
-# Speak your mind with the hash symbol. They go from the symbol to the end of
-# the line.
-
-
-################################################################################
-## Table
-
-# Tables (also known as hash tables or dictionaries) are collections of
-# key/value pairs. They appear in square brackets on a line by themselves.
-
-[table]
-
-key = "value" # Yeah, you can do this.
-
-# Nested tables are denoted by table names with dots in them. Name your tables
-# whatever crap you please, just don't use #, ., [ or ].
-
-[table.subtable]
-
-key = "another value"
-
-# You don't need to specify all the super-tables if you don't want to. TOML
-# knows how to do it for you.
-
-# [x] you
-# [x.y] don't
-# [x.y.z] need these
-[x.y.z.w] # for this to work
-
-
-################################################################################
-## Inline Table
-
-# Inline tables provide a more compact syntax for expressing tables. They are
-# especially useful for grouped data that can otherwise quickly become verbose.
-# Inline tables are enclosed in curly braces `{` and `}`. No newlines are
-# allowed between the curly braces unless they are valid within a value.
-
-[table.inline]
-
-name = { first = "Tom", last = "Preston-Werner" }
-point = { x = 1, y = 2 }
-
-
-################################################################################
-## String
-
-# There are four ways to express strings: basic, multi-line basic, literal, and
-# multi-line literal. All strings must contain only valid UTF-8 characters.
-
-[string.basic]
-
-basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
-
-[string.multiline]
-
-# The following strings are byte-for-byte equivalent:
-key1 = "One\nTwo"
-key2 = """One\nTwo"""
-key3 = """
-One
-Two"""
-
-[string.multiline.continued]
-
-# The following strings are byte-for-byte equivalent:
-key1 = "The quick brown fox jumps over the lazy dog."
-
-key2 = """
-The quick brown \
-
-
- fox jumps over \
- the lazy dog."""
-
-key3 = """\
- The quick brown \
- fox jumps over \
- the lazy dog.\
- """
-
-[string.literal]
-
-# What you see is what you get.
-winpath = 'C:\Users\nodejs\templates'
-winpath2 = '\\ServerX\admin$\system32\'
-quoted = 'Tom "Dubs" Preston-Werner'
-regex = '<\i\c*\s*>'
-
-
-[string.literal.multiline]
-
-regex2 = '''I [dw]on't need \d{2} apples'''
-lines = '''
-The first newline is
-trimmed in raw strings.
- All other whitespace
- is preserved.
-'''
-
-
-################################################################################
-## Integer
-
-# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
-# Negative numbers are prefixed with a minus sign.
-
-[integer]
-
-key1 = +99
-key2 = 42
-key3 = 0
-key4 = -17
-
-[integer.underscores]
-
-# For large numbers, you may use underscores to enhance readability. Each
-# underscore must be surrounded by at least one digit.
-key1 = 1_000
-key2 = 5_349_221
-key3 = 1_2_3_4_5 # valid but inadvisable
-
-
-################################################################################
-## Float
-
-# A float consists of an integer part (which may be prefixed with a plus or
-# minus sign) followed by a fractional part and/or an exponent part.
-
-[float.fractional]
-
-key1 = +1.0
-key2 = 3.1415
-key3 = -0.01
-
-[float.exponent]
-
-key1 = 5e+22
-key2 = 1e6
-key3 = -2E-2
-
-[float.both]
-
-key = 6.626e-34
-
-[float.underscores]
-
-key1 = 9_224_617.445_991_228_313
-key2 = 1e1_00
-
-
-################################################################################
-## Boolean
-
-# Booleans are just the tokens you're used to. Always lowercase.
-
-[boolean]
-
-True = true
-False = false
-
-
-################################################################################
-## Datetime
-
-# Datetimes are RFC 3339 dates.
-
-[datetime]
-
-key1 = 1979-05-27T07:32:00Z
-key2 = 1979-05-27T00:32:00-07:00
-key3 = 1979-05-27T00:32:00.999999-07:00
-
-
-################################################################################
-## Array
-
-# Arrays are square brackets with other primitives inside. Whitespace is
-# ignored. Elements are separated by commas. Data types may not be mixed.
-
-[array]
-
-key1 = [ 1, 2, 3 ]
-key2 = [ "red", "yellow", "green" ]
-key3 = [ [ 1, 2 ], [3, 4, 5] ]
-#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
-
-# Arrays can also be multiline. So in addition to ignoring whitespace, arrays
-# also ignore newlines between the brackets. Terminating commas are ok before
-# the closing bracket.
-
-key5 = [
- 1, 2, 3
-]
-key6 = [
- 1,
- 2, # this is ok
-]
-
-
-################################################################################
-## Array of Tables
-
-# These can be expressed by using a table name in double brackets. Each table
-# with the same double bracketed name will be an element in the array. The
-# tables are inserted in the order encountered.
-
-[[products]]
-
-name = "Hammer"
-sku = 738594937
-
-[[products]]
-
-[[products]]
-
-name = "Nail"
-sku = 284758393
-color = "gray"
-
-
-# You can create nested arrays of tables as well.
-
-[[fruit]]
- name = "apple"
-
- [fruit.physical]
- color = "red"
- shape = "round"
-
- [[fruit.variety]]
- name = "red delicious"
-
- [[fruit.variety]]
- name = "granny smith"
-
-[[fruit]]
- name = "banana"
-
- [[fruit.variety]]
- name = "plantain"
diff --git a/vendor/github.com/pelletier/go-toml/benchmark.yml b/vendor/github.com/pelletier/go-toml/benchmark.yml
deleted file mode 100644
index 0bd19f08..00000000
--- a/vendor/github.com/pelletier/go-toml/benchmark.yml
+++ /dev/null
@@ -1,121 +0,0 @@
----
-array:
- key1:
- - 1
- - 2
- - 3
- key2:
- - red
- - yellow
- - green
- key3:
- - - 1
- - 2
- - - 3
- - 4
- - 5
- key4:
- - - 1
- - 2
- - - a
- - b
- - c
- key5:
- - 1
- - 2
- - 3
- key6:
- - 1
- - 2
-boolean:
- 'False': false
- 'True': true
-datetime:
- key1: '1979-05-27T07:32:00Z'
- key2: '1979-05-27T00:32:00-07:00'
- key3: '1979-05-27T00:32:00.999999-07:00'
-float:
- both:
- key: 6.626e-34
- exponent:
- key1: 5.0e+22
- key2: 1000000
- key3: -0.02
- fractional:
- key1: 1
- key2: 3.1415
- key3: -0.01
- underscores:
- key1: 9224617.445991227
- key2: 1.0e+100
-fruit:
-- name: apple
- physical:
- color: red
- shape: round
- variety:
- - name: red delicious
- - name: granny smith
-- name: banana
- variety:
- - name: plantain
-integer:
- key1: 99
- key2: 42
- key3: 0
- key4: -17
- underscores:
- key1: 1000
- key2: 5349221
- key3: 12345
-products:
-- name: Hammer
- sku: 738594937
-- {}
-- color: gray
- name: Nail
- sku: 284758393
-string:
- basic:
- basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
- literal:
- multiline:
- lines: |
- The first newline is
- trimmed in raw strings.
- All other whitespace
- is preserved.
- regex2: I [dw]on't need \d{2} apples
- quoted: Tom "Dubs" Preston-Werner
- regex: "<\\i\\c*\\s*>"
- winpath: C:\Users\nodejs\templates
- winpath2: "\\\\ServerX\\admin$\\system32\\"
- multiline:
- continued:
- key1: The quick brown fox jumps over the lazy dog.
- key2: The quick brown fox jumps over the lazy dog.
- key3: The quick brown fox jumps over the lazy dog.
- key1: |-
- One
- Two
- key2: |-
- One
- Two
- key3: |-
- One
- Two
-table:
- inline:
- name:
- first: Tom
- last: Preston-Werner
- point:
- x: 1
- y: 2
- key: value
- subtable:
- key: another value
-x:
- y:
- z:
- w: {}
diff --git a/vendor/github.com/pelletier/go-toml/go.mod b/vendor/github.com/pelletier/go-toml/go.mod
index c7faa6b3..e924cb90 100644
--- a/vendor/github.com/pelletier/go-toml/go.mod
+++ b/vendor/github.com/pelletier/go-toml/go.mod
@@ -2,8 +2,4 @@ module github.com/pelletier/go-toml
go 1.12
-require (
- github.com/BurntSushi/toml v0.3.1
- github.com/davecgh/go-spew v1.1.1
- gopkg.in/yaml.v2 v2.3.0
-)
+require github.com/davecgh/go-spew v1.1.1
diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go
index 425e847a..b1886192 100644
--- a/vendor/github.com/pelletier/go-toml/lexer.go
+++ b/vendor/github.com/pelletier/go-toml/lexer.go
@@ -306,7 +306,7 @@ func (l *tomlLexer) lexComma() tomlLexStateFn {
// Parse the key and emits its value without escape sequences.
// bare keys, basic string keys and literal string keys are supported.
func (l *tomlLexer) lexKey() tomlLexStateFn {
- growingString := ""
+ var sb strings.Builder
for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() {
if r == '"' {
@@ -315,7 +315,9 @@ func (l *tomlLexer) lexKey() tomlLexStateFn {
if err != nil {
return l.errorf(err.Error())
}
- growingString += "\"" + str + "\""
+ sb.WriteString("\"")
+ sb.WriteString(str)
+ sb.WriteString("\"")
l.next()
continue
} else if r == '\'' {
@@ -324,41 +326,45 @@ func (l *tomlLexer) lexKey() tomlLexStateFn {
if err != nil {
return l.errorf(err.Error())
}
- growingString += "'" + str + "'"
+ sb.WriteString("'")
+ sb.WriteString(str)
+ sb.WriteString("'")
l.next()
continue
} else if r == '\n' {
return l.errorf("keys cannot contain new lines")
} else if isSpace(r) {
- str := " "
+ var str strings.Builder
+ str.WriteString(" ")
+
// skip trailing whitespace
l.next()
for r = l.peek(); isSpace(r); r = l.peek() {
- str += string(r)
+ str.WriteRune(r)
l.next()
}
// break loop if not a dot
if r != '.' {
break
}
- str += "."
+ str.WriteString(".")
// skip trailing whitespace after dot
l.next()
for r = l.peek(); isSpace(r); r = l.peek() {
- str += string(r)
+ str.WriteRune(r)
l.next()
}
- growingString += str
+ sb.WriteString(str.String())
continue
} else if r == '.' {
// skip
} else if !isValidBareChar(r) {
return l.errorf("keys cannot contain %c character", r)
}
- growingString += string(r)
+ sb.WriteRune(r)
l.next()
}
- l.emitWithValue(tokenKey, growingString)
+ l.emitWithValue(tokenKey, sb.String())
return l.lexVoid
}
@@ -383,7 +389,7 @@ func (l *tomlLexer) lexLeftBracket() tomlLexStateFn {
}
func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) {
- growingString := ""
+ var sb strings.Builder
if discardLeadingNewLine {
if l.follow("\r\n") {
@@ -397,14 +403,14 @@ func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNe
// find end of string
for {
if l.follow(terminator) {
- return growingString, nil
+ return sb.String(), nil
}
next := l.peek()
if next == eof {
break
}
- growingString += string(l.next())
+ sb.WriteRune(l.next())
}
return "", errors.New("unclosed string")
@@ -438,7 +444,7 @@ func (l *tomlLexer) lexLiteralString() tomlLexStateFn {
// Terminator is the substring indicating the end of the token.
// The resulting string does not include the terminator.
func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) {
- growingString := ""
+ var sb strings.Builder
if discardLeadingNewLine {
if l.follow("\r\n") {
@@ -451,7 +457,7 @@ func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine,
for {
if l.follow(terminator) {
- return growingString, nil
+ return sb.String(), nil
}
if l.follow("\\") {
@@ -469,61 +475,61 @@ func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine,
l.next()
}
case '"':
- growingString += "\""
+ sb.WriteString("\"")
l.next()
case 'n':
- growingString += "\n"
+ sb.WriteString("\n")
l.next()
case 'b':
- growingString += "\b"
+ sb.WriteString("\b")
l.next()
case 'f':
- growingString += "\f"
+ sb.WriteString("\f")
l.next()
case '/':
- growingString += "/"
+ sb.WriteString("/")
l.next()
case 't':
- growingString += "\t"
+ sb.WriteString("\t")
l.next()
case 'r':
- growingString += "\r"
+ sb.WriteString("\r")
l.next()
case '\\':
- growingString += "\\"
+ sb.WriteString("\\")
l.next()
case 'u':
l.next()
- code := ""
+ var code strings.Builder
for i := 0; i < 4; i++ {
c := l.peek()
if !isHexDigit(c) {
return "", errors.New("unfinished unicode escape")
}
l.next()
- code = code + string(c)
+ code.WriteRune(c)
}
- intcode, err := strconv.ParseInt(code, 16, 32)
+ intcode, err := strconv.ParseInt(code.String(), 16, 32)
if err != nil {
- return "", errors.New("invalid unicode escape: \\u" + code)
+ return "", errors.New("invalid unicode escape: \\u" + code.String())
}
- growingString += string(rune(intcode))
+ sb.WriteRune(rune(intcode))
case 'U':
l.next()
- code := ""
+ var code strings.Builder
for i := 0; i < 8; i++ {
c := l.peek()
if !isHexDigit(c) {
return "", errors.New("unfinished unicode escape")
}
l.next()
- code = code + string(c)
+ code.WriteRune(c)
}
- intcode, err := strconv.ParseInt(code, 16, 64)
+ intcode, err := strconv.ParseInt(code.String(), 16, 64)
if err != nil {
- return "", errors.New("invalid unicode escape: \\U" + code)
+ return "", errors.New("invalid unicode escape: \\U" + code.String())
}
- growingString += string(rune(intcode))
+ sb.WriteRune(rune(intcode))
default:
return "", errors.New("invalid escape sequence: \\" + string(l.peek()))
}
@@ -534,7 +540,7 @@ func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine,
return "", fmt.Errorf("unescaped control character %U", r)
}
l.next()
- growingString += string(r)
+ sb.WriteRune(r)
}
if l.peek() == eof {
@@ -769,19 +775,19 @@ func init() {
// /!\ also matches the empty string
//
// Example matches:
- //1979-05-27T07:32:00Z
- //1979-05-27T00:32:00-07:00
- //1979-05-27T00:32:00.999999-07:00
- //1979-05-27 07:32:00Z
- //1979-05-27 00:32:00-07:00
- //1979-05-27 00:32:00.999999-07:00
- //1979-05-27T07:32:00
- //1979-05-27T00:32:00.999999
- //1979-05-27 07:32:00
- //1979-05-27 00:32:00.999999
- //1979-05-27
- //07:32:00
- //00:32:00.999999
+ // 1979-05-27T07:32:00Z
+ // 1979-05-27T00:32:00-07:00
+ // 1979-05-27T00:32:00.999999-07:00
+ // 1979-05-27 07:32:00Z
+ // 1979-05-27 00:32:00-07:00
+ // 1979-05-27 00:32:00.999999-07:00
+ // 1979-05-27T07:32:00
+ // 1979-05-27T00:32:00.999999
+ // 1979-05-27 07:32:00
+ // 1979-05-27 00:32:00.999999
+ // 1979-05-27
+ // 07:32:00
+ // 00:32:00.999999
dateRegexp = regexp.MustCompile(`^(?:\d{1,4}-\d{2}-\d{2})?(?:[T ]?\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})?)?`)
}
diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go
index db5a7b4f..032e0ffc 100644
--- a/vendor/github.com/pelletier/go-toml/marshal.go
+++ b/vendor/github.com/pelletier/go-toml/marshal.go
@@ -76,6 +76,7 @@ var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
var localDateType = reflect.TypeOf(LocalDate{})
var localTimeType = reflect.TypeOf(LocalTime{})
var localDateTimeType = reflect.TypeOf(LocalDateTime{})
+var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
// Check if the given marshal type maps to a Tree primitive
func isPrimitive(mtype reflect.Type) bool {
@@ -436,6 +437,7 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
if tree, ok := val.(*Tree); ok && mtypef.Anonymous && !opts.nameFromTag && !e.promoteAnon {
e.appendTree(tval, tree)
} else {
+ val = e.wrapTomlValue(val, tval)
tval.SetPathWithOptions([]string{opts.name}, SetOptions{
Comment: opts.comment,
Commented: opts.commented,
@@ -474,6 +476,7 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
if err != nil {
return nil, err
}
+ val = e.wrapTomlValue(val, tval)
if e.quoteMapKeys {
keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.order, e.arraysOneElementPerLine)
if err != nil {
@@ -516,13 +519,13 @@ func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (int
// Convert given marshal value to toml value
func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
- e.line++
if mtype.Kind() == reflect.Ptr {
switch {
case isCustomMarshaler(mtype):
return callCustomMarshaler(mval)
case isTextMarshaler(mtype):
- return callTextMarshaler(mval)
+ b, err := callTextMarshaler(mval)
+ return string(b), err
default:
return e.valueToToml(mtype.Elem(), mval.Elem())
}
@@ -534,7 +537,8 @@ func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface
case isCustomMarshaler(mtype):
return callCustomMarshaler(mval)
case isTextMarshaler(mtype):
- return callTextMarshaler(mval)
+ b, err := callTextMarshaler(mval)
+ return string(b), err
case isTree(mtype):
return e.valueToTree(mtype, mval)
case isOtherSequence(mtype), isCustomMarshalerSequence(mtype), isTextMarshalerSequence(mtype):
@@ -577,6 +581,25 @@ func (e *Encoder) appendTree(t, o *Tree) error {
return nil
}
+// Create a toml value with the current line number as the position line
+func (e *Encoder) wrapTomlValue(val interface{}, parent *Tree) interface{} {
+ _, isTree := val.(*Tree)
+ _, isTreeS := val.([]*Tree)
+ if isTree || isTreeS {
+ return val
+ }
+
+ ret := &tomlValue{
+ value: val,
+ position: Position{
+ e.line,
+ parent.position.Col,
+ },
+ }
+ e.line++
+ return ret
+}
+
// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
// sub-structs, and only definite types can be unmarshaled.
@@ -681,6 +704,8 @@ func (d *Decoder) unmarshal(v interface{}) error {
switch elem.Kind() {
case reflect.Struct, reflect.Map:
+ case reflect.Interface:
+ elem = mapStringInterfaceType
default:
return errors.New("only a pointer to struct or map can be unmarshaled from TOML")
}
@@ -717,6 +742,10 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V
if mvalPtr := reflect.New(mtype); isCustomUnmarshaler(mvalPtr.Type()) {
d.visitor.visitAll()
+ if tval == nil {
+ return mvalPtr.Elem(), nil
+ }
+
if err := callCustomUnmarshaler(mvalPtr, tval.ToMap()); err != nil {
return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err)
}
diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go
index d323c39b..cbb89a9a 100644
--- a/vendor/github.com/pelletier/go-toml/toml.go
+++ b/vendor/github.com/pelletier/go-toml/toml.go
@@ -122,6 +122,89 @@ func (t *Tree) GetPath(keys []string) interface{} {
}
}
+// GetArray returns the value at key in the Tree.
+// It returns []string, []int64, etc type if key has homogeneous lists
+// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings.
+// Returns nil if the path does not exist in the tree.
+// If keys is of length zero, the current tree is returned.
+func (t *Tree) GetArray(key string) interface{} {
+ if key == "" {
+ return t
+ }
+ return t.GetArrayPath(strings.Split(key, "."))
+}
+
+// GetArrayPath returns the element in the tree indicated by 'keys'.
+// If keys is of length zero, the current tree is returned.
+func (t *Tree) GetArrayPath(keys []string) interface{} {
+ if len(keys) == 0 {
+ return t
+ }
+ subtree := t
+ for _, intermediateKey := range keys[:len(keys)-1] {
+ value, exists := subtree.values[intermediateKey]
+ if !exists {
+ return nil
+ }
+ switch node := value.(type) {
+ case *Tree:
+ subtree = node
+ case []*Tree:
+ // go to most recent element
+ if len(node) == 0 {
+ return nil
+ }
+ subtree = node[len(node)-1]
+ default:
+ return nil // cannot navigate through other node types
+ }
+ }
+ // branch based on final node type
+ switch node := subtree.values[keys[len(keys)-1]].(type) {
+ case *tomlValue:
+ switch n := node.value.(type) {
+ case []interface{}:
+ return getArray(n)
+ default:
+ return node.value
+ }
+ default:
+ return node
+ }
+}
+
+// if homogeneous array, then return slice type object over []interface{}
+func getArray(n []interface{}) interface{} {
+ var s []string
+ var i64 []int64
+ var f64 []float64
+ var bl []bool
+ for _, value := range n {
+ switch v := value.(type) {
+ case string:
+ s = append(s, v)
+ case int64:
+ i64 = append(i64, v)
+ case float64:
+ f64 = append(f64, v)
+ case bool:
+ bl = append(bl, v)
+ default:
+ return n
+ }
+ }
+ if len(s) == len(n) {
+ return s
+ } else if len(i64) == len(n) {
+ return i64
+ } else if len(f64) == len(n) {
+ return f64
+ } else if len(bl) == len(n) {
+ return bl
+ }
+ return n
+}
+
// GetPosition returns the position of the given key.
func (t *Tree) GetPosition(key string) Position {
if key == "" {
@@ -130,6 +213,50 @@ func (t *Tree) GetPosition(key string) Position {
return t.GetPositionPath(strings.Split(key, "."))
}
+// SetPositionPath sets the position of element in the tree indicated by 'keys'.
+// If keys is of length zero, the current tree position is set.
+func (t *Tree) SetPositionPath(keys []string, pos Position) {
+ if len(keys) == 0 {
+ t.position = pos
+ return
+ }
+ subtree := t
+ for _, intermediateKey := range keys[:len(keys)-1] {
+ value, exists := subtree.values[intermediateKey]
+ if !exists {
+ return
+ }
+ switch node := value.(type) {
+ case *Tree:
+ subtree = node
+ case []*Tree:
+ // go to most recent element
+ if len(node) == 0 {
+ return
+ }
+ subtree = node[len(node)-1]
+ default:
+ return
+ }
+ }
+ // branch based on final node type
+ switch node := subtree.values[keys[len(keys)-1]].(type) {
+ case *tomlValue:
+ node.position = pos
+ return
+ case *Tree:
+ node.position = pos
+ return
+ case []*Tree:
+ // go to most recent element
+ if len(node) == 0 {
+ return
+ }
+ node[len(node)-1].position = pos
+ return
+ }
+}
+
// GetPositionPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned.
func (t *Tree) GetPositionPath(keys []string) Position {
@@ -212,7 +339,8 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac
// go to most recent element
if len(node) == 0 {
// create element if it does not exist
- subtree.values[intermediateKey] = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
+ node = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
+ subtree.values[intermediateKey] = node
}
subtree = node[len(node)-1]
}
@@ -232,6 +360,8 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac
toInsert = value
case *tomlValue:
v.comment = opts.Comment
+ v.commented = opts.Commented
+ v.multiline = opts.Multiline
toInsert = v
default:
toInsert = &tomlValue{value: value,
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go
index 79610e9b..80353500 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_create.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go
@@ -57,6 +57,19 @@ func simpleValueCoercion(object interface{}) (interface{}, error) {
return float64(original), nil
case fmt.Stringer:
return original.String(), nil
+ case []interface{}:
+ value := reflect.ValueOf(original)
+ length := value.Len()
+ arrayValue := reflect.MakeSlice(value.Type(), 0, length)
+ for i := 0; i < length; i++ {
+ val := value.Index(i).Interface()
+ simpleValue, err := simpleValueCoercion(val)
+ if err != nil {
+ return nil, err
+ }
+ arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
+ }
+ return arrayValue.Interface(), nil
default:
return nil, fmt.Errorf("cannot convert type %T to Tree", object)
}
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go
index 2d6487ed..ae6dac49 100644
--- a/vendor/github.com/pelletier/go-toml/tomltree_write.go
+++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go
@@ -163,7 +163,7 @@ func tomlValueStringRepresentation(v interface{}, commented string, indent strin
return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
b, _ := v.([]byte)
- return tomlValueStringRepresentation(string(b), commented, indent, ord, arraysOneElementPerLine)
+ return string(b), nil
case bool:
if value {
return "true", nil
diff --git a/vendor/github.com/slack-go/slack/.golangci.yml b/vendor/github.com/slack-go/slack/.golangci.yml
new file mode 100644
index 00000000..c16f5389
--- /dev/null
+++ b/vendor/github.com/slack-go/slack/.golangci.yml
@@ -0,0 +1,14 @@
+run:
+ timeout: 6m
+ issues-exit-code: 1
+linters:
+ disable-all: true
+ enable:
+ - goimports
+ - govet
+ - interfacer
+ - misspell
+ - structcheck
+ - unconvert
+issues:
+ new: true
diff --git a/vendor/github.com/slack-go/slack/.travis.yml b/vendor/github.com/slack-go/slack/.travis.yml
deleted file mode 100644
index f2019d72..00000000
--- a/vendor/github.com/slack-go/slack/.travis.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-language: go
-
-env:
- - GO111MODULE=on
-
-install: true
-
-before_install:
- - export PATH=$HOME/gopath/bin:$PATH
- # install gometalinter
- - curl -L https://git.io/vp6lP | sh
-
-script:
- - PATH=$PWD/bin:$PATH gometalinter ./...
- - go test -race -cover ./...
-
-matrix:
- allow_failures:
- - go: tip
- include:
- - go: "1.7.x"
- script: go test -v ./...
- - go: "1.8.x"
- script: go test -v ./...
- - go: "1.9.x"
- script: go test -v ./...
- - go: "1.10.x"
- script: go test -v ./...
- - go: "1.11.x"
- script: go test -v -mod=vendor ./...
- - go: "1.12.x"
- script: go test -v -mod=vendor ./...
- - go: "1.13.x"
- script: go test -v -mod=vendor ./...
- - go: "1.14.x"
- script: go test -v -mod=vendor ./...
- - go: "tip"
- script: go test -v -mod=vendor ./...
-
-git:
- depth: 10
diff --git a/vendor/github.com/slack-go/slack/attachments.go b/vendor/github.com/slack-go/slack/attachments.go
index 5f388e9f..b5b79f9f 100644
--- a/vendor/github.com/slack-go/slack/attachments.go
+++ b/vendor/github.com/slack-go/slack/attachments.go
@@ -75,7 +75,7 @@ type Attachment struct {
Title string `json:"title,omitempty"`
TitleLink string `json:"title_link,omitempty"`
Pretext string `json:"pretext,omitempty"`
- Text string `json:"text"` // Required
+ Text string `json:"text,omitempty"`
ImageURL string `json:"image_url,omitempty"`
ThumbURL string `json:"thumb_url,omitempty"`
diff --git a/vendor/github.com/slack-go/slack/block_action.go b/vendor/github.com/slack-go/slack/block_action.go
index fe46a95c..c15e4a3f 100644
--- a/vendor/github.com/slack-go/slack/block_action.go
+++ b/vendor/github.com/slack-go/slack/block_action.go
@@ -6,7 +6,7 @@ package slack
type ActionBlock struct {
Type MessageBlockType `json:"type"`
BlockID string `json:"block_id,omitempty"`
- Elements BlockElements `json:"elements"`
+ Elements *BlockElements `json:"elements"`
}
// BlockType returns the type of the block
@@ -19,7 +19,7 @@ func NewActionBlock(blockID string, elements ...BlockElement) *ActionBlock {
return &ActionBlock{
Type: MBTAction,
BlockID: blockID,
- Elements: BlockElements{
+ Elements: &BlockElements{
ElementSet: elements,
},
}
diff --git a/vendor/github.com/slack-go/slack/channels.go b/vendor/github.com/slack-go/slack/channels.go
index a90d2384..c05521d0 100644
--- a/vendor/github.com/slack-go/slack/channels.go
+++ b/vendor/github.com/slack-go/slack/channels.go
@@ -19,6 +19,12 @@ type channelResponseFull struct {
}
// Channel contains information about the channel
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type Channel struct {
GroupConversation
IsChannel bool `json:"is_channel"`
@@ -38,9 +44,21 @@ func (api *Client) channelRequest(ctx context.Context, path string, values url.V
}
// GetChannelsOption option provided when getting channels.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type GetChannelsOption func(*ChannelPagination) error
// GetChannelsOptionExcludeMembers excludes the members collection from each channel.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func GetChannelsOptionExcludeMembers() GetChannelsOption {
return func(p *ChannelPagination) error {
p.excludeMembers = true
@@ -49,6 +67,12 @@ func GetChannelsOptionExcludeMembers() GetChannelsOption {
}
// GetChannelsOptionExcludeArchived excludes archived channels from results.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func GetChannelsOptionExcludeArchived() GetChannelsOption {
return func(p *ChannelPagination) error {
p.excludeArchived = true
@@ -58,12 +82,24 @@ func GetChannelsOptionExcludeArchived() GetChannelsOption {
// ArchiveChannel archives the given channel
// see https://api.slack.com/methods/channels.archive
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveChannel(channelID string) error {
return api.ArchiveChannelContext(context.Background(), channelID)
}
// ArchiveChannelContext archives the given channel with a custom context
// see https://api.slack.com/methods/channels.archive
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string) (err error) {
values := url.Values{
"token": {api.token},
@@ -76,12 +112,24 @@ func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string)
// UnarchiveChannel unarchives the given channel
// see https://api.slack.com/methods/channels.unarchive
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveChannel(channelID string) error {
return api.UnarchiveChannelContext(context.Background(), channelID)
}
// UnarchiveChannelContext unarchives the given channel with a custom context
// see https://api.slack.com/methods/channels.unarchive
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string) (err error) {
values := url.Values{
"token": {api.token},
@@ -94,12 +142,24 @@ func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string
// CreateChannel creates a channel with the given name and returns a *Channel
// see https://api.slack.com/methods/channels.create
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChannel(channelName string) (*Channel, error) {
return api.CreateChannelContext(context.Background(), channelName)
}
// CreateChannelContext creates a channel with the given name and returns a *Channel with a custom context
// see https://api.slack.com/methods/channels.create
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChannelContext(ctx context.Context, channelName string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -115,12 +175,24 @@ func (api *Client) CreateChannelContext(ctx context.Context, channelName string)
// GetChannelHistory retrieves the channel history
// see https://api.slack.com/methods/channels.history
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelHistory(channelID string, params HistoryParameters) (*History, error) {
return api.GetChannelHistoryContext(context.Background(), channelID, params)
}
// GetChannelHistoryContext retrieves the channel history with a custom context
// see https://api.slack.com/methods/channels.history
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
@@ -160,12 +232,24 @@ func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID strin
// GetChannelInfo retrieves the given channel
// see https://api.slack.com/methods/channels.info
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelInfo(channelID string) (*Channel, error) {
return api.GetChannelInfoContext(context.Background(), channelID)
}
// GetChannelInfoContext retrieves the given channel with a custom context
// see https://api.slack.com/methods/channels.info
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -182,12 +266,24 @@ func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string)
// InviteUserToChannel invites a user to a given channel and returns a *Channel
// see https://api.slack.com/methods/channels.invite
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToChannel(channelID, user string) (*Channel, error) {
return api.InviteUserToChannelContext(context.Background(), channelID, user)
}
// InviteUserToChannelContext invites a user to a given channel and returns a *Channel with a custom context
// see https://api.slack.com/methods/channels.invite
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -204,12 +300,24 @@ func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, us
// JoinChannel joins the currently authenticated user to a channel
// see https://api.slack.com/methods/channels.join
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) JoinChannel(channelName string) (*Channel, error) {
return api.JoinChannelContext(context.Background(), channelName)
}
// JoinChannelContext joins the currently authenticated user to a channel with a custom context
// see https://api.slack.com/methods/channels.join
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -225,12 +333,24 @@ func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (
// LeaveChannel makes the authenticated user leave the given channel
// see https://api.slack.com/methods/channels.leave
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveChannel(channelID string) (bool, error) {
return api.LeaveChannelContext(context.Background(), channelID)
}
// LeaveChannelContext makes the authenticated user leave the given channel with a custom context
// see https://api.slack.com/methods/channels.leave
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (bool, error) {
values := url.Values{
"token": {api.token},
@@ -247,12 +367,24 @@ func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (b
// KickUserFromChannel kicks a user from a given channel
// see https://api.slack.com/methods/channels.kick
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromChannel(channelID, user string) error {
return api.KickUserFromChannelContext(context.Background(), channelID, user)
}
// KickUserFromChannelContext kicks a user from a given channel with a custom context
// see https://api.slack.com/methods/channels.kick
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, user string) (err error) {
values := url.Values{
"token": {api.token},
@@ -278,6 +410,12 @@ func newChannelPagination(c *Client, options ...GetChannelsOption) (cp ChannelPa
}
// ChannelPagination allows for paginating over the channels
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type ChannelPagination struct {
Channels []Channel
limit int
@@ -288,11 +426,23 @@ type ChannelPagination struct {
}
// Done checks if the pagination has completed
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (ChannelPagination) Done(err error) bool {
return err == errPaginationComplete
}
// Failure checks if pagination failed.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (t ChannelPagination) Failure(err error) error {
if t.Done(err) {
return nil
@@ -301,6 +451,11 @@ func (t ChannelPagination) Failure(err error) error {
return err
}
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (t ChannelPagination) Next(ctx context.Context) (_ ChannelPagination, err error) {
var (
resp *channelResponseFull
@@ -332,18 +487,36 @@ func (t ChannelPagination) Next(ctx context.Context) (_ ChannelPagination, err e
}
// GetChannelsPaginated fetches channels in a paginated fashion, see GetChannelsContext for usage.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelsPaginated(options ...GetChannelsOption) ChannelPagination {
return newChannelPagination(api, options...)
}
// GetChannels retrieves all the channels
// see https://api.slack.com/methods/channels.list
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
return api.GetChannelsContext(context.Background(), excludeArchived, options...)
}
// GetChannelsContext retrieves all the channels with a custom context
// see https://api.slack.com/methods/channels.list
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) (results []Channel, err error) {
if excludeArchived {
options = append(options, GetChannelsOptionExcludeArchived())
@@ -373,6 +546,12 @@ func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool,
// (just one per channel). This is useful for when reading scroll-back history, or following a busy live channel. A
// timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout.
// see https://api.slack.com/methods/channels.mark
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelReadMark(channelID, ts string) error {
return api.SetChannelReadMarkContext(context.Background(), channelID, ts)
}
@@ -380,6 +559,12 @@ func (api *Client) SetChannelReadMark(channelID, ts string) error {
// SetChannelReadMarkContext sets the read mark of a given channel to a specific point with a custom context
// For more details see SetChannelReadMark documentation
// see https://api.slack.com/methods/channels.mark
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts string) (err error) {
values := url.Values{
"token": {api.token},
@@ -393,12 +578,24 @@ func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts
// RenameChannel renames a given channel
// see https://api.slack.com/methods/channels.rename
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameChannel(channelID, name string) (*Channel, error) {
return api.RenameChannelContext(context.Background(), channelID, name)
}
// RenameChannelContext renames a given channel with a custom context
// see https://api.slack.com/methods/channels.rename
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameChannelContext(ctx context.Context, channelID, name string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -417,12 +614,24 @@ func (api *Client) RenameChannelContext(ctx context.Context, channelID, name str
// SetChannelPurpose sets the channel purpose and returns the purpose that was successfully set
// see https://api.slack.com/methods/channels.setPurpose
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelPurpose(channelID, purpose string) (string, error) {
return api.SetChannelPurposeContext(context.Background(), channelID, purpose)
}
// SetChannelPurposeContext sets the channel purpose and returns the purpose that was successfully set with a custom context
// see https://api.slack.com/methods/channels.setPurpose
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purpose string) (string, error) {
values := url.Values{
"token": {api.token},
@@ -439,12 +648,24 @@ func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purp
// SetChannelTopic sets the channel topic and returns the topic that was successfully set
// see https://api.slack.com/methods/channels.setTopic
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelTopic(channelID, topic string) (string, error) {
return api.SetChannelTopicContext(context.Background(), channelID, topic)
}
// SetChannelTopicContext sets the channel topic and returns the topic that was successfully set with a custom context
// see https://api.slack.com/methods/channels.setTopic
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic string) (string, error) {
values := url.Values{
"token": {api.token},
@@ -461,12 +682,24 @@ func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic
// GetChannelReplies gets an entire thread (a message plus all the messages in reply to it).
// see https://api.slack.com/methods/channels.replies
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelReplies(channelID, thread_ts string) ([]Message, error) {
return api.GetChannelRepliesContext(context.Background(), channelID, thread_ts)
}
// GetChannelRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context
// see https://api.slack.com/methods/channels.replies
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) {
values := url.Values{
"token": {api.token},
diff --git a/vendor/github.com/slack-go/slack/conversation.go b/vendor/github.com/slack-go/slack/conversation.go
index 60c50fc7..6fc4a083 100644
--- a/vendor/github.com/slack-go/slack/conversation.go
+++ b/vendor/github.com/slack-go/slack/conversation.go
@@ -621,3 +621,25 @@ func (api *Client) GetConversationHistoryContext(ctx context.Context, params *Ge
return &response, response.Err()
}
+
+// MarkConversation sets the read mark of a conversation to a specific point
+func (api *Client) MarkConversation(channel, ts string) (err error) {
+ return api.MarkConversationContext(context.Background(), channel, ts)
+}
+
+// MarkConversationContext sets the read mark of a conversation to a specific point with a custom context
+func (api *Client) MarkConversationContext(ctx context.Context, channel, ts string) error {
+ values := url.Values{
+ "token": {api.token},
+ "channel": {channel},
+ "ts": {ts},
+ }
+
+ response := &SlackResponse{}
+
+ err := api.postMethod(ctx, "conversations.mark", values, response)
+ if err != nil {
+ return err
+ }
+ return response.Err()
+}
diff --git a/vendor/github.com/slack-go/slack/files.go b/vendor/github.com/slack-go/slack/files.go
index 3a7363de..713038f0 100644
--- a/vendor/github.com/slack-go/slack/files.go
+++ b/vendor/github.com/slack-go/slack/files.go
@@ -11,13 +11,14 @@ import (
const (
// Add here the defaults in the siten
- DEFAULT_FILES_USER = ""
- DEFAULT_FILES_CHANNEL = ""
- DEFAULT_FILES_TS_FROM = 0
- DEFAULT_FILES_TS_TO = -1
- DEFAULT_FILES_TYPES = "all"
- DEFAULT_FILES_COUNT = 100
- DEFAULT_FILES_PAGE = 1
+ DEFAULT_FILES_USER = ""
+ DEFAULT_FILES_CHANNEL = ""
+ DEFAULT_FILES_TS_FROM = 0
+ DEFAULT_FILES_TS_TO = -1
+ DEFAULT_FILES_TYPES = "all"
+ DEFAULT_FILES_COUNT = 100
+ DEFAULT_FILES_PAGE = 1
+ DEFAULT_FILES_SHOW_HIDDEN = false
)
// File contains all the information for a file
@@ -132,6 +133,7 @@ type GetFilesParameters struct {
Types string
Count int
Page int
+ ShowHidden bool
}
// ListFilesParameters contains all the parameters necessary (including the optional ones) for a ListFiles() request
@@ -163,6 +165,7 @@ func NewGetFilesParameters() GetFilesParameters {
Types: DEFAULT_FILES_TYPES,
Count: DEFAULT_FILES_COUNT,
Page: DEFAULT_FILES_PAGE,
+ ShowHidden: DEFAULT_FILES_SHOW_HIDDEN,
}
}
@@ -267,6 +270,9 @@ func (api *Client) GetFilesContext(ctx context.Context, params GetFilesParameter
if params.Page != DEFAULT_FILES_PAGE {
values.Add("page", strconv.Itoa(params.Page))
}
+ if params.ShowHidden != DEFAULT_FILES_SHOW_HIDDEN {
+ values.Add("show_files_hidden_by_limit", strconv.FormatBool(params.ShowHidden))
+ }
response, err := api.fileRequest(ctx, "files.list", values)
if err != nil {
diff --git a/vendor/github.com/slack-go/slack/groups.go b/vendor/github.com/slack-go/slack/groups.go
index 6ea1b134..4c5793dc 100644
--- a/vendor/github.com/slack-go/slack/groups.go
+++ b/vendor/github.com/slack-go/slack/groups.go
@@ -7,6 +7,12 @@ import (
)
// Group contains all the information for a group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type Group struct {
GroupConversation
IsGroup bool `json:"is_group"`
@@ -38,11 +44,23 @@ func (api *Client) groupRequest(ctx context.Context, path string, values url.Val
}
// ArchiveGroup archives a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveGroup(group string) error {
return api.ArchiveGroupContext(context.Background(), group)
}
// ArchiveGroupContext archives a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveGroupContext(ctx context.Context, group string) error {
values := url.Values{
"token": {api.token},
@@ -54,11 +72,23 @@ func (api *Client) ArchiveGroupContext(ctx context.Context, group string) error
}
// UnarchiveGroup unarchives a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveGroup(group string) error {
return api.UnarchiveGroupContext(context.Background(), group)
}
// UnarchiveGroupContext unarchives a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveGroupContext(ctx context.Context, group string) error {
values := url.Values{
"token": {api.token},
@@ -70,11 +100,23 @@ func (api *Client) UnarchiveGroupContext(ctx context.Context, group string) erro
}
// CreateGroup creates a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateGroup(group string) (*Group, error) {
return api.CreateGroupContext(context.Background(), group)
}
// CreateGroupContext creates a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateGroupContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
@@ -94,12 +136,24 @@ func (api *Client) CreateGroupContext(ctx context.Context, group string) (*Group
// 2. Archives the existing group.
// 3. Creates a new group with the name of the existing group.
// 4. Adds all members of the existing group to the new group.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChildGroup(group string) (*Group, error) {
return api.CreateChildGroupContext(context.Background(), group)
}
// CreateChildGroupContext creates a new private group archiving the old one with a custom context
// For more information see CreateChildGroup
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChildGroupContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
@@ -114,11 +168,23 @@ func (api *Client) CreateChildGroupContext(ctx context.Context, group string) (*
}
// GetGroupHistory fetches all the history for a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupHistory(group string, params HistoryParameters) (*History, error) {
return api.GetGroupHistoryContext(context.Background(), group, params)
}
// GetGroupHistoryContext fetches all the history for a private group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupHistoryContext(ctx context.Context, group string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
@@ -156,11 +222,23 @@ func (api *Client) GetGroupHistoryContext(ctx context.Context, group string, par
}
// InviteUserToGroup invites a specific user to a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToGroup(group, user string) (*Group, bool, error) {
return api.InviteUserToGroupContext(context.Background(), group, user)
}
// InviteUserToGroupContext invites a specific user to a private group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToGroupContext(ctx context.Context, group, user string) (*Group, bool, error) {
values := url.Values{
"token": {api.token},
@@ -176,11 +254,23 @@ func (api *Client) InviteUserToGroupContext(ctx context.Context, group, user str
}
// LeaveGroup makes authenticated user leave the group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveGroup(group string) error {
return api.LeaveGroupContext(context.Background(), group)
}
// LeaveGroupContext makes authenticated user leave the group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveGroupContext(ctx context.Context, group string) (err error) {
values := url.Values{
"token": {api.token},
@@ -192,11 +282,23 @@ func (api *Client) LeaveGroupContext(ctx context.Context, group string) (err err
}
// KickUserFromGroup kicks a user from a group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromGroup(group, user string) error {
return api.KickUserFromGroupContext(context.Background(), group, user)
}
// KickUserFromGroupContext kicks a user from a group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user string) (err error) {
values := url.Values{
"token": {api.token},
@@ -209,11 +311,23 @@ func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user str
}
// GetGroups retrieves all groups
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroups(excludeArchived bool) ([]Group, error) {
return api.GetGroupsContext(context.Background(), excludeArchived)
}
// GetGroupsContext retrieves all groups with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupsContext(ctx context.Context, excludeArchived bool) ([]Group, error) {
values := url.Values{
"token": {api.token},
@@ -230,11 +344,23 @@ func (api *Client) GetGroupsContext(ctx context.Context, excludeArchived bool) (
}
// GetGroupInfo retrieves the given group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupInfo(group string) (*Group, error) {
return api.GetGroupInfoContext(context.Background(), group)
}
// GetGroupInfoContext retrieves the given group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupInfoContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
@@ -254,12 +380,24 @@ func (api *Client) GetGroupInfoContext(ctx context.Context, group string) (*Grou
// timer before making the call. In this way, any further updates needed during the timeout will not generate extra
// calls (just one per channel). This is useful for when reading scroll-back history, or following a busy live
// channel. A timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupReadMark(group, ts string) error {
return api.SetGroupReadMarkContext(context.Background(), group, ts)
}
// SetGroupReadMarkContext sets the read mark on a private group with a custom context
// For more details see SetGroupReadMark
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string) (err error) {
values := url.Values{
"token": {api.token},
@@ -272,11 +410,23 @@ func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string
}
// OpenGroup opens a private group
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenGroup(group string) (bool, bool, error) {
return api.OpenGroupContext(context.Background(), group)
}
// OpenGroupContext opens a private group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenGroupContext(ctx context.Context, group string) (bool, bool, error) {
values := url.Values{
"token": {api.token},
@@ -293,11 +443,23 @@ func (api *Client) OpenGroupContext(ctx context.Context, group string) (bool, bo
// RenameGroup renames a group
// XXX: They return a channel, not a group. What is this crap? :(
// Inconsistent api it seems.
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameGroup(group, name string) (*Channel, error) {
return api.RenameGroupContext(context.Background(), group, name)
}
// RenameGroupContext renames a group with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameGroupContext(ctx context.Context, group, name string) (*Channel, error) {
values := url.Values{
"token": {api.token},
@@ -315,11 +477,23 @@ func (api *Client) RenameGroupContext(ctx context.Context, group, name string) (
}
// SetGroupPurpose sets the group purpose
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupPurpose(group, purpose string) (string, error) {
return api.SetGroupPurposeContext(context.Background(), group, purpose)
}
// SetGroupPurposeContext sets the group purpose with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupPurposeContext(ctx context.Context, group, purpose string) (string, error) {
values := url.Values{
"token": {api.token},
@@ -335,11 +509,23 @@ func (api *Client) SetGroupPurposeContext(ctx context.Context, group, purpose st
}
// SetGroupTopic sets the group topic
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupTopic(group, topic string) (string, error) {
return api.SetGroupTopicContext(context.Background(), group, topic)
}
// SetGroupTopicContext sets the group topic with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupTopicContext(ctx context.Context, group, topic string) (string, error) {
values := url.Values{
"token": {api.token},
@@ -356,12 +542,24 @@ func (api *Client) SetGroupTopicContext(ctx context.Context, group, topic string
// GetGroupReplies gets an entire thread (a message plus all the messages in reply to it).
// see https://api.slack.com/methods/groups.replies
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupReplies(channelID, thread_ts string) ([]Message, error) {
return api.GetGroupRepliesContext(context.Background(), channelID, thread_ts)
}
// GetGroupRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context
// see https://api.slack.com/methods/groups.replies
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) {
values := url.Values{
"token": {api.token},
diff --git a/vendor/github.com/slack-go/slack/im.go b/vendor/github.com/slack-go/slack/im.go
index ee784fef..a884b295 100644
--- a/vendor/github.com/slack-go/slack/im.go
+++ b/vendor/github.com/slack-go/slack/im.go
@@ -21,6 +21,12 @@ type imResponseFull struct {
}
// IM contains information related to the Direct Message channel
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type IM struct {
Conversation
IsUserDeleted bool `json:"is_user_deleted"`
@@ -37,11 +43,23 @@ func (api *Client) imRequest(ctx context.Context, path string, values url.Values
}
// CloseIMChannel closes the direct message channel
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CloseIMChannel(channel string) (bool, bool, error) {
return api.CloseIMChannelContext(context.Background(), channel)
}
// CloseIMChannelContext closes the direct message channel with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (bool, bool, error) {
values := url.Values{
"token": {api.token},
@@ -57,12 +75,24 @@ func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (b
// OpenIMChannel opens a direct message channel to the user provided as argument
// Returns some status and the channel ID
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenIMChannel(user string) (bool, bool, string, error) {
return api.OpenIMChannelContext(context.Background(), user)
}
// OpenIMChannelContext opens a direct message channel to the user provided as argument with a custom context
// Returns some status and the channel ID
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenIMChannelContext(ctx context.Context, user string) (bool, bool, string, error) {
values := url.Values{
"token": {api.token},
@@ -77,11 +107,23 @@ func (api *Client) OpenIMChannelContext(ctx context.Context, user string) (bool,
}
// MarkIMChannel sets the read mark of a direct message channel to a specific point
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) MarkIMChannel(channel, ts string) (err error) {
return api.MarkIMChannelContext(context.Background(), channel, ts)
}
// MarkIMChannelContext sets the read mark of a direct message channel to a specific point with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string) error {
values := url.Values{
"token": {api.token},
@@ -94,11 +136,23 @@ func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string)
}
// GetIMHistory retrieves the direct message channel history
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMHistory(channel string, params HistoryParameters) (*History, error) {
return api.GetIMHistoryContext(context.Background(), channel, params)
}
// GetIMHistoryContext retrieves the direct message channel history with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMHistoryContext(ctx context.Context, channel string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
@@ -136,11 +190,23 @@ func (api *Client) GetIMHistoryContext(ctx context.Context, channel string, para
}
// GetIMChannels returns the list of direct message channels
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMChannels() ([]IM, error) {
return api.GetIMChannelsContext(context.Background())
}
// GetIMChannelsContext returns the list of direct message channels with a custom context
+//
+// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
+// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
+// Also, existing applications will not be able to use these APIs after February 24th, 2021.
+//
+// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMChannelsContext(ctx context.Context) ([]IM, error) {
values := url.Values{
"token": {api.token},
diff --git a/vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go b/vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go
index cb850577..0182ec68 100644
--- a/vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go
+++ b/vendor/github.com/slack-go/slack/internal/errorsx/errorsx.go
@@ -6,3 +6,12 @@ type String string
func (t String) Error() string {
return string(t)
}
+
+// Is reports whether String matches with the target error
+func (t String) Is(target error) bool {
+ if target == nil {
+ return false
+ }
+
+ return t.Error() == target.Error()
+}
diff --git a/vendor/github.com/slack-go/slack/logger.go b/vendor/github.com/slack-go/slack/logger.go
index 6a3533a9..90cb3caa 100644
--- a/vendor/github.com/slack-go/slack/logger.go
+++ b/vendor/github.com/slack-go/slack/logger.go
@@ -18,7 +18,7 @@ type ilogger interface {
Println(...interface{})
}
-type debug interface {
+type Debug interface {
Debug() bool
// Debugf print a formatted debug line.
diff --git a/vendor/github.com/slack-go/slack/misc.go b/vendor/github.com/slack-go/slack/misc.go
index a5ca51bc..336f0afb 100644
--- a/vendor/github.com/slack-go/slack/misc.go
+++ b/vendor/github.com/slack-go/slack/misc.go
@@ -88,7 +88,7 @@ func fileUploadReq(ctx context.Context, path string, values url.Values, r io.Rea
return req, nil
}
-func downloadFile(client httpClient, token string, downloadURL string, writer io.Writer, d debug) error {
+func downloadFile(client httpClient, token string, downloadURL string, writer io.Writer, d Debug) error {
if downloadURL == "" {
return fmt.Errorf("received empty download URL")
}
@@ -142,7 +142,7 @@ func jsonReq(endpoint string, body interface{}) (req *http.Request, err error) {
return req, nil
}
-func parseResponseBody(body io.ReadCloser, intf interface{}, d debug) error {
+func parseResponseBody(body io.ReadCloser, intf interface{}, d Debug) error {
response, err := ioutil.ReadAll(body)
if err != nil {
return err
@@ -155,7 +155,7 @@ func parseResponseBody(body io.ReadCloser, intf interface{}, d debug) error {
return json.Unmarshal(response, intf)
}
-func postLocalWithMultipartResponse(ctx context.Context, client httpClient, method, fpath, fieldname string, values url.Values, intf interface{}, d debug) error {
+func postLocalWithMultipartResponse(ctx context.Context, client httpClient, method, fpath, fieldname string, values url.Values, intf interface{}, d Debug) error {
fullpath, err := filepath.Abs(fpath)
if err != nil {
return err
@@ -169,7 +169,7 @@ func postLocalWithMultipartResponse(ctx context.Context, client httpClient, meth
return postWithMultipartResponse(ctx, client, method, filepath.Base(fpath), fieldname, values, file, intf, d)
}
-func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, d debug) error {
+func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, d Debug) error {
pipeReader, pipeWriter := io.Pipe()
wr := multipart.NewWriter(pipeWriter)
errc := make(chan error)
@@ -216,7 +216,7 @@ func postWithMultipartResponse(ctx context.Context, client httpClient, path, nam
}
}
-func doPost(ctx context.Context, client httpClient, req *http.Request, parser responseParser, d debug) error {
+func doPost(ctx context.Context, client httpClient, req *http.Request, parser responseParser, d Debug) error {
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
@@ -233,7 +233,7 @@ func doPost(ctx context.Context, client httpClient, req *http.Request, parser re
}
// post JSON.
-func postJSON(ctx context.Context, client httpClient, endpoint, token string, json []byte, intf interface{}, d debug) error {
+func postJSON(ctx context.Context, client httpClient, endpoint, token string, json []byte, intf interface{}, d Debug) error {
reqBody := bytes.NewBuffer(json)
req, err := http.NewRequest("POST", endpoint, reqBody)
if err != nil {
@@ -246,7 +246,7 @@ func postJSON(ctx context.Context, client httpClient, endpoint, token string, js
}
// post a url encoded form.
-func postForm(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d debug) error {
+func postForm(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d Debug) error {
reqBody := strings.NewReader(values.Encode())
req, err := http.NewRequest("POST", endpoint, reqBody)
if err != nil {
@@ -256,7 +256,7 @@ func postForm(ctx context.Context, client httpClient, endpoint string, values ur
return doPost(ctx, client, req, newJSONParser(intf), d)
}
-func getResource(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d debug) error {
+func getResource(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d Debug) error {
req, err := http.NewRequest("GET", endpoint, nil)
if err != nil {
return err
@@ -267,12 +267,12 @@ func getResource(ctx context.Context, client httpClient, endpoint string, values
return doPost(ctx, client, req, newJSONParser(intf), d)
}
-func parseAdminResponse(ctx context.Context, client httpClient, method string, teamName string, values url.Values, intf interface{}, d debug) error {
+func parseAdminResponse(ctx context.Context, client httpClient, method string, teamName string, values url.Values, intf interface{}, d Debug) error {
endpoint := fmt.Sprintf(WEBAPIURLFormat, teamName, method, time.Now().Unix())
return postForm(ctx, client, endpoint, values, intf, d)
}
-func logResponse(resp *http.Response, d debug) error {
+func logResponse(resp *http.Response, d Debug) error {
if d.Debug() {
text, err := httputil.DumpResponse(resp, true)
if err != nil {
@@ -300,7 +300,7 @@ func timerReset(t *time.Timer, d time.Duration) {
t.Reset(d)
}
-func checkStatusCode(resp *http.Response, d debug) error {
+func checkStatusCode(resp *http.Response, d Debug) error {
if resp.StatusCode == http.StatusTooManyRequests {
retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64)
if err != nil {
diff --git a/vendor/github.com/slack-go/slack/reminders.go b/vendor/github.com/slack-go/slack/reminders.go
index de1170a6..f312af3f 100644
--- a/vendor/github.com/slack-go/slack/reminders.go
+++ b/vendor/github.com/slack-go/slack/reminders.go
@@ -3,17 +3,16 @@ package slack
import (
"context"
"net/url"
- "time"
)
type Reminder struct {
- ID string `json:"id"`
- Creator string `json:"creator"`
- User string `json:"user"`
- Text string `json:"text"`
- Recurring bool `json:"recurring"`
- Time time.Time `json:"time"`
- CompleteTS int `json:"complete_ts"`
+ ID string `json:"id"`
+ Creator string `json:"creator"`
+ User string `json:"user"`
+ Text string `json:"text"`
+ Recurring bool `json:"recurring"`
+ Time int `json:"time"`
+ CompleteTS int `json:"complete_ts"`
}
type reminderResp struct {
diff --git a/vendor/github.com/slack-go/slack/security.go b/vendor/github.com/slack-go/slack/security.go
index dbe8fb2d..45103529 100644
--- a/vendor/github.com/slack-go/slack/security.go
+++ b/vendor/github.com/slack-go/slack/security.go
@@ -20,6 +20,7 @@ const (
// SecretsVerifier contains the information needed to verify that the request comes from Slack
type SecretsVerifier struct {
+ d Debug
signature []byte
hmac hash.Hash
}
@@ -75,6 +76,11 @@ func NewSecretsVerifier(header http.Header, secret string) (sv SecretsVerifier,
return sv, err
}
+func (v *SecretsVerifier) WithDebug(d Debug) *SecretsVerifier {
+ v.d = d
+ return v
+}
+
func (v *SecretsVerifier) Write(body []byte) (n int, err error) {
return v.hmac.Write(body)
}
@@ -86,8 +92,10 @@ func (v SecretsVerifier) Ensure() error {
if hmac.Equal(computed, v.signature) {
return nil
}
-
- return fmt.Errorf("Expected signing signature: %s, but computed: %s", hex.EncodeToString(v.signature), hex.EncodeToString(computed))
+ if v.d != nil && v.d.Debug() {
+ v.d.Debugln(fmt.Sprintf("Expected signing signature: %s, but computed: %s", hex.EncodeToString(v.signature), hex.EncodeToString(computed)))
+ }
+ return fmt.Errorf("Computed unexpected signature of: %s", hex.EncodeToString(computed))
}
func abs64(n int64) int64 {
diff --git a/vendor/github.com/slack-go/slack/users.go b/vendor/github.com/slack-go/slack/users.go
index cdef4242..c2ee8713 100644
--- a/vendor/github.com/slack-go/slack/users.go
+++ b/vendor/github.com/slack-go/slack/users.go
@@ -513,7 +513,7 @@ func (api *Client) DeleteUserPhotoContext(ctx context.Context) (err error) {
//
// For more information see SetUserRealNameContextWithUser
func (api *Client) SetUserRealName(realName string) error {
- return api.SetUserRealNameContextWithUser(context.Background(), realName, realName)
+ return api.SetUserRealNameContextWithUser(context.Background(), "", realName)
}
// SetUserRealNameContextWithUser will set a real name for the provided user with a custom context
@@ -531,11 +531,15 @@ func (api *Client) SetUserRealNameContextWithUser(ctx context.Context, user, rea
}
values := url.Values{
- "user": {user},
"token": {api.token},
"profile": {string(profile)},
}
+ // optional field. It should not be set if empty
+ if user != "" {
+ values["user"] = []string{user}
+ }
+
response := &userResponseFull{}
if err = api.postMethod(ctx, "users.profile.set", values, response); err != nil {
return err
@@ -557,7 +561,7 @@ func (api *Client) SetUserCustomStatus(statusText, statusEmoji string, statusExp
//
// For more information see SetUserCustomStatus
func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, statusEmoji string, statusExpiration int64) error {
- return api.SetUserCustomStatusContextWithUser(context.Background(), "", statusText, statusEmoji, statusExpiration)
+ return api.SetUserCustomStatusContextWithUser(ctx, "", statusText, statusEmoji, statusExpiration)
}
// SetUserCustomStatusWithUser will set a custom status and emoji for the provided user.
@@ -598,11 +602,15 @@ func (api *Client) SetUserCustomStatusContextWithUser(ctx context.Context, user,
}
values := url.Values{
- "user": {user},
"token": {api.token},
"profile": {string(profile)},
}
+ // optional field. It should not be set if empty
+ if user != "" {
+ values["user"] = []string{user}
+ }
+
response := &userResponseFull{}
if err = api.postMethod(ctx, "users.profile.set", values, response); err != nil {
return err