tilda-sync
Version:
Клиент для импорта сайта на Тильде (Tilda.cc) в проекте на Node.js.
288 lines (287 loc) • 10.5 kB
JavaScript
import fetch from 'node-fetch';
import utils from './utils.js';
import { handlePage } from './handlePage.js';
import { handleProjectData } from './handleProjectData.js';
import TildaRouterSrc from './TildaRouterSrc.js';
import { handleHtaccess } from './handleHtaccess.js';
class TildaSync {
TILDA_URL;
piblicKey;
secretKey;
debug;
constructor(options) {
let { publicKey, secretKey, debug } = options;
this.TILDA_URL = 'http://api.tildacdn.info/v1';
this.piblicKey = publicKey;
this.secretKey = secretKey;
this.debug = (debug === true) ? true : false;
}
getProjectsList = () => {
return new Promise(async (resolve, reject) => {
let projects;
try {
projects = await this.fetcher({
url: '/getprojectslist/'
});
resolve(projects);
}
catch (err) {
reject(err);
}
});
};
getPagesList = (projectId) => {
return new Promise(async (resolve, reject) => {
try {
const pages = await this.fetcher({
url: '/getpageslist/',
params: {
projectid: projectId
}
});
resolve(pages);
}
catch (err) {
reject(err);
}
});
};
getPage = (pageId) => {
return new Promise(async (resolve, reject) => {
let pages;
try {
pages = await this.fetcher({
url: '/getpage/',
params: {
pageid: pageId
}
});
resolve(pages);
}
catch (err) {
reject(err);
}
});
};
getPageFull = (pageId) => {
return new Promise(async (resolve, reject) => {
let pages;
try {
pages = await this.fetcher({
url: '/getpagefull/',
params: {
pageid: pageId
}
});
resolve(pages);
}
catch (err) {
reject(err);
}
});
};
getPageExport = (pageId) => {
return new Promise(async (resolve, reject) => {
let pages;
try {
pages = await this.fetcher({
url: '/getpageexport/',
params: {
pageid: pageId
}
});
resolve(pages);
}
catch (err) {
reject(err);
}
});
};
getPageFullExport = (pageId) => {
return new Promise(async (resolve, reject) => {
let pages;
try {
pages = await this.fetcher({
url: '/getpagefullexport/',
params: {
pageid: pageId
}
});
resolve(pages);
}
catch (err) {
reject(err);
}
});
};
getProjectExport = (projectId) => {
return new Promise(async (resolve, reject) => {
try {
const projectData = await this.fetcher({
url: '/getprojectexport/',
params: {
projectid: projectId
}
});
resolve(projectData);
}
catch (err) {
reject(err);
}
});
};
importProject = (projectId, folder = projectId, routerFile = { isEnabled: true, path: folder, filename: 'pages' + projectId + '.json' }) => {
return new Promise(async (resolve, reject) => {
if (this.debug)
console.time('⏱ Import site');
folder = folder + '';
const routerFileDefaults = { isEnabled: true, path: folder, filename: 'pages' + projectId + '.json' };
routerFile = { ...routerFileDefaults, ...routerFile };
if (routerFile.path === undefined || routerFile.path === '') {
routerFile.path = folder;
}
if (routerFile.isEnabled === undefined) {
routerFile.isEnabled = true;
}
if (routerFile.filename === undefined) {
routerFile.filename = 'pages' + projectId + '.json';
}
let toBeDownloaded = [];
let projectData;
try {
projectData = await this.getProjectExport(projectId);
if (projectData.status === 'ERROR') {
throw new Error('Tilda API responsed with an error status');
}
else if (projectData.status !== 'FOUND') {
throw new Error('Project not found');
}
let projectParseResult = await handleProjectData(projectData.result, folder, this.debug);
toBeDownloaded = [...projectParseResult.downloads];
if (routerFile.isEnabled === true) {
handleHtaccess(routerFile.filename, routerFile.path, projectData.result.htaccess, { logs: this.debug });
}
}
catch (err) {
this.debugMsg(err);
reject({ success: false, details: err.message });
return;
}
try {
let pages = await this.getPagesList(projectId);
if (pages.status === 'ERROR') {
throw new Error('Tilda API responsed with an error status');
}
else if (pages.status !== 'FOUND') {
throw new Error('No pages found');
}
let i = 0;
while (i < pages.result.length) {
let pageImportResult = await this.importPage(pages.result[i].id, folder, { download: false });
toBeDownloaded = [
...toBeDownloaded,
...pageImportResult.downloads
];
i++;
}
}
catch (err) {
this.debugMsg(err.message);
reject({ success: false, details: err.message });
}
try {
this.debugMsg('💾 Starting downloading all project files');
await this.staticDownloader(toBeDownloaded, folder, projectData.result.export_csspath);
}
catch (err) {
this.debugMsg(err.message);
reject({ success: false, details: err.message });
return;
}
this.debugMsg('👌 Project import finished successfully');
if (this.debug)
console.timeEnd('⏱ Import site');
resolve({ success: true });
});
};
importPage = (pageId, folder = 'imported_pages', options = { download: true }) => {
return new Promise(async (resolve, reject) => {
this.debugMsg('📡 Getting page #' + pageId);
let { download } = options;
let pageFullExport = await this.getPageFullExport(pageId);
let customCssFolder = pageFullExport.result.export_csspath;
let parseResult = await handlePage(pageFullExport.result, folder, { logs: this.debug });
if (download === true) {
this.debugMsg('💾 Starting downloading all project files');
await this.staticDownloader(parseResult.downloads, folder, customCssFolder);
}
if (parseResult.success === true) {
this.debugMsg('✅ Page has been imported');
resolve({ success: true, downloads: parseResult.downloads });
}
else {
reject({ success: false, details: 'Page parsing failed' });
}
});
};
staticDownloader = (arr, folder, exportCssPath = '') => {
return new Promise(async (resolve, reject) => {
try {
let toBeDownloadedFiltered = utils.filterDownloadList(arr, {
logs: this.debug
});
let i = 0;
while (i < toBeDownloadedFiltered.length) {
let fileInfo = toBeDownloadedFiltered[i];
utils.downloadFile(fileInfo, folder, this.debug);
if (fileInfo.to === 'custom.css' && exportCssPath !== '') {
let fileInfoUpd = { ...fileInfo };
fileInfoUpd.subfolder = '';
utils.downloadFile(fileInfoUpd, folder, this.debug);
}
await utils.addDelay(120);
i++;
}
resolve(true);
}
catch (err) {
this.debugMsg('❌ Error on downloader loop');
reject(err);
}
});
};
fetcher = (options) => {
return new Promise(async (resolve, reject) => {
let { url, params } = options;
try {
if (!url)
throw new Error('Missing URL');
let fetchOptions = {
method: 'GET',
};
let queryURL = this.TILDA_URL;
queryURL += url;
queryURL += '?publickey=' + this.piblicKey;
queryURL += '&secretkey=' + this.secretKey;
for (let key in params) {
queryURL += '&' + key + '=' + params[key];
}
const resultRaw = await fetch(queryURL, fetchOptions);
const result = await resultRaw.json();
if (result.status === 'ERROR') {
throw new Error('Fetched result status: ERROR');
}
resolve(result);
}
catch (err) {
reject(err);
}
});
};
debugMsg = (text) => {
if (this.debug === true)
console.log(text);
};
}
export const TildaRouter = TildaRouterSrc;
export default TildaSync;