Getting inventory contexts of Steam users - reverse-engineering

A stack overflow answer explains how to retrieve a user's public inventory
http://steamcommunity.com/profiles/<PROFILEID>/inventory/json/<APPID>/<CONTEXTID>
I read that context ID must be set as 2 to find items for most games, but this is not always the case. Is there any official API to find a user's inventory contexts? steamapis.com already has a paid API which performs this task:
{
"steamID": {
"universe": 1,
"type": 1,
"instance": 1,
"accountid": 78261062
},
"name": "PEPZ",
"onlineState": "online",
"stateMessage": "Online",
"privacyState": "public",
"visibilityState": "3",
"avatarHash": "5b702b331ddeb928225ad562a3e729aecd191b9a",
"vacBanned": false,
"tradeBanState": "None",
"isLimitedAccount": false,
"customURL": "pepzwee",
"memberSince": "2011-02-21T22:00:00.000Z",
"location": "Estonia",
"realName": "SteamApis.com Developer",
"summary": "",
"groups": [
{
"universe": 1,
"type": 7,
"instance": 0,
"accountid": 28077004
},
...
],
"primaryGroup": {
"universe": 1,
"type": 7,
"instance": 0,
"accountid": 28077004
},
"contexts": {
"440": {
"appid": 440,
"name": "Team Fortress 2",
"icon": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/440/e3f595a92552da3d664ad00277fad2107345f743.jpg",
"link": "http://steamcommunity.com/app/440",
"asset_count": 11,
"inventory_logo": "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/apps/440/e613d1d46de26ea755105b898cc8830d305353f3.png",
"trade_permissions": "FULL",
"load_failed": 0,
"rgContexts": {
"2": {
"asset_count": 11,
"id": "2",
"name": "Backpack"
}
}
},
...
}
}
Where "rgContexts" contains inventory context for each game.

