mirror of
https://github.com/SophiaAtkinson/discord-hedgedoc-md.git
synced 2025-06-26 22:37:41 -07:00
Initial commit (v1.0.5)
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
config.json
|
||||||
|
data/state.json
|
||||||
|
old.js
|
||||||
|
package-lock.json
|
13
config.json.example
Normal file
13
config.json.example
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "first",
|
||||||
|
"markdownURL": "https://example.com/s/example/download",
|
||||||
|
"webhookURL": "https://discord.com/api/webhooks/example/example"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "second",
|
||||||
|
"markdownURL": "https://example.com/s/example/download",
|
||||||
|
"webhookURL": "https://discord.com/api/webhooks/example/example"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
145
index.js
Normal file
145
index.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
const axios = require('axios');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// --- CONFIG ---
|
||||||
|
const pollIntervalMs = 30 * 1000; // 30 seconds
|
||||||
|
const configPath = path.join(__dirname, 'config.json');
|
||||||
|
const statePath = path.join(__dirname, './data/state.json');
|
||||||
|
|
||||||
|
// Load configs
|
||||||
|
let configs;
|
||||||
|
try {
|
||||||
|
configs = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❗ Failed to load config.json:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load or initialize global state
|
||||||
|
let state = {};
|
||||||
|
if (fs.existsSync(statePath)) {
|
||||||
|
try {
|
||||||
|
state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❗ Failed to load state.json:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save global state
|
||||||
|
function saveState() {
|
||||||
|
fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize content
|
||||||
|
function normalizeContent(content) {
|
||||||
|
return content.replace(/\r\n/g, '\n').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch markdown content
|
||||||
|
async function fetchMarkdown(url) {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(url);
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❗ Error fetching markdown:', error.message);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a new message
|
||||||
|
async function createNewMessage(config) {
|
||||||
|
try {
|
||||||
|
const content = state[config.name].lastContent;
|
||||||
|
const payload = { content: content.length > 2000 ? content.slice(0, 1997) + '...' : content };
|
||||||
|
const { data } = await axios.post(`${config.webhookURL}?wait=true`, payload);
|
||||||
|
if (data?.id) {
|
||||||
|
state[config.name].messageId = data.id;
|
||||||
|
saveState();
|
||||||
|
console.log(`✅ [${config.name}] New message sent and ID saved.`);
|
||||||
|
} else {
|
||||||
|
console.error(`❗ [${config.name}] Failed to get message ID.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ [${config.name}] Error sending new message:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update existing message
|
||||||
|
async function updateMessage(config) {
|
||||||
|
try {
|
||||||
|
const content = state[config.name].lastContent;
|
||||||
|
const payload = { content: content.length > 2000 ? content.slice(0, 1997) + '...' : content };
|
||||||
|
await axios.patch(`${config.webhookURL}/messages/${state[config.name].messageId}`, payload);
|
||||||
|
console.log(`✅ [${config.name}] Message updated.`);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response && error.response.status === 404) {
|
||||||
|
console.error(`⚠️ [${config.name}] Message not found (deleted?). Creating new...`);
|
||||||
|
state[config.name].messageId = '';
|
||||||
|
await createNewMessage(config);
|
||||||
|
} else {
|
||||||
|
console.error(`❌ [${config.name}] Error updating message:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate existing message
|
||||||
|
async function validateExistingMessage(config) {
|
||||||
|
if (!state[config.name]?.messageId) return;
|
||||||
|
try {
|
||||||
|
await axios.get(`${config.webhookURL}/messages/${state[config.name].messageId}`);
|
||||||
|
console.log(`✅ [${config.name}] Existing message validated.`);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response && error.response.status === 404) {
|
||||||
|
console.error(`⚠️ [${config.name}] Message not found. Will create new.`);
|
||||||
|
state[config.name].messageId = '';
|
||||||
|
} else {
|
||||||
|
console.error(`❗ [${config.name}] Error validating message:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for updates for a single config
|
||||||
|
async function checkForUpdates(config) {
|
||||||
|
if (!state[config.name]) {
|
||||||
|
state[config.name] = { messageId: '', lastContent: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
await validateExistingMessage(config);
|
||||||
|
|
||||||
|
console.log(`🔄 [${config.name}] Checking for updates...`);
|
||||||
|
const markdown = await fetchMarkdown(config.markdownURL);
|
||||||
|
const normalizedMarkdown = normalizeContent(markdown);
|
||||||
|
|
||||||
|
if (!normalizedMarkdown) {
|
||||||
|
console.log(`⚠️ [${config.name}] No content fetched.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state[config.name].messageId) {
|
||||||
|
console.log(`📄 [${config.name}] No message ID found, creating...`);
|
||||||
|
state[config.name].lastContent = normalizedMarkdown;
|
||||||
|
await createNewMessage(config);
|
||||||
|
} else if (normalizedMarkdown !== state[config.name].lastContent) {
|
||||||
|
console.log(`📄 [${config.name}] Content changed, updating...`);
|
||||||
|
state[config.name].lastContent = normalizedMarkdown;
|
||||||
|
saveState();
|
||||||
|
await updateMessage(config);
|
||||||
|
} else {
|
||||||
|
console.log(`⏳ [${config.name}] No changes detected.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
(async () => {
|
||||||
|
console.log('🚀 Starting poller...');
|
||||||
|
for (const config of configs) {
|
||||||
|
await checkForUpdates(config);
|
||||||
|
}
|
||||||
|
setInterval(async () => {
|
||||||
|
for (const config of configs) {
|
||||||
|
await checkForUpdates(config);
|
||||||
|
}
|
||||||
|
}, pollIntervalMs);
|
||||||
|
})();
|
17
package.json
Normal file
17
package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "discord-hedgedoc-md",
|
||||||
|
"version": "1.0.5",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node index.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Sophia Atkinson",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.9.0",
|
||||||
|
"fs": "^0.0.1-security",
|
||||||
|
"path": "^0.12.7"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user