Blame


1 1081cf75 2024-11-04 o package fs
2 1081cf75 2024-11-04 o
3 1081cf75 2024-11-04 o import (
4 1081cf75 2024-11-04 o "errors"
5 1081cf75 2024-11-04 o "fmt"
6 1081cf75 2024-11-04 o "io"
7 1081cf75 2024-11-04 o "io/fs"
8 1081cf75 2024-11-04 o "path"
9 1081cf75 2024-11-04 o "strconv"
10 1081cf75 2024-11-04 o "strings"
11 1081cf75 2024-11-04 o "time"
12 1081cf75 2024-11-04 o
13 1081cf75 2024-11-04 o "olowe.co/apub/lemmy"
14 1081cf75 2024-11-04 o )
15 1081cf75 2024-11-04 o
16 1081cf75 2024-11-04 o type FS struct {
17 1081cf75 2024-11-04 o Client *lemmy.Client
18 1081cf75 2024-11-04 o started bool
19 1081cf75 2024-11-04 o }
20 1081cf75 2024-11-04 o
21 1081cf75 2024-11-04 o func (fsys *FS) start() error {
22 1081cf75 2024-11-04 o if fsys.Client == nil {
23 1081cf75 2024-11-04 o fsys.Client = &lemmy.Client{}
24 1081cf75 2024-11-04 o }
25 1081cf75 2024-11-04 o fsys.started = true
26 1081cf75 2024-11-04 o return nil
27 1081cf75 2024-11-04 o }
28 1081cf75 2024-11-04 o
29 1081cf75 2024-11-04 o func (fsys *FS) Open(name string) (fs.File, error) {
30 1081cf75 2024-11-04 o if !fs.ValidPath(name) {
31 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrInvalid}
32 1081cf75 2024-11-04 o } else if strings.Contains(name, `\`) {
33 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrInvalid}
34 1081cf75 2024-11-04 o }
35 1081cf75 2024-11-04 o name = path.Clean(name)
36 1081cf75 2024-11-04 o
37 1081cf75 2024-11-04 o if !fsys.started {
38 1081cf75 2024-11-04 o if err := fsys.start(); err != nil {
39 1081cf75 2024-11-04 o return nil, fmt.Errorf("start fs: %w", err)
40 1081cf75 2024-11-04 o }
41 1081cf75 2024-11-04 o }
42 1081cf75 2024-11-04 o if name == "." {
43 1081cf75 2024-11-04 o return fsys.openRoot()
44 1081cf75 2024-11-04 o }
45 1081cf75 2024-11-04 o
46 1081cf75 2024-11-04 o elems := strings.Split(name, "/")
47 1081cf75 2024-11-04 o // We've only got communities, then posts/comments.
48 1081cf75 2024-11-04 o // Anything deeper cannot exist.
49 1081cf75 2024-11-04 o if len(elems) > 3 {
50 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrNotExist}
51 1081cf75 2024-11-04 o }
52 1081cf75 2024-11-04 o
53 1081cf75 2024-11-04 o community, _, err := fsys.Client.LookupCommunity(elems[0])
54 1081cf75 2024-11-04 o if errors.Is(err, lemmy.ErrNotFound) {
55 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrNotExist}
56 1081cf75 2024-11-04 o } else if err != nil {
57 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, err}
58 1081cf75 2024-11-04 o }
59 1081cf75 2024-11-04 o if len(elems) == 1 {
60 1081cf75 2024-11-04 o return &lFile{
61 1081cf75 2024-11-04 o info: &community,
62 1081cf75 2024-11-04 o buf: io.NopCloser(strings.NewReader(community.Name())),
63 1081cf75 2024-11-04 o client: fsys.Client,
64 1081cf75 2024-11-04 o }, nil
65 1081cf75 2024-11-04 o }
66 1081cf75 2024-11-04 o
67 1081cf75 2024-11-04 o id, err := strconv.Atoi(elems[1])
68 1081cf75 2024-11-04 o if err != nil {
69 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fmt.Errorf("bad post id")}
70 1081cf75 2024-11-04 o }
71 1081cf75 2024-11-04 o post, err := fsys.Client.LookupPost(id)
72 1081cf75 2024-11-04 o if errors.Is(err, lemmy.ErrNotFound) {
73 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrNotExist}
74 1081cf75 2024-11-04 o } else if err != nil {
75 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, err}
76 1081cf75 2024-11-04 o }
77 1081cf75 2024-11-04 o if len(elems) == 2 {
78 1081cf75 2024-11-04 o return &lFile{
79 1081cf75 2024-11-04 o info: &post,
80 1081cf75 2024-11-04 o buf: io.NopCloser(strings.NewReader(post.Name())),
81 1081cf75 2024-11-04 o client: fsys.Client,
82 1081cf75 2024-11-04 o }, nil
83 1081cf75 2024-11-04 o }
84 1081cf75 2024-11-04 o if elems[2] == "post" {
85 1081cf75 2024-11-04 o info, err := postFile(&post).Stat()
86 1081cf75 2024-11-04 o if err != nil {
87 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fmt.Errorf("prepare post file info: %w", err)}
88 1081cf75 2024-11-04 o }
89 1081cf75 2024-11-04 o return &lFile{
90 1081cf75 2024-11-04 o info: info,
91 1081cf75 2024-11-04 o buf: io.NopCloser(postText(&post)),
92 1081cf75 2024-11-04 o client: fsys.Client,
93 1081cf75 2024-11-04 o }, nil
94 1081cf75 2024-11-04 o }
95 1081cf75 2024-11-04 o
96 1081cf75 2024-11-04 o id, err = strconv.Atoi(elems[2])
97 1081cf75 2024-11-04 o if err != nil {
98 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fmt.Errorf("bad comment id")}
99 1081cf75 2024-11-04 o }
100 1081cf75 2024-11-04 o comment, err := fsys.Client.LookupComment(id)
101 1081cf75 2024-11-04 o if errors.Is(err, lemmy.ErrNotFound) {
102 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, fs.ErrNotExist}
103 1081cf75 2024-11-04 o } else if err != nil {
104 1081cf75 2024-11-04 o return nil, &fs.PathError{"open", name, err}
105 1081cf75 2024-11-04 o }
106 1081cf75 2024-11-04 o return &lFile{
107 1081cf75 2024-11-04 o info: &comment,
108 1081cf75 2024-11-04 o buf: io.NopCloser(commentText(&comment)),
109 1081cf75 2024-11-04 o client: fsys.Client,
110 1081cf75 2024-11-04 o }, nil
111 1081cf75 2024-11-04 o }
112 1081cf75 2024-11-04 o
113 1081cf75 2024-11-04 o func (fsys *FS) openRoot() (fs.File, error) {
114 1081cf75 2024-11-04 o dirinfo := new(dirInfo)
115 1081cf75 2024-11-04 o communities, err := fsys.Client.Communities(lemmy.ListAll)
116 1081cf75 2024-11-04 o if err != nil {
117 1081cf75 2024-11-04 o return nil, err
118 1081cf75 2024-11-04 o }
119 1081cf75 2024-11-04 o for _, c := range communities {
120 1081cf75 2024-11-04 o c := c
121 1081cf75 2024-11-04 o dent := fs.FileInfoToDirEntry(&c)
122 1081cf75 2024-11-04 o dirinfo.entries = append(dirinfo.entries, dent)
123 1081cf75 2024-11-04 o }
124 1081cf75 2024-11-04 o return &dummy{
125 1081cf75 2024-11-04 o name: ".",
126 1081cf75 2024-11-04 o mode: fs.ModeDir | 0444,
127 1081cf75 2024-11-04 o contents: []byte("hello, world!"),
128 1081cf75 2024-11-04 o dirinfo: dirinfo,
129 1081cf75 2024-11-04 o mtime: time.Now(),
130 1081cf75 2024-11-04 o }, nil
131 1081cf75 2024-11-04 o }