11 1081cf75 2024-11-04 o "olowe.co/apub/lemmy"
14 1081cf75 2024-11-04 o type fakeStat struct {
17 1081cf75 2024-11-04 o mode fs.FileMode
18 1081cf75 2024-11-04 o mtime time.Time
21 1081cf75 2024-11-04 o func (s *fakeStat) Name() string { return s.name }
22 1081cf75 2024-11-04 o func (s *fakeStat) Size() int64 { return s.size }
23 1081cf75 2024-11-04 o func (s *fakeStat) Mode() fs.FileMode { return s.mode }
24 1081cf75 2024-11-04 o func (s *fakeStat) ModTime() time.Time { return s.mtime }
25 1081cf75 2024-11-04 o func (s *fakeStat) IsDir() bool { return s.mode.IsDir() }
26 1081cf75 2024-11-04 o func (s *fakeStat) Sys() any { return nil }
28 1081cf75 2024-11-04 o type dummy struct {
30 1081cf75 2024-11-04 o mode fs.FileMode
31 1081cf75 2024-11-04 o mtime time.Time
32 1081cf75 2024-11-04 o contents []byte
33 1081cf75 2024-11-04 o dirinfo *dirInfo
34 1081cf75 2024-11-04 o buf io.ReadCloser
37 1081cf75 2024-11-04 o func (f *dummy) Name() string { return f.name }
38 1081cf75 2024-11-04 o func (f *dummy) IsDir() bool { return f.mode.IsDir() }
39 1081cf75 2024-11-04 o func (f *dummy) Type() fs.FileMode { return f.mode.Type() }
40 1081cf75 2024-11-04 o func (f *dummy) Info() (fs.FileInfo, error) { return f.Stat() }
42 1081cf75 2024-11-04 o func (f *dummy) Stat() (fs.FileInfo, error) {
43 1081cf75 2024-11-04 o return &fakeStat{
46 1081cf75 2024-11-04 o size: int64(len(f.contents)),
47 1081cf75 2024-11-04 o mtime: f.mtime,
51 1081cf75 2024-11-04 o func (f *dummy) Read(p []byte) (int, error) {
52 1081cf75 2024-11-04 o if f.buf == nil {
53 1081cf75 2024-11-04 o f.buf = io.NopCloser(bytes.NewReader(f.contents))
55 1081cf75 2024-11-04 o return f.buf.Read(p)
58 1081cf75 2024-11-04 o func (f *dummy) Close() error {
59 1081cf75 2024-11-04 o if f.buf == nil {
62 1081cf75 2024-11-04 o err := f.buf.Close()
67 1081cf75 2024-11-04 o func (f *dummy) ReadDir(n int) ([]fs.DirEntry, error) {
68 1081cf75 2024-11-04 o if !f.mode.IsDir() {
69 1081cf75 2024-11-04 o return nil, &fs.PathError{"readdir", f.name, fmt.Errorf("not a directory")}
70 1081cf75 2024-11-04 o } else if f.dirinfo == nil {
71 1081cf75 2024-11-04 o // TODO(otl): is this accidental? maybe return an error here.
72 1081cf75 2024-11-04 o return nil, &fs.PathError{"readdir", f.name, fmt.Errorf("no dirinfo to track reads")}
75 1081cf75 2024-11-04 o return f.dirinfo.ReadDir(n)
78 1081cf75 2024-11-04 o type lFile struct {
79 1081cf75 2024-11-04 o info fs.FileInfo
80 1081cf75 2024-11-04 o dirinfo *dirInfo
81 1081cf75 2024-11-04 o client *lemmy.Client
82 1081cf75 2024-11-04 o buf io.ReadCloser
85 1081cf75 2024-11-04 o func (f *lFile) Read(p []byte) (int, error) {
86 1081cf75 2024-11-04 o if f.buf == nil {
87 1081cf75 2024-11-04 o f.buf = io.NopCloser(strings.NewReader("directory"))
89 1081cf75 2024-11-04 o return f.buf.Read(p)
92 1081cf75 2024-11-04 o func (f *lFile) Close() error {
93 1081cf75 2024-11-04 o if f.buf == nil || f.dirinfo == nil {
94 1081cf75 2024-11-04 o return fs.ErrClosed
96 1081cf75 2024-11-04 o f.dirinfo = nil
97 1081cf75 2024-11-04 o err := f.buf.Close()
102 1081cf75 2024-11-04 o func (f *lFile) Stat() (fs.FileInfo, error) {
103 1081cf75 2024-11-04 o return f.info, nil
106 1081cf75 2024-11-04 o func (f *lFile) ReadDir(n int) ([]fs.DirEntry, error) {
107 1081cf75 2024-11-04 o if f.dirinfo == nil {
108 1081cf75 2024-11-04 o f.dirinfo = new(dirInfo)
109 1081cf75 2024-11-04 o switch f.info.(type) {
110 1081cf75 2024-11-04 o case *lemmy.Community:
111 1081cf75 2024-11-04 o posts, err := f.client.Posts(f.info.Name(), lemmy.ListAll)
112 1081cf75 2024-11-04 o if err != nil {
113 1081cf75 2024-11-04 o return nil, &fs.PathError{"readdir", f.info.Name(), err}
115 1081cf75 2024-11-04 o for _, p := range posts {
117 1081cf75 2024-11-04 o f.dirinfo.entries = append(f.dirinfo.entries, fs.FileInfoToDirEntry(&p))
119 1081cf75 2024-11-04 o case *lemmy.Post:
120 1081cf75 2024-11-04 o p := f.info.(*lemmy.Post)
121 1081cf75 2024-11-04 o comments, err := f.client.Comments(p.ID, lemmy.ListAll)
122 1081cf75 2024-11-04 o if err != nil {
123 1081cf75 2024-11-04 o return nil, &fs.PathError{"readdir", f.info.Name(), err}
125 1081cf75 2024-11-04 o for _, c := range comments {
127 1081cf75 2024-11-04 o f.dirinfo.entries = append(f.dirinfo.entries, fs.FileInfoToDirEntry(&c))
129 1081cf75 2024-11-04 o f.dirinfo.entries = append(f.dirinfo.entries, postFile(p))
131 1081cf75 2024-11-04 o return nil, &fs.PathError{"readdir", f.info.Name(), fmt.Errorf("not a directory")}
134 1081cf75 2024-11-04 o return f.dirinfo.ReadDir(n)
136 1081cf75 2024-11-04 o func postText(p *lemmy.Post) *bytes.Buffer {
137 1081cf75 2024-11-04 o buf := &bytes.Buffer{}
138 1081cf75 2024-11-04 o fmt.Fprintln(buf, "From:", p.CreatorID)
139 1081cf75 2024-11-04 o fmt.Fprintf(buf, "Message-Id: <%d>\n", p.ID)
140 1081cf75 2024-11-04 o fmt.Fprintf(buf, "List-Archive: <%s>\n", p.URL)
141 1081cf75 2024-11-04 o fmt.Fprintln(buf, "Date:", p.ModTime().Format(time.RFC822))
142 1081cf75 2024-11-04 o fmt.Fprintln(buf, "Subject:", p.Title)
143 1081cf75 2024-11-04 o fmt.Fprintln(buf)
144 1081cf75 2024-11-04 o if p.URL != "" {
145 1081cf75 2024-11-04 o fmt.Fprintln(buf, p.URL)
147 1081cf75 2024-11-04 o fmt.Fprintln(buf, p.Body)
151 1081cf75 2024-11-04 o func postFile(p *lemmy.Post) *dummy {
152 1081cf75 2024-11-04 o return &dummy{
155 1081cf75 2024-11-04 o mtime: p.ModTime(),
156 1081cf75 2024-11-04 o contents: postText(p).Bytes(),
160 1081cf75 2024-11-04 o func commentText(c *lemmy.Comment) *bytes.Buffer {
161 1081cf75 2024-11-04 o buf := &bytes.Buffer{}
162 1081cf75 2024-11-04 o fmt.Fprintln(buf, "From:", c.CreatorID)
163 1081cf75 2024-11-04 o fmt.Fprintln(buf, "Date:", c.ModTime().Format(time.RFC822))
164 1081cf75 2024-11-04 o fmt.Fprintf(buf, "Message-ID: <%d>\n", c.ID)
165 1081cf75 2024-11-04 o fmt.Fprintf(buf, "List-Archive: <%s>\n", c.ActivityURL)
166 1081cf75 2024-11-04 o fmt.Fprintln(buf, "Subject: Re:", c.PostID)
167 1081cf75 2024-11-04 o fmt.Fprintln(buf)
168 1081cf75 2024-11-04 o fmt.Fprintln(buf, c.Content)