This commit is contained in:
2025-09-09 00:10:53 +03:00
parent 38f2a05107
commit 204fc092d7
239 changed files with 22447 additions and 9536 deletions

View File

@@ -51,7 +51,12 @@ cd /home/rozenrod/webapps/sheep-service.com
```
```
docker-compose pull && docker-compose -p Sheep-Service up --build -d
cd /home/rozenrod/webapps/sheep-service.com && docker-compose pull && docker-compose -p sheep-service up --build -d api ws web
```
or
```
cd /home/rozenrod/webapps/sheep-service.com && docker-compose pull && docker-compose --profile with-nginx -p sheep-service up --build -d
```
<br>
@@ -259,3 +264,28 @@ echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time;
```
sudo /opt/certbot/bin/pip install --upgrade certbot certbot-nginx
```
<br>
<br>
# CRONTAB
```
crontab -e
```
```
#####################
# Script for saving a backup copy of the Sheep-Service database every day at 22:30
30 22 * * * cd /home/rozenrod/webapps/sheep-service.com && /usr/bin/python3 backup.py >> /home/rozenrod/webapps/sheep-service.com/log/backup.log 2>&1
#####################
```
```
sudo pip3 install python-dotenv
```
<br>
<br>

View File

@@ -1,9 +1,10 @@
const express = require('express');
const app = express();
const routes = require('./routes/index');
require("dotenv").config();
// const cors = require('cors');
const port = 4000;
const port = process.env.API_PORT || 4000;
// app.use(cors())
app.use(express.json({ limit: '50mb' }));

View File

@@ -4,31 +4,210 @@ const path = require('path');
const dbPath = process.env.DATABASE_PATH || '../';
const db = new sqlite3.Database(path.join(dbPath, 'database.sqlite'));
// db.serialize(() => {
// db.run(`
// CREATE TABLE IF NOT EXISTS sheeps (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// uuid TEXT UNIQUE
// )
// `);
db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS sheeps (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER,
name TEXT,
icon TEXT,
uuid TEXT,
uuid_manager TEXT,
appointment TEXT DEFAULT 'lamb',
mode INTEGER DEFAULT 0,
mode_title TEXT DEFAULT 'Користувач'
)
`);
// db.run(`
// CREATE TABLE IF NOT EXISTS administrators (
// sheep_id INTEGER PRIMARY KEY,
// can_view_sheeps INTEGER DEFAULT 0,
// FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
// )
// `);
db.run(`
CREATE TABLE IF NOT EXISTS possibilities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sheep_id INTEGER,
can_add_sheeps INTEGER DEFAULT 0,
can_view_sheeps INTEGER DEFAULT 0,
can_add_territory INTEGER DEFAULT 0,
can_view_territory INTEGER DEFAULT 0,
can_manager_territory INTEGER DEFAULT 0,
can_add_stand INTEGER DEFAULT 0,
can_view_stand INTEGER DEFAULT 0,
can_manager_stand INTEGER DEFAULT 0,
can_add_schedule INTEGER DEFAULT 0,
can_view_schedule INTEGER DEFAULT 0,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
// db.run(`
// CREATE TABLE IF NOT EXISTS sessions (
// session_id TEXT PRIMARY KEY,
// sheep_id INTEGER,
// role TEXT DEFAULT 'sheep',
// expires_at INTEGER,
// FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
// )
// `);
// });
db.run(`
CREATE TABLE IF NOT EXISTS groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_number INTEGER,
share_hash TEXT
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS subscription (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sheep_id INTEGER,
token TEXT,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS badges (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sheep_id INTEGER,
quantity INTEGER,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS house (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER,
title TEXT,
number TEXT,
points TEXT DEFAULT '[]',
points_number TEXT DEFAULT '[]',
geo TEXT DEFAULT '[]',
osm_id TEXT DEFAULT '[]',
settlement TEXT,
description TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
FOREIGN KEY (group_id) REFERENCES groups(group_number)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS entrance (
id INTEGER PRIMARY KEY AUTOINCREMENT,
house_id INTEGER,
entrance_number INTEGER,
title TEXT,
points TEXT DEFAULT '[]',
points_number TEXT DEFAULT '[]',
floors_quantity TEXT,
apartments_quantity TEXT,
description TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
FOREIGN KEY (house_id) REFERENCES house(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS entrance_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entrance_id INTEGER,
name TEXT,
date_start TIMESTAMP,
date_end TIMESTAMP,
group_id INTEGER,
sheep_id TEXT,
working INTEGER DEFAULT 0,
FOREIGN KEY (entrance_id) REFERENCES entrance(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS apartments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entrance_id INTEGER,
apartment_number INTEGER,
title TEXT,
floors_number INTEGER,
status INTEGER,
description TEXT,
sheep_id TEXT,
updated_at TIMESTAMP,
FOREIGN KEY (entrance_id) REFERENCES entrance(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS apartments_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sheep_id TEXT,
apartments_id INTEGER,
status INTEGER,
description TEXT,
created_at TIMESTAMP,
FOREIGN KEY (apartments_id) REFERENCES apartments(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS homestead (
id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER,
title TEXT,
number TEXT,
points TEXT DEFAULT '[]',
point_icons TEXT DEFAULT '[]',
geo TEXT DEFAULT '[]',
osm_id TEXT DEFAULT '[]',
settlement TEXT,
description TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
FOREIGN KEY (group_id) REFERENCES groups(group_number)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS homestead_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
homestead_id INTEGER,
name TEXT,
date_start TIMESTAMP,
date_end TIMESTAMP,
group_id INTEGER,
sheep_id TEXT,
working INTEGER DEFAULT 0,
FOREIGN KEY (homestead_id) REFERENCES homestead(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS meetings_schedule (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TIMESTAMP,
type INTEGER,
name TEXT,
sheep_id TEXT,
title TEXT,
number TEXT,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS stand_list (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
hour_start INTEGER DEFAULT 10,
hour_end INTEGER DEFAULT 16,
quantity_sheep INTEGER DEFAULT 2,
week_days TEXT DEFAULT '[0, 1, 2, 3, 4, 5, 6]'
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS stand_schedule (
id INTEGER PRIMARY KEY AUTOINCREMENT,
stand INTEGER,
date TIMESTAMP,
hour INTEGER,
sheep_id TEXT,
number_sheep TEXT,
updated_at TIMESTAMP,
FOREIGN KEY (stand) REFERENCES stand_list(id),
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
});
module.exports = db;

View File

@@ -1,6 +0,0 @@
const TelegramConfig = {
token: "7855966674:AAEw9l_EF0GcpjrkSFzt0aLukEfJxBA2gcY",
chatId: "224538769"
}
module.exports = TelegramConfig;

View File

@@ -5,7 +5,7 @@ class ApartmentsController {
const { entrance_id } = req.params;
if (entrance_id) {
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let result = await ApartmentsService.getApartments(entrance_id);
if (result) {
return res
@@ -33,7 +33,7 @@ class ApartmentsController {
const data = req.body;
if (entrance_id && data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await ApartmentsService.createApartments(
entrance_id,
data
@@ -62,7 +62,7 @@ class ApartmentsController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await ApartmentsService.updateApartments(data);
if (result) {
return res.status(200).send(result);
@@ -87,7 +87,7 @@ class ApartmentsController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await ApartmentsService.deleteApartments(data);
if (result) {
return res.status(200).send(result);

View File

@@ -2,8 +2,8 @@ const AuthService = require('../services/auth.service');
class AuthController {
async login(req, res) {
if (req.sheepId && req.sheepRole) {
const result = await AuthService.findUserByID(req.sheepId, req.sheepRole);
if (req.sheepId) {
const result = await AuthService.findUserByID(req.sheepId, req.mode);
if (result) {
return res.status(200).send(result);
} else {

View File

@@ -0,0 +1,112 @@
const BuildingsService = require('../services/buildings.service');
class BuildingsController {
async getList(req, res) {
const { id } = req.params;
if (id) {
if (req.possibilities.can_view_territory) {
let result = await BuildingsService.getList(id);
if (result) {
return res
.status(200)
.send(result);
} else {
return res
.status(500)
.send({ message: 'Internal server error.' });
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'Buildings not found.' });
}
}
async createBuildings(req, res) {
const { id } = req.params;
const data = req.body;
if (id && data) {
if (req.possibilities.can_add_territory) {
let result = await BuildingsService.createBuildings(
id,
data
);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable create building.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'Entrance not found.' });
}
}
async updateBuildings(req, res) {
const data = req.body;
if (data) {
if (req.possibilities.can_add_territory) {
let result = await BuildingsService.updateBuildings(data);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable update building.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'Data not found.' });
}
}
async deleteBuildings(req, res) {
const { id } = req.params;
if (id) {
if (req.possibilities.can_add_territory) {
let result = await BuildingsService.deleteBuildings(id);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable delete building.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'building id not found.' });
}
}
}
module.exports = new BuildingsController();

View File

@@ -5,7 +5,7 @@ class ConstructorController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await ConstructorService.createPack(data);
if (result) {

View File

@@ -5,7 +5,7 @@ class EntrancesController {
const { house_id } = req.params;
if (house_id) {
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let result = await EntrancesService.getEntrances(house_id);
if (result) {
return res
@@ -33,7 +33,7 @@ class EntrancesController {
const data = req.body;
if (house_id) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await EntrancesService.createEntrance(
house_id,
data
@@ -62,7 +62,7 @@ class EntrancesController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await EntrancesService.updateEntrance(data);
if (result) {
return res.status(200).send(result);
@@ -87,7 +87,7 @@ class EntrancesController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await EntrancesService.deleteEntrance(data);
if (result) {
return res.status(200).send(result);

View File

@@ -4,7 +4,7 @@ class GeneratorCardsController {
async getScreen(req, res) {
const { lat, lng, type, wayId, zoom, id, address, number } = req.query;
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await saveCards({ center: {lat:lat,lng:lng}, wayId: wayId, zoom: zoom ?? 18, type: type, number: id, address: `${address} ${number}` });
console.log(result);

View File

@@ -5,7 +5,7 @@ class HistoryEntranceController {
const { entrance_id } = req.params;
if (entrance_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryEntranceService.getHistoryEntrance(entrance_id);
if (result) {
return res
@@ -33,7 +33,7 @@ class HistoryEntranceController {
const data = req.body;
if (entrance_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryEntranceService.createHistoryEntrance(
entrance_id,
data
@@ -62,7 +62,7 @@ class HistoryEntranceController {
const { entrance_id } = req.params;
if (entrance_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryEntranceService.updateHistoryEntrance(entrance_id);
if (result) {
return res.status(200).send(result);
@@ -87,7 +87,7 @@ class HistoryEntranceController {
const { entrance_id } = req.params;
if (entrance_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryEntranceService.deleteHistoryEntrance(entrance_id);
if (result) {
return res.status(200).send(result);

View File

@@ -5,7 +5,7 @@ class HistoryHomesteadController {
const { homestead_id } = req.params;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryHomesteadService.getHistoryHomestead(homestead_id);
if (result) {
return res
@@ -33,7 +33,7 @@ class HistoryHomesteadController {
const data = req.body;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryHomesteadService.createHistoryHomestead(
homestead_id,
data
@@ -63,7 +63,7 @@ class HistoryHomesteadController {
const { homestead_id } = req.params;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryHomesteadService.updateHistoryHomestead(homestead_id);
if (result) {
return res.status(200).send(result);
@@ -88,7 +88,7 @@ class HistoryHomesteadController {
const { homestead_id } = req.params;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HistoryHomesteadService.deleteHistoryHomestead(homestead_id);
if (result) {
return res.status(200).send(result);

View File

@@ -4,19 +4,21 @@ class HomesteadsController {
async getList(req, res) {
const { mode } = req.query;
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let group_id = 0;
let sheepName = false;
if (req.sheepRole == "administrator") {
group_id = 0;
} else if (req.sheepRole == "moderator") {
group_id = req.group_id;
}
// if (req.mode == 2) {
// group_id = 0;
// } else if (req.mode == 1) {
// group_id = req.group_id;
// }
if (mode == "sheep") {
group_id = req.group_id;
sheepName = req.sheepName;
} else if (mode == "group"){
group_id = req.group_id;
}
let result = await HomesteadsService.getList(group_id, sheepName);
@@ -40,7 +42,7 @@ class HomesteadsController {
const { homestead_id } = req.params;
if (homestead_id) {
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let result = await HomesteadsService.getHomestead(homestead_id);
if (result) {
return res
@@ -67,7 +69,7 @@ class HomesteadsController {
const data = req.body;
if (data) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await HomesteadsService.createHomestead(data);
if (result) {
return res.status(200).send(result);
@@ -93,7 +95,7 @@ class HomesteadsController {
const data = req.body;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HomesteadsService.updateHomestead(homestead_id, data);
if (result) {
return res.status(200).send(result);
@@ -118,7 +120,7 @@ class HomesteadsController {
const { homestead_id } = req.params;
if (homestead_id) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await HomesteadsService.deleteHomestead(homestead_id);
if (result) {
return res.status(200).send(result);

View File

@@ -1,22 +1,44 @@
const HousesService = require('../services/houses.service');
class HousesController {
async getListEntrance(req, res) {
if (req.possibilities.can_manager_territory) {
let result = await HousesService.getListEntrance();
if (result) {
return res
.status(200)
.send(result);
} else {
return res
.status(500)
.send({ message: 'Internal server error.' });
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
}
async getList(req, res) {
const { mode } = req.query;
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let group_id = 0;
let sheepName = false;
if (req.sheepRole == "administrator") {
group_id = 0;
} else if (req.sheepRole == "moderator") {
group_id = req.group_id;
}
// if (req.mode == 2) {
// group_id = 0;
// } else if (req.mode == 1) {
// group_id = req.group_id;
// }
if (mode == "sheep") {
group_id = req.group_id;
sheepName = req.sheepName;
} else if (mode == "group"){
group_id = req.group_id;
}
let result = await HousesService.getList(group_id, sheepName);
@@ -40,7 +62,7 @@ class HousesController {
const { house_id } = req.params;
if (house_id) {
if (req.sheepRole == "administrator" || (req.sheepRole == "moderator" && req.moderator.can_manager_territory) || req.can_view_territory) {
if (req.possibilities.can_view_territory) {
let result = await HousesService.getHouse(house_id);
if (result) {
return res
@@ -66,7 +88,7 @@ class HousesController {
async createHouse(req, res) {
const data = req.body;
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await HousesService.createHouse(data);
if (result) {
return res.status(200).send(result);
@@ -87,7 +109,7 @@ class HousesController {
const data = req.body;
if (house_id) {
if (req.sheepRole == "administrator" || req.moderator.can_manager_territory) {
if (req.possibilities.can_manager_territory) {
let result = await HousesService.updateHouse(house_id, data);
if (result) {
return res.status(200).send(result);
@@ -112,7 +134,7 @@ class HousesController {
const { house_id } = req.params;
if (house_id) {
if (req.sheepRole == "administrator" || req.moderator.can_add_territory) {
if (req.possibilities.can_add_territory) {
let result = await HousesService.deleteHouse(house_id);
if (result) {
return res.status(200).send(result);

View File

@@ -0,0 +1,67 @@
const PushService = require('../services/push.service');
class PushController {
async getKey(req, res) {
let result = await PushService.getKey();
if (result) {
return res.status(200).send(result);
} else {
return res.status(404).send({
message: 'Key not found.'
});
}
}
async createSubscribe(req, res) {
const data = req.body;
if (data) {
if (req.sheepId) {
let result = await PushService.createSubscribe(req.sheepId, data);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable create subscribe.',
});
}
} else {
return res
.status(401)
.send({ message: 'Sheeps not found.' });
}
} else {
return res
.status(401)
.send({ message: 'Data not found.' });
}
}
async deleteSubscribe(req, res) {
const data = req.body;
if (data) {
if (req.sheepId) {
let result = await PushService.deleteSubscribe(data);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable delete subscribe.',
});
}
} else {
return res
.status(401)
.send({ message: 'Sheeps not found.' });
}
} else {
return res
.status(401)
.send({ message: 'Data not found.' });
}
}
}
module.exports = new PushController();

View File

@@ -1,24 +0,0 @@
const RotationService = require('../services/rotation.service');
class RotationController {
async editTables(req, res) {
if (req.sheepRole == "administrator") {
let result = await RotationService.editTables();
if (result) {
return res.status(200).send(result);
} else {
return res
.status(404)
.send({ message: 'User not found.' });
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
}
}
module.exports = new RotationController();

View File

@@ -2,11 +2,11 @@ const SheepsService = require('../services/sheeps.service');
class SheepsController {
async getSheep(req, res) {
const { uuid } = req.query;
const { id } = req.query;
if (uuid) {
if (req.sheepRole) {
const result = await SheepsService.getSheep(uuid, req.sheepRole);
if (id) {
if (req.possibilities.can_view_sheeps) {
const result = await SheepsService.getSheep(id, req.mode);
if (result) {
return res.status(200).send(result);
} else {
@@ -27,8 +27,8 @@ class SheepsController {
}
async getList(req, res) {
if (req.sheepRole) {
const result = await SheepsService.getList(req.sheepRole);
if (req.possibilities.can_view_sheeps) {
const result = await SheepsService.getList(req.mode);
if (result) {
return res.status(200).send(result);
@@ -40,14 +40,14 @@ class SheepsController {
} else {
return res
.status(404)
.send({ message: 'Users not found.' });
.send({ message: 'The sheep does not have enough rights.' });
}
}
async createSheep(req, res) {
const data = req.body;
if (req.sheepRole && (req.sheepRole == "administrator" || req.moderator.can_add_sheeps)) {
if (req.possibilities.can_add_sheeps) {
let result = await SheepsService.createSheep(data);
if (result) {
@@ -65,12 +65,9 @@ class SheepsController {
}
async updateSheep(req, res) {
const { uuid } = req.query;
const data = req.body;
console.log("data", data);
if (req.sheepRole == "administrator") {
if (req.mode == 2) {
let result = await SheepsService.updateSheep(data);
if (result) {
@@ -90,7 +87,7 @@ class SheepsController {
async deleteSheep(req, res) {
const data = req.body;
if (req.sheepRole == "administrator") {
if (req.mode == 2) {
let result = await SheepsService.deleteSheep(data);
if (result) {
return res.status(200).send(result);

View File

@@ -0,0 +1,143 @@
const StandService = require('../services/stand.service');
class StandController {
async getStand(req, res) {
const { stand_id } = req.params;
return res.status(200).send({ stand_id });
}
async getList(req, res) {
if (req.possibilities.can_view_stand) {
const result = await StandService.getList();
if (result) {
return res.status(200).send(result);
} else {
return res
.status(404)
.send({ message: 'Stands not found.' });
}
} else {
return res
.status(404)
.send({ message: 'The sheep does not have enough rights.' });
}
}
async createStand(req, res) {
const data = req.body;
if (data) {
if (req.possibilities.can_add_stand) {
let result = await StandService.createStand(data);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable create stand.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'Data not found.' });
}
}
async updateStand(req, res) {
const { stand_id } = req.params;
const data = req.body;
if (stand_id && data) {
if (req.possibilities.can_add_stand) {
let result = await StandService.updateStand(stand_id, data);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable update stand.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'stand_id or data not found.' });
}
}
async deleteStand(req, res) {
const { stand_id } = req.params;
if (stand_id) {
if (req.possibilities.can_add_stand) {
let result = await StandService.deleteStand(stand_id);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable delete stend.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'stand_id not found.' });
}
}
async createSchedule(req, res) {
const { stand_id } = req.params;
if (stand_id) {
if (req.possibilities.can_add_stand) {
let result = await StandService.createSchedule(stand_id);
if (result) {
return res.status(200).send(result);
} else {
return res.status(500).send({
message: 'Unable create stand.',
});
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
} else {
return res
.status(401)
.send({ message: 'stand_id not found.' });
}
}
async getScheduleList(req, res) {
return res.status(200).send({});
}
async getScheduleHistory(req, res) {
const { stand_schedule_id } = req.params;
return res.status(200).send({ stand_schedule_id });
}
}
module.exports = new StandController();

View File

@@ -5,55 +5,86 @@ const authenticate = (req, res, next) => {
if (!uuid) return res.status(401).json({ error: "Unauthorized" });
db.get(`
SELECT sheeps.*, administrators.* FROM administrators JOIN sheeps ON sheeps.id = administrators.sheep_id WHERE administrators.uuid = ?`,
SELECT
sheeps.*,
possibilities.can_add_sheeps AS can_add_sheeps,
possibilities.can_view_sheeps AS can_view_sheeps,
possibilities.can_add_territory AS can_add_territory,
possibilities.can_view_territory AS can_view_territory,
possibilities.can_manager_territory AS can_manager_territory,
possibilities.can_add_stand AS can_add_stand,
possibilities.can_view_stand AS can_view_stand,
possibilities.can_manager_stand AS can_manager_stand,
possibilities.can_add_schedule AS can_add_schedule,
possibilities.can_view_schedule AS can_view_schedule
FROM
sheeps
LEFT JOIN
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.uuid_manager = ?`,
[uuid],
(err, administrator) => {
if (administrator) {
req.sheepId = administrator.sheep_id;
req.sheepRole = 'administrator';
req.group_id = administrator.group_id;
req.sheepName = administrator.name;
req.can_view_schedule = administrator.can_view_schedule;
req.can_view_stand = administrator.can_view_stand;
req.can_view_territory = administrator.can_view_territory;
(err, moderator) => {
if (moderator) {
req.sheepId = moderator.id;
req.sheepName = moderator.name;
req.group_id = moderator.group_id;
req.mode = Number(moderator.mode);
req.possibilities = {
can_add_sheeps: moderator.can_add_sheeps == 1 ? true : false,
can_view_sheeps: moderator.can_view_sheeps == 1 ? true : false,
can_add_territory: moderator.can_add_territory == 1 ? true : false,
can_view_territory: moderator.can_view_territory == 1 ? true : false,
can_manager_territory: moderator.can_manager_territory == 1 ? true : false,
can_add_stand: moderator.can_add_stand == 1 ? true : false,
can_view_stand: moderator.can_view_stand == 1 ? true : false,
can_manager_stand: moderator.can_manager_stand == 1 ? true : false,
can_add_schedule: moderator.can_add_schedule == 1 ? true : false,
can_view_schedule: moderator.can_view_schedule == 1 ? true : false
}
return next();
}
db.get(`
SELECT sheeps.*, moderators.* FROM moderators JOIN sheeps ON sheeps.id = moderators.sheep_id WHERE moderators.uuid = ?`,
SELECT
sheeps.*,
possibilities.can_add_sheeps AS can_add_sheeps,
possibilities.can_view_sheeps AS can_view_sheeps,
possibilities.can_add_territory AS can_add_territory,
possibilities.can_view_territory AS can_view_territory,
possibilities.can_manager_territory AS can_manager_territory,
possibilities.can_add_stand AS can_add_stand,
possibilities.can_view_stand AS can_view_stand,
possibilities.can_manager_stand AS can_manager_stand,
possibilities.can_add_schedule AS can_add_schedule,
possibilities.can_view_schedule AS can_view_schedule
FROM
sheeps
LEFT JOIN
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.uuid = ?`,
[uuid],
(err, moderator) => {
if (moderator) {
req.sheepId = moderator.sheep_id;
req.sheepRole = 'moderator';
req.moderator = {
"id": moderator.moderators_id ? moderator.moderators_id : false,
"can_add_sheeps": moderator.can_add_sheeps == 1 ? true : false,
"can_add_territory": moderator.can_add_territory == 1 ? true : false,
"can_manager_territory": moderator.can_manager_territory == 1 ? true : false,
"can_add_stand": moderator.can_add_stand == 1 ? true : false,
"can_manager_stand": moderator.can_manager_stand == 1 ? true : false,
"can_add_schedule": moderator.can_add_schedule == 1 ? true : false
}
req.group_id = moderator.group_id;
req.sheepName = moderator.name;
req.can_view_schedule = moderator.can_view_schedule;
req.can_view_stand = moderator.can_view_stand;
req.can_view_territory = moderator.can_view_territory;
return next();
}
db.get(`SELECT sheeps.* FROM sheeps WHERE sheeps.uuid = ?`, [uuid], (err, sheep) => {
(err, sheep) => {
if (sheep) {
req.sheepId = sheep.id;
req.sheepRole = 'sheep';
req.group_id = sheep.group_id;
req.sheepName = sheep.name;
req.can_view_schedule = sheep.can_view_schedule;
req.can_view_stand = sheep.can_view_stand;
req.can_view_territory = sheep.can_view_territory;
req.group_id = sheep.group_id;
req.uuid_manager = null;
req.mode = 0;
req.possibilities = {
can_add_sheeps: false,
can_view_sheeps: false,
can_add_territory: false,
can_manager_territory: false,
can_add_stand: false,
can_manager_stand: false,
can_add_schedule: false,
can_view_territory: sheep.can_view_territory == 1 ? true : false,
can_view_stand: sheep.can_view_stand == 1 ? true : false,
can_view_schedule: sheep.can_view_schedule == 1 ? true : false
}
return next();
}
@@ -63,8 +94,6 @@ const authenticate = (req, res, next) => {
);
}
);
}
);
};
module.exports = authenticate;

449
api/package-lock.json generated
View File

@@ -1,39 +1,41 @@
{
"name": "API Sheep Service",
"version": "1.0.0",
"version": "1.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "API Sheep Service",
"version": "1.0.0",
"version": "1.0.1",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^17.2.0",
"express": "^4.21.0",
"node-telegram-bot-api": "^0.66.0",
"puppeteer": "^24.4.0",
"sharp": "^0.33.5",
"sqlite3": "^5.1.7"
"sqlite3": "^5.1.7",
"web-push": "^3.6.7"
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
"picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"engines": {
"node": ">=6.9.0"
}
@@ -112,9 +114,9 @@
}
},
"node_modules/@emnapi/runtime": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
"integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz",
"integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
@@ -493,15 +495,15 @@
}
},
"node_modules/@puppeteer/browsers": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.8.0.tgz",
"integrity": "sha512-yTwt2KWRmCQAfhvbCRjebaSX8pV1//I0Y3g+A7f/eS7gf0l4eRJoUCvcYdVtboeU4CTOZQuqYbZNS8aBYb8ROQ==",
"version": "2.10.5",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.5.tgz",
"integrity": "sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==",
"dependencies": {
"debug": "^4.4.0",
"debug": "^4.4.1",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.5.0",
"semver": "^7.7.1",
"semver": "^7.7.2",
"tar-fs": "^3.0.8",
"yargs": "^17.7.2"
},
@@ -513,9 +515,9 @@
}
},
"node_modules/@puppeteer/browsers/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -548,12 +550,12 @@
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
},
"node_modules/@types/node": {
"version": "22.13.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.11.tgz",
"integrity": "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==",
"version": "24.0.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz",
"integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==",
"optional": true,
"dependencies": {
"undici-types": "~6.20.0"
"undici-types": "~7.8.0"
}
},
"node_modules/@types/yauzl": {
@@ -584,9 +586,9 @@
}
},
"node_modules/agent-base": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"engines": {
"node": ">= 14"
}
@@ -757,6 +759,17 @@
"safer-buffer": "~2.1.0"
}
},
"node_modules/asn1.js": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"dependencies": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
@@ -828,29 +841,37 @@
"optional": true
},
"node_modules/bare-events": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz",
"integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.0.tgz",
"integrity": "sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg==",
"optional": true
},
"node_modules/bare-fs": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.1.tgz",
"integrity": "sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==",
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.1.6.tgz",
"integrity": "sha512-25RsLF33BqooOEFNdMcEhMpJy8EoR88zSMrnOQOaM3USnOK2VmaJ1uaQEwPA6AQjrv1lXChScosN6CzbwbO9OQ==",
"optional": true,
"dependencies": {
"bare-events": "^2.0.0",
"bare-events": "^2.5.4",
"bare-path": "^3.0.0",
"bare-stream": "^2.0.0"
"bare-stream": "^2.6.4"
},
"engines": {
"bare": ">=1.7.0"
"bare": ">=1.16.0"
},
"peerDependencies": {
"bare-buffer": "*"
},
"peerDependenciesMeta": {
"bare-buffer": {
"optional": true
}
}
},
"node_modules/bare-os": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.0.tgz",
"integrity": "sha512-BUrFS5TqSBdA0LwHop4OjPJwisqxGy6JsWVqV6qaFoe965qqtaKfDzHY5T2YA1gUL0ZeeQeA+4BBc1FJTcHiPw==",
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz",
"integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==",
"optional": true,
"engines": {
"bare": ">=1.14.0"
@@ -943,6 +964,11 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"node_modules/bn.js": {
"version": "4.12.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
"integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw=="
},
"node_modules/body-parser": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
@@ -967,9 +993,9 @@
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"optional": true,
"dependencies": {
"balanced-match": "^1.0.0",
@@ -1007,6 +1033,11 @@
"node": "*"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -1122,9 +1153,9 @@
}
},
"node_modules/chromium-bidi": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-2.1.2.tgz",
"integrity": "sha512-vtRWBK2uImo5/W2oG6/cDkkHSm+2t6VHgnj+Rcwhb0pP74OoUb4GipyRX/T/y39gYQPhioP0DPShn+A7P6CHNw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-5.1.0.tgz",
"integrity": "sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==",
"dependencies": {
"mitt": "^3.0.1",
"zod": "^3.24.1"
@@ -1472,17 +1503,28 @@
}
},
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"engines": {
"node": ">=8"
}
},
"node_modules/devtools-protocol": {
"version": "0.0.1413902",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1413902.tgz",
"integrity": "sha512-yRtvFD8Oyk7C9Os3GmnFZLu53yAfsnyw1s+mLmHHUK0GQEc9zthHWvS1r67Zqzm5t7v56PILHIVZ7kmFMaL2yQ=="
"version": "0.0.1464554",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1464554.tgz",
"integrity": "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw=="
},
"node_modules/dotenv": {
"version": "17.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.0.tgz",
"integrity": "sha512-Q4sgBT60gzd0BB0lSyYD3xM4YxrXA9y4uBDof1JNYGzOXrQdQ6yX+7XIAqoFOGQFOTK1D3Hts5OllpxMDZFONQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
@@ -1511,6 +1553,14 @@
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1551,9 +1601,9 @@
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"dependencies": {
"once": "^1.4.0"
}
@@ -1581,26 +1631,26 @@
}
},
"node_modules/es-abstract": {
"version": "1.23.9",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
"integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
"integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
"dependencies": {
"array-buffer-byte-length": "^1.0.2",
"arraybuffer.prototype.slice": "^1.0.4",
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
"call-bound": "^1.0.3",
"call-bound": "^1.0.4",
"data-view-buffer": "^1.0.2",
"data-view-byte-length": "^1.0.2",
"data-view-byte-offset": "^1.0.1",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0",
"es-object-atoms": "^1.1.1",
"es-set-tostringtag": "^2.1.0",
"es-to-primitive": "^1.3.0",
"function.prototype.name": "^1.1.8",
"get-intrinsic": "^1.2.7",
"get-proto": "^1.0.0",
"get-intrinsic": "^1.3.0",
"get-proto": "^1.0.1",
"get-symbol-description": "^1.1.0",
"globalthis": "^1.0.4",
"gopd": "^1.2.0",
@@ -1612,21 +1662,24 @@
"is-array-buffer": "^3.0.5",
"is-callable": "^1.2.7",
"is-data-view": "^1.0.2",
"is-negative-zero": "^2.0.3",
"is-regex": "^1.2.1",
"is-set": "^2.0.3",
"is-shared-array-buffer": "^1.0.4",
"is-string": "^1.1.1",
"is-typed-array": "^1.1.15",
"is-weakref": "^1.1.0",
"is-weakref": "^1.1.1",
"math-intrinsics": "^1.1.0",
"object-inspect": "^1.13.3",
"object-inspect": "^1.13.4",
"object-keys": "^1.1.1",
"object.assign": "^4.1.7",
"own-keys": "^1.0.1",
"regexp.prototype.flags": "^1.5.3",
"regexp.prototype.flags": "^1.5.4",
"safe-array-concat": "^1.1.3",
"safe-push-apply": "^1.0.0",
"safe-regex-test": "^1.1.0",
"set-proto": "^1.0.0",
"stop-iteration-iterator": "^1.1.0",
"string.prototype.trim": "^1.2.10",
"string.prototype.trimend": "^1.0.9",
"string.prototype.trimstart": "^1.0.8",
@@ -1635,7 +1688,7 @@
"typed-array-byte-offset": "^1.0.4",
"typed-array-length": "^1.0.7",
"unbox-primitive": "^1.1.0",
"which-typed-array": "^1.1.18"
"which-typed-array": "^1.1.19"
},
"engines": {
"node": ">= 0.4"
@@ -1864,9 +1917,9 @@
}
},
"node_modules/extract-zip/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -1970,13 +2023,14 @@
}
},
"node_modules/form-data": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
"integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -2134,9 +2188,9 @@
}
},
"node_modules/get-stream/node_modules/pump": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@@ -2159,9 +2213,9 @@
}
},
"node_modules/get-uri": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz",
"integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==",
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
"integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
"dependencies": {
"basic-ftp": "^5.0.2",
"data-uri-to-buffer": "^6.0.2",
@@ -2172,9 +2226,9 @@
}
},
"node_modules/get-uri/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -2359,10 +2413,18 @@
"node": ">= 0.4"
}
},
"node_modules/http_ece": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.2.0.tgz",
"integrity": "sha512-JrF8SSLVmcvc5NducxgyOrKXe3EsyHMgBFgSaIUGmArKe+rwr0uphRkRXvwiom3I+fpIfoItveHrfudL8/rxuA==",
"engines": {
"node": ">=16"
}
},
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
"optional": true
},
"node_modules/http-errors": {
@@ -2393,9 +2455,9 @@
}
},
"node_modules/http-proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -2439,9 +2501,9 @@
}
},
"node_modules/https-proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -2757,6 +2819,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-negative-zero": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
"integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-number-object": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
@@ -2976,6 +3049,25 @@
"verror": "1.10.0"
}
},
"node_modules/jwa": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
"dependencies": {
"jwa": "^2.0.0",
"safe-buffer": "^5.0.1"
}
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -3034,9 +3126,9 @@
}
},
"node_modules/make-fetch-happen/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"optional": true,
"dependencies": {
"ms": "^2.1.3"
@@ -3182,6 +3274,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3338,9 +3435,9 @@
}
},
"node_modules/node-abi": {
"version": "3.74.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
"integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
"version": "3.75.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
"integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
"dependencies": {
"semver": "^7.3.5"
},
@@ -3564,9 +3661,9 @@
}
},
"node_modules/pac-proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -3710,9 +3807,9 @@
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"node_modules/prebuild-install/node_modules/pump": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@@ -3732,9 +3829,9 @@
}
},
"node_modules/prebuild-install/node_modules/tar-fs": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
"dependencies": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
@@ -3820,9 +3917,9 @@
}
},
"node_modules/proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -3874,16 +3971,16 @@
}
},
"node_modules/puppeteer": {
"version": "24.4.0",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.4.0.tgz",
"integrity": "sha512-E4JhJzjS8AAI+6N/b+Utwarhz6zWl3+MR725fal+s3UlOlX2eWdsvYYU+Q5bXMjs9eZEGkNQroLkn7j11s2k1Q==",
"version": "24.12.1",
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.12.1.tgz",
"integrity": "sha512-+vvwl+Xo4z5uXLLHG+XW8uXnUXQ62oY6KU6bEFZJvHWLutbmv5dw9A/jcMQ0fqpQdLydHmK0Uy7/9Ilj8ufwSQ==",
"hasInstallScript": true,
"dependencies": {
"@puppeteer/browsers": "2.8.0",
"chromium-bidi": "2.1.2",
"@puppeteer/browsers": "2.10.5",
"chromium-bidi": "5.1.0",
"cosmiconfig": "^9.0.0",
"devtools-protocol": "0.0.1413902",
"puppeteer-core": "24.4.0",
"devtools-protocol": "0.0.1464554",
"puppeteer-core": "24.12.1",
"typed-query-selector": "^2.12.0"
},
"bin": {
@@ -3894,25 +3991,25 @@
}
},
"node_modules/puppeteer-core": {
"version": "24.4.0",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.4.0.tgz",
"integrity": "sha512-eFw66gCnWo0X8Hyf9KxxJtms7a61NJVMiSaWfItsFPzFBsjsWdmcNlBdsA1WVwln6neoHhsG+uTVesKmTREn/g==",
"version": "24.12.1",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.12.1.tgz",
"integrity": "sha512-8odp6d3ERKBa3BAVaYWXn95UxQv3sxvP1reD+xZamaX6ed8nCykhwlOiHSaHR9t/MtmIB+rJmNencI6Zy4Gxvg==",
"dependencies": {
"@puppeteer/browsers": "2.8.0",
"chromium-bidi": "2.1.2",
"debug": "^4.4.0",
"devtools-protocol": "0.0.1413902",
"@puppeteer/browsers": "2.10.5",
"chromium-bidi": "5.1.0",
"debug": "^4.4.1",
"devtools-protocol": "0.0.1464554",
"typed-query-selector": "^2.12.0",
"ws": "^8.18.1"
"ws": "^8.18.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/puppeteer-core/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -4296,9 +4393,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"bin": {
"semver": "bin/semver.js"
},
@@ -4588,9 +4685,9 @@
}
},
"node_modules/socks": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
"version": "2.8.6",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz",
"integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
@@ -4614,9 +4711,9 @@
}
},
"node_modules/socks-proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
@@ -4728,10 +4825,22 @@
"node": ">=0.10.0"
}
},
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
"integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
"dependencies": {
"es-errors": "^1.3.0",
"internal-slot": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/streamx": {
"version": "2.22.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz",
"integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==",
"version": "2.22.1",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz",
"integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==",
"dependencies": {
"fast-fifo": "^1.3.2",
"text-decoder": "^1.1.0"
@@ -4855,9 +4964,9 @@
}
},
"node_modules/tar-fs": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz",
"integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
"integrity": "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==",
"dependencies": {
"pump": "^3.0.0",
"tar-stream": "^3.1.5"
@@ -4868,9 +4977,9 @@
}
},
"node_modules/tar-fs/node_modules/pump": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@@ -4903,20 +5012,20 @@
}
},
"node_modules/tldts": {
"version": "6.1.85",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz",
"integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==",
"version": "6.1.86",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
"dependencies": {
"tldts-core": "^6.1.85"
"tldts-core": "^6.1.86"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
"version": "6.1.85",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz",
"integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA=="
"version": "6.1.86",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA=="
},
"node_modules/toidentifier": {
"version": "1.0.1",
@@ -5063,9 +5172,9 @@
}
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"optional": true
},
"node_modules/unique-filename": {
@@ -5167,6 +5276,24 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
},
"node_modules/web-push": {
"version": "3.6.7",
"resolved": "https://registry.npmjs.org/web-push/-/web-push-3.6.7.tgz",
"integrity": "sha512-OpiIUe8cuGjrj3mMBFWY+e4MMIkW3SVT+7vEIjvD9kejGUypv8GPDf84JdPWskK8zMRIJ6xYGm+Kxr8YkPyA0A==",
"dependencies": {
"asn1.js": "^5.3.0",
"http_ece": "1.2.0",
"https-proxy-agent": "^7.0.0",
"jws": "^4.0.0",
"minimist": "^1.2.5"
},
"bin": {
"web-push": "src/cli.js"
},
"engines": {
"node": ">= 16"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -5299,9 +5426,9 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"version": "8.18.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"engines": {
"node": ">=10.0.0"
},
@@ -5366,9 +5493,9 @@
}
},
"node_modules/zod": {
"version": "3.24.2",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
"integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==",
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@@ -1,6 +1,6 @@
{
"name": "API Sheep Service",
"version": "1.0.0",
"version": "1.0.1",
"main": "app.js",
"scripts": {
"start": "node app.js"
@@ -10,10 +10,12 @@
"description": "",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^17.2.0",
"express": "^4.21.0",
"node-telegram-bot-api": "^0.66.0",
"sqlite3": "^5.1.7",
"puppeteer": "^24.4.0",
"sharp": "^0.33.5"
"sharp": "^0.33.5",
"sqlite3": "^5.1.7",
"web-push": "^3.6.7"
}
}

View File

@@ -0,0 +1,13 @@
const express = require('express');
const router = express.Router({ mergeParams: true });
const BuildingsController = require('../controllers/buildings.controller');
const authenticate = require("../middleware/auth");
router
.route('/:id')
.get(authenticate, BuildingsController.getList)
.post(authenticate, BuildingsController.createBuildings)
.put(authenticate, BuildingsController.updateBuildings)
.delete(authenticate, BuildingsController.deleteBuildings);
module.exports = router;

View File

@@ -3,6 +3,10 @@ const router = express.Router();
const HousesController = require('../controllers/houses.controller');
const authenticate = require("../middleware/auth");
router
.route('/list/entrances')
.get(authenticate, HousesController.getListEntrance)
router
.route('/list')
.get(authenticate, HousesController.getList)

View File

@@ -6,11 +6,14 @@ const sheepsRoutes = require('./sheeps.routes');
const constructorRoutes = require('./constructor.routes');
const housesRoutes = require('./houses.routes');
const homesteadsRoutes = require('./homesteads.routes');
const buildingsRoutes = require('./buildings.routes');
const entrancesRoutes = require('./entrances.routes');
const apartmentsRoutes = require('./apartments.routes');
const historyEntranceRoutes = require('./history.entrance.routes');
const historyHomesteadRoutes = require('./history.homestead.routes');
const rotationRoutes = require('./rotation.routes');
const standRoutes = require('./stand.routes');
const pushRoutes = require('./push.routes');
const generatorCardsRoutes = require('./generator.cards.routes');
router.use('/auth', authRoutes);
@@ -18,12 +21,13 @@ router.use('/sheeps?', sheepsRoutes);
router.use('/constructor', constructorRoutes);
router.use('/houses?', housesRoutes);
router.use('/homesteads?', homesteadsRoutes);
router.use('/buildings?', buildingsRoutes);
router.use('/house/:house_id/entrances', entrancesRoutes);
router.use('/apartments?/:entrance_id', apartmentsRoutes);
router.use('/history/entrance/:entrance_id', historyEntranceRoutes);
router.use('/history/homestead/:homestead_id', historyHomesteadRoutes);
router.use('/rotation', rotationRoutes);
router.use('/stand', standRoutes);
router.use('/push', pushRoutes);
router.use('/generator/cards', generatorCardsRoutes);

18
api/routes/push.routes.js Normal file
View File

@@ -0,0 +1,18 @@
const express = require('express');
const router = express.Router();
const PushController = require('../controllers/push.controller');
const authenticate = require("../middleware/auth");
router
.route('/key')
.get(authenticate, PushController.getKey);
router
.route('/subscribe')
.post(authenticate, PushController.createSubscribe);
router
.route('/unsubscribe')
.delete(authenticate, PushController.deleteSubscribe);
module.exports = router;

View File

@@ -1,10 +0,0 @@
const express = require('express');
const router = express.Router();
const RotationController = require('../controllers/rotation.controller');
const authenticate = require("../middleware/auth");
router
.route('/')
.get(authenticate, RotationController.editTables);
module.exports = router;

View File

@@ -0,0 +1,29 @@
const express = require('express');
const router = express.Router();
const StandController = require('../controllers/stand.controller');
const authenticate = require("../middleware/auth");
router
.route('/list')
.get(authenticate, StandController.getList)
.post(authenticate, StandController.createStand);
router
.route('/:stand_id')
.get(authenticate, StandController.getStand)
.put(authenticate, StandController.updateStand)
.delete(authenticate, StandController.deleteStand);
router
.route('/schedule/list')
.get(authenticate, StandController.getScheduleList)
router
.route('/schedule/:stand_id')
.post(authenticate, StandController.createSchedule)
router
.route('/schedule/history/:stand_schedule_id')
.post(authenticate, StandController.getScheduleHistory)
module.exports = router;

View File

@@ -1,34 +1,27 @@
const db = require("../config/db");
class AuthService {
findUserByID(id, sheepRole) {
findUserByID(id, mode) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
possibilities.can_add_sheeps AS can_add_sheeps,
possibilities.can_view_sheeps AS can_view_sheeps,
possibilities.can_add_territory AS can_add_territory,
possibilities.can_view_territory AS can_view_territory,
possibilities.can_manager_territory AS can_manager_territory,
possibilities.can_add_stand AS can_add_stand,
possibilities.can_view_stand AS can_view_stand,
possibilities.can_manager_stand AS can_manager_stand,
possibilities.can_add_schedule AS can_add_schedule,
possibilities.can_view_schedule AS can_view_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.id = ?
LIMIT 1;
`
sheeps.id = ?`;
db.get(sql, [id], (err, sheep) => {
if (err) {
console.error(err.message);
@@ -38,40 +31,36 @@ class AuthService {
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: mode && mode == 2 ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
sheepRole: sheep.mode_title,
possibilities: {
can_add_sheeps: false,
can_view_sheeps: false,
can_add_territory: false,
can_manager_territory: false,
can_add_stand: false,
can_manager_stand: false,
can_add_schedule: false,
can_view_schedule: sheep.can_view_schedule == 1 ? true : false,
can_view_stand: sheep.can_view_stand == 1 ? true : false,
can_view_territory: sheep.can_view_territory == 1 ? true : false
}
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
}
if (sheepRole == "moderator") {
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
if (mode && (mode == 1 || mode == 2)) {
data.possibilities.can_add_sheeps = sheep.can_add_sheeps == 1 ? true : false;
data.possibilities.can_view_sheeps = sheep.can_view_sheeps == 1 ? true : false;
data.possibilities.can_add_territory = sheep.can_add_territory == 1 ? true : false;
data.possibilities.can_manager_territory = sheep.can_manager_territory == 1 ? true : false;
data.possibilities.can_add_stand = sheep.can_add_stand == 1 ? true : false;
data.possibilities.can_manager_stand = sheep.can_manager_stand == 1 ? true : false;
data.possibilities.can_add_schedule = sheep.can_add_schedule == 1 ? true : false;
}
return res(data);

View File

@@ -0,0 +1,102 @@
const db = require("../config/db");
class BuildingsService {
getList(homestead_id) {
return new Promise((res, rej) => {
let sql = `
SELECT
*
FROM
buildings
WHERE
homestead_id = '${homestead_id}'
ORDER BY
id
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"homestead_id": Number(row.homestead_id),
"sheep_id": Number(row.sheep_id),
"geo": JSON.parse(row.geo),
"title": row.title,
"status": Number(row.status),
"description": row.description,
"updated_at": Number(row.updated_at)
}
})
return res(data);
}
});
});
}
createBuildings(homestead_id, data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO buildings(homestead_id, title, geo) VALUES (?, ?, ?)';
db.run(sql, [
homestead_id,
data.title,
JSON.stringify(data.geo)
], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": this.lastID });
}
});
});
}
updateBuildings(data) {
return new Promise((res, rej) => {
let sql = 'UPDATE buildings SET title = ?, status = ?, description = ?, updated_at = ?, geo = ? WHERE id = ?';
db.run(sql, [
data.title,
data.status,
data.description,
Math.floor(new Date(Date.now()).getTime()),
JSON.stringify(data.geo),
data.id
], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok" });
}
});
});
}
deleteBuildings(building_id) {
return new Promise((res, rej) => {
db.run('DELETE FROM buildings WHERE id = ?', [building_id], function(err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok"});
}
});
});
}
}
module.exports = new BuildingsService();

