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
233 lines
5.4 KiB
package altvr
|
|
|
|
// TODO: Handle paginates
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"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)
|
|
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
|
|
}
|