2018-08-21 14:53:17 +02:00
|
|
|
const logger = require('winston');
|
2018-11-09 15:49:03 +01:00
|
|
|
const db = require('server/models');
|
2019-02-19 02:03:37 +01:00
|
|
|
const {
|
|
|
|
details,
|
|
|
|
publishing: { disabled, disabledMessage, primaryClaimAddress },
|
|
|
|
} = require('@config/siteConfig');
|
2018-11-09 15:49:03 +01:00
|
|
|
const { resolveUri } = require('server/lbrynet');
|
2018-08-21 14:53:17 +02:00
|
|
|
const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js');
|
|
|
|
const { handleErrorResponse } = require('../../../utils/errorHandlers.js');
|
|
|
|
const publish = require('../publish/publish.js');
|
|
|
|
const parsePublishApiRequestBody = require('../publish/parsePublishApiRequestBody');
|
2018-10-22 15:52:17 +02:00
|
|
|
const parsePublishApiRequestFiles = require('../publish/parsePublishApiRequestFiles.js');
|
2018-08-21 14:53:17 +02:00
|
|
|
const authenticateUser = require('../publish/authentication.js');
|
|
|
|
const createThumbnailPublishParams = require('../publish/createThumbnailPublishParams.js');
|
2018-12-14 18:42:37 +01:00
|
|
|
const chainquery = require('chainquery').default;
|
2019-01-14 07:27:23 +01:00
|
|
|
const createCanonicalLink = require('@globalutils/createCanonicalLink');
|
2018-08-21 14:53:17 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
route to update a claim through the daemon
|
|
|
|
*/
|
|
|
|
|
2019-02-23 06:52:31 +01:00
|
|
|
const updateMetadata = ({ nsfw, license, licenseUrl, title, description }) => {
|
2018-08-21 14:53:17 +02:00
|
|
|
const update = {};
|
|
|
|
if (nsfw) update['nsfw'] = nsfw;
|
|
|
|
if (license) update['license'] = license;
|
2019-02-26 19:43:35 +01:00
|
|
|
if (licenseUrl) update['licenseUrl'] = licenseUrl;
|
2018-08-21 14:53:17 +02:00
|
|
|
if (title) update['title'] = title;
|
|
|
|
if (description) update['description'] = description;
|
|
|
|
return update;
|
|
|
|
};
|
|
|
|
|
2018-11-07 23:51:06 +01:00
|
|
|
const rando = () => {
|
|
|
|
let text = '';
|
|
|
|
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
|
|
for (let i = 0; i < 6; i += 1) text += possible.charAt(Math.floor(Math.random() * 62));
|
|
|
|
return text;
|
|
|
|
};
|
|
|
|
|
2018-08-21 14:53:17 +02:00
|
|
|
const claimUpdate = ({ body, files, headers, ip, originalUrl, user, tor }, res) => {
|
|
|
|
// logging
|
2019-04-19 18:14:03 +02:00
|
|
|
logger.debug('Claim update request:', {
|
2018-08-21 14:53:17 +02:00
|
|
|
ip,
|
|
|
|
headers,
|
|
|
|
body,
|
|
|
|
files,
|
|
|
|
user,
|
|
|
|
});
|
|
|
|
|
|
|
|
// check for disabled publishing
|
|
|
|
if (disabled) {
|
|
|
|
return res.status(503).json({
|
|
|
|
success: false,
|
|
|
|
message: disabledMessage,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// define variables
|
2018-11-07 23:51:06 +01:00
|
|
|
let channelName,
|
|
|
|
channelId,
|
|
|
|
channelPassword,
|
|
|
|
description,
|
|
|
|
fileName,
|
|
|
|
filePath,
|
|
|
|
fileType,
|
|
|
|
gaStartTime,
|
|
|
|
thumbnail,
|
|
|
|
fileExtension,
|
|
|
|
license,
|
2019-02-23 06:52:31 +01:00
|
|
|
licenseUrl,
|
2018-11-07 23:51:06 +01:00
|
|
|
name,
|
|
|
|
nsfw,
|
|
|
|
thumbnailFileName,
|
|
|
|
thumbnailFilePath,
|
|
|
|
thumbnailFileType,
|
|
|
|
title,
|
|
|
|
claimRecord,
|
|
|
|
metadata,
|
|
|
|
publishResult,
|
|
|
|
thumbnailUpdate = false;
|
2018-08-21 14:53:17 +02:00
|
|
|
// record the start time of the request
|
|
|
|
gaStartTime = Date.now();
|
|
|
|
|
|
|
|
try {
|
2019-02-26 19:43:35 +01:00
|
|
|
({
|
|
|
|
name,
|
|
|
|
nsfw,
|
|
|
|
license,
|
|
|
|
licenseUrl,
|
|
|
|
title,
|
|
|
|
description,
|
|
|
|
thumbnail,
|
|
|
|
} = parsePublishApiRequestBody(body));
|
2019-02-19 02:03:37 +01:00
|
|
|
({
|
|
|
|
fileName,
|
|
|
|
filePath,
|
|
|
|
fileExtension,
|
|
|
|
fileType,
|
|
|
|
thumbnailFileName,
|
|
|
|
thumbnailFilePath,
|
|
|
|
thumbnailFileType,
|
|
|
|
} = parsePublishApiRequestFiles(files, true));
|
|
|
|
({ channelName, channelId, channelPassword } = body);
|
2018-08-21 14:53:17 +02:00
|
|
|
} catch (error) {
|
2019-02-19 02:03:37 +01:00
|
|
|
return res.status(400).json({ success: false, message: error.message });
|
2018-08-21 14:53:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// check channel authorization
|
|
|
|
authenticateUser(channelName, channelId, channelPassword, user)
|
|
|
|
.then(({ channelName, channelClaimId }) => {
|
2018-11-07 23:51:06 +01:00
|
|
|
if (!channelId) {
|
|
|
|
channelId = channelClaimId;
|
|
|
|
}
|
2019-02-19 02:03:37 +01:00
|
|
|
return chainquery.claim.queries
|
|
|
|
.resolveClaimInChannel(name, channelClaimId)
|
|
|
|
.then(claim => claim.dataValues);
|
2018-08-21 14:53:17 +02:00
|
|
|
})
|
|
|
|
.then(claim => {
|
2018-11-06 23:40:38 +01:00
|
|
|
claimRecord = claim;
|
2018-11-07 23:51:06 +01:00
|
|
|
if (claimRecord.content_type === 'video/mp4' && files.file) {
|
|
|
|
thumbnailUpdate = true;
|
|
|
|
}
|
2018-11-06 23:40:38 +01:00
|
|
|
|
2018-11-07 23:51:06 +01:00
|
|
|
if (!files.file || thumbnailUpdate) {
|
2018-11-06 23:40:38 +01:00
|
|
|
return Promise.all([
|
|
|
|
db.File.findOne({ where: { name, claimId: claim.claim_id } }),
|
|
|
|
resolveUri(`${claim.name}#${claim.claim_id}`),
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return [null, null];
|
2018-08-21 14:53:17 +02:00
|
|
|
})
|
2018-11-06 23:40:38 +01:00
|
|
|
.then(([fileResult, resolution]) => {
|
2019-02-19 02:03:37 +01:00
|
|
|
metadata = Object.assign(
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
title: claimRecord.title,
|
|
|
|
description: claimRecord.description,
|
|
|
|
nsfw: claimRecord.nsfw,
|
|
|
|
license: claimRecord.license,
|
2019-02-24 07:23:56 +01:00
|
|
|
licenseUrl: claimRecord.license_url,
|
2019-02-19 02:03:37 +01:00
|
|
|
language: 'en',
|
|
|
|
author: details.title,
|
|
|
|
},
|
2019-02-23 06:52:31 +01:00
|
|
|
updateMetadata({ title, description, nsfw, license, licenseUrl })
|
2019-02-19 02:03:37 +01:00
|
|
|
);
|
2018-08-21 14:53:17 +02:00
|
|
|
const publishParams = {
|
|
|
|
name,
|
2019-02-19 02:03:37 +01:00
|
|
|
bid: '0.01',
|
2018-08-21 14:53:17 +02:00
|
|
|
claim_address: primaryClaimAddress,
|
2019-02-19 02:03:37 +01:00
|
|
|
channel_name: channelName,
|
|
|
|
channel_id: channelId,
|
2018-08-21 14:53:17 +02:00
|
|
|
metadata,
|
|
|
|
};
|
2018-11-07 23:51:06 +01:00
|
|
|
|
2018-08-21 14:53:17 +02:00
|
|
|
if (files.file) {
|
2018-11-07 23:51:06 +01:00
|
|
|
if (thumbnailUpdate) {
|
|
|
|
// publish new thumbnail
|
|
|
|
const newThumbnailName = `${name}-${rando()}`;
|
2019-02-19 02:03:37 +01:00
|
|
|
const newThumbnailParams = createThumbnailPublishParams(
|
|
|
|
filePath,
|
|
|
|
newThumbnailName,
|
|
|
|
license,
|
|
|
|
nsfw
|
|
|
|
);
|
2018-11-07 23:51:06 +01:00
|
|
|
newThumbnailParams['file_path'] = filePath;
|
|
|
|
publish(newThumbnailParams, fileName, fileType);
|
|
|
|
|
2019-02-19 02:03:37 +01:00
|
|
|
publishParams['thumbnail'] = `${details.host}/${newThumbnailParams.channel_name}:${
|
|
|
|
newThumbnailParams.channel_id
|
|
|
|
}/${newThumbnailName}-thumb.jpg`;
|
2018-11-07 23:51:06 +01:00
|
|
|
} else {
|
|
|
|
publishParams['file_path'] = filePath;
|
|
|
|
}
|
2018-08-21 14:53:17 +02:00
|
|
|
} else {
|
2018-11-06 23:40:38 +01:00
|
|
|
fileName = fileResult.fileName;
|
|
|
|
fileType = fileResult.fileType;
|
2018-11-07 23:51:06 +01:00
|
|
|
publishParams['thumbnail'] = claimRecord.thumbnail_url;
|
2018-08-21 14:53:17 +02:00
|
|
|
}
|
|
|
|
|
2018-10-04 16:26:42 +02:00
|
|
|
const fp = files && files.file && files.file.path ? files.file.path : undefined;
|
|
|
|
return publish(publishParams, fileName, fileType, fp);
|
2018-08-21 14:53:17 +02:00
|
|
|
})
|
2018-11-06 23:40:38 +01:00
|
|
|
.then(result => {
|
|
|
|
publishResult = result;
|
|
|
|
|
|
|
|
if (channelName) {
|
2019-02-19 02:03:37 +01:00
|
|
|
return chainquery.claim.queries.getShortClaimIdFromLongClaimId(
|
|
|
|
result.certificateId,
|
|
|
|
channelName
|
|
|
|
);
|
2018-11-06 23:40:38 +01:00
|
|
|
} else {
|
2019-02-19 02:03:37 +01:00
|
|
|
return chainquery.claim.queries
|
|
|
|
.getShortClaimIdFromLongClaimId(result.claimId, name, result)
|
|
|
|
.catch(() => {
|
|
|
|
return result.claimId.slice(0, 1);
|
|
|
|
});
|
2018-11-06 23:40:38 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.then(shortId => {
|
|
|
|
let canonicalUrl;
|
|
|
|
if (channelName) {
|
2019-02-19 02:03:37 +01:00
|
|
|
canonicalUrl = createCanonicalLink({
|
|
|
|
asset: { ...publishResult, channelShortId: shortId },
|
|
|
|
});
|
2018-11-06 23:40:38 +01:00
|
|
|
} else {
|
2018-11-11 01:11:12 +01:00
|
|
|
canonicalUrl = createCanonicalLink({ asset: { ...publishResult, shortId } });
|
2018-11-06 23:40:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (publishResult.error) {
|
2018-10-04 16:26:42 +02:00
|
|
|
res.status(400).json({
|
|
|
|
success: false,
|
2018-11-06 23:40:38 +01:00
|
|
|
message: publishResult.message,
|
2018-10-04 16:26:42 +02:00
|
|
|
});
|
|
|
|
}
|
2018-11-06 23:40:38 +01:00
|
|
|
|
2019-02-19 02:03:37 +01:00
|
|
|
const { claimId } = publishResult;
|
2018-08-21 14:53:17 +02:00
|
|
|
res.status(200).json({
|
|
|
|
success: true,
|
|
|
|
message: 'update successful',
|
2019-02-19 02:03:37 +01:00
|
|
|
data: {
|
2018-08-21 14:53:17 +02:00
|
|
|
name,
|
|
|
|
claimId,
|
2019-02-19 02:03:37 +01:00
|
|
|
url: `${details.host}${canonicalUrl}`, // for backwards compatability with app
|
|
|
|
showUrl: `${details.host}${canonicalUrl}`,
|
|
|
|
serveUrl: `${details.host}${canonicalUrl}${fileExtension}`,
|
|
|
|
pushTo: canonicalUrl,
|
2018-11-06 23:40:38 +01:00
|
|
|
claimData: publishResult,
|
2018-08-21 14:53:17 +02:00
|
|
|
},
|
|
|
|
});
|
|
|
|
// record the publish end time and send to google analytics
|
|
|
|
sendGATimingEvent('end-to-end', 'update', fileType, gaStartTime, Date.now());
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = claimUpdate;
|