forked from s32x/anirip
/
session.go
82 lines (71 loc) · 2.45 KB
/
session.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package crunchyroll /* import "s32x.com/anirip/crunchyroll" */
import (
"bytes"
"net/http"
"net/url"
"strings"
"github.com/PuerkitoBio/goquery"
"s32x.com/anirip/common"
"s32x.com/anirip/common/log"
)
// Login logs the user in to Crunchyroll and stores the session on the client
func Login(c *common.HTTPClient, user, pass string) error {
// Perform preflight request to retrieve the login page
res, err := c.Get("https://www.crunchyroll.com/login", nil)
if err != nil {
return err
}
defer res.Body.Close()
doc, err := goquery.NewDocumentFromResponse(res)
if err != nil {
return err
}
// Scrape the login token
token, _ := doc.Find("#login_form__token").First().Attr("value")
// Sets the credentials and attempts to generate new cookies
if err := createSession(c, user, pass, token); err != nil {
return err
}
// Validates the session created and returns
if err := validateSession(c); err != nil {
return err
}
log.Info("Successfully logged in!")
return nil
}
// createSession sends a login request to Crunchyroll and stores the cookies
// recieved in the clients cookiejar
func createSession(c *common.HTTPClient, user, pass, token string) error {
// Assemble the FormData needed for authentication
body := bytes.NewBufferString(url.Values{
"login_form[name]": {user},
"login_form[password]": {pass},
"login_form[redirect_url]": {"/"},
"login_form[_token]": {token},
}.Encode())
// Execute the post request on the formhandler and store cookies in the jar
head := http.Header{}
head.Add("Referer", "https://www.crunchyroll.com/login")
head.Add("Content-Type", "application/x-www-form-urlencoded")
if _, err := c.Post("https://www.crunchyroll.com/login", head, body); err != nil {
return common.NewError("Failed to execute authentication request", err)
}
return nil
}
// validateSession performs a get request on crunchyrolls homepage and checks
// to be sure a non-empty username is found
func validateSession(c *common.HTTPClient) error {
resp, err := c.Get("http://www.crunchyroll.com/", nil)
if err != nil {
return common.NewError("Failed to execute session validation request", err)
}
doc, err := goquery.NewDocumentFromResponse(resp)
if err != nil {
return common.NewError("Failed to parse session validation page", err)
}
user := strings.TrimSpace(doc.Find("li.username").First().Text())
if resp.StatusCode == 200 && user != "" {
return nil
}
return common.NewError("Failed to verify session", nil)
}