262 lines
6.0 KiB
Go
262 lines
6.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"github.com/jackmordaunt/ghw"
|
|
"github.com/mitchellh/go-ps"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"regexp"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type DistroInfo struct {
|
|
ID string
|
|
LongName string
|
|
ShortName string
|
|
}
|
|
|
|
func getDistroInfo() DistroInfo {
|
|
distroID := ""
|
|
var releaseMap = make(map[string]string)
|
|
if _, err := os.Stat("/etc/os-release"); err == nil {
|
|
releaseMap, err = readKeyValueFile("/etc/os-release")
|
|
if err != nil {
|
|
return DistroInfo{
|
|
ID: "unknown",
|
|
LongName: "Unknown",
|
|
ShortName: "Unknown",
|
|
}
|
|
}
|
|
if value, ok := releaseMap["ID"]; ok {
|
|
distroID = value
|
|
}
|
|
}
|
|
|
|
switch distroID {
|
|
default:
|
|
if id, ok := releaseMap["ID"]; ok {
|
|
if longName, ok := releaseMap["PRETTY_NAME"]; ok {
|
|
if shortName, ok := releaseMap["NAME"]; ok {
|
|
return DistroInfo{
|
|
ID: id,
|
|
LongName: longName,
|
|
ShortName: shortName,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return DistroInfo{
|
|
ID: "unknown",
|
|
LongName: "Unknown",
|
|
ShortName: "Unknown",
|
|
}
|
|
}
|
|
}
|
|
|
|
func getDistroAsciiArt() string {
|
|
defaultAscii :=
|
|
` .--.
|
|
|o_o |
|
|
|:_/ |
|
|
// \ \
|
|
(| | )
|
|
/'\_ _/'\
|
|
\___)=(___/ `
|
|
var id string
|
|
if config.Ascii == "auto" {
|
|
id = getDistroInfo().ID
|
|
} else {
|
|
id = config.Ascii
|
|
}
|
|
userConfDir, err := os.UserConfigDir()
|
|
if err != nil {
|
|
if _, err := os.Stat(path.Join("/etc/stormfetch/ascii/", id)); err == nil {
|
|
bytes, err := os.ReadFile(path.Join("/etc/stormfetch/ascii/", id))
|
|
if err != nil {
|
|
return defaultAscii
|
|
}
|
|
return string(bytes)
|
|
} else {
|
|
return defaultAscii
|
|
}
|
|
}
|
|
if _, err := os.Stat(path.Join(userConfDir, "stormfetch/ascii/", id)); err == nil {
|
|
bytes, err := os.ReadFile(path.Join(userConfDir, "stormfetch/ascii/", id))
|
|
if err != nil {
|
|
return defaultAscii
|
|
}
|
|
return string(bytes)
|
|
} else if _, err := os.Stat(path.Join("/etc/stormfetch/ascii/", id)); err == nil {
|
|
bytes, err := os.ReadFile(path.Join("/etc/stormfetch/ascii/", id))
|
|
if err != nil {
|
|
return defaultAscii
|
|
}
|
|
return string(bytes)
|
|
} else {
|
|
return defaultAscii
|
|
}
|
|
}
|
|
|
|
func getCPUName() string {
|
|
cpu, err := ghw.CPU()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return cpu.Processors[0].Model
|
|
}
|
|
|
|
func getCPUThreads() int {
|
|
cpu, err := ghw.CPU()
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return int(cpu.TotalThreads)
|
|
}
|
|
|
|
func getGPUName() string {
|
|
null, _ := os.Open(os.DevNull)
|
|
serr := os.Stderr
|
|
os.Stderr = null
|
|
gpu, err := ghw.GPU()
|
|
defer null.Close()
|
|
os.Stderr = serr
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
if len(gpu.GraphicsCards) == 0 {
|
|
return ""
|
|
}
|
|
return gpu.GraphicsCards[0].DeviceInfo.Product.Name
|
|
}
|
|
|
|
type Memory struct {
|
|
MemTotal int
|
|
MemFree int
|
|
MemAvailable int
|
|
}
|
|
|
|
func GetMemoryInfo() Memory {
|
|
toInt := func(raw string) int {
|
|
if raw == "" {
|
|
return 0
|
|
}
|
|
res, err := strconv.Atoi(raw)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return res
|
|
}
|
|
|
|
parseLine := func(raw string) (key string, value int) {
|
|
text := strings.ReplaceAll(raw[:len(raw)-2], " ", "")
|
|
keyValue := strings.Split(text, ":")
|
|
return keyValue[0], toInt(keyValue[1])
|
|
}
|
|
|
|
file, err := os.Open("/proc/meminfo")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer file.Close()
|
|
bufio.NewScanner(file)
|
|
scanner := bufio.NewScanner(file)
|
|
res := Memory{}
|
|
for scanner.Scan() {
|
|
key, value := parseLine(scanner.Text())
|
|
switch key {
|
|
case "MemTotal":
|
|
res.MemTotal = value / 1024
|
|
case "MemFree":
|
|
res.MemFree = value / 1024
|
|
case "MemAvailable":
|
|
res.MemAvailable = value / 1024
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func GetDEWM() string {
|
|
processes, err := ps.Processes()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
var executables []string
|
|
for _, process := range processes {
|
|
executables = append(executables, process.Executable())
|
|
}
|
|
|
|
processExists := func(process string) bool {
|
|
return slices.Contains(executables, process)
|
|
}
|
|
runCommand := func(command string) string {
|
|
cmd := exec.Command("/bin/bash", "-c", command)
|
|
workdir, err := os.Getwd()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
cmd.Dir = workdir
|
|
cmd.Env = os.Environ()
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return string(out)
|
|
}
|
|
|
|
if processExists("plasmashell") {
|
|
return strings.TrimSpace("KDE Plasma " + runCommand("plasmashell --version | awk '{print $2}'"))
|
|
} else if processExists("gnome-session") {
|
|
return strings.TrimSpace("Gnome " + runCommand("gnome-shell --version | awk '{print $3}'"))
|
|
} else if processExists("xfce4-session") {
|
|
return strings.TrimSpace("XFCE " + runCommand("xfce4-session --version | grep xfce4-session | awk '{print $2}'"))
|
|
} else if processExists("cinnamon") {
|
|
return strings.TrimSpace("Cinnamon " + runCommand("cinnamon --version | awk '{print $3}'"))
|
|
} else if processExists("mate-panel") {
|
|
return strings.TrimSpace("MATE " + runCommand("mate-about --version | awk '{print $4}'"))
|
|
} else if processExists("lxsession") {
|
|
return "LXDE"
|
|
} else if processExists("sway") {
|
|
return strings.TrimSpace("Sway " + runCommand("sway --version | awk '{print $3}'"))
|
|
} else if processExists("bspwm") {
|
|
return strings.TrimSpace("Bspwm " + runCommand("bspwm -v"))
|
|
} else if processExists("icewm-session") {
|
|
return strings.TrimSpace("IceWM " + runCommand("icewm --version | awk '{print $2}'"))
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func stripAnsii(str string) string {
|
|
const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
|
|
var re = regexp.MustCompile(ansi)
|
|
return re.ReplaceAllString(str, "")
|
|
}
|
|
|
|
func readKeyValueFile(filepath string) (map[string]string, error) {
|
|
ret := make(map[string]string)
|
|
if _, err := os.Stat(filepath); err != nil {
|
|
return nil, err
|
|
}
|
|
bytes, err := os.ReadFile(filepath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
str := string(bytes)
|
|
lines := strings.Split(str, "\n")
|
|
for _, line := range lines {
|
|
if len(strings.Split(line, "=")) >= 2 {
|
|
key := strings.SplitN(line, "=", 2)[0]
|
|
value := strings.SplitN(line, "=", 2)[1]
|
|
if strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"") {
|
|
value = value[1 : len(value)-1]
|
|
}
|
|
ret[key] = value
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|