fork
Configure Feed
Select the types of activity you want to include in your feed.
Live video on the AT Protocol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package proc
2
3import (
4 "bufio"
5 "context"
6 "errors"
7 "fmt"
8 "io"
9 "os"
10 "os/exec"
11 "strings"
12
13 "golang.org/x/sync/errgroup"
14 "stream.place/streamplace/pkg/config"
15 "stream.place/streamplace/pkg/log"
16 "stream.place/streamplace/pkg/mist/mistconfig"
17)
18
19func RunMistServer(ctx context.Context, cli *config.CLI) error {
20 myself, err := os.Executable()
21 if err != nil {
22 return err
23 }
24 f, err := os.CreateTemp("", "mistconfig.json")
25 defer os.Remove(f.Name())
26 if err != nil {
27 return err
28 }
29 conf, err := mistconfig.Generate(cli)
30 if err != nil {
31 return err
32 }
33 err = os.WriteFile(f.Name(), conf, 0644)
34 if err != nil {
35 return err
36 }
37 cmd := exec.CommandContext(ctx, myself,
38 "MistServer",
39 "-c", f.Name(),
40 "-i", "127.0.0.1",
41 "-p", fmt.Sprintf("%d", cli.MistAdminPort),
42 )
43 cmd.Env = []string{
44 "MIST_NO_PRETTY_LOGGING=true",
45 }
46 stdout, err := cmd.StdoutPipe()
47 if err != nil {
48 panic(err)
49 }
50 stderr, err := cmd.StderrPipe()
51 if err != nil {
52 panic(err)
53 }
54 group, ctx := errgroup.WithContext(ctx)
55 output := fmt.Println
56 for i, pipe := range []io.ReadCloser{stdout, stderr} {
57 func(i int, pipe io.ReadCloser) {
58 group.Go(func() error {
59 reader := bufio.NewReader(pipe)
60
61 for {
62 line, isPrefix, err := reader.ReadLine()
63 if err != nil {
64 if !errors.Is(err, io.EOF) {
65 _, _ = output(fmt.Sprintf("reader gave error, ending logging for fd=%d err=%s", i+1, err))
66 }
67 line, _, err := reader.ReadLine()
68 if string(line) != "" {
69 _, _ = output(string(line))
70 }
71 return err
72 }
73 if isPrefix {
74 _, _ = output("warning: preceding line exceeds 64k logging limit and was split")
75 }
76 if string(line) != "" {
77 level, procName, pid, path, streamName, msg, err := ParseMistLog(string(line))
78 if err != nil {
79 log.Log(ctx, "badly formatted mist log", "message", string(line))
80 } else {
81 log.Log(ctx, msg,
82 "level", level,
83 "procName", procName,
84 "pid", pid,
85 "streamName", streamName,
86 "caller", path,
87 )
88 }
89 }
90 }
91 })
92 }(i, pipe)
93 }
94
95 group.Go(func() error {
96 return cmd.Start()
97 })
98
99 return group.Wait()
100}
101
102func ParseMistLog(str string) (string, string, string, string, string, string, error) {
103 parts := strings.Split(str, "|")
104 if len(parts) != 6 {
105 return "", "", "", "", "", "", fmt.Errorf("badly formatted mist string")
106 }
107 return parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], nil
108}