From c1c969db2ee7c68cb096c3a23420b99f30705173 Mon Sep 17 00:00:00 2001 From: Vladimir Hodakov Date: Sat, 14 Sep 2019 18:55:39 +0400 Subject: [PATCH] Add login support, golangci-lint config --- .golangci.yaml | 19 +++++++ main.go => cmd/massdl.go | 7 +++ domains/loginer/v1/checks.go | 12 +++++ domains/loginer/v1/exported.go | 43 ++++++++++++++++ domains/loginer/v1/login.go | 90 ++++++++++++++++++++++++++++++++++ internal/context/context.go | 5 ++ internal/context/exported.go | 2 + 7 files changed, 178 insertions(+) create mode 100644 .golangci.yaml rename main.go => cmd/massdl.go (74%) create mode 100644 domains/loginer/v1/checks.go create mode 100644 domains/loginer/v1/exported.go create mode 100644 domains/loginer/v1/login.go diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..843af8b --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,19 @@ +run: + deadline: 5m +linters: + enable-all: true + disable: + - gochecknoglobals + - goimports + - gocritic +linters-settings: + lll: + line-length: 420 + gocyclo: + min-complexity: 40 + +issues: + exclude-rules: + - path: "exported.go" + linters: + - dupl diff --git a/main.go b/cmd/massdl.go similarity index 74% rename from main.go rename to cmd/massdl.go index 3545d1c..97f4bb0 100644 --- a/main.go +++ b/cmd/massdl.go @@ -5,6 +5,7 @@ package main import ( + "gitlab.com/fat0troll/uploader_tools/domains/loginer/v1" "gitlab.com/fat0troll/uploader_tools/internal/context" ) @@ -13,4 +14,10 @@ func main() { c.Init() c.Logger.Info().Msg("NNM-Club mass torrent files downloader is starting") c.InitConfig() + + loginerv1.New(c) + + c.Flagger.Parse() + + loginerv1.Process() } diff --git a/domains/loginer/v1/checks.go b/domains/loginer/v1/checks.go new file mode 100644 index 0000000..f216762 --- /dev/null +++ b/domains/loginer/v1/checks.go @@ -0,0 +1,12 @@ +// NNM-Club torrent filess mass downloader +// Created for Uploaders group +// Copyright (c) 2012-2019 Vladimir "fat0troll" Hodakov + +package loginerv1 + +// checkConfig checks if there's some errors in config file +func checkConfig() { + if c.Config.URL == "" || c.Config.Password == "" || c.Config.Username == "" { + dlog.Fatal().Msg("Конфиг не заполнен или заполнен не до конца. Запустите программу с ключом -auth для авторизации.") + } +} diff --git a/domains/loginer/v1/exported.go b/domains/loginer/v1/exported.go new file mode 100644 index 0000000..c12cd5d --- /dev/null +++ b/domains/loginer/v1/exported.go @@ -0,0 +1,43 @@ +// NNM-Club torrent filess mass downloader +// Created for Uploaders group +// Copyright (c) 2012-2019 Vladimir "fat0troll" Hodakov + +package loginerv1 + +import ( + "github.com/rs/zerolog" + "gitlab.com/fat0troll/uploader_tools/internal/context" + "gitlab.com/pztrn/flagger" +) + +var ( + c *context.Context + dlog zerolog.Logger +) + +// New initializes package +func New(cc *context.Context) { + c = cc + dlog = c.Logger.With().Str("domain", "loginer").Int("version", 1).Logger() + + _ = c.Flagger.AddFlag(&flagger.Flag{ + Name: "auth", + Description: "Start authentication to NNM-Club website and create application config.", + Type: "bool", + DefaultValue: false, + }) + + dlog.Info().Msg("Domain initialized") +} + +// Process handles authorization +func Process() { + auth, _ := c.Flagger.GetBoolValue("auth") + + if auth { + login() + } + + checkConfig() + obtainCookies() +} diff --git a/domains/loginer/v1/login.go b/domains/loginer/v1/login.go new file mode 100644 index 0000000..77d9528 --- /dev/null +++ b/domains/loginer/v1/login.go @@ -0,0 +1,90 @@ +// NNM-Club torrent filess mass downloader +// Created for Uploaders group +// Copyright (c) 2012-2019 Vladimir "fat0troll" Hodakov + +package loginerv1 + +import ( + "bufio" + "net/http" + "net/url" + "os" + "strings" +) + +// login function name is self-descriptive. +// After successful login it will write cookie file and config in system's +// config directory +func login() { + dlog.Info().Msg("Введите адрес сайта NNM-Club, без протокола (к примеру, nnmclub.ro)") + // First enter is site name, second and third are user credentials + scanner := bufio.NewScanner(os.Stdin) + scanline := 0 + for scanner.Scan() { + scanline++ + switch { + case scanline == 1: + c.Config.URL = scanner.Text() + dlog.Info().Msg("Введите имя пользователя") + case scanline == 2: + c.Config.Username = scanner.Text() + dlog.Info().Msg("Введите пароль") + default: + c.Config.Password = scanner.Text() + } + if scanline == 3 { + break + } + } + if scanner.Err() != nil { + dlog.Fatal().Err(scanner.Err()).Msg("Не удалось прочитать пользовательский ввод.") + } + + c.SaveConfig() + + obtainCookies() + + dlog.Info().Msg("Логин прошёл успешно. Перезапустите программу с ключём -forum НОМЕР_ФОРУМА.") + os.Exit(0) +} + +// obtainCookie tries to login to NNM-Club and saves resulting cookie +// If it can't save cookie, the program will terminate with error and you will +// need to authorize again or retry cookie obtaining. +func obtainCookies() { + // This value is obtained from login.php sources. + nnmClubCode := "58161005a04f0ee5" + + client := http.Client{ + // This is disables redirects for this request. Otherwise we can't obtain cookies + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + } + + formData := url.Values{} + formData.Add("username", c.Config.Username) + formData.Add("password", c.Config.Password) + formData.Add("autologin", "on") + formData.Add("redirect", "index.php") + formData.Add("code", nnmClubCode) + formData.Add("login", "%C2%F5%EE%E4") + + url := "https://" + c.Config.URL + "/forum/login.php" + req, _ := http.NewRequest(http.MethodPost, url, strings.NewReader(formData.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") + + resp, err := client.Do(req) + if err != nil { + dlog.Fatal().Err(err).Msg("Не удалось отправить запрос на авторизацию в NNM-Club.") + } + defer resp.Body.Close() + + if len(resp.Cookies()) == 0 { + dlog.Fatal().Msg("Не удалось получить печеньки от сайта NNM-Club. Неправильные имя/пароль или адрес сайта.") + } + + c.SetCookies(resp.Cookies()) + + dlog.Info().Str("username", c.Config.Username).Msg("Успешный логин.") +} diff --git a/internal/context/context.go b/internal/context/context.go index b9cb9ba..fb79a02 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -11,6 +11,7 @@ import ( "github.com/rs/zerolog" "gitlab.com/pztrn/flagger" "log" + "net/http" "os" "path/filepath" "runtime" @@ -95,3 +96,7 @@ func (c *Context) SaveConfig() { dlog.Fatal().Err(err).Msg("Failed to encode config") } } + +func (c *Context) SetCookies(cookies []*http.Cookie) { + c.Cookies = append(c.Cookies, cookies...) +} diff --git a/internal/context/exported.go b/internal/context/exported.go index f6c2fc6..d1f8a9e 100644 --- a/internal/context/exported.go +++ b/internal/context/exported.go @@ -8,6 +8,7 @@ import ( "github.com/rs/zerolog" "gitlab.com/fat0troll/uploader_tools/internal/config" "gitlab.com/pztrn/flagger" + "net/http" ) var ( @@ -21,6 +22,7 @@ type Context struct { Config config.Config Flagger *flagger.Flagger Logger zerolog.Logger + Cookies []*http.Cookie } // New creates new Context