-
-
Notifications
You must be signed in to change notification settings - Fork 252
Expand file tree
/
Copy pathupload.go
More file actions
167 lines (146 loc) · 5.73 KB
/
Copy pathupload.go
File metadata and controls
167 lines (146 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package upload
import (
"context"
"fmt"
"time"
"github.com/simulot/immich-go/adapters"
"github.com/simulot/immich-go/adapters/folder"
"github.com/simulot/immich-go/adapters/fromimmich"
gp "github.com/simulot/immich-go/adapters/googlePhotos"
"github.com/simulot/immich-go/adapters/shared"
"github.com/simulot/immich-go/app"
"github.com/simulot/immich-go/immich"
"github.com/simulot/immich-go/internal/assets"
"github.com/simulot/immich-go/internal/assets/cache"
"github.com/simulot/immich-go/internal/fileevent"
"github.com/simulot/immich-go/internal/filenames"
"github.com/simulot/immich-go/internal/filters"
"github.com/simulot/immich-go/internal/gen/syncset"
"github.com/simulot/immich-go/internal/groups/burst"
"github.com/simulot/immich-go/internal/groups/epsonfastfoto"
"github.com/simulot/immich-go/internal/groups/series"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
type UpLoadMode int
const (
UpModeGoogleTakeout UpLoadMode = iota
UpModeFolder
UpModeICloud
UpModePicasa
)
func (m UpLoadMode) String() string {
switch m {
case UpModeGoogleTakeout:
return "Google Takeout"
case UpModeFolder:
return "Folder"
case UpModeICloud:
return "iCloud"
case UpModePicasa:
return "Picasa"
default:
return "Unknown"
}
}
type UpCmd struct {
// Cli flags
shared.StackOptions
client app.Client
NoUI bool // Disable UI
Overwrite bool // Always overwrite files on the server with local versions
Tags []string
SessionTag bool
session string // Session tag value
// Upload command state
// Filters []filters.Filter
tz *time.Location
Mode UpLoadMode
app *app.Application
assetIndex *immichIndex // List of assets present on the server
localAssets *syncset.Set[string] // List of assets present on the local input by name+size
immichAssetsReady chan struct{} // Signal that the asset index is ready
deleteServerList []*immich.Asset // List of server assets to remove
adapter adapters.Reader // the source of assets
DebugCounters bool // Enable CSV action counters per file
albumsCache *cache.CollectionCache[assets.Album] // List of albums present on the server
tagsCache *cache.CollectionCache[assets.Tag] // List of tags present on the server
finished bool // the finish task has been run
infoCollector *filenames.InfoCollector // Collects information about the files being processed
}
func (uc *UpCmd) RegisterFlags(flags *pflag.FlagSet) {
uc.client.RegisterFlags(flags, "")
flags.BoolVar(&uc.NoUI, "no-ui", false, "Disable the user interface")
flags.BoolVar(&uc.Overwrite, "overwrite", false, "Always overwrite files on the server with local versions")
flags.StringSliceVar(&uc.Tags, "tag", nil, "Add tags to the imported assets. Can be specified multiple times. Hierarchy is supported using a / separator (e.g. 'tag1/subtag1')")
flags.BoolVar(&uc.SessionTag, "session-tag", false, "Tag uploaded photos with a tag \"{immich-go}/YYYY-MM-DD HH-MM-SS\"")
uc.StackOptions.RegisterFlags(flags)
}
// NewUploadCommand creates the root "upload" command and adds subcommands for each supported source.
// It registers flags and initializes the UpCmd struct, which holds the state for uploads.
func NewUploadCommand(ctx context.Context, app *app.Application) *cobra.Command {
cmd := &cobra.Command{
Use: "upload [flags]",
Short: "Upload photos to an Immich server from various sources",
Args: cobra.NoArgs, // This command does not accept any arguments, only subcommands
}
uc := &UpCmd{
app: app,
localAssets: syncset.New[string](),
immichAssetsReady: make(chan struct{}),
}
// Register CLI flags for the upload command
uc.RegisterFlags(cmd.PersistentFlags())
// Add subcommands for each supported upload source
cmd.AddCommand(folder.NewFromFolderCommand(ctx, cmd, app, uc))
cmd.AddCommand(folder.NewFromICloudCommand(ctx, cmd, app, uc))
cmd.AddCommand(folder.NewFromPicasaCommand(ctx, cmd, app, uc))
cmd.AddCommand(gp.NewFromGooglePhotosCommand(ctx, cmd, app, uc))
cmd.AddCommand(fromimmich.NewFromImmichCommand(ctx, cmd, app, uc))
cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
// Initialize the Journal
if app.Jnl() == nil {
app.SetJnl(fileevent.NewRecorder(app.Log().Logger))
}
app.SetTZ(time.Local)
if tz, err := cmd.Flags().GetString("time-zone"); err == nil && tz != "" {
if loc, err := time.LoadLocation(tz); err == nil {
app.SetTZ(loc)
}
} else {
return err
}
return nil
}
return cmd
}
// Run is called back by the actual asset reader
func (uc *UpCmd) Run(cmd *cobra.Command, adapter adapters.Reader) error {
uc.Mode = UpModeGoogleTakeout // TODO
// ready to run
ctx := cmd.Context()
err := uc.client.Open(ctx, uc.app)
if err != nil {
return nil
}
uc.tz = uc.app.GetTZ()
uc.app.SetSupportedMedia(uc.client.Immich.SupportedMedia())
// Initialize the Journal
if uc.app.Jnl() == nil {
uc.app.SetJnl(fileevent.NewRecorder(uc.app.Log().Logger))
}
if uc.SessionTag {
uc.session = fmt.Sprintf("{immich-go}/%s", time.Now().Format("2006-01-02 15:04:05"))
}
if uc.ManageEpsonFastFoto {
g := epsonfastfoto.Group{}
uc.Groupers = append(uc.Groupers, g.Group)
}
if uc.ManageBurst != filters.BurstNothing {
uc.Groupers = append(uc.Groupers, burst.Group)
}
uc.Groupers = append(uc.Groupers, series.Group)
uc.Filters = append(uc.Filters, uc.ManageBurst.GroupFilter(), uc.ManageRawJPG.GroupFilter(), uc.ManageHEICJPG.GroupFilter())
uc.infoCollector = filenames.NewInfoCollector(uc.tz, uc.app.GetSupportedMedia())
return uc.upload(ctx, adapter)
}