You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
2.6 KiB

2 years ago
package main
import (
"encoding/json"
"fmt"
2 years ago
"io/ioutil"
2 years ago
"math/rand"
"os"
"os/exec"
2 years ago
"path/filepath"
2 years ago
"strings"
2 years ago
"time"
"github.com/AlecAivazis/survey/v2"
2 years ago
"github.com/charmbracelet/glamour"
2 years ago
)
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:
2 years ago
err = visitUsername(os.Args[1])
2 years ago
}
} 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
}
2 years ago
return visitUser(usernames[rand.Intn(len(usernames))])
2 years ago
}
2 years ago
func visitUsername(username string) error {
2 years ago
usernames, err := getUsernames()
if err != nil {
return err
}
for _, name := range usernames {
if name == username {
2 years ago
return visitUser(username)
2 years ago
}
}
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)
2 years ago
return visitUser(username)
}
2 years ago
2 years ago
func visitUser(username string) error {
2 years ago
files, err := ioutil.ReadDir(filepath.Join("/home", username))
if err != nil {
2 years ago
return fmt.Errorf("user is not accepting visitors (could not read user's home directory: %w)", err)
2 years ago
}
2 years ago
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
}
2 years ago
2 years ago
if isMarkdown(file.Name()) {
r, _ := glamour.NewTermRenderer(glamour.WithAutoStyle())
out, err := r.RenderBytes(data)
if err == nil {
fmt.Println(string(out))
return nil
2 years ago
}
}
2 years ago
fmt.Println(string(data))
return nil
2 years ago
}
2 years ago
// TODO handle .plan and .project files
2 years ago
fmt.Println("TODO non-readme fallback")
2 years ago
return nil
}
2 years ago
func isReadme(filename string) bool {
fn := strings.ToLower(filename)
2 years ago
return strings.HasPrefix(fn, "readme") || strings.HasPrefix(fn, "welcome")
2 years ago
}
func isMarkdown(filename string) bool {
fn := strings.ToLower(filename)
return strings.HasSuffix(fn, ".md") || strings.HasSuffix(fn, ".markdown")
}
2 years ago
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
}