Browse Source

Added custom logger and made code a bit less messy

main
Unbewohnte 4 years ago committed by GitHub
parent
commit
8fe388cfd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 133
      OBM.go
  2. 6
      README.md
  3. 3
      go.mod
  4. 53
      logger/logger.go
  5. 53
      manager/helpers.go
  6. 113
      manager/manager.go
  7. 95
      settings/settings.go

133
OBM.go

@ -0,0 +1,133 @@
package main
import (
"errors"
"fmt"
"image"
"image/color"
"image/png"
"os"
"path/filepath"
"sync"
"time"
"github.com/Unbewohnte/OBM/logger"
"github.com/Unbewohnte/OBM/manager"
"github.com/Unbewohnte/OBM/settings"
)
var (
WG sync.WaitGroup
)
// creates a complete black image file
func createBlackBG(width, height int) error {
bgfile, err := os.Create("blackBG.png")
if err != nil {
return errors.New(fmt.Sprintf("Could not create black background file : %s", err))
}
image := image.NewRGBA(image.Rect(0, 0, width, height))
bounds := image.Bounds()
for y := 0; y < bounds.Max.Y; y++ {
for x := 0; x < bounds.Max.X; x++ {
image.Set(x, y, color.Black)
}
}
err = png.Encode(bgfile, image)
if err != nil {
return errors.New(fmt.Sprintf("Could not encode an image : %s", err))
}
err = bgfile.Close()
if err != nil {
return errors.New(fmt.Sprintf("Could not close the background file : %s", err))
}
return nil
}
// a basic implementation of a concurrent worker
func worker(paths <-chan string, replacementImage string, successful, failed *uint64, WG *sync.WaitGroup) {
defer WG.Done()
for songPath := range paths {
s, f := manager.ReplaceBackgrounds(songPath, replacementImage)
*successful += s
*failed += f
}
}
func init() {
exists, err := settings.CheckSettingsFile()
if err != nil {
logger.LogError(true, err)
}
if exists {
logger.LogInfo("Found settings file")
return
}
// settings file does not exist, so create it and exit
settings.CreateSettingsFile()
os.Exit(0)
}
func main() {
startingTime := time.Now().UTC()
settings := settings.GetSettings()
// process the given settings
if settings.CreateBlackBGImage {
err := createBlackBG(1920, 1080)
if err == nil {
logger.LogInfo("Successfully created black background")
} else {
logger.LogWarning(fmt.Sprintf("Could not create black background : %s; continuing to run...", err))
}
}
osuSongsDir, err := manager.GetSongsDir(settings.OsuDir)
if err != nil {
logger.LogError(true, err)
}
if settings.ReplacementImagePath == "" || settings.ReplacementImagePath == " " {
logger.LogError(true, "Image path not specified ! Specify `pathToimage` in settings file !")
}
// reading contents of `Songs` folder
osuSongsDirContents, err := os.ReadDir(osuSongsDir)
if err != nil {
logger.LogError(true, fmt.Sprintf("Error reading osu songs directory : %s", err.Error()))
}
// storing all paths to each beatmap
songPaths := make(chan string, len(osuSongsDirContents))
for _, songDir := range osuSongsDirContents {
if songDir.IsDir() {
songPaths <- filepath.Join(osuSongsDir, songDir.Name())
}
}
logger.LogInfo(fmt.Sprintf("Found %d song folders", len(songPaths)))
// check if there is less job than workers
if settings.Workers > len(songPaths) {
settings.Workers = len(songPaths)
}
// replacing backgrounds for each beatmap concurrently
var successful, failed uint64 = 0, 0
for i := 0; i < int(settings.Workers); i++ {
WG.Add(1)
go worker(songPaths, settings.ReplacementImagePath, &successful, &failed, &WG)
}
close(songPaths)
WG.Wait()
endTime := time.Now().UTC()
logger.LogInfo(fmt.Sprintf("\n\nDONE in %v . %d successful; %d failed", endTime.Sub(startingTime), successful, failed))
}

6
README.md

