diff --git a/cmd/crunchyroll-go/cmd/login.go b/cmd/crunchyroll-go/cmd/login.go index c2f07e0..f15bc5b 100644 --- a/cmd/crunchyroll-go/cmd/login.go +++ b/cmd/crunchyroll-go/cmd/login.go @@ -1,13 +1,20 @@ package cmd import ( + "fmt" "github.com/ByteDream/crunchyroll-go" "github.com/spf13/cobra" "io/ioutil" + "os" + "os/user" + "path/filepath" + "runtime" ) var ( - sessionIDFlag bool + loginSessionIDFlag bool + + loginPersistentFlag bool ) var loginCmd = &cobra.Command{ @@ -15,36 +22,55 @@ var loginCmd = &cobra.Command{ Short: "Login to crunchyroll", Args: cobra.RangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - if sessionIDFlag { - return loginSessionID(args[0], false) + Run: func(cmd *cobra.Command, args []string) { + if loginSessionIDFlag { + loginSessionID(args[0]) } else { - return loginCredentials(args[0], args[1]) + loginCredentials(args[0], args[1]) } }, } func init() { + loginCmd.Flags().BoolVar(&loginSessionIDFlag, "session-id", false, "Use a session id to login instead of username and password") + + loginCmd.Flags().BoolVar(&loginPersistentFlag, "persistent", false, "If the given credential should be stored persistent") + rootCmd.AddCommand(loginCmd) - loginCmd.Flags().BoolVar(&sessionIDFlag, "session-id", false, "session id") } -func loginCredentials(email, password string) error { +func loginCredentials(user, password string) error { out.Debug("Logging in via credentials") - session, err := crunchyroll.LoginWithCredentials(email, password, locale, client) - if err != nil { - return err + if _, err := crunchyroll.LoginWithCredentials(user, password, systemLocale(), client); err != nil { + out.Err(err.Error()) + os.Exit(1) } - return loginSessionID(session.SessionID, true) + + return ioutil.WriteFile(loginStorePath(), []byte(fmt.Sprintf("%s\n%s", user, password)), 0600) } -func loginSessionID(sessionID string, alreadyChecked bool) error { - if !alreadyChecked { - out.Debug("Logging in via session id") - if _, err := crunchyroll.LoginWithSessionID(sessionID, locale, client); err != nil { - return err - } +func loginSessionID(sessionID string) error { + out.Debug("Logging in via session id") + if _, err := crunchyroll.LoginWithSessionID(sessionID, systemLocale(), client); err != nil { + out.Err(err.Error()) + os.Exit(1) } - out.Info("Due to security reasons, you have to login again on the next reboot") - return ioutil.WriteFile(sessionIDPath, []byte(sessionID), 0777) + + return ioutil.WriteFile(loginStorePath(), []byte(sessionID), 0600) +} + +func loginStorePath() string { + path := filepath.Join(os.TempDir(), ".crunchy") + if loginPersistentFlag { + if runtime.GOOS != "windows" { + usr, _ := user.Current() + path = filepath.Join(usr.HomeDir, ".config/crunchyroll-go") + } + + out.Info("The login information will be stored permanently UNENCRYPTED on your drive (%s)", path) + } else { + out.Info("Due to security reasons, you have to login again on the next reboot") + } + + return path } diff --git a/cmd/crunchyroll-go/cmd/utils.go b/cmd/crunchyroll-go/cmd/utils.go index 809e982..4a9e748 100644 --- a/cmd/crunchyroll-go/cmd/utils.go +++ b/cmd/crunchyroll-go/cmd/utils.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/ByteDream/crunchyroll-go" "github.com/ByteDream/crunchyroll-go/utils" - "io/ioutil" "net/http" "net/url" "os" "os/exec" + "os/user" "path" "path/filepath" "reflect" @@ -19,8 +19,6 @@ import ( "time" ) -var sessionIDPath = filepath.Join(os.TempDir(), ".crunchy") - var ( invalidWindowsChars = []string{"<", ">", ":", "\"", "/", "|", "\\", "?", "*"} invalidLinuxChars = []string{"/"} @@ -95,32 +93,49 @@ func freeFileName(filename string) (string, bool) { return filename, j != 0 } -func loadSessionID() (string, error) { - if _, stat := os.Stat(sessionIDPath); os.IsNotExist(stat) { - out.Err("To use this command, login first. Type `%s login -h` to get help", os.Args[0]) - os.Exit(1) - } - body, err := ioutil.ReadFile(sessionIDPath) - if err != nil { - return "", err - } - return strings.ReplaceAll(string(body), "\n", ""), nil -} - func loadCrunchy() { out.SetProgress("Logging in") - sessionID, err := loadSessionID() - if err == nil { - if crunchy, err = crunchyroll.LoginWithSessionID(sessionID, systemLocale(), client); err != nil { + + files := []string{filepath.Join(os.TempDir(), ".crunchy")} + + if runtime.GOOS != "windows" { + usr, _ := user.Current() + files = append(files, filepath.Join(usr.HomeDir, ".config/crunchyroll-go")) + } + + var body []byte + var err error + for _, file := range files { + if _, err = os.Stat(file); os.IsNotExist(err) { + continue + } + body, err = os.ReadFile(file) + break + } + if body == nil { + out.Err("To use this command, login first. Type `%s login -h` to get help", os.Args[0]) + os.Exit(1) + } else if err != nil { + out.Err("Failed to read login information: %v", err) + os.Exit(1) + } + + split := strings.SplitN(string(body), "\n", 2) + if len(split) == 1 || split[2] == "" { + if crunchy, err = crunchyroll.LoginWithSessionID(split[0], systemLocale(), client); err != nil { out.StopProgress(err.Error()) os.Exit(1) } + out.Debug("Logged in with session id %s. BLANK THIS LINE OUT IF YOU'RE ASKED TO POST THE DEBUG OUTPUT SOMEWHERE", split[0]) } else { - out.StopProgress(err.Error()) - os.Exit(1) + if crunchy, err = crunchyroll.LoginWithCredentials(split[0], split[1], systemLocale(), client); err != nil { + out.StopProgress(err.Error()) + os.Exit(1) + } + out.Debug("Logged in with username '%s' and password '%s'. BLANK THIS LINE OUT IF YOU'RE ASKED TO POST THE DEBUG OUTPUT SOMEWHERE", split[0], split[1]) } + out.StopProgress("Logged in") - out.Debug("Logged in with session id %s", sessionID) } func hasFFmpeg() bool {