Compare commits
1 Commits
master
..
dd94c88a0e
| Author | SHA1 | Date | |
|---|---|---|---|
|
dd94c88a0e
|
@@ -1,10 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/yonah/streamdata"
|
||||
)
|
||||
@@ -21,22 +18,4 @@ func printVOD(v *streamdata.VOD) {
|
||||
} else {
|
||||
fmt.Printf("YouTube : %s | %s\n", v.Title, date)
|
||||
}
|
||||
if v.Mirror != "" {
|
||||
fmt.Println("Mirror :", v.Mirror)
|
||||
}
|
||||
}
|
||||
|
||||
// printVODIdent calls printVOD for a VOD identifier.
|
||||
func printVODIdent(channel *streamdata.Channel, ident *streamdata.Ident) error {
|
||||
v, err := channel.Load(ident)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
return syscall.ENOENT
|
||||
}
|
||||
|
||||
printVOD(v)
|
||||
fmt.Println("Path :", channel.Path(ident))
|
||||
return nil
|
||||
}
|
||||
|
||||
+11
-121
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmp"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -12,8 +11,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -203,7 +200,16 @@ func main() {
|
||||
return err
|
||||
}
|
||||
|
||||
return printVODIdent(channel, &ident)
|
||||
if v, err := channel.Load(&ident); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
return syscall.ENOENT
|
||||
} else {
|
||||
printVOD(v)
|
||||
fmt.Println("Path :", channel.Path(&ident))
|
||||
return nil
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -215,129 +221,13 @@ func main() {
|
||||
return errors.New("list requires a channel selected")
|
||||
}
|
||||
|
||||
for ident := range channel.All(&err, true) {
|
||||
for ident := range channel.All(&err) {
|
||||
fmt.Println(ident)
|
||||
}
|
||||
return
|
||||
},
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
"last",
|
||||
"Display metadata of final VOD entry",
|
||||
func([]string) (err error) {
|
||||
if channel == nil {
|
||||
return errors.New("last requires a channel selected")
|
||||
}
|
||||
|
||||
var ident *streamdata.Ident
|
||||
for ident = range channel.All(&err, true) {
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if ident == nil {
|
||||
return errors.New("no entries available")
|
||||
}
|
||||
return printVODIdent(channel, ident)
|
||||
},
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
"mirror",
|
||||
"Populate mirror address of the next un-mirrored asset",
|
||||
func([]string) (err error) {
|
||||
if channel == nil {
|
||||
return errors.New("mirror requires a channel selected")
|
||||
}
|
||||
|
||||
idents := slices.Collect(channel.All(&err, false))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
slices.SortFunc(idents, func(a, b *streamdata.Ident) int {
|
||||
return cmp.Compare(a.Serial, b.Serial)
|
||||
})
|
||||
|
||||
unique := errors.New("entry already mirrored")
|
||||
for i, ident := range idents {
|
||||
if err = channel.Edit(ident, func(v *streamdata.VOD) (err error) {
|
||||
if v.Mirror != "" {
|
||||
return unique
|
||||
}
|
||||
|
||||
var parts []*streamdata.VOD
|
||||
for _, next := range idents[i+1:] {
|
||||
var part *streamdata.VOD
|
||||
if part, err = channel.Load(next); err != nil {
|
||||
return
|
||||
}
|
||||
if part.Title != v.Title {
|
||||
break
|
||||
}
|
||||
parts = append(parts, part)
|
||||
}
|
||||
|
||||
pathname := path.Join(
|
||||
flagBase,
|
||||
"upload"+streamdata.ChannelVODSuffix,
|
||||
)
|
||||
if err = os.Symlink(path.Join(
|
||||
"vod",
|
||||
ident.String()+streamdata.ChannelVODSuffix,
|
||||
), pathname); err != nil {
|
||||
return
|
||||
}
|
||||
log.Println("pending video at", pathname)
|
||||
defer func() {
|
||||
removeErr := os.Remove(pathname)
|
||||
if err == nil {
|
||||
err = removeErr
|
||||
}
|
||||
}()
|
||||
|
||||
defer toErr(&err)
|
||||
isattyStd()
|
||||
br := bufio.NewReader(os.Stdin)
|
||||
|
||||
if len(parts) > 0 {
|
||||
fmt.Println("assets with identical title:")
|
||||
for j := range parts {
|
||||
fmt.Println(idents[i+1+j])
|
||||
}
|
||||
if !require(promptBool(br, "Proceed? ", true)) {
|
||||
for j, part := range parts {
|
||||
fmt.Println(idents[i+1+j])
|
||||
printVOD(part)
|
||||
}
|
||||
return errors.New(
|
||||
strconv.Itoa(len(parts)) + " trailing parts",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
fmt.Println(ident)
|
||||
printVOD(v)
|
||||
v.Mirror = require(promptTrimNoEmpty(br, "Mirror : "))
|
||||
if !require(promptBool(br, "Proceed? ", true)) {
|
||||
v.Mirror = ""
|
||||
goto retry
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
if err == unique {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
return
|
||||
},
|
||||
)
|
||||
|
||||
c.MustParse(os.Args[1:], func(err error) {
|
||||
if channel != nil {
|
||||
if closeErr := channel.Close(); closeErr != nil {
|
||||
|
||||
@@ -2,4 +2,4 @@ module git.gensokyo.uk/yonah/streamdata
|
||||
|
||||
go 1.26
|
||||
|
||||
require hakurei.app v0.4.5
|
||||
require hakurei.app v0.3.8-0.20260317115839-6cdb6a652b63
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
hakurei.app v0.4.5 h1:u/aEG1K9E0sRORGaaTKkvL3UdaTrw7q6t/Y0pnlTVvs=
|
||||
hakurei.app v0.4.5/go.mod h1:rIWpoHYiZtIPue49bQLkROpQHYh/j2VjJGFrzNrvixU=
|
||||
hakurei.app v0.3.8-0.20260317115839-6cdb6a652b63 h1:Nx5eaHEbWUx6pwA4A+EdmHXvCvO3Xbw7PPcT1QbsVcA=
|
||||
hakurei.app v0.3.8-0.20260317115839-6cdb6a652b63/go.mod h1:rIWpoHYiZtIPue49bQLkROpQHYh/j2VjJGFrzNrvixU=
|
||||
|
||||
@@ -86,8 +86,8 @@ func atoi(data []byte) (v uint64, err error) {
|
||||
10, 64,
|
||||
)
|
||||
if err != nil {
|
||||
numError, ok := errors.AsType[*strconv.NumError](err)
|
||||
if ok && numError != nil {
|
||||
var numError *strconv.NumError
|
||||
if errors.As(err, &numError) && numError != nil {
|
||||
err = numError.Unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-11
@@ -130,8 +130,6 @@ type VOD struct {
|
||||
Date time.Time `json:"date"`
|
||||
// Free-form category string.
|
||||
Category string `json:"category,omitempty"`
|
||||
// A mirror site the asset is uploaded to, usually YouTube.
|
||||
Mirror string `json:"mirror,omitempty"`
|
||||
}
|
||||
|
||||
// ChannelMismatchError describes a mismatching [Ident.Channel] passed to [Channel.Add].
|
||||
@@ -276,10 +274,7 @@ func (c *Channel) Path(ident *Ident) string {
|
||||
// All returns an iterator over all known [Ident] in the on-disk representation.
|
||||
// Iteration stops when encountering the first non-nil error, and its value is
|
||||
// saved to the value pointed to by errP.
|
||||
//
|
||||
// If reuse is true, the same value is updated every iteration and the same
|
||||
// address is yileded as a result.
|
||||
func (c *Channel) All(errP *error, reuse bool) iter.Seq[*Ident] {
|
||||
func (c *Channel) All(errP *error) iter.Seq[*Ident] {
|
||||
return func(yield func(*Ident) bool) {
|
||||
dents, err := c.root.FS().(fs.ReadDirFS).ReadDir(channelPathVOD)
|
||||
if err != nil {
|
||||
@@ -301,11 +296,7 @@ func (c *Channel) All(errP *error, reuse bool) iter.Seq[*Ident] {
|
||||
return
|
||||
}
|
||||
|
||||
p := &ident
|
||||
if !reuse {
|
||||
p = new(ident)
|
||||
}
|
||||
if !yield(p) {
|
||||
if !yield(&ident) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -303,7 +303,7 @@ func TestChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
var iterErr error
|
||||
idents := slices.Collect(c.All(&iterErr, false))
|
||||
idents := slices.Collect(c.All(&iterErr))
|
||||
if iterErr != nil {
|
||||
t.Fatalf("All: error = %#v", iterErr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user