Merge pull request #12 from greirson/add-notifications

Add notifications support via Apprise
This commit is contained in:
abite
2025-01-31 00:00:40 -06:00
committed by GitHub
6 changed files with 64 additions and 2 deletions

View File

@@ -5,4 +5,8 @@ PORT=3000 # The port the server will listen on
MAX_FILE_SIZE=1024 # Maximum file size in MB (default: 1024 MB / 1 GB)
# Security
DUMBDROP_PIN= # Optional 4-digit PIN protection (leave empty to disable)
DUMBDROP_PIN= # Optional 4-digit PIN protection (leave empty to disable)
# Notifications
APPRISE_URL= # Apprise URL for notifications (leave empty to disable)
APPRISE_MESSAGE= # Custom message for notifications (default: "File uploaded: {filename}")

View File

@@ -1,5 +1,16 @@
FROM node:18-alpine
# Install python and create virtual environment
RUN apk add --no-cache python3 py3-pip && \
python3 -m venv /opt/venv
# Activate virtual environment and install apprise
RUN . /opt/venv/bin/activate && \
pip install --no-cache-dir apprise
# Add virtual environment to PATH
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY package*.json ./

View File

@@ -18,6 +18,8 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up
- Configurable file size limits
- Drag and Drop Directory Support (Maintains file structure in upload)
- Optional PIN protection (4-10 digits) with secure validation
- Configurable notifications via Apprise
- Custom notification messages with filename templating
## Environment Variables
@@ -26,6 +28,8 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up
| PORT | Server port | 3000 | No |
| MAX_FILE_SIZE| Maximum file size in MB | 1024 | No |
| DUMBDROP_PIN | PIN protection (4-10 digits) | None | No |
| APPRISE_URL | Apprise URL for notifications | None | No |
| APPRISE_MESSAGE| Notification message template | "File uploaded: {filename}" | No |
## Security Features
@@ -35,6 +39,12 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up
- Secure PIN validation middleware
- No PIN storage in browser (memory only)
## Notification Support
- Integration with [Apprise](https://github.com/caronc/apprise?tab=readme-ov-file#supported-notifications) for flexible notifications
- Support for all Apprise notification services
- Customizable notification messages with filename templating
- Optional - disabled if no APPRISE_URL is set
# Future Features
- Camera Upload for Mobile
- Enhanced Progress Features (upload speed display, time remaining estimation)
@@ -87,6 +97,8 @@ services:
- $(pwd)/local_uploads:/app/uploads
environment:
- DUMBDROP_PIN=123456
# - APPRISE_URL= # i.e. tgram://bottoken/ChatID
# - APPRISE_MESSAGE=
image: abite3/dumbdrop:latest
```

View File

@@ -4,7 +4,9 @@ services:
ports:
- 3000:3000
volumes:
- $(pwd)/local_uploads:/app/uploads
- ./local_uploads:/app/uploads
environment:
- DUMBDROP_PIN=123456
- APPRISE_URL= # i.e. tgram://bottoken/ChatID
- APPRISE_MESSAGE= # dont add quotes here
image: abite3/dumbdrop:latest

View File

@@ -12,6 +12,7 @@
"license": "ISC",
"description": "A simple file upload application",
"dependencies": {
"apprise": "^1.0.0",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.0.3",

View File

@@ -5,12 +5,17 @@ const cors = require('cors');
const fs = require('fs');
const crypto = require('crypto');
const cookieParser = require('cookie-parser');
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);
require('dotenv').config();
const app = express();
const port = process.env.PORT || 3000;
const uploadDir = './uploads'; // Local development
const maxFileSize = parseInt(process.env.MAX_FILE_SIZE || '1024') * 1024 * 1024; // Convert MB to bytes
const APPRISE_URL = process.env.APPRISE_URL;
const APPRISE_MESSAGE = process.env.APPRISE_MESSAGE || 'File uploaded: {filename}';
// Brute force protection setup
const loginAttempts = new Map(); // Stores IP addresses and their attempt counts
@@ -291,6 +296,9 @@ app.post('/upload/chunk/:uploadId', express.raw({
upload.writeStream.end();
uploads.delete(uploadId);
log.success(`Upload completed: ${upload.filename}`);
// Add notification here
sendNotification(upload.filename);
}
} catch (err) {
log.error(`Chunk upload failed: ${err.message}`);
@@ -325,6 +333,15 @@ app.listen(port, () => {
log.info(`Server running at http://localhost:${port}`);
log.info(`Upload directory: ${uploadDir}`);
// Add Apprise configuration logging
if (APPRISE_URL) {
log.info(`Apprise notifications enabled`);
log.info(`Apprise URL: ${APPRISE_URL}`);
log.info(`Apprise message template: ${APPRISE_MESSAGE}`);
} else {
log.info('Apprise notifications disabled - no URL configured');
}
// List directory contents
try {
const files = fs.readdirSync(uploadDir);
@@ -336,3 +353,18 @@ app.listen(port, () => {
log.error(`Failed to list directory contents: ${err.message}`);
}
});
// Add this helper function after other helper functions
async function sendNotification(filename) {
if (!APPRISE_URL) return;
try {
const message = APPRISE_MESSAGE.replace('{filename}', filename);
// Execute apprise command
await execAsync(`apprise "${APPRISE_URL}" -b "${message}"`);
log.info(`Notification sent for: ${filename}`);
} catch (err) {
log.error(`Failed to send notification: ${err.message}`);
}
}