Пример #1
0
// GetLatestModel returns the asset id of the latest model for a given user.
// While this is useful for retrieving the asset id of a newly created model
// that was just uploaded, it is not necessarily reliable for this purpose.
func GetLatestModel(client *rbxweb.Client, userId int32) (assetId int64, err error) {
	if userId == 0 {
		return 0, errors.New("invalid user id")
	}

	query := url.Values{
		"Category":          {"Models"},
		"SortType":          {"RecentlyUpdated"},
		"IncludeNotForSale": {"true"},
		"ResultsPerPage":    {"1"},
		"CreatorID":         {client.I32toa(userId)},
	}
	resp, err := client.Get(client.GetURL(`api`, `/catalog/json`, query))
	if err = client.AssertResp(resp, err); err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	var asset []struct {
		AssetId int64
	}
	if err = dec.Decode(&asset); err != nil {
		return 0, errors.New("JSON decode failed: " + err.Error())
	}
	return asset[0].AssetId, nil
}
Пример #2
0
// Wall posts a message to a group wall. The account the client is logged into
// must have a group role that has permission to post to the group's wall.
//
// This function requires the client to be logged in.
func Wall(client *rbxweb.Client, groupID int32, message string) (success bool) {
	page := client.GetURL(`www`, `/My/Groups.aspx`, url.Values{"gid": {client.I32toa(groupID)}})
	err := client.DoRawPost(page, url.Values{
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$GroupWallPane$NewPost":                       {message},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$GroupWallPane$NewPostButton":                 {},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$rbxGroupRoleSetMembersPane$currentRoleSetID": {},
	})
	if err != nil {
		return false
	}
	return true
}
Пример #3
0
// Search is used to perform a search query for Roblox assets.
func Search(client *rbxweb.Client, query Query) (result []Result, err error) {
	values := convertQuery(query)
	resp, err := client.Get(client.GetURL(`www`, `/catalog/json`, values))
	if err = client.AssertResp(resp, err); err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	dec.Decode(&result)
	return
}
Пример #4
0
// GetInfo returns information about an asset, given an asset id.
func GetInfo(client *rbxweb.Client, id int64) (info Info, err error) {
	query := url.Values{
		"assetId": {client.I64toa(id)},
	}
	resp, err := client.Get(client.GetURL(`api`, `/marketplace/productinfo`, query))
	if err = client.AssertResp(resp, err); err != nil {
		return Info{}, err
	}
	defer resp.Body.Close()

	dec := json.NewDecoder(resp.Body)
	dec.Decode(&info)
	return
}
Пример #5
0
// Add adds an asset to a set. The set must belong to the current user, and
// the asset must be addable to sets.
//
// This function requires the client to be logged in.
func Add(client *rbxweb.Client, assetId int64, setId int32) (err error) {
	query := url.Values{
		"rqtype":  {"addtoset"},
		"assetId": {client.I64toa(assetId)},
		"setId":   {client.I32toa(setId)},
	}

	resp, err := client.Post(client.GetURL(`www`, `/Sets/SetHandler.ashx`, query), "", nil)
	if err = client.AssertResp(resp, err); err != nil {
		return err
	}
	resp.Body.Close()
	return nil
}
Пример #6
0
// UpdatePlace uploads data from `reader` to Roblox as a Place asset.
// `placeId` must be the id of an existing place. This function cannot create
// a new place.
//
// This function requires the client to be logged in.
func UpdatePlace(client *rbxweb.Client, reader io.Reader, placeId int64) (err error) {
	query := url.Values{
		"assetid": {client.I64toa(placeId)},
		"type":    {"Place"},
	}
	buf := new(bytes.Buffer)
	buf.ReadFrom(reader)
	req, _ := http.NewRequest("POST", client.GetURL(`www`, `/Data/Upload.ashx`, query), buf)
	req.Header.Set("User-Agent", "Roblox")

	resp, err := client.Do(req)
	if err = client.AssertResp(resp, err); err != nil {
		return err
	}
	defer resp.Body.Close()
	return nil
}
Пример #7
0
// Upload generically uploads data from `reader` as an asset to the ROBLOX
// website. `info` can be used to specify information about the model. The
// following parameters are known:
//
//     type           - The type of asset.
//     assetid        - The id of the asset to update. 0 uploads a new asset.
//     name           - The name of the asset.
//     description    - The asset's description.
//     genreTypeId    - The asset's genre.
//     isPublic       - Whether the asset can be taken by other users.
//     allowComments  - Whether users can comment on the asset.
//
// The success of this function is highly dependent on these parameters. For
// example, most asset types may only be uploaded by authorized users.
// Parameters that specify information about the asset only apply for new
// assets. That is, updating an asset will only update the contents, but not
// the information about it.
//
// `assetVersionId` is the version id of the uploaded asset. This is unique
// for each upload. This can be used with GetIdFromVersion to get the asset
// id.
//
// This function requires the client to be logged in.
func Upload(client *rbxweb.Client, reader io.Reader, info url.Values) (assetVersionId int64, err error) {
	buf := new(bytes.Buffer)
	buf.ReadFrom(reader)
	req, _ := http.NewRequest("POST", client.GetURL(`www`, `/Data/Upload.ashx`, info), buf)
	req.Header.Set("User-Agent", "roblox/rbxweb")

	resp, err := client.Do(req)
	if err = client.AssertResp(resp, err); err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	r := new(bytes.Buffer)
	r.ReadFrom(resp.Body)
	assetVersionId, _ = client.Atoi64(r.String())

	return assetVersionId, err
}
Пример #8
0
// GetIdFromVersion returns an asset id from an asset version id.
func GetIdFromVersion(client *rbxweb.Client, assetVersionId int64) (assetId int64, err error) {
	query := url.Values{
		"avid": {client.I64toa(assetVersionId)},
	}

	// This relies on how asset names are converted to url names. Currently,
	// if an asset name is "_", its url becomes "unnamed".
	req, _ := http.NewRequest("HEAD", client.GetURL(`www`, `/_-item`, query), nil)
	resp, err := client.Do(req)
	if err = client.AssertResp(resp, err); err != nil {
		return 0, err
	}
	resp.Body.Close()

	values, err := url.ParseQuery(resp.Header.Get("Location"))
	if err = client.AssertResp(resp, err); err != nil {
		return 0, err
	}

	return client.Atoi64(values.Get("id"))
}
Пример #9
0
func TradeRobux(client *rbxweb.Client, robux int64, tickets int64, limit bool, split bool) (err error) {
	page := client.GetURL(`www`, `/My/Money.aspx`, nil)
	query := url.Values{
		"__EVENTTARGET":                                                           {"ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$SubmitTradeButton"},
		"__VIEWSTATE":                                                             {},
		"__EVENTVALIDATION":                                                       {},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$HaveCurrencyDropDownList": {"Robux"},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$HaveAmountTextBoxRestyle": {strconv.Itoa(robux)},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$WantCurrencyDropDownList": {"Tickets"},
		"ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$WantAmountTextBox":        {strconv.Itoa(tickets)},
	}
	if limit {
		query.Set("ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$OrderType", "LimitOrderRadioButton")
	} else {
		query.Set("ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$OrderType", "MarketOrderRadioButton")
	}
	if split {
		query.Set("ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$AllowSplitTradesCheckBox", "on")
	} else {
		query.Set("ctl00$ctl00$cphRoblox$cphMyRobloxContent$ctl00$AllowSplitTradesCheckBox", "off")
	}
	err = client.DoRawPost(page, query)
	return
}