Initial
This commit is contained in:
commit
d1b62c2407
199
item.go
Normal file
199
item.go
Normal file
@ -0,0 +1,199 @@
|
||||
package roblox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Item struct containing data on retrieved items
|
||||
type Item struct {
|
||||
ProductID string
|
||||
ItemID string
|
||||
AssetID string
|
||||
UserID string
|
||||
UserName string
|
||||
Type string
|
||||
Name string
|
||||
CopyLocked bool
|
||||
Owned bool
|
||||
}
|
||||
|
||||
// ItemInfo return info of selected item
|
||||
func (s *Session) ItemInfo(url string) (Item, error) {
|
||||
var item Item
|
||||
|
||||
resp, err := s.client.Get(url)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return item, fmt.Errorf("Failed to get item info. Status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
page := string(body)
|
||||
|
||||
pItem := regexp.MustCompile("data-product-id=\"(.+)\"").FindStringSubmatch(page)
|
||||
if len(pItem) > 0 {
|
||||
item.ProductID, err = safeRetrieve("data-product-id=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
item.CopyLocked = false
|
||||
item.UserID, err = safeRetrieve("data-expected-seller-id=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
item.UserName, err = safeRetrieve("data-seller-name=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
} else {
|
||||
item.ProductID = "locked"
|
||||
item.CopyLocked = true
|
||||
item.UserID = ""
|
||||
item.UserName = ""
|
||||
item.AssetID = ""
|
||||
}
|
||||
|
||||
asset := regexp.MustCompile("data-userasset-id=\"(.+)\"").FindStringSubmatch(page)
|
||||
if len(asset) > 0 {
|
||||
item.AssetID, err = safeRetrieve("data-userasset-id=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
item.Owned = true
|
||||
} else {
|
||||
item.AssetID = ""
|
||||
item.Owned = false
|
||||
}
|
||||
|
||||
item.ItemID, err = safeRetrieve("data-item-id=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
item.Name, err = safeRetrieve("data-item-name=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
item.Type, err = safeRetrieve("data-asset-type=\"(.+)\"", page)
|
||||
if err != nil {
|
||||
return item, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// AddItem add item by id to inventory
|
||||
func (s *Session) AddItem(id string, seller string) error {
|
||||
v := url.Values{}
|
||||
v.Set("rqtype", "purchase")
|
||||
v.Set("productID", id)
|
||||
v.Set("expectedCurrency", "1")
|
||||
v.Set("expectedPrice", "0")
|
||||
v.Set("expectedSellerID", seller)
|
||||
v.Set("userAssetID", "")
|
||||
resp, err := s.client.Post("https://www.roblox.com/api/item.ashx?"+v.Encode(), "application/json", bytes.NewBufferString(""))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 403 {
|
||||
req, err := http.NewRequest("POST", "https://www.roblox.com/api/item.ashx?"+v.Encode(), bytes.NewBufferString(""))
|
||||
req.Header.Set("X-Csrf-Token", resp.Header["X-Csrf-Token"][0])
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("Failed to add item. Status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveItem will remove item from inventory
|
||||
func (s *Session) RemoveItem(id string) error {
|
||||
v := url.Values{}
|
||||
v.Set("assetId", id)
|
||||
resp, err := s.client.Post("https://www.roblox.com/asset/delete-from-inventory", "application/x-www-form-urlencoded", bytes.NewBufferString(v.Encode()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 403 {
|
||||
req, err := http.NewRequest("POST", "https://www.roblox.com/asset/delete-from-inventory", bytes.NewBufferString(v.Encode()))
|
||||
req.Header.Set("X-Csrf-Token", resp.Header["X-Csrf-Token"][0])
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("Failed to remove item. Status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetModels will list models in inventory
|
||||
func (s *Session) GetModels(user string) ([]Item, error) {
|
||||
var Data []Item
|
||||
|
||||
resp, err := s.client.Get("https://www.roblox.com/users/inventory/list-json?assetTypeId=10&userId=" + user)
|
||||
if err != nil {
|
||||
return Data, fmt.Errorf("Could not get list: %s", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
var dat map[string]interface{}
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if err := json.Unmarshal(body, &dat); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
set := dat["Data"].(map[string]interface{})
|
||||
ilist := set["Items"].([]interface{})
|
||||
for _, obj := range ilist {
|
||||
itm := obj.(map[string]interface{})
|
||||
iInfo := itm["Item"].(map[string]interface{})
|
||||
iCreator := itm["Creator"].(map[string]interface{})
|
||||
Data = append(Data, Item{"", strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", iInfo["AssetId"].(float64)), "0"), "."), "", strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", iCreator["Id"].(float64)), "0"), "."), iCreator["Name"].(string), "Model", iInfo["Name"].(string), false, true})
|
||||
}
|
||||
|
||||
return Data, nil
|
||||
}
|
||||
return Data, fmt.Errorf("Could not get models. Status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
func safeRetrieve(pattern string, source string) (string, error) {
|
||||
pItem := regexp.MustCompile(pattern).FindStringSubmatch(source)
|
||||
if len(pItem) > 0 {
|
||||
return pItem[1], nil
|
||||
}
|
||||
return "", fmt.Errorf("Could not find item on in string")
|
||||
}
|
136
message.go
Normal file
136
message.go
Normal file
@ -0,0 +1,136 @@
|
||||
package roblox
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Message structure for message data
|
||||
type Message struct {
|
||||
ID string
|
||||
Subject string
|
||||
Body string
|
||||
FromID string
|
||||
FromName string
|
||||
}
|
||||
|
||||
// GetInbox makes a request to retrieve message list
|
||||
func (s *Session) GetInbox() ([]Message, error) {
|
||||
var messages []Message
|
||||
resp, err := s.client.Get("https://www.roblox.com/messages/api/get-messages")
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
var data map[string]interface{}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
|
||||
collection, exists := data["Collection"]
|
||||
if exists {
|
||||
for _, value := range collection.([]interface{}) {
|
||||
// We will assume if we got this far everything exists
|
||||
msg := value.(map[string]interface{})
|
||||
sender := msg["Sender"].(map[string]interface{})
|
||||
|
||||
message := Message{}
|
||||
message.ID = string(int(msg["Id"].(float64)))
|
||||
message.Subject = msg["Subject"].(string)
|
||||
message.Body = msg["Body"].(string)
|
||||
message.FromID = string(int(sender["UserId"].(float64)))
|
||||
message.FromName = sender["UserName"].(string)
|
||||
messages = append(messages, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return messages, err
|
||||
}
|
||||
|
||||
// SendMessage will send a message via post
|
||||
func (s *Session) SendMessage(subject string, body string, recipientid int) error {
|
||||
payload := map[string]interface{}{
|
||||
"subject": subject,
|
||||
"body": body,
|
||||
"recipientId": recipientid,
|
||||
}
|
||||
data, err := json.Marshal(&payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.client.Post("https://www.roblox.com/messages/send", "application/json", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
// CSRF Token Status
|
||||
if resp.StatusCode == 403 {
|
||||
req, err := http.NewRequest("POST", "https://www.roblox.com/messages/send", bytes.NewBuffer(data))
|
||||
req.Header.Set("X-Csrf-Token", resp.Header["X-Csrf-Token"][0])
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("Messaged send failed. Status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ArchiveMessages will archieve a list of messages
|
||||
func (s *Session) ArchiveMessages(ids []string) error {
|
||||
payload := map[string][]string{
|
||||
"messageIds": ids,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(&payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := s.client.Post("https://www.roblox.com/messages/api/archive-messages", "application/json", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
// CSRF Token Status
|
||||
if resp.StatusCode == 403 {
|
||||
req, err := http.NewRequest("POST", "https://www.roblox.com/messages/api/archive-messages", bytes.NewBuffer(data))
|
||||
req.Header.Set("X-Csrf-Token", resp.Header["X-Csrf-Token"][0])
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("Archive failed. Status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
38
session.go
Normal file
38
session.go
Normal file
@ -0,0 +1,38 @@
|
||||
package roblox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Session struct for roblox login session data and members
|
||||
type Session struct {
|
||||
ID string
|
||||
username string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// New create a new session and logs in with provided data
|
||||
func New(user string, pass string, id string) (*Session, error) {
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
Jar: cookieJar,
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("username", user)
|
||||
v.Set("password", pass)
|
||||
v.Set("submitLogin", "Log In")
|
||||
v.Set("ReturnUrl", "")
|
||||
|
||||
session := Session{id, user, client}
|
||||
|
||||
resp, err := client.PostForm("https://www.roblox.com/newlogin", v)
|
||||
if resp.StatusCode != 200 {
|
||||
return &session, fmt.Errorf("Messaged send failed. Status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return &session, err
|
||||
}
|
Loading…
Reference in New Issue
Block a user