CheckIn/main.go

159 lines
4.0 KiB
Go
Raw Normal View History

2020-11-12 19:19:36 +00:00
package main
import (
2020-11-13 05:34:00 +00:00
"bufio"
"flag"
2020-11-13 05:34:00 +00:00
"fmt"
2020-11-12 22:06:19 +00:00
"io"
"io/ioutil"
2020-11-13 05:34:00 +00:00
"os"
"os/user"
"path"
"path/filepath"
"strings"
"time"
2020-11-12 19:19:36 +00:00
)
func main() {
flag.Parse()
switch flag.Arg(0) {
case "set":
2020-11-13 06:22:45 +00:00
err := SetStatus(flag.Args()[1:])
2020-11-13 03:59:45 +00:00
if err != nil {
fmt.Fprintf(os.Stderr, "Could not set: %v", err)
}
case "get":
2020-11-13 06:22:45 +00:00
err := GetStatus(flag.Args()[1:])
if err != nil {
fmt.Fprintf(os.Stderr, "Could not get: %v", err)
}
default:
fmt.Printf("Usage:\n\t%v <set|get>\n", os.Args[0])
flag.PrintDefaults()
}
}
2020-11-13 06:22:45 +00:00
// GetStatus collects all recent statuses from all users on the system.
// Any errors that occur while pulling individual statuss are silently ignored
func GetStatus(args []string) error {
getFlags := flag.NewFlagSet(os.Args[0]+" get", flag.ExitOnError)
2020-11-13 06:22:45 +00:00
freshDays := getFlags.Int("freshness", 14, "get all statuses newer than this number of days")
getFlags.Parse(args)
freshLimit := time.Now().AddDate(0, 0, *freshDays*-1)
2020-11-13 06:22:45 +00:00
allStatusPaths, err := filepath.Glob("/home/*/.checkin")
if err != nil {
// *Should* never happen, since path is hardcoded and that's the only reason Glob can error out.
return err
}
2020-11-13 06:22:45 +00:00
// Filter out any statuses that are older than our cutoff time.
freshStatusPaths := make([]string, 0, len(allStatusPaths))
for _, statusPath := range allStatusPaths {
statusInfo, err := os.Stat(statusPath)
if err != nil {
continue
}
2020-11-13 06:22:45 +00:00
if statusInfo.ModTime().After(freshLimit) {
freshStatusPaths = append(freshStatusPaths, statusPath)
}
}
2020-11-13 06:22:45 +00:00
// Print the contents of all statuses
for _, statusPath := range freshStatusPaths {
statusBytes, err := ioutil.ReadFile(statusPath)
if err != nil {
continue
}
2020-11-13 06:22:45 +00:00
status := string(statusBytes)
// Check to see if file starts with user's name.
2020-11-13 06:22:45 +00:00
if !strings.HasPrefix(status, "~") {
// Strip /home from path
2020-11-13 06:22:45 +00:00
homelessPath, err := filepath.Rel("/home", statusPath)
if err != nil {
continue
}
2020-11-13 06:22:45 +00:00
// Strip .checkin from path, leaving us with the user's name.
username := filepath.Dir(homelessPath)
2020-11-13 06:22:45 +00:00
status = fmt.Sprintf("~%s: %s", username, status)
}
// Trim trailing newline (if any)
2020-11-13 06:22:45 +00:00
status = strings.TrimSpace(status)
2020-11-13 05:34:00 +00:00
2020-11-13 06:22:45 +00:00
fmt.Println(status)
}
2020-11-13 05:34:00 +00:00
return nil
}
2020-11-13 06:22:45 +00:00
// SetStatus sets the curent user's status, either by reading the value from the command line or by prompting the user to input it interactively.
func SetStatus(args []string) error {
setFlags := flag.NewFlagSet(os.Args[0]+" set", flag.ExitOnError)
includeWd := setFlags.Bool("include-wd", false, "if set, appends working directory to your message")
setFlags.Parse(args)
2020-11-12 22:06:19 +00:00
curUser, err := user.Current()
if err != nil {
2020-11-13 03:59:45 +00:00
return err
2020-11-12 22:06:19 +00:00
}
2020-11-13 06:22:45 +00:00
// User status is written to ~/.checkin
outputPath := path.Join(curUser.HomeDir, ".checkin")
2020-11-12 22:13:09 +00:00
2020-11-13 03:11:40 +00:00
// Prompt user for input
2020-11-12 22:06:19 +00:00
fmt.Printf("What's ~%v been up to?\n~%v", curUser.Username, curUser.Username)
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
2020-11-13 03:59:45 +00:00
return err
2020-11-12 22:06:19 +00:00
}
// Strip whitespace
input = strings.TrimSpace(input)
2020-11-13 03:11:40 +00:00
// Remove file on blank input
if input == "" {
2020-11-12 22:13:09 +00:00
err = os.Remove(outputPath)
// File already pre-non-existing is considered success.
if os.IsNotExist(err) {
return nil
} else if err != nil {
2020-11-13 03:59:45 +00:00
return err
2020-11-12 22:13:09 +00:00
}
2020-11-13 03:59:45 +00:00
return nil
2020-11-12 22:13:09 +00:00
}
2020-11-13 03:11:40 +00:00
// Prepend status with user's name
input = fmt.Sprintf("~%s%s", curUser.Username, input)
2020-11-13 03:11:40 +00:00
if *includeWd {
wd, err := os.Getwd()
if err != nil {
return err
}
// If they're in their home directory, swap /home/user out for ~user
homelessPath, err := filepath.Rel(curUser.HomeDir, wd)
2020-11-13 06:11:20 +00:00
// Gotta be careful because Rel doesn't care if wd is a subdirectory of HomeDir,
// it'll slather as much "../../.." as it needs to make it relative.
if err == nil && !strings.HasPrefix(homelessPath, "..") {
wd = filepath.Join("~"+curUser.Username, homelessPath)
}
input = fmt.Sprintf("%s (%s)", input, wd)
}
input = input + "\n"
2020-11-13 03:11:40 +00:00
// Write file and create if it doesn't exist as world-readable.
2020-11-12 22:06:19 +00:00
err = ioutil.WriteFile(outputPath, []byte(input), 0644)
if err != nil {
2020-11-13 03:59:45 +00:00
return err
2020-11-12 22:06:19 +00:00
}
2020-11-13 03:59:45 +00:00
return nil
2020-11-13 05:34:00 +00:00
}