Skip to content

Instantly share code, notes, and snippets.

@AzureFlow
Created January 18, 2023 01:30
Show Gist options
  • Save AzureFlow/f6f44bf0c2cab2b205a59067a1d1cd07 to your computer and use it in GitHub Desktop.
Save AzureFlow/f6f44bf0c2cab2b205a59067a1d1cd07 to your computer and use it in GitHub Desktop.
Simple Wolfram|Alpha client in PHP
<?php
use AzureFlow\WolfApi\QueryBuilder;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
require __DIR__ . '/../vendor/autoload.php';
// Docs
// https://products.wolframalpha.com/api/documentation
// https://github.com/aeurielesn/wolfram-alpha-java-binding
// https://github.com/francescomalatesta/wolframalphaphp
// https://github.com/larrabyte/bakerbot/blob/a64b2e29bafc0ab6e6c1da2d3f842667ef15af52/backends/wolfram.py
// https://github.com/scalarwaves/iloa/blob/ba20464f0df52b2c8a37d67619afebe21d17a1da/src/commands/wolfram.js#L103
// salt: EumRuvaOhx7ENr9N
// legacy: Y5H46L-2KR8T4PPQQ
// pro: Y5H46L-VGTX7EAWVP
// consumerSecretPro: kGnawxw9fUUTyD8lHUJgJ29i+M6HjzHoxCTJbwupppY=
// consumerKeyPro: kSJ68leuI9qCVleZ+Xt50uDOBkN9FlhH/c/Fh9mZF1A=
// mobileProAppApiKey: 4c83bda499424d2eb03631fe48e79cee
const API_URL = 'https://api.wolframalpha.com/v2/query.jsp';
const APP_ID = 'Y5H46L-2KR8T4PPQQ';
const APP_SALT = 'EumRuvaOhx7ENr9N';
$client = new Client([
RequestOptions::HEADERS => [
'Accept' => '*/*',
'User-Agent' => 'Wolfram|Alpha Java Binding 1.1',
'Accept-Language' => 'en-US,en;q=0.9',
],
]);
// https://products.wolframalpha.com/api/documentation?scrollTo=pod-states
// $formats = ['png','plaintext','imagemap','minput','sound'];
$formats = ['plaintext'];
// Example query
// appid: Y5H46L-2KR8T4PPQQ
// input: x^2 +5x +6=0
// banners: image
// format: png,plaintext,imagemap,minput,sound
// async: false
// scantimeout: 25.0
// podtimeout: 25.0
// formattimeout: 25.0
// countrycode: US
// languagecode: en
// sidebarlinks: true
// includepodid: Solution
// podstate: Solution__Step-by-step solution
// width: 1328
// maxwidth: 2760
// mag: 3.5
// device: Android
// sig: 57A5148397C56B4C6E3AB05F9413EE6D
$query = new QueryBuilder();
$query->add('appid', APP_ID);
$query->add('input', 'x^2 + 5x + 6 = 0');
$query->add('output', 'json');
// $query->add('banners', 'image');
// $query->add('async', 0.25);
// $query->add('scantimeout', 0.5);
// $query->add('sidebarlinks', true);
// $query->add('podtimeout', true);
// $query->add('width', 1328);
// $query->add('maxwidth', 2760);
// $query->add('mag', 3.5);
$query->add('format', implode(',', $formats));
$query->add('podstate', 'Solution__Step-by-step solution');
$query->add('podstate', 'Solution__Use factor method');
$query->add('includepodid', 'Solution');
// $query->add('countrycode', 'US');
// $query->add('languagecode', 'en');
$query->add('device', 'Android');
$resp = $client->get(API_URL, [
RequestOptions::QUERY => $query->build(),
]);
$result = json_decode($resp->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR)['queryresult'];
if($result['numpods'] > 0)
{
echo end($result['pods'][0]['subpods'])['plaintext'] . PHP_EOL;
}
else
{
$msg = isset($result['error']) ? $result['error']['msg'] : 'N/A';
echo "ERROR: $msg" . PHP_EOL;
}
<?php declare(strict_types=1);
namespace AzureFlow\WolfApi;
class QueryBuilder
{
private array $parts = [];
public function add(string $key, mixed $value): void
{
$this->parts[] = [
'key' => $key,
'value' => (string) $value,
];
}
public function build(): string
{
usort($this->parts, static function($item1, $item2) {
return strnatcmp($item1['key'], $item2['key']);
});
$queryString = implode(
'&',
array_map(static function($part) {
return urlencode($part['key']) . '=' . urlencode($part['value']);
}, $this->parts)
);
$sigString = $this->generateSignature();
return "$queryString&sig=$sigString";
}
public function __toString()
{
return $this->build();
}
protected function generateSignature(): string
{
$queryStr = implode(
'',
array_map(static function($part) {
return urlencode($part['key']) . urlencode($part['value']);
}, $this->parts)
);
return strtoupper(md5(APP_SALT . $queryStr));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment