Skip to content

Instantly share code, notes, and snippets.

@xrabohrok
Created September 18, 2024 06:17
Show Gist options
  • Save xrabohrok/c74ee316bd23372f7d2327cd4b92ab30 to your computer and use it in GitHub Desktop.
Save xrabohrok/c74ee316bd23372f7d2327cd4b92ab30 to your computer and use it in GitHub Desktop.
deploy script for uploading to neocities.
import axios from 'axios';
import * as fs from 'fs';
import * as fspromise from 'fs/promises'
import * as readline from 'readline'
import FormData from 'form-data'
import execSync from 'child_process';
// current assumptions
const secretFile = 'secret';
const localArtifactRoot = 'src/.vuepress/dist/';
const batchSize = 3;
const excludeFiles = [
'sitemap.xsl' // this is a paid feature for Neocities
]
var neocityUser = '';
var neocityPW = '';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
var authKey = '';
while(authKey === ''){
if(!fs.existsSync(secretFile)){
console.log('No Key found');
console.log('==================');
neocityUser = await new Promise( resolve => {
rl.question('Please enter Neocities Username:', resolve);
});
neocityPW = await new Promise( resolve => {
rl.question('Please enter Neocities Password:', resolve);
});
neocityPW = encodeURI(neocityPW);
await axios.get( `https://${neocityUser}:${neocityPW}@neocities.org/api/key`)
.then( response => {
if(response.data?.result === 'success'){
authKey = response.data.api_key;
fs.writeFileSync(secretFile, authKey);
}
});
}
else{
console.log('Auth Key found');
authKey = fs.readFileSync(secretFile, {encoding:'ascii'});
//test the auth key because it might have expired
const neocities_temp = axios.create({
baseURL: 'https://neocities.org/api',
headers: {
Authorization: `Bearer ${authKey}`
}
});
var failed = false;
var result = await neocities_temp.get('/list')
.catch(reason => {
console.log(reason);
failed = true;
});
if( result?.status === 401 || result?.status === 403 || failed){
console.log('Nuking auth file, likely expired.')
fs.rmSync(secretFile);
authKey = '';
}
}
}
console.log(`Auth Key: ${authKey}`);
const neocities = axios.create({
baseURL: 'https://neocities.org/api',
headers: {
Authorization: `Bearer ${authKey}`
}
})
var executing = true;
while(executing){
console.log('What do you want to do?');
console.log('\t # 1. Update Build artifact');
console.log('\t # 2. Get Website Info');
console.log('\t # 3. Get a list of all files')
console.log('\t # 4. Upload to Neocities');
console.log('\t # 0. Quit');
var choice = await new Promise( resolve => {
rl.question('Choose from above:', resolve);
});
choice = choice.trim();
if(choice === '0'){
executing = false;
}
else if(choice === '1'){
if(fs.existsSync(localArtifactRoot)){
fs.rmSync(localArtifactRoot, {recursive: true});
console.log('dist folder nuked');
}
execSync.execSync('npm run docs:build');
}
else if(choice === '2'){
var info = await neocities.get('/info');
console.log(JSON.stringify(info.data));
}
else if(choice === '3'){
var info = await neocities.get('/list');
if(info.data?.result === 'success'){
var files = info.data.files.map(f =>{
return `${f?.size}\t | ${f?.updated_at} \t | ${f?.path} `
});
files.forEach(f => {
console.log(f);
});
}
}
else if(choice === '4'){
var distStructure = await fspromise.readdir(localArtifactRoot, {recursive: true, encoding: 'utf8', withFileTypes: true});
var filesToUpload = []
distStructure
.filter(d => !d.isDirectory())
.filter(f => excludeFiles.findIndex(ex => f.name.includes(ex)) < 0)
.forEach(d =>{
const normalizedFileName = `${d.parentPath.replace(/\/$/, '')}/${d.name}`
filesToUpload.push({
localFile: normalizedFileName,
remoteFile: normalizedFileName.replace(localArtifactRoot, '')
})
});
var batchNum = 0
for(let i = 0; i < filesToUpload.length; i += batchSize){
var batch = filesToUpload.slice(i, i + batchSize);
var formData = new FormData();
batch.forEach(bi => {
formData.append(bi.remoteFile, fs.createReadStream(bi.localFile));
});
await neocities.post('upload', formData, {
headers: {
...formData.getHeaders()
},
}).then( () => {
batchNum += 1;
console.log(`batch ${batchNum} of ${Math.ceil(filesToUpload.length/batchSize)} Success`);
});
}
console.log(`Number of files: ${distStructure.length}`);
}
else {
console.log(`Command not Recognized: ${choice}`);
}
}
process.exit(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment