Merge pull request #255 from lbryio/209-quickstart

LBRY Developer Program
This commit is contained in:
netop:// ウェッブ 2019-02-19 16:22:28 -06:00 committed by GitHub
commit c7332eb6f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 346 additions and 143 deletions

View file

@ -2,6 +2,12 @@
# HTTPS is assumed for security reasons
DAEMON_URL=
# These are for powering the LBRY Developer Program
# /developer-program
GITHUB_APP_ID=
GITHUB_APP_SECRET=
REWARD_URL=api.lbry.io
# https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app
# We use this to show the GitHub feed on the homepage
GITHUB_OAUTH_TOKEN=

View file

@ -0,0 +1,46 @@
"use strict"; /* global document, history, send, window */
document.getElementById("get-started").onclick = event => {
event.preventDefault();
send({
message: "auth me with github"
});
};
if (window.location.search.includes("?code=")) {
document.querySelector("developer-program").innerHTML = `
<form>
<input-submit>
<input id="walletAddress" placeholder="Your LBRY wallet address" type="text"/>
<input id="oauthCode" type="hidden" value="${window.location.search.split("?code=").pop()}"/>
<button id="creditsAcquire" title="Get LBRY credits" type="button">Get credits</button>
</input-submit>
</form>
<h4>Need An Address?</h4>
<p>To receive your LBC, you'll need a wallet address. While graphical wallets are available, the recommended path for engineers is to:</p>
<ol>
<li>Download <a href="https://github.com/lbryio/lbry/releases">the LBRY SDK</a>.</li>
<li>Launch the command-line utility (<code>./lbrynet start</code>).</li>
<li>Run <code>./lbrynet address list</code> and copy the <code>id</code> field.</li>
</ol>
`;
history.replaceState({}, "", window.location.pathname); // clean up URL bar
}
if (document.getElementById("creditsAcquire")) {
document.getElementById("creditsAcquire").onclick = () => {
send({
address: document.getElementById("walletAddress").value,
code: document.getElementById("oauthCode").value,
message: "verify github auth"
});
document.querySelector("developer-program").innerHTML = "<p><em>Awaiting response from LBRY server...</em></p>";
};
}

View file

@ -111,7 +111,8 @@ function debounce(func, wait, immediate) {
const later = () => {
timeout = null;
if (!immediate) func.apply(context, args);
if (!immediate)
func.apply(context, args);
};
const callNow = immediate && !timeout;
@ -119,7 +120,8 @@ function debounce(func, wait, immediate) {
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
if (callNow)
func.apply(context, args);
};
}
@ -129,9 +131,9 @@ function initializePlayground() {
document.querySelector("#fetch-claim-uri").focus();
document.querySelector(".playground-navigation__example:nth-child(1)").classList.add("active");
send(JSON.stringify({
send({
message: "landed on playground"
}));
});
setTimeout(() => {
document.querySelector(".playground-navigation__example:nth-child(1)").click();
@ -139,16 +141,17 @@ function initializePlayground() {
}
function fetchMetadata(exampleNumber, data) {
if (!exampleNumber) return;
if (!exampleNumber)
return;
switch(exampleNumber) {
case 1:
send(JSON.stringify({
send({
claim: data,
message: "fetch metadata",
method: "resolve",
example: exampleNumber
}));
});
document.getElementById("fetch-claim-uri").value = data;
document.getElementById("playground-results").innerHTML = playgroundResponseForExample1(data);
@ -156,24 +159,24 @@ function fetchMetadata(exampleNumber, data) {
break;
case 2:
send(JSON.stringify({
send({
data: data,
message: "fetch metadata",
method: "publish",
example: exampleNumber
}));
});
document.getElementById("playground-results").innerHTML = playgroundResponseForExample2(getMemeInfo());
document.getElementById("playground-loader").style.display = "none";
break;
case 3:
send(JSON.stringify({
send({
claim: data,
message: "fetch metadata",
method: "claim_tip",
example: exampleNumber
}));
});
document.getElementById("fetch-claim-uri").value = data;
document.getElementById("playground-results").innerHTML = playgroundResponseForExample3(data);
@ -265,9 +268,7 @@ const handleExamples = debounce(event => {
if (document.getElementById("playground-url").style.display === "none")
document.getElementById("playground-url").removeAttribute("style");
for (const example of document.querySelectorAll(".playground-navigation__example"))
example.classList.remove("active");
document.querySelectorAll(".playground-navigation__example").forEach(example => example.classList.remove("active"));
document.querySelector(".playground-navigation__example:nth-child(1)").classList.add("active");
document.getElementById("playground-loader").innerHTML = "";
@ -276,9 +277,9 @@ const handleExamples = debounce(event => {
document.getElementById("playground-loader").removeAttribute("style");
document.getElementById("playground-results").removeAttribute("style");
send(JSON.stringify({
send({
message: `request for ${data.action}`
}));
});
break;
@ -291,9 +292,7 @@ const handleExamples = debounce(event => {
document.getElementById("fetch-claim-uri").value = ""; // reset URL bar
document.getElementById("playground-url").style.display = "none";
for (const example of document.querySelectorAll(".playground-navigation__example"))
example.classList.remove("active");
document.querySelectorAll(".playground-navigation__example").forEach(example => example.classList.remove("active"));
document.querySelector(".playground-navigation__example:nth-child(2)").classList.add("active");
document.getElementById("playground-loader").innerHTML = "";
@ -302,9 +301,9 @@ const handleExamples = debounce(event => {
document.getElementById("playground-loader").removeAttribute("style");
document.getElementById("playground-results").removeAttribute("style");
send(JSON.stringify({
send({
message: `request for ${data.action}`
}));
});
break;
@ -320,9 +319,7 @@ const handleExamples = debounce(event => {
if (document.getElementById("playground-url").style.display === "none")
document.getElementById("playground-url").removeAttribute("style");
for (const example of document.querySelectorAll(".playground-navigation__example"))
example.classList.remove("active");
document.querySelectorAll(".playground-navigation__example").forEach(example => example.classList.remove("active"));
document.querySelector(".playground-navigation__example:nth-child(3)").classList.add("active");
document.getElementById("playground-loader").innerHTML = "";
@ -331,9 +328,9 @@ const handleExamples = debounce(event => {
document.getElementById("playground-loader").removeAttribute("style");
document.getElementById("playground-results").removeAttribute("style");
send(JSON.stringify({
send({
message: `request for ${data.action}`
}));
});
break;

View file

@ -0,0 +1,32 @@
"use strict";
// I M P O R T
import html from "choo/html";
// E X P O R T
export default () => {
if (
!process.env.GITHUB_APP_ID ||
!process.env.GITHUB_APP_SECRET ||
!process.env.REWARD_URL
) {
return html`
<developer-program>
<p><strong>Environment variables required to enable functionality are missing.</strong></p>
</developer-program>
`;
}
return html`
<developer-program>
<button class="button" id="get-started">Claim Developer LBC</button>
<small class="meta">This will authenticate you with GitHub to prove eligibility as well as mark you as a follower of LBRY.</small>
</developer-program>
`;
};

View file

@ -28,10 +28,10 @@ export default () => dedent`
function example1() {
return html`
<div class="playground-content__urlbar" id="playground-url">
<input-submit class="playground-content__urlbar" id="playground-url">
<span>lbry://</span><input id="fetch-claim-uri" placeholder="&thinsp;Enter a LBRY address or select a video below" type="text"/>
<button class="button" data-action="execute claim" type="button">Resolve</button>
</div>
</input-submit>
<div class="playground-content__trends" id="playground-loader"></div>
<div id="playground-results"></div>

View file

@ -45,14 +45,9 @@ function handleApiLanguageToggles(language) {
const examples = document.querySelectorAll("[data-api-example-type]");
const toggles = document.querySelectorAll("*[id^='toggle-']");
for (const example of examples)
example.classList.remove("active");
for (const example of codeExamples)
example.classList.add("active");
for (const toggle of toggles)
toggle.classList.remove("active");
examples.forEach(example => example.classList.remove("active"));
codeExamples.forEach(example => example.classList.add("active"));
toggles.forEach(example => example.classList.remove("active"));
document.getElementById(`toggle-${language}`).classList.add("active");
});

View file

@ -26,6 +26,9 @@ if (
// Smooth scroll
document.querySelectorAll("a[href^='#']").forEach(anchor => {
if (anchor.classList.contains("no-smooth")) // Ignore smooth scroll functionality
return;
anchor.addEventListener("click", event => {
event.preventDefault();
@ -60,10 +63,10 @@ document.querySelector("[data-action='subscribe to newsletter']").onclick = () =
document.getElementById("emailMessage").classList.remove("error");
send(JSON.stringify({
send({
email: email,
message: "subscribe"
}));
});
};
@ -87,6 +90,5 @@ function scrollToElementOnLoad() {
function validateEmail(email) {
const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\\.,;:\s@"]{2,})$/i;
return emailRegex.test(String(email));
return emailRegex.test(String(email)); // eslint-disable-line padding-line-between-statements
}

View file

@ -224,7 +224,7 @@
;(function(doc, proto) {
try {
doc.querySelector(":scope body");
} catch (err) {
} catch(err) {
["querySelector", "querySelectorAll"].forEach(method => {
const nativ = proto[method];

View file

@ -1,4 +1,4 @@
"use strict"; /* global document, location, WebSocket */
"use strict"; /* global document, location, WebSocket, window */
@ -12,22 +12,36 @@ document.addEventListener("DOMContentLoaded", () => {
let ws = null;
function checkWebSocketConnection() {
if (!ws || ws.readyState === 3) initializeWebSocketConnection();
if (!ws || ws.readyState === 3)
initializeWebSocketConnection();
}
function initializeWebSocketConnection() {
ws = new WebSocket(location.origin.replace(/^http/, "ws"));
ws.onopen = () => {
console.log("WebSocket connection established"); // eslint-disable-line
};
// ws.onopen = () => console.log("WebSocket connection established"); // eslint-disable-line no-console
ws.onmessage = socket => {
const data = JSON.parse(socket.data);
switch(true) {
case data.message === "notification": // TODO: Make work with appending so multiple notifications can be sent
document.getElementById("flash-container").innerHTML =
`<div class="flash active${data.type ? " " + data.type : ""}">${data.details}</div>`;
setTimeout(() => {
document.getElementById("flash-container").innerHTML = "";
}, 2100);
break;
case data.message === "redirect":
window.location.href = data.url;
break;
case data.message === "show result":
if (!data.example) return;
if (!data.example)
return;
document.querySelector(data.selector).innerHTML = data.html;
@ -60,8 +74,8 @@ function initializeWebSocketConnection() {
}
if (data.example === 2) {
detectLanguageAndUpdate(); // eslint-disable-line
initCanvas(); // eslint-disable-line
detectLanguageAndUpdate(); // eslint-disable-line no-undef
initCanvas(); // eslint-disable-line no-undef
setTimeout(() => {
document.querySelector(".playground-content__meme__canvas__thumbnail").click();
@ -83,36 +97,24 @@ function initializeWebSocketConnection() {
break;
case data.message === "notification": // TODO: Make work with appending so multiple notifications can be sent
document.getElementById("flash-container").innerHTML =
`<div class="flash active${data.type ? " " + data.type : ""}">${data.details}</div>`;
setTimeout(() => {
document.getElementById("flash-container").innerHTML = "";
}, 2100);
break;
default:
console.log(data); // eslint-disable-line
console.log(data); // eslint-disable-line no-console
break;
}
};
ws.onclose = () => {
console.log("WebSocket connection lost"); // eslint-disable-line
checkWebSocketConnection(); // reconnect now
};
ws.onclose = () => checkWebSocketConnection(); // reconnect now
}
function send(msg) { // eslint-disable-line
socketReady(ws, () => ws.send(msg));
function send(msg) { // eslint-disable-line no-unused-vars
socketReady(ws, () => ws.send(JSON.stringify(msg)));
}
function socketReady(socket, callback) {
setTimeout(() => {
if (socket && socket.readyState === 1) {
if (callback !== undefined) callback();
if (callback !== undefined)
callback();
return;
}

View file

@ -11,16 +11,16 @@ import stringifyObject from "stringify-object";
// U T I L S
import randomString from "./random-string";
import messageSlack from "./slack";
import publishMeme from "./publish-meme";
import randomString from "./random-string";
import { send } from "@socket";
import uploadImage from "./upload-image";
const allowedQueryMethods = [
"claim_tip",
"publish",
"resolve",
"claim_tip"
"resolve"
];
const approvedContentIdsForTipping = [
@ -60,11 +60,11 @@ export default async(data, socket) => {
const resolveMethod = data.method;
if (allowedQueryMethods.indexOf(resolveMethod) < 0) {
return socket.send(JSON.stringify({
return send(socket, {
details: "Unallowed resolve method for tutorial",
message: "notification",
type: "error"
}));
});
}
body.authorization = process.env.LBRY_DAEMON_ACCESS_TOKEN;
@ -77,7 +77,7 @@ export default async(data, socket) => {
// E X A M P L E
case resolveMethod === "claim_tip":
if (!approvedContentIdsForTipping.includes(claimAddress)) {
return socket.send(JSON.stringify({
return send(socket, {
example: data.example,
html: raw(`
<h3>Response</h3>
@ -85,7 +85,7 @@ export default async(data, socket) => {
`),
message: "show result",
selector: `#example${data.example}-result`
}));
});
}
apiRequestMethod = "POST";
@ -140,7 +140,7 @@ export default async(data, socket) => {
"json"
);
return socket.send(JSON.stringify({
return send(socket, {
example: data.example,
html: raw(`
<h3>Response</h3>
@ -149,15 +149,15 @@ export default async(data, socket) => {
`),
message: "show result",
selector: `#example${data.example}-result`
}));
});
}
catch(memePublishError) {
socket.send(JSON.stringify({
send(socket, {
details: "Meme publish failed",
message: "notification",
type: "error"
}));
});
if (process.env.NODE_ENV !== "development") {
messageSlack({
@ -172,11 +172,11 @@ export default async(data, socket) => {
}
catch(imageUploadError) {
socket.send(JSON.stringify({
send(socket, {
details: "Image upload failed",
message: "notification",
type: "error"
}));
});
if (process.env.NODE_ENV !== "development") {
messageSlack({
@ -241,7 +241,7 @@ export default async(data, socket) => {
"json"
);
return socket.send(JSON.stringify({
return send(socket, {
example: data.example,
html: raw(`
<h3>Response</h3>
@ -250,7 +250,7 @@ export default async(data, socket) => {
`),
message: "show result",
selector: `#example${data.example}-result`
}));
});
}
return response.body.result[Object.keys(response.body.result)[0]].claim;

View file

@ -30,13 +30,13 @@ String.prototype.escape = function() {
let client;
if (typeof process.env.GITHUB_OAUTH_TOKEN !== "undefined") {
if (process.env.GITHUB_OAUTH_TOKEN) {
octokit = new Octokit({
auth: `token ${process.env.GITHUB_OAUTH_TOKEN}`
});
} else process.stdout.write(`${color.red("[missing]")} GitHub token`);
if (typeof process.env.REDISCLOUD_URL !== "undefined") {
if (process.env.REDISCLOUD_URL) {
client = redis.createClient(process.env.REDISCLOUD_URL);
client.on("error", redisError => {
@ -258,7 +258,7 @@ function generateEvent(event) {
}
function generateGitHubFeed(displayGitHubFeed) {
if (typeof process.env.REDISCLOUD_URL !== "undefined") {
if (process.env.REDISCLOUD_URL) {
client.zrevrange("events", 0, 9, (err, reply) => {
if (err) return; // TODO: Render a div with nice error message
@ -346,8 +346,10 @@ function updateGithubFeed() {
const eventString = JSON.stringify(item);
client.zrank("events", eventString, (err, reply) => {
if (reply === null) client.zadd("events", item.id, eventString, callback);
else callback();
if (reply === null)
client.zadd("events", item.id, eventString, callback);
else
callback();
});
}, () => client.zremrangebyrank("events", 0, -51)); // Keep the latest 50 events
})

View file

@ -28,7 +28,7 @@ export default async(publishMetadata) => {
try {
const response = await got.put(queryUrl, options);
return response.body; // eslint-disable-line padding-line-between-statements
} catch (error) {
} catch(error) {
return error;
}
};

View file

@ -28,7 +28,7 @@ export default async(imageSource) => {
try {
const response = await got.post(queryUrl, options);
return response.body; // eslint-disable-line padding-line-between-statements
} catch (error) {
} catch(error) {
return error;
}
};

View file

@ -22,6 +22,7 @@
@import "pages/api";
@import "pages/contributing";
@import "pages/developer";
@import "pages/documentation";
@import "pages/home";
@import "pages/page";

View file

@ -164,7 +164,7 @@
padding-left: 0.1rem;
li {
list-style-type: lower-roman;
list-style-type: decimal;
}
}

View file

@ -0,0 +1,14 @@
developer-program {
@extend %markdown;
.button {
margin: 1rem auto;
display: block;
}
small {
display: block;
font-size: 0.8rem;
text-align: center;
}
}

View file

@ -13,45 +13,56 @@ import fetchMetadata from "@helper/fetch-metadata";
import { generateGitHubFeed } from "@helper/github";
import messageSlack from "@helper/slack";
let apiUrl = process.env.REWARD_URL;
let githubAppId = process.env.GITHUB_APP_ID;
let githubAppSecret = process.env.GITHUB_APP_SECRET;
// P R O G R A M
export default (socket, action) => {
if (typeof socket !== "object" && typeof action !== "object") return;
if (typeof socket !== "object" && typeof action !== "object")
return;
switch(true) {
case action.message === "auth me with github":
getGitHubUserToken(socket);
break;
case action.message === "verify github auth":
syncWithApi(action, socket);
break;
case action.message === "fetch metadata":
fetchMetadata(action, socket);
break;
case action.message === "landed on homepage":
generateGitHubFeed(result => {
socket.send(JSON.stringify({
send(socket, {
html: result,
message: "updated html",
selector: "#github-feed"
}));
});
});
break;
case action.message === "landed on playground":
generateContent(1, result => {
socket.send(JSON.stringify({
send(socket, {
html: result,
message: "updated html",
selector: "#playground-loader"
}));
});
});
break;
case action.message === "request for playground, example 1":
generateContent(1, result => {
socket.send(JSON.stringify({
send(socket, {
html: result,
message: "updated html",
selector: "#playground-loader"
}));
});
});
break;
@ -61,11 +72,11 @@ export default (socket, action) => {
case action.message === "request for playground, example 3":
generateContent(3, result => {
socket.send(JSON.stringify({
send(socket, {
html: result,
message: "updated html",
selector: "#playground-loader"
}));
});
});
break;
@ -85,15 +96,19 @@ export default (socket, action) => {
function generateContent(exampleNumber, displayTrendingContent) {
if (exampleNumber === 1) {
return getTrendingContent().then(response => {
if (!response || !response.success || response.success !== true || !response.data) return "";
if (!response || !response.success || response.success !== true || !response.data)
return "";
const rawContentCollection = [];
const renderedContentCollection = [];
const trendingContentData = response.data;
for (const data of trendingContentData) {
rawContentCollection.push(fetchMetadata({ claim: data.url, method: "resolve", example: exampleNumber }));
}
for (const data of trendingContentData)
rawContentCollection.push(fetchMetadata({
claim: data.url,
example: exampleNumber,
method: "resolve"
}));
Promise.all(rawContentCollection).then(collection => {
for (const part of collection) {
@ -116,7 +131,7 @@ function generateContent(exampleNumber, displayTrendingContent) {
</div>
</section>
`);
} catch (err) {
} catch(err) {
return; // TODO: Return nice error message
}
}
@ -315,19 +330,26 @@ function generateMemeCreator(socket) {
</form>
`;
return socket.send(JSON.stringify({
return send(socket, {
example: 2,
html: memeCreator,
message: "updated html",
selector: "#playground-loader"
}));
});
}
function getGitHubUserToken(socket) {
send(socket, {
message: "redirect",
url: `https://github.com/login/oauth/authorize?client_id=${githubAppId}&scope=public_repo,user:email`
});
}
async function getTrendingContent() {
try {
const response = await got("https://api.lbry.io/file/list_trending");
return JSON.parse(response.body); // eslint-disable-line padding-line-between-statements
} catch (error) {
} catch(error) {
return error;
}
}
@ -344,22 +366,24 @@ function makeImageSourceSecure(url) {
async function newsletterSubscribe(data, socket) {
const email = data.email;
if (!validateEmail(email)) return socket.send(JSON.stringify({
class: "error",
html: "Your email address is invalid",
message: "updated html",
selector: "#emailMessage"
}));
if (!validateEmail(email)) {
send(socket, {
class: "error",
html: "Your email address is invalid",
message: "updated html",
selector: "#emailMessage"
});
}
try {
await got.post(`https://api.lbry.io/list/subscribe?email=${encodeURIComponent(email)}&tag=developer`);
return socket.send(JSON.stringify({
return send(socket, {
html: "Thank you! Please confirm subscription in your inbox.",
message: "updated html",
selector: "#emailMessage"
}));
} catch (error) {
});
} catch(error) {
const response = JSON.parse(error.body);
if (!response.success) {
@ -369,12 +393,12 @@ async function newsletterSubscribe(data, socket) {
`> _Cause: ${email} interacted with the form_\n`
);
return socket.send(JSON.stringify({
return send(socket, {
class: "error",
html: response.error,
message: "updated html",
selector: "#emailMessage"
}));
});
}
messageSlack(
@ -383,12 +407,56 @@ async function newsletterSubscribe(data, socket) {
`> _Cause: ${email} interacted with the form_\n`
);
return socket.send(JSON.stringify({
return send(socket, {
class: "error",
html: "Something is terribly wrong",
message: "updated html",
selector: "#emailMessage"
}));
});
}
}
export function send(transport, data) {
return transport.send(JSON.stringify(data));
}
async function syncWithApi(data, socket) {
const tokenResponse = await verifyGitHubToken(data.code);
if (tokenResponse === null) {
return send(socket, {
html: "<p><strong>There was an issue with accessing GitHub's API. Please try again later.</strong></p>",
message: "updated html",
selector: "developer-program"
});
}
try {
let result = await got(`https://${apiUrl}/reward/new?github_token=${tokenResponse}&reward_type=github_developer&wallet_address=${data.address}`, { json: true });
result = result.body.data;
return send(socket, {
html: `<p><strong>Success!</strong> Your wallet has been credited with ${result.reward_amount} LBC.</p><p>We have a great reference for the <a href="/api/sdk">LBRY SDK here</a> to help you get started.</p><p>You can see proof of this transaction on <a href="https://explorer.lbry.io/tx/${result.transaction_id}">our Blockain Explorer</a>.</p>`,
message: "updated html",
selector: "developer-program"
});
} catch(error) {
if (!error.body) {
return send(socket, {
html: "<p><strong>LBRY API is down. Please try again later.</strong></p>",
message: "updated html",
selector: "developer-program"
});
}
console.log(error.body); // eslint-disable-line no-console
return send(socket, {
html: "<p>You have already claimed this reward. This reward is limited to <strong>ONE</strong> per person. Your enthusiasm is appreciated.</p>",
message: "updated html",
selector: "developer-program"
});
}
}
@ -396,3 +464,15 @@ function validateEmail(email) {
const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\\.,;:\s@"]{2,})$/i;
return emailRegex.test(String(email)); // eslint-disable-line padding-line-between-statements
}
async function verifyGitHubToken(code) {
try {
let result = await got.post(`https://github.com/login/oauth/access_token?client_id=${githubAppId}&client_secret=${githubAppSecret}&code=${code}`, { json: true });
result = result.body;
return result.access_token;
} catch(verificationError) {
console.log(verificationError.body); // eslint-disable-line no-console
return null;
}
}

View file

@ -96,9 +96,7 @@ export default () => html`
<script>
document.addEventListener("DOMContentLoaded", () => {
send(JSON.stringify({
"message": "landed on homepage"
}));
send({ message: "landed on homepage" });
});
document.getElementsByTagName("body")[0].classList.add("home"); // TODO: make this happen in components/layout

View file

@ -43,7 +43,6 @@ export default (state, emit) => { // eslint-disable-line
}
}
state.lbry = customMetadata;
}
@ -56,23 +55,26 @@ export default (state, emit) => { // eslint-disable-line
// below should be refactored into components
let pageScript = "";
if (partialPath === "glossary")
pageScript =
"<script>" +
fs.readFileSync(`${process.cwd()}/app/components/client/glossary-scripts.js`, "utf-8") +
"</script>";
switch(true) {
case partialPath === "developer-program":
pageScript = renderClientScript("devprogram-scripts");
break;
if (partialPath === "overview")
pageScript =
"<script>" +
fs.readFileSync(`${process.cwd()}/app/components/client/ecosystem-scripts.js`, "utf-8") +
"</script>";
case partialPath === "glossary":
pageScript = renderClientScript("glossary-scripts");
break;
if (partialPath === "playground")
pageScript =
"<script>" +
fs.readFileSync(`${process.cwd()}/app/components/client/playground-scripts.js`, "utf-8") +
"</script>";
case partialPath === "overview":
pageScript = renderClientScript("ecosystem-scripts");
break;
case partialPath === "playground":
pageScript = renderClientScript("playground-scripts");
break;
default:
break;
}
return html`
<article class="page" itemtype="http://schema.org/BlogPosting">
@ -93,3 +95,15 @@ export default (state, emit) => { // eslint-disable-line
</article>
`;
};
// H E L P E R
function renderClientScript(clientScriptFileName) {
return `
<script>
${fs.readFileSync((`${process.cwd()}/app/components/client/${clientScriptFileName}.js`), "utf-8")}
</script>
`;
}

View file

@ -0,0 +1,13 @@
---
title: Developer Program
---
LBRY offers a complimentary 100 LBC to qualified engineers to facilitate exploration, development, and testing.
To qualify you must:
- Have a GitHub account prior to January 1st, 2018.
- Have made a public pull request within the past year.
### Claim LBC
<DeveloperProgram/>

View file

@ -5,6 +5,7 @@
"@helper": "app/helpers",
"@module": "app/modules",
"@root": ".",
"@socket": "app/sockets.js",
"@view": "app/views"
},
"author": "LBRY Team",
@ -94,8 +95,8 @@
"css": "sass --load-path=node_modules --update app/sass:app/dist --style compressed",
"format": "eslint '**/*.js' --fix --ignore-pattern '/app/dist/'",
"postinstall": "link-module-alias",
"preinstall": "command -v link-module-alias && link-module-alias clean || true",
"start": "npm run css && npm i && NODE_ENV=production node index.js",
"preinstall": "command -v link-module-alias; link-module-alias clean || true",
"start": "npm run css; npm i; NODE_ENV=production node index.js",
"test": "run-s test:*",
"test:dependencies": "updates --update ./ --exclude fastify,prismjs",
"test:lint": "standardx --verbose | snazzy",