lbrypress/classes/LBRY_Daemon.php

400 lines
12 KiB
PHP
Raw Normal View History

<?php
/**
* Main class for the Daemon setup
*
* @package LBRYPress
*/
class LBRY_Daemon
{
/**
* The address of the Lbry Daemon
* @var string
*/
private $address = 'localhost:5279';
2020-02-18 01:17:57 +01:00
/**
* The Daemon's Status
*/
private $daemon_running = false;
2020-02-18 02:13:55 +01:00
/**
* The Daemon Notice Handler
*/
private $notice = null;
/**
* The Daemon Logger
* @var LBRY_Daemon_Logger
*/
public $logger = null;
2018-10-29 22:55:26 +01:00
/**
* LBRY Daemon Object constructor
*/
public function __construct()
2018-10-29 22:55:26 +01:00
{
$this->logger = new LBRY_Daemon_Logger();
2020-02-18 02:13:55 +01:00
$this->notice = new LBRY_Admin_Notice();
2020-02-18 01:17:57 +01:00
$this->daemon_running = $this->test_daemon();
2020-02-18 02:13:55 +01:00
if (!$this->daemon_running) {
$this->start_daemon();
2020-02-18 05:18:26 +01:00
$this->notice->set_notice('error', 'Cannot connect to the LBRY Daemon. Attempting to start daemon server. <br /> If you are still having troubles, click <a href="' . admin_url('admin.php?page=lbrypress-help') . '">HERE</a> for help.');
2020-02-18 02:13:55 +01:00
}
2020-02-18 01:17:57 +01:00
}
/**
* Returns a boolean representation of daemon status
* @return bool Whether or not the daemon is running
*/
private function test_daemon()
{
2020-02-18 02:13:55 +01:00
try {
$result = $this->request('status')->result;
return $result->is_running;
} catch (LBRYDaemonException $e) {
$this->logger->log('daemon_status_error', $e->getMessage() . ' | Code: ' . $e->getCode());
return false;
}
}
/**
* Attempts to start the daemon
*/
private function start_daemon()
{
2020-02-18 05:18:26 +01:00
// Check if a daemon start process is already running
$options = get_option(LBRY_SETTINGS);
if ($options[LBRY_DAEMON_PID]) {
if ($this->is_process_running($options[LBRY_DAEMON_PID])) {
return;
}
$options[LBRY_DAEMON_PID] = false;
update_option(LBRY_SETTINGS, $options);
}
// Using proc_open to set up the request
// Again, this is unix only
$cmd = ABSPATH . "lbrynet start";
$command = $cmd . ' > /dev/null 2> /dev/null & echo $!;';
$pid = exec($command);
if ($pid) {
$options = get_option(LBRY_SETTINGS);
$options[LBRY_DAEMON_PID] = $pid;
update_option(LBRY_SETTINGS, $options);
}
}
/**
2020-02-18 05:18:26 +01:00
* Attempts to stop the daemon
*/
private function stop_daemon()
{
2020-02-18 05:18:26 +01:00
exec(ABSPATH . 'lbrynet stop > /dev/null 2> /dev/null &');
}
/**
* Checks to see if a PID is currently running
* @param int $pid
* @return boolean
*/
private function is_process_running($pid)
{
// This is unix specific
$lines_out = array();
exec('ps '.(int)$pid, $lines_out);
if(count($lines_out) >= 2) {
// Process is running
return true;
}
return false;
}
/**
2018-11-04 00:37:32 +01:00
* Returns an unused address
* https://lbry.tech/api/sdk#address_unused
* @return string Unused wallet address in base58
*/
public function wallet_unused_address()
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
2018-10-29 22:55:26 +01:00
try {
2018-11-04 00:37:32 +01:00
$result = $this->request('address_unused');
2018-10-29 22:55:26 +01:00
return $result->result;
} catch (LBRYDaemonException $e) {
2018-11-04 00:37:32 +01:00
$this->logger->log('address_unused error', $e->getMessage() . ' | Code: ' . $e->getCode());
2020-02-18 02:13:55 +01:00
$this->notice->set_notice('error', 'Issue getting unused address.');
2018-10-29 22:55:26 +01:00
return;
}
}
/**
* Returns an paginated array of Address lists
2018-11-04 00:37:32 +01:00
* https://lbry.tech/api/sdk#address_list
2020-01-28 00:07:32 +01:00
* @param int $page Pagination page number
* @return array Array of address lists linked to this account
2018-11-04 00:37:32 +01:00
*/
public function address_list($page = 1)
2018-11-04 00:37:32 +01:00
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
// Get 20 per page
$params = array(
'page' => $page,
'page_size' => 20
);
2018-11-04 00:37:32 +01:00
try {
$result = $this->request('address_list', $params);
2020-01-28 00:04:37 +01:00
return $result->result->items;
2018-11-04 00:37:32 +01:00
} catch (LBRYDaemonException $e) {
$this->logger->log('address_list error', $e->getMessage() . ' | Code: ' . $e->getCode());
2020-02-18 02:13:55 +01:00
$this->notice->set_notice('error', 'Issue getting address list.');
2018-11-04 00:37:32 +01:00
return;
}
}
/**
* Returns the available balance of a current LBRY account
2018-11-04 00:37:32 +01:00
* https://lbry.tech/api/sdk#account_balance
* @param string $address Wallet Address
* @return float Wallet Balance
*/
2018-10-05 01:47:32 +02:00
public function wallet_balance()
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
2018-10-29 22:55:26 +01:00
try {
2018-11-04 00:37:32 +01:00
$result = $this->request('account_balance');
return $result->result->available;
2018-10-29 22:55:26 +01:00
} catch (LBRYDaemonException $e) {
2018-11-04 00:37:32 +01:00
$this->logger->log('account_balance error', $e->getMessage() . ' | Code: ' . $e->getCode());
2020-02-18 02:13:55 +01:00
$this->notice->set_notice('error', 'Issue getting account balance.');
2018-10-29 22:55:26 +01:00
return;
}
}
/**
2018-11-04 00:37:32 +01:00
* Returns a list of channels for this account
* https://lbry.tech/api/sdk#channel_list
* @param int $page Pagination page number
* @return array claim dictionary or null if empty
*/
public function channel_list($page = 1)
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
$params = array(
'page' => $page,
'page_size' => 20
);
2018-10-29 22:55:26 +01:00
try {
$result = $this->request('channel_list', $params)->result->items;
2018-10-29 22:55:26 +01:00
return empty($result) ? null : $result;
} catch (LBRYDaemonException $e) {
$this->logger->log('channel_list error', $e->getMessage() . ' | Code: ' . $e->getCode());
2020-02-18 02:13:55 +01:00
$this->notice->set_notice('error', 'Issue retrieving channel list.');
2018-10-29 22:55:26 +01:00
return;
}
}
/**
2018-11-04 00:37:32 +01:00
* Create a claim for a new channel
* https://lbry.tech/api/sdk#channel_create
* @return array dictionary containing result of the request
*/
2018-09-14 02:34:11 +02:00
public function channel_new($channel_name, $bid_amount)
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
// TODO: Sanitize channel name and bid
// Make sure no @ sign, as we will add that
if (strpos($channel_name, '@')) {
throw new \Exception('Illegal character "@" in channel name', 1);
}
// No white space allowed
if (strpos($channel_name, ' ')) {
throw new \Exception("No spaces allowed in channel name", 1);
}
$channel_name = '@' . $channel_name;
2018-10-29 22:55:26 +01:00
try {
$result = $this->request(
'channel_create',
2018-10-29 22:55:26 +01:00
array(
'name' => $channel_name,
'bid' => number_format(floatval($bid_amount), 2, '.', '')
2018-10-29 22:55:26 +01:00
)
);
return $result->result;
} catch (LBRYDaemonException $e) {
$this->logger->log('channel_new error', $e->getMessage() . ' | Code: ' . $e->getCode());
throw new \Exception('Issue creating new channel.', 1);
2018-10-29 22:55:26 +01:00
return;
}
}
/**
* Returns the canonical URL for the supplied claim ID, null otherwise
* @param string $claim_id
* @return string Canonical URL, null if not found
*/
public function canonical_url($claim_id = null)
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
if (!$claim_id) {
return null;
}
try {
$result = $this->request(
'claim_search',
array(
'claim_id' => $claim_id,
'no_totals' => true
)
);
$items = $result->result->items;
if (!$items) {
return null;
}
return $items[0]->canonical_url;
} catch (LBRYDaemonException $e) {
$this->logger->log('canonical_url error', $e->getMessage() . ' | Code: ' . $e->getCode());
return;
}
}
2018-10-12 09:42:40 +02:00
/**
* Publishes a post to the LBRY Network
2018-11-04 00:37:32 +01:00
* https://lbry.tech/api/sdk#publish
* @param array $args An array containing necessary data for publish post
*
* Available params:
* ['name', 'bid', 'file_path', 'title', 'description', 'language', 'license', 'channel_id', 'thumbnail']
*
* @return object $result
2018-10-12 09:42:40 +02:00
*/
public function publish($args)
2018-10-12 09:42:40 +02:00
{
2020-02-18 01:17:57 +01:00
if (!$this->daemon_running) return;
2018-10-29 22:55:26 +01:00
try {
$result = $this->request(
'publish',
$args
);
$this->logger->log('publish success!', 'Successfully published post with result: ' . print_r($result->result, true));
2018-10-29 22:55:26 +01:00
return $result->result;
} catch (LBRYDaemonException $e) {
$this->logger->log('publish error', $e->getMessage() . ' | Code: ' . $e->getCode());
2020-02-18 02:13:55 +01:00
$this->notice->set_notice('error', 'Issue publishing / updating post to LBRY Network.');
2018-10-29 22:55:26 +01:00
return;
}
2018-10-12 09:42:40 +02:00
}
2018-10-29 22:55:26 +01:00
/**
* Sends a cURL request to the LBRY Daemon
* @param string $method The method to call on the LBRY API
* @param array $params The Parameters to send the LBRY API Call
* @return string The cURL response
*/
private function request($method, $params = array())
{
// JSONify our request data
$data = array(
'method' => $method,
'params' => $params
);
$data = json_encode($data);
// Send it via curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->address);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
2018-10-29 22:55:26 +01:00
$response_code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
2018-10-29 22:55:26 +01:00
if ($response_code != '200') {
$this->logger->log("Damon Connection Issue", "Daemon connection returned response code $response_code");
throw new LBRYDaemonException("Daemon Connection Issue", $response_code);
}
$result = json_decode($result);
$this->check_for_errors($result);
return $result;
}
/**
* Checks for erros in decoded daemon response and throws an exception if it finds one
* @param $response
*/
private function check_for_errors($response)
{
if (property_exists($response, 'error')) {
2018-10-29 22:55:26 +01:00
$message = $response->error->message;
$code = $response->error->code;
$this->logger->log("Daemon error code $code", $message);
throw new LBRYDaemonException($message, $code);
}
}
/**
* Temporary placeholder function for daemon. Not currently in use.
* @return [type] [description]
*/
2018-10-29 22:55:26 +01:00
// private function download_daemon()
// {
// $output_filename = "lbrydaemon";
//
// // HACK: Shouldn't just directly download, need to know OS, etc
// // TODO: Make sure we are only installing if not there or corrupted
// $host = "http://build.lbry.io/daemon/build-6788_commit-5099e19_branch-lbryum-refactor/mac/lbrynet";
// $fp = fopen(LBRY_URI . '/' . $output_filename, 'w+');
// $ch = curl_init();
// curl_setopt($ch, CURLOPT_URL, $host);
// curl_setopt($ch, CURLOPT_VERBOSE, 1);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// curl_setopt($ch, CURLOPT_FILE, $fp);
// curl_setopt($ch, CURLOPT_AUTOREFERER, false);
// curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
// curl_setopt($ch, CURLOPT_HEADER, 0);
//
// $result = curl_exec($ch);
// curl_close($ch);
// fclose($fp);
//
// $filepath = LBRY_URI . '/' . $output_filename;
//
// `chmod +x {$filepath}`;
// error_log(`{$filepath} status`);
// `{$filepath} start &`;
// }
}
2018-10-29 22:55:26 +01:00
class LBRYDaemonException extends Exception
{
public function __contstruct($message = '', $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}