add visit
parent
7e22317ae9
commit
362ca0fa19
|
@ -0,0 +1,143 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/charmbracelet/glamour"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
if len(os.Args) > 2 {
|
||||
fmt.Println("expected zero or one arguments")
|
||||
}
|
||||
if len(os.Args) > 1 {
|
||||
arg := os.Args[1]
|
||||
switch arg {
|
||||
case "-r", "--random":
|
||||
err = visitRandomUser()
|
||||
default:
|
||||
err = visitUsername(os.Args[1])
|
||||
}
|
||||
} else {
|
||||
err = visitPrompt()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func visitRandomUser() error {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
usernames, err := getUsernames()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return visitUser(usernames[rand.Intn(len(usernames))])
|
||||
}
|
||||
|
||||
func visitUsername(username string) error {
|
||||
usernames, err := getUsernames()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range usernames {
|
||||
if name == username {
|
||||
return visitUser(username)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("no such user: %s", username)
|
||||
}
|
||||
|
||||
func visitPrompt() error {
|
||||
usernames, err := getUsernames()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
username := ""
|
||||
prompt := &survey.Select{
|
||||
Message: "Choose a townie to visit!",
|
||||
Options: usernames,
|
||||
}
|
||||
survey.AskOne(prompt, &username)
|
||||
return visitUser(username)
|
||||
}
|
||||
|
||||
func visitUser(username string) error {
|
||||
files, err := ioutil.ReadDir(filepath.Join("/home", username))
|
||||
if err != nil {
|
||||
return fmt.Errorf("user is not accepting visitors (could not read user's home directory: %w)", err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if !isReadme(file.Name()) {
|
||||
continue
|
||||
}
|
||||
|
||||
path := filepath.Join("/home", username, file.Name())
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if isMarkdown(file.Name()) {
|
||||
r, _ := glamour.NewTermRenderer(glamour.WithAutoStyle())
|
||||
out, err := r.RenderBytes(data)
|
||||
if err == nil {
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(string(data))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO handle .plan and .project files
|
||||
|
||||
fmt.Println("TODO non-readme fallback")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isReadme(filename string) bool {
|
||||
fn := strings.ToLower(filename)
|
||||
return strings.HasPrefix(fn, "readme") || strings.HasPrefix(fn, "welcome")
|
||||
}
|
||||
|
||||
func isMarkdown(filename string) bool {
|
||||
fn := strings.ToLower(filename)
|
||||
return strings.HasSuffix(fn, ".md") || strings.HasSuffix(fn, ".markdown")
|
||||
}
|
||||
|
||||
func getUsernames() ([]string, error) {
|
||||
cmd := exec.Command("/bin/bash", "-c", "town stats | jq -r '.users|map(.username)'")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usernames := []string{}
|
||||
err = json.Unmarshal(output, &usernames)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return usernames, nil
|
||||
}
|
Loading…
Reference in New Issue