@@ -2,6 +2,7 @@ package lume
2
2
3
3
import (
4
4
"archive/zip"
5
+ "bytes"
5
6
"context"
6
7
"encoding/json"
7
8
"errors"
@@ -12,6 +13,7 @@ import (
12
13
"io/fs"
13
14
"log"
14
15
"log/slog"
16
+ "mime/multipart"
15
17
"net/http"
16
18
"os"
17
19
"os/exec"
@@ -26,6 +28,7 @@ import (
26
28
"google.golang.org/protobuf/types/known/timestamppb"
27
29
"gopkg.in/mxpv/patreon-go.v1"
28
30
"tailscale.com/metrics"
31
+ "within.website/x/web"
29
32
"xeiaso.net/v4/internal/config"
30
33
"xeiaso.net/v4/internal/jsonfeed"
31
34
"xeiaso.net/v4/pb/external/mi"
@@ -40,11 +43,13 @@ var (
40
43
41
44
_ fs.FS = (* FS )(nil )
42
45
43
- opens = metrics.LabelMap {Label : "name" }
44
- builds = expvar .NewInt ("gauge_xesite_builds" )
45
- updates = expvar .NewInt ("gauge_xesite_updates" )
46
- updateErrors = expvar .NewInt ("gauge_xesite_update_errors" )
47
- lastBuildTime = expvar .NewInt ("gauge_xesite_last_build_time_ms" )
46
+ opens = metrics.LabelMap {Label : "name" }
47
+ builds = expvar .NewInt ("gauge_xesite_builds" )
48
+ updates = expvar .NewInt ("gauge_xesite_updates" )
49
+ updateErrors = expvar .NewInt ("gauge_xesite_update_errors" )
50
+ lastBuildTime = expvar .NewInt ("gauge_xesite_last_build_time_ms" )
51
+ futureSightPokes = expvar .NewInt ("gauge_xesite_future_sight_pokes" )
52
+ futureSightErrors = expvar .NewInt ("gauge_xesite_future_sight_errors" )
48
53
)
49
54
50
55
func init () {
@@ -127,14 +132,15 @@ func (f *FS) Open(name string) (fs.File, error) {
127
132
}
128
133
129
134
type Options struct {
130
- Development bool
131
- Branch string
132
- Repo string
133
- StaticSiteDir string
134
- URL string
135
- PatreonClient * patreon.Client
136
- DataDir string
137
- MiURL string
135
+ Development bool
136
+ Branch string
137
+ Repo string
138
+ StaticSiteDir string
139
+ URL string
140
+ PatreonClient * patreon.Client
141
+ DataDir string
142
+ MiURL string
143
+ FutureSightURL string
138
144
}
139
145
140
146
func New (ctx context.Context , o * Options ) (* FS , error ) {
@@ -217,6 +223,10 @@ func New(ctx context.Context, o *Options) (*FS, error) {
217
223
slog .Debug ("mi integration enabled" )
218
224
}
219
225
226
+ if o .FutureSightURL != "" {
227
+ slog .Debug ("future sight integration enabled" )
228
+ }
229
+
220
230
conf , err := config .Load (filepath .Join (fs .repoDir , "config.dhall" ))
221
231
if err != nil {
222
232
log .Fatal (err )
@@ -231,6 +241,10 @@ func New(ctx context.Context, o *Options) (*FS, error) {
231
241
go fs .mimiRefresh ()
232
242
fs .lastBuildTime = time .Now ()
233
243
244
+ if o .FutureSightURL != "" {
245
+ go fs .FutureSight (context .Background ())
246
+ }
247
+
234
248
return fs , nil
235
249
}
236
250
@@ -300,6 +314,10 @@ func (f *FS) Update(ctx context.Context) error {
300
314
301
315
go f .mimiRefresh ()
302
316
317
+ if f .opt .FutureSightURL != "" {
318
+ go f .FutureSight (context .Background ())
319
+ }
320
+
303
321
return nil
304
322
}
305
323
@@ -616,3 +634,57 @@ func (f *FS) mimiRefresh() {
616
634
}
617
635
}
618
636
}
637
+
638
+ func (f * FS ) FutureSight (ctx context.Context ) {
639
+ if err := f .futureSight (ctx ); err != nil {
640
+ slog .Error ("failed to poke future sight" , "err" , err )
641
+ futureSightErrors .Add (1 )
642
+ return
643
+ }
644
+
645
+ futureSightPokes .Add (1 )
646
+ }
647
+
648
+ func (f * FS ) futureSight (ctx context.Context ) error {
649
+ zipLoc := filepath .Join (f .opt .DataDir , "site.zip" )
650
+
651
+ fin , err := os .Open (zipLoc )
652
+ if err != nil {
653
+ return fmt .Errorf ("lume: can't open site zip for future sight: %w" , err )
654
+ }
655
+ defer fin .Close ()
656
+
657
+ buf := bytes .NewBuffer (nil )
658
+ writer := multipart .NewWriter (buf )
659
+
660
+ part , err := writer .CreateFormFile ("file" , filepath .Base (zipLoc ))
661
+ if err != nil {
662
+ return fmt .Errorf ("lume: can't create form file: %w" , err )
663
+ }
664
+
665
+ if _ , err := io .Copy (part , fin ); err != nil {
666
+ return fmt .Errorf ("lume: can't copy file to buffer: %w" , err )
667
+ }
668
+
669
+ if err := writer .Close (); err != nil {
670
+ return fmt .Errorf ("lume: can't close writer: %w" , err )
671
+ }
672
+
673
+ req , err := http .NewRequestWithContext (ctx , "POST" , f .opt .FutureSightURL + "/upload" , buf )
674
+ if err != nil {
675
+ return fmt .Errorf ("lume: can't create request: %w" , err )
676
+ }
677
+
678
+ req .Header .Set ("Content-Type" , writer .FormDataContentType ())
679
+
680
+ resp , err := http .DefaultClient .Do (req )
681
+ if err != nil {
682
+ return fmt .Errorf ("lume: can't post to future sight: %w" , err )
683
+ }
684
+
685
+ if resp .StatusCode != http .StatusOK {
686
+ return web .NewError (http .StatusOK , resp )
687
+ }
688
+
689
+ return nil
690
+ }
0 commit comments