-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Episode path format #108
base: master
Are you sure you want to change the base?
Episode path format #108
Changes from all commits
fef8fef
f5826e3
f0c571d
d4f2489
2d25bb4
e532b5a
f472487
9fe8fee
7e8071e
367d33d
8d6540a
2258e17
3f03e52
0a4d680
c8f6e73
72f2bba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,34 +9,71 @@ import ( | |
) | ||
|
||
type localMigration struct { | ||
Name string | ||
Query string | ||
Name string | ||
Condition []string | ||
Query []string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a Condition string array and turned Query in to a string array to support skipping a migration if it's not necessary, and to support multiple Condition and Query statements. |
||
} | ||
|
||
var migrations = []localMigration{ | ||
{ | ||
Name: "2020_11_03_04_42_SetDefaultDownloadStatus", | ||
Query: "update podcast_items set download_status=2 where download_path!='' and download_status=0", | ||
Name: "2020_11_03_04_42_SetDefaultDownloadStatus", | ||
Condition: []string{}, | ||
Query: []string{ | ||
"update podcast_items set download_status=2 where download_path!='' and download_status=0", | ||
}, | ||
}, | ||
{ | ||
Name: "2021_06_01_00_00_ConvertFileNameFormat", | ||
Condition: []string{ | ||
"SELECT COUNT(*) > 0 FROM (SELECT name FROM pragma_table_info('settings') where name is 'append_date_to_file_name');", | ||
"SELECT COUNT(*) > 0 FROM (SELECT name FROM pragma_table_info('settings') where name is 'append_episode_number_to_file_name');", | ||
}, | ||
Query: []string{ | ||
"UPDATE settings SET file_name_format = CASE WHEN append_date_to_file_name AND append_episode_number_to_file_name THEN '%EpisodeNumber%-%EpisodeDate%-%EpisodeTitle%' WHEN append_date_to_file_name THEN '%EpisodeDate%-%EpisodeTitle%' WHEN append_episode_number_to_file_name THEN '%EpisodeNumber%-%EpisodeTitle%' ELSE '%EpisodeTitle%' END", | ||
// sqlite3 v3.35.0 supports DROP COLUMN | ||
// "ALTER TABLE settings DROP COLUMN append_episode_number_to_file_name", | ||
// "ALTER TABLE settings DROP COLUMN append_date_to_file_name", | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ConvertFileNameFormat needs conditions to ensure it doesn't try to convert the old "append" fields to the new "file name format" if those fields don't exist in the database. Ideally multiple Query statements would be used to drop the old "append" columns, but that's not supported until sqlite3 v3.35. The alternative is recreating the table, but that seems excessive. |
||
}, | ||
} | ||
|
||
func RunMigrations() { | ||
for _, mig := range migrations { | ||
ExecuteAndSaveMigration(mig.Name, mig.Query) | ||
fmt.Println(mig.Name) | ||
ExecuteAndSaveMigration(mig.Name, mig.Condition, mig.Query) | ||
} | ||
} | ||
func ExecuteAndSaveMigration(name string, query string) error { | ||
func ExecuteAndSaveMigration(name string, condition []string, query []string) error { | ||
var migration Migration | ||
result := DB.Where("name=?", name).First(&migration) | ||
if errors.Is(result.Error, gorm.ErrRecordNotFound) { | ||
fmt.Println(query) | ||
result = DB.Debug().Exec(query) | ||
if result.Error == nil { | ||
DB.Save(&Migration{ | ||
Date: time.Now(), | ||
Name: name, | ||
}) | ||
var rawResult string | ||
var shouldMigrate = true | ||
for _, q := range condition { | ||
fmt.Println("cond: " + q) | ||
result = DB.Debug().Raw(q).Scan(&rawResult) | ||
if result.Error != nil { | ||
fmt.Println(result.Error) | ||
return result.Error | ||
} | ||
shouldMigrate = shouldMigrate && rawResult == "1" | ||
} | ||
if shouldMigrate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only execute the migration if the Conditions succeeded. |
||
for _, q := range query { | ||
fmt.Println("exec: " + q) | ||
result = DB.Debug().Exec(q) | ||
if result.Error != nil { | ||
fmt.Println(result.Error) | ||
return result.Error | ||
} | ||
} | ||
} else { | ||
fmt.Println("migration not required") | ||
} | ||
DB.Save(&Migration{ | ||
Date: time.Now(), | ||
Name: name, | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still save the migration to the Migration table as long as there wasn't an actual error. |
||
return result.Error | ||
} | ||
return nil | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ import ( | |
stringy "github.com/gobeam/stringy" | ||
) | ||
|
||
func Download(link string, episodeTitle string, podcastName string, prefix string) (string, error) { | ||
func Download(link string, episodeTitle string, podcastName string, episodePathName string) (string, error) { | ||
if link == "" { | ||
return "", errors.New("Download path empty") | ||
} | ||
|
@@ -39,12 +39,13 @@ func Download(link string, episodeTitle string, podcastName string, prefix strin | |
return "", err | ||
} | ||
|
||
fileName := getFileName(link, episodeTitle, ".mp3") | ||
if prefix != "" { | ||
fileName = fmt.Sprintf("%s-%s", prefix, fileName) | ||
} | ||
folder := createDataFolderIfNotExists(podcastName) | ||
finalPath := path.Join(folder, fileName) | ||
fileExtension := path.Ext(getFileName(link, episodeTitle, ".mp3")) | ||
finalPath := path.Join( | ||
os.Getenv("DATA"), | ||
cleanFileName(podcastName), | ||
fmt.Sprintf("%s%s", episodePathName, fileExtension)) | ||
dir, _ := path.Split(finalPath) | ||
createPreSanitizedPath(dir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly use the episodePathName as it is passed in to Download() and don't sanitize the path components again as they were already sanitized as they were created. |
||
|
||
if _, err := os.Stat(finalPath); !os.IsNotExist(err) { | ||
changeOwnership(finalPath) | ||
|
@@ -358,17 +359,21 @@ func getRequest(url string) (*http.Request, error) { | |
return req, nil | ||
} | ||
|
||
func createFolder(folder string, parent string) string { | ||
folder = cleanFileName(folder) | ||
//str := stringy.New(folder) | ||
folderPath := path.Join(parent, folder) | ||
func createPreSanitizedPath(folderPath string) string { | ||
if _, err := os.Stat(folderPath); os.IsNotExist(err) { | ||
os.MkdirAll(folderPath, 0777) | ||
changeOwnership(folderPath) | ||
} | ||
return folderPath | ||
} | ||
|
||
func createFolder(folder string, parent string) string { | ||
folder = cleanFileName(folder) | ||
//str := stringy.New(folder) | ||
folderPath := path.Join(parent, folder) | ||
return createPreSanitizedPath(folderPath) | ||
} | ||
|
||
func createDataFolderIfNotExists(folder string) string { | ||
dataPath := os.Getenv("DATA") | ||
return createFolder(folder, dataPath) | ||
|
@@ -395,7 +400,6 @@ func getFileName(link string, title string, defaultExtension string) string { | |
//str := stringy.New(title) | ||
str := stringy.New(cleanFileName(title)) | ||
return str.KebabCase().Get() + ext | ||
|
||
} | ||
|
||
func cleanFileName(original string) string { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the text field where the format is entered. Ideally this would be less direct and populated by dragging tokens in to the field or by selection from a menu, but it's a start at least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a bit of Javascript to help populate the format field when the format keys are clicked.