2017-06-19 18:37:35 +02:00
const fs = require ( 'fs' ) ;
const path = require ( 'path' ) ;
const Sequelize = require ( 'sequelize' ) ;
const basename = path . basename ( module . filename ) ;
const config = require ( 'config' ) ;
const db = { } ;
2017-06-19 22:22:06 +02:00
const logger = require ( 'winston' ) ;
2017-06-15 20:15:13 +02:00
2017-10-18 00:09:43 +02:00
const NO _CHANNEL = 'NO_CHANNEL' ;
2017-10-18 00:50:35 +02:00
const NO _CLAIM = 'NO_CLAIM' ;
2017-10-18 00:09:43 +02:00
2017-09-14 00:06:45 +02:00
const database = config . get ( 'Database.Database' ) ;
const username = config . get ( 'Database.Username' ) ;
const password = config . get ( 'Database.Password' ) ;
2017-09-13 02:59:55 +02:00
const sequelize = new Sequelize ( database , username , password , {
host : 'localhost' ,
dialect : 'mysql' ,
2017-06-19 22:22:06 +02:00
logging : false ,
2017-08-26 13:31:16 +02:00
pool : {
max : 5 ,
min : 0 ,
2017-09-13 02:59:55 +02:00
idle : 10000 ,
acquire : 10000 ,
2017-08-26 13:31:16 +02:00
} ,
2017-06-19 22:22:06 +02:00
} ) ;
2017-06-15 20:15:13 +02:00
2017-09-08 02:08:06 +02:00
function sortResult ( result , longId ) {
let claimIndex ;
let shortId = longId . substring ( 0 , 1 ) ; // default sort id is the first letter
let shortIdLength = 0 ;
// find the index of this certificate
claimIndex = result . findIndex ( element => {
return element . claimId === longId ;
} ) ;
if ( claimIndex < 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 , claimIndex ) ;
// remove certificates with the same prefixes until none are left.
while ( possibleMatches . length > 0 ) {
shortIdLength += 1 ;
shortId = longId . substring ( 0 , shortIdLength ) ;
possibleMatches = possibleMatches . filter ( element => {
return ( element . claimId . substring ( 0 , shortIdLength ) === shortId ) ;
} ) ;
}
// return the short Id
logger . debug ( 'short channel id ===' , shortId ) ;
return shortId ;
}
function getLongClaimIdFromShortClaimId ( name , shortId ) {
return new Promise ( ( resolve , reject ) => {
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 } )
. then ( result => {
switch ( result . length ) {
case 0 :
2017-10-18 00:50:35 +02:00
return resolve ( NO _CLAIM ) ;
2017-09-08 02:08:06 +02:00
default : // note results must be sorted
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
}
function getTopFreeClaimIdByClaimName ( name ) {
return new Promise ( ( resolve , reject ) => {
db
2017-09-27 03:49:37 +02:00
. sequelize . query ( ` SELECT claimId FROM Claim WHERE name = ' ${ name } ' ORDER BY effectiveAmount DESC, height ASC LIMIT 1 ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-09-08 02:08:06 +02:00
. then ( result => {
2017-10-18 20:16:07 +02:00
logger . debug ( 'getTopFreeClaimIdByClaimName result:' , result ) ;
2017-09-08 02:08:06 +02:00
switch ( result . length ) {
case 0 :
2017-10-18 19:00:24 +02:00
return resolve ( NO _CLAIM ) ;
2017-09-08 02:08:06 +02:00
default :
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
function getLongChannelIdFromShortChannelId ( channelName , channelId ) {
return new Promise ( ( resolve , reject ) => {
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 => {
switch ( result . length ) {
case 0 :
2017-10-18 00:09:43 +02:00
return resolve ( NO _CHANNEL ) ;
2017-09-08 02:08:06 +02:00
default : // note results must be sorted
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
}
function getLongChannelIdFromChannelName ( channelName ) {
2017-10-18 00:09:43 +02:00
logger . debug ( ` getLongChannelIdFromChannelName( ${ channelName } ) ` ) ;
2017-09-08 02:08:06 +02:00
return new Promise ( ( resolve , reject ) => {
db
2017-10-17 06:25:29 +02:00
. sequelize . query ( ` SELECT claimId, amount, height FROM Certificate WHERE name = ' ${ channelName } ' ORDER BY effectiveAmount DESC, height ASC LIMIT 1; ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-09-08 02:08:06 +02:00
. then ( result => {
switch ( result . length ) {
case 0 :
2017-10-18 00:09:43 +02:00
return resolve ( NO _CHANNEL ) ;
2017-09-08 02:08:06 +02:00
default :
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
}
2017-06-15 20:15:13 +02:00
sequelize
. authenticate ( )
. then ( ( ) => {
2017-06-22 01:36:08 +02:00
logger . info ( 'Sequelize has established mysql connection successfully.' ) ;
2017-06-15 20:15:13 +02:00
} )
. catch ( err => {
2017-06-22 01:36:08 +02:00
logger . error ( 'Sequelize was unable to connect to the database:' , err ) ;
2017-06-19 18:37:35 +02:00
} ) ;
2017-06-15 20:15:13 +02:00
2017-07-13 00:30:31 +02:00
fs
. readdirSync ( _ _dirname )
. filter ( file => {
return ( file . indexOf ( '.' ) !== 0 && file !== basename && file . slice ( - 3 ) === '.js' ) ;
} )
. forEach ( file => {
const model = sequelize [ 'import' ] ( path . join ( _ _dirname , file ) ) ;
db [ model . name ] = model ;
} ) ;
2017-06-17 22:51:30 +02:00
Object . keys ( db ) . forEach ( modelName => {
2017-06-15 20:15:13 +02:00
if ( db [ modelName ] . associate ) {
2017-07-13 01:57:12 +02:00
logger . info ( 'Associating model:' , modelName ) ;
2017-06-19 18:37:35 +02:00
db [ modelName ] . associate ( db ) ;
2017-06-15 20:15:13 +02:00
}
2017-06-19 18:37:35 +02:00
} ) ;
2017-06-15 20:15:13 +02:00
2017-09-07 21:24:40 +02:00
db . sequelize = sequelize ;
db . Sequelize = Sequelize ;
2017-08-16 20:00:17 +02:00
db [ 'upsert' ] = ( Model , values , condition , tableName ) => {
2017-08-04 20:32:21 +02:00
return Model
. findOne ( { where : condition } )
. then ( function ( obj ) {
if ( obj ) { // update
2017-08-16 20:00:17 +02:00
logger . debug ( ` updating " ${ values . name } " " ${ values . claimId } " in db. ${ tableName } ` ) ;
2017-08-04 20:32:21 +02:00
return obj . update ( values ) ;
} else { // insert
2017-08-16 20:00:17 +02:00
logger . debug ( ` creating " ${ values . name } " " ${ values . claimId } " in db. ${ tableName } ` ) ;
2017-08-04 20:32:21 +02:00
return Model . create ( values ) ;
}
2017-09-08 02:08:06 +02:00
} )
. catch ( function ( error ) {
2017-08-04 20:32:21 +02:00
logger . error ( 'Sequelize findOne error' , error ) ;
} ) ;
} ;
2017-09-07 21:24:40 +02:00
db [ 'getTrendingClaims' ] = ( startDate ) => {
return db . sequelize . query ( ` SELECT COUNT(*), File.* FROM Request LEFT JOIN File ON Request.FileId = File.id WHERE FileId IS NOT NULL AND nsfw != 1 AND trendingEligible = 1 AND Request.createdAt > " ${ startDate } " GROUP BY FileId ORDER BY COUNT(*) DESC LIMIT 25; ` , { type : db . sequelize . QueryTypes . SELECT } ) ;
} ;
db [ 'getRecentClaims' ] = ( ) => {
return db . sequelize . query ( ` SELECT * FROM File WHERE nsfw != 1 AND trendingEligible = 1 ORDER BY createdAt DESC LIMIT 25; ` , { type : db . sequelize . QueryTypes . SELECT } ) ;
} ;
2017-06-15 20:15:13 +02:00
2017-09-08 02:08:06 +02:00
db [ 'getShortClaimIdFromLongClaimId' ] = ( claimId , claimName ) => {
return new Promise ( ( resolve , reject ) => {
logger . debug ( 'finding short channel id' ) ;
db
. sequelize . query ( ` SELECT claimId, height FROM Claim WHERE name = ' ${ claimName } ' ORDER BY height; ` , { type : db . sequelize . QueryTypes . SELECT } )
. then ( result => {
switch ( result . length ) {
case 0 :
2017-09-14 20:34:13 +02:00
throw new Error ( 'That is an invalid claim name' ) ;
2017-09-08 02:08:06 +02:00
default :
return resolve ( sortResult ( result , claimId ) ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
2017-09-28 20:42:29 +02:00
db [ 'getShortChannelIdFromLongChannelId' ] = ( longChannelId , channelName ) => {
2017-09-08 02:08:06 +02:00
return new Promise ( ( resolve , reject ) => {
2017-09-29 00:47:55 +02:00
logger . debug ( ` finding short channel id for ${ longChannelId } ${ channelName } ` ) ;
2017-09-08 02:08:06 +02:00
db
. sequelize . query ( ` SELECT claimId, height FROM Certificate WHERE name = ' ${ channelName } ' ORDER BY height; ` , { type : db . sequelize . QueryTypes . SELECT } )
. then ( result => {
switch ( result . length ) {
case 0 :
2017-09-14 20:34:13 +02:00
throw new Error ( 'That is an invalid channel name' ) ;
2017-09-08 02:08:06 +02:00
default :
return resolve ( sortResult ( result , longChannelId ) ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
db [ 'getAllFreeClaims' ] = ( name ) => {
return new Promise ( ( resolve , reject ) => {
db
. sequelize . query ( ` SELECT name, claimId, outpoint, height, address FROM Claim WHERE name = ' ${ name } ' ORDER BY amount DESC, height ASC ` , { type : db . sequelize . QueryTypes . SELECT } )
. then ( result => {
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
default :
return resolve ( result ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
db [ 'resolveClaim' ] = ( name , claimId ) => {
return new Promise ( ( resolve , reject ) => {
db
2017-09-11 21:45:07 +02:00
. sequelize . query ( ` SELECT name, claimId, outpoint, height, address, title, description, thumbnail FROM Claim WHERE name = ' ${ name } ' AND claimId = ' ${ claimId } ' ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-09-08 02:08:06 +02:00
. then ( result => {
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
case 1 :
return resolve ( result [ 0 ] ) ;
default :
2017-09-14 20:34:13 +02:00
throw new Error ( 'more than one entry matches that name and claimID' ) ;
2017-09-08 02:08:06 +02:00
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
db [ 'getClaimIdByLongChannelId' ] = ( channelId , claimName ) => {
return new Promise ( ( resolve , reject ) => {
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 } )
. then ( result => {
switch ( result . length ) {
case 0 :
2017-10-18 00:50:35 +02:00
return resolve ( NO _CLAIM ) ;
2017-09-08 02:08:06 +02:00
default :
return resolve ( result [ 0 ] . claimId ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
db [ 'getAllChannelClaims' ] = ( channelId ) => {
return new Promise ( ( resolve , reject ) => {
logger . debug ( ` finding all claims in channel " ${ channelId } " ` ) ;
db
2017-10-13 03:55:26 +02:00
. sequelize . query ( ` SELECT name, claimId, outpoint, height, address, contentType, title, description, license, thumbnail FROM Claim WHERE certificateId = ' ${ channelId } ' ORDER BY height DESC; ` , { type : db . sequelize . QueryTypes . SELECT } )
2017-09-08 02:08:06 +02:00
. then ( result => {
switch ( result . length ) {
case 0 :
return resolve ( null ) ;
default :
return resolve ( result ) ;
}
} )
. catch ( error => {
reject ( error ) ;
} ) ;
} ) ;
} ;
db [ 'getLongClaimId' ] = ( claimName , claimId ) => {
2017-10-18 20:16:07 +02:00
logger . debug ( ` getLongClaimId( ${ claimName } , ${ claimId } ) ` ) ;
2017-10-18 00:50:35 +02:00
if ( claimId && ( claimId . length === 40 ) ) { // if a full claim id is provided
2017-09-08 02:08:06 +02:00
return new Promise ( ( resolve , reject ) => resolve ( claimId ) ) ;
} else if ( claimId && claimId . length < 40 ) {
2017-10-18 00:50:35 +02:00
return getLongClaimIdFromShortClaimId ( claimName , claimId ) ; // if a short claim id is provided
} else {
return getTopFreeClaimIdByClaimName ( claimName ) ; // if no claim id is provided
2017-09-08 02:08:06 +02:00
}
} ;
db [ 'getLongChannelId' ] = ( channelName , channelId ) => {
2017-10-17 06:25:29 +02:00
logger . debug ( ` getLongChannelId ( ${ channelName } , ${ channelId } ) ` ) ;
2017-10-18 00:50:35 +02:00
if ( channelId && ( channelId . length === 40 ) ) { // if a full channel id is provided
2017-09-08 02:08:06 +02:00
return new Promise ( ( resolve , reject ) => resolve ( channelId ) ) ;
2017-10-18 00:50:35 +02:00
} else if ( channelId && channelId . length < 40 ) { // if a short channel id is provided
2017-09-08 02:08:06 +02:00
return getLongChannelIdFromShortChannelId ( channelName , channelId ) ;
} else {
2017-10-18 00:50:35 +02:00
return getLongChannelIdFromChannelName ( channelName ) ; // if no channel id provided
2017-09-08 02:08:06 +02:00
}
} ;
2017-06-19 18:37:35 +02:00
module . exports = db ;