more customisation, more QoL improvements
an all-around good time!
This commit is contained in:
parent
2954689784
commit
45db651388
9 changed files with 315 additions and 147 deletions
|
|
@ -17,70 +17,59 @@ import (
|
|||
"google.golang.org/api/youtube/v3"
|
||||
)
|
||||
|
||||
var DEFAULT_TAGS = []string{
|
||||
"ari melody",
|
||||
"ari melody LIVE",
|
||||
"livestream",
|
||||
"vtuber",
|
||||
"twitch",
|
||||
"gaming",
|
||||
"let's play",
|
||||
"full VOD",
|
||||
"VOD",
|
||||
"stream",
|
||||
"archive",
|
||||
}
|
||||
|
||||
const (
|
||||
CATEGORY_GAMING = "20"
|
||||
CATEGORY_ENTERTAINMENT = "24"
|
||||
YT_CATEGORY_GAMING = "20"
|
||||
YT_CATEGORY_ENTERTAINMENT = "24"
|
||||
)
|
||||
|
||||
type TitleType int
|
||||
type CategoryType int
|
||||
const (
|
||||
TITLE_GAME TitleType = iota
|
||||
TITLE_OTHER
|
||||
CATEGORY_GAME CategoryType = iota
|
||||
CATEGORY_ENTERTAINMENT
|
||||
)
|
||||
|
||||
type (
|
||||
Title struct {
|
||||
Name string
|
||||
Type TitleType
|
||||
Url string
|
||||
Category struct {
|
||||
Name string
|
||||
Type CategoryType
|
||||
Url string
|
||||
}
|
||||
|
||||
Video struct {
|
||||
Title *Title
|
||||
Part int
|
||||
Date time.Time
|
||||
Tags []string
|
||||
Filename string
|
||||
Title string
|
||||
Category *Category
|
||||
Part int
|
||||
Date time.Time
|
||||
Tags []string
|
||||
Filename string
|
||||
SizeBytes int64
|
||||
}
|
||||
)
|
||||
|
||||
func BuildVideo(metadata *scanner.Metadata) (*Video, error) {
|
||||
var titleType TitleType
|
||||
switch metadata.Category.Type {
|
||||
case "gaming":
|
||||
titleType = TITLE_GAME
|
||||
default:
|
||||
titleType = TITLE_OTHER
|
||||
}
|
||||
|
||||
videoDate, err := time.Parse("2006-01-02", metadata.Date)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse date from metadata: %v", err)
|
||||
}
|
||||
|
||||
return &Video{
|
||||
Title: &Title{
|
||||
var category *Category = nil
|
||||
if metadata.Category != nil {
|
||||
category = &Category{
|
||||
Name: metadata.Category.Name,
|
||||
Type: titleType,
|
||||
Type: CATEGORY_ENTERTAINMENT,
|
||||
Url: metadata.Category.Url,
|
||||
},
|
||||
}
|
||||
var ok bool
|
||||
category.Type, ok = videoCategoryStringTypes[metadata.Category.Type]
|
||||
if !ok { category.Type = CATEGORY_ENTERTAINMENT }
|
||||
}
|
||||
|
||||
return &Video{
|
||||
Title: metadata.Title,
|
||||
Category: category,
|
||||
Part: metadata.Part,
|
||||
Date: videoDate,
|
||||
Tags: DEFAULT_TAGS,
|
||||
Tags: DefaultTags,
|
||||
Filename: path.Join(
|
||||
metadata.FootageDir,
|
||||
fmt.Sprintf(
|
||||
|
|
@ -91,73 +80,92 @@ func BuildVideo(metadata *scanner.Metadata) (*Video, error) {
|
|||
}
|
||||
|
||||
type (
|
||||
MetaTitle struct {
|
||||
MetaCategory struct {
|
||||
Name string
|
||||
Type string
|
||||
Url string
|
||||
}
|
||||
|
||||
Metadata struct {
|
||||
Date string
|
||||
Title *MetaTitle
|
||||
Part int
|
||||
Title string
|
||||
Date string
|
||||
Category *MetaCategory
|
||||
Part int
|
||||
}
|
||||
)
|
||||
|
||||
var videoCategoryTypeStrings = map[CategoryType]string{
|
||||
CATEGORY_GAME: "gaming",
|
||||
CATEGORY_ENTERTAINMENT: "entertainment",
|
||||
}
|
||||
var videoCategoryStringTypes = map[string]CategoryType{
|
||||
"gaming": CATEGORY_GAME,
|
||||
"entertainment": CATEGORY_ENTERTAINMENT,
|
||||
}
|
||||
var videoYtCategory = map[CategoryType]string {
|
||||
CATEGORY_GAME: YT_CATEGORY_GAMING,
|
||||
CATEGORY_ENTERTAINMENT: YT_CATEGORY_ENTERTAINMENT,
|
||||
}
|
||||
|
||||
var DefaultTags []string
|
||||
func GetDefaultTags(filepath string) ([]string, error) {
|
||||
file, err := os.ReadFile(filepath)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
tags := strings.Split(string(file), "\n")
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
var titleTemplate *template.Template = template.Must(
|
||||
template.ParseFiles("template/title.txt"),
|
||||
)
|
||||
func BuildTitle(video *Video) (string, error) {
|
||||
var titleType string
|
||||
switch video.Title.Type {
|
||||
case TITLE_GAME:
|
||||
titleType = "game"
|
||||
case TITLE_OTHER:
|
||||
fallthrough
|
||||
default:
|
||||
titleType = "other"
|
||||
out := &bytes.Buffer{}
|
||||
|
||||
var category *MetaCategory
|
||||
if video.Category != nil {
|
||||
category = &MetaCategory{
|
||||
Name: video.Category.Name,
|
||||
Type: videoCategoryTypeStrings[video.Category.Type],
|
||||
Url: video.Category.Url,
|
||||
}
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
titleTemplate.Execute(out, Metadata{
|
||||
// TODO: give templates date format and lowercase functions
|
||||
// these should not be hard-coded!
|
||||
err := titleTemplate.Execute(out, Metadata{
|
||||
Title: video.Title,
|
||||
Date: strings.ToLower(video.Date.Format("02 Jan 2006")),
|
||||
Title: &MetaTitle{
|
||||
Name: video.Title.Name,
|
||||
Type: titleType,
|
||||
Url: video.Title.Url,
|
||||
},
|
||||
Category: category,
|
||||
Part: video.Part,
|
||||
})
|
||||
|
||||
return strings.TrimSpace(out.String()), nil
|
||||
return strings.TrimSpace(out.String()), err
|
||||
}
|
||||
|
||||
var descriptionTemplate *template.Template = template.Must(
|
||||
template.ParseFiles("template/description.txt"),
|
||||
)
|
||||
func BuildDescription(video *Video) (string, error) {
|
||||
var titleType string
|
||||
switch video.Title.Type {
|
||||
case TITLE_GAME:
|
||||
titleType = "game"
|
||||
case TITLE_OTHER:
|
||||
fallthrough
|
||||
default:
|
||||
titleType = "other"
|
||||
out := &bytes.Buffer{}
|
||||
|
||||
var category *MetaCategory
|
||||
if video.Category != nil {
|
||||
category = &MetaCategory{
|
||||
Name: video.Category.Name,
|
||||
Type: videoCategoryTypeStrings[video.Category.Type],
|
||||
Url: video.Category.Url,
|
||||
}
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
descriptionTemplate.Execute(out, Metadata{
|
||||
err := descriptionTemplate.Execute(out, Metadata{
|
||||
Title: video.Title,
|
||||
Date: strings.ToLower(video.Date.Format("02 Jan 2006")),
|
||||
Title: &MetaTitle{
|
||||
Name: video.Title.Name,
|
||||
Type: titleType,
|
||||
Url: video.Title.Url,
|
||||
},
|
||||
Category: category,
|
||||
Part: video.Part,
|
||||
})
|
||||
|
||||
return out.String(), nil
|
||||
return strings.TrimSpace(out.String()), err
|
||||
}
|
||||
|
||||
func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtube.Video, error) {
|
||||
|
|
@ -182,12 +190,11 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
|
|||
|
||||
videoService := youtube.NewVideosService(service)
|
||||
|
||||
var categoryId string
|
||||
switch video.Title.Type {
|
||||
case TITLE_GAME:
|
||||
categoryId = CATEGORY_GAMING
|
||||
default:
|
||||
categoryId = CATEGORY_ENTERTAINMENT
|
||||
categoryId := YT_CATEGORY_ENTERTAINMENT
|
||||
if video.Category != nil {
|
||||
if cid, ok := videoYtCategory[video.Category.Type]; ok {
|
||||
categoryId = cid
|
||||
}
|
||||
}
|
||||
|
||||
call := videoService.Insert([]string{
|
||||
|
|
@ -196,7 +203,7 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
|
|||
Snippet: &youtube.VideoSnippet{
|
||||
Title: title,
|
||||
Description: description,
|
||||
Tags: append(DEFAULT_TAGS, video.Tags...),
|
||||
Tags: append(DefaultTags, video.Tags...),
|
||||
CategoryId: categoryId, // gaming
|
||||
},
|
||||
Status: &youtube.VideoStatus{
|
||||
|
|
@ -213,6 +220,12 @@ func UploadVideo(ctx context.Context, token *oauth2.Token, video *Video) (*youtu
|
|||
|
||||
log.Println("Uploading video...")
|
||||
|
||||
call.ProgressUpdater(func(current, total int64) {
|
||||
// for some reason, this only returns 0.
|
||||
// instead, we pull the file size from the ffmpeg output directly.
|
||||
if total == 0 { total = video.SizeBytes }
|
||||
fmt.Printf("Uploading... (%.2f%%)\n", float64(current) / float64(total))
|
||||
})
|
||||
ytVideo, err := call.Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to upload video: %v\n", err)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue