Skip to content

Commit

Permalink
implement file storage
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Mar 25, 2024
1 parent 428b571 commit 3c6362a
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 27 deletions.
18 changes: 9 additions & 9 deletions internal/viewer/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package viewer

import (
"errors"
"io"
"io/fs"
"net/http"
"os"
"path/filepath"
Expand Down Expand Up @@ -45,6 +45,10 @@ func (v *Viewer) newFileHandler(fn func(w http.ResponseWriter, r *http.Request,
func (v *Viewer) channelHandler(w http.ResponseWriter, r *http.Request, id string) {
mm, err := v.src.AllMessages(id)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
http.NotFound(w, r)
return
}
v.lg.Printf("%s: error: %v", id, err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
Expand Down Expand Up @@ -134,7 +138,8 @@ func (v *Viewer) fileHandler(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
return
}
f, err := v.src.File(id, filename)
fs := v.src.FS()
path, err := v.src.File(id, filename)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
http.NotFound(w, r)
Expand All @@ -144,13 +149,8 @@ func (v *Viewer) fileHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fi, err := f.Stat()
if err != nil {
v.lg.Printf("error: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.ServeContent(w, r, filename, fi.ModTime(), f.(io.ReadSeeker)) // TODO: hack

http.ServeFileFS(w, r, fs, path)
}

func (v *Viewer) userHandler(w http.ResponseWriter, r *http.Request) {
Expand Down
13 changes: 7 additions & 6 deletions internal/viewer/source/chunkdir.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package source

import (
"io/fs"
"os"

"github.com/rusq/slack"
"github.com/rusq/slackdump/v3/internal/chunk"
)

type ChunkDir struct {
d *chunk.Directory
filestorage
}

func NewChunkDir(d *chunk.Directory) *ChunkDir {
return &ChunkDir{d: d}
var st filestorage = fstNotFound{}
if fst, err := newMattermostStorage(os.DirFS(d.Name())); err == nil {
st = fst
}
return &ChunkDir{d: d, filestorage: st}
}

func (c *ChunkDir) AllMessages(channelID string) ([]slack.Message, error) {
Expand Down Expand Up @@ -66,7 +71,3 @@ func (c *ChunkDir) Type() string {
func (c *ChunkDir) Users() ([]slack.User, error) {
return c.d.Users()
}

func (c *ChunkDir) File(fileID string, filename string) (f fs.File, err error) {
return c.d.File(fileID, filename)
}
14 changes: 8 additions & 6 deletions internal/viewer/source/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ type Dump struct {
c []slack.Channel
fs fs.FS
name string
filestorage
}

func NewDump(fsys fs.FS, name string) (*Dump, error) {
var st filestorage = fstNotFound{}
if fst, err := newDumpStorage(fsys); err == nil {
st = fst
}
d := &Dump{
fs: fsys,
name: name,
fs: fsys,
name: name,
filestorage: st,
}
// initialise channels for quick lookup
c, err := d.Channels()
Expand Down Expand Up @@ -130,7 +136,3 @@ func (d Dump) ChannelInfo(channelID string) (*slack.Channel, error) {
}
return nil, fs.ErrNotExist
}

func (d Dump) File(id string, filename string) (f fs.File, err error) {
panic("not implemented")
}
23 changes: 19 additions & 4 deletions internal/viewer/source/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Export struct {
fs fs.FS
chanNames map[string]string // maps the channel id to the channel name.
name string // name of the file
filestorage
}

func NewExport(fsys fs.FS, name string) (*Export, error) {
Expand All @@ -31,10 +32,28 @@ func NewExport(fsys fs.FS, name string) (*Export, error) {
for _, ch := range c {
z.chanNames[ch.ID] = ch.Name
}
// determine files path
rslv, err := exportType(fsys)
if err != nil {
return nil, err
}
z.filestorage = rslv

return z, nil
}

// exportType determines the type of the file storage used.
func exportType(fsys fs.FS) (filestorage, error) {
if _, err := fs.Stat(fsys, "__uploads"); err == nil {
return newMattermostStorage(fsys)
}
idx, err := buildFileIndex(fsys, ".")
if err != nil || len(idx) == 0 {
return fstNotFound{}, nil
}
return newStandardStorage(fsys, idx), nil
}

func (e *Export) Channels() ([]slack.Channel, error) {
cc, err := unmarshal[[]slack.Channel](e.fs, "channels.json")
if err != nil {
Expand Down Expand Up @@ -115,7 +134,3 @@ func (e *Export) ChannelInfo(channelID string) (*slack.Channel, error) {
}
return nil, fmt.Errorf("%s: %s", "channel not found", channelID)
}

func (e *Export) File(id string, name string) (fs.File, error) {
panic("not implemented")
}
36 changes: 36 additions & 0 deletions internal/viewer/source/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package source
import (
"archive/zip"
"io/fs"
"os"
"path/filepath"
"reflect"
"testing"
Expand Down Expand Up @@ -112,3 +113,38 @@ func TestExport_AllMessages(t *testing.T) {
})
}
}

func Test_buildFileIndex(t *testing.T) {
type args struct {
fsys fs.FS
dir string
}
tests := []struct {
name string
args args
want map[string]string
wantErr bool
}{
{
name: "test",
args: args{
fsys: os.DirFS(filepath.Join("..", "..", "..", "tmp", "stdexport")),
dir: ".",
},
want: map[string]string{},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := buildFileIndex(tt.args.fsys, tt.args.dir)
if (err != nil) != tt.wantErr {
t.Errorf("buildFileIndex() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("buildFileIndex() = %v, want %v", got, tt.want)
}
})
}
}
Loading

0 comments on commit 3c6362a

Please sign in to comment.