Browse Source

Redid the layout; improved code readability

main 1.3.2
Unbewohnte 3 years ago committed by GitHub
parent
commit
5d8af5a146
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      OBM.go
  2. 116
      manager/beatmap.go
  3. 82
      manager/paths.go
  4. 8
      settings/settings.go
  5. 6
      util/copy.go
  6. 12
      worker.go

30
OBM.go

@ -12,21 +12,19 @@ import (
"github.com/Unbewohnte/OBM/util" "github.com/Unbewohnte/OBM/util"
) )
var ( type result struct {
WG sync.WaitGroup beatmapName string
) numberOfDiffs uint
successful uint64
failed uint64
}
type job struct { type job struct {
beatmapFolderPath string beatmap manager.Beatmap
replacementImagePath string replacementImagePath string
retrievementPath string retrievementPath string
} }
type result struct {
successful uint64
failed uint64
}
func init() { func init() {
exists, err := settings.DoesExist() exists, err := settings.DoesExist()
if err != nil { if err != nil {
@ -44,6 +42,8 @@ func init() {
} }
func main() { func main() {
var WG sync.WaitGroup
startingTime := time.Now() startingTime := time.Now()
SETTINGS := settings.Get() SETTINGS := settings.Get()
@ -58,23 +58,24 @@ func main() {
} }
} }
beatmaps, err := manager.GetBeatmapFolderPaths(SETTINGS.OsuDir) beatmaps, err := manager.GetBeatmaps(SETTINGS.OsuDir)
if err != nil { if err != nil {
logger.LogError(true, "Error getting beatmap folders: ", err) logger.LogError(true, "Error getting beatmaps: ", err)
} }
logger.LogInfo(fmt.Sprintf("Found %d beatmap folders", len(beatmaps))) logger.LogInfo(fmt.Sprintf("Found %d beatmaps", len(beatmaps)))
// creating jobs for workers // creating jobs for workers
jobs := make(chan job, len(beatmaps)) jobs := make(chan job, len(beatmaps))
for _, beatmap := range beatmaps { for _, beatmap := range beatmaps {
jobs <- job{ jobs <- job{
beatmapFolderPath: beatmap, beatmap: beatmap,
replacementImagePath: SETTINGS.BackgroundReplacement.ReplacementImagePath, replacementImagePath: SETTINGS.BackgroundReplacement.ReplacementImagePath,
retrievementPath: SETTINGS.BackgroundRetrievement.RetrievementPath, retrievementPath: SETTINGS.BackgroundRetrievement.RetrievementPath,
} }
} }
close(jobs) close(jobs)
// perform the magic
results := make(chan result, len(jobs)) results := make(chan result, len(jobs))
workerPool(jobs, results, SETTINGS.Workers, &WG) workerPool(jobs, results, SETTINGS.Workers, &WG)
WG.Wait() WG.Wait()
@ -85,6 +86,9 @@ func main() {
for result := range results { for result := range results {
successful += result.successful successful += result.successful
failed += result.failed failed += result.failed
logger.LogInfo(fmt.Sprintf("Beatmap: %s; Number of diffs: %d;\n Successful: %d; Failed: %d",
result.beatmapName, result.numberOfDiffs, result.successful, result.failed))
} }
total := successful + failed total := successful + failed

116
manager/beatmap.go

@ -0,0 +1,116 @@
package manager
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
)
// the main beatmap struct, contains necessary data for functions
type Beatmap struct {
Name string
Path string
Diffs []string
}
// parses given .osu file and returns the filename of its background
// NOTE: Osu! beatmap (as whole) can have multiple backgrounds for each .osu file
// the perfect example : https://osu.ppy.sh/beatmapsets/43701#osu/137122
// this is why this functions asks for a certain difficulty (.osu filename) to be sure
// to return the correct background name
func (BEATMAP *Beatmap) GetBackgroundName(mapName string) (string, error) {
beatmapBytes, err := os.ReadFile(filepath.Join(BEATMAP.Path, mapName))
if err != nil {
return "", err
}
beatmapContents := string(beatmapBytes)
// get index of "[Events]" (this is where BG filename is stored)
eventsIndex := strings.Index(beatmapContents, "[Events]")
if eventsIndex == -1 {
return "", errors.New("Could not retrieve index of \"[Events]\"")
}
// get index of [TimingPoints] (this tag is right after the previous "[Events]" tag,
// so we can grab the whole "[Events]" tag contents)
timingPointsIndex := strings.Index(beatmapContents, "[TimingPoints]")
if timingPointsIndex == -1 {
return "", errors.New("Could not retrieve index of \"[TimingPoints]\"")
}
contentBetween := strings.Split(beatmapContents[eventsIndex:timingPointsIndex], ",")
for _, chunk := range contentBetween {
if util.IsImage(chunk) {
return strings.Split(chunk, "\"")[1], nil
}
}
return "", nil
}
// parses each beatmap`s .osu file for background info;
// removes original background and replaces it with copied version of given image
func (BEATMAP *Beatmap) ReplaceBackgrounds(replacementPicPath string) (successful, failed uint64) {
// looping through each .osu file of a beatmap
for _, diff := range BEATMAP.Diffs {
background, err := BEATMAP.GetBackgroundName(diff)
if err != nil || background == "" {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Error gettings background filename: %s", diff, err))
failed++
continue
}
// remove old bg
err = os.Remove(filepath.Join(BEATMAP.Path, background))
if err != nil {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Could not remove the old bg: %s", diff, err))
failed++
continue
}
// copy given picture, thus replacing background
err = util.CopyFile(replacementPicPath, filepath.Join(BEATMAP.Path, background))
if err != nil {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Could not copy: %s", diff, err))
failed++
continue
}
successful++
}
return successful, failed
}
// retrieves backgrounds from given beatmap folder (same as in `ReplaceBackgrounds`) and copies them to the retrievement path
func (BEATMAP *Beatmap) RetrieveBackgrounds(retrievementPath string) (successful, failed uint64) {
// looping through each .osu file of a beatmap
for _, diff := range BEATMAP.Diffs {
background, err := BEATMAP.GetBackgroundName(diff)
if err != nil || background == "" {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Error gettings background filename: %s", diff, err))
failed++
continue
}
// creating directory that represents current beatmap
dstPath := filepath.Join(retrievementPath, BEATMAP.Name)
err = os.MkdirAll(dstPath, os.ModePerm)
if err != nil {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Error creating a directory: %s", diff, err))
failed++
continue
}
// copy background to the `retrievementPath`
err = util.CopyFile(filepath.Join(BEATMAP.Path, background), filepath.Join(dstPath, background))
if err != nil {
logger.LogError(false, fmt.Sprintf("BEATMAP: %s: Could not copy: %s", diff, err))
failed++
continue
}
successful++
}
return successful, failed
}

82
manager/paths.go

@ -0,0 +1,82 @@
package manager
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/util"
)
// filepath.Joins the main osu directory with its songs folder
func getSongsDir(baseOsuDir string) (string, error) {
songsDir := filepath.Join(baseOsuDir, "Songs")
stat, err := os.Stat(songsDir)
if err != nil {
return "", errors.New(fmt.Sprintf("Could not process the given path : %s", err))
}
if !stat.IsDir() {
return "", errors.New("Given Osu! directory is not a directory !")
}
return songsDir, nil
}
// checks for .osu files in given path and returns all found instances
func getDiffs(path string) ([]string, error) {
files, err := os.ReadDir(path)
if err != nil {
return nil, errors.New(fmt.Sprintf("Could not read a directory : %s", err))
}
var diffs []string
for _, file := range files {
filename := file.Name()
if util.IsBeatmap(filename) {
diffs = append(diffs, filename)
}
}
return diffs, nil
}
// constructs a `Beatmap` struct and returns it
func newBeatmap(name, path string, diffs []string) Beatmap {
return Beatmap{
Name: name,
Path: path,
Diffs: diffs,
}
}
// returns an array of beatmaps from given base Osu! directory
func GetBeatmaps(baseOsuDir string) ([]Beatmap, error) {
songsDir, err := getSongsDir(baseOsuDir)
if err != nil {
return nil, err
}
contents, err := os.ReadDir(songsDir)
if err != nil {
return nil, errors.New(fmt.Sprintf("Could not read a directory : %s", err))
}
var beatmaps []Beatmap
// looping through all folders in yourOsuDir/Songs/ directory
for _, file := range contents {
if file.IsDir() {
// retrieving all necessary data for creating a new instance of a beatmap
beatmapName := file.Name()
pathToBeatmap := filepath.Join(songsDir, beatmapName)
diffs, err := getDiffs(pathToBeatmap)
if err != nil {
continue
}
newBeatmap := newBeatmap(beatmapName, pathToBeatmap, diffs)
beatmaps = append(beatmaps, newBeatmap)
}
}
return beatmaps, nil
}

8
settings/settings.go

@ -69,7 +69,7 @@ func Create() error {
return nil return nil
} }
// unmarshalls settings.json into struct // unmarshalls settings.json into struct and processes the edge-cases
func Get() Settings { func Get() Settings {
settingsFileContents, err := os.ReadFile(settingsFilename) settingsFileContents, err := os.ReadFile(settingsFilename)
if err != nil { if err != nil {
@ -82,6 +82,12 @@ func Get() Settings {
logger.LogError(true, fmt.Sprintf("Could not unmarshal json file : %s", err)) logger.LogError(true, fmt.Sprintf("Could not unmarshal json file : %s", err))
} }
// if all features are disabled
if !settings.BackgroundReplacement.Enabled && !settings.BackgroundRetrievement.Enabled {
logger.LogInfo("No features enabled. Exiting...")
os.Exit(0)
}
// checking for edge cases or mistakes made in the settings file, // checking for edge cases or mistakes made in the settings file,
// enabled and disabled fields // enabled and disabled fields
if settings.BackgroundReplacement.Enabled { if settings.BackgroundReplacement.Enabled {

6
util/copy.go

@ -8,14 +8,14 @@ import (
) )
// opens given files, copies one into another // opens given files, copies one into another
func CopyFile(src, dst string) error { func CopyFile(srcPath, dstPath string) error {
srcFile, err := os.Open(src) srcFile, err := os.Open(srcPath)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Could not open src file : %s", err)) return errors.New(fmt.Sprintf("Could not open src file : %s", err))
} }
defer srcFile.Close() defer srcFile.Close()
dstFile, err := os.OpenFile(dst, os.O_WRONLY, os.ModePerm) dstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Could not open dst file : %s", err)) return errors.New(fmt.Sprintf("Could not open dst file : %s", err))
} }

12
worker.go

@ -2,8 +2,6 @@ package main
import ( import (
"sync" "sync"
"github.com/Unbewohnte/OBM/manager"
) )
// a basic implementation of a concurrent worker // a basic implementation of a concurrent worker
@ -13,18 +11,20 @@ func worker(jobs <-chan job, results chan result, WG *sync.WaitGroup) {
var successful, failed uint64 = 0, 0 var successful, failed uint64 = 0, 0
if job.retrievementPath != "" { if job.retrievementPath != "" {
s, f := manager.RetrieveBackgrounds(job.beatmapFolderPath, job.retrievementPath) s, f := job.beatmap.RetrieveBackgrounds(job.retrievementPath)
successful += s successful += s
failed += f failed += f
} }
if job.replacementImagePath != "" { if job.replacementImagePath != "" {
s, f := manager.ReplaceBackgrounds(job.beatmapFolderPath, job.replacementImagePath) s, f := job.beatmap.ReplaceBackgrounds(job.replacementImagePath)
successful += s successful += s
failed += f failed += f
} }
results <- result{ results <- result{
successful: successful, beatmapName: job.beatmap.Name,
failed: failed, numberOfDiffs: uint(len(job.beatmap.Diffs)),
successful: successful,
failed: failed,
} }
} }

Loading…
Cancel
Save