You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
5.4 KiB

package altvr
import (
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"git.lalonde.me/matth/AltVRBot/pkg/utils"
"github.com/PuerkitoBio/goquery"
"golang.org/x/net/html"
)
const (
_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"
)
func (avr *AltVR) doLogin() error {
u, _ := url.Parse("https://account.altvr.com/users/sign_in")
client := &http.Client{Jar: avr.jar}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
log.Fatalln(err)
}
req.Header.Set("User-Agent", _UA)
resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Page unavailable (%d)", resp.StatusCode)
}
ctype := resp.Header.Get("content-Type")
if !strings.HasPrefix(ctype, "text/html") {
return errors.New("Invalid content type")
}
tokenizer := html.NewTokenizer(resp.Body)
var authToken string
found := false
for {
tokenType := tokenizer.Next()
if tokenType == html.ErrorToken {
err := tokenizer.Err()
if err == io.EOF {
break
}
return errors.New("Invalid content")
}
if tokenType == html.SelfClosingTagToken {
token := tokenizer.Token()
if "input" == token.Data {
value := ""
for _, a := range token.Attr {
if a.Key == "name" {
if a.Val == "authenticity_token" {
found = true
}
}
if a.Key == "value" {
value = a.Val
}
}
if found {
authToken = value
break
}
}
}
}
if authToken == "" {
return errors.New("Auth token not found")
}
postData := url.Values{
"authenticity_token": {authToken},
"utf8": {"✓"},
"user[tz_offset]": {"0"},
"user[remember_me]": {"1"},
"user[email]": {avr.username},
"user[password]": {avr.password},
}
req, err = http.NewRequest("POST", u.String(), strings.NewReader(postData.Encode()))
if err != nil {
log.Fatalln(err)
}
req.Header.Set("User-Agent", _UA)
resp, err = client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
avr.csrfToken = resp.Header.Get("X-CSRF-Token")
// Load the HTML document
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return err
}
hrefProfile, loggedIn := doc.Find("body > div.main-wrapper > div.nav-bar > div > div > div:nth-child(2) > div:nth-child(2) > a").Attr("href")
if !loggedIn {
return errorLogin
}
avr.userID = strings.Replace(strings.Replace(hrefProfile, "/user_profile", "", -1), "/users/", "", -1)
return nil
}
func (avr *AltVR) fetchMyUser() (User, error) {
if avr.userID == "" {
return User{}, errorLogin
}
body, err := avr.get("users/" + avr.userID)
if err != nil {
return User{}, err
}
var users Users
json.Unmarshal(body, &users)
return users.Users[0], nil
}
func (avr *AltVR) fetchClientIP() (string, error) {
body, err := avr.get("client_ip.json")
if err != nil {
return "", err
}
var cip ClientIP
json.Unmarshal(body, &cip)
return cip.ClientIP, nil
}
func (avr *AltVR) fetchFriendships() ([]Friendship, error) {
body, err := avr.get("friendships/friends?include_users=false&online=false&per=50&page=1")
if err != nil {
return []Friendship{}, err
}
var friendship Friendships
json.Unmarshal(body, &friendship)
return friendship.Friendships, nil
}
func (avr *AltVR) fetchFriendshipsOnline() ([]Friendship, error) {
body, err := avr.get("friendships/friends?include_users=false&online=true&per=50&page=1")
if err != nil {
return []Friendship{}, err
}
var friendship Friendships
json.Unmarshal(body, &friendship)
return friendship.Friendships, nil
}
func (avr *AltVR) fetchUsers(userIDs ...string) ([]User, error) {
if len(userIDs) == 0 {
return []User{}, nil
}
body, err := avr.get("users/" + strings.Join(userIDs[:], ","))
if err != nil {
return []User{}, err
}
var users Users
json.Unmarshal(body, &users)
return users.Users, nil
}
func (avr *AltVR) fetchPendingFriendshipRequests() ([]Friendship, error) {
body, err := avr.get("friendships/incoming_friend_requests?include_users=false&per=50&page=1")
if err != nil {
return []Friendship{}, err
}
var friendship Friendships
json.Unmarshal(body, &friendship)
return friendship.Friendships, nil
}
func (avr *AltVR) acceptPendingFriendshipRequest(friendshipID string) error {
_, err := avr.post("friendships/"+friendshipID+"/accept", strings.NewReader("")) //strings.NewReader(url.Values{}.Encode())
return err
}
func (avr *AltVR) denyPendingFriendshipRequest(friendshipID string) error {
_, err := avr.post("friendships/"+friendshipID+"/deny", strings.NewReader(""))
return err
}
func (avr *AltVR) fetchPendingConversations() ([]Conversation, error) {
body, err := avr.get("conversations")
if err != nil {
return []Conversation{}, err
}
var conversations Conversations
json.Unmarshal(body, &conversations)
return conversations.Conversations, nil
}
func (avr *AltVR) postNewConversation(userID, message string) error {
uid, _ := strconv.ParseUint(userID, 10, 64)
message = utils.TruncateString(message, 140)
jv, _ := json.Marshal(&ConversationNewMessageOutgoing{
Conversation: ConversationNewMessage{
UserID: uid,
Subject: message,
}})
_, err := avr.post("conversations.json", strings.NewReader(string(jv)))
return err
}
func (avr *AltVR) markConversationAsRead(conversationID string) error {
_, err := avr.post("conversations/"+conversationID+"/mark_as_read", strings.NewReader(""))
return err
}