diff --git a/controller/Controller.class.php b/controller/Controller.class.php index 9a69d3b0..9093542d 100644 --- a/controller/Controller.class.php +++ b/controller/Controller.class.php @@ -86,6 +86,10 @@ class Controller } $router->get('/roadmap', 'ContentActions::executeRoadmap'); + $router->post('/quickstart/auth', 'DeveloperActions::executeQuickstartAuth'); + $router->get('/quickstart/{step}?', 'DeveloperActions::executeQuickstart'); + $router->get('/quickstart/github/callback', 'DeveloperActions::executeQuickstartGithubCallback'); + $router->post('/postcommit', 'OpsActions::executePostCommit'); $router->post('/log-upload', 'OpsActions::executeLogUpload'); $router->get(static::CACHE_CLEAR_PATH, 'OpsActions::executeClearCache'); diff --git a/controller/action/DeveloperActions.class.php b/controller/action/DeveloperActions.class.php new file mode 100644 index 00000000..2b43a264 --- /dev/null +++ b/controller/action/DeveloperActions.class.php @@ -0,0 +1,126 @@ + 'Home', + 'install' => 'Installation', + 'api' => 'The API', + 'credits' => 'Credits' + ]; + $allSteps = array_keys($stepLabels); + $currentStep = $step ?: $allSteps[0]; + + $viewParams = [ + 'currentStep' => $currentStep, + 'stepLabels' => $stepLabels + ]; + + if ($currentStep !== 'all') { + if (!isset($stepLabels[$currentStep])) { + Controller::redirect('/quickstart'); + } + + $stepNum = array_flip($allSteps)[$currentStep]; + + $viewParams += [ + 'stepNum' => $stepNum, + 'prevStep' => $stepNum === 0 ? null : $allSteps[$stepNum - 1], + 'nextStep' => $stepNum + 1 >= count($allSteps) ? null : $allSteps[$stepNum + 1], + ]; + } + + return ['developer/quickstart', $viewParams]; + } + + public static function prepareQuickstartHomePartial(array $vars) + { + return $vars + [ + 'usdValue' => static::DEVELOPER_REWARD * LBRY::getLBCtoUSDRate() + ]; + } + + + public static function prepareQuickstartInstallPartial(array $vars) + { + return $vars + ['versions' => [ + Os::OS_LINUX => Github::getDaemonReleaseProperty(OS::OS_LINUX, 'tag_name'), + Os::OS_OSX => Github::getDaemonReleaseProperty(OS::OS_OSX, 'tag_name'), + Os::OS_WINDOWS => Github::getDaemonReleaseProperty(OS::OS_WINDOWS, 'tag_name'), + ]]; + } + + public static function prepareFormNewDeveloperRewardPartial(array $vars) + { + return $vars + [ + 'defaultWalletAddress' => Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS), + 'error' => Session::get(Session::KEY_DEVELOPER_LAST_FORM) == "new_developer" ? Session::getFlash(Session::KEY_DEVELOPER_CREDITS_ERROR) : '', + 'apiUrl' => LBRY::getApiUrl('/reward/new?reward_type=new_developer') + ]; + } + + public static function prepareFormCreditsPublishPartial(array $vars) + { + return $vars + [ + 'defaultWalletAddress' => Session::get(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS), + 'error' => Session::get(Session::KEY_DEVELOPER_LAST_FORM) == "new_publish" ? Session::getFlash(Session::KEY_DEVELOPER_CREDITS_ERROR) : '', + 'apiUrl' => LBRY::getApiUrl('/reward/new?reward_type=first_publish') + ]; + } + + public static function executeQuickstartAuth() + { + Session::set(Session::KEY_DEVELOPER_CREDITS_WALLET_ADDRESS, trim(Request::getPostParam('wallet_address'))); + Session::set(Session::KEY_DEVELOPER_LAST_FORM, Request::getPostParam('formName')); + + if (Request::getPostParam('returnUrl')) { + Session::set(Session::KEY_DEVELOPER_RETURN_URL_SUCCESS, Request::getPostParam('returnUrl')); + } + + if (!Config::get(Config::GITHUB_DEVELOPER_CREDITS_CLIENT_ID)) { + throw new Exception('no github client id'); + } + + $gitHubParams = [ + 'client_id' => Config::get(Config::GITHUB_DEVELOPER_CREDITS_CLIENT_ID), + 'redirect_uri' => Request::getHostAndProto() . '/quickstart/github/callback', + 'scope' => 'user:email', + 'allow_signup' => false + ]; + + return Controller::redirect('https://github.com/login/oauth/authorize?' . http_build_query($gitHubParams)); + } + + public static function executeQuickstartGithubCallback() + { + $code = Request::getParam('code'); + + if (!$code) { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'This does not appear to be a valid response from GitHub.'); + } else { + $authResponseData = Curl::post('https://github.com/login/oauth/access_token', [ + 'code' => $code, + 'client_id' => Config::get(Config::GITHUB_DEVELOPER_CREDITS_CLIENT_ID), + 'client_secret' => Config::get(Config::GITHUB_DEVELOPER_CREDITS_CLIENT_SECRET) + ], [ + 'headers' => ['Accept: application/json'], + 'json_response' => true + ]); + + if (!$authResponseData || !isset($authResponseData['access_token'])) { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'Request to GitHub failed.'); + } elseif (isset($authResponseData['error_description'])) { + Session::setFlash(Session::KEY_DEVELOPER_CREDITS_ERROR, 'GitHub replied: ' . $authResponseData['error_description']); + } else { + Session::set(Session::KEY_GITHUB_ACCESS_TOKEN, $authResponseData['access_token']); + } + } + + return Controller::redirect(Session::get(Session::KEY_DEVELOPER_RETURN_URL_SUCCESS, '/quickstart/credits')); + } +} diff --git a/controller/action/DownloadActions.class.php b/controller/action/DownloadActions.class.php index 90c9aea2..101b8e86 100644 --- a/controller/action/DownloadActions.class.php +++ b/controller/action/DownloadActions.class.php @@ -23,11 +23,11 @@ class DownloadActions extends Actions if (isset($oses[$os])) { $uri = GitHub::getDaemonDownloadUrl($os); - } - return Controller::redirect($uri, 302); - } } + return Controller::redirect($uri ?: '/quickstart', 302); + } + /* * this is a quick fix to add android, prob not proper design */ diff --git a/view/template/developer/_formCreditsPublish.php b/view/template/developer/_formCreditsPublish.php new file mode 100644 index 00000000..87d47874 --- /dev/null +++ b/view/template/developer/_formCreditsPublish.php @@ -0,0 +1,28 @@ + +lbry.quickstartForm('#form-new-publish-reward', ""); + +
diff --git a/view/template/developer/_formNewDeveloperReward.php b/view/template/developer/_formNewDeveloperReward.php new file mode 100644 index 00000000..99f7d440 --- /dev/null +++ b/view/template/developer/_formNewDeveloperReward.php @@ -0,0 +1,26 @@ + + lbry.quickstartForm('#form-new-developer-reward', ""); + + diff --git a/view/template/developer/_quickstartApi.php b/view/template/developer/_quickstartApi.php new file mode 100644 index 00000000..d336b035 --- /dev/null +++ b/view/template/developer/_quickstartApi.php @@ -0,0 +1,65 @@ +
+ When running, the LBRY daemon provides a JSON-RPC server running at http://localhost:5279
.
+
+ It can be accessed by any utility capable of making HTTPS GET and POST requests, such as cURL or possibly your toaster. On Windows? You can also use PowerShell. Learn more. +
++ To verify the LBRY daemon is running correctly, let's try looking up a URI: +
+$curl 'http://localhost:5279' --data '{"method":"resolve","params":{"uri":"what"}}'
+[
+ {
+ "author": "Samuel Bryan",
+ "content_type": "video/mp4",
+ "description": "What is LBRY? An introduction with Alex Tabarrok",
+ "language": "en",
+ "license": "LBRY inc",
+ "nsfw": false,
+ "sources": {
+ "lbry_sd_hash": "d5169241150022f996fa7cd6a9a1c421937276a3275eb912790bd07ba7aec1fac5fd45431d226b8fb402691e79aeb24b"
+ },
+ "thumbnail": "https://s3.amazonaws.com/files.lbry.io/logo.png",
+ "title": "What is LBRY?",
+ "ver": "0.0.3"
+ }
+]
+
+ Above, we called the method
+ resolve
+ for the URL lbry://what
. This returned the metadata associated with the URL.
+
+ Now let's download it. This time we're going to call the method get
with the same parameters.
+
$curl 'http://localhost:5279' --data '{"method":"get","params":{"uri":"what"} }'
+[
+ {
+ //some response fields omitted for brevity
+ "claim_id": "7b670f0034d0eb119c32acfe8b19ae6622dd218f", //a claim ID is persistent for a piece of content. It stays the same if the original publisher updates the entry.
+ "download_directory": "/home/kauffj/Downloads",
+ "download_path": "/home/kauffj/Downloads/LBRY100.mp4",
+ "file_name": "LBRY100.mp4",
+ "metadata": { ... }, //same dictionary as above
+ "outpoint": "6e224057a9dfa3417bb3890da2c4b4e9d2471641185c6c8b33cb57d61365a4f0:1", //an outpoint is a frozen-in-time pointer to a specific piece of content. It changes if the content changes.
+ "total_bytes": 158433904,
+ "written_bytes": 0 //will increase as the file downloads
+ }
+]
+This file will download in the background to the download_directory
specified in the returned data. Subsequent calls to get
or file_list
will return the status.
The LBRY API consists of about 50 calls, all related to discovering, distributing, and purchasing content. View the full API documentation.
+You can also list all of the commands available by calling the help command.
+$curl 'http://localhost:5279' --data '{"method":"help"}'
+
+If you are running Windows and would like to follow this guide you could substitute curl with a PowerShell console and the following code. +
+$Invoke-RestMethod -Uri 'http://localhost:5279' -Body 'THE_JSON_DATA' -Method POST | ConvertTo-Json
+
+If PowerShell does not work and you want to continue with cURL, you'll need to escape inner double quotes with a \ to pass the JSON properly via Command Prompt. +
+$curl "http://localhost:5279" --data "{\"method\":\"get\",\"params\":{\"uri\":\"what\"} }"
+
diff --git a/view/template/developer/_quickstartCredits.php b/view/template/developer/_quickstartCredits.php
new file mode 100644
index 00000000..42259bcb
--- /dev/null
+++ b/view/template/developer/_quickstartCredits.php
@@ -0,0 +1,76 @@
+So far, everything we've done with LBRY has been free. However, some actions, such as reserving a name or purchasing paid content, require credits.
++ There are several ways to obtain credits. See this page for options. We also reward + testers and contributors, so join our Discord Chat if you'd like to help. +
+ +To receive credits, you will need to generate a wallet address:
+$curl 'http://localhost:5279' --data '{"method":"wallet_new_address"}'
+["bbFxRyWCFRkA9YcuuZD8nE7XTLUxYnddTs"]
+
+Once you have received or purchased some credits, confirm your balance by calling wallet_balance
:
$curl 'http://localhost:5279' --data '{"method":"wallet_balance"}'
+[50.00000000]
+
+
+Publishing to LBRY is just as easy as everything else!
+Not sure what to publish? We recommend your favorite picture or home video. Or just grab something from here.
+$curl 'http://localhost:5279' --data '{"method":"publish", "params": {
+ "name": "electricsheep",
+ "file_path": "/home/kauffj/Desktop/electric-sheep.mp4",
+ "bid": 1,
+ "metadata": {
+ "description": "Some interesting content",
+ "title": "My interesting content",
+ "author": "Video shot by me@example.com",
+ "language": "en",
+ "license": "LBRY Inc",
+ "nsfw": false
+ } //this should match the metadata returned by resolve_name
+}}'
+[
+ {
+ "claim_id": "2081486f32dc493980c77bdaa0502950b532af13",
+ "fee": 0.000329,
+ "nout": 0,
+ "tx": "0100000001a2dcee285b3f552fb8b3eef416c9f17...",
+ "txid": "d71d63ebb3e10067bfd0b302433bc1ab09fbdd5dc9bc687f50aeb6809d1770fe" //this is the value you need to copy
+ }
+]
+
+
+It's a Disaster starring David Cross is just one of tens of thousands of great pieces of content available. Check it out!
+Note! This will cost you LBC. Run the resolve command to see the cost.
+$curl 'http://localhost:5279' --data '{"method":"get","params":{"uri":"itsadisaster"} }'
+[
+ {
+ //some response fields omitted for brevity
+ "claim_id": "bd970a51249cba542a9acfb130147294a6326ee2",
+ "download_directory": "/home/kauffj/Downloads",
+ "download_path": "/home/kauffj/Downloads/It's A Disaster_Feature.mp4",
+ "metadata": {
+ "author": "Written and directed by Todd Berger",
+ "content_type": "video/mp4",
+ "description": "Four couples meet for Sunday brunch only to discover they are stuck in a house together as the world may be about to end."
+ }
+ }
+]
+
+
+LBRY comes with a fully-featured UI so that normal people can use it too. You can download it here.
++ Start building something awesome! LBRY works as a discovery and distribution backend for everything from films to CAD files. + View the full API documentation. +
++ Join our Discord chat to interact with LBRY developers and other community members. Please visit the #dev room (note: this is not a default channel). +
++ Visit our GitHub page to view the source code or report issues. +
diff --git a/view/template/developer/_quickstartHome.php b/view/template/developer/_quickstartHome.php new file mode 100644 index 00000000..992f1eb6 --- /dev/null +++ b/view/template/developer/_quickstartHome.php @@ -0,0 +1,16 @@ + ++ Begin the Guide +
+ diff --git a/view/template/developer/_quickstartInstall.php b/view/template/developer/_quickstartInstall.php new file mode 100644 index 00000000..48878f8f --- /dev/null +++ b/view/template/developer/_quickstartInstall.php @@ -0,0 +1,33 @@ +macOS | +Linux | +Windows | +
---|---|---|
Download | +Download | +Download | +
+ If you prefer to compile from source or are not on one of the above operating systems, follow + this guide. +
++ Unzip and launch the daemon: +
+
+ $lbrynet-daemon
+
While running, the daemon will provide a JSON-RPC interface on localhost. We'll learn how to interact with that next.
+macOS and Windows do not currently bundle the daemon separately. Just launch the full app and the API will still be available. This will be resolved in v0.9. + + */ ?> \ No newline at end of file diff --git a/view/template/developer/quickstart.php b/view/template/developer/quickstart.php new file mode 100644 index 00000000..21c47e2e --- /dev/null +++ b/view/template/developer/quickstart.php @@ -0,0 +1,53 @@ + + + + + false, 'isAbsolute' => false]) ?> +