<?php
use Abraham\TwitterOAuth\TwitterOAuth;
use GuzzleHttp\Client;
if (isset ($_GET['callback'])) {
header("Content-type: text/javascript");
} else {
header("Content-type: application/json");
}
include_once 'common.php';
function searchTwitter($token, $request_vars) {
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $token['oauth_token'], $token['oauth_token_secret']);
$statuses = $connection->get("search/tweets", $request_vars);
return array_map(function($tweet) {
$res = $tweet;
$res['type'] = "Twitter";
return $res;
}, $statuses);
}
function searchMastodon($token, $request_vars, $domain) {
$mapTootDomain = function($toot) use ($domain) {
return mapToot($toot, $domain);
};
$tag = $request_vars['q'] ?? false;
$rv = [
'limit' => min(intval($request_vars['count'] ?? 40), 40),
];
if ($request_vars['since_id'] ?? false) {
$rv['since_id'] = $request_vars['since_id'];
}
if(!$tag) {
return ["statuses" => []];
}
$client = new Client([
'base_uri' => "https://$domain",
'timeout' => 2.0,
]);
$resp = $client->get("/api/v1/timelines/tag/".ltrim($tag, '#'),[
"headers" => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
"query" => $rv
]);
$body = (string)($resp->getBody());
$statuses = json_decode($body, true);
return ["statuses" => array_map($mapTootDomain, $statuses)];
}
function buildUsernameWithDomain($acct, $domain) {
return str_contains($acct, '@')?$acct:"$acct@$domain";
}
function getFullText($toot) {
if ($toot['reblog']) {
return $toot['reblog']['content'];
}
return $toot['content'];
}
function getRetweetedStatus($toot) {
$reblog = $toot["reblog"];
if (!$reblog) {
return null;
}
return ['id_str' => strval($reblog['id'])];
}
function buildUser($account, $domain) {
return [
"id" => strval($account['id']),
"screen_name" => buildUsernameWithDomain($account['acct'], $domain),
"name" => $account['display_name'],
"profile_image_url_https" => $account['avatar'],
"url" => $account['url']
];
}
function mapToot($toot, $domain) {
$new_obj = [
'type' => 'Mastodon',
'id' => strval($toot['id']),
'from_user' => buildUsernameWithDomain($toot["account"]["acct"],$domain),
'user' => buildUser($toot["account"], $domain),
'from_user_id' => strval($toot["account"]["id"]),
'in_reply_to_status_id' => $toot["in_reply_to_id"]?strval($toot["in_reply_to_id"]):null,
'created_at' => $toot['created_at'],
'full_text' => getFullText($toot),
'retweeted_status' => getRetweetedStatus($toot),
'url' => $toot['url'],
'uri' => $toot['uri'],
];
return $new_obj;
}
$cacheDriver = new Stash\Driver\Sqlite(array('path' => sys_get_temp_dir()."/polemictweet_cache.db"));
$cachePool = new Stash\Pool($cacheDriver);
/**
* Check for a POSTed status message to send to Twitter
*/
if (!empty($_GET)
&& isset($_SESSION['SOCIAL_ACCESS_TOKEN'])) {
$socialNetwork = isset($_GET['social_network'])?$_GET['social_network']:"Twitter";
$request_vars = array_filter($_GET,fn ($key) => $key != 'social_network', ARRAY_FILTER_USE_KEY);
$itemCachePath="search/tweets?" . http_build_query($request_vars) . "_" . $_SESSION['SOCIAL_ACCESS_TOKEN'];
$cachedStatusesResp = $cachePool->getItem($itemCachePath);
$statusesStr = $cachedStatusesResp->get();
if ($cachedStatusesResp->isMiss()) {
$cachedStatusesResp->lock();
$token = unserialize($_SESSION['SOCIAL_ACCESS_TOKEN']);
$statuses = [];
if ($socialNetwork == "Twitter") {
$statuses = searchTwitter($token, $request_vars);
} else if ($socialNetwork == "Mastodon") {
$statuses = searchMastodon($token, $request_vars, $_SESSION['SOCIAL_LOGIN_DOMAIN']);
}
$statusesStr = json_encode($statuses);
$cachedStatusesResp->set($statusesStr)->expiresAfter(3);
$cachePool->save($cachedStatusesResp);
}
echo($statusesStr);
} else {
/**
* Mistaken request? Some malfeasant trying something?
*/
exit('Invalid tweet request. Oops. Sorry.');
}
?>