p5.js-web-editor/server/scripts/examples.js

330 lines
10 KiB
JavaScript

import rp from 'request-promise';
import Q from 'q';
import mongoose from 'mongoose';
import objectID from 'bson-objectid';
import shortid from 'shortid';
import eachSeries from 'async/eachSeries';
import User from '../models/user';
import Project from '../models/project';
const defaultHTML =
`<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
`;
const defaultCSS =
`html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
`;
const clientId = process.env.GITHUB_ID;
const clientSecret = process.env.GITHUB_SECRET;
const headers = { 'User-Agent': 'p5js-web-editor/0.0.1' };
const mongoConnectionString = process.env.MONGO_URL;
mongoose.connect(mongoConnectionString, { useMongoClient: true });
mongoose.connection.on('error', () => {
console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
process.exit(1);
});
function getCategories() {
const categories = [];
const options = {
url: `https://api.github.com/repos/processing/p5.js-website/contents/src/data/examples/en?client_id=${
clientId}&client_secret=${clientSecret}`,
method: 'GET',
headers,
json: true
};
return rp(options).then((res) => {
res.forEach((metadata) => {
let category = '';
for (let j = 1; j < metadata.name.split('_').length; j += 1) {
category += `${metadata.name.split('_')[j]} `;
}
categories.push({ url: metadata.url, name: category.trim() });
});
return categories;
}).catch((err) => {
throw err;
});
}
function getSketchesInCategories(categories) {
return Q.all(categories.map((category) => {
const options = {
url: `${category.url.replace('?ref=master', '')}?client_id=${clientId}&client_secret=${clientSecret}`,
method: 'GET',
headers,
json: true
};
return rp(options).then((res) => {
const projectsInOneCategory = [];
res.forEach((example) => {
let projectName;
if (example.name === '02_Instance_Container.js') {
for (let i = 1; i < 5; i += 1) {
const instanceProjectName = `${category.name}: Instance Container ${i}`;
projectsInOneCategory.push({ sketchUrl: example.download_url, projectName: instanceProjectName });
}
} else {
if (example.name.split('_')[1]) {
projectName = `${category.name}: ${example.name.split('_').slice(1).join(' ').replace('.js', '')}`;
} else {
projectName = `${category.name}: ${example.name.replace('.js', '')}`;
}
projectsInOneCategory.push({ sketchUrl: example.download_url, projectName });
}
});
return projectsInOneCategory;
}).catch((err) => {
throw err;
});
}));
}
function getSketchContent(projectsInAllCategories) {
return Q.all(projectsInAllCategories.map(projectsInOneCategory => Q.all(projectsInOneCategory.map((project) => {
const options = {
url: `${project.sketchUrl.replace('?ref=master', '')}?client_id=${clientId}&client_secret=${clientSecret}`,
method: 'GET',
headers
};
return rp(options).then((res) => {
const noNumberprojectName = project.projectName.replace(/(\d+)/g, '');
if (noNumberprojectName === 'Instance Mode: Instance Container ') {
for (let i = 0; i < 4; i += 1) {
const splitedRes = `${res.split('*/')[1].split('</html>')[i]}</html>\n`;
project.sketchContent = splitedRes.replace(
'p5.js',
'https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js'
);
}
} else {
project.sketchContent = res;
}
return project;
}).catch((err) => {
throw err;
});
}))));
}
function createProjectsInP5user(projectsInAllCategories) {
const options = {
url: `https://api.github.com/repos/processing/p5.js-website/contents/src/data/examples/assets?client_id=${
clientId}&client_secret=${clientSecret}`,
method: 'GET',
headers,
json: true
};
rp(options).then((res) => {
User.findOne({ username: 'p5' }, (err, user) => {
if (err) throw err;
eachSeries(projectsInAllCategories, (projectsInOneCategory, categoryCallback) => {
eachSeries(projectsInOneCategory, (project, projectCallback) => {
let newProject;
const a = objectID().toHexString();
const b = objectID().toHexString();
const c = objectID().toHexString();
const r = objectID().toHexString();
const noNumberprojectName = project.projectName.replace(/(\d+)/g, '');
if (noNumberprojectName === 'Instance Mode: Instance Container ') {
newProject = new Project({
name: project.projectName,
user: user._id,
files: [
{
name: 'root',
id: r,
_id: r,
children: [a, b, c],
fileType: 'folder'
},
{
name: 'sketch.js',
content: '// Instance Mode: Instance Container, please check its index.html file',
id: a,
_id: a,
fileType: 'file',
children: []
},
{
name: 'index.html',
content: project.sketchContent,
isSelectedFile: true,
id: b,
_id: b,
fileType: 'file',
children: []
},
{
name: 'style.css',
content: defaultCSS,
id: c,
_id: c,
fileType: 'file',
children: []
}
],
_id: shortid.generate()
});
} else {
newProject = new Project({
name: project.projectName,
user: user._id,
files: [
{
name: 'root',
id: r,
_id: r,
children: [a, b, c],
fileType: 'folder'
},
{
name: 'sketch.js',
content: project.sketchContent,
id: a,
_id: a,
isSelectedFile: true,
fileType: 'file',
children: []
},
{
name: 'index.html',
content: defaultHTML,
id: b,
_id: b,
fileType: 'file',
children: []
},
{
name: 'style.css',
content: defaultCSS,
id: c,
_id: c,
fileType: 'file',
children: []
}
],
_id: shortid.generate()
});
}
const assetsInProject = project.sketchContent.match(/assets\/[\w-]+\.[\w]*/g)
|| project.sketchContent.match(/asset\/[\w-]*/g) || [];
assetsInProject.forEach((assetNamePath, i) => {
let assetName = assetNamePath.split('assets/')[1];
res.forEach((asset) => {
if (asset.name === assetName || asset.name.split('.')[0] === assetName) {
assetName = asset.name;
}
});
if (assetName !== '') {
if (i === 0) {
const id = objectID().toHexString();
newProject.files.push({
name: 'assets',
id,
_id: id,
children: [],
fileType: 'folder'
});
// add assets folder inside root
newProject.files[0].children.push(id);
}
const fileID = objectID().toHexString();
newProject.files.push({
name: assetName,
url: `https://cdn.jsdelivr.net/gh/processing/p5.js-website@master/src/data/examples/assets/${assetName}`,
id: fileID,
_id: fileID,
children: [],
fileType: 'file'
});
console.log(`create assets: ${assetName}`);
// add asset file inside the newly created assets folder at index 4
newProject.files[4].children.push(fileID);
}
});
newProject.save((saveErr, savedProject) => {
if (saveErr) throw saveErr;
console.log(`Created a new project in p5 user: ${savedProject.name}`);
projectCallback();
});
}, (categoryErr) => {
categoryCallback();
});
}, (examplesErr) => {
process.exit();
});
});
}).catch((err) => {
throw err;
});
}
function getp5User() {
User.findOne({ username: 'p5' }, (err, user) => {
if (err) throw err;
let p5User = user;
if (!p5User) {
p5User = new User({
username: 'p5',
email: process.env.EXAMPLE_USER_EMAIL,
password: process.env.EXAMPLE_USER_PASSWORD
});
p5User.save((saveErr) => {
if (saveErr) throw saveErr;
console.log(`Created a user p5 ${p5User}`);
});
}
Project.find({ user: p5User._id }, (projectsErr, projects) => {
// if there are already some sketches, delete them
console.log('Deleting old projects...');
projects.forEach((project) => {
Project.remove({ _id: project._id }, (removeErr) => {
if (removeErr) throw removeErr;
});
});
});
return getCategories()
.then(getSketchesInCategories)
.then(getSketchContent)
.then(createProjectsInP5user);
});
}
getp5User();