Development #287
7 changed files with 61 additions and 57 deletions
18
README.md
18
README.md
|
@ -24,19 +24,23 @@ spee.ch is a single-serving site that reads and publishes images and videos to a
|
||||||
## API
|
## API
|
||||||
|
|
||||||
#### GET
|
#### GET
|
||||||
* /api/resolve/:name
|
* /api/claim-resolve/:name
|
||||||
* example: `curl https://spee.ch/api/resolve/doitlive`
|
* example: `curl https://spee.ch/api/claim-resolve/doitlive`
|
||||||
* /api/claim-list/:name
|
* /api/claim-list/:name
|
||||||
* example: `curl https://spee.ch/api/claim-list/doitlive`
|
* example: `curl https://spee.ch/api/claim-list/doitlive`
|
||||||
* /api/is-claim-available/:name (returns `true`/`false` for whether a name is available through spee.ch)
|
* /api/claim-is-available/:name (
|
||||||
* example: `curl https://spee.ch/api/is-claim-available/doitlive`
|
* returns `true`/`false` for whether a name is available through spee.ch
|
||||||
|
* example: `curl https://spee.ch/api/claim-is-available/doitlive`
|
||||||
|
* /api/channel-is-available/:name (
|
||||||
|
* returns `true`/`false` for whether a channel is available through spee.ch
|
||||||
|
* example: `curl https://spee.ch/api/channel-is-available/@CoolChannel`
|
||||||
|
|
||||||
#### POST
|
#### POST
|
||||||
* /api/publish
|
* /api/claim-publish
|
||||||
* example: `curl -X POST -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/publish`
|
* example: `curl -X POST -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/claim-publish`
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* `name`
|
* `name`
|
||||||
* `file` (.mp4, .jpeg, .jpg, .gif, or .png)
|
* `file` (must be type .mp4, .jpeg, .jpg, .gif, or .png)
|
||||||
* `nsfw` (optional)
|
* `nsfw` (optional)
|
||||||
* `license` (optional)
|
* `license` (optional)
|
||||||
* `title` (optional)
|
* `title` (optional)
|
||||||
|
|
|
@ -6,9 +6,9 @@ const NO_CHANNEL = 'NO_CHANNEL';
|
||||||
const NO_FILE = 'NO_FILE';
|
const NO_FILE = 'NO_FILE';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getClaimId (channelName, channelId, name, claimId) {
|
getClaimId (channelName, channelClaimId, name, claimId) {
|
||||||
if (channelName) {
|
if (channelName) {
|
||||||
return module.exports.getClaimIdByChannel(channelName, channelId, name);
|
return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);
|
||||||
} else {
|
} else {
|
||||||
return module.exports.getClaimIdByClaim(name, claimId);
|
return module.exports.getClaimIdByClaim(name, claimId);
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getClaimIdByChannel (channelName, channelId, claimName) {
|
getClaimIdByChannel (channelName, channelClaimId, claimName) {
|
||||||
logger.debug(`getClaimIdByChannel(${channelName}, ${channelId}, ${claimName})`);
|
logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
db.Certificate.getLongChannelId(channelName, channelId) // 1. get the long channel id
|
db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result === NO_CHANNEL) {
|
if (result === NO_CHANNEL) {
|
||||||
resolve(result); // resolves NO_CHANNEL
|
resolve(result); // resolves NO_CHANNEL
|
||||||
|
@ -44,24 +44,24 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getChannelContents (channelName, channelId) {
|
getChannelContents (channelName, channelClaimId) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let longChannelId;
|
let longChannelClaimId;
|
||||||
let shortChannelId;
|
let shortChannelClaimId;
|
||||||
db.Certificate.getLongChannelId(channelName, channelId) // 1. get the long channel Id
|
db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel Id
|
||||||
.then(result => { // 2. get all claims for that channel
|
.then(result => { // 2. get all claims for that channel
|
||||||
if (result === NO_CHANNEL) {
|
if (result === NO_CHANNEL) {
|
||||||
return NO_CHANNEL;
|
return NO_CHANNEL;
|
||||||
}
|
}
|
||||||
longChannelId = result;
|
longChannelClaimId = result;
|
||||||
return db.Certificate.getShortChannelIdFromLongChannelId(longChannelId, channelName);
|
return db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName);
|
||||||
})
|
})
|
||||||
.then(result => { // 3. get all Claim records for this channel
|
.then(result => { // 3. get all Claim records for this channel
|
||||||
if (result === NO_CHANNEL) {
|
if (result === NO_CHANNEL) {
|
||||||
return NO_CHANNEL;
|
return NO_CHANNEL;
|
||||||
}
|
}
|
||||||
shortChannelId = result;
|
shortChannelClaimId = result;
|
||||||
return db.Claim.getAllChannelClaims(longChannelId);
|
return db.Claim.getAllChannelClaims(longChannelClaimId);
|
||||||
})
|
})
|
||||||
.then(result => { // 4. add extra data not available from Claim table
|
.then(result => { // 4. add extra data not available from Claim table
|
||||||
if (result === NO_CHANNEL) {
|
if (result === NO_CHANNEL) {
|
||||||
|
@ -71,17 +71,17 @@ module.exports = {
|
||||||
if (result) {
|
if (result) {
|
||||||
result.forEach(element => {
|
result.forEach(element => {
|
||||||
const fileExtenstion = element.contentType.substring(element.contentType.lastIndexOf('/') + 1);
|
const fileExtenstion = element.contentType.substring(element.contentType.lastIndexOf('/') + 1);
|
||||||
element['showUrlLong'] = `/${channelName}:${longChannelId}/${element.name}`;
|
element['showUrlLong'] = `/${channelName}:${longChannelClaimId}/${element.name}`;
|
||||||
element['directUrlLong'] = `/${channelName}:${longChannelId}/${element.name}.${fileExtenstion}`;
|
element['directUrlLong'] = `/${channelName}:${longChannelClaimId}/${element.name}.${fileExtenstion}`;
|
||||||
element['showUrlShort'] = `/${channelName}:${shortChannelId}/${element.name}`;
|
element['showUrlShort'] = `/${channelName}:${shortChannelClaimId}/${element.name}`;
|
||||||
element['directUrlShort'] = `/${channelName}:${shortChannelId}/${element.name}.${fileExtenstion}`;
|
element['directUrlShort'] = `/${channelName}:${shortChannelClaimId}/${element.name}.${fileExtenstion}`;
|
||||||
element['thumbnail'] = module.exports.chooseThumbnail(element, DEFAULT_THUMBNAIL);
|
element['thumbnail'] = module.exports.chooseThumbnail(element, DEFAULT_THUMBNAIL);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
resolve({
|
resolve({
|
||||||
channelName,
|
channelName,
|
||||||
longChannelId,
|
longChannelClaimId,
|
||||||
shortChannelId,
|
shortChannelClaimId,
|
||||||
claims: result,
|
claims: result,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -78,7 +78,7 @@ const Asset = function () {
|
||||||
};
|
};
|
||||||
this.checkClaimAvailability = function () {
|
this.checkClaimAvailability = function () {
|
||||||
const that = this;
|
const that = this;
|
||||||
const uri = `/api/local-file-available/${this.state.claimName}/${this.state.claimId}`;
|
const uri = `/api/file-is-available/${this.state.claimName}/${this.state.claimId}`;
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
console.log(`checking local availability for ${this.state.claimName}#${this.state.claimId}`)
|
console.log(`checking local availability for ${this.state.claimName}#${this.state.claimId}`)
|
||||||
xhr.open("GET", uri, true);
|
xhr.open("GET", uri, true);
|
||||||
|
@ -103,7 +103,7 @@ const Asset = function () {
|
||||||
};
|
};
|
||||||
this.getAsset = function() {
|
this.getAsset = function() {
|
||||||
const that = this;
|
const that = this;
|
||||||
const uri = `/api/get-claim/${this.state.claimName}/${this.state.claimId}`;
|
const uri = `/api/claim-get/${this.state.claimName}/${this.state.claimId}`;
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
console.log(`getting ${this.state.claimName}#${this.state.claimId}`)
|
console.log(`getting ${this.state.claimName}#${this.state.claimId}`)
|
||||||
xhr.open("GET", uri, true);
|
xhr.open("GET", uri, true);
|
||||||
|
|
|
@ -102,7 +102,7 @@ const publishFileFunctions = {
|
||||||
return fd;
|
return fd;
|
||||||
},
|
},
|
||||||
publishFile: function (file, metadata) {
|
publishFile: function (file, metadata) {
|
||||||
var uri = "/api/publish";
|
var uri = "/api/claim-publish";
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
var fd = this.appendDataToFormData(file, metadata);
|
var fd = this.appendDataToFormData(file, metadata);
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
|
@ -119,13 +119,13 @@ const validationFunctions = {
|
||||||
checkClaimName: function (name) {
|
checkClaimName: function (name) {
|
||||||
const successDisplayElement = document.getElementById('input-success-claim-name');
|
const successDisplayElement = document.getElementById('input-success-claim-name');
|
||||||
const errorDisplayElement = document.getElementById('input-error-claim-name');
|
const errorDisplayElement = document.getElementById('input-error-claim-name');
|
||||||
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateClaimName, 'Sorry, that ending is already taken', '/api/is-claim-available/');
|
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateClaimName, 'Sorry, that ending is already taken', '/api/claim-is-available/');
|
||||||
},
|
},
|
||||||
checkChannelName: function (name) {
|
checkChannelName: function (name) {
|
||||||
const successDisplayElement = document.getElementById('input-success-channel-name');
|
const successDisplayElement = document.getElementById('input-success-channel-name');
|
||||||
const errorDisplayElement = document.getElementById('input-error-channel-name');
|
const errorDisplayElement = document.getElementById('input-error-channel-name');
|
||||||
name = `@${name}`;
|
name = `@${name}`;
|
||||||
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateChannelName, 'Sorry, that name is already taken', '/api/is-channel-available/');
|
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateChannelName, 'Sorry, that name is already taken', '/api/channel-is-available/');
|
||||||
},
|
},
|
||||||
// validation function which checks all aspects of the publish submission
|
// validation function which checks all aspects of the publish submission
|
||||||
validateFilePublishSubmission: function (stagedFiles, metadata) {
|
validateFilePublishSubmission: function (stagedFiles, metadata) {
|
||||||
|
@ -162,7 +162,7 @@ const validationFunctions = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if all validation passes, check availability of the name (note: do we need to re-validate channel name vs. credentials as well?)
|
// if all validation passes, check availability of the name (note: do we need to re-validate channel name vs. credentials as well?)
|
||||||
return that.isNameAvailable(claimName, '/api/is-claim-available/')
|
return that.isNameAvailable(claimName, '/api/claim-is-available/')
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -193,7 +193,7 @@ const validationFunctions = {
|
||||||
return reject(error);
|
return reject(error);
|
||||||
}
|
}
|
||||||
// 3. if all validation passes, check availability of the name
|
// 3. if all validation passes, check availability of the name
|
||||||
that.isNameAvailable(channelName, '/api/is-channel-available/') // validate the availability
|
that.isNameAvailable(channelName, '/api/channel-is-available/') // validate the availability
|
||||||
.then(function(result) {
|
.then(function(result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
@ -43,7 +43,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to see if asset is available locally
|
// route to see if asset is available locally
|
||||||
app.get('/api/local-file-available/:name/:claimId', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/file-is-available/:name/:claimId', ({ ip, originalUrl, params }, res) => {
|
||||||
const name = params.name;
|
const name = params.name;
|
||||||
const claimId = params.claimId;
|
const claimId = params.claimId;
|
||||||
let isLocalFileAvailable = false;
|
let isLocalFileAvailable = false;
|
||||||
|
@ -59,7 +59,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to get an asset
|
// route to get an asset
|
||||||
app.get('/api/get-claim/:name/:claimId', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/claim-get/:name/:claimId', ({ ip, originalUrl, params }, res) => {
|
||||||
const name = params.name;
|
const name = params.name;
|
||||||
const claimId = params.claimId;
|
const claimId = params.claimId;
|
||||||
// resolve the claim
|
// resolve the claim
|
||||||
|
@ -86,7 +86,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// route to check whether spee.ch has published to a claim
|
// route to check whether spee.ch has published to a claim
|
||||||
app.get('/api/is-claim-available/:name', ({ params }, res) => {
|
app.get('/api/claim-is-available/:name', ({ params }, res) => {
|
||||||
checkClaimNameAvailability(params.name)
|
checkClaimNameAvailability(params.name)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
|
@ -101,7 +101,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to check whether spee.ch has published to a channel
|
// route to check whether spee.ch has published to a channel
|
||||||
app.get('/api/is-channel-available/:name', ({ params }, res) => {
|
app.get('/api/channel-is-available/:name', ({ params }, res) => {
|
||||||
checkChannelAvailability(params.name)
|
checkChannelAvailability(params.name)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
|
@ -112,12 +112,12 @@ module.exports = (app) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
logger.debug('api/is-channel-available/ error', error);
|
logger.debug('api/channel-is-available/ error', error);
|
||||||
res.status(500).json(error);
|
res.status(500).json(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to run a resolve request on the daemon
|
// route to run a resolve request on the daemon
|
||||||
app.get('/api/resolve/:uri', ({ headers, ip, originalUrl, params }, res) => {
|
app.get('/api/claim-resolve/:uri', ({ headers, ip, originalUrl, params }, res) => {
|
||||||
resolveUri(params.uri)
|
resolveUri(params.uri)
|
||||||
.then(resolvedUri => {
|
.then(resolvedUri => {
|
||||||
postToStats('serve', originalUrl, ip, null, null, 'success');
|
postToStats('serve', originalUrl, ip, null, null, 'success');
|
||||||
|
@ -128,7 +128,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to run a publish request on the daemon
|
// route to run a publish request on the daemon
|
||||||
app.post('/api/publish', multipartMiddleware, ({ body, files, ip, originalUrl, user }, res) => {
|
app.post('/api/claim-publish', multipartMiddleware, ({ body, files, ip, originalUrl, user }, res) => {
|
||||||
let file, fileName, filePath, fileType, name, nsfw, license, title, description, thumbnail, anonymous, skipAuth, channelName, channelPassword;
|
let file, fileName, filePath, fileType, name, nsfw, license, title, description, thumbnail, anonymous, skipAuth, channelName, channelPassword;
|
||||||
// validate that mandatory parts of the request are present
|
// validate that mandatory parts of the request are present
|
||||||
try {
|
try {
|
||||||
|
@ -179,7 +179,7 @@ module.exports = (app) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channelName = cleanseChannelName(channelName);
|
channelName = cleanseChannelName(channelName);
|
||||||
logger.debug(`/api/publish > name: ${name}, license: ${license} title: "${title}" description: "${description}" channelName: "${channelName}" channelPassword: "${channelPassword}" nsfw: "${nsfw}"`);
|
logger.debug(`name: ${name}, license: ${license} title: "${title}" description: "${description}" channelName: "${channelName}" channelPassword: "${channelPassword}" nsfw: "${nsfw}"`);
|
||||||
// check channel authorization
|
// check channel authorization
|
||||||
authenticateOrSkip(skipAuth, channelName, channelPassword)
|
authenticateOrSkip(skipAuth, channelName, channelPassword)
|
||||||
.then(authenticated => {
|
.then(authenticated => {
|
||||||
|
@ -216,7 +216,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to get a short claim id from long claim Id
|
// route to get a short claim id from long claim Id
|
||||||
app.get('/api/short-claim-id/:longId/:name', ({ params }, res) => {
|
app.get('/api/claim-shorten-id/:longId/:name', ({ params }, res) => {
|
||||||
db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)
|
db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)
|
||||||
.then(shortId => {
|
.then(shortId => {
|
||||||
res.status(200).json(shortId);
|
res.status(200).json(shortId);
|
||||||
|
@ -227,7 +227,7 @@ module.exports = (app) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// route to get a short channel id from long channel Id
|
// route to get a short channel id from long channel Id
|
||||||
app.get('/api/short-channel-id/:longId/:name', ({ ip, originalUrl, params }, res) => {
|
app.get('/api/channel-shorten-id/:longId/:name', ({ ip, originalUrl, params }, res) => {
|
||||||
db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)
|
db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)
|
||||||
.then(shortId => {
|
.then(shortId => {
|
||||||
logger.debug('sending back short channel id', shortId);
|
logger.debug('sending back short channel id', shortId);
|
||||||
|
|
|
@ -105,16 +105,16 @@ function returnOptionsForChannelPageRendering (result, query) {
|
||||||
const totalPages = determineTotalPages(result.claims);
|
const totalPages = determineTotalPages(result.claims);
|
||||||
const paginationPage = getPage(query);
|
const paginationPage = getPage(query);
|
||||||
const options = {
|
const options = {
|
||||||
layout : 'channel',
|
layout : 'channel',
|
||||||
channelName : result.channelName,
|
channelName : result.channelName,
|
||||||
longChannelId : result.longChannelId,
|
longChannelClaimId : result.longChannelClaimId,
|
||||||
shortChannelId: result.shortChannelId,
|
shortChannelClaimId: result.shortChannelClaimId,
|
||||||
claims : extractPageFromClaims(result.claims, paginationPage),
|
claims : extractPageFromClaims(result.claims, paginationPage),
|
||||||
previousPage : determinePreviousPage(paginationPage),
|
previousPage : determinePreviousPage(paginationPage),
|
||||||
currentPage : paginationPage,
|
currentPage : paginationPage,
|
||||||
nextPage : determineNextPage(totalPages, paginationPage),
|
nextPage : determineNextPage(totalPages, paginationPage),
|
||||||
totalPages : totalPages,
|
totalPages : totalPages,
|
||||||
totalResults : determineTotalClaims(result),
|
totalResults : determineTotalClaims(result),
|
||||||
};
|
};
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
@ -131,10 +131,10 @@ function sendChannelContentsToClient (result, query, res) {
|
||||||
function showChannelPageToClient (uri, originalUrl, ip, query, res) {
|
function showChannelPageToClient (uri, originalUrl, ip, query, res) {
|
||||||
let channelName = returnChannelNameFromUri(uri);
|
let channelName = returnChannelNameFromUri(uri);
|
||||||
logger.debug('channel name =', channelName);
|
logger.debug('channel name =', channelName);
|
||||||
let channelId = returnChannelIdFromUri(uri);
|
let channelClaimId = returnChannelIdFromUri(uri);
|
||||||
logger.debug('channel Id =', channelId);
|
logger.debug('channel Id =', channelClaimId);
|
||||||
// 1. retrieve the channel contents
|
// 1. retrieve the channel contents
|
||||||
getChannelContents(channelName, channelId)
|
getChannelContents(channelName, channelClaimId)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
sendChannelContentsToClient(result, query, res);
|
sendChannelContentsToClient(result, query, res);
|
||||||
})
|
})
|
||||||
|
@ -202,7 +202,7 @@ function serveAssetToClient (claimId, name, res) {
|
||||||
.then(fileInfo => {
|
.then(fileInfo => {
|
||||||
logger.debug('fileInfo:', fileInfo);
|
logger.debug('fileInfo:', fileInfo);
|
||||||
if (fileInfo === NO_FILE) {
|
if (fileInfo === NO_FILE) {
|
||||||
res.status(307).redirect(`/api/get-claim/${name}/${claimId}`);
|
res.status(307).redirect(`/api/claim-get/${name}/${claimId}`);
|
||||||
} else {
|
} else {
|
||||||
return serveHelpers.serveFile(fileInfo, claimId, name, res);
|
return serveHelpers.serveFile(fileInfo, claimId, name, res);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue