Merge branch 'master' into patch-3
This commit is contained in:
commit
7096393dd5
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -15,8 +15,8 @@ jobs:
|
|||
uses: actions/checkout@master
|
||||
|
||||
- name: Compile
|
||||
uses: xxxserxxx/actions/golang-build@v2.0.3
|
||||
uses: xxxserxxx/actions/golang-build@v2.2.1
|
||||
env:
|
||||
SRCPATH: ./cmd/gotop
|
||||
with:
|
||||
args: darwin/amd64/1 darwin/arm64/1 linux/amd64 linux/386 linux/arm64 linux/arm7 linux/arm6 linux/arm5 windows/amd64/1 windows/386/1 freebsd/amd64/1
|
||||
args: darwin/amd64/1 darwin/arm64/1 linux/amd64 linux/386 linux/arm64 linux/arm7 linux/arm6 linux/arm5 windows/amd64/1 windows/386/1 freebsd/amd64/1
|
||||
|
|
4
.github/workflows/prerelease.yml
vendored
4
.github/workflows/prerelease.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
uses: actions/checkout@master
|
||||
|
||||
- name: Make binaries
|
||||
uses: xxxserxxx/actions/golang-build@v2.0.3
|
||||
uses: xxxserxxx/actions/golang-build@v2.2.1
|
||||
with:
|
||||
args: darwin/amd64/1 darwin/arm64/1 linux/amd64 linux/386 linux/arm64 linux/arm7 linux/arm6 linux/arm5 windows/amd64/1 windows/386/1 freebsd/amd64/1
|
||||
env:
|
||||
|
@ -36,3 +36,5 @@ jobs:
|
|||
files: |
|
||||
.release/*.tgz
|
||||
.release/*.zip
|
||||
.release/*.rpm
|
||||
.release/*.deb
|
||||
|
|
33
build/gotop.conf
Normal file
33
build/gotop.conf
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Scale graphs to this level; 7 is the default, 2 is zoomed out.
|
||||
graphhorizontalscale=7
|
||||
# If true, start the UI with the help visible
|
||||
helpvisible=false
|
||||
# The color scheme to use. See `--list colorschemes`
|
||||
colorscheme=default
|
||||
# How frequently to update the UI, in nanoseconds
|
||||
updateinterval=1000000000
|
||||
# If true, show the average CPU load
|
||||
averagecpu=false
|
||||
# If true, show load per CPU
|
||||
percpuload=true
|
||||
# Temperature units. C for Celcius, F for Fahrenheit
|
||||
tempscale=C
|
||||
# If true, display a status bar
|
||||
statusbar=false
|
||||
# The network interface to monitor
|
||||
netinterface=all
|
||||
# A layout name. See `--list layouts`
|
||||
layout=default
|
||||
# The maximum log file size, in bytes
|
||||
maxlogsize=5000000
|
||||
# If set, export data as Promethius metrics on the interface:port.
|
||||
# E.g., `:8080` (colon is required, interface is not)
|
||||
#metricsexportport=
|
||||
# Display network IO in mpbs if true
|
||||
mbps=false
|
||||
# A list of enabled temp sensors. See `--list devices`
|
||||
#temperatures=
|
||||
# Enable NVidia GPU metrics.
|
||||
nvidia=false
|
||||
# To configure the NVidia refresh rate, set a duration:
|
||||
#nvidiarefresh=30s
|
|
@ -1,15 +1,31 @@
|
|||
name: "gotop"
|
||||
arch: "amd64"
|
||||
platform: "linux"
|
||||
version: "v${VERSION}"
|
||||
section: "default"
|
||||
priority: "extra"
|
||||
maintainer: "Sean Russell <ser@ser1.net>"
|
||||
description: |
|
||||
A terminal based graphical activity monitor inspired by gtop and vtop
|
||||
vendor: "Sean Russell"
|
||||
homepage: "https://github.com/xxxserxxx/gotop"
|
||||
license: "GNU Affero General Public License v3.0"
|
||||
bindir: "/usr/local/bin"
|
||||
files:
|
||||
build/gotop: "/usr/local/bin/gotop"
|
||||
name: gotop
|
||||
arch: ${GOARCH}
|
||||
platform: linux
|
||||
version: v${VERSION}
|
||||
version_schema: semver
|
||||
version_metadata: git
|
||||
section: default
|
||||
priority: extra
|
||||
maintainer: Sean Russell <ser@ser1.net>
|
||||
description: A terminal based graphical activity monitor inspired by gtop and vtop
|
||||
vendor: Sean Russell
|
||||
homepage: https://github.com/xxxserxxx/gotop
|
||||
license: The MIT License (Festival variant)
|
||||
contents:
|
||||
# The executable
|
||||
- src: ${EXECUTABLE}
|
||||
dst: /usr/bin/gotop
|
||||
|
||||
# Default configuration
|
||||
- src: build/gotop.conf
|
||||
dst: /etc/gotop/gotop.conf
|
||||
type: config|noreplace
|
||||
|
||||
# Contributed layouts
|
||||
- src: layouts/htop
|
||||
dst: /etc/gotop/htop
|
||||
type: config|noreplace
|
||||
|
||||
# Manpage
|
||||
- src: ${MANPAGE}
|
||||
dst: /usr/share/man8/gotop.8.gz
|
||||
|
|
96
cmd/gotop/description.txt
Normal file
96
cmd/gotop/description.txt
Normal file
|
@ -0,0 +1,96 @@
|
|||
gotop shows system information in a terminal UI. It can be configured to have
|
||||
different layouts, color schemes, and widgets, and it is able to show
|
||||
information from other computers.
|
||||
|
||||
Anything you change on the command line can be written to a config file
|
||||
using the `--write-config` argument, which can then be edited further.
|
||||
Just get your arguments the way you like, then run gotop again with the same
|
||||
arguments and the `--write-config` flag, and gotop will persist your
|
||||
options.
|
||||
|
||||
Colorschemes are json files; put them in the config directory (usually
|
||||
~/.config/gotop/{name}.json) and load them with the `-c {name}` argument.
|
||||
The keys are:
|
||||
|
||||
Fg -- int, foreground color
|
||||
Bg -- int, background color
|
||||
BorderLabel -- int, color of widget text
|
||||
BorderLine -- int, color of borders
|
||||
CPULines -- array of ints for the colors of lines
|
||||
BattLines -- array of ints for the colors of lines
|
||||
MemLines -- array of ints for the colors of lines
|
||||
ProcCursor -- int, color of the cursor in the process widget
|
||||
Sparkline -- int, color of the graph bars
|
||||
DiskBar -- int, color of the disk bars
|
||||
TempLow -- int, color used for low temperatures
|
||||
TempHigh -- int, color used for high temperatures
|
||||
|
||||
For example:
|
||||
|
||||
{ "Fg": 7, "CPULines": [4, 3, 2, 1, 5, 6, 7, 8] }
|
||||
|
||||
Colorschemes are referred to by their name minus the .json suffix. More
|
||||
examples are here:
|
||||
|
||||
https://github.com/xxxserxxx/gotop/tree/master/colorschemes
|
||||
|
||||
Layout files are plain text files, with widget names on rows roughly representing
|
||||
a grid. The format is ROWSPAN:WIDGETNAME/COLSPAN. COLSPAN is relative to the
|
||||
rest of the line, so a line saying "cpu mem/3" will give the CPU widget 25% of
|
||||
the width, and the memory widget 75% of the width. ROWSPAN is the height of
|
||||
the widget, so "2:cpu mem" will make the CPU widget 2 rows high, and the memory
|
||||
widget 1 row high. An example is:
|
||||
|
||||
2:cpu
|
||||
disk/1 2:mem/2
|
||||
temp
|
||||
2:net 2:procs
|
||||
|
||||
Save your layout under any file name either in the config directory or your current
|
||||
directory and reference the file name with the `-l` argument. More details about
|
||||
the rules are here:
|
||||
|
||||
https://github.com/xxxserxxx/gotop/blob/master/docs/layouts.md
|
||||
|
||||
and examples are here:
|
||||
|
||||
https://github.com/xxxserxxx/gotop/tree/master/layouts
|
||||
|
||||
gotop can function as both a metrics exporter and viewer. As an exporter, it
|
||||
exports Prometheus metrics, and it does not handle either encryption or
|
||||
authentication, and so should be run behind a reverse proxy. When gotop is run
|
||||
with the `-x` argument, gotop will export metrics on the given port. To try it,
|
||||
run
|
||||
|
||||
gotop -x :8884
|
||||
|
||||
and then from another shell, run:
|
||||
|
||||
curl http://localhost:8884/metrics
|
||||
|
||||
To show these metrics in gotop, instead of curl run:
|
||||
|
||||
gotop --remote-url http://localhost:8884/metrics
|
||||
|
||||
You will see additional values in your widgets. To monitor remote machines,
|
||||
run gotop on them with the `-x` export flag behind a reverse proxy such as
|
||||
Caddy:
|
||||
|
||||
myserver.net {
|
||||
basicauth / gtuser gtpass
|
||||
reverse-proxy /metrics http://localhost:8884
|
||||
}
|
||||
|
||||
and then on your local gotop:
|
||||
|
||||
gotop --remote-url https://gtuser:gtpass@myserver.net/metrics
|
||||
|
||||
Config files, layouts, and color schemes are searched for (in order):
|
||||
|
||||
- In the current directory
|
||||
- In $XDG_CONFIG_DIR/gotop
|
||||
- In /etc/gotop (on Linux and MacOS)
|
||||
|
||||
More information and detailed documentation can found at
|
||||
https://github.com/xxxserxxx/gotop`
|
||||
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -21,10 +22,10 @@ import (
|
|||
|
||||
"github.com/VictoriaMetrics/metrics"
|
||||
jj "github.com/cloudfoundry-attic/jibber_jabber"
|
||||
"github.com/droundy/goopt"
|
||||
ui "github.com/gizak/termui/v3"
|
||||
"github.com/shibukawa/configdir"
|
||||
"github.com/xxxserxxx/lingo/v2"
|
||||
"github.com/xxxserxxx/opflag"
|
||||
|
||||
"github.com/xxxserxxx/gotop/v4"
|
||||
"github.com/xxxserxxx/gotop/v4/colorschemes"
|
||||
|
@ -55,62 +56,78 @@ var (
|
|||
tr lingo.Translations
|
||||
)
|
||||
|
||||
//go:embed "description.txt"
|
||||
var description string
|
||||
|
||||
func parseArgs() error {
|
||||
cds := conf.ConfigDir.QueryFolders(configdir.All)
|
||||
cpaths := make([]string, len(cds))
|
||||
for i, p := range cds {
|
||||
cpaths[i] = p.Path
|
||||
}
|
||||
help := opflag.BoolP("help", "h", false, tr.Value("args.help"))
|
||||
color := opflag.StringP("color", "c", conf.Colorscheme.Name, tr.Value("args.color"))
|
||||
opflag.IntVarP(&conf.GraphHorizontalScale, "graphscale", "S", conf.GraphHorizontalScale, tr.Value("args.scale"))
|
||||
version := opflag.BoolP("version", "v", false, tr.Value("args.version"))
|
||||
versioN := opflag.BoolP("", "V", false, tr.Value("args.version"))
|
||||
opflag.BoolVarP(&conf.PercpuLoad, "percpu", "p", conf.PercpuLoad, tr.Value("args.percpu"))
|
||||
opflag.BoolVar(&conf.NoPercpuLoad, "no-percpu", conf.NoPercpuLoad, tr.Value("args.no-percpu"))
|
||||
opflag.BoolVarP(&conf.AverageLoad, "averagecpu", "a", conf.AverageLoad, tr.Value("args.cpuavg"))
|
||||
opflag.BoolVar(&conf.NoAverageLoad, "no-averagecpu", conf.NoAverageLoad, tr.Value("args.no-cpuavg"))
|
||||
fahrenheit := opflag.BoolP("fahrenheit", "f", conf.TempScale == 'F', tr.Value("args.temp"))
|
||||
opflag.BoolVarP(&conf.Statusbar, "statusbar", "s", conf.Statusbar, tr.Value("args.statusbar"))
|
||||
opflag.BoolVar(&conf.NoStatusbar, "no-statusbar", conf.NoStatusbar, tr.Value("args.no-statusbar"))
|
||||
opflag.DurationVarP(&conf.UpdateInterval, "rate", "r", conf.UpdateInterval, tr.Value("args.rate"))
|
||||
opflag.StringVarP(&conf.Layout, "layout", "l", conf.Layout, tr.Value("args.layout"))
|
||||
opflag.StringVarP(&conf.NetInterface, "interface", "i", "all", tr.Value("args.net"))
|
||||
opflag.StringVarP(&conf.ExportPort, "export", "x", conf.ExportPort, tr.Value("args.export"))
|
||||
opflag.BoolVarP(&conf.Mbps, "mbps", "", conf.Mbps, tr.Value("args.mbps"))
|
||||
opflag.BoolVar(&conf.NoMbps, "no-mbps", conf.NoMbps, tr.Value("args.no-mbps"))
|
||||
opflag.BoolVar(&conf.Test, "test", conf.Test, tr.Value("args.test"))
|
||||
opflag.BoolVar(&conf.NoTest, "no-test", conf.NoTest, tr.Value("args.no-test"))
|
||||
opflag.StringP("", "C", "", tr.Value("args.conffile"))
|
||||
opflag.BoolVarP(&conf.Nvidia, "nvidia", "", conf.Nvidia, "Enable NVidia GPU support")
|
||||
opflag.BoolVarP(&conf.NoNvidia, "no-nvidia", "", conf.NoNvidia, "Disable NVidia GPU support")
|
||||
list := opflag.String("list", "", tr.Value("args.list"))
|
||||
wc := opflag.Bool("write-config", false, tr.Value("args.write"))
|
||||
opflag.SortFlags = false
|
||||
opflag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, tr.Value("usage", os.Args[0]))
|
||||
opflag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "Project home: https://github.com/xxxserxxx/gotop\n")
|
||||
goopt.Summary = "A terminal based graphical activity monitor, inspired by gtop and vtop"
|
||||
goopt.Version = Version
|
||||
goopt.Description = func() string {
|
||||
return description
|
||||
}
|
||||
opflag.Parse()
|
||||
if *version || *versioN {
|
||||
fmt.Printf("gotop %s (%s)\n", Version, BuildDate)
|
||||
os.Exit(0)
|
||||
color := goopt.String([]string{"--color", "-c"}, conf.Colorscheme.Name, tr.Value("args.color"))
|
||||
graphhorizontalscale := goopt.Int([]string{"--graphscale", "-S"}, conf.GraphHorizontalScale, tr.Value("args.scale"))
|
||||
version := goopt.Flag([]string{"-v", "-V", "--version"}, []string{}, tr.Value("args.version"), "")
|
||||
percpuload := goopt.Flag([]string{"--percpu", "-p"}, []string{"--no-percpu"}, tr.Value("args.percpu"), tr.Value("args.no-percpu"))
|
||||
averageload := goopt.Flag([]string{"--averagecpu", "-a"}, []string{"--no-averagecpu"}, tr.Value("args.cpuavg"), tr.Value("args.no-cpuavg"))
|
||||
tempScale := goopt.Flag([]string{"--fahrenheit"}, []string{"--celsius"}, tr.Value("args.temp"), tr.Value("args.tempc"))
|
||||
statusbar := goopt.Flag([]string{"--statusbar", "-s"}, []string{"--no-statusbar"}, tr.Value("args.statusbar"), tr.Value("args.no-statusbar"))
|
||||
updateinterval := goopt.String([]string{"--rate", "-r"}, conf.UpdateInterval.String(), tr.Value("args.rate"))
|
||||
layout := goopt.String([]string{"--layout", "-l"}, conf.Layout, tr.Value("args.layout"))
|
||||
netinterface := goopt.String([]string{"--interface", "-i"}, "all", tr.Value("args.net"))
|
||||
exportport := goopt.String([]string{"--export", "-x"}, conf.ExportPort, tr.Value("args.export"))
|
||||
mbps := goopt.Flag([]string{"--mbps"}, []string{"--bytes"}, tr.Value("args.mbps"), tr.Value("args.no-mbps"))
|
||||
test := goopt.Flag([]string{"--test"}, []string{"--no-test"}, tr.Value("args.test"), tr.Value("args.no-test"))
|
||||
// This is so the flag package doesn't barf on an unrecognized flag; it's processed earlier
|
||||
goopt.String([]string{"-C"}, "", tr.Value("args.conffile"))
|
||||
nvidia := goopt.Flag([]string{"--nvidia"}, []string{"--no-nvidia"}, tr.Value("args.nvidia"), tr.Value("args.no-nvidia"))
|
||||
list := goopt.String([]string{"--list"}, "", tr.Value("args.list"))
|
||||
wc := goopt.Flag([]string{"--write-config"}, []string{}, tr.Value("args.write"), "")
|
||||
goopt.Parse(nil)
|
||||
|
||||
conf.PercpuLoad = *percpuload
|
||||
conf.GraphHorizontalScale = *graphhorizontalscale
|
||||
conf.PercpuLoad = *percpuload
|
||||
conf.AverageLoad = *averageload
|
||||
conf.Statusbar = *statusbar
|
||||
conf.Layout = *layout
|
||||
conf.NetInterface = *netinterface
|
||||
conf.ExportPort = *exportport
|
||||
conf.Mbps = *mbps
|
||||
conf.Nvidia = *nvidia
|
||||
conf.AverageLoad = *averageload
|
||||
conf.Test = *test
|
||||
conf.Statusbar = *statusbar
|
||||
conf.Mbps = *mbps
|
||||
conf.Nvidia = *nvidia
|
||||
if upInt, err := time.ParseDuration(*updateinterval); err == nil {
|
||||
conf.UpdateInterval = upInt
|
||||
} else {
|
||||
fmt.Printf("Update interval must be a time interval such as '10s' or '1m'")
|
||||
os.Exit(1)
|
||||
}
|
||||
if *help {
|
||||
opflag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
cs, err := colorschemes.FromName(conf.ConfigDir, *color)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.Colorscheme = cs
|
||||
if *fahrenheit {
|
||||
if *tempScale {
|
||||
conf.TempScale = 'F'
|
||||
} else {
|
||||
conf.TempScale = 'C'
|
||||
}
|
||||
|
||||
if *version {
|
||||
fmt.Printf("gotop %s (%s)\n", Version, BuildDate)
|
||||
os.Exit(0)
|
||||
}
|
||||
if *color != "" {
|
||||
cs, err := colorschemes.FromName(conf.ConfigDir, *color)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.Colorscheme = cs
|
||||
}
|
||||
if *list != "" {
|
||||
switch *list {
|
||||
case "layouts":
|
||||
|
@ -168,25 +185,6 @@ func parseArgs() error {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
if conf.NoStatusbar {
|
||||
conf.Statusbar = false
|
||||
}
|
||||
if conf.NoPercpuLoad {
|
||||
conf.PercpuLoad = false
|
||||
}
|
||||
if conf.NoAverageLoad {
|
||||
conf.AverageLoad = false
|
||||
}
|
||||
if conf.NoMbps {
|
||||
conf.Mbps = false
|
||||
}
|
||||
if conf.NoTest {
|
||||
conf.Test = false
|
||||
}
|
||||
if conf.NoNvidia {
|
||||
conf.Nvidia = false
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -379,6 +377,7 @@ func eventLoop(c gotop.Config, grid *layout.MyGrid) {
|
|||
}
|
||||
|
||||
// FIXME CPU use regression
|
||||
// TODO add CPU freq
|
||||
func main() {
|
||||
// TODO: Make this an option, for performance testing
|
||||
//go func() {
|
||||
|
|
|
@ -29,6 +29,9 @@ func SetTr(tra lingo.Translations) {
|
|||
// directories for a scheme matching the name. The search order
|
||||
// is the same as for config files.
|
||||
func FromName(confDir configdir.ConfigDir, c string) (Colorscheme, error) {
|
||||
if c == "" {
|
||||
c = "default"
|
||||
}
|
||||
if cs, ok := registry[c]; ok {
|
||||
return cs, nil
|
||||
}
|
||||
|
|
12
config.go
12
config.go
|
@ -34,26 +34,20 @@ type Config struct {
|
|||
Colorscheme colorschemes.Colorscheme
|
||||
UpdateInterval time.Duration
|
||||
AverageLoad bool
|
||||
NoAverageLoad bool
|
||||
PercpuLoad bool
|
||||
NoPercpuLoad bool
|
||||
Statusbar bool
|
||||
NoStatusbar bool
|
||||
TempScale widgets.TempScale
|
||||
NetInterface string
|
||||
Layout string
|
||||
MaxLogSize int64
|
||||
ExportPort string
|
||||
Mbps bool
|
||||
NoMbps bool
|
||||
Temps []string
|
||||
Test bool
|
||||
NoTest bool
|
||||
ExtensionVars map[string]string
|
||||
ConfigFile string
|
||||
Tr lingo.Translations
|
||||
Nvidia bool
|
||||
NoNvidia bool
|
||||
NvidiaRefresh time.Duration
|
||||
}
|
||||
|
||||
|
@ -67,15 +61,9 @@ func NewConfig() Config {
|
|||
HelpVisible: false,
|
||||
UpdateInterval: time.Second,
|
||||
AverageLoad: false,
|
||||
NoAverageLoad: false,
|
||||
PercpuLoad: true,
|
||||
NoPercpuLoad: false,
|
||||
TempScale: widgets.Celsius,
|
||||
Statusbar: false,
|
||||
NoStatusbar: false,
|
||||
NoMbps: false,
|
||||
NoTest: false,
|
||||
NoNvidia: false,
|
||||
NetInterface: widgets.NetInterfaceAll,
|
||||
MaxLogSize: 5000000,
|
||||
Layout: "default",
|
||||
|
|
|
@ -10,11 +10,12 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xxxserxxx/opflag"
|
||||
"github.com/droundy/goopt"
|
||||
)
|
||||
|
||||
var name string
|
||||
var remote_url string
|
||||
var nameP *string
|
||||
var remoteUrlP *string
|
||||
var sleepP *string
|
||||
var sleep time.Duration
|
||||
var remoteLock sync.Mutex
|
||||
|
||||
|
@ -26,9 +27,9 @@ var remoteLock sync.Mutex
|
|||
// FIXME high CPU use when remote goes offline
|
||||
// FIXME higher CPU use when using remote in general
|
||||
func init() {
|
||||
opflag.StringVarP(&name, "remote-name", "", "", "Remote: name of remote gotop")
|
||||
opflag.StringVarP(&remote_url, "remote-url", "", "", "Remote: URL of remote gotop")
|
||||
opflag.DurationVarP(&sleep, "remote-refresh", "", 0, "Remote: Frequency to refresh data, in seconds")
|
||||
nameP = goopt.String([]string{"--remote-name"}, "", "Remote: name of remote gotop")
|
||||
remoteUrlP = goopt.String([]string{"--remote-url"}, "", "Remote: URL of remote gotop")
|
||||
sleepP = goopt.String([]string{"--remote-refresh"}, "", "Remote: Frequency to refresh data, in seconds")
|
||||
|
||||
RegisterStartup(startup)
|
||||
}
|
||||
|
@ -47,27 +48,34 @@ func startup(vars map[string]string) error {
|
|||
|
||||
remoteLock = sync.Mutex{}
|
||||
remotes := parseConfig(vars)
|
||||
// Don't set anything up if there's nothing to do
|
||||
if (name == "" || remote_url == "") && len(remotes) == 0 {
|
||||
return nil
|
||||
}
|
||||
if remote_url != "" {
|
||||
|
||||
if remoteUrlP != nil && *remoteUrlP != "" {
|
||||
var name string
|
||||
r := Remote{
|
||||
url: remote_url,
|
||||
refresh: 2 * time.Second,
|
||||
url: *remoteUrlP,
|
||||
refresh: 5 * time.Second,
|
||||
}
|
||||
if name == "" {
|
||||
if nameP == nil && *nameP != "" {
|
||||
name = *nameP
|
||||
} else {
|
||||
name = "Remote"
|
||||
}
|
||||
if sleep != 0 {
|
||||
r.refresh = sleep
|
||||
if sleepP == nil && *sleepP != "" {
|
||||
sleep, err := time.ParseDuration(*sleepP)
|
||||
if err == nil {
|
||||
r.refresh = sleep
|
||||
} else {
|
||||
log.Printf("invalid refresh duration %s for %s; using default", *sleepP, *remoteUrlP)
|
||||
}
|
||||
}
|
||||
remotes[name] = r
|
||||
}
|
||||
|
||||
if len(remotes) == 0 {
|
||||
log.Println("Remote: no remote URL provided; disabling extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
RegisterTemp(updateTemp)
|
||||
RegisterMem(updateMem)
|
||||
RegisterCPU(updateUsage)
|
||||
|
@ -83,7 +91,6 @@ func startup(vars map[string]string) error {
|
|||
w := &sync.WaitGroup{}
|
||||
for n, r := range remotes {
|
||||
n = n + "-"
|
||||
r.url = r.url
|
||||
var u *url.URL
|
||||
w.Add(1)
|
||||
go func(name string, remote Remote, wg *sync.WaitGroup) {
|
||||
|
@ -232,7 +239,6 @@ func updateUsage(cpus map[string]int, _ bool) map[string]error {
|
|||
|
||||
func parseConfig(vars map[string]string) map[string]Remote {
|
||||
rv := make(map[string]Remote)
|
||||
log.Printf("VARS = %s", vars)
|
||||
for key, value := range vars {
|
||||
if strings.HasPrefix(key, "remote-") {
|
||||
parts := strings.Split(key, "-")
|
||||
|
|
|
@ -81,6 +81,7 @@ no-percpu="Abschalten die CPU im CPU-Widget anzeigen."
|
|||
cpuavg="Durchschnittliche CPU im CPU-Widget anzeigen."
|
||||
no-cpuavg="Abschalten die Durchschnittliche CPU im CPU-Widget anzeigen."
|
||||
temp="Temperaturen in Fahrenheit anzeigen."
|
||||
tempc="Temperaturen in Celsius anzeigen."
|
||||
statusbar="Statusleiste mit Uhrzeit anzeigen."
|
||||
no-statusbar="Abschalten die Statusleiste mit Uhrzeit anzeigen."
|
||||
rate="Frequenz aktualisieren. Die meisten Zeiteinheiten werden akzeptiert. \"1m\" = jede Minute aktualisieren. \"100 ms\" = alle 100 ms aktualisieren."
|
||||
|
@ -88,11 +89,12 @@ layout="Name der Layoutspezifikationsdatei für die Benutzeroberfläche. \"-\" l
|
|||
net="Netzwerkschnittstelle auswählen. Mehrere Schnittstellen können durch Kommata getrennt werden. Schnittstellen mit \"!\" werden ignoriert."
|
||||
export="Metriken für den Export auf dem angegebenen Port aktivieren."
|
||||
mbps="Netzwerkrate als MBit/s anzeigen."
|
||||
no-mbps="Abschalten die Netzwerkrate als MBit/s anzeigen."
|
||||
bytes="Netzwerkrate als bytes/s anzeigen."
|
||||
test="Tests ausführen und mit Erfolgs- oder Fehlercode beenden."
|
||||
no-test="Abschalten Tests"
|
||||
conffile="Konfigurationsdatei, die anstelle der Standardeinstellung verwendet werden soll (muss ERSTES ARGUMENT sein)."
|
||||
nvidia="NVidia-GPU-Metriken aktivieren."
|
||||
no-nvidia="NVidia-GPU-Metriken abschalten."
|
||||
nvidiarefresh="Frequenz aktualisieren. Die meisten Zeiteinheiten werden akzeptiert."
|
||||
list="""
|
||||
Auflisten von <devices|layouts|colorschemes|paths|keys|langs>
|
||||
|
|
|
@ -77,10 +77,11 @@ color="Set a colorscheme."
|
|||
scale="Graph scale factor, >0"
|
||||
version="Print version and exit."
|
||||
percpu="Show each CPU in the CPU widget."
|
||||
no-percpu="Disable show each CPU in the CPU widget."
|
||||
no-percpu="Show aggregate CPU in the CPU widget."
|
||||
cpuavg="Show average CPU in the CPU widget."
|
||||
no-cpuavg="Disable show average CPU in the CPU widget."
|
||||
temp="Show temperatures in fahrenheit."
|
||||
tempc="Show temperatures in celsius."
|
||||
statusbar="Show a statusbar with the time."
|
||||
no-statusbar="Disable statusbar."
|
||||
rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms."
|
||||
|
@ -88,11 +89,12 @@ layout="Name of layout spec file for the UI. Use \"-\" to pipe."
|
|||
net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\""
|
||||
export="Enable metrics for export on the specified port."
|
||||
mbps="Show network rate as mbps."
|
||||
no-mbps="Disable show network rate as mbps."
|
||||
bytes="Show network rate as bytes."
|
||||
test="Runs tests and exits with success/failure code."
|
||||
no-test="Disable tests."
|
||||
conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)"
|
||||
nvidia="Enable NVidia GPU metrics"
|
||||
conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)."
|
||||
nvidia="Enable NVidia GPU metrics."
|
||||
no-nvidia="Disable NVidia GPU metrics."
|
||||
nvidiarefresh="Refresh frequency. Most time units accepted."
|
||||
# TRANSLATORS: Please don't translate the **labels** ("devices", "layouts") as they don't change in the code.
|
||||
list="""
|
||||
|
|
|
@ -81,6 +81,7 @@ no-percpu="Malŝalti montri ĉiun CPU en la CPU-fenestraĵo."
|
|||
cpuavg="Montri duonan CPU en la CPU-fenestraĵo."
|
||||
no-cpuavg="Malŝalti montri duonan CPU en la CPU-fenestraĵo."
|
||||
temp="Montri temperaturojn en fahrenheit."
|
||||
tempc="Montri temperaturojn en celsius."
|
||||
statusbar="Montri statusbarbaron kun la tempo."
|
||||
no-statusbar="Malŝalti montri statusbarbaron kun la tempo."
|
||||
rate="Refreŝiga ofteco. Plej multaj unuoj akceptitaj. \"1m\" = refreŝigi ĉiun minuton. \"100ms\" = refreŝigi ĉiun dekonon minuton."
|
||||
|
@ -88,11 +89,12 @@ layout="Nomo de aranĝa specifa dosiero por la UI. Uzu \"-\" por pipi."
|
|||
net="Elekti retinterfacon. Multaj interfacoj povas esti difinitaj per komparaj valoroj. Interfacoj ankaŭ povas esti ignorataj per \"!\""
|
||||
export="Ebligu metrikojn por eksportado en la specifita haveno."
|
||||
mbps="Montri reta takson kiel mbps."
|
||||
no-mbps="Malŝalti montri reta takson kiel mbps."
|
||||
bytes="Malŝalti montri reta takson kiel bajtoj."
|
||||
test="Ekzekutas testojn kaj forirojn kun sukceso / fiaska kodo."
|
||||
no-test="Malŝalti ekzekutas testojn kaj forirojn kun sukceso / fiaska kodo."
|
||||
conffile="Agordi dosiero por uzi anstataŭ defaŭlte (DEVAS ESTI UNUA ARGUMENTO)"
|
||||
nvidia="Ebligu NVidia GPU-metrikojn"
|
||||
no-nvidia="Malŝalti NVidia GPU-metrikojn"
|
||||
nvidiarefresh="Refreŝigi oftecon. Plej multaj tempunuoj akceptis."
|
||||
# TRANSLATORS: Please don't translate the list entries
|
||||
list="""
|
||||
|
|
|
@ -81,6 +81,7 @@ no-percpu="Inutilizar muestra cada CPU en el widget de CPU."
|
|||
cpuavg="Mostrar uso de CPU promedio en el widget de CPU."
|
||||
no-cpuavg="Inutilizar mostrar uso de CPU promedio en el widget de CPU."
|
||||
temp="Mostrar temperaturas en grados Fahrenheit."
|
||||
tempc="Mostrar temperaturas en grados Celsius."
|
||||
statusbar="Muestra una barra de estado con la hora."
|
||||
no-statusbar="Inutilizar muestra una barra de estado con la hora."
|
||||
rate="Actualizar frecuencia. Se aceptan la mayoría de las unidades de tiempo. \"1m\" = actualizar cada minuto. \"100ms\" = actualizar cada 100ms."
|
||||
|
@ -88,11 +89,12 @@ layout="Nombre de archivo de especificaciones de diseño para la interfaz de usu
|
|||
net="Seleccionar interfaz de red. Se pueden definir varias interfaces utilizando valores separados por comas. Interfaces también se pueden ignorar usando \"!\""
|
||||
export="Habilitar métricas para exportar en el puerto especificado."
|
||||
mbps="Muestra la velocidad de la red como mbps."
|
||||
no-mbps="Inutilizar muestra la velocidad de la red como mbps."
|
||||
bytes="Inutilizar muestra la velocidad de la red como bytes."
|
||||
test="Ejecuta pruebas y sale con código de éxito / error."
|
||||
no-test="Inutilizar ejecuta pruebas y sale con código de éxito / error."
|
||||
conffile="Archivo de configuración para usar en lugar de predeterminado (DEBE SER EL PRIMER ARGUMENTO)"
|
||||
nvidia="Habilitar métrica de NVidia GPU"
|
||||
nonvidia="Inutilizar métrica de NVidia GPU"
|
||||
nvidiarefresh="Frecuencia de actualización. Se aceptan la mayoría de las unidades de tiempo."
|
||||
# TRANSLATORS: Please don't translate the **labels** ("devices", "layouts") as they don't change in the code.
|
||||
list="""
|
||||
|
|
|
@ -81,6 +81,7 @@ no-percpu="Désactiver montrer chaque CPU dans le widget CPU."
|
|||
cpuavg="Montrer le CPU moyen dans le widget CPU."
|
||||
no-cpuavg="Désactiver montrer le CPU moyen dans le widget CPU."
|
||||
temp="Montrer les températures en fahrenheit."
|
||||
tempc="Montrer les températures en celsius."
|
||||
statusbar="Montrer une barre d'état avec l'heure."
|
||||
no-statusbar="Désactiver montrer une barre d'état avec l'heure."
|
||||
rate="Fréquence de rafraîchissement. La plupart des unités de temps sont acceptées. \"1m\" = rafraîchir toutes les minutes. \"100ms\" = rafraîchir toutes les 100ms."
|
||||
|
@ -88,11 +89,12 @@ layout="Nom du fichier de spécification de disposition pour l'interface utilisa
|
|||
net="Choisir l'interface réseau. Plusieurs interfaces peuvent être décrites en les séparant par des virgules. Elles peuvent aussi être ignorées avec \"!\""
|
||||
export="Activer l'export des mesures sur le port indiqué."
|
||||
mbps="Montrer le débit réseau en mbps."
|
||||
no-mbps="Désactiver montrer le débit réseau en mbps."
|
||||
bytes="Désactiver montrer le débit réseau en bytes."
|
||||
test="Lancer les tests et sortir avec le code de succès ou d'échec."
|
||||
no-test="Désactiver lancer les tests et sortir avec le code de succès ou d'échec."
|
||||
conffile="Fichier de configuration à utiliser au lieu du fichier par défaut (DOIT ÊTRE PASSÉ EN PREMIER)"
|
||||
nvidia="Activer les métriques GPU NVidia"
|
||||
no-nvidia="Désactiver les métriques GPU NVidia"
|
||||
nvidiarefresh="Rafraîchir la fréquence. La plupart des unités de temps sont acceptées."
|
||||
# TRANSLATORS: Please don't translate the **labels** ("devices", "layouts") as they don't change in the code.
|
||||
list="""
|
||||
|
|
|
@ -73,14 +73,18 @@ version="Напечатать версию и выйти."
|
|||
percpu="Показать каждый CPU в CPU виджете."
|
||||
cpuavg="Показать средний CPU в CPU виджете."
|
||||
temp="Показать температуру в фаренгейтах."
|
||||
tempc="Show temperatures in celsius."
|
||||
statusbar="Показать статусбар со временем."
|
||||
rate="Частота обновления. Поддерживается большинство единиц измерения. \"1m\" = обновлять каждую минуту. \"100ms\" = обновлять каждые 100мс."
|
||||
layout="Название файла спецификации для раскладки. Используйте \"-\" для нескольких раскладок."
|
||||
net="Выбрать сетевой интерфейс. Несколько интерфейсов можно определить через запятую. Для игнорирования определённых интерфейсов используйте \"!\""
|
||||
export="Включить метрику для экспорта на указанном порту."
|
||||
mbps="Показать скорость сети в мб/с"
|
||||
bytes="Show network rate as bytes."
|
||||
test="Запуск тестов и выход с успешным/провальным кодом."
|
||||
conffile="Файл конфигурации вместо того, что по умолчанию (ДОЛЖЕН БЫТЬ ПЕРВЫМ АРГУМЕНТОМ)"
|
||||
nvidia="Enable NVidia GPU metrics."
|
||||
nvidiarefresh="Refresh frequency. Most time units accepted."
|
||||
# TRANSLATORS: Please don't translate the **labels** ("devices", "layouts") as they don't change in the code.
|
||||
list="""
|
||||
Перечислить <devices|layouts|colorschemes|paths|keys|langs>
|
||||
|
|
|
@ -80,6 +80,7 @@ no-percpu=".tegdiw UPC eht ni UPC hcae wohs elbasiD"
|
|||
cpuavg=".tegdiw UPC eht ni UPC egareva wohS"
|
||||
no-cpuavg=".tegdiw UPC eht ni UPC egareva wohs elbasiD"
|
||||
temp=".tiehnerhaf ni serutarepmet wohS.tiehnerhaf ni serutarepmet wohS"
|
||||
tempc=".suislec ni serutarepmet wohS.tiehnerhaf ni serutarepmet wohS"
|
||||
statusbar=".emit eht htiw rabsutats a wohS"
|
||||
no-statusbar=".emit eht htiw rabsutats a wohs elbasiD"
|
||||
rate=".sm001 yreve hserfer = \"sm001\" .etunim yreve hserfer = \"m1\" .detpecca stinu emit tsoM .ycneuqerf hserfeR"
|
||||
|
@ -87,11 +88,12 @@ layout="Name of layout spec file for the UI. Use \"-\" to pipe."
|
|||
net="gnisu derongi eb osla nac secafretnI .seulav detarapes ammoc gnisu denifed eb nac secafretni lareveS .ecafretni krowten tceleS \"!\""
|
||||
export=".trop deificeps eht no tropxe rof scirtem elbanE"
|
||||
mbps=".spbm sa etar krowten wohS"
|
||||
no-mbps=".spbm sa etar krowten wohs elbasiD"
|
||||
bytes=".setyb sa etar krowten wohs elbasiD"
|
||||
test=".edoc eruliaf/sseccus htiw stixe dna stset snuR"
|
||||
no-test=".edoc eruliaf/sseccus htiw stixe dna stset snur elbasiD"
|
||||
conffile=")TNEMUGRA TSRIF EB TSUM( tluafed fo daetsni esu ot elif gifnoC"
|
||||
nvidia="scirtem UPG aidiVN elbanE"
|
||||
no-nvidia="scirtem UPG aidiVN elbasiD"
|
||||
nvidiarefresh=".detpecca stinu emit tsoM .ycneuqerf hserfeR"
|
||||
list="""
|
||||
>snart|syek|shtap|semehcsroloc|stuoyal|secived< tsiL
|
||||
|
|
|
@ -81,6 +81,7 @@ no-percpu="在 CPU 组件中不显示每个 CPU。"
|
|||
cpuavg="在 CPU 组件中显示平均 CPU。"
|
||||
no-cpuavg="在 CPU 组件中不显示平均 CPU。"
|
||||
temp="显示华氏温度。"
|
||||
tempc="Show temperatures in celsius."
|
||||
statusbar="显示时间状态栏。"
|
||||
no-statusbar="不显示状态栏。"
|
||||
rate="刷新频率。常见的时间单位皆可用。\"1m\" = 每分钟刷新。\"100ms\" = 每100毫秒刷新。"
|
||||
|
@ -88,11 +89,12 @@ layout="布局描述文件名。使用 \"-\" 连接。"
|
|||
net="选择网卡。多个网卡用逗号分隔。使用 \"!\" 忽略指定网卡。"
|
||||
export="在指定端口上启用指标输出。"
|
||||
mbps="显示网速为 mbps。"
|
||||
no-mbps="显示网速时不使用 mbps。"
|
||||
bytes="显示网速为 字节."
|
||||
test="执行测试并返回成功或失败码。"
|
||||
no-test="不执行测试。"
|
||||
conffile="用于替代缺省参数的配置文件(必须是第一个参数)"
|
||||
nvidia="启用NVidia GPU指标"
|
||||
no-nvidia="不显示NVidia GPU指标"
|
||||
nvidiarefresh="刷新频率。常见的时间单位皆可用。"
|
||||
list="""
|
||||
列出 <devices|layouts|colorschemes|paths|keys|langs>
|
||||
|
|
|
@ -1,38 +1,17 @@
|
|||
# Current steps for a release
|
||||
|
||||
1. ~~Update Version in main.go~~ (now set in package build)
|
||||
2. Update CHANGELOG.md
|
||||
3. Tag
|
||||
4. Push everything
|
||||
5. Wait for the github workflows to complete
|
||||
6. Download and verify the correct version of one of the binaries
|
||||
7. Finish the draft release and publish.
|
||||
8. Check gotop-builder for a successful everything build; if successful, publish.
|
||||
9. Notify Nix
|
||||
10. ~~Notify Homebrew~~ Automated now.
|
||||
11. Trigger extensions:
|
||||
```
|
||||
for p in builder nvidia remote linux; do
|
||||
curl -H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Authorization: token ${TOKEN}" \
|
||||
--request POST \
|
||||
--data "{'event_type': 'my-release', 'client_payload': {'tag': '${TAG}'}}" \
|
||||
https://api.github.com/repos/xxxserxxx/gotop-${p}/dispatches
|
||||
done
|
||||
```
|
||||
and then go in and mark each release as not a pre-release.
|
||||
12. Wait for the [AUR](https://github.com/xxxserxxx/gotop-linux) project to finish building.
|
||||
1. Update package versions in gotop and gotop-bin
|
||||
2. namcap PKGBUILD
|
||||
3. updpkgsums
|
||||
4. makepkg --printsrcinfo > .SRCINFO
|
||||
5. git commit -a
|
||||
6. git push
|
||||
7. Test install `gotop`, `gotop-bin`, and `gotop-git` with running & version check
|
||||
|
||||
The AUR project still needs secret credentials to aurpublish to the AUR
|
||||
repository, so the final publish step is still currently manual.
|
||||
|
||||
1. Update CHANGELOG.md
|
||||
2. Tag
|
||||
3. Push everything
|
||||
4. Wait for the github workflows to complete
|
||||
5. Download and verify the correct version of one of the binaries
|
||||
6. Finish the draft release and publish.
|
||||
7. Check gotop-builder for a successful everything build; if successful, publish.
|
||||
8. Notify Nix
|
||||
9. ~~Notify Homebrew~~ ~~Automated now.~~ Automation broke. Notify manually.
|
||||
10. Do the Arch release.
|
||||
1. cd actions/arch-package
|
||||
2. VERSION=v4.1.2 ./run.sh
|
||||
|
||||
## Nix
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 // indirect
|
||||
github.com/distatus/battery v0.10.0
|
||||
github.com/droundy/goopt v0.0.0-20170604162106-0b8effe182da
|
||||
github.com/gizak/termui/v3 v3.1.0
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.4
|
||||
|
@ -17,7 +18,6 @@ require (
|
|||
github.com/shirou/gopsutil v3.20.12+incompatible
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/xxxserxxx/lingo/v2 v2.0.1
|
||||
github.com/xxxserxxx/opflag v1.0.5
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -14,6 +14,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distatus/battery v0.10.0 h1:YbizvmV33mqqC1fPCAEaQGV3bBhfYOfM+2XmL+mvt5o=
|
||||
github.com/distatus/battery v0.10.0/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE=
|
||||
github.com/droundy/goopt v0.0.0-20170604162106-0b8effe182da h1:79H+mNJWOObWrQgbkSvvZ3t/D2lKWaTi9mu/v7fNRvg=
|
||||
github.com/droundy/goopt v0.0.0-20170604162106-0b8effe182da/go.mod h1:ytRJ64WkuW4kf6/tuYqBATBCRFUP8X9+LDtgcvE+koI=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
|
@ -71,8 +73,6 @@ github.com/valyala/histogram v1.0.1 h1:FzA7n2Tz/wKRMejgu3PV1vw3htAklTjjuoI6z3d4K
|
|||
github.com/valyala/histogram v1.0.1/go.mod h1:lQy0xA4wUz2+IUnf97SivorsJIp8FxsnRd6x25q7Mto=
|
||||
github.com/xxxserxxx/lingo/v2 v2.0.1 h1:6uLLKzPqL0XpdFmNMmpSfu+uIzQk344ebfdpFWbGuxs=
|
||||
github.com/xxxserxxx/lingo/v2 v2.0.1/go.mod h1:Hr6LTxpwirwJ2Qe83MvgSQARPFDzZ4S6DKd6ciuED7A=
|
||||
github.com/xxxserxxx/opflag v1.0.5 h1:2H4Qtl1qe+dSkEcGt+fBe2mQ8z14MgkWPqcLaoa6k90=
|
||||
github.com/xxxserxxx/opflag v1.0.5/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
Loading…
Reference in New Issue
Block a user