This commit is contained in:
Mekan1206
2026-06-02 14:28:25 +05:00
commit b154d5c198
9 changed files with 2049 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules/
*.sqlite

37
db.js Normal file
View File

@@ -0,0 +1,37 @@
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
const dbPath = path.resolve(__dirname, 'database.sqlite');
const db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error('Error opening database', err.message);
} else {
console.log('Connected to the SQLite database.');
// Create devices table
db.run(`CREATE TABLE IF NOT EXISTS devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
login TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
)`, (err) => {
if (err) {
console.error('Error creating devices table', err);
} else {
// Insert a default device for testing if it doesn't exist
db.run(`INSERT OR IGNORE INTO devices (login, password) VALUES ('admin', 'admin123')`);
}
});
// Create sms_queue table
db.run(`CREATE TABLE IF NOT EXISTS sms_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
phone TEXT NOT NULL,
message TEXT NOT NULL,
status TEXT DEFAULT 'pending', -- pending, processing, sent, failed
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`);
}
});
module.exports = db;

1752
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

17
package.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "otp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"socket.io": "^4.7.4",
"sqlite3": "^6.0.1"
}
}

51
queueWorker.js Normal file
View File

@@ -0,0 +1,51 @@
const db = require('./db');
function startQueueWorker(io) {
console.log('Starting SMS Queue Worker...');
setInterval(() => {
// Check if there are any connected devices (we'll broadcast to the 'devices' room)
// For simplicity, we just fetch one pending message and emit it.
// If the app is connected, it will process it.
db.get(`SELECT * FROM sms_queue WHERE status = 'pending' ORDER BY created_at ASC LIMIT 1`, (err, row) => {
if (err) {
console.error('Queue Worker Error:', err);
return;
}
if (row) {
console.log(`Processing SMS ID: ${row.id} for ${row.phone}`);
// Mark as processing
db.run(`UPDATE sms_queue SET status = 'processing', updated_at = CURRENT_TIMESTAMP WHERE id = ?`, [row.id], (updateErr) => {
if (updateErr) {
console.error('Error updating status to processing:', updateErr);
return;
}
// Emit to authenticated devices
io.to('devices').emit('send_sms', {
id: row.id,
phone: row.phone,
message: row.message
});
// Note: If no device is connected, it stays in 'processing' state.
// A robust system would have a timeout to revert 'processing' back to 'pending'.
// We will add a simple timeout mechanism.
setTimeout(() => {
db.get(`SELECT status FROM sms_queue WHERE id = ?`, [row.id], (checkErr, checkRow) => {
if (checkRow && checkRow.status === 'processing') {
console.log(`SMS ID: ${row.id} timed out. Reverting to pending.`);
db.run(`UPDATE sms_queue SET status = 'pending' WHERE id = ?`, [row.id]);
}
});
}, 30000); // 30 seconds timeout
});
}
});
}, 5000); // Check every 5 seconds
}
module.exports = startQueueWorker;

35
readme.md Normal file
View File

@@ -0,0 +1,35 @@
📨 REST API
Endpoint:
# code derek bashga messageler hem ugradyp bilersiniz
POST /api/data
Body (JSON görnüşinde):
{
"phone": "63435005",
"code": "1234"
}
Jogap (Response):
{
"message": "Data received and processed successfully.",
"received": {
"phone": "63435005",
"code": "1234"
}
}
📡 Socket.IO Ulanylyşy
Baglanyşyk döretmek:
const socket = io("http://localhost:3000");
Ibermek:
socket.emit("sendSignInData", { phone: "63435005", code: "1234" });
Almak:
socket.on("sendSmsCode", (data) => {
console.log(data);
});

49
routes/api.js Normal file
View File

@@ -0,0 +1,49 @@
const express = require('express');
const db = require('../db');
module.exports = function (io) {
const router = express.Router();
// Existing endpoint (kept for compatibility if needed, or can be removed later)
router.post('/data', (req, res) => {
const { phone, code } = req.body;
if (!phone || !code) {
return res.status(400).json({ error: 'Phone and Code are required.' });
}
console.log('Received data at /api/data:', { phone, code });
io.emit('sendSignInData', { phone, code });
return res.status(200).json({
message: 'Data received and processed successfully.',
received: { phone, code }
});
});
// New endpoint to queue SMS
router.post('/sms', (req, res) => {
const { phone, message } = req.body;
if (!phone || !message) {
return res.status(400).json({ error: 'Phone and message are required.' });
}
// Insert into queue
db.run(`INSERT INTO sms_queue (phone, message) VALUES (?, ?)`, [phone, message], function(err) {
if (err) {
console.error('Error inserting into sms_queue:', err);
return res.status(500).json({ error: 'Failed to queue SMS.' });
}
return res.status(202).json({
message: 'SMS queued successfully.',
id: this.lastID
});
});
});
return router;
};

32
server.js Normal file
View File

@@ -0,0 +1,32 @@
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const bodyParser = require('body-parser');
const cors = require('cors');
const apiRoutes = require('./routes/api');
const socketHandler = require('./socket');
const startQueueWorker = require('./queueWorker');
require('./db'); // Initialize DB
const app = express();
const server = http.createServer(app);
const io = socketIo(server, {
cors: {
origin: '*',
methods: ['GET', 'POST']
}
});
app.use(cors());
app.use(bodyParser.json());
app.use('/api', apiRoutes(io));
socketHandler(io);
startQueueWorker(io);
const PORT = process.env.PORT || 3000;
server.listen(PORT, '0.0.0.0',() => {
console.log(`Server is running on http://0.0.0.0:${PORT}`);
});

74
socket.js Normal file
View File

@@ -0,0 +1,74 @@
const db = require('./db');
module.exports = function (io) {
// Middleware for authentication
io.use((socket, next) => {
const login = socket.handshake.auth.login;
const password = socket.handshake.auth.password;
if (!login || !password) {
// Allow normal web clients to connect without auth if needed,
// but we won't put them in the 'devices' room.
return next();
}
db.get(`SELECT * FROM devices WHERE login = ? AND password = ?`, [login, password], (err, row) => {
if (err) {
return next(new Error('Database error'));
}
if (!row) {
return next(new Error('Authentication error'));
}
// Attach device info to socket
socket.device = row;
next();
});
});
io.on('connection', (socket) => {
console.log('A user connected:', socket.id);
if (socket.device) {
console.log(`Device authenticated: ${socket.device.login}`);
socket.join('devices');
}
// Handle SMS status updates from the app
socket.on('sms_status', (data) => {
console.log('Received sms_status:', data);
const { id, status } = data; // status should be 'sent' or 'failed'
if (id && status) {
db.run(`UPDATE sms_queue SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, [status, id], (err) => {
if (err) {
console.error('Error updating SMS status:', err);
} else {
console.log(`Updated SMS ID ${id} to status: ${status}`);
}
});
}
});
// Existing events
socket.on('sendSignInData', (data) => {
console.log('sendSignInData:', data);
io.emit('sendSmsCode', { phone: data.phone, code: data.code });
});
socket.on('sendDatas', (data) => {
console.log('sendDatas:', data);
io.emit('sendData', { phone: data.phone, code: data.code });
});
socket.on('disconnect', () => {
console.log('User disconnected:', socket.id);
});
socket.on('error', (err) => {
console.error('Socket error:', err);
});
});
};