I found out with some inspect element work, that there is a script tag available with the exact information you need. This is an example of my profile:
var g_rgWalletInfo = {"success":false};
var g_bInventoryIsInModalDialog = false;
var g_bIsInMarketplace = false;
UserYou.SetSteamId( '76561199033382814' );
var g_rgAppContextData = {"753":{"appid":753,"name":"Steam","icon":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/753\/135dc1ac1cd9763dfc8ad52f4e880d2ac058a36c.jpg","link":"https:\/\/steamcommunity.com\/app\/753","asset_count":303,"inventory_logo":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/753\/db8ca9e130b7b37685ab2229bf5a288aefc3f0fa.png","trade_permissions":"FULL","load_failed":0,"store_vetted":"1","rgContexts":{"6":{"asset_count":303,"id":"6","name":"Community"}}},"730":{"appid":730,"name":"Counter-Strike: Global Offensive","icon":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/730\/69f7ebe2735c366c65c0b33dae00e12dc40edbe4.jpg","link":"https:\/\/steamcommunity.com\/app\/730","asset_count":61,"inventory_logo":"https:\/\/cdn.cloudflare.steamstatic.com\/steamcommunity\/public\/images\/apps\/730\/3ab6e87a04994b900881f694284a75150e640536.png","trade_permissions":"FULL","load_failed":0,"store_vetted":"1","rgContexts":{"2":{"asset_count":61,"id":"2","name":"Backpack"}}}};
var g_strInventoryLoadURL = 'https://steamcommunity.com/id/stoplookingatmyid/inventory/json/';
$J( function() {
UserYou.LoadContexts( g_rgAppContextData );
} );
$J( function() {
var bHasPendingGifts = false;
InitInventoryPage( bHasPendingGifts, -1, false );
});
var g_bInClient = false;
var g_bInChinaRealm = false;
var g_bViewingOwnProfile = false;
var g_bMarketAllowed = false;
var g_strLanguage = 'english';
var g_strCountryCode = "US";
var g_strProfileURL = 'https://steamcommunity.com/id/stoplookingatmyid';
Some of this data is junk, but g_rgAppContextData is exactly what you need in JSON format, and it just needs to be parsed if your programming language of choice. In this example, 753 is the app id of Steam, with 6 being the context id, and 730 is CSGO'S app id, with 2 as the context id. with This data won't be present if the user has a private steam inventory.

Related

Import collection using button importing same collection multiple times - Postman

I'm using Postman version 6.6.0, and trying import API collection via Run in Postman button. I have one HTML page which looks like:
<div id="hiddenEnv" class="nodisplay highlight highlight-attention">
<p>
Click the button below to import into Postman
</p>
<p>
<div class="postman-run-button"
data-postman-action="collection/import"
data-postman-var-1="abcd"></div>
<script type="text/javascript">
(function (p,o,s,t,m,a,n) {
!p[s] && (p[s] = function () { (p[t] || (p[t] = [])).push(arguments); });
!o.getElementById(s+t) && o.getElementsByTagName("head")[0].appendChild((
(n = o.createElement("script")),
(n.id = s+t), (n.async = 1), (n.src = m), n
));
}(window, document, "_pm", "PostmanRunObject", "https://run.pstmn.io/button.js"));
</script>
</p>
</div>
And js code:
$(function() {
var lastEnv;
function newEnv(name) {
debugger;
var env = {
"id": generateUUID(),
"name": "MyProject-" + name,
"values": [{
"key": "hostenv",
"value": "",
"type": "text",
"enabled": true
},
{
"key": "username",
"value": "",
"type": "text",
"enabled": true
},
{
"key": "password",
"value": "",
"type": "text",
"enabled": true
}
],
"timestamp": 1544608923,
"synced": false,
"syncedFilename": "",
"team": null,
"isDeleted": false
};
return env;
}
$('#enter-creds').on('click', function(ev) {
var options = {
"name": "sampleBasicModal",
"content": $("script#envModal").html(),
onComplete: function(ev) {
console.log(ev);
var modal = $(ev.currentTarget).closest('.modal');
var form = modal.find('form');
console.log(form);
var formArr = form.serializeArray();
var envName = _.find(formArr, {name: 'hostenv'}).value.split('.')[0];
var envOutput = newEnv(envName);
var formObj = {};
formObj.hostenv = _.find(formArr, {name: 'hostenv'}).value;
formObj.username = _.find(formArr, {name: 'username'}).value;
formObj.password = _.find(formArr, {name: 'password'}).value;
if (!_pm('env.create', 'MyProject-' + envName, formObj)) {
_pm('env.replace', 'MyProject-' + envName, formObj);
}
lastEnv = envOutput;
$('#shownEnv').remove();
$('#hiddenEnv').slideDown(750);
}
};
var inst = Olive.modal.show(options);
ev.preventDefault();
});
});
I'm able to import my collections to Postman environment. However, same collection keep adding 7 to 8 times. I couldn't find where is the issue!
Edit:
I have checked it few times and then found that issue occurred when I have multiple environments.
After discussing this issue with a Postman team member, they found that there is an issue in the Postman with Windows OS, here is the reported link
Collection getting imported multiple times when using RiP button [Windows]

How to convert JSON/Dynamic Structure to Map in Haxe?

I'm a very new to coding and generally work with a drag and drop editor that is based on Haxe (Stencyl) as a hobby.
I have a JSON file that I would like to convert into a nested map (dictionary). I have tried using the JSON parsing function but it returns an anonymous (dynamic) structure.
How can I either convert the JSON file into a map or convert the Anonymous structure into a map?
Sample of the JSON:
{
"apple": {
"value": 10,
"health": 15,
"tags": [
"fruit",
"fiber",
"sweet"
]
},
"lemon": {
"value": 5,
"health": 10,
"tags": [
"fruit",
"citrus",
"sour"
]
},
"ham": {
"value": 50,
"health": 50,
"tags": [
"salty",
"meat"
]
}
}
Another option would be to use the json2object library, which natively supports Map<String, T>:
import sys.io.File;
import json2object.JsonParser;
class Main {
public static function main() {
var parser = new JsonParser<Data>();
var source = File.getContent("data.json");
var data = parser.fromJson(source, "data.json");
trace(data["apple"].value); // 10
}
}
typedef Data = Map<String, {
var value:Int;
var health:Int;
var tags:Array<String>;
}>
This approach avoids both reflection and Dynamic, which are usually considered bad practice.
You could create Map and fill it via Reflect api:
var parse = haxe.Json.parse(s);
var map:Map<String, StructData> = new Map();
for(field in Reflect.fields(parse))
{
map.set(field, Reflect.field(parse, field));
}
typedef StructData = {
var value:Int;
var health:Int;
var tags:Array<String>;
}
https://try.haxe.org/#DFa77
Take a look at the DynamicAccess abstract here.
Given your sample I've made a quick example here:
import haxe.DynamicAccess;
typedef Food = {
var value:Int;
var health:Int;
var tags:Array<String>;
}
class Test {
static function main() {
var json = {
"apple": {
"value": 10,
"health": 15,
"tags": [
"fruit",
"fiber",
"sweet"
]
},
"lemon": {
"value": 5,
"health": 10,
"tags": [
"fruit",
"citrus",
"sour"
]
},
"ham": {
"value": 50,
"health": 50,
"tags": [
"salty",
"meat"
]
}
};
var foodMap:DynamicAccess<Food> = json;
// Get a single entry
var apple = foodMap.get("apple");
trace(apple.tags.join(", "));
// Loop through names
for (foodName in foodMap.keys()) {
trace(foodName);
trace(foodMap.get(foodName).value);
}
}
}

Unable to get the length of JSON object

I am getting 'TypeError: Cannot convert undefined or null to object' while trying to access the length of json object in nodejs.
Following is how my data looks like:
{
"college": [
{
"colleges": [],
"department": [
1,
2,
3
],
"general_course": [],
"id": 1,
"name": "College of the Arts",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1919"
},
{
"colleges": [],
"department": [
4,
5,
6
],
"general_course": [],
"id": 2,
"name": "College of Communications",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1920"
},
{
"colleges": [],
"department": [
7,
12
],
"general_course": [],
"id": 3,
"name": "College of Education",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1921"
},
{
"colleges": [],
"department": [
13,
17,
19
],
"general_course": [],
"id": 4,
"name": "College of Engineering and Computer Science",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1922"
},
{
"colleges": [],
"department": [
20,
26,
27
],
"general_course": [],
"id": 5,
"name": "College of Health and Human Development",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1923"
},
{
"colleges": [],
"department": [
28,
29,
32,
48
],
"general_course": [],
"id": 6,
"name": "College of Humanities and Social Sciences",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1924"
},
{
"colleges": [],
"department": [
52,
57
],
"general_course": [],
"id": 7,
"name": "College of Natural Sciences and Mathematics",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1925"
},
{
"colleges": [],
"department": [
58,
59,
63
],
"general_course": [],
"id": 8,
"name": "Mihaylo College of Business and Economics",
"short_name": "",
"url": "/content.php?catoid=16&navoid=1926"
}
]
}
Step 1 - Parsing it into nodejs:
let colleges = JSON.parse(data)
Step 2 - Saving it into the dialogflow app data:
app.data.collegeData = data;
Step 3 - Accessing the length:
let collegeLength = Object.keys(app.data.collegeData.college).length;
Getting following error in firebase console:
TypeError: Cannot convert undefined or null to object
Update:
Here is the code:
if ( app.data.collegeData === undefined ){
app.data.collegeData = [];
}
**Step 1 =>**
showColleges(college);
**Step 2 =>**
function showColleges(collegeName){
if (app.data.collegeData.length === 0){
getCollegeData().then(buildSingleCollegeResponse(collegeName))
.catch(function (err){
console.log('No college data')
console.log(err)
});
}
else{
buildSingleCollegeResponse(collegeName);
}
}
**Step 3 =>**
function getCollegeData(){
console.log('Inside get College Data')
return requestAPI(URL)
.then(function (data) {
let colleges = JSON.parse(data)
if (colleges.hasOwnProperty('college')){
saveData(colleges)
}
return null;
})
.catch(function (err) {
console.log('No college data')
console.log(err)
});
}
**Step 4 =>**
function saveData(data){
app.data.collegeData = data;
console.log(app.data.collegeData)
}
**Step 5 =>**
function buildSingleCollegeResponse(collegeName){
let responseToUser, text;
//console.log('Data is -> '+ Object.keys(app.data.collegeData.college).length);
//console.log('Length is -> '+ app.data.collegeData.college.length);
console.log('Count is -> '+app.data.collegeCount);
let collegeLength = Object.keys(app.data.collegeData.college).length;
if ( collegeLength === 0){
responseToUser = 'No colleges available at this time';
text = 'No colleges available at this time';
}
else if ( app.data.collegeCount < collegeLength ){
for ( var i = 1; i <= collegeLength; i++)
{
console.log('All Colleges:: '+app.data.collegeData.college[i])
let coll = app.data.collegeData.college[i]
let name = coll.name
console.log('checkCollegeExist => College Name:: '+ name)
console.log('checkCollegeExist => Parameter => College Name:: '+collegeName)
if(String(name).valueOf() === String(collegeName).valueOf()){
responseToUser = 'Yes! CSUF has '+collegeName;
text = 'Yes! CSUF has '+collegeName;
}else{
responseToUser = 'CSUF does not teach ' +collegeName+' currently';
text = 'CSUF does not teach ' +collegeName+' currently';
}
}
}
else{
responseToUser = 'No more colleges';
}
if (requestSource === googleAssistantRequest) {
sendGoogleResponse(responseToUser);
} else {
sendResponse(text);
}
}
This is the culprit:
getCollegeData().then(buildSingleCollegeResponse(collegeName))
That calls buildSingleCollegeResponse(collegeName) and then passes its return value into then, just like foo(bar()) calls bar and passes its return value into foo.
You wanted to pass a functon to then:
getCollegeData().then(() => buildSingleCollegeResponse(collegeName))
// An arrow function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that now that it's clear from the updated question that app.data.collegeData.college is an array, there's no need for Object.keys. Change:
let collegeLength = Object.keys(app.data.collegeData.college).length;
to simply
let collegeLength = app.data.collegeData.college.length;
Arrays have a length property (whereas non-array objects don't, by default).
You haven't mentioned what value app.data holds before issuing app.data.collegeData = data;
If app.data is undefined you should try app.data = {collegeData: data}
Or else negating what app stores. Following works
app = {};
app.data = {};
app.data.collegeData = data;
app.data.collegeData.college.length
You don't need to do the following
let collegeLength = Object.keys(app.data.collegeData.college).length;
Update: Refer to https://jsfiddle.net/dmxuum79/3/

How to loop through JSON object?

How can we loop through given JSON object to traverse all its properties:
<script type="text/javascript">
var students = '{"name": "John", "age": 30, "subjects": [{ "name": "IT", "marks": 85 }, { "name": "Maths", "marks": 75 }, { "name": "English", "marks": 60 }]}';
var myObj = JSON.parse(students);
alert(myObj.name);
alert(myObj.age);
alert(myObj.subjects[0]['name']);
alert(myObj.subjects[0]['marks']);
alert(myObj.subjects[1]['name']);
alert(myObj.subjects[1]['marks']);
alert(myObj.subjects[2]['name']);
alert(myObj.subjects[2]['marks']);
</script>
You can see I am accessing nested "subject" properties by using its index and property name. But the code becomes lengthy to traverse each items. To avoid it, I am wondering how to loop (e.g. for in loop) through by writing single line of code to access all its properties?
You could do this:
var myObj = JSON.parse(students);
for(var index = 0; index < myObj.subjects.length; index++) {
alert(myObj.subjects[index]['name']);
alert(myObj.subjects[index]['marks']);
}
Just use Each function to iterate the each subjects
var students = '{"name": "John", "age": 30, "subjects": [{ "name": "IT", "marks": 85 }, { "name": "Maths", "marks": 75 }, { "name": "English", "marks": 60 }]}';
var myObj = JSON.parse(students);
$.each(myObj['subjects'], function(index, value) {
console.log(value['name']+" "+ value['marks']);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
try using stringify
var myObj = JSON.stringify(students);
for(var index=0;index < myObj.subjects.length;index++) {
alert ( myObj.subjects[index] );
}

Dynamically Parsing JSON with Groovy

I have a JSON document pulled back from a support system API. With my code, I want to pull out the pre-configured fields dynamically, presuming that the JSON may have more or fewer of the desired fields when my program calls the API.
I have some code that works, though it seems very convoluted and inefficient.
Here is a snippet of the pieces of JSON that I'm interested in:
{
"rows": [
{
"assignee_id": 1,
"created": "2017-01-25T14:13:19Z",
"custom_fields": [],
"fields": [],
"group_id": 2468,
"priority": "Low",
"requester_id": 2,
"status": "Open",
"subject": "Support request",
"ticket": {
"description": "Ticket descritpion",
"id": 1000,
"last_comment": {
"author_id": 2,
"body": "Arbitrary text",
"created_at": "2017-02-09T14:21:38Z",
"public": false
},
"priority": "low",
"status": "open",
"subject": "Support request",
"type": "incident",
"url": "Arbitrary URL"
},
"updated": "2017-02-09T14:21:38Z",
"updated_by_type": "Agent"
},
{
"assignee_id": 1,
"created": "2017-02-09T14:00:18Z",
"custom_fields": [],
"fields": [],
"group_id": 3579,
"priority": "Normal",
"requester_id": 15,
"status": "Open",
"subject": "Change request",
"ticket": {
"description": "I want to change this...",
"id": 1001,
"last_comment": {
"author_id": 20,
"body": "I want to change the CSS on my website",
"created_at": "2017-02-09T14:12:12Z",
"public": true
},
"priority": "normal",
"status": "open",
"subject": "Change request",
"type": "incident",
"url": "Arbitrary URL"
},
"updated": "2017-02-09T14:12:12Z",
"updated_by_type": "Agent"
}
]
}
I have an ArrayList called wantedFields that I build up from a config to define which information I want to pull out from the JSON:
["id","subject","requester_id","status","priority","updated","url"]
The complexity is that data is replicated in the API, and I only want to pull out data once, with a preference for the data in "rows" where applicable. My method for doing this is below. It feels like I'm repeating code but I can't really see how to make this work more efficiently. The JSON is held as "viewAsJson".
def ArrayList<Map<String,Object>> assignConfiguredFields(viewAsJson, wantedFields) {
//Pull out configured fields from JSON and store as Map to write as CSV later
ArrayList<Map<String,Object>> listOfDataToWrite = new ArrayList<Map<String,Object>>()
ArrayList<String> rowKeyList = new ArrayList<String>()
def validationRow = viewAsJson.rows.get(0)
//Compare one row object to config first
validationRow.each { k, v ->
if (wantedFields.contains(k)) {
wantedFields.remove(k)
rowKeyList.add(k)
}
}
ArrayList<String> ticketKeyList = new ArrayList<String>()
def validationTicket = viewAsJson.rows.ticket.get(0)
//Compare one ticket object to config first
validationTicket.each { k, v ->
if (wantedFields.contains(k)) {
wantedFields.remove(k)
ticketKeyList.add(k)
}
}
def rows = viewAsJson.rows
def tickets = viewAsJson.rows.ticket
//Pull matching ticket objects from JSON and store in Map
ArrayList<Map<String,Object>> tickList= new ArrayList<>()
ArrayList<Map<String,Object>> rowList= new ArrayList<>()
rows.each { row ->
Map<String,Object> rowMap = new HashMap<>()
row.each { k, v ->
if(rowKeyList.contains(k))
rowMap.put(k,v)
}
rowList.add(rowMap)
}
tickets.each { ticket ->
Map<String,Object> ticketMap = new HashMap<>()
ticket.each { k, v ->
if(ticketKeyList.contains(k))
ticketMap.put(k, v)
}
tickList.add(ticketMap)
}
for (int i = 0; i < rowList.size(); i++) {
HashMap<String,Object> dataMap = new HashMap<>()
dataMap.putAll(rowList.get(i))
dataMap.putAll(tickList.get(i))
listOfDataToWrite.add(dataMap)
}
println listOfDataToWrite
return listOfDataToWrite
}
I know there should be some validation for if the wantedFields ArrayList is still populated. I've iterated on this code so many times I just forgot to re-add that this time.
I don't know if you still need this code but why not try something like this.
Have a translation map and run each row through it.
Object tranverseMapForValue(Map source, String keysToTranverse, Integer location = 0){
List keysToTranverseList = keysToTranverse.split(/\./)
tranverseMapForValue(source, keysToTranverseList, location)
}
Object tranverseMapForValue(Map source, List keysToTranverse, Integer location = 0){
if(source.isEmpty() || keysToTranverse.isEmpty()){
return null
}
String key = keysToTranverse[location]
if(source[key] instanceof Map){
return tranverseMapForValue(source[key], keysToTranverse, location + 1)
}
else{
return source[key]
}
}
Map translation = [
"ticket.id": "id",
"ticket.subject": "subject",
"requester_id": "requester_id",
"ticket.status": "status",
"priority": "priority",
"updated": "updated",
"ticket.url": "url"
]
List rows = []
json.rows.each{ row ->
Map mapForRow = [:]
translation.each{ sourceKey, newKey ->
mapForRow << [(newKey): tranverseMapForValue(row, sourceKey)]
}
rows.add(mapForRow)
}