Using Valve/Steam API to get multiple IDs converted - php

So this is a VERY long explanation.
I have a Counter-Strike: Source server, with an in-game plugin for a store. This store saves its data in a MySQL Database (for this instance, named 'store'). The store keeps track of player's money in that database (on column 'credits' in table 'users'). It stores the clients based on a 'steam_id' (unique to every client)
The format of a 'steam_id' is (example): STEAM_0:0:123456789 OR STEAM_0:1:12345789.
My page that I have displays the top 1000 users from the database (sorted by credits).
My Problem: I need to convert these ugly steam_id's to actual names.
Where I am right now:
Steam API Documentation
According to the API documentation, I have to use 'community ids' when I query the API. If I want to get more than one user, I can use commas to separate community ids in the GET string.
(http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=APIKEY&steamids=76561197960435530,76561197960435531&format=json)
I have a function that converts the steam_id's to API-acceptable ID's.
function SteamID2CommunityID($steam_id){
$parts = explode(':', str_replace('STEAM_', '' ,$id));
$communityID = bcadd(bcadd('76561197960265728', $parts['1']), bcmul($parts['2'], '2'));
return $communityID;
}
With that, I can make my list of comma separated community ids with this:
while ($row = $mysqli->fetch_assoc($request)) {
$ids .= ',' . SteamID2CommunityID($row['steamid']) . ',';
}
Now for the tricky part, all these values come back in one JSON array. I need to add something, so when I display my data, I can convert a 'steam_id' straight to a 'name' (with the existing array).
Example of an output (most keys & values are removed to make it readable)
Array (
[response] => Array
(
[players] => Array
(
[0] => Array
(
[steamid] => 76561198010207577
[personaname] => [rGA] Stainbow
)
[1] => Array
(
[steamid] => 76561197966653036
[personaname] => |K}{R|Mastarious(MNBH)
)
)
)
)
So again, how would I go about going straight from a 'steam_id' to a name?
Thank you to anybody who can provide code and/or suggestions!

This is a variant duplicate of another Stack Overflow question, which is more practical and less localized, but I might as well answer this.
Assuming that your input steam_id is $INPUT and your final output array is stored in $OUTPUT, this is the functional foreach approach that you could use to convert steam_id to personaname:
/**
* Convert steam_id to personaname
* #returns STRING The name associated with the given steam_id
* BOOL FALSE if no match was found
*/
function steamID_to_name($INPUT, $OUTPUT)
{
// This gets the relevant part of the API response.
$array = $OUTPUT['response']['players'];
// Using your function to convert `steam_id` to a community ID
$community_id = SteamID2CommunityID($INPUT);
// Linear search
foreach ($array as $array_item)
{
// If a match was found...
if ($community_id == $array_item['steamid'])
// Return the name
return $array_item['personaname'];
}
// If no match was found, return FALSE.
return false;
}

Related

PHP sort list of subdomains by domain

I have a list of domains (array)
sub1.dom1.tld1
sub2.dom2.tld2
sub1.sub2.dom1.tld1
sub3.dom1.tld3
I want to achieve the following:
dom1.tld1
-> sub1.dom1.tld1
-> sub2.dom1.tld1
--> sub1.sub2.dom1.tld1
dom2.tld2
-> sub2.dom2.tld2
dom1.tld3
-> sub3.dom1.tld3
I have tried to adapt this, but it doesn't really fit:
How to alphabetically sort a php array after a certain character in a string
I would appreciate any kind of help.
I've had to attack a similar headache before. In the short term I flip the order of the domain components and use a hidden sorting column in a table/view:
$sortstring = implode('.',array_reverse(explode('.', $domain)));
In the long term I saved the reverse format of the domain records before saving changes to the DB into a computed field/column so that it didn't have to be re-computed every time the domain list is viewed.
If you don't want that sub-domain, just remove the last element of the array after the flip....
You can proceed like this:
$array=array(
'sub1.dom1.tld1',
'sub2.dom2.tld2',
'sub1.sub2.dom1.tld1',
'sub2.sub2.dom1.tld1',
'sub3.sub2.dom1.tld1',
'sub3.dom1.tld3');
function cmp($a,$b){
$a=array_reverse(explode('.',$a));
$b=array_reverse(explode('.',$b));
$ca=count($a);
$cb=count($b);
$string='';;
for($i=0,$c=min($ca,$cb);$i<$c;$i++){
$result=strnatcmp($a[$i],$b[$i]);
if($result!==0) return $result;
}
return $result;
}
usort($array,'cmp');
print_r($array);
and the output is:
Array
(
[0] => sub1.dom1.tld1
[1] => sub1.sub2.dom1.tld1
[2] => sub2.sub2.dom1.tld1
[3] => sub3.sub2.dom1.tld1
[4] => sub2.dom2.tld2
[5] => sub3.dom1.tld3
)
Here is an approach similar to #Elementary answer combine to #CBO one:
$domains = [
'sub.bbb.com',
'www.aaa.com',
'*.zzz.com',
'aaa.com',
'*.sub.bbb.com',
'zzz.com',
'beta.bbb.com',
'bbb.com',
'aaa.fr',
];
// #see https://stackoverflow.com/a/61461912/1731473
$computeDomainToSort = static function (string $domain): string {
return \implode(
'.',
array_reverse(
explode('.', $domain,
// Keep the base domain.tld collapsed for comparison.
substr_count($domain, '.')
)
)
);
};
\usort($this->domains, static function (string $domain1, string $domain2) use ($computeDomainToSort): int {
$domain1 = $computeDomainToSort($domain1);
$domain2 = $computeDomainToSort($domain2);
return strnatcmp($domain1, $domain2);
});
That way, given domains will be sorted like this:
aaa.com
www.aaa.com
aaa.fr
bbb.com
beta.bbb.com
sub.bbb.com
*.sub.bbb.com
zzz.com
*.zzz.com
The main difference is on the $computeDomainToSort lambda function, where I keep the base domain.tld onto one piece to have a more natural sorting.

