Compare commits

...

9 Commits
1.3.5 ... main

Author SHA1 Message Date
Kasianov Nikolai Alekseevich 11d493bb14 Removed accidental logs file 2 years ago
Kasianov Nikolai Alekseevich 76b489b424 Tidied a bit, changed go.mod 2 years ago
Gitea 09c3956cb9 No more github 2 years ago
Unbewohnte 88f50f8724 Little fix 3 years ago
Unbewohnte e76f34e0fb
Important note 3 years ago
Unbewohnte cbf2354d1e
Add files via upload 3 years ago
Unbewohnte ed33ca27c3
Some minor documentaion and notes added 3 years ago
Unbewohnte f9eca425b6
Typo 3 years ago
Unbewohnte b91af019b4
Title 3 years ago
  1. 3
      .gitignore
  2. 2
      Makefile
  3. 9
      README.md
  4. 16
      flags.go
  5. 3
      go.mod
  6. 66
      src/OBM.go
  7. 3
      src/go.mod
  8. 0
      src/logger/logger.go
  9. 11
      src/manager/beatmap.go
  10. 10
      src/manager/parse.go
  11. 2
      src/manager/remove.go
  12. 4
      src/manager/replace.go
  13. 4
      src/manager/retrieve.go
  14. 0
      src/manager/search.go
  15. 15
      src/settings/settings.go
  16. 0
      src/settings/structure.go
  17. 0
      src/util/background.go
  18. 2
      src/util/checks.go
  19. 0
      src/util/copy.go
  20. 51
      worker.go

3
.gitignore vendored

@ -0,0 +1,3 @@
settings.json
OBM
logs

2
Makefile

@ -0,0 +1,2 @@
all:
cd src && go build && mv OBM ..

9
README.md

@ -1,6 +1,7 @@
# OBM (Osu!-Background-Manager)
## This utility will help you with replacement and retrievement of Osu!\`s beatmaps\` backgrounds
## This utility will help you with replacement, retrievement and removement of Osu!\`s beatmaps\` backgrounds
## NOTE: does NOT work with Osu!Lazer (Lazer has a different handling for beatmaps)
**Use at your own risk !**
There is no way to return removed original backgrounds unless you delete all beatmaps and reimport newly downloaded versions of them again.
@ -23,7 +24,7 @@ There is no way to return removed original backgrounds unless you delete all bea
---
## Usage
To run - `./OBM` in terminal (on Unix) || `OBM` in command line (on Windows) (a simple double-click on exe will certainly work as well)
To run - `./OBM` in terminal (on Unix) || `OBM.exe` in command line (on Windows) (a simple double-click on exe will certainly work as well)
### First run
1. The program will generate a settings.json file if it is not already in the directory when you run it
@ -35,8 +36,8 @@ To run - `./OBM` in terminal (on Unix) || `OBM` in command line (on Windows) (a
1. Start the utility again. If it has found the settings file - it will perform the magic according to provided rules
### Flags (starting from version 1.3.4)
Right now there is 2 arguments that you can specify before running the program - "beatmap" and "showOrder".
### Flags
Right now there are 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.

16
flags.go

@ -1,16 +0,0 @@
package main
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")
)

3
go.mod

@ -1,3 +0,0 @@
module github.com/Unbewohnte/OBM
go 1.16

66
OBM.go → src/OBM.go