@ -10,15 +10,15 @@ There is no way to return removed original backgrounds unless you delete all bea
## Installation ## Installation
### From source ### From source
1. git clone [https://github.com/Unbewohnte/OBM.git](https://github.com/Unbewohnte/OBM.git) or download and unzip the archive 1. `git clone https://github.com/Unbewohnte/OBM.git` or download and unzip the archive
2. cd into the directory 2. cd into the directory
3. go build 3. `go build`
### From release ### From release
1. go to the [releases](https://github.com/Unbewohnte/OBM/releases) page 1. go to the [releases](https://github.com/Unbewohnte/OBM/releases) page
2. choose your OS and download the archive 2. choose your OS and download the archive
3. cd to the location of the downloaded version 3. cd to the location of the downloaded version
4. unzip (7z x **archive_name**) - for 7z archives 4. unzip (`7z x **archive_name**`) - for 7z archives
--- ---

3
go.mod

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

53
logger/logger.go

@ -0,0 +1,53 @@
package logger
import (
"log"
"os"
"path/filepath"
)
var (
infoLogger *log.Logger
warningLogger *log.Logger
errorLogger *log.Logger
)
// creates directory for logs and sets output to file
func createLogsfile() *os.File {
logsDir := filepath.Join(".", "logs")
err := os.MkdirAll(logsDir, os.ModePerm)
if err != nil {
panic(err)
}
logfile, err := os.Create(filepath.Join(logsDir, "logs.log"))
log.SetOutput(logfile)
return logfile
}
// creates new custom loggers
func setUpLoggers(logfile *os.File) {
infoLogger = log.New(logfile, "INFO: ", log.Ldate|log.Ltime)
warningLogger = log.New(logfile, "WARNING: ", log.Ldate|log.Ltime)
errorLogger = log.New(logfile, "ERROR: ", log.Ldate|log.Ltime)
}
func init() {
logfile := createLogsfile()
setUpLoggers(logfile)
}
func LogInfo(message ...interface{}) {
infoLogger.Println(message...)
}
func LogWarning(message ...interface{}) {
warningLogger.Println(message...)
}
func LogError(isFatal bool, message ...interface{}) {
if isFatal {
errorLogger.Fatal(message...)
}
errorLogger.Println(message...)
}

53
manager/helpers.go

@ -0,0 +1,53 @@
package manager
import (
"errors"
"fmt"
"io"
"os"
"strings"
)
// checks if given string contains ".osu" file extention
func isBeatmap(filename string) bool {
if len(filename) < 5 {
return false
}
if filename[len(filename)-4:] == ".osu" {
return true
}
return false
}
// checks if given string contains the image file extention
func isImage(filename string) bool {
var imageExtentions []string = []string{"jpeg", "jpg", "png", "JPEG", "JPG", "PNG"}
for _, extention := range imageExtentions {
if strings.Contains(filename, extention) {
return true
}
}
return false
}
// opens given files, copies one into another
func copyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return errors.New(fmt.Sprintf("Could not open src file : %s", err))
}
defer srcFile.Close()
dstFile, err := os.OpenFile(dst, os.O_WRONLY, os.ModePerm)
if err != nil {
return errors.New(fmt.Sprintf("Could not open dst file : %s", err))
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return errors.New(fmt.Sprintf("Could not copy file : %s", err))
}
return nil
}

113
manager/manager.go

@ -0,0 +1,113 @@
package manager
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Unbewohnte/OBM/logger"
)
// filepath.Joins the main osu directory with its songs folder
func GetSongsDir(osudir string) (string, error) {
songsDir := filepath.Join(osudir, "Songs")
stat, err := os.Stat(songsDir)
if err != nil {
return "", errors.New(fmt.Sprintf("Could not read the given path : %s", err))
}
if !stat.IsDir() {
return "", errors.New("Given Osu! directory is not a directory !")
}
return songsDir, nil
}
// parses given .osu file and returns the filename of its background
func GetBackgroundName(pathToOSUbeatmap string) (string, error) {
beatmapBytes, err := os.ReadFile(pathToOSUbeatmap)
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 isImage(chunk) {
return strings.Split(chunk, "\"")[1], nil
}
}
return "", nil
}
// reads contents of given dir; searches for .osu files; parses them for background info;
// removes original background and replaces it with copied version of given image
func ReplaceBackgrounds(beatmapFolder, replacementPicPath string) (successful, failed uint64) {
files, err := os.ReadDir(beatmapFolder)
if err != nil {
logger.LogError(false, fmt.Sprintf("Wrong path : %s", err))
}
for _, file := range files {
filename := file.Name()
if isBeatmap(filename) {
beatmap := filename
// getting BG filename
beatmapBackgroundFilename, err := GetBackgroundName(filepath.Join(beatmapFolder, beatmap))
if err != nil {
logger.LogWarning(fmt.Sprintf("BEATMAP: %s: Error getting background filename: %s", beatmap, err))
failed++
continue
}
if beatmapBackgroundFilename == "" {
logger.LogWarning(fmt.Sprintf("BEATMAP: %s Could not find background filename in this beatmap file", beatmap))
failed++
continue
}
backgroundPath := filepath.Join(beatmapFolder, beatmapBackgroundFilename)
// remove old background
err = os.Remove(backgroundPath)
if err != nil {
failed++
logger.LogWarning(fmt.Sprintf("BEATMAP: %s: Could not remove old background : %s", beatmap, err))
}
// create new background file
bgFile, err := os.Create(backgroundPath)
if err != nil {
failed++
logger.LogWarning(fmt.Sprintf("BEATMAP: %s: Could not create new background file : %s", beatmap, err))
continue
}
defer bgFile.Close()
// copy the contents of a given image to the newly created bg file
err = copyFile(replacementPicPath, backgroundPath)
if err != nil {
logger.LogWarning(fmt.Sprintf("BEATMAP: %s: Could not copy file: %s", beatmap, err))
failed++
continue
}
successful++
}
}
return successful, failed
}

95
settings/settings.go

@ -0,0 +1,95 @@
package settings
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/Unbewohnte/OBM/logger"
)
// struct for json settings` file contents
type Settings struct {
OsuDir string `json:"pathToOsu"`
ReplacementImagePath string `json:"pathToimage"`
CreateBlackBGImage bool `json:"createBlackBackgoundImage"`
Workers int `json:"Workers"`
}
const (
settingsFilename string = "settings.json"
)
var (
defaultSettings Settings = Settings{
OsuDir: "",
ReplacementImagePath: "",
CreateBlackBGImage: true,
Workers: 100,
}
)
// checks if the settings.json exists in current directory
func CheckSettingsFile() (bool, error) {
files, err := os.ReadDir(".")
if err != nil {
return false, errors.New(fmt.Sprintf("ERROR : Unable to read current directory %s", err))
}
for _, file := range files {
if !file.IsDir() && file.Name() == settingsFilename {
return true, nil
}
}
return false, nil
}
// creates "settings.json" and sets the flag
func CreateSettingsFile() error {
exists, err := CheckSettingsFile()
if err != nil {
return err
}
if exists {
return nil
}
file, err := os.Create(settingsFilename)
if err != nil {
return errors.New(fmt.Sprintf("ERROR: Error creating settings file... : %s", err))
}
settingsJson, err := json.MarshalIndent(defaultSettings, "", " ")
if err != nil {
return errors.New(fmt.Sprintf("ERROR: Error creating settings file... : %s", err))
}
file.Write(settingsJson)
file.Close()
logger.LogInfo("Successfully created new settingsFile")
return nil
}
// unmarshalls settings.json into struct
func GetSettings() Settings {
settingsFile, err := os.ReadFile(settingsFilename)
if err != nil {
logger.LogError(true, "Could not read settings file : ", err.Error())
}
var settings Settings
err = json.Unmarshal(settingsFile, &settings)
if err != nil {
logger.LogError(true, "Could not unmarshal json file : ", err)
}
if settings.Workers <= 0 {
logger.LogInfo("`Workers` is set to 0 or less. Replaced with 1")
settings.Workers = 1
}
return settings
}
Loading…
Cancel
Save