Browse Source

Removement, flags, settings etc...

main
Unbewohnte 4 years ago committed by GitHub
parent
commit
728beb991e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      OBM.go
  2. 12
      README.md
  3. 5
      flags.go
  4. 116
      manager/beatmap.go
  5. 43
      manager/parse.go
  6. 31
      manager/remove.go
  7. 36
      manager/replace.go
  8. 52
      manager/retrieve.go
  9. 20
      manager/search.go
  10. 5
      settings/structure.go
  11. 2
      util/background.go
  12. 8
      util/checks.go
  13. 2
      util/copy.go
  14. 11
      worker.go

14
OBM.go

@ -24,6 +24,7 @@ type job struct {
beatmap manager.Beatmap
replacementImagePath string
retrievementPath string
remove bool
}
func init() {
@ -41,6 +42,12 @@ func init() {
// parse for `-beatmap` argument
flag.Parse()
// if `-showOrder` is checked - show the message
if *showOrder == true {
fmt.Print(orderMessage)
os.Exit(0)
}
return
}
@ -68,7 +75,7 @@ func main() {
}
logger.LogInfo(fmt.Sprintf("Found %d beatmaps", len(beatmaps)))
// If `cmdlnBeatmap` is specified - do the magic only for found beatmaps
// If `-beatmap` flag is specified - do the magic only on found beatmaps
if *cmdlnBeatmap != "" {
logger.LogInfo(fmt.Sprintf("Trying to locate \"%s\"...", *cmdlnBeatmap))
found, n := manager.Search(beatmaps, *cmdlnBeatmap)
@ -89,6 +96,7 @@ func main() {
beatmap: beatmap,
replacementImagePath: SETTINGS.BackgroundReplacement.ReplacementImagePath,
retrievementPath: SETTINGS.BackgroundRetrievement.RetrievementPath,
remove: SETTINGS.BackgroundRemovement.Enabled,
}
}
close(jobs)
@ -110,7 +118,7 @@ func main() {
}
total := successful + failed
logger.LogInfo(fmt.Sprintf("DONE in %v. %d operations successful (%d%%/100%%); %d failed (%d%%/100%%)",
time.Since(startingTime), successful, successful/total*100, failed, failed/total*100))
logger.LogInfo(fmt.Sprintf("DONE in %v. %d operations successful (%.2f%%/100%%); %d failed (%.2f%%/100%%)",
time.Since(startingTime), successful, float32(successful)/float32(total)*100, failed, float32(failed)/float32(total)*100))
}

12
README.md