How do I insert my imploded array into my database?

I'm trying to update permissions of userroles in my application.
Everything works the way I want untill I want to insert the changes into my database.
$permission = $_POST['permission'];
$permissiondb = implode(",", $permission);
print_r($permission)
print_r($permissiondb);
The permission print shows this:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 6 [4] => 5 [5] => 4 )
The permissiondb print shows this:
1,2,3,6,5,4
my db query is:
INSERT INTO give_permissions (userrole, permission_id) VALUES ($userrole, $permissions);
When I send the values to my database it inserts a ' 0 ' at the wanted userrole, but instead
I want the system to put in all permissions for the userrole.
I hope I gave enough code for you to help me... can someone help me with this?
You have a list of ids which are being stored in permission_id which suggests that its setup to take a single integer? Thus a list of ids will not work.
a) Change your data type to varchar and wrap $permissions with '$permissions'.
By using this method you would stick with implode(",", $permissions) but there is a better way.
// Your example with modifications
$permission = $_POST['permission'];
$permissiondb = implode(",", $permission);
// INSERT INTO give_permissions (userrole, permission_id)
// VALUES ($userrole, '$permissiondb');
b) Change your data type to varchar and use 'json_encode($permissions)' - This would be the preferable option by many as a shortcut.
When you use json_encode() you store it in a more manageable way. When you encode it you will receive a string in the format of [{1},{2},...] which you can drop into your table quite nicely.
So what about later on when you want to retrieve that permissions list? You use json_decode($permissions) which will then give you a JSON array. For your purposes its easier to cast that json array to a standard array (array)json_decode($permissions) which will take that [{}] string and give you a perfectly standard array(1,2,3,...).
// Your example with modifications
$permission = $_POST['permission'];
$permissiondb = json_encode($permission);
// INSERT INTO give_permissions (userrole, permission_id)
// VALUES ($userrole, '$permissiondb');
c) Setup a corresponding table to take each id and link them. - This would be the perfect ideal.
Change permission data type int to varchar and try this
INSERT INTO give_permissions (userrole, permission_id) VALUES ($userrole, $permissions);

PHP find the array index key of multi dimensional array to update array

I am trying to come up with a means of working with what could potentially be very large array sets. What I am doing is working with the facebook graph api.
So when a user signs up for a service that I am building, I store their facebook id in a table in my service. The point of this is to allow a user who signs up for my service to find friends of their's who are on facebook and have also signed up through my service to find one another easier.
What I am trying to do currently is take the object that the facebook api returns for the /me/friends data and pass that to a function that I have building a query to my DB for the ID's found in the FB data which works fine. Also while this whole bit is going on I have an array of just facebook id's building up so I can use them in an in_array scenario. As my query only returns facebook id's found matching
While this data is looping through itself to create the query I also update the object to contain one more key/value pair per item on the list which is "are_friends"=> false So far to this point it all works smooth and relatively fast, and I have my query results. Which I am looping over.
So I am at a part where I want to avoid having a loop within a loop. This is where the in_array() bit comes in. Since I created the array of stored fb id's I can now loop over my results to see if there's a match, and in that event I want to take the original object that I appended 'are_friends'=>false to and change the ones in that set that match to "true" instead of false. I just can't think of a good way without looping over the original array inside the loop that is the results array.
So I am hoping someone can help me come up with a solution here without that secondary loop
The array up to this point that starts off as the original looks like
Array(
[data](
[0] => array(
are_fb_friends => false
name => user name
id => 1000
)
[1] => array(
are_fb_friends => false
name => user name
id => 2000
)
[2] => array(
are_fb_friends => false
name => user name
id => 3000
)
)
)
As per request
This is my current code logic, that I am attempting to describe above..
public function fromFB($arr = array())
{
$new_arr = array();
if((is_array($arr))&&(count($arr) > 0))
{
$this->db->select()->from(MEMB_BASIC);
$first_pass = 0;
for($i=0;$i < count($arr);$i++)
{
$arr[$i]['are_fb_friends'] = "false";
$new_arr[] = $arr[$i]['id'];
if($first_pass == 0)
{
$this->db->where('facebookID', $arr[$i]['id']);
}
else
{
$this->db->or_where('facebookID', $arr[$i]['id']);
}
$first_pass++;
}
$this->db->limit(count($arr));
$query = $this->db->get();
if($query->num_rows() > 0)
{
$result = $query->result();
foreach($result as $row)
{
if(in_array($row->facebookID, $new_arr))
{
array_keys($arr, "blue");
}
}
}
}
return $arr;
}
To search a value and get its key in an array, you can use the array_search function which returns the key of the element.
$found_key = array_search($needle, $array);
For multidimensional array search in PHP look at https://stackoverflow.com/a/8102246/648044.
If you're worried about optimization I think you have to try using a query on a database (with proper indexing).
By the way, are you using the Facebook Query Language? If not give it a try, it's useful.

