Add external debug file, refactoring and push rule parser
This commit is contained in:
parent
7994c289aa
commit
35b6c7bd27
@ -22,6 +22,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"maunium.net/go/gomatrix"
|
"maunium.net/go/gomatrix"
|
||||||
|
"maunium.net/go/gomuks/matrix/ext"
|
||||||
rooms "maunium.net/go/gomuks/matrix/room"
|
rooms "maunium.net/go/gomuks/matrix/room"
|
||||||
"maunium.net/go/gomuks/ui/debug"
|
"maunium.net/go/gomuks/ui/debug"
|
||||||
)
|
)
|
||||||
@ -33,7 +34,7 @@ type Session struct {
|
|||||||
NextBatch string
|
NextBatch string
|
||||||
FilterID string
|
FilterID string
|
||||||
Rooms map[string]*rooms.Room
|
Rooms map[string]*rooms.Room
|
||||||
PushRules *gomatrix.PushRuleset
|
PushRules *gomx_ext.PushRuleset
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) LoadSession(mxid string) error {
|
func (config *Config) LoadSession(mxid string) error {
|
||||||
|
@ -65,6 +65,7 @@ func NewGomuks(enableDebug bool) *Gomuks {
|
|||||||
|
|
||||||
main := gmx.ui.InitViews()
|
main := gmx.ui.InitViews()
|
||||||
if enableDebug {
|
if enableDebug {
|
||||||
|
debug.EnableExternal()
|
||||||
main = gmx.debug.Wrap(main)
|
main = gmx.debug.Wrap(main)
|
||||||
gmx.debugMode = true
|
gmx.debugMode = true
|
||||||
}
|
}
|
||||||
|
@ -33,5 +33,5 @@ type MatrixContainer interface {
|
|||||||
JoinRoom(roomID string) error
|
JoinRoom(roomID string) error
|
||||||
LeaveRoom(roomID string) 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) *room.Room
|
GetRoom(roomID string) *rooms.Room
|
||||||
}
|
}
|
||||||
|
18
matrix/ext/doc.go
Normal file
18
matrix/ext/doc.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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 gomx_ext contains extensions to the gomatrix package.
|
||||||
|
package gomx_ext
|
376
matrix/ext/pushrules.go
Normal file
376
matrix/ext/pushrules.go
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
package gomx_ext
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zyedidia/glob"
|
||||||
|
"maunium.net/go/gomatrix"
|
||||||
|
"maunium.net/go/gomuks/matrix/room"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetPushRules returns the push notification rules for the given scope.
|
||||||
|
func GetPushRules(client *gomatrix.Client) (resp *PushRuleset, err error) {
|
||||||
|
u, _ := url.Parse(client.BuildURL("pushrules", "global"))
|
||||||
|
u.Path += "/"
|
||||||
|
_, err = client.MakeRequest("GET", u.String(), nil, &resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushRuleset struct {
|
||||||
|
Override PushRuleArray
|
||||||
|
Content PushRuleArray
|
||||||
|
Room PushRuleMap
|
||||||
|
Sender PushRuleMap
|
||||||
|
Underride PushRuleArray
|
||||||
|
}
|
||||||
|
|
||||||
|
type rawPushRuleset struct {
|
||||||
|
Override PushRuleArray `json:"override"`
|
||||||
|
Content PushRuleArray `json:"content"`
|
||||||
|
Room PushRuleArray `json:"room"`
|
||||||
|
Sender PushRuleArray `json:"sender"`
|
||||||
|
Underride PushRuleArray `json:"underride"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *PushRuleset) UnmarshalJSON(raw []byte) (err error) {
|
||||||
|
data := rawPushRuleset{}
|
||||||
|
err = json.Unmarshal(raw, &data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.Override = data.Override.setType(OverrideRule)
|
||||||
|
rs.Content = data.Content.setType(ContentRule)
|
||||||
|
rs.Room = data.Room.setTypeAndMap(RoomRule)
|
||||||
|
rs.Sender = data.Sender.setTypeAndMap(SenderRule)
|
||||||
|
rs.Underride = data.Underride.setType(UnderrideRule)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *PushRuleset) MarshalJSON() ([]byte, error) {
|
||||||
|
data := rawPushRuleset{
|
||||||
|
Override: rs.Override,
|
||||||
|
Content: rs.Content,
|
||||||
|
Room: rs.Room.unmap(),
|
||||||
|
Sender: rs.Sender.unmap(),
|
||||||
|
Underride: rs.Underride,
|
||||||
|
}
|
||||||
|
return json.Marshal(&data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rs *PushRuleset) GetActions(room *rooms.Room, event *gomatrix.Event) (match []*PushAction) {
|
||||||
|
if match = rs.Override.GetActions(room, event); match != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if match = rs.Content.GetActions(room, event); match != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if match = rs.Room.GetActions(room, event); match != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if match = rs.Sender.GetActions(room, event); match != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if match = rs.Underride.GetActions(room, event); match != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushRuleArray []*PushRule
|
||||||
|
|
||||||
|
func (rules PushRuleArray) setType(typ PushRuleType) PushRuleArray {
|
||||||
|
for _, rule := range rules {
|
||||||
|
rule.Type = typ
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rules PushRuleArray) GetActions(room *rooms.Room, event *gomatrix.Event) []*PushAction {
|
||||||
|
for _, rule := range rules {
|
||||||
|
if !rule.Match(room, event) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return rule.Actions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushRuleMap struct {
|
||||||
|
Map map[string]*PushRule
|
||||||
|
Type PushRuleType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rules PushRuleArray) setTypeAndMap(typ PushRuleType) PushRuleMap {
|
||||||
|
data := PushRuleMap{
|
||||||
|
Map: make(map[string]*PushRule),
|
||||||
|
Type: typ,
|
||||||
|
}
|
||||||
|
for _, rule := range rules {
|
||||||
|
rule.Type = typ
|
||||||
|
data.Map[rule.RuleID] = rule
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ruleMap PushRuleMap) GetActions(room *rooms.Room, event *gomatrix.Event) []*PushAction {
|
||||||
|
var rule *PushRule
|
||||||
|
var found bool
|
||||||
|
switch ruleMap.Type {
|
||||||
|
case RoomRule:
|
||||||
|
rule, found = ruleMap.Map[event.RoomID]
|
||||||
|
case SenderRule:
|
||||||
|
rule, found = ruleMap.Map[event.Sender]
|
||||||
|
}
|
||||||
|
if found && rule.Match(room, event) {
|
||||||
|
return rule.Actions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ruleMap PushRuleMap) unmap() PushRuleArray {
|
||||||
|
array := make(PushRuleArray, len(ruleMap.Map))
|
||||||
|
index := 0
|
||||||
|
for _, rule := range ruleMap.Map {
|
||||||
|
array[index] = rule
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushRuleType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OverrideRule PushRuleType = "override"
|
||||||
|
ContentRule PushRuleType = "content"
|
||||||
|
RoomRule PushRuleType = "room"
|
||||||
|
SenderRule PushRuleType = "sender"
|
||||||
|
UnderrideRule PushRuleType = "underride"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushRule struct {
|
||||||
|
// The type of this rule.
|
||||||
|
Type PushRuleType `json:"-"`
|
||||||
|
// The ID of this rule.
|
||||||
|
// For room-specific rules and user-specific rules, this is the room or user ID (respectively)
|
||||||
|
// For other types of rules, this doesn't affect anything.
|
||||||
|
RuleID string `json:"rule_id"`
|
||||||
|
// The actions this rule should trigger when matched.
|
||||||
|
Actions []*PushAction `json:"actions"`
|
||||||
|
// Whether this is a default rule, or has been set explicitly.
|
||||||
|
Default bool `json:"default"`
|
||||||
|
// Whether or not this push rule is enabled.
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
// The conditions to match in order to trigger this rule.
|
||||||
|
// Only applicable to generic underride/override rules.
|
||||||
|
Conditions []*PushCondition `json:"conditions,omitempty"`
|
||||||
|
// Pattern for content-specific push rules
|
||||||
|
Pattern string `json:"pattern,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rule *PushRule) Match(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
if !rule.Enabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch rule.Type {
|
||||||
|
case OverrideRule, UnderrideRule:
|
||||||
|
return rule.matchConditions(room, event)
|
||||||
|
case ContentRule:
|
||||||
|
return rule.matchPattern(room, event)
|
||||||
|
case RoomRule:
|
||||||
|
return rule.RuleID == event.RoomID
|
||||||
|
case SenderRule:
|
||||||
|
return rule.RuleID == event.Sender
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rule *PushRule) matchConditions(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
for _, cond := range rule.Conditions {
|
||||||
|
if !cond.Match(room, event) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rule *PushRule) matchPattern(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
pattern, err := glob.Compile(rule.Pattern)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
text, _ := event.Content["body"].(string)
|
||||||
|
return pattern.MatchString(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushActionType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ActionNotify PushActionType = "notify"
|
||||||
|
ActionDontNotify PushActionType = "dont_notify"
|
||||||
|
ActionCoalesce PushActionType = "coalesce"
|
||||||
|
ActionSetTweak PushActionType = "set_tweak"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushActionTweak string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TweakSound PushActionTweak = "sound"
|
||||||
|
TweakHighlight PushActionTweak = "highlight"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushAction struct {
|
||||||
|
Action PushActionType
|
||||||
|
Tweak PushActionTweak
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *PushAction) UnmarshalJSON(raw []byte) error {
|
||||||
|
var data interface{}
|
||||||
|
|
||||||
|
err := json.Unmarshal(raw, &data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val := data.(type) {
|
||||||
|
case string:
|
||||||
|
action.Action = PushActionType(val)
|
||||||
|
case map[string]interface{}:
|
||||||
|
tweak, ok := val["set_tweak"].(string)
|
||||||
|
if ok {
|
||||||
|
action.Action = ActionSetTweak
|
||||||
|
action.Tweak = PushActionTweak(tweak)
|
||||||
|
action.Value, _ = val["value"].(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (action *PushAction) MarshalJSON() (raw []byte, err error) {
|
||||||
|
if action.Action == ActionSetTweak {
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"set_tweak": action.Tweak,
|
||||||
|
"value": action.Value,
|
||||||
|
}
|
||||||
|
return json.Marshal(&data)
|
||||||
|
} else {
|
||||||
|
data := string(action.Action)
|
||||||
|
return json.Marshal(&data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
KindEventMatch PushKind = "event_match"
|
||||||
|
KindContainsDisplayName PushKind = "contains_display_name"
|
||||||
|
KindRoomMemberCount PushKind = "room_member_count"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushCondition struct {
|
||||||
|
Kind PushKind `json:"kind"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Pattern string `json:"pattern,omitempty"`
|
||||||
|
Is string `json:"string,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var MemberCountFilterRegex = regexp.MustCompile("^(==|[<>]=?)?([0-9]+)$")
|
||||||
|
|
||||||
|
func (cond *PushCondition) Match(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
switch cond.Kind {
|
||||||
|
case KindEventMatch:
|
||||||
|
return cond.matchValue(room, event)
|
||||||
|
case KindContainsDisplayName:
|
||||||
|
return cond.matchDisplayName(room, event)
|
||||||
|
case KindRoomMemberCount:
|
||||||
|
return cond.matchMemberCount(room, event)
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cond *PushCondition) matchValue(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
index := strings.IndexRune(cond.Key, '.')
|
||||||
|
key := cond.Key
|
||||||
|
subkey := ""
|
||||||
|
if index > 0 {
|
||||||
|
subkey = key[index+1:]
|
||||||
|
key = key[0:index]
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern, err := glob.Compile(cond.Pattern)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch key {
|
||||||
|
case "type":
|
||||||
|
return pattern.MatchString(event.Type)
|
||||||
|
case "sender":
|
||||||
|
return pattern.MatchString(event.Sender)
|
||||||
|
case "room_id":
|
||||||
|
return pattern.MatchString(event.RoomID)
|
||||||
|
case "state_key":
|
||||||
|
if event.StateKey == nil {
|
||||||
|
return cond.Pattern == ""
|
||||||
|
}
|
||||||
|
return pattern.MatchString(*event.StateKey)
|
||||||
|
case "content":
|
||||||
|
val, _ := event.Content[subkey].(string)
|
||||||
|
return pattern.MatchString(val)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cond *PushCondition) matchDisplayName(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
member := room.GetMember(room.Owner)
|
||||||
|
if member == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
text, _ := event.Content["body"].(string)
|
||||||
|
return strings.Contains(text, member.DisplayName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Event) bool {
|
||||||
|
groupGroups := MemberCountFilterRegex.FindAllStringSubmatch(cond.Is, -1)
|
||||||
|
if len(groupGroups) != 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
operator := "=="
|
||||||
|
wantedMemberCount := 0
|
||||||
|
|
||||||
|
group := groupGroups[0]
|
||||||
|
if len(group) == 0 {
|
||||||
|
return true
|
||||||
|
} else if len(group) == 1 {
|
||||||
|
wantedMemberCount, _ = strconv.Atoi(group[0])
|
||||||
|
} else {
|
||||||
|
operator = group[0]
|
||||||
|
wantedMemberCount, _ = strconv.Atoi(group[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
memberCount := len(room.GetMembers())
|
||||||
|
|
||||||
|
switch operator {
|
||||||
|
case "==":
|
||||||
|
return wantedMemberCount == memberCount
|
||||||
|
case ">":
|
||||||
|
return wantedMemberCount > memberCount
|
||||||
|
case ">=":
|
||||||
|
return wantedMemberCount >= memberCount
|
||||||
|
case "<":
|
||||||
|
return wantedMemberCount < memberCount
|
||||||
|
case "<=":
|
||||||
|
return wantedMemberCount <= memberCount
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,8 @@ import (
|
|||||||
"maunium.net/go/gomatrix"
|
"maunium.net/go/gomatrix"
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
rooms "maunium.net/go/gomuks/matrix/room"
|
"maunium.net/go/gomuks/matrix/ext"
|
||||||
|
"maunium.net/go/gomuks/matrix/room"
|
||||||
"maunium.net/go/gomuks/notification"
|
"maunium.net/go/gomuks/notification"
|
||||||
"maunium.net/go/gomuks/ui/debug"
|
"maunium.net/go/gomuks/ui/debug"
|
||||||
"maunium.net/go/gomuks/ui/types"
|
"maunium.net/go/gomuks/ui/types"
|
||||||
@ -120,13 +121,20 @@ func (c *Container) Client() *gomatrix.Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) UpdatePushRules() {
|
func (c *Container) UpdatePushRules() {
|
||||||
resp, err := c.client.PushRules()
|
resp, err := gomx_ext.GetPushRules(c.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Print("Failed to fetch push rules:", err)
|
debug.Print("Failed to fetch push rules:", err)
|
||||||
}
|
}
|
||||||
c.config.Session.PushRules = resp
|
c.config.Session.PushRules = resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) PushRules() *gomx_ext.PushRuleset {
|
||||||
|
if c.config.Session.PushRules == nil {
|
||||||
|
c.UpdatePushRules()
|
||||||
|
}
|
||||||
|
return c.config.Session.PushRules
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Container) UpdateRoomList() {
|
func (c *Container) UpdateRoomList() {
|
||||||
resp, err := c.client.JoinedRooms()
|
resp, err := c.client.JoinedRooms()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -200,6 +208,20 @@ func (c *Container) NotifyMessage(room *rooms.Room, message *types.Message) {
|
|||||||
func (c *Container) HandleMessage(evt *gomatrix.Event) {
|
func (c *Container) HandleMessage(evt *gomatrix.Event) {
|
||||||
room, message := c.ui.MainView().ProcessMessageEvent(evt)
|
room, message := c.ui.MainView().ProcessMessageEvent(evt)
|
||||||
if room != nil {
|
if room != nil {
|
||||||
|
match := c.PushRules().GetActions(room.Room, evt)
|
||||||
|
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.WriteRune('[')
|
||||||
|
for i, rule := range match {
|
||||||
|
fmt.Fprintf(&buf, "{%s, %s, %s}", rule.Action, rule.Tweak, rule.Value)
|
||||||
|
if i < len(match)-1 {
|
||||||
|
buf.WriteRune(',')
|
||||||
|
buf.WriteRune(' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteRune(']')
|
||||||
|
debug.Print(buf.String())
|
||||||
|
|
||||||
c.NotifyMessage(room.Room, message)
|
c.NotifyMessage(room.Room, message)
|
||||||
room.AddMessage(message, widget.AppendMessage)
|
room.AddMessage(message, widget.AppendMessage)
|
||||||
c.ui.Render()
|
c.ui.Render()
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package room
|
package rooms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"maunium.net/go/gomatrix"
|
"maunium.net/go/gomatrix"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package room
|
package rooms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
45
ui/debug/external.go
Normal file
45
ui/debug/external.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// 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 debug
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var writer io.Writer
|
||||||
|
|
||||||
|
func EnableExternal() {
|
||||||
|
var err error
|
||||||
|
writer, err = os.OpenFile("/tmp/gomuks-debug.log", os.O_WRONLY|os.O_APPEND, 0644)
|
||||||
|
if err != nil {
|
||||||
|
writer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtPrintf(text string, args ...interface{}) {
|
||||||
|
if writer != nil {
|
||||||
|
fmt.Fprintf(writer, text + "\n", args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtPrint(text ...interface{}) {
|
||||||
|
if writer != nil {
|
||||||
|
fmt.Fprintln(writer, text...)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user