Skip to content

Commit

Permalink
feat: Add plugins page
Browse files Browse the repository at this point in the history
  • Loading branch information
shdwmtr committed Jan 3, 2025
1 parent 46a0f10 commit f0c19fa
Show file tree
Hide file tree
Showing 18 changed files with 4,620 additions and 803 deletions.
125 changes: 115 additions & 10 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,24 @@ const { cache_handler, reset } = require("./middleware/cache.js")
const { rate_limit } = require("./middleware/rate-limiter.js")

admin.initializeApp({
credential: admin.credential.cert(require('./credentials/cert.json'))
credential: admin.credential.cert(require('./credentials/cert.json')),
storageBucket: "millennium-d9ce0.appspot.com"
});

const bucket = admin.storage().bucket();
const db = admin.firestore();

const { check_updates } = require("./v2/check-updates.js")
const { get_details } = require('./v2/get-details.js')
const { get_featured } = require('./v2/featured.js')
const { get_update_v2 } = require("./v2/get-update.js")
const { get_update } = require("./v2/get-update.js")
const { download } = require("./v2/download.js")

const { RetreivePluginList } = require("./plugin/GetPluginList.js")
const { RetrievePluginList } = require("./plugin/GetPluginList.js")
const { GetPluginData } = require("./plugin/GetPluginData.js")
const { GetDownloadInfo } = require("./plugin/GetDownloadInfo.js")
const { GetPluginMetadata } = require("./plugin/GetPluginMetadata.js")

millennium.get("/api/updater", cache_handler, (_, res) => {
res.json({
Expand Down Expand Up @@ -95,20 +101,119 @@ millennium.get("/api/cache/reset", cache_handler, (_, res) => {
/**
* Support for plugins
*/
const FetchPlugins = async () => {
return new Promise(async (resolve, reject) => {
try {
const pluginList = await RetrievePluginList();

// Fetch all plugin metadata, data, and download counts in parallel
const [metadata, pluginData] = await Promise.all([
GetPluginMetadata(),
GetPluginData(pluginList)
]);

// Fetch all download counts in one Firestore call
const downloadDocs = await db.collection('downloads').get();
const downloadCounts = {};
downloadDocs.forEach(doc => {
downloadCounts[doc.id] = doc.data().downloadCount || 0;
});


// Process the plugin data
for (const key in pluginData) {
const data = metadata.find(meta => meta.commitId === pluginData[key].id);
if (data) {
const pluginId = data.id.substring(0, 12); // Shortened ID
const initCommitId = data.id; // Full ID

pluginData[key].downloadCount = downloadCounts[initCommitId] ?? 0;
pluginData[key].id = pluginId;
pluginData[key].initCommitId = initCommitId;
}
}

resolve(pluginData);
}
catch (error) {
console.error("An error occurred while processing plugins:", error);
reject(error);
}
});
};

millennium.get("/api/v1/plugins", cache_handler, async (req, res) => {
const pluginList = await RetreivePluginList()
const pluginData = await GetPluginData(pluginList)

res.json(pluginData)
res.json(await FetchPlugins())
})

millennium.get("/api/v1/plugins/:id", cache_handler, async (req, res) => {
const pluginList = await RetreivePluginList()
const pluginData = await GetPluginData(pluginList)
millennium.get("/api/v1/plugin/:id", cache_handler, async (req, res) => {
const plugin = (await FetchPlugins()).find(plugin => plugin.id === req.params.id)

const plugin = pluginData.find(plugin => plugin.id === req.params.id)
try {
const pluginBuild = bucket.file(`plugins/${plugin.initCommitId}.zip`);
const [ exists ] = await pluginBuild.exists()

if (exists) {
const [ metadata ] = await pluginBuild.getMetadata()
plugin.commitDate = new Date(metadata.updated) > new Date(metadata.timeCreated) ? metadata.updated : metadata.timeCreated;
plugin.fileSize = Number(metadata.size);
plugin.hasValidBuild = true;
}
else {
console.warn(`Plugin ${plugin.id} does not have a build available.`)
plugin.hasValidBuild = false;
}
}
catch (error) {
console.error("An error occurred while checking plugin build:", error);
plugin.hasValidBuild = false;
}

plugin.downloadUrl = `/api/v1/plugins/download/?id=${plugin?.initCommitId}&n=${plugin?.pluginJson?.name}.zip`;

console.log("Sending plugin", plugin)
res.json(plugin)
})

millennium.get('/api/v1/plugins/download', async (req, res) => {
console.log("Getting download info for", req.query.id);
const fileName = req.query.id;

console.log(req.query)
const downloadFileName = req.query.n;

console.log("using filename", downloadFileName);
const file = bucket.file(`plugins/${fileName}.zip`);

// Increment the download count in Firestore
try {

const docRef = db.collection('downloads').doc(fileName);
await docRef.set(
{ downloadCount: admin?.firestore?.FieldValue?.increment(1) ?? 1 },
{ merge: true }
);
console.log(`Download count incremented for ${fileName}`);
}
catch (err) {
console.error('Error updating download count:', err);
// Continue processing the request even if updating count fails
}

file.createReadStream()
.on('error', (err) => {
console.error('Error streaming file:', err);
res.status(500).send('Error streaming file');
})
.on('response', (response) => {
res.setHeader('Content-Type', response.headers['content-type']);
res.setHeader('Content-Disposition', `attachment; filename="${downloadFileName}"`);
})
.pipe(res)
.on('finish', () => {
console.log(`File ${fileName} streamed successfully!`);
});
});


exports.api = functions.https.onRequest(millennium)
6 changes: 3 additions & 3 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase emulators:start --only functions --project=steam-brew",
"shell": "firebase functions:shell --project=steam-brew --port=3000",
"shell": "firebase functions:shell --project=steam-brew --port=3001",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"deploy": "firebase deploy --only functions --project=steam-brew",
"logs": "firebase functions:log"
},
"engines": {
Expand All @@ -23,4 +23,4 @@
"firebase-functions-test": "^3.1.0"
},
"private": true
}
}
30 changes: 30 additions & 0 deletions api/plugin/GetDownloadInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const GetDownloadInfo = async () => {
return new Promise((resolve, reject) => {
fetch("https://api.github.com/repos/shdwmtr/plugdb/releases", {
headers: {
'Authorization': process.env.BEARER,
'Content-Type': 'application/json'
},
})
.then(text => text.json())
.then(data => {

let downloadCounts = {};

data.forEach(release => {
release.assets.forEach(asset => {
if (downloadCounts[asset.name]) {
downloadCounts[asset.name] += asset.download_count;
} else {
downloadCounts[asset.name] = asset.download_count;
}
});
});

resolve(downloadCounts);
})
.catch(err => { reject(err) })
})
}

module.exports = { GetDownloadInfo }
13 changes: 7 additions & 6 deletions api/plugin/GetPluginData.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const GetPluginData = (pluginList) => {
repoOwner: owner {
login
}
commitId: object(expression: "${repo.commit}") {
... on Commit {
oid
}
}
}
`).join('\n')}
}
Expand All @@ -49,7 +54,7 @@ const GetPluginData = (pluginList) => {
const response = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.BEARER}`,
'Authorization': process.env.BEARER,
'Content-Type': 'application/json'
},
body: JSON.stringify({ query })
Expand All @@ -64,9 +69,6 @@ const GetPluginData = (pluginList) => {
const jsonResponse = Object.values(data.data).map(repository => repository).map(repo => {
const pluginJson = JSON.parse(repo.pluginJson.text);

const id = HashInformation(repo.repoOwner.login, repo.repoName);
mutablePluginData[id] = mutablePluginData?.[id] != undefined ? mutablePluginData[id] : 0;

return {
pluginJson: pluginJson,
usesBackend: pluginJson?.useBackend === true || pluginJson?.useBackend === undefined,
Expand All @@ -76,8 +78,7 @@ const GetPluginData = (pluginList) => {
commitDate: repo.commit.committedDate,
repoName: repo.repoName,
repoOwner: repo.repoOwner.login,
id: id,
downloadCount: mutablePluginData[id]
id: repo.commitId.oid
}
});

Expand Down
6 changes: 3 additions & 3 deletions api/plugin/GetPluginList.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const querystring = require("querystring")

const RetreivePluginList = async () => {
const RetrievePluginList = async () => {
return new Promise((resolve, reject) => {
fetch("https://api.github.com/repos/shdwmtr/plugdb/contents/plugins", {
headers: {
'Authorization': `Bearer ${process.env.BEARER}`,
'Authorization': process.env.BEARER,
'Content-Type': 'application/json'
},
})
Expand All @@ -30,4 +30,4 @@ const RetreivePluginList = async () => {
})
}

module.exports = { RetreivePluginList }
module.exports = { RetrievePluginList }
17 changes: 17 additions & 0 deletions api/plugin/GetPluginMetadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const GetPluginMetadata = async () => {
return new Promise((resolve, reject) => {
fetch("https://raw.githubusercontent.com/shdwmtr/plugdb/refs/heads/main/metadata.json", {
headers: {
'Authorization': process.env.BEARER,
'Content-Type': 'application/json'
},
})
.then(text => text.json())
.then(data => {
resolve(data);
})
.catch(err => { reject(err) })
})
}

module.exports = { GetPluginMetadata }
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"geist": "^1.3.0",
"hast-util-sanitize": "^5.0.2",
"highlight.js": "^11.10.0",
"next": "14.1.0",
"notyf": "^3.10.0",
Expand All @@ -21,11 +22,13 @@
"react-select": "^5.8.0",
"react-toastify": "^10.0.5",
"react-tooltip": "^5.26.4",
"rehype-sanitize": "^6.0.0",
"rehype-stringify": "^10.0.0",
"remark-gfm": "^4.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"unified": "^11.0.4"
"unified": "^11.0.4",
"unist-util-visit": "^5.0.0"
},
"devDependencies": {
"@fullhuman/postcss-purgecss": "^6.0.0"
Expand Down
26 changes: 26 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f0c19fa

Please sign in to comment.