Update to latest gomatrix. Things are broken
This commit is contained in:
parent
68db26bcac
commit
cfb2cc057c
40
Gopkg.lock
generated
40
Gopkg.lock
generated
@ -4,14 +4,14 @@
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/disintegration/imaging"
|
||||
packages = ["."]
|
||||
revision = "bbcee2f5c9d5e94ca42c8b50ec847fec64a6c134"
|
||||
version = "v1.4.2"
|
||||
revision = "0bd5694c78c9c3d9a3cd06a706a8f3c59296a9ac"
|
||||
version = "v1.5.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -26,16 +26,16 @@
|
||||
version = "v1.5.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lucasb-eyer/go-colorful"
|
||||
packages = ["."]
|
||||
revision = "8abd3beca3a7f5039809449d6013a0254ac22bb1"
|
||||
revision = "345fbb3dbcdb252d9985ee899a84963c0fa24c82"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-runewidth"
|
||||
packages = ["."]
|
||||
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
|
||||
version = "v0.0.2"
|
||||
revision = "ce7b0b5c7b45a81508558cd1dba6bb1e4ddb51bb"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -50,10 +50,10 @@
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/renstrom/fuzzysearch"
|
||||
packages = ["fuzzy"]
|
||||
revision = "500e0fce37a81072d9bf4ec1bf5d32f52c807282"
|
||||
revision = "b18e754edff4833912ef4dce9eaca885bd3f0de1"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -64,14 +64,14 @@
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert"]
|
||||
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||
version = "v1.2.1"
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/zyedidia/clipboard"
|
||||
packages = ["."]
|
||||
revision = "4611e809d8b1a3051c11d11f4b610c44df73fa38"
|
||||
revision = "bd31d747117d04b4e25b61f73e1ea4faeea3c56a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -85,7 +85,7 @@
|
||||
"vp8l",
|
||||
"webp"
|
||||
]
|
||||
revision = "f315e440302883054d0c2bd85486878cb4f8572c"
|
||||
revision = "c73c2afc3b812cdd6385de5a50616511c4a3d458"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@ -94,7 +94,7 @@
|
||||
"html",
|
||||
"html/atom"
|
||||
]
|
||||
revision = "dfa909b99c79129e1100513e5cd36307665e5723"
|
||||
revision = "8a410e7b638dca158bf9e766925842f6651ff828"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
@ -118,7 +118,7 @@
|
||||
branch = "v1"
|
||||
name = "gopkg.in/toast.v1"
|
||||
packages = ["."]
|
||||
revision = "b700e246b8b6d3e13554091e540e1019e26389f1"
|
||||
revision = "0a84660828b24d25b35525c9a1f1f51267f8da91"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
@ -130,7 +130,13 @@
|
||||
branch = "master"
|
||||
name = "maunium.net/go/gomatrix"
|
||||
packages = ["."]
|
||||
revision = "b491397f18b90e34ef54b8b3598666564b90b01a"
|
||||
revision = "d651abc3ecb4bbd85a6b17b710632e73ddbbc6aa"
|
||||
|
||||
[[projects]]
|
||||
name = "maunium.net/go/maulogger"
|
||||
packages = ["."]
|
||||
revision = "64f0aa33b6c51313e15575257db71dec44fe7988"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -33,14 +33,14 @@ type MatrixContainer interface {
|
||||
Logout()
|
||||
|
||||
SendPreferencesToMatrix()
|
||||
SendMessage(roomID, msgtype, message string) (string, error)
|
||||
SendMarkdownMessage(roomID, msgtype, message string) (string, error)
|
||||
SendMessage(roomID string, msgtype gomatrix.MessageType, message string) (string, error)
|
||||
SendMarkdownMessage(roomID string, msgtype gomatrix.MessageType, message string) (string, error)
|
||||
SendTyping(roomID string, typing bool)
|
||||
MarkRead(roomID, eventID string)
|
||||
JoinRoom(roomID, server string) (*rooms.Room, error)
|
||||
LeaveRoom(roomID string) error
|
||||
|
||||
GetHistory(roomID, prevBatch string, limit int) ([]gomatrix.Event, string, error)
|
||||
GetHistory(roomID, prevBatch string, limit int) ([]*gomatrix.Event, string, error)
|
||||
GetRoom(roomID string) *rooms.Room
|
||||
|
||||
Download(mxcURL string) ([]byte, string, string, error)
|
||||
|
@ -73,8 +73,8 @@ type RoomView interface {
|
||||
SetTyping(users []string)
|
||||
UpdateUserList()
|
||||
|
||||
NewMessage(id, sender, msgtype, text string, timestamp time.Time) Message
|
||||
NewTempMessage(msgtype, text string) Message
|
||||
NewMessage(id, sender string, msgtype gomatrix.MessageType, text string, timestamp time.Time) Message
|
||||
NewTempMessage(msgtype gomatrix.MessageType, text string) Message
|
||||
AddMessage(message Message, direction MessageDirection)
|
||||
AddServiceMessage(message string)
|
||||
}
|
||||
@ -111,8 +111,8 @@ type Message interface {
|
||||
SetID(id string)
|
||||
ID() string
|
||||
|
||||
SetType(msgtype string)
|
||||
Type() string
|
||||
SetType(msgtype gomatrix.MessageType)
|
||||
Type() gomatrix.MessageType
|
||||
|
||||
NotificationContent() string
|
||||
|
||||
|
@ -175,6 +175,8 @@ func (c *Container) PushRules() *pushrules.PushRuleset {
|
||||
return c.config.PushRules
|
||||
}
|
||||
|
||||
var AccountDataGomuksPreferences = gomatrix.NewEventType("net.maunium.gomuks.preferences")
|
||||
|
||||
// OnLogin initializes the syncer and updates the room list.
|
||||
func (c *Container) OnLogin() {
|
||||
c.ui.OnLogin()
|
||||
@ -183,14 +185,14 @@ func (c *Container) OnLogin() {
|
||||
|
||||
debug.Print("Initializing syncer")
|
||||
c.syncer = NewGomuksSyncer(c.config)
|
||||
c.syncer.OnEventType("m.room.message", c.HandleMessage)
|
||||
c.syncer.OnEventType("m.room.member", c.HandleMembership)
|
||||
c.syncer.OnEventType("m.receipt", c.HandleReadReceipt)
|
||||
c.syncer.OnEventType("m.typing", c.HandleTyping)
|
||||
c.syncer.OnEventType("m.direct", c.HandleDirectChatInfo)
|
||||
c.syncer.OnEventType("m.push_rules", c.HandlePushRules)
|
||||
c.syncer.OnEventType("m.tag", c.HandleTag)
|
||||
c.syncer.OnEventType("net.maunium.gomuks.preferences", c.HandlePreferences)
|
||||
c.syncer.OnEventType(gomatrix.EventMessage, c.HandleMessage)
|
||||
c.syncer.OnEventType(gomatrix.StateMember, c.HandleMembership)
|
||||
c.syncer.OnEventType(gomatrix.EphemeralEventReceipt, c.HandleReadReceipt)
|
||||
c.syncer.OnEventType(gomatrix.EphemeralEventTyping, c.HandleTyping)
|
||||
c.syncer.OnEventType(gomatrix.AccountDataDirectChats, c.HandleDirectChatInfo)
|
||||
c.syncer.OnEventType(gomatrix.AccountDataPushRules, c.HandlePushRules)
|
||||
c.syncer.OnEventType(gomatrix.AccountDataRoomTags, c.HandleTag)
|
||||
c.syncer.OnEventType(AccountDataGomuksPreferences, c.HandlePreferences)
|
||||
c.syncer.InitDoneCallback = func() {
|
||||
c.config.AuthCache.InitialSyncDone = true
|
||||
c.config.SaveAuthCache()
|
||||
@ -301,10 +303,10 @@ func (c *Container) HandleMembership(source EventSource, evt *gomatrix.Event) {
|
||||
}
|
||||
|
||||
func (c *Container) processOwnMembershipChange(evt *gomatrix.Event) {
|
||||
membership, _ := evt.Content["membership"].(string)
|
||||
prevMembership := "leave"
|
||||
membership := evt.Content.Membership
|
||||
prevMembership := gomatrix.MembershipLeave
|
||||
if evt.Unsigned.PrevContent != nil {
|
||||
prevMembership, _ = evt.Unsigned.PrevContent["membership"].(string)
|
||||
prevMembership = evt.Unsigned.PrevContent.Membership
|
||||
}
|
||||
debug.Printf("Processing own membership change: %s->%s in %s", prevMembership, membership, evt.RoomID)
|
||||
if membership == prevMembership {
|
||||
@ -326,7 +328,7 @@ func (c *Container) processOwnMembershipChange(evt *gomatrix.Event) {
|
||||
|
||||
func (c *Container) parseReadReceipt(evt *gomatrix.Event) (largestTimestampEvent string) {
|
||||
var largestTimestamp int64
|
||||
for eventID, rawContent := range evt.Content {
|
||||
for eventID, rawContent := range evt.Content.Raw {
|
||||
content, ok := rawContent.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
@ -368,7 +370,7 @@ func (c *Container) HandleReadReceipt(source EventSource, evt *gomatrix.Event) {
|
||||
|
||||
func (c *Container) parseDirectChatInfo(evt *gomatrix.Event) map[*rooms.Room]bool {
|
||||
directChats := make(map[*rooms.Room]bool)
|
||||
for _, rawRoomIDList := range evt.Content {
|
||||
for _, rawRoomIDList := range evt.Content.Raw {
|
||||
roomIDList, ok := rawRoomIDList.([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
@ -416,15 +418,12 @@ func (c *Container) HandlePushRules(source EventSource, evt *gomatrix.Event) {
|
||||
func (c *Container) HandleTag(source EventSource, evt *gomatrix.Event) {
|
||||
room := c.config.GetRoom(evt.RoomID)
|
||||
|
||||
tags, _ := evt.Content["tags"].(map[string]interface{})
|
||||
newTags := make([]rooms.RoomTag, len(tags))
|
||||
newTags := make([]rooms.RoomTag, len(evt.Content.RoomTags))
|
||||
index := 0
|
||||
for tag, infoifc := range tags {
|
||||
info, _ := infoifc.(map[string]interface{})
|
||||
for tag, info := range evt.Content.RoomTags {
|
||||
order := "0.5"
|
||||
rawOrder, ok := info["order"]
|
||||
if ok {
|
||||
order = fmt.Sprintf("%v", rawOrder)
|
||||
if len(info.Order) > 0 {
|
||||
order = info.Order
|
||||
}
|
||||
newTags[index] = rooms.RoomTag{
|
||||
Tag: tag,
|
||||
@ -440,13 +439,7 @@ func (c *Container) HandleTag(source EventSource, evt *gomatrix.Event) {
|
||||
|
||||
// HandleTyping is the event handler for the m.typing event.
|
||||
func (c *Container) HandleTyping(source EventSource, evt *gomatrix.Event) {
|
||||
users := evt.Content["user_ids"].([]interface{})
|
||||
|
||||
strUsers := make([]string, len(users))
|
||||
for i, user := range users {
|
||||
strUsers[i] = user.(string)
|
||||
}
|
||||
c.ui.MainView().SetTyping(evt.RoomID, strUsers)
|
||||
c.ui.MainView().SetTyping(evt.RoomID, evt.Content.TypingUserIDs)
|
||||
}
|
||||
|
||||
func (c *Container) MarkRead(roomID, eventID string) {
|
||||
@ -455,11 +448,11 @@ func (c *Container) MarkRead(roomID, eventID string) {
|
||||
}
|
||||
|
||||
// SendMessage sends a message with the given text to the given room.
|
||||
func (c *Container) SendMessage(roomID, msgtype, text string) (string, error) {
|
||||
func (c *Container) SendMessage(roomID string, msgtype gomatrix.MessageType, text string) (string, error) {
|
||||
defer debug.Recover()
|
||||
c.SendTyping(roomID, false)
|
||||
resp, err := c.client.SendMessageEvent(roomID, "m.room.message",
|
||||
gomatrix.TextMessage{MsgType: msgtype, Body: text})
|
||||
resp, err := c.client.SendMessageEvent(roomID, gomatrix.EventMessage,
|
||||
gomatrix.Content{MsgType: msgtype, Body: text})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -498,7 +491,7 @@ var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\
|
||||
//
|
||||
// If the given text contains markdown formatting symbols, it will be rendered into HTML before sending.
|
||||
// Otherwise, it will be sent as plain text.
|
||||
func (c *Container) SendMarkdownMessage(roomID, msgtype, text string) (string, error) {
|
||||
func (c *Container) SendMarkdownMessage(roomID string, msgtype gomatrix.MessageType, text string) (string, error) {
|
||||
defer debug.Recover()
|
||||
|
||||
html := c.renderMarkdown(text)
|
||||
@ -511,12 +504,12 @@ func (c *Container) SendMarkdownMessage(roomID, msgtype, text string) (string, e
|
||||
text = roomRegex.ReplaceAllString(text, "$1")
|
||||
|
||||
c.SendTyping(roomID, false)
|
||||
resp, err := c.client.SendMessageEvent(roomID, "m.room.message",
|
||||
map[string]interface{}{
|
||||
"msgtype": msgtype,
|
||||
"body": text,
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": html,
|
||||
resp, err := c.client.SendMessageEvent(roomID, gomatrix.EventMessage,
|
||||
gomatrix.Content{
|
||||
MsgType: msgtype,
|
||||
Body: text,
|
||||
Format: gomatrix.FormatHTML,
|
||||
FormattedBody: html,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -567,7 +560,7 @@ func (c *Container) LeaveRoom(roomID string) error {
|
||||
}
|
||||
|
||||
// GetHistory fetches room history.
|
||||
func (c *Container) GetHistory(roomID, prevBatch string, limit int) ([]gomatrix.Event, string, error) {
|
||||
func (c *Container) GetHistory(roomID, prevBatch string, limit int) ([]*gomatrix.Event, string, error) {
|
||||
resp, err := c.client.Messages(roomID, prevBatch, "", 'b', limit)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
@ -23,14 +23,13 @@ import (
|
||||
|
||||
"maunium.net/go/gomatrix"
|
||||
"maunium.net/go/gomuks/lib/glob"
|
||||
"maunium.net/go/gomuks/matrix/rooms"
|
||||
)
|
||||
|
||||
// Room is an interface with the functions that are needed for processing room-specific push conditions
|
||||
type Room interface {
|
||||
GetMember(mxid string) *rooms.Member
|
||||
GetMembers() map[string]*rooms.Member
|
||||
GetSessionOwner() *rooms.Member
|
||||
GetMember(mxid string) *gomatrix.Member
|
||||
GetMembers() map[string]*gomatrix.Member
|
||||
GetSessionOwner() string
|
||||
}
|
||||
|
||||
// PushCondKind is the type of a push condition.
|
||||
@ -89,7 +88,7 @@ func (cond *PushCondition) matchValue(room Room, event *gomatrix.Event) bool {
|
||||
|
||||
switch key {
|
||||
case "type":
|
||||
return pattern.MatchString(event.Type)
|
||||
return pattern.MatchString(event.Type.String())
|
||||
case "sender":
|
||||
return pattern.MatchString(event.Sender)
|
||||
case "room_id":
|
||||
@ -100,7 +99,7 @@ func (cond *PushCondition) matchValue(room Room, event *gomatrix.Event) bool {
|
||||
}
|
||||
return pattern.MatchString(*event.StateKey)
|
||||
case "content":
|
||||
val, _ := event.Content[subkey].(string)
|
||||
val, _ := event.Content.Raw[subkey].(string)
|
||||
return pattern.MatchString(val)
|
||||
default:
|
||||
return false
|
||||
@ -108,12 +107,12 @@ func (cond *PushCondition) matchValue(room Room, event *gomatrix.Event) bool {
|
||||
}
|
||||
|
||||
func (cond *PushCondition) matchDisplayName(room Room, event *gomatrix.Event) bool {
|
||||
member := room.GetSessionOwner()
|
||||
if member == nil || member.UserID == event.Sender {
|
||||
ownerID := room.GetSessionOwner()
|
||||
if ownerID == event.Sender {
|
||||
return false
|
||||
}
|
||||
text, _ := event.Content["body"].(string)
|
||||
return strings.Contains(text, member.DisplayName)
|
||||
member := room.GetMember(ownerID)
|
||||
return strings.Contains(event.Content.Body, member.Displayname)
|
||||
}
|
||||
|
||||
func (cond *PushCondition) matchMemberCount(room Room, event *gomatrix.Event) bool {
|
||||
|
@ -21,19 +21,17 @@ func GetScopedPushRules(client *gomatrix.Client, scope string) (resp *PushRulese
|
||||
return
|
||||
}
|
||||
|
||||
type contentWithRuleset struct {
|
||||
Ruleset *PushRuleset `json:"global"`
|
||||
}
|
||||
|
||||
// EventToPushRules converts a m.push_rules event to a PushRuleset by passing the data through JSON.
|
||||
func EventToPushRules(event *gomatrix.Event) (*PushRuleset, error) {
|
||||
content, _ := event.Content["global"]
|
||||
raw, err := json.Marshal(content)
|
||||
content := &contentWithRuleset{}
|
||||
err := json.Unmarshal(event.Content.VeryRaw, content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ruleset := &PushRuleset{}
|
||||
err = json.Unmarshal(raw, ruleset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ruleset, nil
|
||||
return content.Ruleset, nil
|
||||
}
|
||||
|
@ -154,6 +154,5 @@ func (rule *PushRule) matchPattern(room Room, event *gomatrix.Event) bool {
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
text, _ := event.Content["body"].(string)
|
||||
return pattern.MatchString(text)
|
||||
return pattern.MatchString(event.Content.Body)
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
// gomuks - A terminal Matrix client written in Go.
|
||||
// Copyright (C) 2018 Tulir Asokan
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rooms
|
||||
|
||||
import (
|
||||
"maunium.net/go/gomatrix"
|
||||
)
|
||||
|
||||
// Membership is an enum specifying the membership state of a room member.
|
||||
type Membership string
|
||||
|
||||
// The allowed membership states as specified in spec section 10.5.5.
|
||||
const (
|
||||
MembershipJoin Membership = "join"
|
||||
MembershipLeave Membership = "leave"
|
||||
MembershipInvite Membership = "invite"
|
||||
MembershipBan Membership = "ban"
|
||||
MembershipKnock Membership = "knock"
|
||||
)
|
||||
|
||||
// Member represents a member in a room.
|
||||
type Member struct {
|
||||
// The MXID of the member.
|
||||
UserID string `json:"-"`
|
||||
// The membership status. Defaults to leave.
|
||||
Membership Membership `json:"membership"`
|
||||
// The display name of the user. Defaults to the user ID.
|
||||
DisplayName string `json:"displayname"`
|
||||
// The avatar URL of the user. Defaults to an empty string.
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
// eventToRoomMember converts a m.room.member state event into a Member object.
|
||||
func eventToRoomMember(userID string, event *gomatrix.Event) *Member {
|
||||
membership, _ := event.Content["membership"].(string)
|
||||
avatarURL, _ := event.Content["avatar_url"].(string)
|
||||
|
||||
displayName, _ := event.Content["displayname"].(string)
|
||||
if len(displayName) == 0 {
|
||||
displayName = userID
|
||||
}
|
||||
|
||||
return &Member{
|
||||
UserID: userID,
|
||||
Membership: Membership(membership),
|
||||
DisplayName: displayName,
|
||||
AvatarURL: avatarURL,
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// gomuks - A terminal Matrix client written in Go.
|
||||
// Copyright (C) 2018 Tulir Asokan
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rooms_test
|
@ -82,10 +82,10 @@ type Room struct {
|
||||
LastReceivedMessage time.Time
|
||||
|
||||
// MXID -> Member cache calculated from membership events.
|
||||
memberCache map[string]*Member
|
||||
memberCache map[string]*gomatrix.Member
|
||||
// The first non-SessionUserID member in the room. Calculated at
|
||||
// the same time as memberCache.
|
||||
firstMemberCache *Member
|
||||
firstMemberCache *gomatrix.Member
|
||||
// The name of the room. Calculated from the state event name,
|
||||
// canonical_alias or alias or the member cache.
|
||||
nameCache string
|
||||
@ -222,25 +222,25 @@ func (room *Room) UpdateState(event *gomatrix.Event) {
|
||||
room.State[event.Type] = make(map[string]*gomatrix.Event)
|
||||
}
|
||||
switch event.Type {
|
||||
case "m.room.name":
|
||||
case gomatrix.StateRoomName:
|
||||
room.nameCache = ""
|
||||
case "m.room.canonical_alias":
|
||||
case gomatrix.StateCanonicalAlias:
|
||||
if room.nameCacheSource >= CanonicalAliasRoomName {
|
||||
room.nameCache = ""
|
||||
}
|
||||
room.canonicalAliasCache = ""
|
||||
case "m.room.aliases":
|
||||
case gomatrix.StateAliases:
|
||||
if room.nameCacheSource >= AliasRoomName {
|
||||
room.nameCache = ""
|
||||
}
|
||||
room.aliasesCache = nil
|
||||
case "m.room.member":
|
||||
case gomatrix.StateMember:
|
||||
room.memberCache = nil
|
||||
room.firstMemberCache = nil
|
||||
if room.nameCacheSource >= MemberRoomName {
|
||||
room.nameCache = ""
|
||||
}
|
||||
case "m.room.topic":
|
||||
case gomatrix.StateTopic:
|
||||
room.topicCache = ""
|
||||
}
|
||||
|
||||
@ -248,7 +248,7 @@ func (room *Room) UpdateState(event *gomatrix.Event) {
|
||||
if event.StateKey != nil {
|
||||
stateKey = *event.StateKey
|
||||
}
|
||||
if event.Type != "m.room.member" {
|
||||
if event.Type != gomatrix.StateMember {
|
||||
debug.Printf("Updating state %s#%s for %s", event.Type, stateKey, room.ID)
|
||||
}
|
||||
|
||||
@ -260,14 +260,14 @@ func (room *Room) UpdateState(event *gomatrix.Event) {
|
||||
}
|
||||
|
||||
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
|
||||
func (room *Room) GetStateEvent(eventType string, stateKey string) *gomatrix.Event {
|
||||
func (room *Room) GetStateEvent(eventType gomatrix.EventType, stateKey string) *gomatrix.Event {
|
||||
stateEventMap, _ := room.State[eventType]
|
||||
event, _ := stateEventMap[stateKey]
|
||||
return event
|
||||
}
|
||||
|
||||
// GetStateEvents returns the state events for the given type.
|
||||
func (room *Room) GetStateEvents(eventType string) map[string]*gomatrix.Event {
|
||||
func (room *Room) GetStateEvents(eventType gomatrix.EventType) map[string]*gomatrix.Event {
|
||||
stateEventMap, _ := room.State[eventType]
|
||||
return stateEventMap
|
||||
}
|
||||
@ -275,9 +275,9 @@ func (room *Room) GetStateEvents(eventType string) map[string]*gomatrix.Event {
|
||||
// GetTopic returns the topic of the room.
|
||||
func (room *Room) GetTopic() string {
|
||||
if len(room.topicCache) == 0 {
|
||||
topicEvt := room.GetStateEvent("m.room.topic", "")
|
||||
topicEvt := room.GetStateEvent(gomatrix.StateTopic, "")
|
||||
if topicEvt != nil {
|
||||
room.topicCache, _ = topicEvt.Content["topic"].(string)
|
||||
room.topicCache = topicEvt.Content.Topic
|
||||
}
|
||||
}
|
||||
return room.topicCache
|
||||
@ -285,9 +285,9 @@ func (room *Room) GetTopic() string {
|
||||
|
||||
func (room *Room) GetCanonicalAlias() string {
|
||||
if len(room.canonicalAliasCache) == 0 {
|
||||
canonicalAliasEvt := room.GetStateEvent("m.room.canonical_alias", "")
|
||||
canonicalAliasEvt := room.GetStateEvent(gomatrix.StateCanonicalAlias, "")
|
||||
if canonicalAliasEvt != nil {
|
||||
room.canonicalAliasCache, _ = canonicalAliasEvt.Content["alias"].(string)
|
||||
room.canonicalAliasCache = canonicalAliasEvt.Content.Alias
|
||||
} else {
|
||||
room.canonicalAliasCache = "-"
|
||||
}
|
||||
@ -301,17 +301,10 @@ func (room *Room) GetCanonicalAlias() string {
|
||||
// GetAliases returns the list of aliases that point to this room.
|
||||
func (room *Room) GetAliases() []string {
|
||||
if room.aliasesCache == nil {
|
||||
aliasEvents := room.GetStateEvents("m.room.aliases")
|
||||
aliasEvents := room.GetStateEvents(gomatrix.StateAliases)
|
||||
room.aliasesCache = []string{}
|
||||
for _, event := range aliasEvents {
|
||||
aliases, _ := event.Content["aliases"].([]interface{})
|
||||
|
||||
newAliases := make([]string, len(room.aliasesCache)+len(aliases))
|
||||
copy(newAliases, room.aliasesCache)
|
||||
for index, alias := range aliases {
|
||||
newAliases[len(room.aliasesCache)+index], _ = alias.(string)
|
||||
}
|
||||
room.aliasesCache = newAliases
|
||||
room.aliasesCache = append(room.aliasesCache, event.Content.Aliases...)
|
||||
}
|
||||
}
|
||||
return room.aliasesCache
|
||||
@ -319,9 +312,9 @@ func (room *Room) GetAliases() []string {
|
||||
|
||||
// updateNameFromNameEvent updates the room display name to be the name set in the name event.
|
||||
func (room *Room) updateNameFromNameEvent() {
|
||||
nameEvt := room.GetStateEvent("m.room.name", "")
|
||||
nameEvt := room.GetStateEvent(gomatrix.StateRoomName, "")
|
||||
if nameEvt != nil {
|
||||
room.nameCache, _ = nameEvt.Content["name"].(string)
|
||||
room.nameCache = nameEvt.Content.Name
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,9 +346,9 @@ func (room *Room) updateNameFromMembers() {
|
||||
} else if room.firstMemberCache == nil {
|
||||
room.nameCache = "Room"
|
||||
} else if len(members) == 2 {
|
||||
room.nameCache = room.firstMemberCache.DisplayName
|
||||
room.nameCache = room.firstMemberCache.Displayname
|
||||
} else {
|
||||
firstMember := room.firstMemberCache.DisplayName
|
||||
firstMember := room.firstMemberCache.Displayname
|
||||
room.nameCache = fmt.Sprintf("%s and %d others", firstMember, len(members)-2)
|
||||
}
|
||||
}
|
||||
@ -391,18 +384,18 @@ func (room *Room) GetTitle() string {
|
||||
}
|
||||
|
||||
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
||||
func (room *Room) createMemberCache() map[string]*Member {
|
||||
cache := make(map[string]*Member)
|
||||
events := room.GetStateEvents("m.room.member")
|
||||
func (room *Room) createMemberCache() map[string]*gomatrix.Member {
|
||||
cache := make(map[string]*gomatrix.Member)
|
||||
events := room.GetStateEvents(gomatrix.StateMember)
|
||||
room.firstMemberCache = nil
|
||||
if events != nil {
|
||||
for userID, event := range events {
|
||||
member := eventToRoomMember(userID, event)
|
||||
member := &event.Content.Member
|
||||
if room.firstMemberCache == nil && userID != room.SessionUserID {
|
||||
room.firstMemberCache = member
|
||||
}
|
||||
if member.Membership != "leave" {
|
||||
cache[member.UserID] = member
|
||||
cache[userID] = member
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,7 +407,7 @@ func (room *Room) createMemberCache() map[string]*Member {
|
||||
//
|
||||
// The members are returned from the cache.
|
||||
// If the cache is empty, it is updated first.
|
||||
func (room *Room) GetMembers() map[string]*Member {
|
||||
func (room *Room) GetMembers() map[string]*gomatrix.Member {
|
||||
if len(room.memberCache) == 0 || room.firstMemberCache == nil {
|
||||
room.createMemberCache()
|
||||
}
|
||||
@ -423,7 +416,7 @@ func (room *Room) GetMembers() map[string]*Member {
|
||||
|
||||
// GetMember returns the member with the given MXID.
|
||||
// If the member doesn't exist, nil is returned.
|
||||
func (room *Room) GetMember(userID string) *Member {
|
||||
func (room *Room) GetMember(userID string) *gomatrix.Member {
|
||||
if len(room.memberCache) == 0 {
|
||||
room.createMemberCache()
|
||||
}
|
||||
@ -432,8 +425,8 @@ func (room *Room) GetMember(userID string) *Member {
|
||||
}
|
||||
|
||||
// GetSessionOwner returns the Member instance of the user whose session this room was created for.
|
||||
func (room *Room) GetSessionOwner() *Member {
|
||||
return room.GetMember(room.SessionUserID)
|
||||
func (room *Room) GetSessionOwner() string {
|
||||
return room.SessionUserID
|
||||
}
|
||||
|
||||
// NewRoom creates a new Room with the given ID
|
||||
|
@ -51,7 +51,7 @@ type EventHandler func(source EventSource, event *gomatrix.Event)
|
||||
// pattern to notify callers about incoming events. See GomuksSyncer.OnEventType for more information.
|
||||
type GomuksSyncer struct {
|
||||
Session SyncerSession
|
||||
listeners map[string][]EventHandler // event type to listeners array
|
||||
listeners map[gomatrix.EventType][]EventHandler // event type to listeners array
|
||||
FirstSyncDone bool
|
||||
InitDoneCallback func()
|
||||
}
|
||||
@ -60,7 +60,7 @@ type GomuksSyncer struct {
|
||||
func NewGomuksSyncer(session SyncerSession) *GomuksSyncer {
|
||||
return &GomuksSyncer{
|
||||
Session: session,
|
||||
listeners: make(map[string][]EventHandler),
|
||||
listeners: make(map[gomatrix.EventType][]EventHandler),
|
||||
FirstSyncDone: false,
|
||||
}
|
||||
}
|
||||
@ -114,20 +114,11 @@ func (s *GomuksSyncer) processSyncEvents(room *rooms.Room, events []*gomatrix.Ev
|
||||
}
|
||||
}
|
||||
|
||||
func isState(event *gomatrix.Event) bool {
|
||||
switch event.Type {
|
||||
case "m.room.member", "m.room.name", "m.room.topic", "m.room.aliases", "m.room.canonical_alias":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GomuksSyncer) processSyncEvent(room *rooms.Room, event *gomatrix.Event, source EventSource) {
|
||||
if room != nil {
|
||||
event.RoomID = room.ID
|
||||
}
|
||||
if isState(event) {
|
||||
if event.Type.Class == gomatrix.StateEventType {
|
||||
room.UpdateState(event)
|
||||
}
|
||||
s.notifyListeners(source, event)
|
||||
@ -135,7 +126,7 @@ func (s *GomuksSyncer) processSyncEvent(room *rooms.Room, event *gomatrix.Event,
|
||||
|
||||
// OnEventType allows callers to be notified when there are new events for the given event type.
|
||||
// There are no duplicate checks.
|
||||
func (s *GomuksSyncer) OnEventType(eventType string, callback EventHandler) {
|
||||
func (s *GomuksSyncer) OnEventType(eventType gomatrix.EventType, callback EventHandler) {
|
||||
_, exists := s.listeners[eventType]
|
||||
if !exists {
|
||||
s.listeners[eventType] = []EventHandler{}
|
||||
|
@ -19,6 +19,7 @@ package ui
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maunium.net/go/gomatrix"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@ -132,7 +133,7 @@ func cmdSendEvent(cmd *Command) {
|
||||
return
|
||||
}
|
||||
roomID := cmd.Args[0]
|
||||
eventType := cmd.Args[1]
|
||||
eventType := gomatrix.NewEventType(cmd.Args[1])
|
||||
rawContent := strings.Join(cmd.Args[2:], "")
|
||||
debug.Print(roomID, eventType, rawContent)
|
||||
|
||||
@ -161,7 +162,7 @@ func cmdSetState(cmd *Command) {
|
||||
}
|
||||
|
||||
roomID := cmd.Args[0]
|
||||
eventType := cmd.Args[1]
|
||||
eventType := gomatrix.NewEventType(cmd.Args[1])
|
||||
stateKey := cmd.Args[2]
|
||||
if stateKey == "-" {
|
||||
stateKey = ""
|
||||
|
@ -18,6 +18,7 @@ package messages
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"maunium.net/go/gomatrix"
|
||||
"time"
|
||||
|
||||
"maunium.net/go/gomuks/config"
|
||||
@ -33,7 +34,7 @@ func init() {
|
||||
|
||||
type BaseMessage struct {
|
||||
MsgID string
|
||||
MsgType string
|
||||
MsgType gomatrix.MessageType
|
||||
MsgSenderID string
|
||||
MsgSender string
|
||||
MsgSenderColor tcell.Color
|
||||
@ -47,7 +48,7 @@ type BaseMessage struct {
|
||||
prevPrefs config.UserPreferences
|
||||
}
|
||||
|
||||
func newBaseMessage(id, sender, displayname, msgtype string, timestamp time.Time) BaseMessage {
|
||||
func newBaseMessage(id, sender, displayname string, msgtype gomatrix.MessageType, timestamp time.Time) BaseMessage {
|
||||
return BaseMessage{
|
||||
MsgSenderID: sender,
|
||||
MsgSender: displayname,
|
||||
@ -194,11 +195,11 @@ func (msg *BaseMessage) SetID(id string) {
|
||||
msg.MsgID = id
|
||||
}
|
||||
|
||||
func (msg *BaseMessage) Type() string {
|
||||
func (msg *BaseMessage) Type() gomatrix.MessageType {
|
||||
return msg.MsgType
|
||||
}
|
||||
|
||||
func (msg *BaseMessage) SetType(msgtype string) {
|
||||
func (msg *BaseMessage) SetType(msgtype gomatrix.MessageType) {
|
||||
msg.MsgType = msgtype
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ package messages
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"maunium.net/go/gomatrix"
|
||||
"time"
|
||||
|
||||
"maunium.net/go/gomuks/config"
|
||||
@ -34,7 +35,7 @@ type ExpandedTextMessage struct {
|
||||
}
|
||||
|
||||
// NewExpandedTextMessage creates a new ExpandedTextMessage object with the provided values and the default state.
|
||||
func NewExpandedTextMessage(id, sender, displayname, msgtype string, text tstring.TString, timestamp time.Time) UIMessage {
|
||||
func NewExpandedTextMessage(id, sender, displayname string, msgtype gomatrix.MessageType, text tstring.TString, timestamp time.Time) UIMessage {
|
||||
return &ExpandedTextMessage{
|
||||
BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
||||
MsgText: text,
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"maunium.net/go/gomatrix"
|
||||
"time"
|
||||
|
||||
"image/color"
|
||||
@ -47,7 +48,7 @@ type ImageMessage struct {
|
||||
}
|
||||
|
||||
// NewImageMessage creates a new ImageMessage object with the provided values and the default state.
|
||||
func NewImageMessage(matrix ifc.MatrixContainer, id, sender, displayname, msgtype, body, homeserver, fileID string, data []byte, timestamp time.Time) UIMessage {
|
||||
func NewImageMessage(matrix ifc.MatrixContainer, id, sender, displayname string, msgtype gomatrix.MessageType, body, homeserver, fileID string, data []byte, timestamp time.Time) UIMessage {
|
||||
return &ImageMessage{
|
||||
newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
||||
body,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
"golang.org/x/net/html"
|
||||
"maunium.net/go/gomatrix"
|
||||
"maunium.net/go/gomuks/matrix/rooms"
|
||||
@ -29,7 +30,6 @@ import (
|
||||
"maunium.net/go/gomuks/ui/widget"
|
||||
"maunium.net/go/tcell"
|
||||
"strconv"
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
)
|
||||
|
||||
var matrixToURL = regexp.MustCompile("^(?:https?://)?(?:www\\.)?matrix\\.to/#/([#@!].*)")
|
||||
@ -173,7 +173,7 @@ func (parser *htmlParser) linkToTString(node *html.Node, stripLinebreak bool) ts
|
||||
pillTarget := match[1]
|
||||
if pillTarget[0] == '@' {
|
||||
if member := parser.room.GetMember(pillTarget); member != nil {
|
||||
return tstring.NewColorTString(member.DisplayName, widget.GetHashColor(member.UserID))
|
||||
return tstring.NewColorTString(member.Displayname, widget.GetHashColor(pillTarget))
|
||||
}
|
||||
}
|
||||
return tstring.NewTString(pillTarget)
|
||||
@ -271,14 +271,13 @@ func (parser *htmlParser) Parse(htmlData string) tstring.TString {
|
||||
|
||||
// ParseHTMLMessage parses a HTML-formatted Matrix event into a UIMessage.
|
||||
func ParseHTMLMessage(room *rooms.Room, evt *gomatrix.Event, senderDisplayname string) tstring.TString {
|
||||
htmlData, _ := evt.Content["formatted_body"].(string)
|
||||
htmlData := evt.Content.FormattedBody
|
||||
htmlData = strings.Replace(htmlData, "\t", " ", -1)
|
||||
|
||||
parser := htmlParser{room}
|
||||
str := parser.Parse(htmlData)
|
||||
|
||||
msgtype, _ := evt.Content["msgtype"].(string)
|
||||
if msgtype == "m.emote" {
|
||||
if evt.Content.MsgType == gomatrix.MsgEmote {
|
||||
str = tstring.Join([]tstring.TString{
|
||||
tstring.NewTString("* "),
|
||||
tstring.NewColorTString(senderDisplayname, widget.GetHashColor(evt.Sender)),
|
||||
|
@ -33,9 +33,9 @@ import (
|
||||
|
||||
func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *gomatrix.Event) messages.UIMessage {
|
||||
switch evt.Type {
|
||||
case "m.room.message":
|
||||
case gomatrix.EventMessage:
|
||||
return ParseMessage(matrix, room, evt)
|
||||
case "m.room.member":
|
||||
case gomatrix.StateMember:
|
||||
return ParseMembershipEvent(room, evt)
|
||||
}
|
||||
return nil
|
||||
@ -53,32 +53,28 @@ func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *gomatrix.Ev
|
||||
displayname := evt.Sender
|
||||
member := room.GetMember(evt.Sender)
|
||||
if member != nil {
|
||||
displayname = member.DisplayName
|
||||
displayname = member.Displayname
|
||||
}
|
||||
msgtype, _ := evt.Content["msgtype"].(string)
|
||||
text, _ := evt.Content["body"].(string)
|
||||
ts := unixToTime(evt.Timestamp)
|
||||
switch msgtype {
|
||||
switch evt.Content.MsgType {
|
||||
case "m.text", "m.notice", "m.emote":
|
||||
format, hasFormat := evt.Content["format"].(string)
|
||||
if hasFormat && format == "org.matrix.custom.html" {
|
||||
if evt.Content.Format == gomatrix.FormatHTML {
|
||||
text := ParseHTMLMessage(room, evt, displayname)
|
||||
return messages.NewExpandedTextMessage(evt.ID, evt.Sender, displayname, msgtype, text, ts)
|
||||
return messages.NewExpandedTextMessage(evt.ID, evt.Sender, displayname, evt.Content.MsgType, text, ts)
|
||||
}
|
||||
text = strings.Replace(text, "\t", " ", -1)
|
||||
return messages.NewTextMessage(evt.ID, evt.Sender, displayname, msgtype, text, ts)
|
||||
evt.Content.Body = strings.Replace(evt.Content.Body, "\t", " ", -1)
|
||||
return messages.NewTextMessage(evt.ID, evt.Sender, displayname, evt.Content.MsgType, evt.Content.Body, ts)
|
||||
case "m.image":
|
||||
url, _ := evt.Content["url"].(string)
|
||||
data, hs, id, err := matrix.Download(url)
|
||||
data, hs, id, err := matrix.Download(evt.Content.URL)
|
||||
if err != nil {
|
||||
debug.Printf("Failed to download %s: %v", url, err)
|
||||
debug.Printf("Failed to download %s: %v", evt.Content.URL, err)
|
||||
}
|
||||
return messages.NewImageMessage(matrix, evt.ID, evt.Sender, displayname, msgtype, text, hs, id, data, ts)
|
||||
return messages.NewImageMessage(matrix, evt.ID, evt.Sender, displayname, evt.Content.MsgType, evt.Content.Body, hs, id, data, ts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMembershipChangeMessage(evt *gomatrix.Event, membership, prevMembership, senderDisplayname, displayname, prevDisplayname string) (sender string, text tstring.TString) {
|
||||
func getMembershipChangeMessage(evt *gomatrix.Event, membership, prevMembership gomatrix.Membership, senderDisplayname, displayname, prevDisplayname string) (sender string, text tstring.TString) {
|
||||
switch membership {
|
||||
case "invite":
|
||||
sender = "---"
|
||||
@ -92,12 +88,11 @@ func getMembershipChangeMessage(evt *gomatrix.Event, membership, prevMembership,
|
||||
case "leave":
|
||||
sender = "<--"
|
||||
if evt.Sender != *evt.StateKey {
|
||||
if prevMembership == "ban" {
|
||||
if prevMembership == gomatrix.MembershipBan {
|
||||
text = tstring.NewColorTString(fmt.Sprintf("%s unbanned %s", senderDisplayname, displayname), tcell.ColorGreen)
|
||||
text.Colorize(len(senderDisplayname)+len(" unbanned "), len(displayname), widget.GetHashColor(*evt.StateKey))
|
||||
} else {
|
||||
reason, _ := evt.Content["reason"].(string)
|
||||
text = tstring.NewColorTString(fmt.Sprintf("%s kicked %s: %s", senderDisplayname, displayname, reason), tcell.ColorRed)
|
||||
text = tstring.NewColorTString(fmt.Sprintf("%s kicked %s: %s", senderDisplayname, displayname, evt.Content.Reason), tcell.ColorRed)
|
||||
text.Colorize(len(senderDisplayname)+len(" kicked "), len(displayname), widget.GetHashColor(*evt.StateKey))
|
||||
}
|
||||
text.Colorize(0, len(senderDisplayname), widget.GetHashColor(evt.Sender))
|
||||
@ -109,8 +104,7 @@ func getMembershipChangeMessage(evt *gomatrix.Event, membership, prevMembership,
|
||||
text.Colorize(0, len(displayname), widget.GetHashColor(*evt.StateKey))
|
||||
}
|
||||
case "ban":
|
||||
reason, _ := evt.Content["reason"].(string)
|
||||
text = tstring.NewColorTString(fmt.Sprintf("%s banned %s: %s", senderDisplayname, displayname, reason), tcell.ColorRed)
|
||||
text = tstring.NewColorTString(fmt.Sprintf("%s banned %s: %s", senderDisplayname, displayname, evt.Content.Reason), tcell.ColorRed)
|
||||
text.Colorize(len(senderDisplayname)+len(" banned "), len(displayname), widget.GetHashColor(*evt.StateKey))
|
||||
text.Colorize(0, len(senderDisplayname), widget.GetHashColor(evt.Sender))
|
||||
}
|
||||
@ -121,20 +115,20 @@ func getMembershipEventContent(room *rooms.Room, evt *gomatrix.Event) (sender st
|
||||
member := room.GetMember(evt.Sender)
|
||||
senderDisplayname := evt.Sender
|
||||
if member != nil {
|
||||
senderDisplayname = member.DisplayName
|
||||
senderDisplayname = member.Displayname
|
||||
}
|
||||
|
||||
membership, _ := evt.Content["membership"].(string)
|
||||
displayname, _ := evt.Content["displayname"].(string)
|
||||
membership := evt.Content.Membership
|
||||
displayname := evt.Content.Displayname
|
||||
if len(displayname) == 0 {
|
||||
displayname = *evt.StateKey
|
||||
}
|
||||
|
||||
prevMembership := "leave"
|
||||
prevMembership := gomatrix.MembershipLeave
|
||||
prevDisplayname := *evt.StateKey
|
||||
if evt.Unsigned.PrevContent != nil {
|
||||
prevMembership, _ = evt.Unsigned.PrevContent["membership"].(string)
|
||||
prevDisplayname, _ = evt.Unsigned.PrevContent["displayname"].(string)
|
||||
prevMembership = evt.Unsigned.PrevContent.Membership
|
||||
prevDisplayname = evt.Unsigned.PrevContent.Displayname
|
||||
if len(prevDisplayname) == 0 {
|
||||
prevDisplayname = *evt.StateKey
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package messages
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"maunium.net/go/gomatrix"
|
||||
"time"
|
||||
|
||||
"maunium.net/go/gomuks/config"
|
||||
@ -37,7 +38,7 @@ type TextMessage struct {
|
||||
}
|
||||
|
||||
// NewTextMessage creates a new UITextMessage object with the provided values and the default state.
|
||||
func NewTextMessage(id, sender, displayname, msgtype, text string, timestamp time.Time) UIMessage {
|
||||
func NewTextMessage(id, sender, displayname string, msgtype gomatrix.MessageType, text string, timestamp time.Time) UIMessage {
|
||||
return &TextMessage{
|
||||
BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
||||
MsgText: text,
|
||||
@ -57,7 +58,7 @@ func (msg *TextMessage) getCache() tstring.TString {
|
||||
return msg.cache
|
||||
}
|
||||
|
||||
func (msg *TextMessage) SetType(msgtype string) {
|
||||
func (msg *TextMessage) SetType(msgtype gomatrix.MessageType) {
|
||||
msg.BaseMessage.SetType(msgtype)
|
||||
msg.cache = nil
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maunium.net/go/gomatrix"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
@ -242,7 +243,7 @@ func (view *RoomView) SetTyping(users []string) {
|
||||
for index, user := range users {
|
||||
member := view.Room.GetMember(user)
|
||||
if member != nil {
|
||||
users[index] = member.DisplayName
|
||||
users[index] = member.Displayname
|
||||
}
|
||||
}
|
||||
view.typing = users
|
||||
@ -255,14 +256,14 @@ type completion struct {
|
||||
|
||||
func (view *RoomView) autocompleteUser(existingText string) (completions []completion) {
|
||||
textWithoutPrefix := strings.TrimPrefix(existingText, "@")
|
||||
for _, user := range view.Room.GetMembers() {
|
||||
if user.DisplayName == textWithoutPrefix || user.UserID == existingText {
|
||||
for userID, user := range view.Room.GetMembers() {
|
||||
if user.Displayname == textWithoutPrefix || userID == existingText {
|
||||
// Exact match, return that.
|
||||
return []completion{{user.DisplayName, user.UserID}}
|
||||
return []completion{{user.Displayname, userID}}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(user.DisplayName, textWithoutPrefix) || strings.HasPrefix(user.UserID, existingText) {
|
||||
completions = append(completions, completion{user.DisplayName, user.UserID})
|
||||
if strings.HasPrefix(user.Displayname, textWithoutPrefix) || strings.HasPrefix(userID, existingText) {
|
||||
completions = append(completions, completion{user.Displayname, userID})
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -330,12 +331,12 @@ func (view *RoomView) MxRoom() *rooms.Room {
|
||||
func (view *RoomView) UpdateUserList() {
|
||||
var joined strings.Builder
|
||||
var invited strings.Builder
|
||||
for _, user := range view.Room.GetMembers() {
|
||||
for userID, user := range view.Room.GetMembers() {
|
||||
if user.Membership == "join" {
|
||||
joined.WriteString(widget.AddColor(user.DisplayName, widget.GetHashColorName(user.UserID)))
|
||||
joined.WriteString(widget.AddColor(user.Displayname, widget.GetHashColorName(userID)))
|
||||
joined.WriteRune('\n')
|
||||
} else if user.Membership == "invite" {
|
||||
invited.WriteString(widget.AddColor(user.DisplayName, widget.GetHashColorName(user.UserID)))
|
||||
invited.WriteString(widget.AddColor(user.Displayname, widget.GetHashColorName(userID)))
|
||||
invited.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
@ -346,26 +347,26 @@ func (view *RoomView) UpdateUserList() {
|
||||
}
|
||||
}
|
||||
|
||||
func (view *RoomView) newUIMessage(id, sender, msgtype, text string, timestamp time.Time) messages.UIMessage {
|
||||
func (view *RoomView) newUIMessage(id, sender string, msgtype gomatrix.MessageType, text string, timestamp time.Time) messages.UIMessage {
|
||||
member := view.Room.GetMember(sender)
|
||||
displayname := sender
|
||||
if member != nil {
|
||||
displayname = member.DisplayName
|
||||
displayname = member.Displayname
|
||||
}
|
||||
msg := messages.NewTextMessage(id, sender, displayname, msgtype, text, timestamp)
|
||||
return msg
|
||||
}
|
||||
|
||||
func (view *RoomView) NewMessage(id, sender, msgtype, text string, timestamp time.Time) ifc.Message {
|
||||
func (view *RoomView) NewMessage(id, sender string, msgtype gomatrix.MessageType, text string, timestamp time.Time) ifc.Message {
|
||||
return view.newUIMessage(id, sender, msgtype, text, timestamp)
|
||||
}
|
||||
|
||||
func (view *RoomView) NewTempMessage(msgtype, text string) ifc.Message {
|
||||
func (view *RoomView) NewTempMessage(msgtype gomatrix.MessageType, text string) ifc.Message {
|
||||
now := time.Now()
|
||||
id := strconv.FormatInt(now.UnixNano(), 10)
|
||||
sender := ""
|
||||
if ownerMember := view.Room.GetSessionOwner(); ownerMember != nil {
|
||||
sender = ownerMember.DisplayName
|
||||
if ownerMember := view.Room.GetMember(view.Room.GetSessionOwner()); ownerMember != nil {
|
||||
sender = ownerMember.Displayname
|
||||
}
|
||||
message := view.newUIMessage(id, sender, msgtype, text, now)
|
||||
message.SetState(ifc.MessageStateSending)
|
||||
|
@ -497,7 +497,7 @@ func (view *MainView) LoadHistory(room string) {
|
||||
}
|
||||
roomView.Room.PrevBatch = prevBatch
|
||||
for _, evt := range history {
|
||||
message := view.ParseEvent(roomView, &evt)
|
||||
message := view.ParseEvent(roomView, evt)
|
||||
if message != nil {
|
||||
roomView.AddMessage(message, ifc.PrependMessage)
|
||||
}
|
||||
|
2
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
2
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
@ -2,7 +2,7 @@ ISC License
|
||||
|
||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
|
187
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
187
vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
@ -16,7 +16,9 @@
|
||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build !js,!appengine,!safe,!disableunsafe
|
||||
// Go versions prior to 1.4 are disabled because they use a different layout
|
||||
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
||||
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
||||
|
||||
package spew
|
||||
|
||||
@ -34,80 +36,49 @@ const (
|
||||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||
)
|
||||
|
||||
var (
|
||||
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
|
||||
// internal reflect.Value fields. These values are valid before golang
|
||||
// commit ecccf07e7f9d which changed the format. The are also valid
|
||||
// after commit 82f48826c6c7 which changed the format again to mirror
|
||||
// the original format. Code in the init function updates these offsets
|
||||
// as necessary.
|
||||
offsetPtr = uintptr(ptrSize)
|
||||
offsetScalar = uintptr(0)
|
||||
offsetFlag = uintptr(ptrSize * 2)
|
||||
type flag uintptr
|
||||
|
||||
// flagKindWidth and flagKindShift indicate various bits that the
|
||||
// reflect package uses internally to track kind information.
|
||||
//
|
||||
// flagRO indicates whether or not the value field of a reflect.Value is
|
||||
// read-only.
|
||||
//
|
||||
// flagIndir indicates whether the value field of a reflect.Value is
|
||||
// the actual data or a pointer to the data.
|
||||
//
|
||||
// These values are valid before golang commit 90a7c3c86944 which
|
||||
// changed their positions. Code in the init function updates these
|
||||
// flags as necessary.
|
||||
flagKindWidth = uintptr(5)
|
||||
flagKindShift = uintptr(flagKindWidth - 1)
|
||||
flagRO = uintptr(1 << 0)
|
||||
flagIndir = uintptr(1 << 1)
|
||||
var (
|
||||
// flagRO indicates whether the value field of a reflect.Value
|
||||
// is read-only.
|
||||
flagRO flag
|
||||
|
||||
// flagAddr indicates whether the address of the reflect.Value's
|
||||
// value may be taken.
|
||||
flagAddr flag
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Older versions of reflect.Value stored small integers directly in the
|
||||
// ptr field (which is named val in the older versions). Versions
|
||||
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
|
||||
// scalar for this purpose which unfortunately came before the flag
|
||||
// field, so the offset of the flag field is different for those
|
||||
// versions.
|
||||
//
|
||||
// This code constructs a new reflect.Value from a known small integer
|
||||
// and checks if the size of the reflect.Value struct indicates it has
|
||||
// the scalar field. When it does, the offsets are updated accordingly.
|
||||
vv := reflect.ValueOf(0xf00)
|
||||
if unsafe.Sizeof(vv) == (ptrSize * 4) {
|
||||
offsetScalar = ptrSize * 2
|
||||
offsetFlag = ptrSize * 3
|
||||
}
|
||||
// flagKindMask holds the bits that make up the kind
|
||||
// part of the flags field. In all the supported versions,
|
||||
// it is in the lower 5 bits.
|
||||
const flagKindMask = flag(0x1f)
|
||||
|
||||
// Commit 90a7c3c86944 changed the flag positions such that the low
|
||||
// order bits are the kind. This code extracts the kind from the flags
|
||||
// field and ensures it's the correct type. When it's not, the flag
|
||||
// order has been changed to the newer format, so the flags are updated
|
||||
// accordingly.
|
||||
upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
|
||||
upfv := *(*uintptr)(upf)
|
||||
flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
|
||||
if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
|
||||
flagKindShift = 0
|
||||
flagRO = 1 << 5
|
||||
flagIndir = 1 << 6
|
||||
// Different versions of Go have used different
|
||||
// bit layouts for the flags type. This table
|
||||
// records the known combinations.
|
||||
var okFlags = []struct {
|
||||
ro, addr flag
|
||||
}{{
|
||||
// From Go 1.4 to 1.5
|
||||
ro: 1 << 5,
|
||||
addr: 1 << 7,
|
||||
}, {
|
||||
// Up to Go tip.
|
||||
ro: 1<<5 | 1<<6,
|
||||
addr: 1 << 8,
|
||||
}}
|
||||
|
||||
// Commit adf9b30e5594 modified the flags to separate the
|
||||
// flagRO flag into two bits which specifies whether or not the
|
||||
// field is embedded. This causes flagIndir to move over a bit
|
||||
// and means that flagRO is the combination of either of the
|
||||
// original flagRO bit and the new bit.
|
||||
//
|
||||
// This code detects the change by extracting what used to be
|
||||
// the indirect bit to ensure it's set. When it's not, the flag
|
||||
// order has been changed to the newer format, so the flags are
|
||||
// updated accordingly.
|
||||
if upfv&flagIndir == 0 {
|
||||
flagRO = 3 << 5
|
||||
flagIndir = 1 << 7
|
||||
}
|
||||
var flagValOffset = func() uintptr {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
return field.Offset
|
||||
}()
|
||||
|
||||
// flagField returns a pointer to the flag field of a reflect.Value.
|
||||
func flagField(v *reflect.Value) *flag {
|
||||
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
||||
}
|
||||
|
||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||
@ -119,34 +90,56 @@ func init() {
|
||||
// This allows us to check for implementations of the Stringer and error
|
||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||
// inaccessible values such as unexported struct fields.
|
||||
func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
|
||||
indirects := 1
|
||||
vt := v.Type()
|
||||
upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
|
||||
rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
|
||||
if rvf&flagIndir != 0 {
|
||||
vt = reflect.PtrTo(v.Type())
|
||||
indirects++
|
||||
} else if offsetScalar != 0 {
|
||||
// The value is in the scalar field when it's not one of the
|
||||
// reference types.
|
||||
switch vt.Kind() {
|
||||
case reflect.Uintptr:
|
||||
case reflect.Chan:
|
||||
case reflect.Func:
|
||||
case reflect.Map:
|
||||
case reflect.Ptr:
|
||||
case reflect.UnsafePointer:
|
||||
default:
|
||||
upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
|
||||
offsetScalar)
|
||||
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
||||
return v
|
||||
}
|
||||
flagFieldPtr := flagField(&v)
|
||||
*flagFieldPtr &^= flagRO
|
||||
*flagFieldPtr |= flagAddr
|
||||
return v
|
||||
}
|
||||
|
||||
// Sanity checks against future reflect package changes
|
||||
// to the type or semantics of the Value.flag field.
|
||||
func init() {
|
||||
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||
if !ok {
|
||||
panic("reflect.Value has no flag field")
|
||||
}
|
||||
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
||||
panic("reflect.Value flag field has changed kind")
|
||||
}
|
||||
type t0 int
|
||||
var t struct {
|
||||
A t0
|
||||
// t0 will have flagEmbedRO set.
|
||||
t0
|
||||
// a will have flagStickyRO set
|
||||
a t0
|
||||
}
|
||||
vA := reflect.ValueOf(t).FieldByName("A")
|
||||
va := reflect.ValueOf(t).FieldByName("a")
|
||||
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
||||
|
||||
// Infer flagRO from the difference between the flags
|
||||
// for the (otherwise identical) fields in t.
|
||||
flagPublic := *flagField(&vA)
|
||||
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
||||
flagRO = flagPublic ^ flagWithRO
|
||||
|
||||
// Infer flagAddr from the difference between a value
|
||||
// taken from a pointer and not.
|
||||
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
||||
flagNoPtr := *flagField(&vA)
|
||||
flagPtr := *flagField(&vPtrA)
|
||||
flagAddr = flagNoPtr ^ flagPtr
|
||||
|
||||
// Check that the inferred flags tally with one of the known versions.
|
||||
for _, f := range okFlags {
|
||||
if flagRO == f.ro && flagAddr == f.addr {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
pv := reflect.NewAt(vt, upv)
|
||||
rv = pv
|
||||
for i := 0; i < indirects; i++ {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
return rv
|
||||
panic("reflect.Value read-only flag has changed semantics")
|
||||
}
|
||||
|
2
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
@ -16,7 +16,7 @@
|
||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||
// tag is deprecated and thus should not be used.
|
||||
// +build js appengine safe disableunsafe
|
||||
// +build js appengine safe disableunsafe !go1.4
|
||||
|
||||
package spew
|
||||
|
||||
|
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
2
vendor/github.com/davecgh/go-spew/spew/common.go
generated
vendored
@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||
w.Write(closeParenBytes)
|
||||
}
|
||||
|
||||
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
|
||||
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
|
||||
// prefix to Writer w.
|
||||
func printHexPtr(w io.Writer, p uintptr) {
|
||||
// Null pointer.
|
||||
|
10
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
10
vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
@ -35,16 +35,16 @@ var (
|
||||
|
||||
// cCharRE is a regular expression that matches a cgo char.
|
||||
// It is used to detect character arrays to hexdump them.
|
||||
cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
|
||||
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
|
||||
|
||||
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||
// char. It is used to detect unsigned character arrays to hexdump
|
||||
// them.
|
||||
cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
|
||||
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
|
||||
|
||||
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||
// It is used to detect uint8_t arrays to hexdump them.
|
||||
cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
|
||||
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
|
||||
)
|
||||
|
||||
// dumpState contains information about the state of a dump operation.
|
||||
@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||
// Display dereferenced value.
|
||||
d.w.Write(openParenBytes)
|
||||
switch {
|
||||
case nilFound == true:
|
||||
case nilFound:
|
||||
d.w.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound == true:
|
||||
case cycleFound:
|
||||
d.w.Write(circularBytes)
|
||||
|
||||
default:
|
||||
|
4
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
4
vendor/github.com/davecgh/go-spew/spew/format.go
generated
vendored
@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) {
|
||||
|
||||
// Display dereferenced value.
|
||||
switch {
|
||||
case nilFound == true:
|
||||
case nilFound:
|
||||
f.fs.Write(nilAngleBytes)
|
||||
|
||||
case cycleFound == true:
|
||||
case cycleFound:
|
||||
f.fs.Write(circularShortBytes)
|
||||
|
||||
default:
|
||||
|
36
vendor/github.com/disintegration/imaging/effects.go
generated
vendored
36
vendor/github.com/disintegration/imaging/effects.go
generated
vendored
@ -38,9 +38,13 @@ func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
|
||||
|
||||
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 x := 0; x < src.w; x++ {
|
||||
for i, v := range scanLine {
|
||||
scanLineF[i] = float64(v)
|
||||
}
|
||||
for x, idx := 0, 0; x < src.w; x, idx = x+1, idx+4 {
|
||||
min := x - radius
|
||||
if min < 0 {
|
||||
min = 0
|
||||
@ -55,10 +59,10 @@ func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
|
||||
i := ix * 4
|
||||
weight := kernel[absint(x-ix)]
|
||||
wsum += weight
|
||||
wa := float64(scanLine[i+3]) * weight
|
||||
r += float64(scanLine[i+0]) * wa
|
||||
g += float64(scanLine[i+1]) * wa
|
||||
b += float64(scanLine[i+2]) * wa
|
||||
wa := scanLineF[i+3] * weight
|
||||
r += scanLineF[i+0] * wa
|
||||
g += scanLineF[i+1] * wa
|
||||
b += scanLineF[i+2] * wa
|
||||
a += wa
|
||||
}
|
||||
if a != 0 {
|
||||
@ -67,12 +71,12 @@ func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
|
||||
b /= a
|
||||
}
|
||||
|
||||
j := y*dst.Stride + x*4
|
||||
dst.Pix[j+0] = clamp(r)
|
||||
dst.Pix[j+1] = clamp(g)
|
||||
dst.Pix[j+2] = clamp(b)
|
||||
dst.Pix[j+3] = clamp(a / wsum)
|
||||
scanLine[idx+0] = clamp(r)
|
||||
scanLine[idx+1] = clamp(g)
|
||||
scanLine[idx+2] = clamp(b)
|
||||
scanLine[idx+3] = clamp(a / wsum)
|
||||
}
|
||||
copy(dst.Pix[y*dst.Stride:], scanLine)
|
||||
}
|
||||
})
|
||||
|
||||
@ -86,8 +90,12 @@ func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
|
||||
|
||||
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 {
|
||||
@ -103,10 +111,10 @@ func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
|
||||
i := iy * 4
|
||||
weight := kernel[absint(y-iy)]
|
||||
wsum += weight
|
||||
wa := float64(scanLine[i+3]) * weight
|
||||
r += float64(scanLine[i+0]) * wa
|
||||
g += float64(scanLine[i+1]) * wa
|
||||
b += float64(scanLine[i+2]) * wa
|
||||
wa := scanLineF[i+3] * weight
|
||||
r += scanLineF[i+0] * wa
|
||||
g += scanLineF[i+1] * wa
|
||||
b += scanLineF[i+2] * wa
|
||||
a += wa
|
||||
}
|
||||
if a != 0 {
|
||||
|
272
vendor/github.com/disintegration/imaging/helpers.go
generated
vendored
272
vendor/github.com/disintegration/imaging/helpers.go
generated
vendored
@ -1,272 +0,0 @@
|
||||
package imaging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/gif"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/image/bmp"
|
||||
"golang.org/x/image/tiff"
|
||||
)
|
||||
|
||||
// Format is an image file format.
|
||||
type Format int
|
||||
|
||||
// Image file formats.
|
||||
const (
|
||||
JPEG Format = iota
|
||||
PNG
|
||||
GIF
|
||||
TIFF
|
||||
BMP
|
||||
)
|
||||
|
||||
func (f Format) String() string {
|
||||
switch f {
|
||||
case JPEG:
|
||||
return "JPEG"
|
||||
case PNG:
|
||||
return "PNG"
|
||||
case GIF:
|
||||
return "GIF"
|
||||
case TIFF:
|
||||
return "TIFF"
|
||||
case BMP:
|
||||
return "BMP"
|
||||
default:
|
||||
return "Unsupported"
|
||||
}
|
||||
}
|
||||
|
||||
var formatFromExt = map[string]Format{
|
||||
".jpg": JPEG,
|
||||
".jpeg": JPEG,
|
||||
".png": PNG,
|
||||
".tif": TIFF,
|
||||
".tiff": TIFF,
|
||||
".bmp": BMP,
|
||||
".gif": GIF,
|
||||
}
|
||||
|
||||
// FormatFromFilename parses image format from filename extension:
|
||||
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
|
||||
func FormatFromFilename(filename string) (Format, error) {
|
||||
ext := strings.ToLower(filepath.Ext(filename))
|
||||
if f, ok := formatFromExt[ext]; ok {
|
||||
return f, nil
|
||||
}
|
||||
return -1, ErrUnsupportedFormat
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrUnsupportedFormat means the given image format (or file extension) is unsupported.
|
||||
ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
|
||||
)
|
||||
|
||||
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{}
|
||||
|
||||
// Decode reads an image from r.
|
||||
func Decode(r io.Reader) (image.Image, error) {
|
||||
img, _, err := image.Decode(r)
|
||||
return img, err
|
||||
}
|
||||
|
||||
// Open loads an image from file
|
||||
func Open(filename string) (image.Image, error) {
|
||||
file, err := fs.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
return Decode(file)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
var err error
|
||||
switch format {
|
||||
case JPEG:
|
||||
var rgba *image.RGBA
|
||||
if nrgba, ok := img.(*image.NRGBA); ok {
|
||||
if nrgba.Opaque() {
|
||||
rgba = &image.RGBA{
|
||||
Pix: nrgba.Pix,
|
||||
Stride: nrgba.Stride,
|
||||
Rect: nrgba.Rect,
|
||||
}
|
||||
}
|
||||
}
|
||||
if rgba != nil {
|
||||
err = jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality})
|
||||
} else {
|
||||
err = jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality})
|
||||
}
|
||||
|
||||
case PNG:
|
||||
enc := png.Encoder{CompressionLevel: cfg.pngCompressionLevel}
|
||||
err = enc.Encode(w, img)
|
||||
|
||||
case GIF:
|
||||
err = gif.Encode(w, img, &gif.Options{
|
||||
NumColors: cfg.gifNumColors,
|
||||
Quantizer: cfg.gifQuantizer,
|
||||
Drawer: cfg.gifDrawer,
|
||||
})
|
||||
|
||||
case TIFF:
|
||||
err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
|
||||
|
||||
case BMP:
|
||||
err = bmp.Encode(w, img)
|
||||
|
||||
default:
|
||||
err = ErrUnsupportedFormat
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
defer func() {
|
||||
cerr := file.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
return Encode(file, img, f, opts...)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
463
vendor/github.com/disintegration/imaging/io.go
generated
vendored
Normal file
463
vendor/github.com/disintegration/imaging/io.go
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
||||
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"
|
||||
)
|
||||
|
||||
// Format is an image file format.
|
||||
type Format int
|
||||
|
||||
// Image file formats.
|
||||
const (
|
||||
JPEG Format = iota
|
||||
PNG
|
||||
GIF
|
||||
TIFF
|
||||
BMP
|
||||
)
|
||||
|
||||
func (f Format) String() string {
|
||||
switch f {
|
||||
case JPEG:
|
||||
return "JPEG"
|
||||
case PNG:
|
||||
return "PNG"
|
||||
case GIF:
|
||||
return "GIF"
|
||||
case TIFF:
|
||||
return "TIFF"
|
||||
case BMP:
|
||||
return "BMP"
|
||||
default:
|
||||
return "Unsupported"
|
||||
}
|
||||
}
|
||||
|
||||
var formatFromExt = map[string]Format{
|
||||
"jpg": JPEG,
|
||||
"jpeg": JPEG,
|
||||
"png": PNG,
|
||||
"tif": TIFF,
|
||||
"tiff": TIFF,
|
||||
"bmp": BMP,
|
||||
"gif": GIF,
|
||||
}
|
||||
|
||||
// FormatFromExtension parses image format from extension:
|
||||
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.
|
||||
func FormatFromExtension(ext string) (Format, error) {
|
||||
if f, ok := formatFromExt[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok {
|
||||
return f, nil
|
||||
}
|
||||
return -1, ErrUnsupportedFormat
|
||||
}
|
||||
|
||||
// FormatFromFilename parses image format from filename extension:
|
||||
// "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)
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrUnsupportedFormat means the given image format (or file extension) is unsupported.
|
||||
ErrUnsupportedFormat = errors.New("imaging: unsupported image format")
|
||||
)
|
||||
|
||||
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...)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
var err error
|
||||
switch format {
|
||||
case JPEG:
|
||||
var rgba *image.RGBA
|
||||
if nrgba, ok := img.(*image.NRGBA); ok {
|
||||
if nrgba.Opaque() {
|
||||
rgba = &image.RGBA{
|
||||
Pix: nrgba.Pix,
|
||||
Stride: nrgba.Stride,
|
||||
Rect: nrgba.Rect,
|
||||
}
|
||||
}
|
||||
}
|
||||
if rgba != nil {
|
||||
err = jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality})
|
||||
} else {
|
||||
err = jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality})
|
||||
}
|
||||
|
||||
case PNG:
|
||||
enc := png.Encoder{CompressionLevel: cfg.pngCompressionLevel}
|
||||
err = enc.Encode(w, img)
|
||||
|
||||
case GIF:
|
||||
err = gif.Encode(w, img, &gif.Options{
|
||||
NumColors: cfg.gifNumColors,
|
||||
Quantizer: cfg.gifQuantizer,
|
||||
Drawer: cfg.gifDrawer,
|
||||
})
|
||||
|
||||
case TIFF:
|
||||
err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
|
||||
|
||||
case BMP:
|
||||
err = bmp.Encode(w, img)
|
||||
|
||||
default:
|
||||
err = ErrUnsupportedFormat
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
defer func() {
|
||||
cerr := file.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
return Encode(file, img, f, opts...)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
34
vendor/github.com/disintegration/imaging/tools.go
generated
vendored
34
vendor/github.com/disintegration/imaging/tools.go
generated
vendored
@ -1,10 +1,44 @@
|
||||
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
|
||||
|
||||
|
33
vendor/github.com/lucasb-eyer/go-colorful/README.md
generated
vendored
33
vendor/github.com/lucasb-eyer/go-colorful/README.md
generated
vendored
@ -124,17 +124,16 @@ Because a `colorful.Color` implements Go's `color.Color` interface (found in the
|
||||
`image/color` package), it can be used anywhere that expects a `color.Color`.
|
||||
|
||||
Furthermore, you can convert anything that implements the `color.Color` interface
|
||||
into a `colorful.Color` using the `MakeColorful` function:
|
||||
into a `colorful.Color` using the `MakeColor` function:
|
||||
|
||||
```go
|
||||
c := colorful.MakeColor(color.Gray16{12345})
|
||||
c, ok := colorful.MakeColor(color.Gray16{12345})
|
||||
```
|
||||
|
||||
**Caveat:** Be aware that for this latter conversion (using `MakeColor`) hits a corner-case
|
||||
when alpha is exactly zero. Because `color.Color` uses pre-multiplied alpha colors,
|
||||
this means the RGB values are lost and it's impossible to recover them. The current
|
||||
implementation `panic()`s in that case, see [issue 21](https://github.com/lucasb-eyer/go-colorful/issues/21)
|
||||
for discussion and suggesting alternatives.
|
||||
**Caveat:** Be aware that this latter conversion (using `MakeColor`) hits a
|
||||
corner-case when alpha is exactly zero. Because `color.Color` uses pre-multiplied
|
||||
alpha colors, this means the RGB values are lost (set to 0) and it's impossible
|
||||
to recover them. In such a case `MakeColor` will return `false` as its second value.
|
||||
|
||||
### Comparing colors
|
||||
In the RGB color space, the Euclidian distance between colors *doesn't* correspond
|
||||
@ -456,16 +455,26 @@ but that is outside the scope of this library.
|
||||
Thanks to [@ZirconiumX](https://github.com/ZirconiumX) for starting this investigation,
|
||||
see [issue #18](https://github.com/lucasb-eyer/go-colorful/issues/18) for details.
|
||||
|
||||
### Q: `MakeColor` panics when alpha is zero!
|
||||
A: Because in that case, the conversion is undefined. See
|
||||
[issue 21](https://github.com/lucasb-eyer/go-colorful/issues/21)
|
||||
as well as the short caveat discussion in the ["The `color.Color` interface"](README.md#the-colorcolor-interface) section above.
|
||||
### Q: Why would `MakeColor` ever fail!?
|
||||
A: `MakeColor` fails when the alpha channel is zero. In that case, the
|
||||
conversion is undefined. See [issue 21](https://github.com/lucasb-eyer/go-colorful/issues/21)
|
||||
as well as the short caveat note in the ["The `color.Color` interface"](README.md#the-colorcolor-interface)
|
||||
section above.
|
||||
|
||||
Who?
|
||||
====
|
||||
|
||||
This library has been developed by Lucas Beyer with contributions from
|
||||
Bastien Dejean (@baskerville) and Phil Kulak (@pkulak).
|
||||
Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli).
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
### Version 1.0
|
||||
- API Breaking change in `MakeColor`: instead of `panic`ing when alpha is zero, it now returns a secondary, boolean return value indicating success. See [the color.Color interface](https://github.com/lucasb-eyer/go-colorful#the-colorcolor-interface) section and [this FAQ entry](https://github.com/lucasb-eyer/go-colorful#q-why-would-makecolor-ever-fail) for details.
|
||||
|
||||
### Version 0.9
|
||||
- Initial version number after having ignored versioning for a long time :)
|
||||
|
||||
License: MIT
|
||||
============
|
||||
|
7
vendor/github.com/lucasb-eyer/go-colorful/colors.go
generated
vendored
7
vendor/github.com/lucasb-eyer/go-colorful/colors.go
generated
vendored
@ -22,8 +22,11 @@ func (col Color) RGBA() (r, g, b, a uint32) {
|
||||
}
|
||||
|
||||
// Constructs a colorful.Color from something implementing color.Color
|
||||
func MakeColor(col color.Color) Color {
|
||||
func MakeColor(col color.Color) (Color, bool) {
|
||||
r, g, b, a := col.RGBA()
|
||||
if a == 0 {
|
||||
return Color{0, 0, 0}, false
|
||||
}
|
||||
|
||||
// Since color.Color is alpha pre-multiplied, we need to divide the
|
||||
// RGB values by alpha again in order to get back the original RGB.
|
||||
@ -34,7 +37,7 @@ func MakeColor(col color.Color) Color {
|
||||
b *= 0xffff
|
||||
b /= a
|
||||
|
||||
return Color{float64(r) / 65535.0, float64(g) / 65535.0, float64(b) / 65535.0}
|
||||
return Color{float64(r) / 65535.0, float64(g) / 65535.0, float64(b) / 65535.0}, true
|
||||
}
|
||||
|
||||
// Might come in handy sometimes to reduce boilerplate code.
|
||||
|
14
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
14
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
@ -1,13 +1,24 @@
|
||||
package runewidth
|
||||
|
||||
import "os"
|
||||
|
||||
var (
|
||||
// EastAsianWidth will be set true if the current locale is CJK
|
||||
EastAsianWidth = IsEastAsian()
|
||||
EastAsianWidth bool
|
||||
|
||||
// DefaultCondition is a condition in current locale
|
||||
DefaultCondition = &Condition{EastAsianWidth}
|
||||
)
|
||||
|
||||
func init() {
|
||||
env := os.Getenv("RUNEWIDTH_EASTASIAN")
|
||||
if env == "" {
|
||||
EastAsianWidth = IsEastAsian()
|
||||
} else {
|
||||
EastAsianWidth = env == "1"
|
||||
}
|
||||
}
|
||||
|
||||
type interval struct {
|
||||
first rune
|
||||
last rune
|
||||
@ -55,6 +66,7 @@ var private = table{
|
||||
var nonprint = table{
|
||||
{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
|
||||
{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
|
||||
{0x2028, 0x2029},
|
||||
{0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
|
||||
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
|
||||
}
|
||||
|
2
vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
2
vendor/github.com/renstrom/fuzzysearch/LICENSE
generated
vendored
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Peter Renström
|
||||
Copyright (c) 2018 Peter Lithammer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
5
vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
5
vendor/github.com/renstrom/fuzzysearch/fuzzy/fuzzy.go
generated
vendored
@ -112,10 +112,7 @@ Outer:
|
||||
}
|
||||
|
||||
// Count up remaining char
|
||||
for len(target) > 0 {
|
||||
target = target[utf8.RuneLen(rune(target[0])):]
|
||||
runeDiff++
|
||||
}
|
||||
runeDiff += utf8.RuneCountInString(target)
|
||||
|
||||
return runeDiff
|
||||
}
|
||||
|
139
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
139
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
@ -13,6 +13,9 @@ import (
|
||||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Condition(t, comp, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -23,11 +26,17 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo
|
||||
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -37,6 +46,9 @@ func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -45,6 +57,9 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string
|
||||
//
|
||||
// assert.Emptyf(t, obj, "error message %s", "formatted")
|
||||
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Empty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -56,6 +71,9 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -65,6 +83,9 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
|
||||
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -73,6 +94,9 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
|
||||
//
|
||||
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -83,6 +107,9 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -90,16 +117,25 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
||||
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -107,31 +143,43 @@ func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}
|
||||
//
|
||||
// assert.Falsef(t, myBool, "error message %s", "formatted")
|
||||
func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return False(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -141,6 +189,9 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -150,6 +201,9 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -159,6 +213,9 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -166,6 +223,9 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin
|
||||
//
|
||||
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -173,31 +233,49 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms
|
||||
//
|
||||
// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -205,6 +283,9 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin
|
||||
//
|
||||
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -213,6 +294,9 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
|
||||
//
|
||||
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
|
||||
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -220,6 +304,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
|
||||
//
|
||||
// assert.Nilf(t, err, "error message %s", "formatted")
|
||||
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -230,6 +317,9 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoError(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -240,6 +330,9 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -250,6 +343,9 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -260,6 +356,9 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{})
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -267,6 +366,9 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
|
||||
//
|
||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -274,6 +376,9 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bo
|
||||
//
|
||||
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -282,6 +387,9 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo
|
||||
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -290,11 +398,17 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
|
||||
//
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -302,6 +416,9 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -310,6 +427,9 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool
|
||||
//
|
||||
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -318,6 +438,9 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
|
||||
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -326,6 +449,9 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
|
||||
//
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -333,6 +459,9 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args
|
||||
//
|
||||
// assert.Truef(t, myBool, "error message %s", "formatted")
|
||||
func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return True(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
@ -340,10 +469,16 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
1
vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
generated
vendored
1
vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
generated
vendored
@ -1,4 +1,5 @@
|
||||
{{.CommentFormat}}
|
||||
func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
|
||||
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||
return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
|
||||
}
|
||||
|
278
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
278
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
@ -13,11 +13,17 @@ import (
|
||||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Condition(a.t, comp, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Conditionf(a.t, comp, msg, args...)
|
||||
}
|
||||
|
||||
@ -28,6 +34,9 @@ func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}
|
||||
// a.Contains(["Hello", "World"], "World")
|
||||
// a.Contains({"Hello": "World"}, "Hello")
|
||||
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Contains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -38,16 +47,25 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ..
|
||||
// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Containsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
@ -57,6 +75,9 @@ func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bo
|
||||
//
|
||||
// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatch(a.t, listA, listB, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -66,6 +87,9 @@ func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndA
|
||||
//
|
||||
// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatchf(a.t, listA, listB, msg, args...)
|
||||
}
|
||||
|
||||
@ -74,6 +98,9 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st
|
||||
//
|
||||
// a.Empty(obj)
|
||||
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Empty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -82,6 +109,9 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// a.Emptyf(obj, "error message %s", "formatted")
|
||||
func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Emptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -93,6 +123,9 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{})
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equal(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -102,6 +135,9 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualError(err, expectedErrorString)
|
||||
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualError(a.t, theError, errString, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -111,6 +147,9 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...
|
||||
// actualObj, err := SomeFunction()
|
||||
// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
|
||||
func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualErrorf(a.t, theError, errString, msg, args...)
|
||||
}
|
||||
|
||||
@ -119,6 +158,9 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a
|
||||
//
|
||||
// a.EqualValues(uint32(123), int32(123))
|
||||
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -127,6 +169,9 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
||||
//
|
||||
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValuesf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
@ -138,6 +183,9 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equalf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
@ -148,6 +196,9 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Error(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -158,6 +209,9 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Errorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
@ -165,6 +219,9 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// a.Exactly(int32(123), int64(123))
|
||||
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactly(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -172,26 +229,41 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg
|
||||
//
|
||||
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
||||
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactlyf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
// Fail reports a failure through
|
||||
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Fail(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNow fails test
|
||||
func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNow(a.t, failureMessage, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNowf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Failf(a.t, failureMessage, msg, args...)
|
||||
}
|
||||
|
||||
@ -199,6 +271,9 @@ func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{
|
||||
//
|
||||
// a.False(myBool)
|
||||
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return False(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -206,56 +281,77 @@ func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// a.Falsef(myBool, "error message %s", "formatted")
|
||||
func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Falsef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExists(a.t, path, msgAndArgs...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExistsf(a.t, path, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
|
||||
}
|
||||
|
||||
@ -265,6 +361,9 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -274,6 +373,9 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
@ -283,6 +385,9 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -292,6 +397,9 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
@ -301,6 +409,9 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -310,6 +421,9 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
|
||||
}
|
||||
|
||||
@ -317,6 +431,9 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s
|
||||
//
|
||||
// a.Implements((*MyInterface)(nil), new(MyObject))
|
||||
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -324,6 +441,9 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{},
|
||||
//
|
||||
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implementsf(a.t, interfaceObject, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -331,26 +451,41 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}
|
||||
//
|
||||
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
||||
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDelta(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
@ -358,36 +493,57 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del
|
||||
//
|
||||
// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsType(a.t, expectedType, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsTypef(a.t, expectedType, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -395,6 +551,9 @@ func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg s
|
||||
//
|
||||
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEq(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -402,6 +561,9 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf
|
||||
//
|
||||
// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEqf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
@ -410,6 +572,9 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
|
||||
//
|
||||
// a.Len(mySlice, 3)
|
||||
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Len(a.t, object, length, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -418,6 +583,9 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface
|
||||
//
|
||||
// a.Lenf(mySlice, 3, "error message %s", "formatted")
|
||||
func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Lenf(a.t, object, length, msg, args...)
|
||||
}
|
||||
|
||||
@ -425,6 +593,9 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in
|
||||
//
|
||||
// a.Nil(err)
|
||||
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -432,6 +603,9 @@ func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// a.Nilf(err, "error message %s", "formatted")
|
||||
func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -442,6 +616,9 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) b
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoError(a.t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -452,6 +629,9 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoErrorf(a.t, err, msg, args...)
|
||||
}
|
||||
|
||||
@ -462,6 +642,9 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
|
||||
// a.NotContains(["Hello", "World"], "Earth")
|
||||
// a.NotContains({"Hello": "World"}, "Earth")
|
||||
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContains(a.t, s, contains, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -472,6 +655,9 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs
|
||||
// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContainsf(a.t, s, contains, msg, args...)
|
||||
}
|
||||
|
||||
@ -482,6 +668,9 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmpty(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -492,6 +681,9 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmptyf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -502,6 +694,9 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -512,6 +707,9 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqualf(a.t, expected, actual, msg, args...)
|
||||
}
|
||||
|
||||
@ -519,6 +717,9 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str
|
||||
//
|
||||
// a.NotNil(err)
|
||||
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNil(a.t, object, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -526,6 +727,9 @@ func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool
|
||||
//
|
||||
// a.NotNilf(err, "error message %s", "formatted")
|
||||
func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNilf(a.t, object, msg, args...)
|
||||
}
|
||||
|
||||
@ -533,6 +737,9 @@ func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}
|
||||
//
|
||||
// a.NotPanics(func(){ RemainCalm() })
|
||||
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -540,6 +747,9 @@ func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool
|
||||
//
|
||||
// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
@ -548,6 +758,9 @@ func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}
|
||||
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
||||
// a.NotRegexp("^start", "it's not starting")
|
||||
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -556,6 +769,9 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
||||
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
@ -564,6 +780,9 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg
|
||||
//
|
||||
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -572,16 +791,25 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
|
||||
//
|
||||
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
||||
@ -589,6 +817,9 @@ func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bo
|
||||
//
|
||||
// a.Panics(func(){ GoCrazy() })
|
||||
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panics(a.t, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -597,6 +828,9 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
|
||||
func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValue(a.t, expected, f, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -605,6 +839,9 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgA
|
||||
//
|
||||
// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValuef(a.t, expected, f, msg, args...)
|
||||
}
|
||||
|
||||
@ -612,6 +849,9 @@ func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg
|
||||
//
|
||||
// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panicsf(a.t, f, msg, args...)
|
||||
}
|
||||
|
||||
@ -620,6 +860,9 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b
|
||||
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||
// a.Regexp("start...$", "it's not starting")
|
||||
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexp(a.t, rx, str, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -628,6 +871,9 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
||||
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexpf(a.t, rx, str, msg, args...)
|
||||
}
|
||||
|
||||
@ -636,6 +882,9 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
|
||||
//
|
||||
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subset(a.t, list, subset, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -644,6 +893,9 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
|
||||
//
|
||||
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subsetf(a.t, list, subset, msg, args...)
|
||||
}
|
||||
|
||||
@ -651,6 +903,9 @@ func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, a
|
||||
//
|
||||
// a.True(myBool)
|
||||
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return True(a.t, value, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -658,6 +913,9 @@ func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// a.Truef(myBool, "error message %s", "formatted")
|
||||
func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Truef(a.t, value, msg, args...)
|
||||
}
|
||||
|
||||
@ -665,6 +923,9 @@ func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
|
||||
//
|
||||
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
|
||||
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
||||
}
|
||||
|
||||
@ -672,15 +933,24 @@ func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta
|
||||
//
|
||||
// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||
}
|
||||
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zero(a.t, i, msgAndArgs...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := a.t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zerof(a.t, i, msg, args...)
|
||||
}
|
||||
|
1
vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
1
vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
@ -1,4 +1,5 @@
|
||||
{{.CommentWithoutT "a"}}
|
||||
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
|
||||
if h, ok := a.t.(tHelper); ok { h.Helper() }
|
||||
return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
|
||||
}
|
||||
|
216
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
216
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@ -27,6 +27,22 @@ type TestingT interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||
// for table driven tests.
|
||||
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
|
||||
|
||||
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||
// for table driven tests.
|
||||
type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
|
||||
|
||||
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||
// for table driven tests.
|
||||
type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
|
||||
|
||||
// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||
// for table driven tests.
|
||||
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
||||
|
||||
// Comparison a custom function that returns true on success and false on failure
|
||||
type Comparison func() (success bool)
|
||||
|
||||
@ -38,21 +54,23 @@ type Comparison func() (success bool)
|
||||
//
|
||||
// This function does no assertion of any kind.
|
||||
func ObjectsAreEqual(expected, actual interface{}) bool {
|
||||
|
||||
if expected == nil || actual == nil {
|
||||
return expected == actual
|
||||
}
|
||||
if exp, ok := expected.([]byte); ok {
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
} else if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
|
||||
exp, ok := expected.([]byte)
|
||||
if !ok {
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
}
|
||||
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
|
||||
// ObjectsAreEqualValues gets whether two objects are equal, or if their
|
||||
@ -156,21 +174,6 @@ func isTest(name, prefix string) bool {
|
||||
return !unicode.IsLower(rune)
|
||||
}
|
||||
|
||||
// getWhitespaceString returns a string that is long enough to overwrite the default
|
||||
// output from the go testing framework.
|
||||
func getWhitespaceString() string {
|
||||
|
||||
_, file, line, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
parts := strings.Split(file, "/")
|
||||
file = parts[len(parts)-1]
|
||||
|
||||
return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
|
||||
|
||||
}
|
||||
|
||||
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||
if len(msgAndArgs) == 0 || msgAndArgs == nil {
|
||||
return ""
|
||||
@ -195,7 +198,7 @@ func indentMessageLines(message string, longestLabelLen int) string {
|
||||
// no need to align first line because it starts at the correct location (after the label)
|
||||
if i != 0 {
|
||||
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
|
||||
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
}
|
||||
outBuf.WriteString(scanner.Text())
|
||||
}
|
||||
@ -209,6 +212,9 @@ type failNower interface {
|
||||
|
||||
// FailNow fails test
|
||||
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Fail(t, failureMessage, msgAndArgs...)
|
||||
|
||||
// We cannot extend TestingT with FailNow() and
|
||||
@ -227,8 +233,11 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
|
||||
|
||||
// Fail reports a failure through
|
||||
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
content := []labeledContent{
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")},
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
|
||||
{"Error", failureMessage},
|
||||
}
|
||||
|
||||
@ -244,7 +253,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
content = append(content, labeledContent{"Messages", message})
|
||||
}
|
||||
|
||||
t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...))
|
||||
t.Errorf("\n%s", ""+labeledOutput(content...))
|
||||
|
||||
return false
|
||||
}
|
||||
@ -256,7 +265,7 @@ type labeledContent struct {
|
||||
|
||||
// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
|
||||
//
|
||||
// \r\t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
// \t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
//
|
||||
// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
|
||||
// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
|
||||
@ -272,7 +281,7 @@ func labeledOutput(content ...labeledContent) string {
|
||||
}
|
||||
var output string
|
||||
for _, v := range content {
|
||||
output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
}
|
||||
return output
|
||||
}
|
||||
@ -281,6 +290,9 @@ func labeledOutput(content ...labeledContent) string {
|
||||
//
|
||||
// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
|
||||
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||
|
||||
if object == nil {
|
||||
@ -295,6 +307,9 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
|
||||
return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
|
||||
@ -311,6 +326,9 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
@ -349,6 +367,9 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
||||
//
|
||||
// assert.EqualValues(t, uint32(123), int32(123))
|
||||
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqualValues(expected, actual) {
|
||||
diff := diff(expected, actual)
|
||||
@ -366,12 +387,15 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
|
||||
//
|
||||
// assert.Exactly(t, int32(123), int64(123))
|
||||
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
aType := reflect.TypeOf(expected)
|
||||
bType := reflect.TypeOf(actual)
|
||||
|
||||
if aType != bType {
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
||||
}
|
||||
|
||||
return Equal(t, expected, actual, msgAndArgs...)
|
||||
@ -382,6 +406,9 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||
//
|
||||
// assert.NotNil(t, err)
|
||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !isNil(object) {
|
||||
return true
|
||||
}
|
||||
@ -407,6 +434,9 @@ func isNil(object interface{}) bool {
|
||||
//
|
||||
// assert.Nil(t, err)
|
||||
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isNil(object) {
|
||||
return true
|
||||
}
|
||||
@ -446,6 +476,9 @@ func isEmpty(object interface{}) bool {
|
||||
//
|
||||
// assert.Empty(t, obj)
|
||||
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := isEmpty(object)
|
||||
if !pass {
|
||||
@ -463,6 +496,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := !isEmpty(object)
|
||||
if !pass {
|
||||
@ -490,6 +526,9 @@ func getLen(x interface{}) (ok bool, length int) {
|
||||
//
|
||||
// assert.Len(t, mySlice, 3)
|
||||
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ok, l := getLen(object)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
|
||||
@ -505,6 +544,14 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
||||
//
|
||||
// assert.True(t, myBool)
|
||||
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if h, ok := t.(interface {
|
||||
Helper()
|
||||
}); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != true {
|
||||
return Fail(t, "Should be true", msgAndArgs...)
|
||||
@ -518,6 +565,9 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// assert.False(t, myBool)
|
||||
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != false {
|
||||
return Fail(t, "Should be false", msgAndArgs...)
|
||||
@ -534,6 +584,9 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
@ -592,6 +645,9 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||
// assert.Contains(t, ["Hello", "World"], "World")
|
||||
// assert.Contains(t, {"Hello": "World"}, "Hello")
|
||||
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
@ -612,6 +668,9 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
||||
// assert.NotContains(t, ["Hello", "World"], "Earth")
|
||||
// assert.NotContains(t, {"Hello": "World"}, "Earth")
|
||||
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
@ -630,6 +689,9 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
||||
//
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return true // we consider nil to be equal to the nil set
|
||||
}
|
||||
@ -671,6 +733,9 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
||||
//
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...)
|
||||
}
|
||||
@ -713,6 +778,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
||||
//
|
||||
// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isEmpty(listA) && isEmpty(listB) {
|
||||
return true
|
||||
}
|
||||
@ -763,6 +831,9 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
|
||||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
result := comp()
|
||||
if !result {
|
||||
Fail(t, "Condition failed!", msgAndArgs...)
|
||||
@ -800,9 +871,12 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
|
||||
//
|
||||
// assert.Panics(t, func(){ GoCrazy() })
|
||||
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
@ -813,13 +887,16 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
|
||||
func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
funcDidPanic, panicValue := didPanic(f)
|
||||
if !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
if panicValue != expected {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
@ -829,9 +906,12 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr
|
||||
//
|
||||
// assert.NotPanics(t, func(){ RemainCalm() })
|
||||
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
@ -841,6 +921,9 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
|
||||
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
dt := expected.Sub(actual)
|
||||
if dt < -delta || dt > delta {
|
||||
@ -890,6 +973,9 @@ func toFloat(x interface{}) (float64, bool) {
|
||||
//
|
||||
// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
|
||||
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
af, aok := toFloat(expected)
|
||||
bf, bok := toFloat(actual)
|
||||
@ -916,6 +1002,9 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
|
||||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
@ -937,6 +1026,9 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
||||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Map ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Map {
|
||||
@ -994,6 +1086,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||
if err != nil {
|
||||
return Fail(t, err.Error(), msgAndArgs...)
|
||||
@ -1008,6 +1103,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
||||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
@ -1038,6 +1136,9 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err != nil {
|
||||
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
|
||||
}
|
||||
@ -1052,6 +1153,9 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return Fail(t, "An error is expected but got nil.", msgAndArgs...)
|
||||
@ -1066,6 +1170,9 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualError(t, err, expectedErrorString)
|
||||
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !Error(t, theError, msgAndArgs...) {
|
||||
return false
|
||||
}
|
||||
@ -1099,6 +1206,9 @@ func matchRegexp(rx interface{}, str interface{}) bool {
|
||||
// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
|
||||
// assert.Regexp(t, "start...$", "it's not starting")
|
||||
func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
@ -1114,6 +1224,9 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface
|
||||
// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
|
||||
// assert.NotRegexp(t, "^start", "it's not starting")
|
||||
func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
if match {
|
||||
@ -1126,6 +1239,9 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
|
||||
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
@ -1134,6 +1250,9 @@ func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
@ -1142,6 +1261,9 @@ func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@ -1157,6 +1279,9 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@ -1174,6 +1299,9 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
//
|
||||
// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
var expectedJSONAsInterface, actualJSONAsInterface interface{}
|
||||
|
||||
if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
|
||||
@ -1212,12 +1340,18 @@ func diff(expected interface{}, actual interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
|
||||
return ""
|
||||
}
|
||||
|
||||
e := spewConfig.Sdump(expected)
|
||||
a := spewConfig.Sdump(actual)
|
||||
var e, a string
|
||||
if ek != reflect.String {
|
||||
e = spewConfig.Sdump(expected)
|
||||
a = spewConfig.Sdump(actual)
|
||||
} else {
|
||||
e = expected.(string)
|
||||
a = actual.(string)
|
||||
}
|
||||
|
||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||
A: difflib.SplitLines(e),
|
||||
@ -1254,3 +1388,7 @@ var spewConfig = spew.ConfigState{
|
||||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
22
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
22
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
@ -12,10 +12,11 @@ import (
|
||||
// an error if building a new request fails.
|
||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||
w := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
req.URL.RawQuery = values.Encode()
|
||||
handler(w, req)
|
||||
return w.Code, nil
|
||||
}
|
||||
@ -26,6 +27,9 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
@ -46,6 +50,9 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
@ -66,6 +73,9 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
@ -95,10 +105,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s
|
||||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
@ -112,10 +125,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
|
4
vendor/github.com/zyedidia/clipboard/LICENSE
generated
vendored
4
vendor/github.com/zyedidia/clipboard/LICENSE
generated
vendored
@ -1,3 +1,7 @@
|
||||
Copyright (c) 2018 Zachary Yedidia. Modifications to atotto/clipboard.
|
||||
|
||||
Original license:
|
||||
|
||||
Copyright (c) 2013 Ato Araki. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
4
vendor/github.com/zyedidia/clipboard/README.md
generated
vendored
4
vendor/github.com/zyedidia/clipboard/README.md
generated
vendored
@ -1,3 +1,7 @@
|
||||
# This is a fork of atotto/clipboard
|
||||
|
||||
This fork is used for `zyedidia/micro` and has some modifications, namely: support for the primary clipboard on linux and support for an internal clipboard if the system clipboard is not available.
|
||||
|
||||
[![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard) [![Build Status](https://drone.io/github.com/atotto/clipboard/status.png)](https://drone.io/github.com/atotto/clipboard/latest)
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard)
|
||||
|
122
vendor/golang.org/x/image/bmp/writer.go
generated
vendored
122
vendor/golang.org/x/image/bmp/writer.go
generated
vendored
@ -49,20 +49,91 @@ func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
|
||||
func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
|
||||
buf := make([]byte, step)
|
||||
for y := dy - 1; y >= 0; y-- {
|
||||
min := y*stride + 0
|
||||
max := y*stride + dx*4
|
||||
off := 0
|
||||
for i := min; i < max; i += 4 {
|
||||
buf[off+2] = pix[i+0]
|
||||
buf[off+1] = pix[i+1]
|
||||
buf[off+0] = pix[i+2]
|
||||
off += 3
|
||||
if opaque {
|
||||
for y := dy - 1; y >= 0; y-- {
|
||||
min := y*stride + 0
|
||||
max := y*stride + dx*4
|
||||
off := 0
|
||||
for i := min; i < max; i += 4 {
|
||||
buf[off+2] = pix[i+0]
|
||||
buf[off+1] = pix[i+1]
|
||||
buf[off+0] = pix[i+2]
|
||||
off += 3
|
||||
}
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for y := dy - 1; y >= 0; y-- {
|
||||
min := y*stride + 0
|
||||
max := y*stride + dx*4
|
||||
off := 0
|
||||
for i := min; i < max; i += 4 {
|
||||
a := uint32(pix[i+3])
|
||||
if a == 0 {
|
||||
buf[off+2] = 0
|
||||
buf[off+1] = 0
|
||||
buf[off+0] = 0
|
||||
buf[off+3] = 0
|
||||
off += 4
|
||||
continue
|
||||
} else if a == 0xff {
|
||||
buf[off+2] = pix[i+0]
|
||||
buf[off+1] = pix[i+1]
|
||||
buf[off+0] = pix[i+2]
|
||||
buf[off+3] = 0xff
|
||||
off += 4
|
||||
continue
|
||||
}
|
||||
buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8)
|
||||
buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8)
|
||||
buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8)
|
||||
buf[off+3] = uint8(a)
|
||||
off += 4
|
||||
}
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
|
||||
buf := make([]byte, step)
|
||||
if opaque {
|
||||
for y := dy - 1; y >= 0; y-- {
|
||||
min := y*stride + 0
|
||||
max := y*stride + dx*4
|
||||
off := 0
|
||||
for i := min; i < max; i += 4 {
|
||||
buf[off+2] = pix[i+0]
|
||||
buf[off+1] = pix[i+1]
|
||||
buf[off+0] = pix[i+2]
|
||||
off += 3
|
||||
}
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for y := dy - 1; y >= 0; y-- {
|
||||
min := y*stride + 0
|
||||
max := y*stride + dx*4
|
||||
off := 0
|
||||
for i := min; i < max; i += 4 {
|
||||
buf[off+2] = pix[i+0]
|
||||
buf[off+1] = pix[i+1]
|
||||
buf[off+0] = pix[i+2]
|
||||
buf[off+3] = pix[i+3]
|
||||
off += 4
|
||||
}
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -105,6 +176,7 @@ func Encode(w io.Writer, m image.Image) error {
|
||||
|
||||
var step int
|
||||
var palette []byte
|
||||
var opaque bool
|
||||
switch m := m.(type) {
|
||||
case *image.Gray:
|
||||
step = (d.X + 3) &^ 3
|
||||
@ -134,6 +206,28 @@ func Encode(w io.Writer, m image.Image) error {
|
||||
h.fileSize += uint32(len(palette)) + h.imageSize
|
||||
h.pixOffset += uint32(len(palette))
|
||||
h.bpp = 8
|
||||
case *image.RGBA:
|
||||
opaque = m.Opaque()
|
||||
if opaque {
|
||||
step = (3*d.X + 3) &^ 3
|
||||
h.bpp = 24
|
||||
} else {
|
||||
step = 4 * d.X
|
||||
h.bpp = 32
|
||||
}
|
||||
h.imageSize = uint32(d.Y * step)
|
||||
h.fileSize += h.imageSize
|
||||
case *image.NRGBA:
|
||||
opaque = m.Opaque()
|
||||
if opaque {
|
||||
step = (3*d.X + 3) &^ 3
|
||||
h.bpp = 24
|
||||
} else {
|
||||
step = 4 * d.X
|
||||
h.bpp = 32
|
||||
}
|
||||
h.imageSize = uint32(d.Y * step)
|
||||
h.fileSize += h.imageSize
|
||||
default:
|
||||
step = (3*d.X + 3) &^ 3
|
||||
h.imageSize = uint32(d.Y * step)
|
||||
@ -160,7 +254,9 @@ func Encode(w io.Writer, m image.Image) error {
|
||||
case *image.Paletted:
|
||||
return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
|
||||
case *image.RGBA:
|
||||
return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
|
||||
return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
|
||||
case *image.NRGBA:
|
||||
return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
|
||||
}
|
||||
return encode(w, m, step)
|
||||
}
|
||||
|
103
vendor/golang.org/x/net/html/parse.go
generated
vendored
103
vendor/golang.org/x/net/html/parse.go
generated
vendored
@ -209,27 +209,6 @@ loop:
|
||||
p.oe = p.oe[:i+1]
|
||||
}
|
||||
|
||||
// generateAllImpliedEndTags pops nodes off the stack of open elements as long as
|
||||
// the top node has a tag name of caption, colgroup, dd, div, dt, li, optgroup, option, p, rb,
|
||||
// rp, rt, rtc, span, tbody, td, tfoot, th, thead or tr.
|
||||
func (p *parser) generateAllImpliedEndTags() {
|
||||
var i int
|
||||
for i = len(p.oe) - 1; i >= 0; i-- {
|
||||
n := p.oe[i]
|
||||
if n.Type == ElementNode {
|
||||
switch n.DataAtom {
|
||||
// TODO: remove this divergence from the HTML5 spec
|
||||
case a.Caption, a.Colgroup, a.Dd, a.Div, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb,
|
||||
a.Rp, a.Rt, a.Rtc, a.Span, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
p.oe = p.oe[:i+1]
|
||||
}
|
||||
|
||||
// addChild adds a child node n to the top element, and pushes n onto the stack
|
||||
// of open elements if it is an element node.
|
||||
func (p *parser) addChild(n *Node) {
|
||||
@ -276,7 +255,7 @@ func (p *parser) fosterParent(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
if template != nil && (table == nil || j < i) {
|
||||
if template != nil && (table == nil || j > i) {
|
||||
template.AppendChild(n)
|
||||
return
|
||||
}
|
||||
@ -679,11 +658,16 @@ func inHeadIM(p *parser) bool {
|
||||
if !p.oe.contains(a.Template) {
|
||||
return true
|
||||
}
|
||||
p.generateAllImpliedEndTags()
|
||||
if n := p.oe.top(); n.DataAtom != a.Template {
|
||||
return true
|
||||
// TODO: remove this divergence from the HTML5 spec.
|
||||
//
|
||||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
|
||||
p.generateImpliedEndTags()
|
||||
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||
if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
|
||||
p.oe = p.oe[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
p.popUntil(defaultScope, a.Template)
|
||||
p.clearActiveFormattingElements()
|
||||
p.templateStack.pop()
|
||||
p.resetInsertionMode()
|
||||
@ -860,9 +844,13 @@ func inBodyIM(p *parser) bool {
|
||||
// The newline, if any, will be dealt with by the TextToken case.
|
||||
p.framesetOK = false
|
||||
case a.Form:
|
||||
if p.oe.contains(a.Template) || p.form == nil {
|
||||
p.popUntil(buttonScope, a.P)
|
||||
p.addElement()
|
||||
if p.form != nil && !p.oe.contains(a.Template) {
|
||||
// Ignore the token
|
||||
return true
|
||||
}
|
||||
p.popUntil(buttonScope, a.P)
|
||||
p.addElement()
|
||||
if !p.oe.contains(a.Template) {
|
||||
p.form = p.top()
|
||||
}
|
||||
case a.Li:
|
||||
@ -1070,13 +1058,7 @@ func inBodyIM(p *parser) bool {
|
||||
p.acknowledgeSelfClosingTag()
|
||||
}
|
||||
return true
|
||||
case a.Frame:
|
||||
// TODO: remove this divergence from the HTML5 spec.
|
||||
if p.oe.contains(a.Template) {
|
||||
p.addElement()
|
||||
return true
|
||||
}
|
||||
case a.Caption, a.Col, a.Colgroup, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
|
||||
case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
|
||||
// Ignore the token.
|
||||
default:
|
||||
p.reconstructActiveFormattingElements()
|
||||
@ -1098,12 +1080,13 @@ func inBodyIM(p *parser) bool {
|
||||
p.popUntil(defaultScope, p.tok.DataAtom)
|
||||
case a.Form:
|
||||
if p.oe.contains(a.Template) {
|
||||
if !p.oe.contains(a.Form) {
|
||||
i := p.indexOfElementInScope(defaultScope, a.Form)
|
||||
if i == -1 {
|
||||
// Ignore the token.
|
||||
return true
|
||||
}
|
||||
p.generateImpliedEndTags()
|
||||
if p.tok.DataAtom == a.Form {
|
||||
if p.oe[i].DataAtom != a.Form {
|
||||
// Ignore the token.
|
||||
return true
|
||||
}
|
||||
@ -1346,9 +1329,6 @@ func textIM(p *parser) bool {
|
||||
// Section 12.2.6.4.9.
|
||||
func inTableIM(p *parser) bool {
|
||||
switch p.tok.Type {
|
||||
case ErrorToken:
|
||||
// Stop parsing.
|
||||
return true
|
||||
case TextToken:
|
||||
p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
|
||||
switch p.oe.top().DataAtom {
|
||||
@ -1443,6 +1423,8 @@ func inTableIM(p *parser) bool {
|
||||
case DoctypeToken:
|
||||
// Ignore the token.
|
||||
return true
|
||||
case ErrorToken:
|
||||
return inBodyIM(p)
|
||||
}
|
||||
|
||||
p.fosterParenting = true
|
||||
@ -1545,6 +1527,8 @@ func inColumnGroupIM(p *parser) bool {
|
||||
case a.Template:
|
||||
return inHeadIM(p)
|
||||
}
|
||||
case ErrorToken:
|
||||
return inBodyIM(p)
|
||||
}
|
||||
if p.oe.top().DataAtom != a.Colgroup {
|
||||
return true
|
||||
@ -1709,9 +1693,6 @@ func inCellIM(p *parser) bool {
|
||||
// Section 12.2.6.4.16.
|
||||
func inSelectIM(p *parser) bool {
|
||||
switch p.tok.Type {
|
||||
case ErrorToken:
|
||||
// Stop parsing.
|
||||
return true
|
||||
case TextToken:
|
||||
p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
|
||||
case StartTagToken:
|
||||
@ -1775,6 +1756,8 @@ func inSelectIM(p *parser) bool {
|
||||
case DoctypeToken:
|
||||
// Ignore the token.
|
||||
return true
|
||||
case ErrorToken:
|
||||
return inBodyIM(p)
|
||||
}
|
||||
|
||||
return true
|
||||
@ -1841,15 +1824,26 @@ func inTemplateIM(p *parser) bool {
|
||||
// Ignore the token.
|
||||
return true
|
||||
}
|
||||
case ErrorToken:
|
||||
if !p.oe.contains(a.Template) {
|
||||
// Ignore the token.
|
||||
return true
|
||||
}
|
||||
// TODO: remove this divergence from the HTML5 spec.
|
||||
//
|
||||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
|
||||
p.generateImpliedEndTags()
|
||||
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||
if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
|
||||
p.oe = p.oe[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
p.clearActiveFormattingElements()
|
||||
p.templateStack.pop()
|
||||
p.resetInsertionMode()
|
||||
return false
|
||||
}
|
||||
if !p.oe.contains(a.Template) {
|
||||
// Ignore the token.
|
||||
return true
|
||||
}
|
||||
p.popUntil(defaultScope, a.Template)
|
||||
p.clearActiveFormattingElements()
|
||||
p.templateStack.pop()
|
||||
p.resetInsertionMode()
|
||||
return false
|
||||
}
|
||||
|
||||
@ -1923,11 +1917,6 @@ func inFramesetIM(p *parser) bool {
|
||||
p.acknowledgeSelfClosingTag()
|
||||
case a.Noframes:
|
||||
return inHeadIM(p)
|
||||
case a.Template:
|
||||
// TODO: remove this divergence from the HTML5 spec.
|
||||
//
|
||||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
|
||||
return inTemplateIM(p)
|
||||
}
|
||||
case EndTagToken:
|
||||
switch p.tok.DataAtom {
|
||||
|
5
vendor/gopkg.in/toast.v1/toast.go
generated
vendored
5
vendor/gopkg.in/toast.v1/toast.go
generated
vendored
@ -11,6 +11,7 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var toastTemplate *template.Template
|
||||
@ -347,7 +348,9 @@ func invokeTemporaryScript(content string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", "-File", file).Run(); err != nil {
|
||||
cmd := exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", "-File", file)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||||
if err = cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
145
vendor/maunium.net/go/gomatrix/client.go
generated
vendored
145
vendor/maunium.net/go/gomatrix/client.go
generated
vendored
@ -6,13 +6,16 @@ package gomatrix
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"maunium.net/go/maulogger"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -26,6 +29,7 @@ type Client struct {
|
||||
Client *http.Client // The underlying HTTP client which will be used to make HTTP requests.
|
||||
Syncer Syncer // The thing which can process /sync responses
|
||||
Store Storer // The thing which can store rooms/tokens/ids
|
||||
Logger maulogger.Logger
|
||||
|
||||
// The ?user_id= query parameter for application services. This must be set *prior* to calling a method. If this is empty,
|
||||
// no user_id parameter will be sent.
|
||||
@ -39,6 +43,7 @@ type Client struct {
|
||||
// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
|
||||
type HTTPError struct {
|
||||
WrappedError error
|
||||
RespError *RespError
|
||||
Message string
|
||||
Code int
|
||||
}
|
||||
@ -177,6 +182,14 @@ func (cli *Client) StopSync() {
|
||||
cli.incrementSyncingID()
|
||||
}
|
||||
|
||||
func (cli *Client) LogRequest(req *http.Request, body string) {
|
||||
if cli.Logger == nil {
|
||||
return
|
||||
}
|
||||
|
||||
cli.Logger.Debugfln("%s %s %s", req.Method, req.URL.Path, body)
|
||||
}
|
||||
|
||||
// MakeRequest makes a JSON HTTP request to the given URL.
|
||||
// If "resBody" is not nil, the response body will be json.Unmarshalled into it.
|
||||
//
|
||||
@ -186,12 +199,14 @@ func (cli *Client) StopSync() {
|
||||
func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{}, resBody interface{}) ([]byte, error) {
|
||||
var req *http.Request
|
||||
var err error
|
||||
logBody := "{}"
|
||||
if reqBody != nil {
|
||||
var jsonStr []byte
|
||||
jsonStr, err = json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logBody = string(jsonStr)
|
||||
req, err = http.NewRequest(method, httpURL, bytes.NewBuffer(jsonStr))
|
||||
} else {
|
||||
req, err = http.NewRequest(method, httpURL, nil)
|
||||
@ -201,6 +216,7 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
cli.LogRequest(req, logBody)
|
||||
res, err := cli.Client.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
@ -211,9 +227,11 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
|
||||
contents, err := ioutil.ReadAll(res.Body)
|
||||
if res.StatusCode/100 != 2 { // not 2xx
|
||||
var wrap error
|
||||
var respErr RespError
|
||||
if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" {
|
||||
respErr := &RespError{}
|
||||
if _ = json.Unmarshal(contents, respErr); respErr.ErrCode != "" {
|
||||
wrap = respErr
|
||||
} else {
|
||||
respErr = nil
|
||||
}
|
||||
|
||||
// If we failed to decode as RespError, don't just drop the HTTP body, include it in the
|
||||
@ -227,6 +245,7 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
|
||||
Code: res.StatusCode,
|
||||
Message: msg,
|
||||
WrappedError: wrap,
|
||||
RespError: respErr,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -342,7 +361,7 @@ func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) {
|
||||
}
|
||||
}
|
||||
if res == nil {
|
||||
return nil, fmt.Errorf("registration failed: does this server support m.login.dummy?")
|
||||
return nil, fmt.Errorf("registration failed: does this server support m.login.dummy? ")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
@ -442,17 +461,38 @@ func (cli *Client) SetAvatarURL(url string) (err error) {
|
||||
|
||||
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
func (cli *Client) SendMessageEvent(roomID string, eventType EventType, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
txnID := txnID()
|
||||
urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID)
|
||||
urlPath := cli.BuildURL("rooms", roomID, "send", eventType.String(), txnID)
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMassagedMessageEvent(roomID string, eventType EventType, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
txnID := txnID()
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "send", eventType.String(), txnID}, map[string]string{
|
||||
"ts": strconv.FormatInt(ts, 10),
|
||||
})
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
|
||||
func (cli *Client) SendStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey)
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMassagedStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "state", eventType.String(), stateKey}, map[string]string{
|
||||
"ts": strconv.FormatInt(ts, 10),
|
||||
})
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
@ -460,37 +500,39 @@ func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSO
|
||||
// SendText sends an m.room.message event into the given room with a msgtype of m.text
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-text
|
||||
func (cli *Client) SendText(roomID, text string) (*RespSendEvent, error) {
|
||||
return cli.SendMessageEvent(roomID, "m.room.message",
|
||||
TextMessage{"m.text", text})
|
||||
return cli.SendMessageEvent(roomID, EventMessage, Content{
|
||||
MsgType: MsgText,
|
||||
Body: text,
|
||||
})
|
||||
}
|
||||
|
||||
// SendImage sends an m.room.message event into the given room with a msgtype of m.image
|
||||
// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-image
|
||||
func (cli *Client) SendImage(roomID, body, url string) (*RespSendEvent, error) {
|
||||
return cli.SendMessageEvent(roomID, "m.room.message",
|
||||
ImageMessage{
|
||||
MsgType: "m.image",
|
||||
Body: body,
|
||||
URL: url,
|
||||
})
|
||||
return cli.SendMessageEvent(roomID, EventMessage, Content{
|
||||
MsgType: MsgImage,
|
||||
Body: body,
|
||||
URL: url,
|
||||
})
|
||||
}
|
||||
|
||||
// SendVideo sends an m.room.message event into the given room with a msgtype of m.video
|
||||
// See https://matrix.org/docs/spec/client_server/r0.2.0.html#m-video
|
||||
func (cli *Client) SendVideo(roomID, body, url string) (*RespSendEvent, error) {
|
||||
return cli.SendMessageEvent(roomID, "m.room.message",
|
||||
VideoMessage{
|
||||
MsgType: "m.video",
|
||||
Body: body,
|
||||
URL: url,
|
||||
})
|
||||
return cli.SendMessageEvent(roomID, EventMessage, Content{
|
||||
MsgType: MsgVideo,
|
||||
Body: body,
|
||||
URL: url,
|
||||
})
|
||||
}
|
||||
|
||||
// SendNotice sends an m.room.message event into the given room with a msgtype of m.notice
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#m-notice
|
||||
func (cli *Client) SendNotice(roomID, text string) (*RespSendEvent, error) {
|
||||
return cli.SendMessageEvent(roomID, "m.room.message",
|
||||
TextMessage{"m.notice", text})
|
||||
return cli.SendMessageEvent(roomID, EventMessage, Content{
|
||||
MsgType: MsgNotice,
|
||||
Body: text,
|
||||
})
|
||||
}
|
||||
|
||||
// RedactEvent redacts the given event. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid
|
||||
@ -569,11 +611,18 @@ func (cli *Client) UserTyping(roomID string, typing bool, timeout int64) (resp *
|
||||
return
|
||||
}
|
||||
|
||||
func (cli *Client) SetPresence(status string) (err error) {
|
||||
req := ReqPresence{Presence: status}
|
||||
u := cli.BuildURL("presence", cli.UserID, "status")
|
||||
_, err = cli.MakeRequest("PUT", u, req, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// StateEvent gets a single state event in a room. It will attempt to JSON unmarshal into the given "outContent" struct with
|
||||
// the HTTP response body, or return an error.
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
func (cli *Client) StateEvent(roomID, eventType, stateKey string, outContent interface{}) (err error) {
|
||||
u := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
|
||||
func (cli *Client) StateEvent(roomID string, eventType EventType, stateKey string, outContent interface{}) (err error) {
|
||||
u := cli.BuildURL("rooms", roomID, "state", eventType.String(), stateKey)
|
||||
_, err = cli.MakeRequest("GET", u, nil, outContent)
|
||||
return
|
||||
}
|
||||
@ -587,18 +636,48 @@ func (cli *Client) UploadLink(link string) (*RespMediaUpload, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cli.UploadToContentRepo(res.Body, res.Header.Get("Content-Type"), res.ContentLength)
|
||||
return cli.Upload(res.Body, res.Header.Get("Content-Type"), res.ContentLength)
|
||||
}
|
||||
|
||||
func (cli *Client) Download(mxcURL string) (io.ReadCloser, error) {
|
||||
if !strings.HasPrefix(mxcURL, "mxc://") {
|
||||
return nil, errors.New("invalid Matrix content URL")
|
||||
}
|
||||
parts := strings.Split(mxcURL[len("mxc://"):], "/")
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("invalid Matrix content URL")
|
||||
}
|
||||
u := cli.BuildBaseURL("_matrix/media/r0/download", parts[0], parts[1])
|
||||
resp, err := cli.Client.Get(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) DownloadBytes(mxcURL string) ([]byte, error) {
|
||||
resp, err := cli.Download(mxcURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Close()
|
||||
return ioutil.ReadAll(resp)
|
||||
}
|
||||
|
||||
func (cli *Client) UploadBytes(data []byte, contentType string) (*RespMediaUpload, error) {
|
||||
return cli.Upload(bytes.NewReader(data), contentType, int64(len(data)))
|
||||
}
|
||||
|
||||
// UploadToContentRepo uploads the given bytes to the content repository and returns an MXC URI.
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-media-r0-upload
|
||||
func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) {
|
||||
func (cli *Client) Upload(content io.Reader, contentType string, contentLength int64) (*RespMediaUpload, error) {
|
||||
req, err := http.NewRequest("POST", cli.BuildBaseURL("_matrix/media/r0/upload"), content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
req.ContentLength = contentLength
|
||||
cli.LogRequest(req, fmt.Sprintf("%d bytes", contentLength))
|
||||
res, err := cli.Client.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
@ -666,6 +745,18 @@ func (cli *Client) Messages(roomID, from, to string, dir rune, limit int) (resp
|
||||
return
|
||||
}
|
||||
|
||||
func (cli *Client) GetEvent(roomID, eventID string) (resp *Event, err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "event", eventID)
|
||||
_, err = cli.MakeRequest("GET", urlPath, nil, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
func (cli *Client) MarkRead(roomID, eventID string) (err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "receipt", "m.read", eventID)
|
||||
_, err = cli.MakeRequest("POST", urlPath, struct{}{}, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// TurnServer returns turn server details and credentials for the client to use when initiating calls.
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-voip-turnserver
|
||||
func (cli *Client) TurnServer() (resp *RespTurnServer, err error) {
|
||||
|
465
vendor/maunium.net/go/gomatrix/events.go
generated
vendored
465
vendor/maunium.net/go/gomatrix/events.go
generated
vendored
@ -1,110 +1,413 @@
|
||||
package gomatrix
|
||||
|
||||
import (
|
||||
"html"
|
||||
"regexp"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type EventTypeClass int
|
||||
|
||||
const (
|
||||
// Normal message events
|
||||
MessageEventType EventTypeClass = iota
|
||||
// State events
|
||||
StateEventType
|
||||
// Ephemeral events
|
||||
EphemeralEventType
|
||||
// Account data events
|
||||
AccountDataEventType
|
||||
// Unknown events
|
||||
UnknownEventType
|
||||
)
|
||||
|
||||
type EventType struct {
|
||||
Type string
|
||||
Class EventTypeClass
|
||||
}
|
||||
|
||||
func NewEventType(name string) EventType {
|
||||
evtType := EventType{Type: name}
|
||||
evtType.Class = evtType.GuessClass()
|
||||
return evtType
|
||||
}
|
||||
|
||||
func (et *EventType) IsState() bool {
|
||||
return et.Class == StateEventType
|
||||
}
|
||||
|
||||
func (et *EventType) IsEphemeral() bool {
|
||||
return et.Class == EphemeralEventType
|
||||
}
|
||||
|
||||
func (et *EventType) IsCustom() bool {
|
||||
return !strings.HasPrefix(et.Type, "m.")
|
||||
}
|
||||
|
||||
func (et *EventType) GuessClass() EventTypeClass {
|
||||
switch et.Type {
|
||||
case StateAliases.Type, StateCanonicalAlias.Type, StateCreate.Type, StateJoinRules.Type, StateMember.Type,
|
||||
StatePowerLevels.Type, StateRoomName.Type, StateRoomAvatar.Type, StateTopic.Type, StatePinnedEvents.Type:
|
||||
return StateEventType
|
||||
case EphemeralEventReceipt.Type, EphemeralEventTyping.Type:
|
||||
return EphemeralEventType
|
||||
case AccountDataDirectChats.Type, AccountDataPushRules.Type, AccountDataRoomTags.Type:
|
||||
return AccountDataEventType
|
||||
case EventRedaction.Type, EventMessage.Type, EventSticker.Type:
|
||||
return MessageEventType
|
||||
default:
|
||||
return UnknownEventType
|
||||
}
|
||||
}
|
||||
|
||||
func (et *EventType) UnmarshalJSON(data []byte) error {
|
||||
err := json.Unmarshal(data, &et.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
et.Class = et.GuessClass()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (et *EventType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&et.Type)
|
||||
}
|
||||
|
||||
func (et *EventType) String() string {
|
||||
return et.Type
|
||||
}
|
||||
|
||||
// State events
|
||||
var (
|
||||
StateAliases = EventType{"m.room.aliases", StateEventType}
|
||||
StateCanonicalAlias = EventType{"m.room.canonical_alias", StateEventType}
|
||||
StateCreate = EventType{"m.room.create", StateEventType}
|
||||
StateJoinRules = EventType{"m.room.join_rules", StateEventType}
|
||||
StateMember = EventType{"m.room.member", StateEventType}
|
||||
StatePowerLevels = EventType{"m.room.power_levels", StateEventType}
|
||||
StateRoomName = EventType{"m.room.name", StateEventType}
|
||||
StateTopic = EventType{"m.room.topic", StateEventType}
|
||||
StateRoomAvatar = EventType{"m.room.avatar", StateEventType}
|
||||
StatePinnedEvents = EventType{"m.room.pinned_events", StateEventType}
|
||||
)
|
||||
|
||||
// Message events
|
||||
var (
|
||||
EventRedaction = EventType{"m.room.redaction", MessageEventType}
|
||||
EventMessage = EventType{"m.room.message", MessageEventType}
|
||||
EventSticker = EventType{"m.sticker", MessageEventType}
|
||||
)
|
||||
|
||||
// Ephemeral events
|
||||
var (
|
||||
EphemeralEventReceipt = EventType{"m.receipt", EphemeralEventType}
|
||||
EphemeralEventTyping = EventType{"m.receipt", EphemeralEventType}
|
||||
)
|
||||
|
||||
// Account data events
|
||||
var (
|
||||
AccountDataDirectChats = EventType{"m.direct", AccountDataEventType}
|
||||
AccountDataPushRules = EventType{"m.push_rules", AccountDataEventType}
|
||||
AccountDataRoomTags = EventType{"m.tag", AccountDataEventType}
|
||||
)
|
||||
|
||||
type MessageType string
|
||||
|
||||
// Msgtypes
|
||||
const (
|
||||
MsgText MessageType = "m.text"
|
||||
MsgEmote = "m.emote"
|
||||
MsgNotice = "m.notice"
|
||||
MsgImage = "m.image"
|
||||
MsgLocation = "m.location"
|
||||
MsgVideo = "m.video"
|
||||
MsgAudio = "m.audio"
|
||||
MsgFile = "m.file"
|
||||
)
|
||||
|
||||
type Format string
|
||||
|
||||
// Message formats
|
||||
const (
|
||||
FormatHTML Format = "org.matrix.custom.html"
|
||||
)
|
||||
|
||||
// Event represents a single Matrix event.
|
||||
type Event struct {
|
||||
StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
|
||||
Sender string `json:"sender"` // The user ID of the sender of the event
|
||||
Type string `json:"type"` // The event type
|
||||
Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server
|
||||
ID string `json:"event_id"` // The unique ID of this event
|
||||
RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence)
|
||||
Content map[string]interface{} `json:"content"` // The JSON content of the event.
|
||||
Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
|
||||
Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
|
||||
StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
|
||||
Sender string `json:"sender"` // The user ID of the sender of the event
|
||||
Type EventType `json:"type"` // The event type
|
||||
Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server
|
||||
ID string `json:"event_id"` // The unique ID of this event
|
||||
RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence)
|
||||
Content Content `json:"content"` // The JSON content of the event.
|
||||
Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
|
||||
Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
|
||||
|
||||
InviteRoomState []StrippedState `json:"invite_room_state"`
|
||||
}
|
||||
|
||||
func (evt *Event) GetStateKey() string {
|
||||
if evt.StateKey != nil {
|
||||
return *evt.StateKey
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type StrippedState struct {
|
||||
Content Content `json:"content"`
|
||||
Type EventType `json:"type"`
|
||||
StateKey string `json:"state_key"`
|
||||
}
|
||||
|
||||
type Unsigned struct {
|
||||
PrevContent map[string]interface{} `json:"prev_content,omitempty"`
|
||||
PrevSender string `json:"prev_sender,omitempty"`
|
||||
ReplacesState string `json:"replaces_state,omitempty"`
|
||||
Age int64 `json:"age"`
|
||||
PrevContent *Content `json:"prev_content,omitempty"`
|
||||
PrevSender string `json:"prev_sender,omitempty"`
|
||||
ReplacesState string `json:"replaces_state,omitempty"`
|
||||
Age int64 `json:"age,omitempty"`
|
||||
}
|
||||
|
||||
// Body returns the value of the "body" key in the event content if it is
|
||||
// present and is a string.
|
||||
func (event *Event) Body() (body string, ok bool) {
|
||||
value, exists := event.Content["body"]
|
||||
if !exists {
|
||||
return
|
||||
type Content struct {
|
||||
VeryRaw json.RawMessage `json:"-"`
|
||||
Raw map[string]interface{} `json:"-"`
|
||||
|
||||
MsgType MessageType `json:"msgtype,omitempty"`
|
||||
Body string `json:"body,omitempty"`
|
||||
Format Format `json:"format,omitempty"`
|
||||
FormattedBody string `json:"formatted_body,omitempty"`
|
||||
|
||||
Info *FileInfo `json:"info,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Membership key for easy access in m.room.member events
|
||||
Membership Membership `json:"membership,omitempty"`
|
||||
|
||||
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
|
||||
|
||||
PowerLevels
|
||||
Member
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
CanonicalAlias
|
||||
RoomName
|
||||
RoomTopic
|
||||
|
||||
RoomTags Tags `json:"tags,omitempty"`
|
||||
TypingUserIDs []string `json:"user_ids,omitempty"`
|
||||
}
|
||||
|
||||
type serializableContent Content
|
||||
|
||||
func (content *Content) UnmarshalJSON(data []byte) error {
|
||||
content.VeryRaw = data
|
||||
if err := json.Unmarshal(data, &content.Raw); err != nil {
|
||||
return err
|
||||
}
|
||||
body, ok = value.(string)
|
||||
return json.Unmarshal(data, (*serializableContent)(content))
|
||||
}
|
||||
|
||||
func (content *Content) UnmarshalPowerLevels() (pl PowerLevels, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &pl)
|
||||
return
|
||||
}
|
||||
|
||||
// MessageType returns the value of the "msgtype" key in the event content if
|
||||
// it is present and is a string.
|
||||
func (event *Event) MessageType() (msgtype string, ok bool) {
|
||||
value, exists := event.Content["msgtype"]
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
msgtype, ok = value.(string)
|
||||
func (content *Content) UnmarshalMember() (m Member, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &m)
|
||||
return
|
||||
}
|
||||
|
||||
// TextMessage is the contents of a Matrix formated message event.
|
||||
type TextMessage struct {
|
||||
MsgType string `json:"msgtype"`
|
||||
Body string `json:"body"`
|
||||
func (content *Content) UnmarshalCanonicalAlias() (ca CanonicalAlias, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &ca)
|
||||
return
|
||||
}
|
||||
|
||||
// ImageInfo contains info about an image - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-image
|
||||
type ImageInfo struct {
|
||||
Height uint `json:"h,omitempty"`
|
||||
Width uint `json:"w,omitempty"`
|
||||
Mimetype string `json:"mimetype,omitempty"`
|
||||
Size uint `json:"size,omitempty"`
|
||||
func (content *Content) GetInfo() *FileInfo {
|
||||
if content.Info == nil {
|
||||
content.Info = &FileInfo{}
|
||||
}
|
||||
return content.Info
|
||||
}
|
||||
|
||||
// VideoInfo contains info about a video - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video
|
||||
type VideoInfo struct {
|
||||
Mimetype string `json:"mimetype,omitempty"`
|
||||
ThumbnailInfo ImageInfo `json:"thumbnail_info"`
|
||||
type Tags map[string]struct {
|
||||
Order string `json:"order"`
|
||||
}
|
||||
|
||||
type RoomName struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type RoomTopic struct {
|
||||
Topic string `json:"topic,omitempty"`
|
||||
}
|
||||
|
||||
// Membership is an enum specifying the membership state of a room member.
|
||||
type Membership string
|
||||
|
||||
// The allowed membership states as specified in spec section 10.5.5.
|
||||
const (
|
||||
MembershipJoin Membership = "join"
|
||||
MembershipLeave Membership = "leave"
|
||||
MembershipInvite Membership = "invite"
|
||||
MembershipBan Membership = "ban"
|
||||
MembershipKnock Membership = "knock"
|
||||
)
|
||||
|
||||
type Member struct {
|
||||
Membership Membership `json:"membership,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
Displayname string `json:"displayname,omitempty"`
|
||||
ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
type ThirdPartyInvite struct {
|
||||
DisplayName string `json:"display_name"`
|
||||
Signed struct {
|
||||
Token string `json:"token"`
|
||||
Signatures json.RawMessage `json:"signatures"`
|
||||
MXID string `json:"mxid"`
|
||||
}
|
||||
}
|
||||
|
||||
type CanonicalAlias struct {
|
||||
Alias string `json:"alias,omitempty"`
|
||||
}
|
||||
|
||||
type PowerLevels struct {
|
||||
usersLock sync.RWMutex `json:"-"`
|
||||
Users map[string]int `json:"users,omitempty"`
|
||||
UsersDefault int `json:"users_default,omitempty"`
|
||||
|
||||
eventsLock sync.RWMutex `json:"-"`
|
||||
Events map[string]int `json:"events,omitempty"`
|
||||
EventsDefault int `json:"events_default,omitempty"`
|
||||
|
||||
StateDefaultPtr *int `json:"state_default,omitempty"`
|
||||
|
||||
InvitePtr *int `json:"invite,omitempty"`
|
||||
KickPtr *int `json:"kick,omitempty"`
|
||||
BanPtr *int `json:"ban,omitempty"`
|
||||
RedactPtr *int `json:"redact,omitempty"`
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) Invite() int {
|
||||
if pl.InvitePtr != nil {
|
||||
return *pl.InvitePtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) Kick() int {
|
||||
if pl.KickPtr != nil {
|
||||
return *pl.KickPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) Ban() int {
|
||||
if pl.BanPtr != nil {
|
||||
return *pl.BanPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) Redact() int {
|
||||
if pl.RedactPtr != nil {
|
||||
return *pl.RedactPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) StateDefault() int {
|
||||
if pl.StateDefaultPtr != nil {
|
||||
return *pl.StateDefaultPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) GetUserLevel(userID string) int {
|
||||
pl.usersLock.RLock()
|
||||
defer pl.usersLock.RUnlock()
|
||||
level, ok := pl.Users[userID]
|
||||
if !ok {
|
||||
return pl.UsersDefault
|
||||
}
|
||||
return level
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) SetUserLevel(userID string, level int) {
|
||||
pl.usersLock.Lock()
|
||||
defer pl.usersLock.Unlock()
|
||||
if level == pl.UsersDefault {
|
||||
delete(pl.Users, userID)
|
||||
} else {
|
||||
pl.Users[userID] = level
|
||||
}
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool {
|
||||
existingLevel := pl.GetUserLevel(userID)
|
||||
if existingLevel != level {
|
||||
pl.SetUserLevel(userID, level)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) GetEventLevel(eventType EventType) int {
|
||||
pl.eventsLock.RLock()
|
||||
defer pl.eventsLock.RUnlock()
|
||||
level, ok := pl.Events[eventType.String()]
|
||||
if !ok {
|
||||
if eventType.IsState() {
|
||||
return pl.StateDefault()
|
||||
}
|
||||
return pl.EventsDefault
|
||||
}
|
||||
return level
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) SetEventLevel(eventType EventType, level int) {
|
||||
pl.eventsLock.Lock()
|
||||
defer pl.eventsLock.Unlock()
|
||||
if (eventType.IsState() && level == pl.StateDefault()) || (!eventType.IsState() && level == pl.EventsDefault) {
|
||||
delete(pl.Events, eventType.String())
|
||||
} else {
|
||||
pl.Events[eventType.String()] = level
|
||||
}
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) EnsureEventLevel(eventType EventType, level int) bool {
|
||||
existingLevel := pl.GetEventLevel(eventType)
|
||||
if existingLevel != level {
|
||||
pl.SetEventLevel(eventType, level)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
MimeType string `json:"mimetype,omitempty"`
|
||||
ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
|
||||
ThumbnailURL string `json:"thumbnail_url,omitempty"`
|
||||
Height uint `json:"h,omitempty"`
|
||||
Width uint `json:"w,omitempty"`
|
||||
Height int `json:"h,omitempty"`
|
||||
Width int `json:"w,omitempty"`
|
||||
Duration uint `json:"duration,omitempty"`
|
||||
Size uint `json:"size,omitempty"`
|
||||
Size int `json:"size,omitempty"`
|
||||
}
|
||||
|
||||
// VideoMessage is an m.video - http://matrix.org/docs/spec/client_server/r0.2.0.html#m-video
|
||||
type VideoMessage struct {
|
||||
MsgType string `json:"msgtype"`
|
||||
Body string `json:"body"`
|
||||
URL string `json:"url"`
|
||||
Info VideoInfo `json:"info"`
|
||||
}
|
||||
|
||||
// ImageMessage is an m.image event
|
||||
type ImageMessage struct {
|
||||
MsgType string `json:"msgtype"`
|
||||
Body string `json:"body"`
|
||||
URL string `json:"url"`
|
||||
Info ImageInfo `json:"info"`
|
||||
}
|
||||
|
||||
// An HTMLMessage is the contents of a Matrix HTML formated message event.
|
||||
type HTMLMessage struct {
|
||||
Body string `json:"body"`
|
||||
MsgType string `json:"msgtype"`
|
||||
Format string `json:"format"`
|
||||
FormattedBody string `json:"formatted_body"`
|
||||
}
|
||||
|
||||
var htmlRegex = regexp.MustCompile("<[^<]+?>")
|
||||
|
||||
// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition
|
||||
// to the provided HTML.
|
||||
func GetHTMLMessage(msgtype, htmlText string) HTMLMessage {
|
||||
return HTMLMessage{
|
||||
Body: html.UnescapeString(htmlRegex.ReplaceAllLiteralString(htmlText, "")),
|
||||
MsgType: msgtype,
|
||||
Format: "org.matrix.custom.html",
|
||||
FormattedBody: htmlText,
|
||||
func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo {
|
||||
if fileInfo.ThumbnailInfo == nil {
|
||||
fileInfo.ThumbnailInfo = &FileInfo{}
|
||||
}
|
||||
return fileInfo.ThumbnailInfo
|
||||
}
|
||||
|
||||
type RelatesTo struct {
|
||||
InReplyTo InReplyTo `json:"m.in_reply_to,omitempty"`
|
||||
}
|
||||
|
||||
type InReplyTo struct {
|
||||
EventID string `json:"event_id,omitempty"`
|
||||
// Not required, just for future-proofing
|
||||
RoomID string `json:"room_id,omitempty"`
|
||||
}
|
||||
|
96
vendor/maunium.net/go/gomatrix/reply.go
generated
vendored
Normal file
96
vendor/maunium.net/go/gomatrix/reply.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
package gomatrix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
var HTMLReplyFallbackRegex = regexp.MustCompile(`^<mx-reply>[\s\S]+?</mx-reply>`)
|
||||
|
||||
func TrimReplyFallbackHTML(html string) string {
|
||||
return HTMLReplyFallbackRegex.ReplaceAllString(html, "")
|
||||
}
|
||||
|
||||
func TrimReplyFallbackText(text string) string {
|
||||
if !strings.HasPrefix(text, "> ") || !strings.Contains(text, "\n") {
|
||||
return text
|
||||
}
|
||||
|
||||
lines := strings.Split(text, "\n")
|
||||
for len(lines) > 0 && strings.HasPrefix(lines[0], "> ") {
|
||||
lines = lines[1:]
|
||||
}
|
||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func (content *Content) RemoveReplyFallback() {
|
||||
if len(content.GetReplyTo()) > 0 {
|
||||
if content.Format == FormatHTML {
|
||||
content.FormattedBody = TrimReplyFallbackHTML(content.FormattedBody)
|
||||
}
|
||||
content.Body = TrimReplyFallbackText(content.Body)
|
||||
}
|
||||
}
|
||||
|
||||
func (content *Content) GetReplyTo() string {
|
||||
if content.RelatesTo != nil {
|
||||
return content.RelatesTo.InReplyTo.EventID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const ReplyFormat = `<mx-reply><blockquote>
|
||||
<a href="https://matrix.to/#/%s/%s">In reply to</a>
|
||||
<a href="https://matrix.to/#/%s">%s</a>
|
||||
%s
|
||||
</blockquote></mx-reply>
|
||||
`
|
||||
|
||||
func (evt *Event) GenerateReplyFallbackHTML() string {
|
||||
body := evt.Content.FormattedBody
|
||||
if len(body) == 0 {
|
||||
body = html.EscapeString(evt.Content.Body)
|
||||
}
|
||||
|
||||
senderDisplayName := evt.Sender
|
||||
|
||||
return fmt.Sprintf(ReplyFormat, evt.RoomID, evt.ID, evt.Sender, senderDisplayName, body)
|
||||
}
|
||||
|
||||
func (evt *Event) GenerateReplyFallbackText() string {
|
||||
body := evt.Content.Body
|
||||
lines := strings.Split(strings.TrimSpace(body), "\n")
|
||||
firstLine, lines := lines[0], lines[1:]
|
||||
|
||||
senderDisplayName := evt.Sender
|
||||
|
||||
var fallbackText strings.Builder
|
||||
fmt.Fprintf(&fallbackText, "> <%s> %s", senderDisplayName, firstLine)
|
||||
for _, line := range lines {
|
||||
fmt.Fprintf(&fallbackText, "\n> %s", line)
|
||||
}
|
||||
fallbackText.WriteString("\n\n")
|
||||
return fallbackText.String()
|
||||
}
|
||||
|
||||
func (content *Content) SetReply(inReplyTo *Event) {
|
||||
if content.RelatesTo == nil {
|
||||
content.RelatesTo = &RelatesTo{}
|
||||
}
|
||||
content.RelatesTo.InReplyTo = InReplyTo{
|
||||
EventID: inReplyTo.ID,
|
||||
RoomID: inReplyTo.RoomID,
|
||||
}
|
||||
|
||||
if content.MsgType == MsgText || content.MsgType == MsgNotice {
|
||||
if len(content.FormattedBody) == 0 || content.Format != FormatHTML {
|
||||
content.FormattedBody = html.EscapeString(content.Body)
|
||||
content.Format = FormatHTML
|
||||
}
|
||||
content.FormattedBody = inReplyTo.GenerateReplyFallbackHTML() + content.FormattedBody
|
||||
content.Body = inReplyTo.GenerateReplyFallbackText() + content.Body
|
||||
}
|
||||
}
|
8
vendor/maunium.net/go/gomatrix/requests.go
generated
vendored
8
vendor/maunium.net/go/gomatrix/requests.go
generated
vendored
@ -31,7 +31,7 @@ type ReqCreateRoom struct {
|
||||
Invite []string `json:"invite,omitempty"`
|
||||
Invite3PID []ReqInvite3PID `json:"invite_3pid,omitempty"`
|
||||
CreationContent map[string]interface{} `json:"creation_content,omitempty"`
|
||||
InitialState []Event `json:"initial_state,omitempty"`
|
||||
InitialState []*Event `json:"initial_state,omitempty"`
|
||||
Preset string `json:"preset,omitempty"`
|
||||
IsDirect bool `json:"is_direct,omitempty"`
|
||||
}
|
||||
@ -74,5 +74,9 @@ type ReqUnbanUser struct {
|
||||
// ReqTyping is the JSON request for https://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-typing-userid
|
||||
type ReqTyping struct {
|
||||
Typing bool `json:"typing"`
|
||||
Timeout int64 `json:"timeout"`
|
||||
Timeout int64 `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
type ReqPresence struct {
|
||||
Presence string `json:"presence"`
|
||||
}
|
2
vendor/maunium.net/go/gomatrix/responses.go
generated
vendored
2
vendor/maunium.net/go/gomatrix/responses.go
generated
vendored
@ -64,7 +64,7 @@ type RespJoinedMembers struct {
|
||||
// RespMessages is the JSON response for https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages
|
||||
type RespMessages struct {
|
||||
Start string `json:"start"`
|
||||
Chunk []Event `json:"chunk"`
|
||||
Chunk []*Event `json:"chunk"`
|
||||
End string `json:"end"`
|
||||
}
|
||||
|
||||
|
20
vendor/maunium.net/go/gomatrix/room.go
generated
vendored
20
vendor/maunium.net/go/gomatrix/room.go
generated
vendored
@ -3,7 +3,7 @@ package gomatrix
|
||||
// Room represents a single Matrix room.
|
||||
type Room struct {
|
||||
ID string
|
||||
State map[string]map[string]*Event
|
||||
State map[EventType]map[string]*Event
|
||||
}
|
||||
|
||||
// UpdateState updates the room's current state with the given Event. This will clobber events based
|
||||
@ -17,7 +17,7 @@ func (room Room) UpdateState(event *Event) {
|
||||
}
|
||||
|
||||
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
|
||||
func (room Room) GetStateEvent(eventType string, stateKey string) *Event {
|
||||
func (room Room) GetStateEvent(eventType EventType, stateKey string) *Event {
|
||||
stateEventMap, _ := room.State[eventType]
|
||||
event, _ := stateEventMap[stateKey]
|
||||
return event
|
||||
@ -25,17 +25,11 @@ func (room Room) GetStateEvent(eventType string, stateKey string) *Event {
|
||||
|
||||
// GetMembershipState returns the membership state of the given user ID in this room. If there is
|
||||
// no entry for this member, 'leave' is returned for consistency with left users.
|
||||
func (room Room) GetMembershipState(userID string) string {
|
||||
state := "leave"
|
||||
event := room.GetStateEvent("m.room.member", userID)
|
||||
func (room Room) GetMembershipState(userID string) Membership {
|
||||
state := MembershipLeave
|
||||
event := room.GetStateEvent(StateMember, userID)
|
||||
if event != nil {
|
||||
membershipState, found := event.Content["membership"]
|
||||
if found {
|
||||
mState, isString := membershipState.(string)
|
||||
if isString {
|
||||
state = mState
|
||||
}
|
||||
}
|
||||
state = event.Content.Membership
|
||||
}
|
||||
return state
|
||||
}
|
||||
@ -45,6 +39,6 @@ func NewRoom(roomID string) *Room {
|
||||
// Init the State map and return a pointer to the Room
|
||||
return &Room{
|
||||
ID: roomID,
|
||||
State: make(map[string]map[string]*Event),
|
||||
State: make(map[EventType]map[string]*Event),
|
||||
}
|
||||
}
|
||||
|
15
vendor/maunium.net/go/gomatrix/sync.go
generated
vendored
15
vendor/maunium.net/go/gomatrix/sync.go
generated
vendored
@ -25,7 +25,7 @@ type Syncer interface {
|
||||
type DefaultSyncer struct {
|
||||
UserID string
|
||||
Store Storer
|
||||
listeners map[string][]OnEventListener // event type to listeners array
|
||||
listeners map[EventType][]OnEventListener // event type to listeners array
|
||||
}
|
||||
|
||||
// OnEventListener can be used with DefaultSyncer.OnEventType to be informed of incoming events.
|
||||
@ -36,7 +36,7 @@ func NewDefaultSyncer(userID string, store Storer) *DefaultSyncer {
|
||||
return &DefaultSyncer{
|
||||
UserID: userID,
|
||||
Store: store,
|
||||
listeners: make(map[string][]OnEventListener),
|
||||
listeners: make(map[EventType][]OnEventListener),
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ func (s *DefaultSyncer) ProcessResponse(res *RespSync, since string) (err error)
|
||||
|
||||
// OnEventType allows callers to be notified when there are new events for the given event type.
|
||||
// There are no duplicate checks.
|
||||
func (s *DefaultSyncer) OnEventType(eventType string, callback OnEventListener) {
|
||||
func (s *DefaultSyncer) OnEventType(eventType EventType, callback OnEventListener) {
|
||||
_, exists := s.listeners[eventType]
|
||||
if !exists {
|
||||
s.listeners[eventType] = []OnEventListener{}
|
||||
@ -112,13 +112,8 @@ func (s *DefaultSyncer) shouldProcessResponse(resp *RespSync, since string) bool
|
||||
for roomID, roomData := range resp.Rooms.Join {
|
||||
for i := len(roomData.Timeline.Events) - 1; i >= 0; i-- {
|
||||
e := roomData.Timeline.Events[i]
|
||||
if e.Type == "m.room.member" && e.StateKey != nil && *e.StateKey == s.UserID {
|
||||
m := e.Content["membership"]
|
||||
mship, ok := m.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if mship == "join" {
|
||||
if e.Type == StateMember && e.GetStateKey() == s.UserID {
|
||||
if e.Content.Membership == "join" {
|
||||
_, ok := resp.Rooms.Join[roomID]
|
||||
if !ok {
|
||||
continue
|
||||
|
21
vendor/maunium.net/go/maulogger/LICENSE
generated
vendored
Normal file
21
vendor/maunium.net/go/maulogger/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Tulir Asokan
|
||||
|
||||
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.
|
6
vendor/maunium.net/go/maulogger/README.md
generated
vendored
Normal file
6
vendor/maunium.net/go/maulogger/README.md
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# maulogger
|
||||
A logger in Go.
|
||||
|
||||
Docs: [godoc.org/maunium.net/go/maulogger](https://godoc.org/maunium.net/go/maulogger)
|
||||
|
||||
Go get: `go get maunium.net/go/maulogger`
|
219
vendor/maunium.net/go/maulogger/logger.go
generated
vendored
Normal file
219
vendor/maunium.net/go/maulogger/logger.go
generated
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
package maulog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Level is the severity level of a log entry.
|
||||
type Level struct {
|
||||
Name string
|
||||
Severity, Color int
|
||||
}
|
||||
|
||||
// LogWriter writes to the log with an optional prefix
|
||||
type LogWriter struct {
|
||||
Level Level
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (lw LogWriter) Write(p []byte) (n int, err error) {
|
||||
log(lw.Level, fmt.Sprint(lw.Prefix, string(p)))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// GetColor gets the ANSI escape color code for the log level.
|
||||
func (lvl Level) GetColor() []byte {
|
||||
if lvl.Color < 0 {
|
||||
return []byte("")
|
||||
}
|
||||
return []byte(fmt.Sprintf("\x1b[%dm", lvl.Color))
|
||||
}
|
||||
|
||||
// GetReset gets the ANSI escape reset code.
|
||||
func (lvl Level) GetReset() []byte {
|
||||
if lvl.Color < 0 {
|
||||
return []byte("")
|
||||
}
|
||||
return []byte("\x1b[0m")
|
||||
}
|
||||
|
||||
var (
|
||||
// Debug is the level for debug messages.
|
||||
Debug = Level{Name: "DEBUG", Color: 36, Severity: 0}
|
||||
// Info is the level for basic log messages.
|
||||
Info = Level{Name: "INFO", Color: -1, Severity: 10}
|
||||
// Warn is the level saying that something went wrong, but the program will continue operating mostly normally.
|
||||
Warn = Level{Name: "WARN", Color: 33, Severity: 50}
|
||||
// Error is the level saying that something went wrong and the program may not operate as expected, but will still continue.
|
||||
Error = Level{Name: "ERROR", Color: 31, Severity: 100}
|
||||
// Fatal is the level saying that something went wrong and the program will not operate normally.
|
||||
Fatal = Level{Name: "FATAL", Color: 35, Severity: 9001}
|
||||
)
|
||||
|
||||
// PrintLevel tells the first severity level at which messages should be printed to stdout
|
||||
var PrintLevel = 10
|
||||
|
||||
// PrintDebug means PrintLevel = 0, kept for backwards compatibility
|
||||
var PrintDebug = false
|
||||
|
||||
// FileTimeformat is the time format used in log file names.
|
||||
var FileTimeformat = "2006-01-02"
|
||||
|
||||
// FileformatArgs is an undocumented integer.
|
||||
var FileformatArgs = 3
|
||||
|
||||
// Fileformat is the format used for log file names.
|
||||
var Fileformat = func(now string, i int) string { return fmt.Sprintf("%[1]s-%02[2]d.log", now, i) }
|
||||
|
||||
// Timeformat is the time format used in logging.
|
||||
var Timeformat = "15:04:05 02.01.2006"
|
||||
|
||||
var writer *bufio.Writer
|
||||
var lines int
|
||||
|
||||
// InitWithWriter initializes MauLogger with the given writer.
|
||||
func InitWithWriter(w *bufio.Writer) {
|
||||
writer = w
|
||||
}
|
||||
|
||||
// Init initializes MauLogger.
|
||||
func Init() {
|
||||
// Find the next file name.
|
||||
now := time.Now().Format(FileTimeformat)
|
||||
i := 1
|
||||
for ; ; i++ {
|
||||
if _, err := os.Stat(Fileformat(now, i)); os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
if i == 99 {
|
||||
i = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
// Open the file
|
||||
file, err := os.OpenFile(Fileformat(now, i), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0700)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if file == nil {
|
||||
panic(os.ErrInvalid)
|
||||
}
|
||||
// Create a writer
|
||||
writer = bufio.NewWriter(file)
|
||||
}
|
||||
|
||||
// Debugf formats and logs a debug message.
|
||||
func Debugf(message string, args ...interface{}) {
|
||||
logln(Debug, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Printf formats and logs a string in the Info log level.
|
||||
func Printf(message string, args ...interface{}) {
|
||||
Infof(message, args...)
|
||||
}
|
||||
|
||||
// Infof formats and logs a string in the Info log level.
|
||||
func Infof(message string, args ...interface{}) {
|
||||
logln(Info, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Warnf formats and logs a string in the Warn log level.
|
||||
func Warnf(message string, args ...interface{}) {
|
||||
logln(Warn, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Errorf formats and logs a string in the Error log level.
|
||||
func Errorf(message string, args ...interface{}) {
|
||||
logln(Error, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Fatalf formats and logs a string in the Fatal log level.
|
||||
func Fatalf(message string, args ...interface{}) {
|
||||
logln(Fatal, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Logf formats and logs a message in the given log level.
|
||||
func Logf(level Level, message string, args ...interface{}) {
|
||||
logln(level, fmt.Sprintf(message, args...))
|
||||
}
|
||||
|
||||
// Debugln logs a debug message.
|
||||
func Debugln(args ...interface{}) {
|
||||
log(Debug, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Println logs a string in the Info log level.
|
||||
func Println(args ...interface{}) {
|
||||
Infoln(args...)
|
||||
}
|
||||
|
||||
// Infoln logs a string in the Info log level.
|
||||
func Infoln(args ...interface{}) {
|
||||
log(Info, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Warnln logs a string in the Warn log level.
|
||||
func Warnln(args ...interface{}) {
|
||||
log(Warn, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Errorln logs a string in the Error log level.
|
||||
func Errorln(args ...interface{}) {
|
||||
log(Error, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Fatalln logs a string in the Fatal log level.
|
||||
func Fatalln(args ...interface{}) {
|
||||
log(Fatal, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
// Logln logs a message in the given log level.
|
||||
func Logln(level Level, args ...interface{}) {
|
||||
log(level, fmt.Sprintln(args...))
|
||||
}
|
||||
|
||||
func logln(level Level, message string) {
|
||||
log(level, fmt.Sprintln(message))
|
||||
}
|
||||
|
||||
func log(level Level, message string) {
|
||||
// Prefix the message with the timestamp and log level.
|
||||
msg := []byte(fmt.Sprintf("[%[1]s] [%[2]s] %[3]s", time.Now().Format(Timeformat), level.Name, message))
|
||||
|
||||
if writer != nil {
|
||||
// Write it to the log file.
|
||||
_, err := writer.Write(msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
lines++
|
||||
// Flush the file if needed
|
||||
if lines == 5 {
|
||||
lines = 0
|
||||
writer.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// Print to stdout using correct color
|
||||
if level.Severity >= PrintLevel || PrintDebug {
|
||||
if level.Severity >= Error.Severity {
|
||||
os.Stderr.Write(level.GetColor())
|
||||
os.Stderr.Write(msg)
|
||||
os.Stderr.Write(level.GetReset())
|
||||
} else {
|
||||
os.Stdout.Write(level.GetColor())
|
||||
os.Stdout.Write(msg)
|
||||
os.Stdout.Write(level.GetReset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown cleans up the logger.
|
||||
func Shutdown() {
|
||||
if writer != nil {
|
||||
writer.Flush()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user