Now all indicator updates properly

This commit is contained in:
eleksir
2024-09-23 19:05:45 +03:00
parent 1a4ab136dc
commit 5bb259a30c
15 changed files with 228 additions and 231 deletions

View File

@@ -25,20 +25,25 @@ func main() {
log.Panicf("Unable to read config: %s", err) log.Panicf("Unable to read config: %s", err)
} }
Conf.UpdateReady = make(chan bool) Conf.Channels.UpdateReady = make(chan bool)
Conf.MsgChan = make(chan []lib.I3BarOutBlock, 64) Conf.Channels.SVPAHandlerChan = make(chan lib.ClickEvent, 256)
Conf.SigChan = make(chan os.Signal, 1) Conf.Channels.MsgChan = make(chan []lib.I3BarOutBlock, 64)
Conf.BatteryString = "<big>⚡</big> ??% •" Conf.Channels.SigChan = make(chan os.Signal, 1)
Conf.ClockTime = "Thu, 1 Jan 1970 1:00" Conf.Channels.RunChan = make(chan []string, 128)
Conf.IfStatus = "" Conf.Values.PrintOutput = true
Conf.VPNStatus = "" Conf.Values.BatteryString = "<big>⚡</big> ??% •"
Conf.Memory.Shared = 0 Conf.Values.ClockTime = "Thu, 1 Jan 1970 1:00"
Conf.Memory.Usedpct = 0 Conf.Values.IfStatus = ""
Conf.Memory.Swap = 0 Conf.Values.VPNStatus = ""
Conf.La = "-1" Conf.Values.Memory.Shared = 0
Conf.Values.Memory.Usedpct = 0
Conf.Values.Memory.Swap = 0
Conf.Values.La = "-1"
// Conf.Values.PA
Conf.Values.SoundVolume = "🔊:0%"
// TODO: Проставить дефолтные значения для глобальных переменных модулей. // TODO: Проставить дефолтные значения для глобальных переменных модулей.
Batt := fmt.Sprintf( Conf.Values.BatteryString = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>", "<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Battery.Color, Conf.Battery.Color,
Conf.Battery.Background, Conf.Battery.Background,
@@ -47,7 +52,7 @@ func main() {
Conf.Battery.Symbol, Conf.Battery.Symbol,
) )
Batt += fmt.Sprintf( Conf.Values.BatteryString += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>", "<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
Conf.Battery.Color, Conf.Battery.Color,
Conf.Battery.Background, Conf.Battery.Background,
@@ -55,7 +60,7 @@ func main() {
Conf.Battery.FontSize, Conf.Battery.FontSize,
) )
SoundVolume := fmt.Sprintf( Conf.Values.SoundVolume = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>🔊</span>", "<span color='%s' background='%s' font='%s' size='%s'>🔊</span>",
Conf.SimpleVolumePa.Color, Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background, Conf.SimpleVolumePa.Background,
@@ -63,7 +68,7 @@ func main() {
Conf.SimpleVolumePa.SymbolFontSize, Conf.SimpleVolumePa.SymbolFontSize,
) )
SoundVolume += fmt.Sprintf( Conf.Values.SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:0%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>:0%%</span>",
Conf.SimpleVolumePa.Color, Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background, Conf.SimpleVolumePa.Background,
@@ -71,7 +76,7 @@ func main() {
Conf.SimpleVolumePa.FontSize, Conf.SimpleVolumePa.FontSize,
) )
Clock := fmt.Sprintf( Conf.Values.ClockTime = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>Thu, 1 Jan 1970 1:00</span>", "<span color='%s' background='%s' font='%s' size='%s'>Thu, 1 Jan 1970 1:00</span>",
Conf.Clock.Color, Conf.Clock.Color,
Conf.Clock.Background, Conf.Clock.Background,
@@ -91,7 +96,7 @@ func main() {
// Kick signal handler // Kick signal handler
go Conf.SigHandler() go Conf.SigHandler()
signal.Notify(Conf.SigChan, signal.Notify(Conf.Channels.SigChan,
syscall.SIGUSR1, syscall.SIGUSR1,
syscall.SIGUSR2, syscall.SIGUSR2,
syscall.SIGQUIT, syscall.SIGQUIT,
@@ -131,7 +136,7 @@ func main() {
} }
if Conf.Cron.Enabled { if Conf.Cron.Enabled {
go lib.RunCron() go Conf.RunCron()
} }
if Conf.Vpn.Enabled { if Conf.Vpn.Enabled {
@@ -156,7 +161,7 @@ func main() {
fmt.Println("[ [],") fmt.Println("[ [],")
for { for {
if <-Conf.UpdateReady { if <-Conf.Channels.UpdateReady {
// Actually build json struct, marshal it and print result // Actually build json struct, marshal it and print result
var j []lib.I3BarOutBlock var j []lib.I3BarOutBlock
@@ -235,7 +240,7 @@ func main() {
Conf.CPUTemp.Background, Conf.CPUTemp.Background,
Conf.CPUTemp.Font, Conf.CPUTemp.Font,
Conf.CPUTemp.FontSize, Conf.CPUTemp.FontSize,
Conf.CPUTemperature, Conf.Values.CPUTemperature,
) )
if Conf.CPUTemp.Separator.Right.Enabled { if Conf.CPUTemp.Separator.Right.Enabled {
@@ -279,9 +284,9 @@ func main() {
Conf.Mem.Background, Conf.Mem.Background,
Conf.Mem.Font, Conf.Mem.Font,
Conf.Mem.FontSize, Conf.Mem.FontSize,
Conf.Memory.Usedpct, Conf.Values.Memory.Usedpct,
Conf.Memory.Shared, Conf.Values.Memory.Shared,
Conf.Memory.Swap, Conf.Values.Memory.Swap,
) )
} else { } else {
b.FullText += fmt.Sprintf( b.FullText += fmt.Sprintf(
@@ -290,8 +295,8 @@ func main() {
Conf.Mem.Background, Conf.Mem.Background,
Conf.Mem.Font, Conf.Mem.Font,
Conf.Mem.FontSize, Conf.Mem.FontSize,
Conf.Memory.Usedpct, Conf.Values.Memory.Usedpct,
Conf.Memory.Shared, Conf.Values.Memory.Shared,
) )
} }
@@ -335,7 +340,7 @@ func main() {
Conf.LA.Background, Conf.LA.Background,
Conf.LA.Font, Conf.LA.Font,
Conf.LA.FontSize, Conf.LA.FontSize,
Conf.La, Conf.Values.La,
) )
if Conf.LA.Separator.Right.Enabled { if Conf.LA.Separator.Right.Enabled {
@@ -378,7 +383,7 @@ func main() {
Conf.NetIf.Background, Conf.NetIf.Background,
Conf.NetIf.Font, Conf.NetIf.Font,
Conf.NetIf.FontSize, Conf.NetIf.FontSize,
Conf.IfStatus, Conf.Values.IfStatus,
) )
if Conf.NetIf.Separator.Right.Enabled { if Conf.NetIf.Separator.Right.Enabled {
@@ -421,7 +426,7 @@ func main() {
Conf.Vpn.Background, Conf.Vpn.Background,
Conf.Vpn.Font, Conf.Vpn.Font,
Conf.Vpn.FontSize, Conf.Vpn.FontSize,
Conf.VPNStatus, Conf.Values.VPNStatus,
) )
if Conf.Vpn.Separator.Right.Enabled { if Conf.Vpn.Separator.Right.Enabled {
@@ -458,7 +463,7 @@ func main() {
) )
} }
b.FullText += Conf.BatteryString b.FullText += Conf.Values.BatteryString
if Conf.Battery.Separator.Right.Enabled { if Conf.Battery.Separator.Right.Enabled {
b.FullText += fmt.Sprintf( b.FullText += fmt.Sprintf(
@@ -496,7 +501,7 @@ func main() {
} }
// Pango format is already applied in plugin src. // Pango format is already applied in plugin src.
b.FullText += SoundVolume b.FullText += Conf.Values.SoundVolume
if Conf.SimpleVolumePa.Separator.Right.Enabled { if Conf.SimpleVolumePa.Separator.Right.Enabled {
b.FullText += fmt.Sprintf( b.FullText += fmt.Sprintf(
@@ -539,7 +544,7 @@ func main() {
Conf.Clock.Background, Conf.Clock.Background,
Conf.Clock.Font, Conf.Clock.Font,
Conf.Clock.FontSize, Conf.Clock.FontSize,
Clock, Conf.Values.ClockTime,
) )
if Conf.Clock.Separator.Right.Enabled { if Conf.Clock.Separator.Right.Enabled {
@@ -559,16 +564,16 @@ func main() {
j = append(j, b) j = append(j, b)
} }
if Conf.PrintOutput && len(j) > 0 { if Conf.Values.PrintOutput && len(j) > 0 {
Conf.MsgChan <- j Conf.Channels.MsgChan <- j
} }
} }
} }
} }
// PrintToI3bar prints info to stdout according to ipc docs (https://i3wm.org/docs/i3bar-protocol.html) // PrintToI3bar prints info to stdout according to ipc docs (https://i3wm.org/docs/i3bar-protocol.html)
func PrintToI3bar(c lib.MyConfig) { func PrintToI3bar(c *lib.MyConfig) {
for message := range c.MsgChan { for message := range c.Channels.MsgChan {
// we do not need to html-encode output, json.Marshal does this forcefully, so invent our own Marshal // we do not need to html-encode output, json.Marshal does this forcefully, so invent our own Marshal
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
encoder := json.NewEncoder(buf) encoder := json.NewEncoder(buf)

View File

@@ -9,7 +9,7 @@ import (
) )
// UpdateBatteryInfo updates info about battery charge. // UpdateBatteryInfo updates info about battery charge.
func (c MyConfig) UpdateBatteryInfo() { func (c *MyConfig) UpdateBatteryInfo() {
var ( var (
ch int ch int
status string status string
@@ -22,11 +22,11 @@ func (c MyConfig) UpdateBatteryInfo() {
if err != nil { if err != nil {
Batts = fmt.Sprintf( Batts = fmt.Sprintf(
"<span font='%s' size='%s'>%s</span><span font='%s' size='%s'> no batt</span>", "<span font='%s' size='%s'>%s</span><span font='%s' size='%s'> no batt</span>",
Conf.Battery.SymbolFont, c.Battery.SymbolFont,
Conf.Battery.SymbolFontSize, c.Battery.SymbolFontSize,
Conf.Battery.Symbol, c.Battery.Symbol,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
) )
} else { } else {
var ( var (
@@ -52,85 +52,85 @@ func (c MyConfig) UpdateBatteryInfo() {
switch { switch {
case ch > 85: case ch > 85:
if Conf.Battery.ChargeColor.Full == "" { if c.Battery.ChargeColor.Full == "" {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} else { } else {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`, `<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.Full, c.Battery.ChargeColor.Full,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} }
case ch < 85 && ch > 40: case ch < 85 && ch > 40:
if Conf.Battery.ChargeColor.AlmostFull == "" { if c.Battery.ChargeColor.AlmostFull == "" {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} else { } else {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`, `<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.AlmostFull, c.Battery.ChargeColor.AlmostFull,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} }
case ch <= 40 && ch >= 10: case ch <= 40 && ch >= 10:
if Conf.Battery.ChargeColor.AlmostEmpty == "" { if c.Battery.ChargeColor.AlmostEmpty == "" {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} else { } else {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`, `<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.AlmostEmpty, c.Battery.ChargeColor.AlmostEmpty,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} }
case ch < 10: case ch < 10:
if Conf.Battery.ChargeColor.Empty == "" { if c.Battery.ChargeColor.Empty == "" {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} else { } else {
chStr = fmt.Sprintf( chStr = fmt.Sprintf(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`, `<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
Conf.Battery.ChargeColor.Empty, c.Battery.ChargeColor.Empty,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
ch, ch,
) )
} }
@@ -138,21 +138,21 @@ func (c MyConfig) UpdateBatteryInfo() {
battsInfo += fmt.Sprintf( battsInfo += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span><span color='%s' background='%s' font='%s' size='%s'>B%d </span>%s<span color='%s' background='%s' font='%s' size='%s'> %s</span>", "<span color='%s' background='%s' font='%s' size='%s'>%s</span><span color='%s' background='%s' font='%s' size='%s'>B%d </span>%s<span color='%s' background='%s' font='%s' size='%s'> %s</span>",
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.SymbolFont, c.Battery.SymbolFont,
Conf.Battery.SymbolFontSize, c.Battery.SymbolFontSize,
Conf.Battery.Symbol, c.Battery.Symbol,
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
i, i,
chStr, chStr,
Conf.Battery.Color, c.Battery.Color,
Conf.Battery.Background, c.Battery.Background,
Conf.Battery.Font, c.Battery.Font,
Conf.Battery.FontSize, c.Battery.FontSize,
status, status,
) )
} }
@@ -162,9 +162,9 @@ func (c MyConfig) UpdateBatteryInfo() {
} }
} }
if c.BatteryString == Batts { if c.Values.BatteryString == Batts {
c.BatteryString = Batts c.Values.BatteryString = Batts
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)

View File

@@ -6,7 +6,7 @@ import (
) )
// UpdateClock get and updates (on i3bar) info about system clock. // UpdateClock get and updates (on i3bar) info about system clock.
func (c MyConfig) UpdateClock() { func (c *MyConfig) UpdateClock() {
for { for {
currentTime := time.Now() currentTime := time.Now()
hours, minutes, _ := currentTime.Clock() hours, minutes, _ := currentTime.Clock()
@@ -17,9 +17,9 @@ func (c MyConfig) UpdateClock() {
myclock := fmt.Sprintf(" %s, %d %s %d % 2d:%02d ", rdow[dow], day, rmonth[month-1], year, hours, minutes) myclock := fmt.Sprintf(" %s, %d %s %d % 2d:%02d ", rdow[dow], day, rmonth[month-1], year, hours, minutes)
if myclock != c.ClockTime { if myclock != c.Values.ClockTime {
c.ClockTime = myclock c.Values.ClockTime = myclock
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)

View File

@@ -11,6 +11,7 @@ import (
"github.com/adrg/xdg" "github.com/adrg/xdg"
"github.com/hjson/hjson-go" "github.com/hjson/hjson-go"
p "github.com/mafik/pulseaudio"
) )
// I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format. // I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format.
@@ -57,10 +58,8 @@ type Separator struct {
} }
type MyConfig struct { type MyConfig struct {
UpdateReady chan bool Values struct {
PrintOutput bool PrintOutput bool
MsgChan chan []I3BarOutBlock
SigChan chan os.Signal
CPUTemperature int64 CPUTemperature int64
BatteryString string BatteryString string
ClockTime string ClockTime string
@@ -68,6 +67,17 @@ type MyConfig struct {
VPNStatus string VPNStatus string
Memory Mem Memory Mem
La string La string
PA *p.Client
SoundVolume string
}
Channels struct {
UpdateReady chan bool
MsgChan chan []I3BarOutBlock
SigChan chan os.Signal
SVPAHandlerChan chan ClickEvent
RunChan chan []string
}
// Default text color // Default text color
Color string `json:"color,omitempty"` Color string `json:"color,omitempty"`
@@ -240,15 +250,12 @@ type MyConfig struct {
} `json:"apps,omitempty"` } `json:"apps,omitempty"`
} }
// Conf global variable with application config.
var Conf MyConfig
// readConf reads and validates config if config does not exist, it puts default config to the same dir where i3 config // readConf reads and validates config if config does not exist, it puts default config to the same dir where i3 config
// is located. // is located.
func ReadConf(DefaultConfig []byte) (MyConfig, error) { func ReadConf(DefaultConfig []byte) (*MyConfig, error) {
var ( var (
path string path string
config MyConfig config *MyConfig
err error err error
buf []byte buf []byte
) )
@@ -294,7 +301,7 @@ func ReadConf(DefaultConfig []byte) (MyConfig, error) {
// We interested in struct as output product: so we parse config to intermediate map then marshal it to json and // We interested in struct as output product: so we parse config to intermediate map then marshal it to json and
// then produced json unmarshal to struct. Not very effective way, but in app lifetime it happens only once. // then produced json unmarshal to struct. Not very effective way, but in app lifetime it happens only once.
var ( var (
sampleConfig MyConfig sampleConfig *MyConfig
tmp map[string]interface{} tmp map[string]interface{}
) )
@@ -1527,19 +1534,19 @@ func ReadConf(DefaultConfig []byte) (MyConfig, error) {
} }
if app.Color == "" { if app.Color == "" {
app.Color = Conf.Color app.Color = sampleConfig.Color
} }
if app.Background == "" { if app.Background == "" {
app.Background = Conf.Background app.Background = sampleConfig.Background
} }
if app.Border == "" { if app.Border == "" {
app.Border = Conf.Color app.Border = sampleConfig.Color
} }
if app.BorderActive == "" { if app.BorderActive == "" {
app.BorderActive = Conf.Color app.BorderActive = sampleConfig.Color
} }
if app.FullText == "" { if app.FullText == "" {

View File

@@ -9,8 +9,8 @@ import (
) )
// UpdateCPUTemperature gets and updates average CPU cores temperature. // UpdateCPUTemperature gets and updates average CPU cores temperature.
func (c MyConfig) UpdateCPUTemperature() { func (c *MyConfig) UpdateCPUTemperature() {
n := len(Conf.CPUTemp.File) n := len(c.CPUTemp.File)
for { for {
var ( var (
@@ -19,7 +19,7 @@ func (c MyConfig) UpdateCPUTemperature() {
tAvg int64 tAvg int64
) )
for i, filename := range Conf.CPUTemp.File { for i, filename := range c.CPUTemp.File {
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
@@ -67,9 +67,9 @@ func (c MyConfig) UpdateCPUTemperature() {
tAvg = tSum / int64(len(temperature)) tAvg = tSum / int64(len(temperature))
} }
if c.CPUTemperature != tAvg { if c.Values.CPUTemperature != tAvg {
c.CPUTemperature = tAvg c.Values.CPUTemperature = tAvg
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@@ -10,7 +10,7 @@ import (
var myCron gocron.Scheduler var myCron gocron.Scheduler
// RunCron parses config part, related to cron tasks and kicks cron to run. // RunCron parses config part, related to cron tasks and kicks cron to run.
func RunCron() { func (c MyConfig) RunCron() {
var err error var err error
myCron, err = gocron.NewScheduler() myCron, err = gocron.NewScheduler()
@@ -21,14 +21,14 @@ func RunCron() {
return return
} }
for _, job := range Conf.Cron.Tasks { for _, job := range c.Cron.Tasks {
_, err := myCron.NewJob( _, err := myCron.NewJob(
gocron.CronJob(job.Time, false), gocron.CronJob(job.Time, false),
gocron.NewTask( gocron.NewTask(
// Сука, просто заспавнить бинарь, ну почему это надо делать через жопу-то? // Сука, просто заспавнить бинарь, ну почему это надо делать через жопу-то?
any( any(
func() bool { func() bool {
RunChan <- job.Cmd c.Channels.RunChan <- job.Cmd
return true return true
}, },

View File

@@ -18,7 +18,7 @@ type WinList struct {
var WL WinList var WL WinList
// UpdateI3WinList subsribes to all window-related events and send them to I3EventParser() for more detailed parsing. // UpdateI3WinList subsribes to all window-related events and send them to I3EventParser() for more detailed parsing.
func (c MyConfig) UpdateI3WinList() { func (c *MyConfig) UpdateI3WinList() {
// TODO: Здесь получить начальный список окон, управляемых i3wm (через GetTree()) и сложить их атрибутику в переменную WL // TODO: Здесь получить начальный список окон, управляемых i3wm (через GetTree()) и сложить их атрибутику в переменную WL
Tree, err := i3.GetTree() Tree, err := i3.GetTree()
@@ -39,7 +39,7 @@ func (c MyConfig) UpdateI3WinList() {
} }
// I3EventParser parses i3wm events and updates WL (aka Windows List). // I3EventParser parses i3wm events and updates WL (aka Windows List).
func (c MyConfig) I3EventParser(e *i3.WindowEvent) { func (c *MyConfig) I3EventParser(e *i3.WindowEvent) {
switch e.Change { switch e.Change {
case "new": case "new":
var ( var (
@@ -68,7 +68,7 @@ func (c MyConfig) I3EventParser(e *i3.WindowEvent) {
count++ count++
WL.Instance.Set(e.Container.WindowProperties.Instance, count) WL.Instance.Set(e.Container.WindowProperties.Instance, count)
c.UpdateReady <- true c.Channels.UpdateReady <- true
case "close": case "close":
countI, exist := WL.Class.Get(e.Container.WindowProperties.Class) countI, exist := WL.Class.Get(e.Container.WindowProperties.Class)
@@ -99,7 +99,7 @@ func (c MyConfig) I3EventParser(e *i3.WindowEvent) {
} }
} }
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
} }
@@ -210,7 +210,7 @@ func FindWindowClass(regexpStr string) bool {
} }
// ExtractProps fills WL stricture collections with instance name and class name of given node (x11, that is). // ExtractProps fills WL stricture collections with instance name and class name of given node (x11, that is).
func (c MyConfig) ExtractProps(n *i3.Node) { func (c *MyConfig) ExtractProps(n *i3.Node) {
var e i3.WindowEvent var e i3.WindowEvent
e.Change = "new" e.Change = "new"
e.Container = *n e.Container = *n

View File

@@ -9,15 +9,12 @@ import (
"time" "time"
) )
// IfStatus global var conaining cumulative status of all monitored net intefaces.
var IfStatus string
// UpdateIfStatus updates network interfaces status for i3bar. // UpdateIfStatus updates network interfaces status for i3bar.
func (c MyConfig) UpdateIfStatus() { func (c *MyConfig) UpdateIfStatus() {
for { for {
var statusSum string var statusSum string
for _, item := range Conf.NetIf.If { for _, item := range c.NetIf.If {
var ( var (
name = item.Name name = item.Name
) )
@@ -35,10 +32,10 @@ func (c MyConfig) UpdateIfStatus() {
} else { } else {
switch strings.TrimSpace(string(operstate)) { switch strings.TrimSpace(string(operstate)) {
case "up": case "up":
StatusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", Conf.NetIf.UpColor) StatusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
operstate = []byte(StatusStr) operstate = []byte(StatusStr)
case "down": case "down":
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", Conf.NetIf.DownColor) statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", c.NetIf.DownColor)
operstate = []byte(statusStr) operstate = []byte(statusStr)
default: default:
operstate = []byte(`?`) operstate = []byte(`?`)
@@ -52,9 +49,9 @@ func (c MyConfig) UpdateIfStatus() {
statusSum += fmt.Sprintf("%s:%s", name, operstate) statusSum += fmt.Sprintf("%s:%s", name, operstate)
} }
if c.IfStatus != statusSum { if c.Values.IfStatus != statusSum {
c.IfStatus = statusSum c.Values.IfStatus = statusSum
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@@ -8,15 +8,15 @@ import (
) )
// UpdateLaStats вытаскивает показание LA за последнюю минуту. // UpdateLaStats вытаскивает показание LA за последнюю минуту.
func (c MyConfig) UpdateLaStats() { func (c *MyConfig) UpdateLaStats() {
for { for {
l, _ := load.Avg() l, _ := load.Avg()
lav := fmt.Sprintf("%.2f", l.Load1) lav := fmt.Sprintf("%.2f", l.Load1)
if c.La != lav { if c.Values.La != lav {
c.La = lav c.Values.La = lav
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@@ -14,11 +14,8 @@ type Mem struct {
Swap uint64 Swap uint64
} }
// Memory stores string with mem stats for i3bar.
var Memory Mem
// UpdateMemStats parses mem info stats. // UpdateMemStats parses mem info stats.
func (c MyConfig) UpdateMemStats() { func (c *MyConfig) UpdateMemStats() {
for { for {
v, err := mem.VirtualMemory() v, err := mem.VirtualMemory()
@@ -38,19 +35,18 @@ func (c MyConfig) UpdateMemStats() {
continue continue
} }
if Conf.Mem.ShowSwap { if c.Mem.ShowSwap {
if Memory.Usedpct != uint64(v.UsedPercent) || Memory.Shared != v.Shared/1024/1024 || if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 || c.Values.Memory.Swap != v.SwapTotal-v.SwapFree {
Memory.Swap != v.SwapTotal-v.SwapFree { c.Values.Memory.Usedpct = uint64(v.UsedPercent)
Memory.Usedpct = uint64(v.UsedPercent) c.Values.Memory.Shared = v.Shared / 1024 / 1024
Memory.Shared = v.Shared / 1024 / 1024 c.Values.Memory.Swap = sw.Used
Memory.Swap = sw.Used c.Channels.UpdateReady <- true
c.UpdateReady <- true
} }
} else { } else {
if Memory.Usedpct != uint64(v.UsedPercent) || Memory.Shared != v.Shared/1024/1024 { if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 {
Memory.Usedpct = uint64(v.UsedPercent) c.Values.Memory.Usedpct = uint64(v.UsedPercent)
Memory.Shared = v.Shared / 1024 / 1024 c.Values.Memory.Shared = v.Shared / 1024 / 1024
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
} }

View File

@@ -10,30 +10,25 @@ import (
p "github.com/mafik/pulseaudio" p "github.com/mafik/pulseaudio"
) )
var SoundVolume = "🔊:0%"
var pa *p.Client
var SVPAHandlerChan = make(chan ClickEvent, 256)
// TODO: https://twin.sh/articles/44/add-a-timeout-to-any-function-in-go timeout pulseaudio calls // TODO: https://twin.sh/articles/44/add-a-timeout-to-any-function-in-go timeout pulseaudio calls
// UpdateVolumeInfo updates info about current Sound Volume. // UpdateVolumeInfo updates info about current Sound Volume.
func (c MyConfig) UpdateVolumeInfo() { func (c *MyConfig) UpdateVolumeInfo() {
var err error var err error
pa, err = p.NewClient() c.Values.PA, err = p.NewClient()
// It can happen if no pulseaudio server running for current user. // It can happen if no pulseaudio server running for current user.
// If no server running we have to run one. // If no server running we have to run one.
if err != nil { if err != nil {
if err := PaReinit(); err != nil { if err := c.PaReinit(); err != nil {
log.Print(err) log.Print(err)
return return
} }
} }
vol, err := pa.Volume() vol, err := c.Values.PA.Volume()
if err != nil { if err != nil {
log.Printf("Unable get volume from pulseaudio server: %s", err) log.Printf("Unable get volume from pulseaudio server: %s", err)
@@ -41,7 +36,7 @@ func (c MyConfig) UpdateVolumeInfo() {
return return
} }
SoundVolume = fmt.Sprintf( c.Values.SoundVolume = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>", "<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
c.SimpleVolumePa.Color, c.SimpleVolumePa.Color,
c.SimpleVolumePa.Background, c.SimpleVolumePa.Background,
@@ -50,7 +45,7 @@ func (c MyConfig) UpdateVolumeInfo() {
c.SimpleVolumePa.Symbol, c.SimpleVolumePa.Symbol,
) )
SoundVolume += fmt.Sprintf( c.Values.SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
c.SimpleVolumePa.Color, c.SimpleVolumePa.Color,
c.SimpleVolumePa.Background, c.SimpleVolumePa.Background,
@@ -59,11 +54,11 @@ func (c MyConfig) UpdateVolumeInfo() {
int64(vol*100), int64(vol*100),
) )
c.UpdateReady <- true c.Channels.UpdateReady <- true
for { for {
// Subscribe to update notification channel, to get info that volume changed. // Subscribe to update notification channel, to get info that volume changed.
pulseUpdate, err := pa.Updates() pulseUpdate, err := c.Values.PA.Updates()
if err != nil { if err != nil {
log.Printf("Unable to subscribe to pulseaudio updates: %s", err) log.Printf("Unable to subscribe to pulseaudio updates: %s", err)
@@ -73,7 +68,7 @@ func (c MyConfig) UpdateVolumeInfo() {
// Rake update events. // Rake update events.
for range pulseUpdate { for range pulseUpdate {
vol, err = pa.Volume() vol, err = c.Values.PA.Volume()
if err != nil { if err != nil {
log.Printf("Unable get volume from pulseaudio server: %s", err) log.Printf("Unable get volume from pulseaudio server: %s", err)
@@ -81,7 +76,7 @@ func (c MyConfig) UpdateVolumeInfo() {
return return
} }
SoundVolume = fmt.Sprintf( c.Values.SoundVolume = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>", "<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
c.SimpleVolumePa.Color, c.SimpleVolumePa.Color,
c.SimpleVolumePa.Background, c.SimpleVolumePa.Background,
@@ -90,7 +85,7 @@ func (c MyConfig) UpdateVolumeInfo() {
c.SimpleVolumePa.Symbol, c.SimpleVolumePa.Symbol,
) )
SoundVolume += fmt.Sprintf( c.Values.SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>", "<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
c.SimpleVolumePa.Color, c.SimpleVolumePa.Color,
c.SimpleVolumePa.Background, c.SimpleVolumePa.Background,
@@ -99,10 +94,10 @@ func (c MyConfig) UpdateVolumeInfo() {
int64(vol*100), int64(vol*100),
) )
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
if err := PaReinit(); err != nil { if err := c.PaReinit(); err != nil {
log.Print(err) log.Print(err)
return return
@@ -110,11 +105,11 @@ func (c MyConfig) UpdateVolumeInfo() {
} }
// This code is unreachable :( // This code is unreachable :(
pa.Close() //nolint:govet c.Values.PA.Close() //nolint:govet
} }
// PaReinit re-inits pulseaudio and connection to it. // PaReinit re-inits pulseaudio and connection to it.
func PaReinit() error { func (c *MyConfig) PaReinit() error {
var err error var err error
// If we out of updates, seems someone killed pulseaudio server. Restart it. // If we out of updates, seems someone killed pulseaudio server. Restart it.
@@ -157,7 +152,7 @@ func PaReinit() error {
// This setting defines if pulseaudio will be run in manner that allows it to exit is other login detected (how // This setting defines if pulseaudio will be run in manner that allows it to exit is other login detected (how
// they guess it - I do not know). In general case we do not want to allow pa to exit and leave our session without // they guess it - I do not know). In general case we do not want to allow pa to exit and leave our session without
// audio. // audio.
if Conf.SimpleVolumePa.DontExitOnLogin { if c.SimpleVolumePa.DontExitOnLogin {
// Do not exit on any kind of login/logout events. // Do not exit on any kind of login/logout events.
cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start") cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start")
} else { } else {
@@ -169,7 +164,7 @@ func PaReinit() error {
return fmt.Errorf("unable to initialize pulseaudio server instance: %w", err) return fmt.Errorf("unable to initialize pulseaudio server instance: %w", err)
} }
pa, err = p.NewClient() c.Values.PA, err = p.NewClient()
if err != nil { if err != nil {
return fmt.Errorf("unable to make client connection to pulseaudio: %w", err) return fmt.Errorf("unable to make client connection to pulseaudio: %w", err)
@@ -178,21 +173,21 @@ func PaReinit() error {
return err return err
} }
func (c MyConfig) SVPAHandler() { func (c *MyConfig) SVPAHandler() {
for e := range SVPAHandlerChan { for e := range c.Channels.SVPAHandlerChan {
if e.Button == 3 { if e.Button == 3 {
RunChan <- Conf.SimpleVolumePa.RightClickCmd c.Channels.RunChan <- c.SimpleVolumePa.RightClickCmd
continue continue
} }
vol, err := pa.Volume() vol, err := c.Values.PA.Volume()
if err != nil { if err != nil {
if err := PaReinit(); err != nil { if err := c.PaReinit(); err != nil {
log.Printf("Unable to get pulseaudio volume: %s", err) log.Printf("Unable to get pulseaudio volume: %s", err)
} else { } else {
vol, err = pa.Volume() vol, err = c.Values.PA.Volume()
if err != nil { if err != nil {
log.Printf("Unable to get volume pulseaudio server behaves weirdly: %s", err) log.Printf("Unable to get volume pulseaudio server behaves weirdly: %s", err)
@@ -201,25 +196,25 @@ func (c MyConfig) SVPAHandler() {
} }
switch e.Button { switch e.Button {
case Conf.SimpleVolumePa.WheelUp: case c.SimpleVolumePa.WheelUp:
vol += float32(Conf.SimpleVolumePa.Step) / 100 vol += float32(c.SimpleVolumePa.Step) / 100
if vol > (float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100) { if vol > (float32(c.SimpleVolumePa.MaxVolumeLimit) / 100) {
vol = float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100 vol = float32(c.SimpleVolumePa.MaxVolumeLimit) / 100
} }
if err := pa.SetVolume(vol); err != nil { if err := c.Values.PA.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err) log.Printf("Unable to set pulseaudio volume: %s", err)
} }
case Conf.SimpleVolumePa.WheelDown: case c.SimpleVolumePa.WheelDown:
vol -= float32(Conf.SimpleVolumePa.Step) / 100 vol -= float32(c.SimpleVolumePa.Step) / 100
if vol < 0 { if vol < 0 {
vol = 0 vol = 0
} }
if err := pa.SetVolume(vol); err != nil { if err := c.Values.PA.SetVolume(vol); err != nil {
log.Printf("Unable to set pulseaudio volume: %s", err) log.Printf("Unable to set pulseaudio volume: %s", err)
} }
} }

View File

@@ -9,20 +9,20 @@ import (
var PrintOutput = true var PrintOutput = true
// SigHandler OS signal handler. // SigHandler OS signal handler.
func (c MyConfig) SigHandler() { func (c *MyConfig) SigHandler() {
for s := range c.SigChan { for s := range c.Channels.SigChan {
switch s { switch s {
case syscall.SIGUSR1: case syscall.SIGUSR1:
log.Print("Got SIGUSR1, stopping output") log.Print("Got SIGUSR1, stopping output")
PrintOutput = false c.Values.PrintOutput = false
case syscall.SIGUSR2: case syscall.SIGUSR2:
log.Print("Got SIGUSR2, resuming output") log.Print("Got SIGUSR2, resuming output")
PrintOutput = true c.Values.PrintOutput = true
c.UpdateReady <- true c.Channels.UpdateReady <- true
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
os.Exit(0) os.Exit(0)

View File

@@ -8,12 +8,9 @@ import (
"time" "time"
) )
// RunChan to this channel we send command and its argv to execute as separate process.
var RunChan = make(chan []string, 128)
// Spawner forks and execs given program, and also detaches form its control tty. // Spawner forks and execs given program, and also detaches form its control tty.
func (c MyConfig) Spawner() { func (c *MyConfig) Spawner() {
for prg := range RunChan { for prg := range c.Channels.RunChan {
devnullR, _ := os.Open(os.DevNull) devnullR, _ := os.Open(os.DevNull)
devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644) devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644)
@@ -48,7 +45,7 @@ func (c MyConfig) Spawner() {
} }
// CleanZombies reaps processes spawned by Spawner() and already exited. // CleanZombies reaps processes spawned by Spawner() and already exited.
func (c MyConfig) CleanZombies() { func (c *MyConfig) CleanZombies() {
r := syscall.Rusage{} r := syscall.Rusage{}
for { for {

View File

@@ -26,7 +26,7 @@ type ClickEvent struct {
// ParseStdin tries to parse text that i3bar prints to our stdin. Currently - it is mouse click events on different // ParseStdin tries to parse text that i3bar prints to our stdin. Currently - it is mouse click events on different
// area names of i3bar. // area names of i3bar.
func (c MyConfig) ParseStdin() { func (c *MyConfig) ParseStdin() {
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
// De-facto it is jsonl, except first line is garbage. Also, first symbol in each strint garbage too. // De-facto it is jsonl, except first line is garbage. Also, first symbol in each strint garbage too.
@@ -84,35 +84,35 @@ func (c MyConfig) ParseStdin() {
// Clock clicks parse. // Clock clicks parse.
if e.Name == "wallclock" { if e.Name == "wallclock" {
if Conf.Clock.LeftClick.Enabled && e.Button == 1 { if c.Clock.LeftClick.Enabled && e.Button == 1 {
RunChan <- Conf.Clock.LeftClick.Cmd c.Channels.RunChan <- c.Clock.LeftClick.Cmd
} else if Conf.Clock.RightClick.Enabled && e.Button == 3 { } else if c.Clock.RightClick.Enabled && e.Button == 3 {
RunChan <- Conf.Clock.RightClick.Cmd c.Channels.RunChan <- c.Clock.RightClick.Cmd
} }
continue continue
} }
if e.Name == "simple-volume-pa" { if e.Name == "simple-volume-pa" {
if Conf.SimpleVolumePa.Enabled { if c.SimpleVolumePa.Enabled {
SVPAHandlerChan <- e c.Channels.SVPAHandlerChan <- e
} }
continue continue
} }
if !Conf.AppButtons.Enabled { if !c.AppButtons.Enabled {
continue continue
} }
for _, app := range Conf.Apps { for _, app := range c.Apps {
switch { switch {
case app.Name != "" && app.Instance != "": case app.Name != "" && app.Instance != "":
if app.Name == e.Name && app.Instance == e.Instance { if app.Name == e.Name && app.Instance == e.Instance {
prg := append([]string{}, app.Cmd) prg := append([]string{}, app.Cmd)
prg = append(prg, app.Args...) prg = append(prg, app.Args...)
RunChan <- prg c.Channels.RunChan <- prg
break break
} }
@@ -120,13 +120,13 @@ func (c MyConfig) ParseStdin() {
prg := append([]string{}, app.Cmd) prg := append([]string{}, app.Cmd)
prg = append(prg, app.Args...) prg = append(prg, app.Args...)
RunChan <- prg c.Channels.RunChan <- prg
case app.Instance != "" && e.Instance == app.Instance: case app.Instance != "" && e.Instance == app.Instance:
prg := append([]string{}, app.Cmd) prg := append([]string{}, app.Cmd)
prg = append(prg, app.Args...) prg = append(prg, app.Args...)
RunChan <- prg c.Channels.RunChan <- prg
} }
} }
} }

View File

@@ -8,7 +8,7 @@ import (
) )
// UpdateVPNStatus periodically update status of openvpn daemon. // UpdateVPNStatus periodically update status of openvpn daemon.
func (c MyConfig) UpdateVPNStatus() { func (c *MyConfig) UpdateVPNStatus() {
var ( var (
vpnCStatus string vpnCStatus string
tcpCheck string tcpCheck string
@@ -17,28 +17,28 @@ func (c MyConfig) UpdateVPNStatus() {
for { for {
if c.VPNFileCheck() { if c.VPNFileCheck() {
if Conf.Vpn.UpColor == "" { if c.Vpn.UpColor == "" {
vpnCheck = `⍋` vpnCheck = `⍋`
} else { } else {
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍋</span>`, c.Vpn.UpColor) vpnCheck = fmt.Sprintf(`<span foreground="%s">⍋</span>`, c.Vpn.UpColor)
} }
} else { } else {
if Conf.Vpn.DownColor == "" { if c.Vpn.DownColor == "" {
vpnCheck = `⍒` vpnCheck = `⍒`
} else { } else {
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍒</span>`, c.Vpn.DownColor) vpnCheck = fmt.Sprintf(`<span foreground="%s">⍒</span>`, c.Vpn.DownColor)
} }
} }
if Conf.Vpn.TCPCheck.Enabled { if c.Vpn.TCPCheck.Enabled {
if c.VPNTCPCheck() { if c.VPNTCPCheck() {
if Conf.Vpn.UpColor == "" { if c.Vpn.UpColor == "" {
tcpCheck = `✔` tcpCheck = `✔`
} else { } else {
tcpCheck = fmt.Sprintf(`<span foreground="%s">✔</span>`, c.Vpn.UpColor) tcpCheck = fmt.Sprintf(`<span foreground="%s">✔</span>`, c.Vpn.UpColor)
} }
} else { } else {
if Conf.Vpn.DownColor == "" { if c.Vpn.DownColor == "" {
tcpCheck = `✘` tcpCheck = `✘`
} else { } else {
tcpCheck = fmt.Sprintf(`<span foreground="%s">✘</span>`, c.Vpn.DownColor) tcpCheck = fmt.Sprintf(`<span foreground="%s">✘</span>`, c.Vpn.DownColor)
@@ -50,9 +50,9 @@ func (c MyConfig) UpdateVPNStatus() {
vpnCStatus = fmt.Sprintf("VPN:%s", vpnCheck) vpnCStatus = fmt.Sprintf("VPN:%s", vpnCheck)
} }
if c.VPNStatus != vpnCStatus { if c.Values.VPNStatus != vpnCStatus {
c.VPNStatus = vpnCStatus c.Values.VPNStatus = vpnCStatus
c.UpdateReady <- true c.Channels.UpdateReady <- true
} }
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
@@ -60,7 +60,7 @@ func (c MyConfig) UpdateVPNStatus() {
} }
// VPNTCPCheck intended to check arbitrary service inside vpn segment, to indicate that openvpn sevice not stoned. // VPNTCPCheck intended to check arbitrary service inside vpn segment, to indicate that openvpn sevice not stoned.
func (c MyConfig) VPNTCPCheck() bool { func (c *MyConfig) VPNTCPCheck() bool {
conn, err := net.DialTimeout( conn, err := net.DialTimeout(
"tcp", "tcp",
fmt.Sprintf("%s:%d", c.Vpn.TCPCheck.Host, c.Vpn.TCPCheck.Port), fmt.Sprintf("%s:%d", c.Vpn.TCPCheck.Host, c.Vpn.TCPCheck.Port),
@@ -76,7 +76,7 @@ func (c MyConfig) VPNTCPCheck() bool {
} }
// VPNFileCheck checks modification time of openvpn-status file. // VPNFileCheck checks modification time of openvpn-status file.
func (c MyConfig) VPNFileCheck() bool { func (c *MyConfig) VPNFileCheck() bool {
var ( var (
fi os.FileInfo fi os.FileInfo
err error err error