View File

@@ -101,17 +101,114 @@ class ConstructorService {
// });
// });
// }
// createPack(data) {
// return new Promise((res, rej) => {
// if (data.type == "house") {
// const sql = `
// INSERT INTO house (
// title, number, points, points_number, geo, osm_id, settlement, created_at
// ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
// db.run(sql, [
// data.title,
// data.number,
// JSON.stringify(data.points),
// JSON.stringify(data.points_number),
// JSON.stringify(data.geo),
// JSON.stringify(data.osm_id),
// data.settlement,
// Math.floor(Date.now())
// ], function (err) {
// if (err) {
// console.error(err.message);
// return res(false);
// }
// if (this.changes === 0) {
// return res(false);
// }
// const houseId = this.lastID;
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
// const entranceStmt = db.prepare(`
// INSERT INTO entrance (
// house_id, entrance_number, title, points, points_number, created_at
// ) VALUES (?, ?, ?, ?, ?, ?)`);
// const apartmentStmt = db.prepare(`
// INSERT INTO apartments (
// entrance_id, apartment_number, title, floors_number
// ) VALUES (?, ?, ?, ?)`);
// const entranceIdMap = {}; // Для сопоставления editor_id → entrance_id
// let pendingEntrances = data.entrance.length;
// data.entrance.forEach((e) => {
// entranceStmt.run(
// houseId,
// Number(e.entrance_number),
// e.title,
// JSON.stringify(e.points),
// JSON.stringify(e.points_number),
// Math.floor(Date.now()),
// function (err) {
// if (err) {
// console.error(err.message);
// return;
// }
// const entranceId = this.lastID;
// entranceIdMap[e.editor_id] = entranceId;
// if (--pendingEntrances === 0) {
// insertApartments();
// }
// }
// );
// });
// function insertApartments() {
// for (const [editor_id, apartments] of Object.entries(data.apartments)) {
// const entranceId = entranceIdMap[editor_id];
// if (!entranceId) continue;
// apartments.forEach(apartment => {
// apartmentStmt.run(
// entranceId,
// Number(apartment.apartment_number),
// apartment.title,
// apartment.floors_number
// );
// });
// }
// entranceStmt.finalize();
// apartmentStmt.finalize();
// res({ "status": "ok", "id": houseId });
// }
// });
// } else if (data.type == "homestead") {
// return res(false);
// } else {
// return res(false);
// }
// });
// }
createPack(data) {
return new Promise((res, rej) => {
if (data.type == "house") {
if (data.type === "house") {
const sql = `
INSERT INTO house (
group_id, title, number, points, points_number, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
title, number, points, points_number, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
@@ -131,103 +228,132 @@ class ConstructorService {
const houseId = this.lastID;
saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 18, type: "house", number: houseId, address: `${data.title} ${data.number}` });
const entranceStmt = db.prepare(`
INSERT INTO entrance (
house_id, entrance_number, title, points, points_number, created_at
) VALUES (?, ?, ?, ?, ?, ?)`);
house_id, entrance_number, title, created_at
) VALUES (?, ?, ?, ?)`);
const apartmentStmt = db.prepare(`
INSERT INTO apartments (
entrance_id, apartment_number, title, floors_number
) VALUES (?, ?, ?, ?)`);
const entranceIdMap = {}; // Для сопоставления editor_id → entrance_id
let pendingEntrances = data.entrances.length;
const entranceIdMap = {};
let pendingEntrances = data.entrance.length;
if (pendingEntrances === 0) return finalize();
data.entrance.forEach((e) => {
// Вставляем подъезды
data.entrances.forEach(entrance => {
entranceStmt.run(
houseId,
Number(e.entrance_number),
e.title,
JSON.stringify(e.points),
JSON.stringify(e.points_number),
Number(entrance.entrance_number),
entrance.title,
Math.floor(Date.now()),
function (err) {
if (err) {
console.error(err.message);
return res(false);
}
const entranceID = this.lastID;
entranceIdMap[entrance.entrance_number] = entranceID;
// Вставляем квартиры данного подъезда
let pendingApartments = entrance.apartments.length;
if (pendingApartments === 0) {
if (--pendingEntrances === 0) finalize();
return;
}
const entranceId = this.lastID;
entranceIdMap[e.editor_id] = entranceId;
if (--pendingEntrances === 0) {
insertApartments();
}
}
);
});
function insertApartments() {
for (const [editor_id, apartments] of Object.entries(data.apartments)) {
const entranceId = entranceIdMap[editor_id];
if (!entranceId) continue;
apartments.forEach(apartment => {
entrance.apartments.forEach(apartment => {
apartmentStmt.run(
entranceId,
entranceID,
Number(apartment.apartment_number),
apartment.title,
apartment.floors_number
Number(apartment.floors_number),
function (err) {
if (err) console.error(err.message);
if (--pendingApartments === 0) {
if (--pendingEntrances === 0) finalize();
}
}
);
});
}
);
});
function finalize() {
entranceStmt.finalize();
apartmentStmt.finalize();
res({ "status": "ok", "id": houseId });
res({ status: "ok", id: houseId });
}
});
} else if (data.type == "homestead") {
let sql = `
INSERT INTO
homestead(
group_id,
title,
number,
points,
point_icons,
geo,
osm_id,
settlement,
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)
} else if (data.type === "homestead") {
const sql = `
INSERT INTO homestead (
title, number, zoom, points, geo, osm_id, settlement, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
Number(data.zoom),
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
JSON.stringify(data.osm_id),
data.settlement,
Math.floor(new Date(Date.now()).getTime())
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
}
if (this.changes === 0) {
return res(false);
} else {
saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 17, type: "homestead", number: this.lastID, address: `${data.title} ${data.number}` })
res({ "status": "ok", "id": this.lastID });
}
const homesteadId = this.lastID;
// saveCards({ center: data.geo, wayId: data.osm_id, zoom: data.zoom ?? 17, type: "homestead", number: homesteadId, address: `${data.title} ${data.number}` });
const buildingStmt = db.prepare(`
INSERT INTO buildings (
homestead_id, title, geo
) VALUES (?, ?, ?)
`);
let pendingBuildings = data.buildings.length;
if (pendingBuildings === 0) return finalize();
data.buildings.forEach(building => {
buildingStmt.run(
homesteadId,
building.title,
JSON.stringify(building.geo),
function (err) {
if (err) {
console.error(err.message);
return res(false);
}
if (--pendingBuildings === 0) finalize();
}
);
});
function finalize() {
buildingStmt.finalize();
res({ status: "ok", id: homesteadId });
}
});
} else {

View File

@@ -30,10 +30,6 @@ class EntrancesService {
"house_id": Number(row.house_id),
"entrance_number": Number(row.entrance_number),
"title": row.title,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"floors_quantity": row.floors_quantity,
"apartments_quantity": row.apartments_quantity,
"description": row.description,
"created_at": Number(row.created_at),
"updated_at": Number(row.updated_at),
@@ -65,29 +61,19 @@ class EntrancesService {
house_id,
entrance_number,
title,
points,
points_number,
floors_quantity,
apartments_quantity,
description,
created_at,
updated_at
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
(?, ?, ?, ?, ?)
`;
db.run(sql, [
house_id,
Number(data.entrance_number),
data.title,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
data.floors_quantity,
data.apartments_quantity,
data.description,
Math.floor(new Date(Date.now()).getTime()),
Math.floor(new Date(Date.now()).getTime()),
Math.floor(new Date(Date.now()).getTime())
], function(err) {
if (err) {
console.error(err.message);
@@ -108,10 +94,6 @@ class EntrancesService {
entrance
SET
title = ?,
points = ?,
points_number = ?,
floors_quantity = ?,
apartments_quantity = ?,
description = ?,
updated_at = ?
WHERE

View File

@@ -64,26 +64,121 @@ class HistoryEntranceService {
});
}
updateHistoryEntrance(entrance_id) {
updateHistoryEntrance(entrance_history_id) {
return new Promise((res, rej) => {
console.log(Number(entrance_id));
const endTime = Date.now(); // 🕒 Час завершення
const entranceHistoryId = Number(entrance_history_id);
let sql = 'UPDATE entrance_history SET date_end = ?, working = ? WHERE id = ?';
db.run(sql, [
Math.floor(new Date(Date.now()).getTime()),
0,
Number(entrance_id)
], function(err) {
if (err) {
console.error(err.message);
// 🔧 Оновлюємо запис в entrance_history
db.run(
`UPDATE entrance_history SET date_end = ?, working = 0 WHERE id = ?`,
[endTime, entranceHistoryId],
function (err) {
if (err || this.changes === 0) {
console.error("❌ Помилка оновлення entrance_history:", err?.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "update": "ok", "id": entrance_id });
}
// 🏢 Отримуємо entrance_id
db.get(
`SELECT entrance_id FROM entrance_history WHERE id = ?`,
[entranceHistoryId],
(err, entrance) => {
if (err || !entrance) {
console.error("❌ Помилка отримання під’їзду:", err?.message);
return res(false);
}
// 🧱 Отримуємо квартири
db.all(
`SELECT * FROM apartments WHERE entrance_id = ? ORDER BY id`,
[entrance.entrance_id],
(err, apartments) => {
if (err) {
console.error("❌ Помилка отримання квартир:", err.message);
return res(false);
}
if (!apartments.length) {
return res({ update: "ok", id: entranceHistoryId, inserted: 0 });
}
const toUpdate = apartments.filter(a => ![2, 6, 0, null].includes(a.status));
// 📝 Готуємо вставку в історію
const stmtInsert = db.prepare(`
INSERT INTO apartments_history
(sheep_id, apartments_id, status, description, created_at)
VALUES (?, ?, ?, ?, ?)
`);
const stmtUpdate = db.prepare(`
UPDATE apartments
SET status = NULL, description = NULL, sheep_id = NULL, updated_at = ?
WHERE id = ?
`);
let completed = 0;
let inserted = 0;
if (!toUpdate.length) {
stmtInsert.finalize();
stmtUpdate.finalize();
return res({ update: "ok", id: entranceHistoryId, inserted: 0 });
}
for (const apt of toUpdate) {
// 🔄 Оновлюємо квартиру
stmtUpdate.run([endTime, apt.id]);
// 🪵 Вставляємо в історію
stmtInsert.run(
[apt.sheep_id, apt.id, apt.status, apt.description, endTime],
(err) => {
if (!err) inserted++;
completed++;
if (completed === toUpdate.length) {
stmtInsert.finalize();
stmtUpdate.finalize();
return res({
update: "ok",
id: entranceHistoryId,
inserted,
});
}
}
);
}
}
);
}
);
}
);
});
// return new Promise((res, rej) => {
// console.log(Number(entrance_id));
// let sql = 'UPDATE entrance_history SET date_end = ?, working = ? WHERE id = ?';
// db.run(sql, [
// Math.floor(new Date(Date.now()).getTime()),
// 0,
// Number(entrance_id)
// ], function(err) {
// if (err) {
// console.error(err.message);
// return res(false);
// } else if (this.changes === 0) {
// return res(false);
// } else {
// res({ "update": "ok", "id": entrance_id });
// }
// });
// });
}
deleteHistoryEntrance(entrance_id) {

View File

@@ -30,8 +30,16 @@ class HomesteadsService {
(SELECT homestead_history.date_end FROM homestead_history WHERE homestead_history.homestead_id = homestead.id ORDER BY homestead_history.date_start DESC LIMIT 1) AS homestead_history_date_end
FROM
homestead
WHERE
group_id == '${group}'
JOIN
homestead_history
ON
homestead.id = homestead_history.homestead_id
AND
homestead_history.working = 1
AND
homestead_history.name = 'Групова'
AND
homestead_history.group_id == '${group}'
`;
}
@@ -52,12 +60,10 @@ class HomesteadsService {
homestead_history
ON
homestead.id = homestead_history.homestead_id
WHERE
homestead.group_id = '${group}'
AND
homestead_history.working = 1
AND
homestead_history.name IN ('Групова', '${sheepName}');
homestead_history.name = '${sheepName}';
`;
}
@@ -69,12 +75,11 @@ class HomesteadsService {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"point_icons": JSON.parse(row.point_icons),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -127,12 +132,11 @@ class HomesteadsService {
} else {
let data = {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"point_icons": JSON.parse(row.point_icons),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -160,27 +164,25 @@ class HomesteadsService {
let sql = `
INSERT INTO
homestead(
group_id,
title,
number,
points,
point_icons,
geo,
zoom,
osm_id,
settlement,
created_at
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)
(?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
Math.floor(new Date(Date.now()).getTime())
@@ -203,12 +205,11 @@ class HomesteadsService {
UPDATE
homestead
SET
group_id = ?,
title = ?,
number = ?,
points = ?,
point_icons = ?,
geo = ?,
zoom = ?,
osm_id = ?,
settlement = ?,
description = ?,
@@ -217,12 +218,11 @@ class HomesteadsService {
id = ?
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.point_icons),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,

View File

@@ -1,6 +1,68 @@
const db = require("../config/db");
class HousesService {
getListEntrance() {
return new Promise((res, rej) => {
let sql = `
SELECT
entrance.*,
COALESCE((SELECT entrance_history.working FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1), 0) AS working,
(SELECT entrance_history.name FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_name,
(SELECT entrance_history.group_id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_group_id,
(SELECT entrance_history.sheep_id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_sheep_id,
(SELECT entrance_history.id FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_id,
(SELECT entrance_history.date_start FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_date_start,
(SELECT entrance_history.date_end FROM entrance_history WHERE entrance_history.entrance_id = entrance.id ORDER BY entrance_history.date_start DESC LIMIT 1) AS entrance_history_date_end,
(SELECT house.settlement FROM house WHERE house.id = entrance.house_id) AS house_settlement,
(SELECT house.title FROM house WHERE house.id = entrance.house_id) AS house_title,
(SELECT house.number FROM house WHERE house.id = entrance.house_id) AS house_number
FROM
entrance
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"house": {
"id": Number(row.house_id),
"title": row.house_title,
"number": row.house_number,
"settlement": row.house_settlement
},
"entrance_number": Number(row.entrance_number),
"title": row.title,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"floors_quantity": row.floors_quantity,
"apartments_quantity": row.apartments_quantity,
"description": row.description,
"created_at": Number(row.created_at),
"updated_at": Number(row.updated_at),
"working": Number(row.working) == 0 ? false : true,
"history": {
"id": row.entrance_history_id ? Number(row.entrance_history_id) : null,
"name": row.entrance_history_name,
"group_id": row.entrance_history_group_id ? Number(row.entrance_history_group_id) : null,
"sheep_id": row.entrance_history_sheep_id ? Number(row.entrance_history_sheep_id) : null,
"date": {
"start": row.entrance_history_date_start ? Number(row.entrance_history_date_start) : null,
"end": row.entrance_history_date_end ? Number(row.entrance_history_date_end) : null
}
}
}
})
return res(data);
}
});
});
}
getList(group, sheepName) {
return new Promise((res, rej) => {
let sql = `
@@ -14,18 +76,25 @@ class HousesService {
if (group != "0" && !sheepName) {
sql = `
SELECT
SELECT DISTINCT
house.*,
(SELECT COUNT(DISTINCT entrance_history.id) FROM entrance_history JOIN entrance ON entrance.id = entrance_history.entrance_id WHERE entrance.house_id = house.id AND entrance_history.working = 1 ORDER BY entrance_history.date_start DESC) AS working,
(SELECT COUNT(*) FROM entrance WHERE entrance.house_id = house.id) AS entrance_quantity
FROM
house
JOIN
entrance ON entrance.house_id = house.id
JOIN
entrance_history ON entrance_history.entrance_id = entrance.id
WHERE
group_id == '${group}'
entrance_history.working = 1
AND
entrance_history.name = 'Групова'
AND
entrance_history.group_id == '${group}'
`;
}
if (sheepName) {
sql = `
SELECT DISTINCT
@@ -39,11 +108,9 @@ class HousesService {
JOIN
entrance_history ON entrance_history.entrance_id = entrance.id
WHERE
house.group_id = '${group}'
AND
entrance_history.working = 1
AND
entrance_history.name IN ('Групова', '${sheepName}');
entrance_history.name = '${sheepName}'
`;
}
@@ -55,12 +122,12 @@ class HousesService {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -102,12 +169,12 @@ class HousesService {
} else {
let data = {
"id": Number(row.id),
"group_id": Number(row.group_id),
"title": row.title,
"number": row.number,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"geo": JSON.parse(row.geo),
"zoom": Number(row.zoom),
"osm_id": JSON.parse(row.osm_id),
"settlement": row.settlement,
"description": row.description,
@@ -129,12 +196,12 @@ class HousesService {
let sql = `
INSERT INTO
house(
group_id,
title,
number,
points,
points_number,
geo,
zoom
osm_id,
settlement,
description,
@@ -146,12 +213,12 @@ class HousesService {
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,
@@ -176,12 +243,12 @@ class HousesService {
UPDATE
house
SET
group_id = ?,
title = ?,
number = ?,
points = ?,
points_number = ?,
geo = ?,
zoom = ?,
osm_id = ?,
settlement = ?,
description = ?,
@@ -190,12 +257,12 @@ class HousesService {
id = ?
`;
db.run(sql, [
Number(data.group_id),
data.title,
data.number,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
JSON.stringify(data.geo),
Number(data.zoom),
JSON.stringify(data.osm_id),
data.settlement,
data.description,

View File

@@ -0,0 +1,70 @@
const crypto = require('crypto');
const db = require("../config/db");
const webpush = require('web-push');
const VAPID_PUBLIC_KEY = process.env.VAPID_PUBLIC_KEY;
const VAPID_PRIVATE_KEY = process.env.VAPID_PRIVATE_KEY;
webpush.setVapidDetails(
'mailto:rozenrod320@gmail.com',
VAPID_PUBLIC_KEY,
VAPID_PRIVATE_KEY
);
class PushService {
getKey() {
return new Promise((res, rej) => {
return res({ "publicKey": VAPID_PUBLIC_KEY });
});
}
createSubscribe(sheep_id, data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO subscription(sheep_id, endpoint, keys, device_name, device_model, created_at) VALUES (?, ?, ?, ?, ?, ?)';
db.run(sql, [
Number(sheep_id),
data.subscription.endpoint,
JSON.stringify(data.subscription.keys),
data.device?.name || "unknown",
data.device?.model || "unknown",
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else {
const payload = JSON.stringify(
{
"title": "Тестове повідомлення",
"body": "Ви успішно підписалися на отримання push повідомлень!",
"url": `https://${process.env.DOMAIN}`
});
webpush.sendNotification(data.subscription, payload).catch(err => {
console.error('Ошибка отправки:', err);
})
return res({ "status": "ok" });
}
});
});
}
deleteSubscribe(data) {
return new Promise((res, rej) => {
db.run('DELETE FROM subscription WHERE endpoint = ?', [data.endpoint], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok" });
}
});
});
}
}
module.exports = new PushService();

View File

@@ -1,106 +0,0 @@
const sqlite3 = require("sqlite3").verbose();
const path = require('path');
const TelegramConfig = require('../config/telegram.config.js');
const TelegramBot = require('node-telegram-bot-api');
const fs = require('fs');
const dbPath = process.env.DATABASE_PATH || '../';
const db = new sqlite3.Database(path.join(dbPath, 'database.sqlite'));
const bot = new TelegramBot(TelegramConfig.token, { polling: false });
class RotationService {
async editTables() {
await bot.sendDocument(TelegramConfig.chatId, fs.createReadStream(path.join(dbPath, 'database.sqlite')), {
filename: "database.sqlite",
contentType: "application/x-sqlite3",
caption: "Резервна копія БД Manager Territory 📄 перед проведенням ротації територій!"
});
console.log("Резервна копія БД відправленна в Telegram");
return new Promise((resolve, reject) => {
db.serialize(() => {
db.get("SELECT MAX(group_id) AS max_id FROM homestead", (err, row) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при отриманні max_id для homestead" });
}
const maxIdHomestead = row?.max_id;
if (maxIdHomestead === null) {
return reject({ "message": "Таблиця homestead пуста або group_id відсутній" });
}
db.get("SELECT MAX(group_id) AS max_id FROM house", (err, row) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при отриманні max_id для house" });
}
const maxIdHouse = row?.max_id;
if (maxIdHouse === null) {
return reject({ "message": "Таблиця house пуста або group_id відсутній" });
}
const currentUnixTime = Math.floor(Date.now());
// Оновлюємо group_id в обох таблицах
db.run("UPDATE homestead SET updated_at = ?, group_id = group_id + 1 WHERE group_id < ? AND group_id > 0", [currentUnixTime, maxIdHomestead + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні значень у homestead" });
}
db.run("UPDATE homestead SET updated_at = ?, group_id = 1 WHERE group_id = ?", [currentUnixTime, maxIdHomestead + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при встановленні group_id = 1 у homestead" });
}
db.run("UPDATE house SET updated_at = ?, group_id = group_id + 1 WHERE group_id < ? AND group_id > 0", [currentUnixTime, maxIdHouse + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні значень у house" });
}
db.run("UPDATE house SET updated_at = ?, group_id = 1 WHERE group_id = ?", [currentUnixTime, maxIdHouse + 1], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при встановленні group_id = 1 у house" });
}
console.log("Ротація homestead та house завершилась успішно");
// Після оновлення homestead та house ми оновлюємо homestead_history та entrance_history
db.run("UPDATE homestead_history SET date_end = ?, working = 0 WHERE working = 1", [currentUnixTime], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні homestead_history" });
}
db.run("UPDATE entrance_history SET date_end = ?, working = 0 WHERE working = 1", [currentUnixTime], (err) => {
if (err) {
console.error(err.message);
return reject({ "message": "Помилка при оновленні entrance_history" });
}
console.log("Ротація homestead_history та entrance_history завершилась успішно");
resolve({ "message": "Ротація завершилась успішно" });
});
});
});
});
});
});
});
});
});
}).catch(error => {
console.error('Помилка при проведенні ротації:', error.message);
return error;
});
}
}
module.exports = new RotationService();

View File

@@ -2,392 +2,272 @@ const crypto = require('crypto');
const db = require("../config/db");
class SheepService {
getSheep(uuid, sheepRole) {
getSheep(id, mode) {
return new Promise((res, rej) => {
let sql = `
const sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
possibilities.can_add_sheeps,
possibilities.can_view_sheeps,
possibilities.can_add_territory,
possibilities.can_view_territory,
possibilities.can_manager_territory,
possibilities.can_add_stand,
possibilities.can_view_stand,
possibilities.can_manager_stand,
possibilities.can_add_schedule,
possibilities.can_view_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
possibilities ON possibilities.sheep_id = sheeps.id
WHERE
sheeps.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
sheeps.id = ?
`;
db.get(sql, [id], (err, sheep) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
}
if (!sheep) {
console.log({ error: "id not found" });
return res(false);
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
const fields = [
"can_add_sheeps",
"can_view_sheeps",
"can_add_territory",
"can_view_territory",
"can_manager_territory",
"can_add_stand",
"can_view_stand",
"can_manager_stand",
"can_add_schedule",
"can_view_schedule"
];
const data = {
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: mode && mode === 2 ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
mode_title: sheep.mode_title,
possibilities: {}
};
fields.forEach(f => {
data.possibilities[f] = false;
});
if (mode && (mode === 1 || mode === 2)) {
fields.forEach(f => {
data.possibilities[f] = !!sheep[f];
});
}
return res(data);
}
});
});
}
getList(sheepRole) {
getList(mode) {
return new Promise((res, rej) => {
let sql = `
const sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps,
moderators.can_add_territory,
moderators.can_manager_territory,
moderators.can_add_stand,
moderators.can_manager_stand,
moderators.can_add_schedule
possibilities.can_add_sheeps,
possibilities.can_view_sheeps,
possibilities.can_add_territory,
possibilities.can_view_territory,
possibilities.can_manager_territory,
possibilities.can_add_stand,
possibilities.can_view_stand,
possibilities.can_manager_stand,
possibilities.can_add_schedule,
possibilities.can_view_schedule
FROM
sheeps
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
LEFT JOIN
administrators ON administrators.sheep_id = sheeps.id
LEFT JOIN
moderators ON moderators.sheep_id = sheeps.id
possibilities ON possibilities.sheep_id = sheeps.id
ORDER BY
id
sheeps.group_id
`;
db.all(sql, (err, sheeps) => {
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let result = sheeps.map((sheep) => {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id ? sheep.administrators_id : false,
"uuid": null
},
"moderator": {
"id": sheep.moderators_id ? sheep.moderators_id : false,
"uuid": null,
"can_add_sheeps": sheep.can_add_sheeps == 1 ? true : false,
"can_add_territory": sheep.can_add_territory == 1 ? true : false,
"can_manager_territory": sheep.can_manager_territory == 1 ? true : false,
"can_add_stand": sheep.can_add_stand == 1 ? true : false,
"can_manager_stand": sheep.can_manager_stand == 1 ? true : false,
"can_add_schedule": sheep.can_add_schedule == 1 ? true : false
}
}
if (sheepRole == "administrator") {
if (sheep.administrators_id) {
data.administrator.uuid = sheep.administrators_uuid;
}
if (sheep.moderators_id) {
data.moderator.uuid = sheep.moderators_uuid;
}
const fields = [
"can_add_sheeps",
"can_view_sheeps",
"can_add_territory",
"can_view_territory",
"can_manager_territory",
"can_add_stand",
"can_view_stand",
"can_manager_stand",
"can_add_schedule",
"can_view_schedule"
];
const result = rows.map(sheep => {
const data = {
id: sheep.id,
group_id: sheep.group_id,
name: sheep.name,
icon: sheep.icon,
uuid: sheep.uuid,
uuid_manager: (mode && mode == 2) ? sheep.uuid_manager : null,
appointment: sheep.appointment,
mode: mode ? Number(sheep.mode) : 0,
mode_title: sheep.mode_title,
possibilities: {}
};
fields.forEach(f => {
data.possibilities[f] = false;
});
if (mode && (mode == 1 || mode == 2)) {
fields.forEach(f => {
data.possibilities[f] = !!sheep[f];
});
}
return data;
})
});
return res(result);
}
});
});
}
getAdministrator(uuid) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
administrators.id AS administrators_id,
administrators.uuid AS administrators_uuid
FROM
sheeps
JOIN
administrators ON sheeps.id = administrators.sheep_id
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
WHERE
administrators.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": {
"id": sheep.administrators_id,
"uuid": sheep.administrators_uuid
},
"moderator": false
}
return res(data);
}
});
});
}
getModerator(uuid) {
return new Promise((res, rej) => {
let sql = `
SELECT
sheeps.*,
groups.group_number AS group_id,
moderators.id AS moderators_id,
moderators.uuid AS moderators_uuid,
moderators.can_add_sheeps AS can_add_sheeps,
moderators.can_add_territory AS can_add_territory,
moderators.can_manager_territory AS can_manager_territory,
moderators.can_add_stand AS can_add_stand,
moderators.can_manager_stand AS can_manager_stand,
moderators.can_add_schedule AS can_add_schedule
FROM
sheeps
JOIN
moderators ON sheeps.id = moderators.sheep_id
LEFT JOIN
groups ON groups.group_number = sheeps.group_id
WHERE
moderators.uuid = ?
LIMIT 1;
`
db.get(sql, [uuid], (err, sheep) => {
if (err) {
console.error(err.message);
return res(false);
} else if (!sheep) {
console.log({ "error": "uuid not found" });
return res(false);
} else {
let data = {
"id": Number(sheep.id),
"group_id": Number(sheep.group_id),
"name": sheep.name,
"icon": sheep.icon,
"uuid": sheep.uuid,
"appointment": sheep.appointment,
"can_view_stand": sheep.can_view_stand == 0 ? false : true,
"can_view_schedule": sheep.can_view_schedule == 0 ? false : true,
"can_view_territory": sheep.can_view_territory == 0 ? false : true,
"administrator": false,
"moderator": {
"id": sheep.moderators_id,
"uuid": sheep.moderators_uuid,
"can_add_sheeps": sheep.can_add_sheeps == 0 ? false : true,
"can_add_territory": sheep.can_add_territory == 0 ? false : true,
"can_manager_territory": sheep.can_manager_territory == 0 ? false : true,
"can_add_stand": sheep.can_add_stand == 0 ? false : true,
"can_manager_stand": sheep.can_manager_stand == 0 ? false : true,
"can_add_schedule": sheep.can_add_schedule == 0 ? false : true
}
}
return res(data);
}
res(result);
});
});
}
createSheep(data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO sheeps(name, group_id, appointment, uuid) VALUES (?, ?, ?, ?)';
const stmt1 = db.prepare('INSERT INTO sheeps(name, group_id, appointment, uuid) VALUES (?, ?, ?, ?)');
const stmt2 = db.prepare('INSERT INTO possibilities(can_view_territory, sheep_id) VALUES (?, ?)');
return new Promise((res, rej) => {
db.serialize(() => {
let uuid = crypto.randomUUID();
db.run(sql, [
stmt1.run([
data.name,
Number(data.group_id),
data.appointment,
uuid
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": this.lastID, "uuid": uuid });
}
if (err) return rej(err);
const newSheepId = this.lastID;
stmt2.run([
1,
newSheepId
], (err2) => {
if (err2) return rej(err2);
res({ status: "ok", id: newSheepId, uuid: uuid });
});
});
});
});
}
updateSheep(data) {
return new Promise(async (res, rej) => {
try {
let sql = `
UPDATE sheeps
SET name = ?, group_id = ?, appointment = ?,
can_view_stand = ?, can_view_schedule = ?, can_view_territory = ?
WHERE uuid = ?
`;
const stmt1 = db.prepare(`
UPDATE
sheeps
SET
name = ?,
group_id = ?,
appointment = ?,
mode = ?,
mode_title = ?,
uuid_manager = ?
WHERE
uuid = ?
`);
await db.run(sql, [
const stmt2 = db.prepare(`
UPDATE
possibilities
SET
can_add_sheeps = ?,
can_view_sheeps = ?,
can_add_territory = ?,
can_view_territory = ?,
can_manager_territory = ?,
can_add_stand = ?,
can_view_stand = ?,
can_manager_stand = ?,
can_add_schedule = ?,
can_view_schedule = ?
WHERE
sheep_id = (SELECT id FROM sheeps WHERE uuid = ? LIMIT 1)
`);
return new Promise((res, rej) => {
db.serialize(() => {
let uuid_manager = crypto.randomUUID();
stmt1.run([
data.name,
Number(data.group_id),
data.appointment,
data.can_view_stand ? 1 : 0,
data.can_view_schedule ? 1 : 0,
data.can_view_territory ? 1 : 0,
Number(data.mode),
data.mode_title,
Number(data.mode) == 0 ? null : (data.uuid_manager ? data.uuid_manager : uuid_manager),
data.uuid
]);
if (data.role === "administrator") {
if (!data.administrator?.id) {
await db.run(
'INSERT INTO administrators(sheep_id, uuid) VALUES (?, ?)',
[data.id, crypto.randomUUID()]
);
console.log({ insert: "ok" });
}
if (data.moderator?.id) {
await db.run('DELETE FROM moderators WHERE id = ?', [data.moderator.id]);
console.log({ delete: "ok" });
}
} else if (data.role === "moderator") {
if (!data.moderator?.id) {
await db.run(
`INSERT INTO moderators(sheep_id, can_add_sheeps, can_add_territory,
can_manager_territory, can_add_stand, can_manager_stand,
can_add_schedule, uuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
data.id,
data.moderator.can_add_sheeps ? 1 : 0,
data.moderator.can_add_territory ? 1 : 0,
data.moderator.can_manager_territory ? 1 : 0,
data.moderator.can_add_stand ? 1 : 0,
data.moderator.can_manager_stand ? 1 : 0,
data.moderator.can_add_schedule ? 1 : 0,
crypto.randomUUID()
]
);
console.log({ insert: "ok" });
} else {
await db.run(
`UPDATE moderators
SET can_add_sheeps = ?, can_add_territory = ?,
can_manager_territory = ?, can_add_stand = ?,
can_manager_stand = ?, can_add_schedule = ?
WHERE id = ?`,
[
data.moderator.can_add_sheeps ? 1 : 0,
data.moderator.can_add_territory ? 1 : 0,
data.moderator.can_manager_territory ? 1 : 0,
data.moderator.can_add_stand ? 1 : 0,
data.moderator.can_manager_stand ? 1 : 0,
data.moderator.can_add_schedule ? 1 : 0,
data.moderator.id
]
);
console.log({ update: "ok" });
}
if (data.administrator?.id) {
await db.run('DELETE FROM administrators WHERE id = ?', [data.administrator.id]);
console.log({ delete: "ok" });
}
} else if (data.role === "sheep") {
if (data.moderator?.id) {
await db.run('DELETE FROM moderators WHERE id = ?', [data.moderator.id]);
console.log({ delete: "ok" });
}
if (data.administrator?.id) {
await db.run('DELETE FROM administrators WHERE id = ?', [data.administrator.id]);
console.log({ delete: "ok" });
}
}
], (err) => {
if (err) return rej(err);
stmt2.run([
data.possibilities.can_add_sheeps,
data.possibilities.can_view_sheeps,
data.possibilities.can_add_territory,
data.possibilities.can_view_territory,
data.possibilities.can_manager_territory,
data.possibilities.can_add_stand,
data.possibilities.can_view_stand,
data.possibilities.can_manager_stand,
data.possibilities.can_add_schedule,
data.possibilities.can_view_schedule,
data.uuid
], (err2) => {
if (err2) return rej(err2);
res({ status: "ok", id: data.id });
} catch (err) {
console.error(err.message);
rej(false);
}
});
});
});
});
}
deleteSheep(data) {
const stmtSelect = db.prepare('SELECT id FROM sheeps WHERE uuid = ?');
const stmtDeletePoss = db.prepare('DELETE FROM possibilities WHERE sheep_id = ?');
const stmtDeleteSheep = db.prepare('DELETE FROM sheeps WHERE uuid = ?');
return new Promise((res, rej) => {
db.run('DELETE FROM sheeps WHERE uuid = ?', [data.uuid], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "dellete": "ok" });
}
db.serialize(() => {
stmtSelect.get([data.uuid], (err, row) => {
if (err) return rej(err);
if (!row) return rej(new Error("Sheep not found"));
const sheepId = row.id;
stmtDeletePoss.run([sheepId], (err2) => {
if (err2) return rej(err2);
stmtDeleteSheep.run([data.uuid], (err3) => {
if (err3) return rej(err3);
res({ status: "ok", deletedSheepId: sheepId });
});
});
});
});
});
}

View File

@@ -0,0 +1,230 @@
const crypto = require('crypto');
const db = require("../config/db");
class StandService {
getStand(id) {
return new Promise((res, rej) => {
return res({ id });
});
}
getList() {
return new Promise((res, rej) => {
const sql = `
SELECT
*
FROM
stand_list
ORDER BY
id
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"title": row.title,
"geo": JSON.parse(row.geo),
"hour_start": Number(row.hour_start),
"hour_end": Number(row.hour_end),
"quantity_sheep": Number(row.quantity_sheep),
"week_days": JSON.parse(row.week_days),
"processing_time": Number(row.processing_time),
"status": row.status == 1 ? true : false,
"updated_at": Number(row.updated_at)
}
})
return res(data);
}
});
});
}
createStand(data) {
return new Promise((res, rej) => {
let sql = 'INSERT INTO stand_list(title, geo, hour_start, hour_end, quantity_sheep, week_days, processing_time, status, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
db.run(sql, [
data.title,
JSON.stringify(data.geo || []),
Number(data.hour_start) || 9,
Number(data.hour_end) || 18,
Number(data.quantity_sheep) || 2,
JSON.stringify(data.week_days || [1]),
Number(data.processing_time) || 1,
1,
Math.floor(Date.now())
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else {
res({ "status": "ok", "id": this.lastID });
}
});
});
}
updateStand(stand_id, data) {
return new Promise((res, rej) => {
const sql = `
UPDATE stand_list SET
title = COALESCE(?, title),
geo = COALESCE(?, geo),
hour_start = COALESCE(?, hour_start),
hour_end = COALESCE(?, hour_end),
quantity_sheep = COALESCE(?, quantity_sheep),
week_days = COALESCE(?, week_days),
status = COALESCE(?, status),
updated_at = ?
WHERE id = ?
`;
db.run(sql, [
data.title ?? null,
data.geo !== undefined ? JSON.stringify(data.geo) : null,
data.hour_start !== undefined ? Number(data.hour_start) : null,
data.hour_end !== undefined ? Number(data.hour_end) : null,
data.quantity_sheep !== undefined ? Number(data.quantity_sheep) : null,
data.week_days !== undefined ? JSON.stringify(data.week_days) : null,
data.status !== undefined ? (data.status ? 1 : 0) : null,
Date.now(),
stand_id
], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ status: "ok", id: stand_id });
}
});
});
}
deleteStand(stand_id) {
return new Promise((res, rej) => {
db.run('DELETE FROM stand_list WHERE id = ?', [stand_id], function (err) {
if (err) {
console.error(err.message);
return res(false);
} else if (this.changes === 0) {
return res(false);
} else {
res({ "status": "ok", "id": stand_id });
}
});
});
}
createSchedule(stand_id) {
return new Promise((res, rej) => {
let date_start;
let getNextMonday = (ts) => {
let date = new Date(ts);
// следующий день после max_date
date.setDate(date.getDate() + 1);
// пока не понедельник добавляем дни
while (date.getDay() !== 1) {
date.setDate(date.getDate() + 1);
}
return date.getTime();
}
// 1. Получаем стенд
db.get(`SELECT * FROM stand_list WHERE id = ?`, [stand_id], (err, stand) => {
if (err) {
console.error(err.message);
return res(false);
}
if (!stand) {
console.log({ error: "id not found" });
return res(false);
}
stand.geo = JSON.parse(stand.geo);
stand.week_days = JSON.parse(stand.week_days)
// 2. Берём последний date из расписания
db.get(
`SELECT MAX(date) AS max_date FROM stand_schedule WHERE stand_id = ?`,
[stand.id],
(err, row) => {
if (err) {
console.error(err.message);
return res(false);
}
if (row && row.max_date) {
date_start = getNextMonday(row.max_date); // заменить начальную дату
} else {
date_start = getNextMonday(Date.now()); // заменить начальную дату
}
// 3. Генерация новых записей
const stand_length = (stand.hour_end - stand.hour_start) / stand.processing_time;
const timestamp = Math.floor(Date.now());
const list = [];
for (const dayOffset of stand.week_days) {
const stand_date = date_start + (dayOffset * 24 * 60 * 60 * 1000);
for (let i = 0; i < stand_length; i++) {
for (let q = 0; q < stand.quantity_sheep; q++) {
list.push([
stand.hour_start + (stand.processing_time * i),
q,
stand_date,
stand.id,
timestamp
]);
}
}
}
if (list.length === 0) {
return res({ status: "empty" });
}
// 4. Массовая вставка
const placeholders = list.map(() => "(?, ?, ?, ?, ?)").join(",");
const values = list.flat();
const insertSQL = `
INSERT INTO stand_schedule(hour, number_sheep, date, stand_id, updated_at)
VALUES ${placeholders}
`;
db.run(insertSQL, values, function (err) {
if (err) {
console.error(err.message);
return res(false);
}
res({ status: "ok", inserted: list.length });
});
}
);
});
});
}
getScheduleList(data) {
return new Promise((res, rej) => {
return res({ data });
});
}
getScheduleHistory(id) {
return new Promise((res, rej) => {
return res({ id });
});
}
}
module.exports = new StandService();