@ -36,10 +36,12 @@ To run - `./OBM` in terminal (on Unix) || `OBM` in command line (on Windows) (a
### Flags (starting from version 1.3.4)
Right now there is one argument that you can specify before running the program - "beatmap".
This flag will tell the program to do its work **ONLY** on beatmaps with specified name; others will be ignored.
The names of beatmaps in Osu! consist an id, author of the soundtrack and the name of the soundtrack, so you can
specify any name in the flag that will contain one of those parts.
Right now there is 2 arguments that you can specify before running the program - "beatmap" and "showOrder".
"-beatmap" flag takes a string; it will tell the program to do its work **ONLY** on beatmaps with specified name; others will be ignored.
The names of beatmaps in Osu! consist an id, artist and the name of the soundtrack, so you can
specify any name in the flag that will contain one of those parts.
"-showOrder" flag takes a boolean; if set to **true** - it will print an order in which the workers perform operations over each beatmap. Right now it`s just a helper flag.
#### Examples
1. `./OBM -beatmap=""` - the same as just `./OBM`. It will affect **all** of your beatmaps
@ -50,6 +52,8 @@ specify any name in the flag that will contain one of those parts.
The search is case-insensitive, so for example `./OBM -beatmap="Road of Resistance"` and `./OBM -beatmap="ROAD of rEsIsTaNcE"` will get you the same results
6. `./OBM -showOrder=true` - will print the order and exit
7. `./OBM -showOrder=true -beatmap="something here"` - will print the order and exit, just like in the previous one
---
## License

5
flags.go

@ -4,8 +4,13 @@ import (
"flag"
)
var (
orderMessage string = "Order: Replace -> Retrieve -> Remove\n"
)
var (
cmdlnBeatmap = flag.String("beatmap", "", `Specifies a certain beatmap.
If set to non "" - the program will search for given name and perform the magic
provided in settings if successful`)
showOrder = flag.Bool("showOrder", false, "Prints an order in which functions are performed on a beatmap")
)

116
manager/beatmap.go

@ -5,9 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
)
@ -89,117 +87,3 @@ func GetBeatmaps(baseOsuDir string) ([]Beatmap, error) {
return beatmaps, nil
}
// 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(replacementImgPath string) (successful, failed uint) {
// 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(replacementImgPath, 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 uint) {
// 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
}
// Search tries to locate instances of beatmaps with the provided name (or part of the name);
// returns a slice of found beatmaps and a number of searched beatmaps
func Search(beatmaps []Beatmap, name string) ([]Beatmap, uint64) {
var instances []Beatmap
var searched uint64 = 0
// to make a search case-insensitive
name = strings.ToLower(name)
for _, beatmap := range beatmaps {
if strings.Contains(strings.ToLower(beatmap.Name), name) {
instances = append(instances, beatmap)
}
searched++
}
return instances, searched
}

43
manager/parse.go

@ -0,0 +1,43 @@
package manager
import (
"errors"
"os"
"path/filepath"
"strings"
"github.com/Unbewohnte/OBM/util"
)
// 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(diff string) (string, error) {
beatmapBytes, err := os.ReadFile(filepath.Join(BEATMAP.Path, diff))
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
}

31
manager/remove.go

@ -0,0 +1,31 @@
package manager
import (
"fmt"
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
)
// parses each difficulty for background info, removes found backgrounds
func (BEATMAP *Beatmap) RemoveBackgrounds() (successful, failed uint) {
// 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 getting background filename: %s", diff, err))
failed++
continue
}
// remove background
err = os.Remove(filepath.Join(BEATMAP.Path, background))
if err != nil {
// background file does not exist (success ???)
successful++
continue
}
successful++
}
return successful, failed
}

36
manager/replace.go

@ -0,0 +1,36 @@
package manager
import (
"fmt"
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
)
// 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(replacementImgPath string) (successful, failed uint) {
// 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 getting background filename: %s", diff, err))
failed++
continue
}
// remove old bg (if there is no background file - no need to worry)
os.Remove(filepath.Join(BEATMAP.Path, background))
// copy given picture, thus replacing background
err = util.CopyFile(replacementImgPath, 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
}

52
manager/retrieve.go

@ -0,0 +1,52 @@
package manager
import (
"fmt"
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
)
// 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 uint) {
// 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 getting background filename: %s", diff, err))
failed++
continue
}
// check if the background does exist
exists := util.DoesExist(filepath.Join(BEATMAP.Path, background))
if !exists {
// if not - we cannot copy it, so moving to the next diff
logger.LogWarning(fmt.Sprintf("BEATMAP: %s: Background does not exist", diff))
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
}

20
manager/search.go

@ -0,0 +1,20 @@
package manager
import "strings"
// Search tries to locate instances of beatmaps with the provided name (or part of the name);
// returns a slice of found beatmaps and a number of searched beatmaps
func Search(beatmaps []Beatmap, name string) ([]Beatmap, uint64) {
var instances []Beatmap
var searched uint64 = 0
// to make the search case-insensitive
name = strings.ToLower(name)
for _, beatmap := range beatmaps {
if strings.Contains(strings.ToLower(beatmap.Name), name) {
instances = append(instances, beatmap)
}
searched++
}
return instances, searched
}

5
settings/structure.go

@ -14,6 +14,10 @@ type backgroundRetrievement struct {
RetrievementPath string `json:"retrievementPath"`
}
type backgroundRemovement struct {
Enabled bool `json:"enabled"`
}
type backgroundCreatement struct {
Enabled bool `json:"enabled"`
Width uint `json:"width"`
@ -25,6 +29,7 @@ type Settings struct {
OsuDir string `json:"pathToOsu"`
BackgroundReplacement backgroundReplacement `json:"backgroundReplacement"`
BackgroundRetrievement backgroundRetrievement `json:"backgroundRetrievement"`
BackgroundRemovement backgroundRemovement `json:"backgroundRemovement"`
CreateBlackBGImage backgroundCreatement `json:"blackBackgroundCreatement"`
Workers int `json:"workers"`
}

2
util/background.go

@ -9,7 +9,7 @@ import (
"os"
)
// creates a complete black image file
// creates a complete black image file in current working directory
func CreateBlackBG(width, height uint) error {
bgfile, err := os.Create("blackBG.png")
if err != nil {

8
util/checks.go

@ -44,3 +44,11 @@ func IsImage(filename string) bool {
}
return false
}
func DoesExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
return false
}
return true
}

2
util/copy.go

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

11
worker.go

@ -10,16 +10,23 @@ func worker(jobs <-chan job, results chan result, WG *sync.WaitGroup) {
for job := range jobs {
var successful, failed uint = 0, 0
// the order is: Replace->Retrieve->Remove (if all 3 options are enabled)
if job.replacementImagePath != "" {
s, f := job.beatmap.ReplaceBackgrounds(job.replacementImagePath)
successful += s
failed += f
}
if job.retrievementPath != "" {
s, f := job.beatmap.RetrieveBackgrounds(job.retrievementPath)
successful += s
failed += f
}
if job.replacementImagePath != "" {
s, f := job.beatmap.ReplaceBackgrounds(job.replacementImagePath)
if job.remove == true {
s, f := job.beatmap.RemoveBackgrounds()
successful += s
failed += f
}
results <- result{
beatmapName: job.beatmap.Name,
numberOfDiffs: uint(len(job.beatmap.Diffs)),

Loading…
Cancel
Save