diff options
| author | Xe Iaso <me@xeiaso.net> | 2025-01-07 23:41:53 -0500 |
|---|---|---|
| committer | Xe Iaso <me@xeiaso.net> | 2025-01-11 16:46:28 -0500 |
| commit | 6bc2938856792f851b18fb3550fdb4c2c8040fce (patch) | |
| tree | e7a77aa35d9c94ae5ea7609c08f00b2b3ffca6eb /cmd/patchouli/main.go | |
| parent | c2187ae96bf081aba31a965d0b58e5934a42a93f (diff) | |
| download | x-6bc2938856792f851b18fb3550fdb4c2c8040fce.tar.xz x-6bc2938856792f851b18fb3550fdb4c2c8040fce.zip | |
kube/alrest: fix
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd/patchouli/main.go')
| -rw-r--r-- | cmd/patchouli/main.go | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/cmd/patchouli/main.go b/cmd/patchouli/main.go new file mode 100644 index 0000000..a316a0c --- /dev/null +++ b/cmd/patchouli/main.go @@ -0,0 +1,134 @@ +package main + +import ( + "context" + "database/sql" + "flag" + "fmt" + "log" + "log/slog" + "net/http" + "path/filepath" + + "connectrpc.com/connect" + _ "github.com/ncruces/go-sqlite3/embed" + "github.com/ncruces/go-sqlite3/gormlite" + slogGorm "github.com/orandin/slog-gorm" + "google.golang.org/protobuf/types/known/timestamppb" + "gorm.io/gorm" + gormPrometheus "gorm.io/plugin/prometheus" + "within.website/x/buf/patchouli" + "within.website/x/buf/patchouli/patchouliconnect" + "within.website/x/cmd/patchouli/ytdlp" + "within.website/x/internal" +) + +var ( + bind = flag.String("bind", ":2934", "HTTP bind address") + dataDir = flag.String("data-dir", "./var", "location to store data persistently") +) + +func main() { + internal.HandleStartup() + + slog.Info("starting up", "bind", *bind, "data-dir", *dataDir) + + db, err := connectDB() + if err != nil { + log.Fatalf("can't connect to DB: %w", err) + } + _ = db + + s := &Server{db: db} + + compress1KB := connect.WithCompressMinBytes(1024) + + mux := http.NewServeMux() + mux.Handle(patchouliconnect.NewSyndicateHandler(s, compress1KB)) + + slog.Info("listening", "url", "http://localhost"+*bind) + log.Fatal(http.ListenAndServe(*bind, mux)) +} + +func connectDB() (*gorm.DB, error) { + db, err := gorm.Open(gormlite.Open(filepath.Join(*dataDir, "data.db")), &gorm.Config{ + Logger: slogGorm.New( + slogGorm.WithErrorField("err"), + slogGorm.WithRecordNotFoundError(), + ), + }) + if err != nil { + return nil, fmt.Errorf("failed to connect to database: %w", err) + } + + if err := db.AutoMigrate( + &Video{}, + ); err != nil { + return nil, fmt.Errorf("failed to migrate schema: %w", err) + } + + db.Use(gormPrometheus.New(gormPrometheus.Config{ + DBName: "mi", + })) + + return db, nil +} + +type Server struct { + db *gorm.DB +} + +func (s *Server) Info( + ctx context.Context, + req *connect.Request[patchouli.TwitchInfoReq], +) ( + *connect.Response[patchouli.TwitchInfoResp], + error, +) { + metadata, err := ytdlp.Metadata(ctx, req.Msg.GetUrl()) + if err != nil { + slog.Error("can't fetch metadata for video", "url", req.Msg.GetUrl(), "err", err) + return nil, connect.NewError(connect.CodeInternal, err) + } + + result := &patchouli.TwitchInfoResp{ + Id: metadata.ID, + Title: metadata.Title, + ThumbnailUrl: metadata.Thumbnail, + Duration: metadata.DurationString, + UploadDate: timestamppb.New(metadata.UploadDate.Time), + Url: req.Msg.GetUrl(), + } + + return connect.NewResponse(result), nil +} + +func (s *Server) Download( + ctx context.Context, + req *connect.Request[patchouli.TwitchDownloadReq], +) ( + *connect.Response[patchouli.TwitchDownloadResp], + error, +) { + dir := filepath.Join(*dataDir, "video") + + if err := ytdlp.Download(ctx, req.Msg.GetUrl(), dir); err != nil { + return nil, err + } + + result := &patchouli.TwitchDownloadResp{ + Url: req.Msg.Url, + Location: dir, + } + + return connect.NewResponse(result), nil +} + +type Video struct { + gorm.Model + TwitchID string `gorm:"uniqueIndex"` + TwitchURL string `gorm:"uniqueIndex"` + Title string + State string + BlogPath sql.NullString +} |
