commit
fb22930042
102
item.go
102
item.go
@ -7,16 +7,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Item struct containing data on retrieved items
|
// Item struct containing data on retrieved items
|
||||||
type Item struct {
|
type Item struct {
|
||||||
ProductID string
|
ProductID int
|
||||||
ItemID string
|
ItemID int
|
||||||
AssetID string
|
AssetID int
|
||||||
UserID string
|
UserID int
|
||||||
UserName string
|
UserName string
|
||||||
Type string
|
Type string
|
||||||
Name string
|
Name string
|
||||||
@ -24,83 +23,14 @@ type Item struct {
|
|||||||
Owned 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
|
// AddItem add item by id to inventory
|
||||||
func (s *Session) AddItem(id string, seller string) error {
|
func (s *Session) AddItem(id int, seller int) error {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("rqtype", "purchase")
|
v.Set("rqtype", "purchase")
|
||||||
v.Set("productID", id)
|
v.Set("productID", strconv.Itoa(id))
|
||||||
v.Set("expectedCurrency", "1")
|
v.Set("expectedCurrency", "1")
|
||||||
v.Set("expectedPrice", "0")
|
v.Set("expectedPrice", "0")
|
||||||
v.Set("expectedSellerID", seller)
|
v.Set("expectedSellerID", strconv.Itoa(seller))
|
||||||
v.Set("userAssetID", "")
|
v.Set("userAssetID", "")
|
||||||
resp, err := s.client.Post("https://www.roblox.com/api/item.ashx?"+v.Encode(), "application/json", bytes.NewBufferString(""))
|
resp, err := s.client.Post("https://www.roblox.com/api/item.ashx?"+v.Encode(), "application/json", bytes.NewBufferString(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -129,9 +59,9 @@ func (s *Session) AddItem(id string, seller string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveItem will remove item from inventory
|
// RemoveItem will remove item from inventory
|
||||||
func (s *Session) RemoveItem(id string) error {
|
func (s *Session) RemoveItem(id int) error {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("assetId", id)
|
v.Set("assetId", strconv.Itoa(id))
|
||||||
resp, err := s.client.Post("https://www.roblox.com/asset/delete-from-inventory", "application/x-www-form-urlencoded", bytes.NewBufferString(v.Encode()))
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -159,10 +89,10 @@ func (s *Session) RemoveItem(id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetModels will list models in inventory
|
// GetModels will list models in inventory
|
||||||
func (s *Session) GetModels(user string) ([]Item, error) {
|
func (s *Session) GetModels(user int) ([]Item, error) {
|
||||||
var Data []Item
|
var Data []Item
|
||||||
|
|
||||||
resp, err := s.client.Get("https://www.roblox.com/users/inventory/list-json?assetTypeId=10&userId=" + user)
|
resp, err := s.client.Get("https://www.roblox.com/users/inventory/list-json?assetTypeId=10&userId=" + strconv.Itoa(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Data, fmt.Errorf("Could not get list: %s", err)
|
return Data, fmt.Errorf("Could not get list: %s", err)
|
||||||
}
|
}
|
||||||
@ -182,18 +112,10 @@ func (s *Session) GetModels(user string) ([]Item, error) {
|
|||||||
itm := obj.(map[string]interface{})
|
itm := obj.(map[string]interface{})
|
||||||
iInfo := itm["Item"].(map[string]interface{})
|
iInfo := itm["Item"].(map[string]interface{})
|
||||||
iCreator := itm["Creator"].(map[string]interface{})
|
iCreator := itm["Creator"].(map[string]interface{})
|
||||||
Data = append(Data, Item{"", strconv.Itoa(int(iInfo["AssetId"].(float64))), "", strconv.Itoa(int(iCreator["Id"].(float64))), iCreator["Name"].(string), "Model", iInfo["Name"].(string), false, true})
|
Data = append(Data, Item{0, int(iInfo["AssetId"].(float64)), 0, int(iCreator["Id"].(float64)), iCreator["Name"].(string), "Model", iInfo["Name"].(string), false, true})
|
||||||
}
|
}
|
||||||
|
|
||||||
return Data, nil
|
return Data, nil
|
||||||
}
|
}
|
||||||
return Data, fmt.Errorf("Could not get models. Status: %d", resp.StatusCode)
|
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")
|
|
||||||
}
|
|
||||||
|
156
message.go
156
message.go
@ -1,156 +0,0 @@
|
|||||||
package roblox
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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 = strconv.Itoa(int(msg["Id"].(float64)))
|
|
||||||
message.Subject = msg["Subject"].(string)
|
|
||||||
message.Body = msg["Body"].(string)
|
|
||||||
message.FromID = strconv.Itoa(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 string) error {
|
|
||||||
reciever, err := strconv.Atoi(recipientid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
payload := map[string]interface{}{
|
|
||||||
"subject": subject,
|
|
||||||
"body": body,
|
|
||||||
"recipientId": reciever,
|
|
||||||
}
|
|
||||||
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 archive a list of messages
|
|
||||||
func (s *Session) ArchiveMessages(ids []string) error {
|
|
||||||
if len(ids) <= 0 {
|
|
||||||
return fmt.Errorf("ID list was empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// We do this because when we turn it to json it will look like [1,2,3]
|
|
||||||
// and not ["1","2","3"]
|
|
||||||
var newList []int
|
|
||||||
for i := 0; i < len(ids); i++ {
|
|
||||||
idString, err := strconv.Atoi(ids[i])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
newList = append(newList, idString)
|
|
||||||
}
|
|
||||||
|
|
||||||
payload := map[string][]int{
|
|
||||||
"messageIds": newList,
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
61
product.go
Normal file
61
product.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package roblox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Product contains info about a product
|
||||||
|
type Product struct {
|
||||||
|
TargetID int `json:"TargetId"`
|
||||||
|
ProductType string `json:"ProductType"`
|
||||||
|
AssetID int `json:"AssetId"`
|
||||||
|
ProductID int `json:"ProductId"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
Description string `json:"Description"`
|
||||||
|
AssetTypeID int `json:"AssetTypeId"`
|
||||||
|
Creator struct {
|
||||||
|
ID int `json:"Id"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
CreatorType string `json:"CreatorType"`
|
||||||
|
CreatorTargetID int `json:"CreatorTargetId"`
|
||||||
|
} `json:"Creator"`
|
||||||
|
IconImageAssetID int `json:"IconImageAssetId"`
|
||||||
|
Created time.Time `json:"Created"`
|
||||||
|
Updated time.Time `json:"Updated"`
|
||||||
|
PriceInRobux int `json:"PriceInRobux"`
|
||||||
|
PriceInTickets int `json:"PriceInTickets"`
|
||||||
|
Sales int `json:"Sales"`
|
||||||
|
IsNew bool `json:"IsNew"`
|
||||||
|
IsForSale bool `json:"IsForSale"`
|
||||||
|
IsPublicDomain bool `json:"IsPublicDomain"`
|
||||||
|
IsLimited bool `json:"IsLimited"`
|
||||||
|
IsLimitedUnique bool `json:"IsLimitedUnique"`
|
||||||
|
Remaining int `json:"Remaining"`
|
||||||
|
MinimumMembershipLevel int `json:"MinimumMembershipLevel"`
|
||||||
|
ContentRatingTypeID int `json:"ContentRatingTypeId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProduct will retrieve store information on a product
|
||||||
|
func (s *Session) GetProduct(id int) (*Product, error) {
|
||||||
|
resp, err := s.client.Get(fmt.Sprintf("http://api.roblox.com/marketplace/productinfo?assetId=%d", id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var info Product
|
||||||
|
err = json.Unmarshal(data, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
17
session.go
17
session.go
@ -9,30 +9,37 @@ import (
|
|||||||
|
|
||||||
// Session struct for roblox login session data and members
|
// Session struct for roblox login session data and members
|
||||||
type Session struct {
|
type Session struct {
|
||||||
ID string
|
ID int
|
||||||
Username string
|
Username string
|
||||||
client *http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// New create a new session and logs in with provided data
|
// New create a new session and logs in with provided data
|
||||||
func New(user string, pass string, id string) (*Session, error) {
|
func New(username, password string) (*Session, error) {
|
||||||
cookieJar, _ := cookiejar.New(nil)
|
cookieJar, _ := cookiejar.New(nil)
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Jar: cookieJar,
|
Jar: cookieJar,
|
||||||
}
|
}
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("username", user)
|
v.Set("username", username)
|
||||||
v.Set("password", pass)
|
v.Set("password", password)
|
||||||
v.Set("submitLogin", "Log In")
|
v.Set("submitLogin", "Log In")
|
||||||
v.Set("ReturnUrl", "")
|
v.Set("ReturnUrl", "")
|
||||||
|
|
||||||
session := Session{id, user, client}
|
session := Session{0, username, client}
|
||||||
|
|
||||||
resp, err := client.PostForm("https://www.roblox.com/newlogin", v)
|
resp, err := client.PostForm("https://www.roblox.com/newlogin", v)
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
return &session, fmt.Errorf("Messaged send failed. Status %d", resp.StatusCode)
|
return &session, fmt.Errorf("Messaged send failed. Status %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info, err := session.GetUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to retrieve user information: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session.ID = info.UserID
|
||||||
|
|
||||||
return &session, err
|
return &session, err
|
||||||
}
|
}
|
||||||
|
37
user.go
Normal file
37
user.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package roblox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserInfo struct {
|
||||||
|
UserID int `json:"UserID"`
|
||||||
|
UserName string `json:"UserName"`
|
||||||
|
RobuxBalance int `json:"RobuxBalance"`
|
||||||
|
TicketsBalance int `json:"TicketsBalance"`
|
||||||
|
ThumbnailURL string `json:"ThumbnailUrl"`
|
||||||
|
IsAnyBuildersClubMember bool `json:"IsAnyBuildersClubMember"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo will retrieve local user information
|
||||||
|
func (s *Session) GetUserInfo() (*UserInfo, error) {
|
||||||
|
resp, err := s.client.Get("http://www.roblox.com/mobileapi/userinfo")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var info UserInfo
|
||||||
|
err = json.Unmarshal(data, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user