@ -7,12 +7,68 @@ import (
"sync"
"time"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/manager"
"github.com/Unbewohnte/OBM/settings"
"github.com/Unbewohnte/OBM/util"
"unbewohnte/OBM/logger"
"unbewohnte/OBM/manager"
"unbewohnte/OBM/settings"
"unbewohnte/OBM/util"
)
const 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")
)
// a basic implementation of a concurrent worker
func worker(jobs <-chan job, results chan result, WG *sync.WaitGroup) {
defer WG.Done()
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.remove == true {
s, f := job.beatmap.RemoveBackgrounds()
successful += s
failed += f
}
results <- result{
beatmapName: job.beatmap.Name,
numberOfDiffs: uint(len(job.beatmap.Diffs)),
successful: successful,
failed: failed,
}
}
}
// the `starter` that `glues` workers and jobs together
func workerPool(jobs chan job, results chan result, numOfWorkers int, WG *sync.WaitGroup) {
// check if there are less jobs than workers
if numOfWorkers > len(jobs) {
numOfWorkers = len(jobs)
}
// replacing backgrounds for each beatmap concurrently
for i := 0; i < numOfWorkers; i++ {
WG.Add(1)
go worker(jobs, results, WG)
}
}
type result struct {
beatmapName string
numberOfDiffs uint
@ -43,7 +99,7 @@ func init() {
// parse for `-beatmap` argument
flag.Parse()
// if `-showOrder` is checked - show the message
// if `-showOrder` is checked - show the message and exit
if *showOrder == true {
fmt.Print(orderMessage)
os.Exit(0)

3
src/go.mod

@ -0,0 +1,3 @@
module unbewohnte/OBM
go 1.16

0
logger/logger.go → src/logger/logger.go

11
manager/beatmap.go → src/manager/beatmap.go

@ -1,12 +1,11 @@
package manager
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/util"
"unbewohnte/OBM/util"
)
// the main beatmap struct, contains necessary data for functions
@ -22,10 +21,10 @@ func getSongsDir(baseOsuDir string) (string, error) {
stat, err := os.Stat(songsDir)
if err != nil {
return "", errors.New(fmt.Sprintf("Could not process the given path : %s", err))
return "", fmt.Errorf("could not process the given path : %s", err)
}
if !stat.IsDir() {
return "", errors.New("Given Osu! directory is not a directory !")
return "", fmt.Errorf("given Osu! directory is not a directory")
}
return songsDir, nil
@ -35,7 +34,7 @@ func getSongsDir(baseOsuDir string) (string, error) {
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))
return nil, fmt.Errorf("could not read a directory : %s", err)
}
var diffs []string
@ -65,7 +64,7 @@ func GetBeatmaps(baseOsuDir string) ([]Beatmap, error) {
}
contents, err := os.ReadDir(songsDir)
if err != nil {
return nil, errors.New(fmt.Sprintf("Could not read a directory : %s", err))
return nil, fmt.Errorf("could not read a directory : %s", err)
}
var beatmaps []Beatmap

10
manager/parse.go → src/manager/parse.go

@ -1,18 +1,18 @@
package manager
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Unbewohnte/OBM/util"
"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
// this is why this function 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))
@ -24,13 +24,13 @@ func (BEATMAP *Beatmap) GetBackgroundName(diff string) (string, error) {
// 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]\"")
return "", fmt.Errorf("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]\"")
return "", fmt.Errorf("could not retrieve index of \"[TimingPoints]\"")
}
contentBetween := strings.Split(beatmapContents[eventsIndex:timingPointsIndex], ",")

2
manager/remove.go → src/manager/remove.go

@ -5,7 +5,7 @@ import (
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
"unbewohnte/OBM/logger"
)
// parses each difficulty for background info, removes found backgrounds

4
manager/replace.go → src/manager/replace.go

@ -5,8 +5,8 @@ import (
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
"unbewohnte/OBM/logger"
"unbewohnte/OBM/util"
)
// parses each beatmap`s .osu file for background info;

4
manager/retrieve.go → src/manager/retrieve.go

@ -5,8 +5,8 @@ import (
"os"
"path/filepath"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
"unbewohnte/OBM/logger"
"unbewohnte/OBM/util"
)
// retrieves backgrounds from given beatmap folder (same as in `ReplaceBackgrounds`) and copies them to the retrievement path

0
manager/search.go → src/manager/search.go

15
settings/settings.go → src/settings/settings.go

@ -2,12 +2,11 @@ package settings
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/util"
"unbewohnte/OBM/logger"
"unbewohnte/OBM/util"
)
const (
@ -18,7 +17,7 @@ const (
func DoesExist() (bool, error) {
files, err := os.ReadDir(".")
if err != nil {
return false, errors.New(fmt.Sprintf("Unable to read current directory %s", err))
return false, fmt.Errorf("wasn`t able to read current directory %s", err)
}
for _, file := range files {
@ -42,8 +41,9 @@ func Create() error {
file, err := os.Create(settingsFilename)
if err != nil {
return errors.New(fmt.Sprintf("Unable to create settings file : %s", err))
return fmt.Errorf("could not create settings file : %s", err)
}
defer file.Close()
// marshaling default settings
settingsJson, err := json.MarshalIndent(Settings{
@ -67,11 +67,10 @@ func Create() error {
Workers: 100,
}, "", " ")
if err != nil {
return errors.New(fmt.Sprintf("Could not marshal settings into file : %s", err))
return fmt.Errorf("could not marshal settings into file : %s", err)
}
file.Write(settingsJson)
file.Close()
return nil
}
@ -90,7 +89,7 @@ func Get() Settings {
}
// if all features are disabled
if !settings.BackgroundReplacement.Enabled && !settings.BackgroundRetrievement.Enabled {
if !settings.BackgroundReplacement.Enabled && !settings.BackgroundRetrievement.Enabled && !settings.BackgroundRemovement.Enabled {
logger.LogInfo("No features enabled. Exiting...")
os.Exit(0)
}

0
settings/structure.go → src/settings/structure.go

0
util/background.go → src/util/background.go

2
util/checks.go → src/util/checks.go

@ -5,6 +5,7 @@ import (
"strings"
)
// checks if given path is a directory
func IsDir(path string) bool {
info, err := os.Stat(path)
if err != nil {
@ -45,6 +46,7 @@ func IsImage(filename string) bool {
return false
}
// checks if given directory/file does exist
func DoesExist(path string) bool {
_, err := os.Stat(path)
if err != nil {

0
util/copy.go → src/util/copy.go

51
worker.go

@ -1,51 +0,0 @@
package main
import (
"sync"
)
// a basic implementation of a concurrent worker
func worker(jobs <-chan job, results chan result, WG *sync.WaitGroup) {
defer WG.Done()
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.remove == true {
s, f := job.beatmap.RemoveBackgrounds()
successful += s
failed += f
}
results <- result{
beatmapName: job.beatmap.Name,
numberOfDiffs: uint(len(job.beatmap.Diffs)),
successful: successful,
failed: failed,
}
}
}
func workerPool(jobs chan job, results chan result, numOfWorkers int, WG *sync.WaitGroup) {
// check if there are less jobs than workers
if numOfWorkers > len(jobs) {
numOfWorkers = len(jobs)
}
// replacing backgrounds for each beatmap concurrently
for i := 0; i < numOfWorkers; i++ {
WG.Add(1)
go worker(jobs, results, WG)
}
}
Loading…
Cancel
Save