alexandria-core
Version:
The core module of Alexandria!
938 lines (736 loc) • 21.8 kB
JavaScript
import axios from 'axios';
try {
var IPFS_MAIN = require('ipfs');
} catch (e) {
//console.log(e);
}
let AlexandriaCore = (function(){
let Core = {};
// Initiate all instances
try {
Core.ipfs = new IPFS_MAIN({
init: true,
start: true,
EXPERMENTAL: {
pubsub: true,
sharding: true,
dht: true
},
config: {
Addresses: {
Swarm: [
'/ip4/163.172.37.165/tcp/4001/ipfs/QmRvfRjoCCwVLbVAiYWqJJCiQKqGqSuKckv4eDKEHZXxZu',
"/ip4/69.172.212.23/tcp/4001/ipfs/QmXUcnxbsDkazGNvgf1kQya6YwVqNsLbVhzg3LHNTteqwz",
// "/ip4/69.172.212.23/tcp/4002/ws/ipfs/QmXUcnxbsDkazGNvgf1kQya6YwVqNsLbVhzg3LHNTteqwz",
"/ip4/192.99.6.117/tcp/4001/ipfs/QmQ85u4dH4EPRpNxLxBMvUCHCUyuyZgBZsfW81rzh51FtY"
// "/ip6/2607:5300:60:3775::/tcp/4001/ipfs/QmQ85u4dH4EPRpNxLxBMvUCHCUyuyZgBZsfW81rzh51FtY"
]
}
}
});
} catch (e) {
Core.ipfs = "not-supported"
}
// Define all of the application URLS
Core.OIPdURL = "https://api.alexandria.io/alexandria/v2";
Core.IPFSGatewayURL = "https://gateway.ipfs.io/ipfs/";
Core.issoURL = "https://isso.alexandria.io/";
// Define URLS for things we don't control, these likely will change often
Core.btcTickerURL = "https://blockchain.info/ticker?cors=true";
Core.Artifact = {};
Core.Artifact.maxThumbnailSize = 512000;
Core.Artifact.getTXID = function(oip){
let txid = "";
try {
txid = oip.txid
} catch(e) {}
return txid;
}
Core.Artifact.getTitle = function(oip){
let title = "";
try {
title = oip['oip-041'].artifact.info.title
} catch(e) {}
return Core.util.decodeMakeJSONSafe(title);
}
Core.Artifact.getType = function(oip){
let type = "";
try {
type = oip['oip-041'].artifact.type.split('-')[0];
} catch(e) {}
return type;
}
Core.Artifact.getSubtype = function(oip){
let subtype = "";
try {
subtype = oip['oip-041'].artifact.type.split('-')[1];
} catch(e) {}
return subtype;
}
Core.Artifact.getDescription = function(oip){
let description = "";
try {
description = oip['oip-041'].artifact.info.description;
} catch(e) {}
return Core.util.decodeMakeJSONSafe(description);
}
Core.Artifact.getFiles = function(oip){
let files = [];
try {
let tmpFiles = oip['oip-041'].artifact.storage.files;
for (let i = 0; i < tmpFiles.length; i++) {
files.push(tmpFiles[i])
}
} catch(e) {}
return [...files];
}
Core.Artifact.getLocation = function(oip){
let location = "";
try {
location = oip['oip-041'].artifact.storage.location
} catch(e) {}
return location;
}
Core.Artifact.getTimestamp = function(oip){
let timestamp = 0;
try {
timestamp = oip['oip-041'].artifact.timestamp
} catch(e) {}
return timestamp;
}
Core.Artifact.getPublisherName = function(oip){
let pubName = "Flotoshi";
try {
pubName = oip.publisherName
} catch(e) {}
return pubName;
}
Core.Artifact.getPublisher = function(oip){
let pubName = "";
try {
pubName = oip.publisher
} catch(e) {}
return pubName;
}
Core.Artifact.getArtist = function(oip){
let artist = "";
try {
artist = oip['oip-041'].artifact.info.extraInfo.artist
} catch(e) {}
if (artist === ""){
try {
artist = Core.Artifact.getPublisherName(oip);
} catch(e) {}
}
return artist;
}
Core.Artifact.getScale = function(oip){
let scale = 1;
try {
let tmpScale = oip['oip-041'].artifact.payment.scale;
if (tmpScale && tmpScale.split(":").length === 2){
scale = tmpScale.split(":")[0];
}
} catch (e) {}
return scale
}
Core.Artifact.getMainFile = function(oip, type){
let mainFile;
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
if (!type){
type = Core.Artifact.getType(oip);
}
for (let i = 0; i < files.length; i++){
if (files[i].type === type && !mainFile){
mainFile = files[i];
}
}
// If no file is found with the correct type, default to use the first file in the Artifact
if (!mainFile){
if (files[0])
mainFile = files[0];
}
return mainFile;
}
Core.Artifact.getDuration = function(oip){
let duration;
let files = Core.Artifact.getFiles(oip);
for (var i = files.length - 1; i >= 0; i--) {
if (files[i].duration && !duration)
duration = files[i].duration;
}
return Core.util.formatDuration(duration);
}
Core.Artifact.getMainPaidFile = function(oip, type){
let mainFile;
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
for (let i = 0; i < files.length; i++){
if (files[i].type === type && (files[i].sugPlay !== 0 || files[i].sugBuy !== 0) && !mainFile){
mainFile = files[i];
}
}
return mainFile;
}
Core.Artifact.getMainFileSugPlay = function(oip, type){
let sugPlay = 0;
try {
sugPlay = Core.Artifact.getMainPaidFile(oip, type).sugPlay / Core.Artifact.getScale(oip);
} catch (e) {}
return sugPlay
}
Core.Artifact.getMainFileSugBuy = function(oip, type){
let sugBuy = 0;
try {
sugBuy = Core.Artifact.getMainPaidFile(oip, type).sugBuy / Core.Artifact.getScale(oip);
} catch (e) {}
return sugBuy
}
Core.Artifact.getMainFileDisPlay = function(oip, type){
let disPlay = false;
try {
disPlay = Core.Artifact.getMainPaidFile(oip, type).disPlay;
} catch (e) {}
if (!disPlay)
disPlay = false;
return disPlay
}
Core.Artifact.getMainFileDisBuy = function(oip, type){
let disBuy = 0;
try {
disBuy = Core.Artifact.getMainPaidFile(oip, type).disBuy;
} catch (e) {}
if (!disBuy)
disBuy = false;
return disBuy
}
Core.Artifact.getThumbnail = function(oip){
let thumbnail;
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
for (let i = 0; i < files.length; i++){
if (files[i].type === "Image" && files[i].subtype === "cover" && !files[i].sugPlay && files[i].fsize < Core.Artifact.maxThumbnailSize && !thumbnail){
thumbnail = files[i];
}
}
if (!thumbnail){
for (let i = 0; i < files.length; i++){
if (files[i].type === "Image" && !files[i].sugPlay && files[i].fsize < Core.Artifact.maxThumbnailSize && !thumbnail){
thumbnail = files[i];
}
}
}
return thumbnail;
}
Core.Artifact.getAlbumArt = function(oip){
let albumArt;
let files = Core.Artifact.getFiles(oip);
for (let i = 0; i < files.length; i++){
if (files[i].type === "Image" && files[i].subtype === "cover" && !files[i].sugPlay && !albumArt){
albumArt = files[i];
}
}
if (!albumArt){
for (let i = 0; i < files.length; i++){
if (files[i].type === "Image" && files[i].subtype === "album-art" && !files[i].sugPlay && !albumArt){
albumArt = files[i];
}
}
}
if (!albumArt){
albumArt = Core.Artifact.getThumbnail(oip);
}
return albumArt;
}
Core.Artifact.getFirstImage = function(oip){
let imageGet;
let files = Core.Artifact.getFiles(oip);
//let location = Core.Artifact.getLocation(oip);
for (let i = 0; i < files.length; i++){
if (files[i].type === "Image" && !imageGet){
imageGet = files[i];
}
}
// let imageURL = "";
// if (imageGet){
// imageURL = location + "/" + imageGet.fname;
// }
return imageGet;
}
Core.Artifact.getFirstHTML = function(oip){
let htmlGet;
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
for (let i = 0; i < files.length; i++){
let extension = Core.util.getExtension(files[i].fname);
if ((extension === "html" || extension === "HTML") && !htmlGet){
htmlGet = files[i];
}
}
let htmlURL = "";
if (htmlGet){
htmlURL = location + "/" + htmlGet.fname;
}
return htmlURL;
}
Core.Artifact.getFirstHTMLURL = function(oip){
let htmlGet;
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
for (let i = 0; i < files.length; i++){
let extension = Core.util.getExtension(files[i].fname);
if ((extension === "html" || extension === "HTML") && !htmlGet){
htmlGet = files[i];
}
}
let htmlURL = "";
if (htmlGet){
htmlURL = location + "/" + htmlGet.fname;
}
return Core.util.buildIPFSURL(htmlURL);
}
Core.Artifact.getSongs = function(oip){
let files = Core.Artifact.getFiles(oip);
let location = Core.Artifact.getLocation(oip);
let artist = Core.Artifact.getArtist(oip);
let albumArtwork = Core.Artifact.getAlbumArt(oip);
let albumArtUrl = Core.util.buildIPFSURL(Core.util.buildIPFSShortURL(oip, albumArtwork));
let songs = [];
for (var i = 0; i < files.length; i++){
if (files[i].type === "Audio"){
let durationNice = Core.util.formatDuration(files[i].duration);
let songObj = JSON.parse(JSON.stringify(files[i]));
songObj.location = location;
songObj.artist = files[i].artist ? files[i].artist : artist
songObj.name = files[i].dname ? files[i].dname : files[i].fname
songObj.albumArtwork = albumArtUrl
songObj.length = durationNice
songs.push(songObj);
}
}
return songs;
}
Core.Artifact.getEntypoIconForType = function(type){
let icon;
switch(type){
case "Audio":
icon = "beamed-note";
break;
case "Video":
icon = "clapperboard";
break;
case "Image":
icon = "image";
break;
case "Text":
icon = "text";
break;
case "Software":
icon = "code";
break;
case "Web":
icon = "code";
break;
default:
icon = "";
break;
}
return icon;
}
Core.Artifact.paid = function(oip){
let files = oip['oip-041'].artifact.storage.files;
let paid = false;
if (files){
for (var i = 0; i < files.length; i++){
if (files[i].sugPlay || files[i].sugBuy)
paid = true;
}
}
return paid;
}
Core.Artifact.isFilePaid = function(file){
let paid = false;
if (file.sugPlay || file.sugBuy)
paid = true;
return paid;
}
Core.Artifact.checkPaidViewFile = function(file){
let paid = false;
if (file.sugPlay)
paid = true;
return paid;
}
Core.Artifact.getFormattedVideoQualities = function(oip){
let files = Core.Artifact.getFiles(oip);
let qualityArr = [];
for (var i = files.length - 1; i >= 0; i--) {
if (files[i].subtype === "HD720" ||
files[i].subtype === "SD480" ||
files[i].subtype === "LOW320" ||
files[i].subtype === "MOB240"){
qualityArr.push({
format: files[i].subtype,
src: Core.util.buildIPFSURL(Core.util.buildIPFSShortURL(oip, files[i])),
type: "video/" + Core.util.getExtension(files[i].fname)
})
}
}
}
Core.Comments = {};
Core.Comments.get = function(hash, callback){
Core.Network.getCommentsFromISSO("/browser/" + hash, function(results){
console.log(results);
callback(results);
})
}
Core.Comments.add = function(hash, comment, callback){
Core.Network.postCommentToISSO("/browser/" + hash, {text: comment}, function(results){
console.log(results)
callback(results);
})
}
Core.Comments.like = function(id, callback){
Core.Network.likeISSOComment(id, function(results){
console.log(results)
callback(results);
})
}
Core.Comments.dislike = function(id, callback){
Core.Network.dislikeISSOComment(id, function(results){
console.log(results)
callback(results);
})
}
Core.Data = {};
Core.Data.getBTCPrice = function(callback){
// Check to see if we should update again, if not, just return the old data.
Core.Network.getLatestBTCPrice(callback);
}
Core.Index = {};
Core.Index.supportedArtifacts = [];
Core.Index.getSupportedArtifacts = function(callback){
Core.Network.getArtifactsFromOIPd(function(jsonResult) {
let filtered = Core.Index.stripUnsupported(jsonResult);
console.log("Filtered: ", filtered)
callback([...filtered]);
});
}
Core.Index.getSuggestedContent = function(userid, callback){
let _Core = Core;
// In the future we will generate content specific for users, for now, just the generic is ok :)
// userid is not currently implemented or used.
Core.Index.getSupportedArtifacts(function(supportedArtifacts){
console.log(supportedArtifacts)
if (supportedArtifacts.length > 25){
callback(supportedArtifacts.slice(0,25));
} else {
callback(supportedArtifacts);
}
})
}
Core.Index.stripUnsupported = function(artifacts){
var supportedArtifacts = [];
for (var x = artifacts.length -1; x >= 0; x--){
if (artifacts[x]['oip-041']){
if (artifacts[x]['oip-041'].artifact.type.split('-').length === 2){
if (!artifacts[x]['oip-041'].artifact.info.nsfw)
supportedArtifacts.push(JSON.parse(JSON.stringify(artifacts[x])));
}
}
}
return [...supportedArtifacts];
}
Core.Index.getArtifactFromID = function(id, callback){
Core.Index.getSupportedArtifacts(function(supportedArtifacts){
for (var i = 0; i < supportedArtifacts.length; i++) {
if (supportedArtifacts[i].txid.substr(0, id.length) === id){
callback([...[supportedArtifacts[i]]]);
}
}
})
}
Core.Index.search = function(options, onSuccess, onError){
Core.Network.searchOIPd(options, function(results){
let res = Core.Index.stripUnsupported(results);
onSuccess(res);
}, function(error){
onError(error);
})
}
Core.Index.getPublisherFromID = function(id, callback){
}
Core.Network = {};
Core.Network.cachedArtifacts = [];
Core.Network.artifactsLastUpdate = 0; // timestamp of last ajax call to the artifacts endpoint.
Core.Network.artifactsUpdateTimelimit = 30 * 1000; // 30 seconds
Core.Network.cachedBTCPriceObj = {};
Core.Network.btcpriceLastUpdate = 0;
Core.Network.btcpriceUpdateTimelimit = 5 * 60 * 1000; // Five minutes
Core.Network.searchOIPd = function(options, onSuccess, onError){
let defaultOptions = {
"protocol" : "media",
"search-on": "*",
"search-like": true
}
if (!options.protocol)
options.protocol = defaultOptions.protocol;
if (!options["search-on"])
options["search-on"] = defaultOptions["search-on"];
if (!options["search-like"])
options["search-like"] = defaultOptions["search-like"];
let _Core = Core;
axios.post(Core.OIPdURL + "/search", options)
.then(function(results){
if (results && results.data && results.data.status === "success" && results.data.response)
onSuccess(results.data.response);
else
onError(results);
});
}
Core.Network.getArtifactsFromOIPd = function(callback){
axios.get(Core.OIPdURL + "/media/get/all", {
transformResponse: [function (data) {
return [...data];
}], responseType: 'json'
}).then( function(results){ callback([...results.data]); });
}
Core.Network.getLatestBTCPrice = function(callback){
if (Core.Network.btcpriceLastUpdate < Date.now() - Core.Network.btcpriceUpdateTimelimit || Core.Network.cachedBTCPriceObj === {}){
let _Core = Core;
axios.get(Core.btcTickerURL).then(function(result){
if (result.status === 200){
_Core.Network.cachedBTCPriceObj = result.data;
_Core.Network.btcpriceLastUpdate = Date.now();
callback(_Core.Network.cachedBTCPriceObj["USD"].last);
}
});
} else {
callback(Core.Network.cachedBTCPriceObj["USD"].last);
}
}
Core.Network.getIPFS = function(callback){
Core.ipfs.on('ready', () => {
callback(Core.ipfs);
})
}
Core.Network.getThumbnailFromIPFS = function(hash, onData, onEnd){
// Require a hash to be passed
if (!hash || hash === "")
return;
if (!onEnd){
onEnd = function(){}
}
let returned = false;
try {
Core.ipfs.files.cat(hash, function (err, file) {
if (err){
console.log(err);
return;
}
let stream = file;
let chunks = [];
if (stream){
stream.on('data', function(chunk) {
chunks.push(chunk);
// Note, this might cause tons of lag depending on how many ongoing IPFS requests we have.
Core.util.chunksToFileURL(chunks, function(data){
returned = true;
onData(data);
})
});
stream.on('end', function(){
Core.util.chunksToFileURL(chunks, function(data){
onEnd(data);
})
})
}
})
} catch (e){
onData(Core.util.buildIPFSURL(hash));
returned = true;
}
setTimeout(function(){
if (!returned){
onData(Core.util.buildIPFSURL(hash));
}
}, 2 * 1000)
}
Core.Network.getFileFromIPFS = function(hash, onComplete){
// Require a hash to be passed
if (!hash || hash === "")
return;
let returned = false;
try {
Core.ipfs.files.cat(hash, function (err, file) {
if (err){
returned = true;
return;
}
let stream = file;
let chunks = [];
if (stream){
stream.on('data', function(chunk) {
chunks.push(chunk);
});
stream.on('end', function(){
Core.util.chunksToFileURL(chunks, function(data){
onComplete(data, hash);
returned = true;
})
})
}
})
} catch(e) { }
setTimeout(function(){
if (!returned){
onComplete(Core.util.buildIPFSURL(hash), hash);
}
}, 2 * 1000)
}
Core.Network.getCommentsFromISSO = function(uri, callback){
axios.get(Core.issoURL + "?uri=" + encodeURIComponent(uri)).then(function(results){
callback(results);
}).catch(function (error) {
// If there is an error, it is likely because the artifact has no comments, just return an empty array.
callback([]);
});
}
Core.Network.postCommentToISSO = function(uri, comment, callback){
var instance = axios.create();
instance.post(Core.issoURL + "new?uri=" + encodeURIComponent(uri), comment, {headers: {"Content-Type": "application/json"}, transformRequest: [(data, headers) => {
delete headers.common.Authorization
return data }]
}).then(function(results){
callback(results);
}).catch(function (error) {
// If there is an error, it is likely because the artifact has no comments, just return an empty array.
callback({error: true});
});
}
Core.Network.likeISSOComment = function(id, callback){
axios.post(Core.issoURL + "id/" + id + "/like", {}).then(function(results){
callback(results);
}).catch(function (error) {
// If there is an error, it is likely because the artifact has no comments, just return an empty array.
callback({error: true});
});
}
Core.Network.dislikeISSOComment = function(id, callback){
axios.post(Core.issoURL + "id/" + id + "/dislike", {}).then(function(results){
callback(results);
}).catch(function (error) {
// If there is an error, it is likely because the artifact has no comments, just return an empty array.
callback({error: true});
});
}
Core.User = {};
Core.User.Identifier = "";
Core.User.Password = "";
Core.User.Login = function(identifier, password){
Core.User.Identifier = identifier;
Core.User.Password = password;
}
Core.User.Logout = function(){
Core.User.Identifier = "";
Core.User.Password = "";
}
Core.User.FollowPublisher = function(publisher){
}
Core.User.UnfollowPublisher = function(publisher){
}
Core.User.LikeArtifact = function(oip){
}
Core.User.NeturalArtifact = function(oip){
}
Core.User.DislikeArtifact = function(oip){
}
Core.User.UpdateArtifactView = function(oip, last_action, current_duration){
}
Core.util = {};
Core.util.chunksToFileURL = function(chunks, onLoad){
var reader = new FileReader();
reader.addEventListener("load", function () {
if (reader.result && reader.result != "data:"){
onLoad(reader.result);
}
}, false);
if (chunks) {
reader.readAsDataURL(new Blob(chunks));
}
}
Core.util.buildIPFSShortURL = function(artifact, file){
if (!artifact || !file)
return "";
let location = Core.Artifact.getLocation(artifact);
return location + "/" + file.fname;
}
Core.util.buildIPFSURL = function(hash, fname){
let trailURL = "";
if (!fname){
let parts = hash.split('/');
if (parts.length == 2){
trailURL = parts[0] + "/" + encodeURIComponent(parts[1]);
} else {
trailURL = hash;
}
} else {
trailURL = hash + "/" + encodeURIComponent(fname);
}
return Core.IPFSGatewayURL + trailURL;
}
Core.util.getExtension = function(filename){
let splitFilename = filename.split(".");
let indexToGrab = splitFilename.length - 1;
return splitFilename[indexToGrab];
}
Core.util.formatDuration = function(intDuration){
if (!intDuration || isNaN(intDuration))
return "";
var sec_num = parseInt(intDuration, 10); // don't forget the second param
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (minutes < 10) {
if (hours !== 0)
minutes = "0"+minutes;
}
if (seconds < 10) {
if (minutes !== 0)
seconds = "0"+seconds;
}
if (hours === 0)
var time = minutes+':'+seconds;
else
var time = hours+':'+minutes+':'+seconds;
return time;
}
Core.util.decodeMakeJSONSafe = function(stringToCheck){
let tmpStr = stringToCheck;
if (typeof tmpStr === "string" && tmpStr.substr(0,1) === '"' && tmpStr.substr(tmpStr.length-1,tmpStr.length) === '"')
tmpStr = eval(tmpStr);
return tmpStr;
}
Core.util.createPriceString = function(price){
// This function assumes the scale has already been applied, and you are passing it a float value
var priceStr = parseFloat(price.toFixed(3));
if (isNaN(priceStr)){
return 0;
}
let priceDecimal = priceStr - parseInt(priceStr);
if (priceDecimal.toString().length === 3){
priceStr = priceStr.toString() + "0";
}
return priceStr.toString();
}
Core.util.calculateBTCCost = function(usd_value, callback){
Core.Data.getBTCPrice(function(btc_price){
callback(usd_value / btc_price)
})
}
Core.util.convertBTCtoBits = function(btc_value){
return btc_value * Math.pow(10,6);
}
return Core;
})();
export default AlexandriaCore;