diff --git a/TODO.md b/TODO.md index 4944953..727df6f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,4 @@ - [x] *.cy file check - [ ] read file in cache - [ ] Chinese language support -- [ ] decrypt folder +- [x] decrypt directly diff --git a/changelog.md b/changelog.md index aa316c9..8a80f44 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +## 1.2.0 + +Support decrypt directory. + ## 1.1.1 DO NOT USE ELSE diff --git a/cmd/cmd.go b/cmd/cmd.go index af78fd3..3766345 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -18,8 +18,8 @@ func Execute() { app := &cli.App{ Name: "ddlcpad", Usage: "Doki Doki Literature Club Plus Asset Decrypter", - UsageText: "ddlcpad file", - Version: "1.1.1", + UsageText: "ddlcpad file/directory", + Version: "1.2.0", Action: func(c *cli.Context) error { // if wrong args, exit @@ -46,8 +46,8 @@ func Execute() { // check if a directory if utils.CheckFileIsDir(fileIn) { logs.InfoLog(fmt.Sprintf("Directory \"%s\" detect, try to decrypt all file in it.", fileIn)) - // todo decrypt whole folder - logs.ErrorLog("(pr welcome) Wait for next version :(") + core.DecryptDirectly(fileIn) + logs.DecryptDirectlySuccessfulMsg() return nil } diff --git a/core/decrypt.go b/core/decrypt.go index aa84a4b..bcd410f 100644 --- a/core/decrypt.go +++ b/core/decrypt.go @@ -47,6 +47,60 @@ func Decrypt(in, out string) bool { return true } +// DecryptDirectly Decrypt all data in directory and create new file. +func DecryptDirectly(dirPath string) { + logs.InfoLog(fmt.Sprintf("Start read files in directory \"%s\".", dirPath)) + + successful := 0 + failed := 0 + skiped := 0 + + // read files in directory + files, err := ioutil.ReadDir(dirPath) + if err != nil { + // todo err handle + panic(err) + } + + for _, file := range files { + // if file is a directory, skip. + if file.IsDir() { + logs.InfoLog(fmt.Sprintf("Directory \"%s\" found, skip.", file.Name())) + skiped++ + continue + } + + // file name + in := dirPath + "/" + file.Name() + out := fmt.Sprintf("%s.out", in) + + // if a *.cy.out file exists, skip. + if utils.CheckFileExist(out) { + logs.InfoLog(fmt.Sprintf("File \"%s\" already exist, skip.", out)) + skiped++ + continue + } + + // try to decrypt file + if Decrypt(in, out) { + logs.InfoLog(fmt.Sprintf("File \"%s\" decrypt successful!", in)) + successful++ + } else { + logs.ErrorLog(fmt.Sprintf("File \"%s\" decrypt failed!", in)) + failed++ + } + } + + total := successful + failed + skiped + + // print result + logs.InfoLog("Decrypt finished.") + logs.InfoLog(fmt.Sprintf("Successful: %d", successful)) + logs.InfoLog(fmt.Sprintf("Failed: %d", failed)) + logs.InfoLog(fmt.Sprintf("Skipped: %d", skiped)) + logs.InfoLog(fmt.Sprintf("Total: %d", total)) +} + // xorByte XOR all bytes input with decrypt key func xorByte(str []byte) (ret []byte) { for i := 0; i < len(str); i++ { diff --git a/logs/logs.go b/logs/logs.go index 4252682..49f4cb0 100644 --- a/logs/logs.go +++ b/logs/logs.go @@ -32,6 +32,19 @@ func DecryptSuccessfulMsg() { fmt.Print("\033[32m***********************************************************\033[0m\n") } +// DecryptDirectlySuccessfulMsg Print help message when decrypt directly success. +func DecryptDirectlySuccessfulMsg() { + fmt.Print("\033[32m*****************************************************\033[0m\n") + fmt.Print("\033[32m* Decrypted Successful! *\033[0m\n") + fmt.Print("\033[32m* Decryption has been completed. *\033[0m\n") + fmt.Print("\033[32m* There may be something wrong, all error has been *\033[0m\n") + fmt.Print("\033[32m* skiped, you can check the log for more detail. *\033[0m\n") + fmt.Print("\033[32m* Now you can use AssetStudio to get all the assert *\033[0m\n") + fmt.Print("\033[32m* files. Here to download AssertStudio: *\033[0m\n") + fmt.Print("\033[32m* *\033[0m\n") + fmt.Print("\033[32m*****************************************************\033[0m\n") +} + // DecryptFailMsg Print help message when decrypt fail. func DecryptFailMsg() { fmt.Print("\033[31m***********************************************************\033[0m\n")