37
backup.py Normal file
View File

@@ -0,0 +1,37 @@
import os
import requests
from datetime import datetime
from zipfile import ZipFile, ZIP_DEFLATED
from dotenv import load_dotenv
# Загрузка переменных из .env
load_dotenv()
TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')
CHAT_ID = os.getenv('CHAT_ID')
DB_PATH = os.path.join(os.getenv('DB_PATH'), 'database.sqlite')
def send_document(filename, caption):
url = f'https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendDocument'
with open(filename, 'rb') as f:
response = requests.post(
url,
data={'chat_id': CHAT_ID, 'caption': caption},
files={'document': f}
)
print(response.json())
def main():
if not TELEGRAM_TOKEN or not CHAT_ID or not DB_PATH:
print("Помилка: TELEGRAM_TOKEN, CHAT_ID або DB_PATH не задано в .env.")
return
if os.path.exists(DB_PATH):
timestamp = datetime.now().strftime("%d.%m.%Y %H:%M")
caption = f"Backup Sheep Service DB - {timestamp}"
send_document(DB_PATH, caption)
else:
print("ZIP file not created")
if __name__ == "__main__":
main()

BIN
cards/cache/T80.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

BIN
cards/homestead/H1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
cards/homestead/H10.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
cards/homestead/H11.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
cards/homestead/H12.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
cards/homestead/H13.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
cards/homestead/H14.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
cards/homestead/H15.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
cards/homestead/H16.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
cards/homestead/H17.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
cards/homestead/H18.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
cards/homestead/H19.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
cards/homestead/H2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
cards/homestead/H20.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
cards/homestead/H21.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
cards/homestead/H22.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
cards/homestead/H23.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
cards/homestead/H24.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
cards/homestead/H25.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
cards/homestead/H26.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
cards/homestead/H27.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
cards/homestead/H28.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
cards/homestead/H29.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
cards/homestead/H3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
cards/homestead/H30.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
cards/homestead/H31.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
cards/homestead/H32.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
cards/homestead/H33.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
cards/homestead/H34.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
cards/homestead/H35.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
cards/homestead/H36.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
cards/homestead/H37.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
cards/homestead/H38.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
cards/homestead/H39.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
cards/homestead/H4.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
cards/homestead/H40.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
cards/homestead/H41.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
cards/homestead/H42.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
cards/homestead/H43.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
cards/homestead/H44.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
cards/homestead/H45.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
cards/homestead/H46.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
cards/homestead/H47.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
cards/homestead/H48.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
cards/homestead/H49.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
cards/homestead/H5.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
cards/homestead/H50.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
cards/homestead/H51.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
cards/homestead/H52.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
cards/homestead/H6.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
cards/homestead/H7.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
cards/homestead/H8.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
cards/homestead/H9.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
cards/house/T1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
cards/house/T10.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
cards/house/T11.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
cards/house/T12.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
cards/house/T13.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
cards/house/T14.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
cards/house/T15.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
cards/house/T16.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Some files were not shown because too many files have changed in this diff Show More