2018-07-12 23:07:16 +02:00
"use strict" ; require ( "dotenv" ) . config ( ) ; require ( "date-format-lite" ) ;
2018-06-01 22:23:53 +02:00
2018-03-28 16:26:59 +02:00
2018-07-05 20:50:18 +02:00
// P A C K A G E S
2018-04-10 11:08:46 +02:00
2018-07-16 23:06:37 +02:00
const color = require ( "turbocolor" ) ;
2018-07-05 20:50:18 +02:00
const cors = require ( "cors" ) ;
2018-07-12 23:07:16 +02:00
const dedent = require ( "dedent" ) ;
2018-05-23 16:25:16 +02:00
2018-07-12 17:21:42 +02:00
const fastify = require ( "fastify" ) ( {
logger : {
level : "warn" ,
prettyPrint : process . env . NODE _ENV === "development" ? true : false
}
} ) ;
2018-05-23 16:25:16 +02:00
2018-07-16 23:06:37 +02:00
const html = require ( "choo-async/html" ) ;
2018-07-18 22:31:05 +02:00
const local = require ( "app-root-path" ) . require ;
2018-07-12 23:07:16 +02:00
const octokit = require ( "@octokit/rest" ) ( ) ;
const redis = require ( "redis" ) ;
2018-07-18 22:31:05 +02:00
const request = require ( "request-promise-native" ) ;
const stringifyObject = require ( "stringify-object" ) ;
2018-07-12 23:07:16 +02:00
// V A R I A B L E S
const github = local ( "/helpers/github" ) ;
2018-07-12 17:21:42 +02:00
const log = console . log ; // eslint-disable-line
2018-07-12 23:07:16 +02:00
const logSlackError = local ( "/helpers/slack" ) ;
2018-07-14 00:20:14 +02:00
const relativeDate = local ( "/modules/relative-date" ) ;
2018-07-12 23:07:16 +02:00
let client ;
if ( typeof process . env . GITHUB _OAUTH _TOKEN !== "undefined" ) {
octokit . authenticate ( {
type : "oauth" ,
token : process . env . GITHUB _OAUTH _TOKEN
} ) ;
2018-07-16 23:06:37 +02:00
} else log ( ` ${ color . red ( "[missing]" ) } GitHub token ` ) ;
2018-07-12 23:07:16 +02:00
if ( typeof process . env . REDISCLOUD _URL !== "undefined" ) {
client = redis . createClient ( process . env . REDISCLOUD _URL ) ;
client . on ( "error" , redisError => {
process . env . NODE _ENV === "development" ?
2018-07-16 23:06:37 +02:00
log ( ` \n ${ color . yellow ( "Unable to connect to Redis client." ) } \n You may be missing an .env file or your connection was reset. ` ) :
2018-07-12 23:07:16 +02:00
logSlackError ( "An error occured with Redis" , redisError )
;
} ) ;
2018-07-16 23:06:37 +02:00
} else log ( ` ${ color . red ( "[missing]" ) } Redis client URL ` ) ;
2018-05-23 16:25:16 +02:00
2018-04-16 15:39:11 +02:00
2018-07-05 20:50:18 +02:00
// P R O G R A M
2018-05-23 16:25:16 +02:00
2018-07-12 17:21:42 +02:00
fastify . use ( cors ( ) ) ;
2018-07-12 23:07:16 +02:00
2018-07-12 17:21:42 +02:00
fastify . register ( require ( "fastify-compress" ) ) ;
fastify . register ( require ( "fastify-ws" ) ) ;
2018-06-08 13:45:56 +02:00
2018-07-12 17:21:42 +02:00
fastify . register ( require ( "fastify-helmet" ) , {
hidePoweredBy : { setTo : "LBRY" }
2018-07-05 20:50:18 +02:00
} ) ;
2018-06-08 13:45:56 +02:00
2018-07-12 17:21:42 +02:00
fastify . register ( require ( "fastify-static" ) , {
root : ` ${ _ _dirname } /public/ ` ,
prefix : "/assets/"
2018-07-05 20:50:18 +02:00
} ) ;
2018-05-30 07:50:48 +02:00
2018-07-12 17:21:42 +02:00
fastify . register ( require ( "choo-ssr/fastify" ) , {
app : require ( "./client" ) ,
plugins : [
[ require ( "choo-bundles/ssr" ) , { } ]
]
} ) ;
2018-05-23 16:25:16 +02:00
2018-07-12 17:21:42 +02:00
fastify . ready ( err => {
if ( err ) throw err ;
2018-05-30 17:25:04 +02:00
2018-07-12 17:21:42 +02:00
fastify . ws . on ( "connection" , socket => {
2018-07-17 21:40:25 +02:00
socket . send ( JSON . stringify ( {
"message" : "notification" ,
"details" : "Welcome"
} ) ) ;
2018-05-30 17:25:04 +02:00
2018-07-16 23:06:37 +02:00
socket . on ( "message" , data => {
data = JSON . parse ( data ) ;
switch ( data . message ) {
case "landed on homepage" :
generateGitHubFeed ( result => {
socket . send ( JSON . stringify ( {
"message" : "updated html" ,
"html" : result ,
"selector" : "#github-feed"
} ) ) ;
} ) ;
break ;
case "fetch metadata" :
2018-07-17 21:40:25 +02:00
fetchMetadata ( data . claim , data . method , socket ) ;
2018-07-16 23:06:37 +02:00
break ;
default :
log ( data ) ;
break ;
2018-07-12 17:21:42 +02:00
}
2018-05-12 12:03:21 +02:00
} ) ;
2018-07-05 20:50:18 +02:00
2018-07-12 23:07:16 +02:00
socket . on ( "close" , ( ) => log ( "Client disconnected." ) ) ; // TODO: Close socket?
2018-07-05 20:50:18 +02:00
} ) ;
2018-07-12 17:21:42 +02:00
} ) ;
2018-06-01 09:10:22 +02:00
2018-07-12 17:21:42 +02:00
// B E G I N
2018-06-01 09:10:22 +02:00
2018-07-12 17:21:42 +02:00
const start = async ( ) => {
try {
await fastify . listen ( process . env . PORT || 8080 , process . env . IP || "0.0.0.0" ) ;
} catch ( err ) {
fastify . log . error ( err ) ;
process . exit ( 1 ) ;
}
2018-06-01 09:10:22 +02:00
2018-07-12 23:07:16 +02:00
process . env . NODE _ENV === "development" ?
2018-07-16 23:06:37 +02:00
log ( ` \n — ${ color . green ( "⚡" ) } ${ fastify . server . address ( ) . port } \n ` ) :
2018-07-12 23:07:16 +02:00
logSlackError ( ` Server started at port \` ${ fastify . server . address ( ) . port } \` ` )
;
2018-07-12 17:21:42 +02:00
} ;
2018-06-06 13:02:16 +02:00
2018-07-12 17:21:42 +02:00
start ( ) ;
2018-07-12 23:07:16 +02:00
// H E L P E R S
function generateGitHubFeed ( displayGitHubFeed ) {
if ( typeof process . env . REDISCLOUD _URL !== "undefined" ) {
client . zrevrange ( "events" , 0 , 9 , ( err , reply ) => {
if ( err ) return ; // TODO: Render a div with nice error message
const events = [ ] ;
const renderedEvents = [ ] ;
reply . forEach ( item => events . push ( JSON . parse ( item ) ) ) ;
for ( const event of events ) {
renderedEvents . push ( `
< div class = 'github-feed__event' >
< a href = "${github.generateUrl(" actor ", event)}" target = "_blank" rel = "noopener noreferrer" >
< img src = "${event.actor.avatar_url}" class = "github-feed__event__avatar" alt = "" / >
< / a >
< p >
$ { github . generateEvent ( event ) }
< a href = "${github.generateUrl(" repo ", event)}" title = "View this repo on GitHub" target = "_blank" rel = "noopener noreferrer" > < strong > $ { event . repo . name } < / s t r o n g > < / a >
< em class = "github-feed__event__time" > $ { relativeDate ( new Date ( event . created _at ) ) } < / e m >
< / p >
< / d i v >
` );
}
// TODO: Update `.last-updated` every minute
displayGitHubFeed ( dedent `
< h3 > GitHub < / h 3 >
< h5 class = "last-updated" > Last updated : $ { new Date ( ) . format ( "YYYY-MM-DD at H:mm:ss A" ) . toLowerCase ( ) . replace ( /-/g , "·" ) } < / h 5 >
$ { renderedEvents . join ( "" ) }
` );
} ) ;
}
}
2018-07-16 23:06:37 +02:00
2018-07-17 21:40:25 +02:00
function fetchMetadata ( claimAddress , resolveMethod , socket ) {
if ( ! claimAddress || ! resolveMethod ) return ;
const allowedClaims = [
2018-07-18 22:31:05 +02:00
"fortnite-top-stream-moments-nickatnyte" ,
"itsadisaster" ,
"six" ,
"unbubbled1-1"
2018-07-17 21:40:25 +02:00
] ;
2018-07-16 23:06:37 +02:00
const allowedMethods = [
"publish" ,
"resolve" ,
"wallet_send"
] ;
2018-07-17 21:40:25 +02:00
if ( ! allowedMethods . includes ( resolveMethod ) ) return socket . send ( JSON . stringify ( {
"message" : "notification" ,
"type" : "error" ,
"details" : "Unallowed resolve method for tutorial"
} ) ) ;
if ( ! allowedClaims . includes ( claimAddress ) ) return socket . send ( JSON . stringify ( {
"message" : "notification" ,
"type" : "error" ,
"details" : "Invalid claim ID for tutorial"
} ) ) ;
2018-07-16 23:06:37 +02:00
2018-07-18 22:31:05 +02:00
const body = { } ;
2018-07-16 23:06:37 +02:00
2018-07-18 22:31:05 +02:00
if ( resolveMethod === "publish" ) {
body . bid = 0.001 ; // Hardcode the publish amount
2018-07-16 23:06:37 +02:00
2018-07-18 22:31:05 +02:00
// Fix the internal image path in daemon
// body.file_path = process.env.LBRY_DAEMON_IMAGES_PATH + body.file_path; // TODO: needed for step 2, check for `file_path`
}
body . method = resolveMethod ;
body . access _token = process . env . LBRY _DAEMON _ACCESS _TOKEN ;
body . uri = claimAddress ;
return new Promise ( ( resolve , reject ) => {
request ( {
url : "http://daemon.lbry.tech" ,
qs : body
} , ( error , response , body ) => {
if ( error ) {
reject ( error ) ;
logSlackError ( "[daemon error]\n" , "```" + JSON . stringify ( error ) + "```" ) ;
return ;
}
body = JSON . parse ( body ) ;
if ( typeof body . error !== "undefined" ) {
reject ( body . error ) ;
logSlackError ( "[daemon error]\n" , "```" + JSON . stringify ( body . error ) + "```" ) ;
return ;
}
socket . send ( JSON . stringify ( {
"message" : "updated html" ,
"html" : html `
< p style = "text-align: center;" > Success ! Here is the response for < strong > lbry : //${claimAddress}</strong>:</p>
< pre > < code class = "json" > $ { stringifyObject ( body , { indent : " " , singleQuotes : false } ) } < / c o d e > < / p r e >
< button data - action = "tour, step two" class = "__button-black" type = "button" > Go to next step < / b u t t o n >
< script > $ ( '#temp-loader' ) . remove ( ) ; < / s c r i p t >
` ,
"selector" : "#step1-result"
} ) ) ;
} ) ;
} ) ;
2018-07-16 23:06:37 +02:00
}