php & mysql: most efficient method to check large array against database

I have a large set of data stored in a multi-dimensional array. An example structure is as below:
Array
(
[1] => Array
(
[0] => motomummy.com
[1] => 1921
[2] => 473
)
[4] => Array
(
[0] => kneedraggers.com
[1] => 3051
[2] => 5067
)
)
I also have a table in a mysql database that currently contains ~80K domain names. This list will grow monthly by possibly ~10K+ domain names. The goal is to compare Array[][0] (the domain name) against the mysql database and return an array with preserved values (but key preservation is not important) that only contains unique values.
Please note, that I only want to compare the first index alone, NOT the entire array.
The initial multi-dimensional array is assumed to be enormous in size (more than likely anywhere from 100k to 10 million results). What is the best way to get data back that is not contained in the database?
What I am doing now is simply storing to an array, the complete list of domains from the database, then using the following function, comparing each value in the initial array against the database array. This is horribly slow and inefficient obviously.
// get result of custom comparison function
$clean = array_filter($INITIAL_LIST, function($elem) {
$wordOkay = true;
// check every word in "filter from database" list, store it only if not in list
foreach ($this->domains as $domain) {
if (stripos($elem[0], $domain) !== false) {
$wordOkay = false;
break;
}
}
return $wordOkay;
});
Some pseudo code or even actual code would be very helpful at this point.
Use the DBMS! It was made for stuff like that.
Create a temporary table temp { id (fill with array index); url (filled with url)}
Fill it with your array's data
Ideally create an index on temp.url
Query the database:
SELECT * FROM `temp` LEFT JOIN `urls`
WHERE urls.url = temp.url AND urls.url IS NULL;
(the table urls is your existing data)

PHP Arrays, Serialization and Unserialization

I have a problem. I have a website with people and different transactions they make to and from a fake online bank. I want to be able to store an array of each person's transactions on my mysql database. I want each transaction to be defined as an associative array with a timestamp and the sql query that represents their transaction with the "bank".
Then I want those, after being serialized, to be the values of a transactions array that holds all of their transactions. Then I want to serialize that and store it in the database so that later I can add a transaction by unserializing it and appending a serialized array of another transaction to it. So far this code below works except that it just overwrites the one transaction and doesn't append a new one. I'd really appreciate any help.
Thanks in advance
function modify_transactions($row, $sql)
{
$sql=mysql_real_escape_string($sql);
if(isset($row["TRANSACTIONS"]))
{
$transactions = unserialize($row["TRANSACTIONS"]);
}
else
{
$transactions = array();
}
$transaction_array = array("timestamp"=>time(),"query"=>$sql);
$transaction_data = serialize($transaction_array);
$transactions[] = $transaction_data;
$transactions_upload = serialize($transactions);
$name = $row["NAME"];
$query = "UPDATE band.students SET TRANSACTIONS = '$transactions_upload' WHERE students.NAME = '$name'";
mysql_query($query);
}
If I were you, I'd rather go for a new table where every entry would represent a transaction and that had a foreign key student_id.
That'd be much, much, much cleaner and more flexible and scalable (i.e. what if you want to show the last 3 transactions of user X? What if a user had several million transactions?).
First, you don't need to serialize each array, then serialize again. Serialize is recursive:
$array = array(
array(
'1',
array()
),
array(
'2',
array()
)
);
$serialized = serialize($array);
$unserialized = unserialize($serialized);
echo "<pre>";
print_r($unserialized);
echo "</pre>";
Prints:
Array
(
[0] => Array
(
[0] => 1
[1] => Array
(
)
)
[1] => Array
(
[0] => 2
[1] => Array
(
)
)
)
So just serialize right before inserting into the database.
Second, you should change your database structure. Like vzwick mentioned, create a new table with a foreign key of the student. That way each entry represents a transaction.
Also, why are you storing the actual SQL query? That doesn't make any sense to me. Why don't you actually make a fake transaction?

Categories