2017-10-31 18:05:15 +01:00
|
|
|
const logger = require('winston');
|
2018-04-27 04:19:11 +02:00
|
|
|
const returnShortId = require('./utils/returnShortId.js');
|
2018-09-21 22:16:01 +02:00
|
|
|
const isApprovedChannel = require('../../utils/isApprovedChannel');
|
2018-06-06 04:34:24 +02:00
|
|
|
const { assetDefaults: { thumbnail: defaultThumbnail }, details: { host } } = require('@config/siteConfig');
|
2018-09-21 22:16:01 +02:00
|
|
|
const { publishing: { serveOnlyApproved, approvedChannels } } = require('@config/siteConfig');
|
2017-12-06 20:53:31 +01:00
|
|
|
|
2018-04-29 21:17:23 +02:00
|
|
|
const NO_CLAIM = 'NO_CLAIM';
|
|
|
|
|
2017-12-06 20:53:31 +01:00
|
|
|
function determineFileExtensionFromContentType (contentType) {
|
|
|
|
switch (contentType) {
|
|
|
|
case 'image/jpeg':
|
|
|
|
case 'image/jpg':
|
2018-09-04 04:43:12 +02:00
|
|
|
return 'jpg';
|
2017-12-06 20:53:31 +01:00
|
|
|
case 'image/png':
|
|
|
|
return 'png';
|
|
|
|
case 'image/gif':
|
|
|
|
return 'gif';
|
|
|
|
case 'video/mp4':
|
|
|
|
return 'mp4';
|
|
|
|
default:
|
2018-09-04 04:43:12 +02:00
|
|
|
logger.debug('setting unknown file type as file extension jpg');
|
|
|
|
return 'jpg';
|
2017-12-06 20:53:31 +01:00
|
|
|
}
|
2018-04-29 21:17:23 +02:00
|
|
|
}
|
2017-12-06 20:53:31 +01:00
|
|
|
|
2017-12-06 23:41:03 +01:00
|
|
|
function determineThumbnail (storedThumbnail, defaultThumbnail) {
|
2017-12-21 19:50:47 +01:00
|
|
|
if (storedThumbnail === '') {
|
|
|
|
return defaultThumbnail;
|
2017-12-06 23:47:50 +01:00
|
|
|
}
|
2017-12-21 19:50:47 +01:00
|
|
|
return storedThumbnail;
|
2018-04-29 21:17:23 +02:00
|
|
|
}
|
2017-12-06 23:23:28 +01:00
|
|
|
|
2017-12-07 00:15:21 +01:00
|
|
|
function prepareClaimData (claim) {
|
|
|
|
// logger.debug('preparing claim data based on resolved data:', claim);
|
2017-12-14 21:32:20 +01:00
|
|
|
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
|
2017-12-07 00:15:21 +01:00
|
|
|
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
|
2018-03-10 03:23:19 +01:00
|
|
|
claim['host'] = host;
|
2017-12-07 00:15:21 +01:00
|
|
|
return claim;
|
2018-04-29 21:17:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function isLongClaimId (claimId) {
|
|
|
|
return (claimId && (claimId.length === 40));
|
|
|
|
}
|
|
|
|
|
|
|
|
function isShortClaimId (claimId) {
|
|
|
|
return (claimId && (claimId.length < 40));
|
|
|
|
}
|
2017-12-06 23:23:28 +01:00
|
|
|
|
2017-11-08 16:25:21 +01:00
|
|
|
module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
|
2017-08-10 18:47:59 +02:00
|
|
|
const Claim = sequelize.define(
|
|
|
|
'Claim',
|
|
|
|
{
|
|
|
|
address: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
amount: {
|
2017-11-08 16:25:21 +01:00
|
|
|
type : DECIMAL(19, 8),
|
2017-08-15 01:16:32 +02:00
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
claimId: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
claimSequence: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : INTEGER,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
decodedClaim: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : BOOLEAN,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
depth: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : INTEGER,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
effectiveAmount: {
|
2017-11-08 16:25:21 +01:00
|
|
|
type : DECIMAL(19, 8),
|
2017-08-15 01:16:32 +02:00
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
hasSignature: {
|
|
|
|
type : BOOLEAN,
|
2017-08-15 01:16:32 +02:00
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
height: {
|
2017-11-08 00:21:42 +01:00
|
|
|
type : INTEGER,
|
2017-08-15 01:16:32 +02:00
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
hex: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : TEXT('long'),
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
name: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
nout: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : INTEGER,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
txid: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
validAtHeight: {
|
2017-11-08 00:21:42 +01:00
|
|
|
type : INTEGER,
|
2017-08-10 18:47:59 +02:00
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
outpoint: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
claimType: {
|
2017-08-15 01:16:32 +02:00
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
2017-08-15 22:48:42 +02:00
|
|
|
certificateId: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
2017-08-10 18:47:59 +02:00
|
|
|
author: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
description: {
|
2017-08-15 22:48:42 +02:00
|
|
|
type : TEXT('long'),
|
2017-08-10 18:47:59 +02:00
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
language: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-15 22:48:42 +02:00
|
|
|
},
|
|
|
|
license: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
licenseUrl: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
nsfw: {
|
|
|
|
type : BOOLEAN,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
preview: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
thumbnail: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
title: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
metadataVersion: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
contentType: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
source: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
sourceType: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
sourceVersion: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
streamVersion: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
|
|
|
valueVersion: {
|
|
|
|
type : STRING,
|
|
|
|
default: null,
|
|
|
|
},
|
2017-10-26 17:31:38 +02:00
|
|
|
channelName: {
|
|
|
|
type : STRING,
|
|
|
|
allowNull: true,
|
|
|
|
default : null,
|
|
|
|
},
|
2017-08-10 18:47:59 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
freezeTableName: true,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-09-15 23:41:47 +02:00
|
|
|
Claim.associate = db => {
|
|
|
|
Claim.belongsTo(db.File, {
|
|
|
|
foreignKey: {
|
|
|
|
allowNull: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-10-31 18:05:15 +01:00
|
|
|
Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {
|
2017-11-27 19:22:47 +01:00
|
|
|
logger.debug(`Claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`);
|
2017-10-31 18:05:15 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.findAll({
|
2017-10-31 19:54:33 +01:00
|
|
|
where: { name: claimName },
|
2017-10-31 18:05:15 +01:00
|
|
|
order: [['height', 'ASC']],
|
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
switch (result.length) {
|
|
|
|
case 0:
|
2017-11-14 23:52:20 +01:00
|
|
|
throw new Error('No claim(s) found with that claim name');
|
2017-10-31 18:05:15 +01:00
|
|
|
default:
|
2017-11-04 01:10:08 +01:00
|
|
|
resolve(returnShortId(result, claimId));
|
2017-10-31 18:05:15 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-12-06 00:11:16 +01:00
|
|
|
Claim.getAllChannelClaims = function (channelClaimId) {
|
|
|
|
logger.debug(`Claim.getAllChannelClaims for ${channelClaimId}`);
|
2017-10-31 19:54:33 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.findAll({
|
2017-12-06 00:11:16 +01:00
|
|
|
where: { certificateId: channelClaimId },
|
2018-06-14 22:06:19 +02:00
|
|
|
order: [['height', 'DESC']],
|
2017-12-07 18:28:44 +01:00
|
|
|
raw : true, // returns an array of only data, not an array of instances
|
2017-10-31 19:54:33 +01:00
|
|
|
})
|
2017-12-06 20:53:31 +01:00
|
|
|
.then(channelClaimsArray => {
|
|
|
|
switch (channelClaimsArray.length) {
|
2017-10-31 19:54:33 +01:00
|
|
|
case 0:
|
|
|
|
return resolve(null);
|
|
|
|
default:
|
2017-12-06 20:53:31 +01:00
|
|
|
channelClaimsArray.forEach(claim => {
|
|
|
|
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
|
2017-12-14 21:32:20 +01:00
|
|
|
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
|
2017-12-06 20:53:31 +01:00
|
|
|
return claim;
|
|
|
|
});
|
|
|
|
return resolve(channelClaimsArray);
|
2017-10-31 19:54:33 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-12-06 00:11:16 +01:00
|
|
|
Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {
|
|
|
|
logger.debug(`finding claim id for claim ${claimName} from channel ${channelClaimId}`);
|
2017-10-31 23:28:11 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
2017-11-01 00:00:12 +01:00
|
|
|
this
|
2017-10-31 23:28:11 +01:00
|
|
|
.findAll({
|
2017-12-06 00:11:16 +01:00
|
|
|
where: { name: claimName, certificateId: channelClaimId },
|
2017-10-31 23:28:11 +01:00
|
|
|
order: [['id', 'ASC']],
|
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
switch (result.length) {
|
|
|
|
case 0:
|
2018-08-08 20:39:35 +02:00
|
|
|
return reject(NO_CLAIM);
|
2017-10-31 23:28:11 +01:00
|
|
|
case 1:
|
|
|
|
return resolve(result[0].claimId);
|
|
|
|
default:
|
2018-08-08 20:39:35 +02:00
|
|
|
logger.warn(`${result.length} records found for "${claimName}" in channel "${channelClaimId}"`);
|
2017-10-31 23:28:11 +01:00
|
|
|
return resolve(result[0].claimId);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-04-29 21:17:23 +02:00
|
|
|
Claim.validateLongClaimId = function (name, claimId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.findOne({
|
|
|
|
where: {
|
|
|
|
name,
|
|
|
|
claimId,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
if (!result) {
|
|
|
|
return reject(NO_CLAIM);
|
|
|
|
}
|
|
|
|
resolve(claimId);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
logger.error(error);
|
|
|
|
reject(NO_CLAIM);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-11-01 00:00:12 +01:00
|
|
|
Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.findAll({
|
|
|
|
where: {
|
|
|
|
name,
|
|
|
|
claimId: {
|
2018-05-15 00:23:50 +02:00
|
|
|
[sequelize.Op.like]: `${shortId}%`,
|
2017-11-01 00:00:12 +01:00
|
|
|
}},
|
|
|
|
order: [['height', 'ASC']],
|
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
switch (result.length) {
|
|
|
|
case 0:
|
2018-04-29 21:17:23 +02:00
|
|
|
return reject(NO_CLAIM);
|
|
|
|
default:
|
2017-11-01 00:00:12 +01:00
|
|
|
return resolve(result[0].claimId);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2018-04-29 21:17:23 +02:00
|
|
|
logger.error(error);
|
|
|
|
reject(NO_CLAIM);
|
2017-11-01 00:00:12 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
Claim.getTopFreeClaimIdByClaimName = function (name) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.findAll({
|
|
|
|
where: { name },
|
2018-04-29 21:17:23 +02:00
|
|
|
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']],
|
2017-11-01 00:00:12 +01:00
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
switch (result.length) {
|
|
|
|
case 0:
|
2018-04-29 21:17:23 +02:00
|
|
|
return reject(NO_CLAIM);
|
2017-11-01 00:00:12 +01:00
|
|
|
default:
|
2017-11-27 19:22:47 +01:00
|
|
|
return resolve(result[0].dataValues.claimId);
|
2017-11-01 00:00:12 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
2018-04-29 21:17:23 +02:00
|
|
|
logger.error(error);
|
|
|
|
reject(NO_CLAIM);
|
2018-02-22 02:02:57 +01:00
|
|
|
});
|
2017-11-21 21:53:43 +01:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2017-11-01 00:00:12 +01:00
|
|
|
Claim.getLongClaimId = function (claimName, claimId) {
|
2018-08-08 20:39:35 +02:00
|
|
|
logger.debug(`getLongClaimId(${claimName}, ${claimId})`);
|
2018-04-29 21:17:23 +02:00
|
|
|
if (isLongClaimId(claimId)) {
|
2017-11-21 21:53:43 +01:00
|
|
|
return this.validateLongClaimId(claimName, claimId);
|
2018-04-29 21:17:23 +02:00
|
|
|
} else if (isShortClaimId(claimId)) {
|
|
|
|
return this.getLongClaimIdFromShortClaimId(claimName, claimId);
|
2017-11-01 00:00:12 +01:00
|
|
|
} else {
|
2018-04-29 21:17:23 +02:00
|
|
|
return this.getTopFreeClaimIdByClaimName(claimName);
|
2017-11-01 00:00:12 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-09-24 15:22:28 +02:00
|
|
|
Claim.fetchClaim = function (name, claimId) {
|
2018-01-31 00:32:42 +01:00
|
|
|
logger.debug(`Claim.resolveClaim: ${name} ${claimId}`);
|
2017-11-01 00:44:32 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.findAll({
|
|
|
|
where: { name, claimId },
|
|
|
|
})
|
2017-12-06 23:23:28 +01:00
|
|
|
.then(claimArray => {
|
|
|
|
switch (claimArray.length) {
|
|
|
|
case 0:
|
|
|
|
return resolve(null);
|
2017-11-01 00:44:32 +01:00
|
|
|
case 1:
|
2017-12-06 23:23:28 +01:00
|
|
|
return resolve(prepareClaimData(claimArray[0].dataValues));
|
2017-11-01 00:44:32 +01:00
|
|
|
default:
|
2018-08-01 19:25:35 +02:00
|
|
|
logger.warn(`more than one record matches ${name}#${claimId} in db.Claim`);
|
2017-12-06 23:23:28 +01:00
|
|
|
return resolve(prepareClaimData(claimArray[0].dataValues));
|
2017-11-01 00:44:32 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-09-24 15:22:28 +02:00
|
|
|
Claim.resolveClaim = function (name, claimId) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this
|
|
|
|
.fetchClaim(name, claimId)
|
|
|
|
.then(claim => {
|
|
|
|
logger.info('resolveClaim claims:', claim);
|
|
|
|
if (serveOnlyApproved && !isApprovedChannel({ longId: claim.certificateId }, approvedChannels)) {
|
|
|
|
throw new Error('This content is unavailable');
|
|
|
|
}
|
|
|
|
return resolve(claim);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
reject(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-06-30 05:34:48 +02:00
|
|
|
Claim.getOutpoint = function (name, claimId) {
|
2018-08-08 20:39:35 +02:00
|
|
|
logger.debug(`finding outpoint for ${name}#${claimId}`);
|
2018-06-30 05:34:48 +02:00
|
|
|
return this
|
|
|
|
.findAll({
|
|
|
|
where : { name, claimId },
|
|
|
|
attributes: ['outpoint'],
|
|
|
|
})
|
|
|
|
.then(result => {
|
|
|
|
logger.debug('outpoint result');
|
|
|
|
switch (result.length) {
|
|
|
|
case 0:
|
|
|
|
throw new Error(`no record found for ${name}#${claimId}`);
|
|
|
|
case 1:
|
|
|
|
return result[0].dataValues.outpoint;
|
|
|
|
default:
|
2018-08-01 19:25:35 +02:00
|
|
|
logger.warn(`more than one record matches ${name}#${claimId} in db.Claim`);
|
|
|
|
return result[0].dataValues.outpoint;
|
2018-06-30 05:34:48 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
throw error;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-08-03 00:54:23 +02:00
|
|
|
Claim.getCurrentHeight = function () {
|
2018-08-15 20:30:08 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return this
|
|
|
|
.max('height')
|
|
|
|
.then(result => {
|
|
|
|
if (result) {
|
|
|
|
return resolve(result);
|
|
|
|
}
|
|
|
|
return resolve(100000);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
return reject(error);
|
|
|
|
});
|
|
|
|
});
|
2018-08-03 00:54:23 +02:00
|
|
|
};
|
|
|
|
|
2017-08-10 18:47:59 +02:00
|
|
|
return Claim;
|
|
|
|
};
|