2017-07-17 22:16:11 +02:00
const logger = require ( 'winston' ) ;
2017-08-03 02:13:02 +02:00
const db = require ( '../models' ) ;
2017-07-17 22:16:11 +02:00
2017-08-23 00:50:20 +02:00
// function determineShortChannelId (name, longChannelId) {
// return new Promise((resolve, reject) => {
// logger.debug('finding short channel id');
// db.sequelize.query(`SELECT claimId, height FROM Certificate WHERE name = '${name}' ORDER BY height;`, { type: db.sequelize.QueryTypes.SELECT })
// .then(result => {
// switch (result.length) {
// case 0:
// return reject(new Error('That is an invalid channel name'));
// default:
// let certificateIndex;
// let shortId = longChannelId.substring(0, 1); // default sort id is the first letter
// let shortIdLength = 0;
// // find the index of this certificate
// certificateIndex = result.findIndex(element => {
// return element.claimId === longChannelId;
// });
// if (certificateIndex < 0) { throw new Error('claimid not found in possible sorted list') }
// // get an array of all certificates with lower height
// let possibleMatches = result.slice(0, certificateIndex);
// // remove certificates with the same prefixes until none are left.
// while (possibleMatches.length > 0) {
// shortIdLength += 1;
// shortId = longChannelId.substring(0, shortIdLength);
// possibleMatches = possibleMatches.filter(element => {
// return (element.claimId.substring(0, shortIdLength) === shortId);
// });
// }
// // return the short Id
// logger.debug('short claim id ===', shortId);
// return resolve(shortId);
// }
// })
// .catch(error => {
// reject(error);
// });
// });
// }
function getLongChannelId ( channelName , channelId ) {
if ( channelId && ( channelId . length === 40 ) ) { // full channel id
return channelId ;
} else if ( channelId && channelId . length < 40 ) { // short channel id
return getLongChannelIdFromShortChannelId ( channelName , channelId ) ;
} else {
return getChannelIdFromChannelName ( channelName ) ;
}
} ;
2017-08-23 01:14:42 +02:00
function getClaimIdByLongChannelId ( channelId , claimName ) {
2017-08-23 00:50:20 +02:00
return new Promise ( ( resolve , reject ) => {
2017-08-23 01:14:42 +02:00
logger . debug ( ` finding claim id for claim " ${ claimName } " from channel " ${ channelId } " ` ) ;
db . sequelize . query ( ` SELECT claimId FROM Claim WHERE name = ' ${ claimName } ' AND certificateId = ' ${ channelId } ' LIMIT 1; ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-08-23 00:50:20 +02:00
. then ( result => {
switch ( result . length ) {
case 0 :
return reject ( new Error ( 'There is no such claim for that channel' ) ) ;
default :
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
}
function getLongChannelIdFromShortChannelId ( channelName , channelId ) {
return new Promise ( ( resolve , reject ) => {
logger . debug ( ` finding long channel id for ${ channelName } : ${ channelId } ` ) ;
// get the long channel Id
db . sequelize . query ( ` SELECT claimId, height FROM Certificate WHERE name = ' ${ channelName } ' AND claimId LIKE ' ${ channelId } %' ORDER BY height ASC LIMIT 1; ` , { type : db . sequelize . QueryTypes . SELECT } )
. then ( result => {
logger . debug ( 'result >>' , result ) ;
switch ( result . length ) {
case 0 :
throw new Error ( 'That is an invalid Short Channel Id' ) ;
default : // note results must be sorted
return ( result [ 0 ] . claimId ) ;
}
} )
// return the long channel id
. then ( longChannelId => {
logger . debug ( 'channelId =' , longChannelId ) ;
return resolve ( longChannelId ) ;
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
}
function getChannelIdFromChannelName ( channelName , claimName ) {
// select the top top channel id
}
2017-08-10 19:49:19 +02:00
function determineShortClaimId ( claimId , height , claimList ) {
2017-07-19 23:11:47 +02:00
logger . debug ( 'determining short url based on claim id and claim list' ) ;
2017-08-10 22:04:31 +02:00
logger . debug ( 'claimlist starting length:' , claimList . length ) ;
2017-08-04 21:58:42 +02:00
// remove this claim from the claim list, if it exists
claimList = claimList . filter ( claim => {
2017-08-16 00:35:03 +02:00
return claim . claimId !== claimId ;
2017-07-19 16:58:44 +02:00
} ) ;
2017-08-10 22:04:31 +02:00
logger . debug ( 'claim list length without this claim:' , claimList . length ) ;
// If there are no other claims, return the first letter of the claim id...
2017-08-04 21:58:42 +02:00
if ( claimList . length === 0 ) {
2017-07-19 23:11:47 +02:00
return claimId . substring ( 0 , 1 ) ;
2017-08-10 22:04:31 +02:00
// ...otherwise determine the proper short id.
2017-07-19 23:11:47 +02:00
} else {
const claimListCopy = claimList ;
2017-08-10 22:04:31 +02:00
let i = 0 ;
// find the longest shared prefix (there is a better way to do this that filters, checks next filter, then filters (i.e. combine this step and next))
while ( claimList . length !== 0 ) {
2017-07-19 23:11:47 +02:00
i ++ ;
claimList = claimList . filter ( claim => {
2017-08-16 00:35:03 +02:00
const otherClaimIdSegmentToCompare = claim . claimId . substring ( 0 , i ) ;
2017-08-10 22:04:31 +02:00
const thisClaimIdSegmentToCompare = claimId . substring ( 0 , i ) ;
logger . debug ( 'compare:' , otherClaimIdSegmentToCompare , '===' , thisClaimIdSegmentToCompare , '?' ) ;
return ( otherClaimIdSegmentToCompare === thisClaimIdSegmentToCompare ) ;
2017-07-19 23:11:47 +02:00
} ) ;
}
2017-08-10 22:04:31 +02:00
// use that longest shared prefix to get only those competing claims
const lastMatchIndex = i - 1 ;
const lastMatch = claimId . substring ( 0 , lastMatchIndex ) ;
logger . debug ( 'last match index:' , lastMatchIndex , 'last match:' , lastMatch ) ;
if ( lastMatchIndex === 0 ) { // if no other claims share a prefix, return with first letter.
return claimId . substring ( 0 , 1 ) ;
}
const allMatchingClaimsAtLastMatch = claimListCopy . filter ( claim => {
2017-08-16 00:35:03 +02:00
return ( claim . claimId . substring ( 0 , lastMatchIndex ) === lastMatch ) ;
2017-07-19 16:58:44 +02:00
} ) ;
2017-08-10 22:04:31 +02:00
// for those that share the longest shared prefix: see which came first in time. whichever is earliest, the others take the extra character
const sortedMatchingClaims = allMatchingClaimsAtLastMatch . sort ( ( a , b ) => {
return ( a . height < b . height ) ;
} ) ;
// compare to the earliest one, if it is earlier, this claim takes the extra character
if ( sortedMatchingClaims [ 0 ] . height < height ) {
return claimId . substring ( 0 , lastMatchIndex + 1 ) ;
2017-07-19 23:11:47 +02:00
}
2017-08-10 22:04:31 +02:00
return claimId . substring ( 0 , lastMatchIndex ) ;
2017-07-19 16:58:44 +02:00
}
2017-07-19 23:11:47 +02:00
}
2017-08-08 02:08:03 +02:00
function createOpenGraphInfo ( { fileType , claimId , name , fileName , fileExt } ) {
2017-08-05 02:41:06 +02:00
return {
2017-08-08 22:05:29 +02:00
embedUrl : ` https://spee.ch/embed/ ${ claimId } / ${ name } ` ,
2017-08-08 20:01:01 +02:00
showUrl : ` https://spee.ch/ ${ claimId } / ${ name } ` ,
source : ` https://spee.ch/ ${ claimId } / ${ name } ${ fileExt } ` ,
directFileUrl : ` https://spee.ch/media/ ${ fileName } ` ,
2017-08-05 02:41:06 +02:00
} ;
}
2017-07-17 22:16:11 +02:00
module . exports = {
serveFile ( { fileName , fileType , filePath } , res ) {
logger . info ( ` serving file ${ fileName } ` ) ;
// set default options
let options = {
headers : {
'X-Content-Type-Options' : 'nosniff' ,
'Content-Type' : fileType ,
} ,
} ;
// adjust default options as needed
switch ( fileType ) {
case 'image/jpeg' :
case 'image/gif' :
case 'image/png' :
case 'video/mp4' :
break ;
default :
logger . warn ( 'sending file with unknown type as .jpeg' ) ;
options [ 'headers' ] [ 'Content-Type' ] = 'image/jpeg' ;
break ;
}
// send the file
res . status ( 200 ) . sendFile ( filePath , options ) ;
} ,
2017-08-02 03:58:13 +02:00
showFile ( fileInfo , res ) {
2017-08-05 02:41:06 +02:00
const openGraphInfo = createOpenGraphInfo ( fileInfo ) ;
res . status ( 200 ) . render ( 'show' , { layout : 'show' , fileInfo , openGraphInfo } ) ;
2017-08-01 02:02:39 +02:00
} ,
2017-08-02 03:58:13 +02:00
showFileLite ( fileInfo , res ) {
2017-08-05 02:41:06 +02:00
const openGraphInfo = createOpenGraphInfo ( fileInfo ) ;
res . status ( 200 ) . render ( 'showLite' , { layout : 'show' , fileInfo , openGraphInfo } ) ;
2017-08-01 02:02:39 +02:00
} ,
2017-08-10 19:49:19 +02:00
getFullClaimIdFromShortId ( shortId , name ) {
2017-08-02 22:16:39 +02:00
return new Promise ( ( resolve , reject ) => {
2017-08-04 20:32:21 +02:00
logger . debug ( 'getting claim_id from short url' ) ;
2017-08-02 22:16:39 +02:00
// use the daemon to check for claims list
2017-08-16 09:03:26 +02:00
db . sequelize . query ( ` SELECT claimId FROM Claim WHERE name = ' ${ name } ' AND claimId LIKE ' ${ shortId } %' ORDER BY height ASC LIMIT 1; ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-08-16 00:35:03 +02:00
. then ( result => {
switch ( result . length ) {
case 0 :
2017-08-23 00:50:20 +02:00
return reject ( new Error ( 'That is an invalid Short Claim Id' ) ) ;
2017-08-16 00:35:03 +02:00
default : // note results must be sorted
2017-08-16 09:03:26 +02:00
return resolve ( result [ 0 ] . claimId ) ;
2017-07-20 19:15:20 +02:00
}
} )
2017-08-16 00:35:03 +02:00
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ,
getShortIdFromClaimId ( claimId , height , name ) {
return new Promise ( ( resolve , reject ) => {
logger . debug ( 'finding short claim id from full claim id' ) ;
2017-08-16 09:03:26 +02:00
db . sequelize . query ( ` SELECT claimId, height FROM Claim WHERE name = ' ${ name } ' ORDER BY claimId; ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-08-16 00:35:03 +02:00
. then ( result => {
switch ( result . length ) {
2017-07-19 18:11:08 +02:00
case 0 :
2017-08-23 00:50:20 +02:00
return reject ( new Error ( 'That is an invalid claim name' ) ) ;
2017-08-16 00:35:03 +02:00
default : // note results must be sorted
2017-08-16 09:03:26 +02:00
const shortId = determineShortClaimId ( claimId , height , result ) ;
2017-08-16 00:35:03 +02:00
logger . debug ( 'short claim id ===' , shortId ) ;
return resolve ( shortId ) ;
2017-07-19 18:11:08 +02:00
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ,
2017-08-16 21:23:02 +02:00
getAllFreeClaims ( name ) {
2017-08-02 22:16:39 +02:00
return new Promise ( ( resolve , reject ) => {
2017-08-16 21:23:02 +02:00
db . sequelize . query ( ` SELECT * FROM Claim WHERE name = ' ${ name } ' ORDER BY amount DESC, height ASC ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-08-16 00:35:03 +02:00
. then ( result => {
2017-08-16 09:03:26 +02:00
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
default :
return resolve ( result ) ;
2017-08-16 00:35:03 +02:00
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ,
2017-08-16 21:23:02 +02:00
getTopFreeClaim ( name ) {
2017-08-16 00:35:03 +02:00
return new Promise ( ( resolve , reject ) => {
2017-08-16 21:23:02 +02:00
db . sequelize . query ( ` SELECT * FROM Claim WHERE name = ' ${ name } ' ORDER BY amount DESC, height ASC LIMIT 1 ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-08-16 00:35:03 +02:00
. then ( result => {
2017-08-16 09:03:26 +02:00
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
default :
2017-08-16 09:40:49 +02:00
return resolve ( result [ 0 ] ) ;
2017-08-16 00:35:03 +02:00
}
2017-07-19 18:11:08 +02:00
} )
. catch ( error => {
reject ( error ) ;
} ) ;
2017-07-17 22:16:11 +02:00
} ) ;
2017-07-19 23:11:47 +02:00
} ,
2017-08-16 21:23:02 +02:00
resolveAgainstClaimTable ( name , claimId ) {
return new Promise ( ( resolve , reject ) => {
db . sequelize . query ( ` SELECT * FROM Claim WHERE name = ' ${ name } ' AND claimId = ' ${ claimId } ' ` , { type : db . sequelize . QueryTypes . SELECT } )
. then ( result => {
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
case 1 :
return resolve ( result [ 0 ] ) ;
default :
return new Error ( 'more than one entry matches that name and claimID' ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ,
2017-08-23 00:50:20 +02:00
getClaimIdByChannel ( channelName , channelId , claimName ) {
return new Promise ( ( resolve , reject ) => {
// 1. get the long channel id
getLongChannelId ( channelName , channelId )
// 2. get the claim Id
. then ( longChannelId => {
return getClaimIdByLongChannelId ( longChannelId , claimName ) ;
} )
. then ( claimId => {
return resolve ( claimId ) ;
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ,
2017-07-17 22:16:11 +02:00
} ;