diff --git a/data/02_global-express.json b/data/02_global-express.json
index 124d754..5ec1953 100644
--- a/data/02_global-express.json
+++ b/data/02_global-express.json
@@ -1,66 +1,66 @@
{
"name": "Global Express",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "source": "https://t.me/Mariupol_global_express/1977",
"points": [
- {
- "coordinates": [
- 37.775896,
- 47.959707
- ],
- "name": "Донецк 7 (микр-н Звездный)",
- "link": "https://ozon.ru/point/534953",
- "address": "Донецк, пр-кт Ленинский 98А",
- "operationTime": "пн-вс с 9:00 до 17:00"
- },
{
"coordinates": [
37.811995,
48.011767
],
- "name": "Донецк 8 (Крытый рынок)",
"link": "https://ozon.ru/point/533323",
- "address": "Донецк, ул. 50-летия СССР 157А",
- "operationTime": "пн-пт с 9:00 до 17:00"
+ "name": "г. Донецк, ул. 50-летия СССР, 157А",
+ "address": "г. Донецк, ул. 50-летия СССР, 157А",
+ "operationTime": "ГРАФИК РАБОТЫ"
},
{
"coordinates": [
37.799192,
47.991666
],
- "name": "Донецк 1 (Южный)",
"link": "https://ozon.ru/point/533347",
- "address": "Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
- "operationTime": "пн-пт с 9:00 до 17:00, сб-вс с 10:00 ло 17:00"
+ "name": "г. Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
+ "address": "г. Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
+ "operationTime": "ГРАФИК РАБОТЫ"
+ },
+ {
+ "coordinates": [
+ 37.775896,
+ 47.959707
+ ],
+ "link": "https://ozon.ru/point/534953",
+ "name": "г. Донецк, пр - кт Ленинский, 98Аостановка «Звездный»",
+ "address": "г. Донецк, пр - кт Ленинский, 98Аостановка «Звездный»",
+ "operationTime": "ГРАФИК РАБОТЫ"
},
{
"coordinates": [
38.635921,
48.047327
],
- "name": "Торез 3",
"link": "https://ozon.ru/point/533350",
+ "name": "г. Торез, 4й микрорайон, (торговые павильоны в районе дома 23)",
"address": "г. Торез, 4й микрорайон, (торговые павильоны в районе дома 23)",
- "operationTime": "пн-вс с 9:00 до 17:00"
+ "operationTime": "ГРАФИК РАБОТЫ"
},
{
"coordinates": [
38.761523,
48.021133
],
- "name": "Снежное",
"link": "https://ozon.ru/point/534920",
+ "name": "Снежное, ул. Дзержинского, 2",
"address": "Снежное, ул. Дзержинского, 2",
- "operationTime": "пн-вс с 9:00 до 17:00"
+ "operationTime": "ГРАФИК РАБОТЫ"
},
{
"coordinates": [
38.208714,
48.221055
],
- "name": "Енакиево",
"link": "https://ozon.ru/point/534903",
+ "name": "Енакиево, проспект Ленина, 98в",
"address": "Енакиево, проспект Ленина, 98в",
- "operationTime": "пн-вс с 9:00 до 17:00"
+ "operationTime": "ГРАФИК РАБОТЫ"
}
]
}
\ No newline at end of file
diff --git a/merged-data.json b/merged-data.json
index c23a263..0c4a340 100644
--- a/merged-data.json
+++ b/merged-data.json
@@ -323,28 +323,16 @@
"source": "https://login.woyag.ru/map",
"provider": "WOЯЖ"
},
- {
- "coordinates": [
- 37.775896,
- 47.959707
- ],
- "name": "Донецк 7 (микр-н Звездный)",
- "link": "https://ozon.ru/point/534953",
- "address": "Донецк, пр-кт Ленинский 98А",
- "operationTime": "пн-вс с 9:00 до 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
- "provider": "Global Express"
- },
{
"coordinates": [
37.811995,
48.011767
],
- "name": "Донецк 8 (Крытый рынок)",
"link": "https://ozon.ru/point/533323",
- "address": "Донецк, ул. 50-летия СССР 157А",
- "operationTime": "пн-пт с 9:00 до 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "name": "г. Донецк, ул. 50-летия СССР, 157А",
+ "address": "г. Донецк, ул. 50-летия СССР, 157А",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
"provider": "Global Express"
},
{
@@ -352,11 +340,23 @@
37.799192,
47.991666
],
- "name": "Донецк 1 (Южный)",
"link": "https://ozon.ru/point/533347",
- "address": "Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
- "operationTime": "пн-пт с 9:00 до 17:00, сб-вс с 10:00 ло 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "name": "г. Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
+ "address": "г. Донецк, площадь Коммунаров 1к1, ТЦ «Южный»",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
+ "provider": "Global Express"
+ },
+ {
+ "coordinates": [
+ 37.775896,
+ 47.959707
+ ],
+ "link": "https://ozon.ru/point/534953",
+ "name": "г. Донецк, пр - кт Ленинский, 98Аостановка «Звездный»",
+ "address": "г. Донецк, пр - кт Ленинский, 98Аостановка «Звездный»",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
"provider": "Global Express"
},
{
@@ -364,11 +364,11 @@
38.635921,
48.047327
],
- "name": "Торез 3",
"link": "https://ozon.ru/point/533350",
+ "name": "г. Торез, 4й микрорайон, (торговые павильоны в районе дома 23)",
"address": "г. Торез, 4й микрорайон, (торговые павильоны в районе дома 23)",
- "operationTime": "пн-вс с 9:00 до 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
"provider": "Global Express"
},
{
@@ -376,11 +376,11 @@
38.761523,
48.021133
],
- "name": "Снежное",
"link": "https://ozon.ru/point/534920",
+ "name": "Снежное, ул. Дзержинского, 2",
"address": "Снежное, ул. Дзержинского, 2",
- "operationTime": "пн-вс с 9:00 до 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
"provider": "Global Express"
},
{
@@ -388,11 +388,11 @@
38.208714,
48.221055
],
- "name": "Енакиево",
"link": "https://ozon.ru/point/534903",
+ "name": "Енакиево, проспект Ленина, 98в",
"address": "Енакиево, проспект Ленина, 98в",
- "operationTime": "пн-вс с 9:00 до 17:00",
- "source": "https://t.me/Mariupol_global_express/1989",
+ "operationTime": "ГРАФИК РАБОТЫ",
+ "source": "https://t.me/Mariupol_global_express/1977",
"provider": "Global Express"
},
{
diff --git a/popup.js b/popup.js
index 5067a1b..c81150b 100644
--- a/popup.js
+++ b/popup.js
@@ -46,7 +46,7 @@ function onClick(event) {
popupAddress.href = `https://yandex.ru/maps/?whatshere[point]=${lon},${lat}&whatshere[zoom]=18&l=map`
popupLink.href = feature.get("link");
popupSource.href = feature.get("source");
- popupOperationTime.textContent = feature.get("operationTime") ?? "неизвестно";
+ popupOperationTime.innerHTML = feature.get("operationTime") ?? "неизвестно";
QRCode.toCanvas(popupCanvas, feature.get("link"), function (error) {
if (error) console.error(error);
diff --git a/scripts/update.js b/scripts/update.js
index 8b3d519..dd13f2d 100644
--- a/scripts/update.js
+++ b/scripts/update.js
@@ -1,49 +1,15 @@
-import fs from "node:fs/promises";
-import { asyncMap } from "modern-async";
-import { getFinalURL } from "./utils.js";
-import ozonWbDpr from "./update/ozon-wb-dpr.js";
-import sevenDostavka from "./update/sevenDostavka.js";
-
-async function woyag() {
- const apiResponse = await fetch("https://login.woyag.ru/ajax/pvz-list");
- const json = await apiResponse.json();
-
- let points = json.filter((point) => !!point.link);
-
- points = await asyncMap(points, async (point) => {
- const link = await getFinalURL(point.link).then(u => {
- const final = new URL(u);
- final.search = '';
- return final.toString();
- })
-
- return {
- coordinates: [parseFloat(point["geo_lng"]), parseFloat(point["geo_lat"])],
- name: point.name,
- address: point.address,
- link,
- operationTime: "пн-вс с 9:00 до 17:45",
- };
- });
-
- await fs.writeFile(
- "data/01_woyag.json",
- JSON.stringify(
- {
- name: "WOЯЖ",
- source: "https://login.woyag.ru/map",
- points,
- },
- undefined,
- 4
- )
- );
-}
+import {
+ woyag,
+ sevenDostavka,
+ ozonWbDpr,
+ globalExpress
+} from './update/index.js';
async function main() {
await woyag();
await sevenDostavka();
await ozonWbDpr();
+ await globalExpress();
}
main();
diff --git a/scripts/update/globalExpress.js b/scripts/update/globalExpress.js
new file mode 100644
index 0000000..ef04766
--- /dev/null
+++ b/scripts/update/globalExpress.js
@@ -0,0 +1,190 @@
+import fs from "node:fs/promises";
+
+import { JSDOM } from "jsdom";
+import { asyncMap } from "modern-async";
+import { getTelegramMessage } from "../utils.js";
+
+const OUTPUT_FILE = "data/02_global-express.json";
+const MAIN_URL = "https://t.me/Mariupol_global_express/1977";
+
+/*
+function generateReadableSchedule(schedule) {
+ const dayMappings = {
+ mon: "Пн",
+ tue: "Вт",
+ wed: "Ср",
+ thu: "Чт",
+ fri: "Пт",
+ sat: "Сб",
+ sun: "Вс",
+ };
+
+ let readableSchedule = "";
+
+ Object.keys(dayMappings).forEach((key) => {
+ const day = dayMappings[key];
+ const daySchedule = schedule[key];
+
+ if (
+ daySchedule &&
+ daySchedule.open_time !== null &&
+ daySchedule.close_time !== null
+ ) {
+ const openTime = formatTime(daySchedule.open_time);
+ const closeTime = formatTime(daySchedule.close_time);
+ const breakStart = daySchedule.break_open_time
+ ? daySchedule.break_open_time
+ : daySchedule.close_time;
+ const breakEnd = daySchedule.break_close_time
+ ? daySchedule.break_close_time
+ : daySchedule.close_time;
+
+ if (breakStart === daySchedule.close_time) {
+ readableSchedule += `${day} ${openTime} - ${closeTime}\n`;
+ } else {
+ const breakStartFormatted = formatTime(breakStart);
+ const breakEndFormatted = formatTime(breakEnd);
+ readableSchedule += `${day} ${openTime} - ${breakStartFormatted}, ${breakEndFormatted} - ${closeTime}\n`;
+ }
+ } else {
+ readableSchedule += `${day} Выходной\n`;
+ }
+ });
+
+ return readableSchedule.trim();
+}
+
+function formatTime(minutes) {
+ if (minutes < 0) return "00:00"; // Время меньше 0, возвращаем 00:00
+ const hours = Math.floor(minutes / 60);
+ const mins = minutes % 60;
+ return `${padZero(hours)}:${padZero(mins)}`;
+}
+
+function padZero(num) {
+ return num.toString().padStart(2, "0");
+}
+*/
+
+async function getPVZFromPost(post) {
+ const message = await getTelegramMessage(post);
+
+ const dom = new JSDOM(message.text);
+ const document = dom.window.document;
+
+ // Ищем координаты, которые всегда в скобках, возможно с пробелами
+ const coordinatesNode = Array.from(document.querySelectorAll("br"))
+ .map((br) => br.nextSibling)
+ .find(
+ (node) =>
+ node &&
+ node.nodeType === 3 &&
+ /\(\s*\d+(\.\d+)?\s*,\s*\d+(\.\d+)?\s*\)/.test(node.nodeValue.trim())
+ );
+
+ let coordinates = null;
+ if (coordinatesNode) {
+ const matches = coordinatesNode.nodeValue.trim().match(/\(\s*([^)]*)\s*\)/);
+ if (matches) {
+ const [lat, lng] = matches[1]
+ .split(",")
+ .map((coord) => parseFloat(coord.trim()));
+ coordinates = [lng, lat];
+ }
+ }
+
+ // Ищем ссылку, которая начинается с https://ozon.ru/point
+ const linkNode = document.querySelector('a[href^="https://ozon.ru/point"]');
+ const link = linkNode ? linkNode.href : null;
+
+ return {
+ coordinates,
+ link,
+ };
+}
+
+async function getFromTelegram() {
+ const message = await getTelegramMessage(MAIN_URL);
+
+ const dom = new JSDOM(message.text);
+ const document = dom.window.document;
+
+ const addressesSection = Array.from(document.querySelectorAll("b")).find(
+ (b) => b.textContent.includes("Наши адреса ПВЗ с OZON")
+ );
+ const privilegesSection = Array.from(document.querySelectorAll("u")).find(
+ (u) => u.textContent.includes("Какие привилегии")
+ );
+
+ const links = [];
+ let currentElement = addressesSection.nextElementSibling;
+
+ while (currentElement && currentElement !== privilegesSection) {
+ if (currentElement.tagName === "A") {
+ links.push(currentElement);
+ }
+ currentElement = currentElement.nextElementSibling;
+ }
+
+ const data = await asyncMap(links, async (link) => {
+ const textContent = link.textContent;
+
+ const pvzData = await getPVZFromPost(link.href);
+
+ return {
+ ...pvzData,
+ name: textContent,
+ address: textContent,
+ };
+ });
+
+ return data;
+}
+
+/*
+async function getFromVK() {
+ const group_id = 124759560;
+ const access_token = "";
+ const v = "5.199";
+
+ const res = await fetch(
+ `https://api.vk.com/method/groups.getAddresses?group_id=${group_id}&access_token=${access_token}&count=999&v=${v}`,
+ {
+ headers: {
+ "Accept-Language": "ru,en;q=0.9",
+ },
+ }
+ );
+
+ const items = (await res.json()).response.items;
+
+ return items.map((item) => ({
+ address: `${item.city.title}, ${item.address}`,
+ timetable: item.timetable,
+ }));
+}
+*/
+
+async function globalExpress() {
+ const points = await getFromTelegram();
+ // const points = await getFromVK();
+
+ fs.writeFile(
+ OUTPUT_FILE,
+ JSON.stringify(
+ {
+ name: "Global Express",
+ source: MAIN_URL,
+ points: points.map((p) => ({
+ ...p,
+ operationTime:
+ `ГРАФИК РАБОТЫ`,
+ })),
+ },
+ undefined,
+ 4
+ )
+ );
+}
+
+export default globalExpress;
diff --git a/scripts/update/index.js b/scripts/update/index.js
index e69de29..9cb03a0 100644
--- a/scripts/update/index.js
+++ b/scripts/update/index.js
@@ -0,0 +1,4 @@
+export { default as woyag } from "./woyag.js";
+export { default as ozonWbDpr } from "./ozon-wb-dpr.js";
+export { default as sevenDostavka } from "./sevenDostavka.js";
+export { default as globalExpress } from "./globalExpress.js";
diff --git a/scripts/update/ozon-wb-dpr.js b/scripts/update/ozon-wb-dpr.js
index 7f3a047..2381d40 100644
--- a/scripts/update/ozon-wb-dpr.js
+++ b/scripts/update/ozon-wb-dpr.js
@@ -4,6 +4,8 @@ import { JSDOM } from "jsdom";
import { asyncMap } from "modern-async";
import fs from "node:fs/promises";
+const OUTPUT_FILE = "data/03_ozon-wb-dpr.json";
+
const MAIN_URL = "https://t.me/ozon_wb_dpr/627";
const QR_FOR_PVZ_STRING = "QR для ПВЗ";
@@ -108,7 +110,7 @@ async function ozonWbDpr() {
});
await fs.writeFile(
- "data/03_ozon-wb-dpr.json",
+ OUTPUT_FILE,
JSON.stringify(
{
name: "ПВЗ ДНР",
diff --git a/scripts/update/sevenDostavka.js b/scripts/update/sevenDostavka.js
index 87afeb4..fb1cfab 100644
--- a/scripts/update/sevenDostavka.js
+++ b/scripts/update/sevenDostavka.js
@@ -1,6 +1,8 @@
import fs from "node:fs/promises";
import { JSDOM } from "jsdom";
+const OUTPUT_FILE = "data/99_sevenDostavka.json";
+
const linkRegexp = new RegExp(/https:\/\/ozon\.ru\/point\/\d+/);
async function sevenDostavka() {
@@ -19,7 +21,7 @@ async function sevenDostavka() {
const points = new Function(`return [{${x}}]`)();
fs.writeFile(
- "data/99_sevenDostavka.json",
+ OUTPUT_FILE,
JSON.stringify(
{
name: "7dostavka",
@@ -44,4 +46,4 @@ async function sevenDostavka() {
}
}
-export default sevenDostavka;
\ No newline at end of file
+export default sevenDostavka;
diff --git a/scripts/update/woyag.js b/scripts/update/woyag.js
new file mode 100644
index 0000000..1a966d5
--- /dev/null
+++ b/scripts/update/woyag.js
@@ -0,0 +1,43 @@
+import fs from "node:fs/promises";
+import { asyncMap } from "modern-async";
+import { getFinalURL } from "../utils.js";
+
+const OUTPUT_FILE = "data/01_woyag.json";
+
+async function woyag() {
+ const apiResponse = await fetch("https://login.woyag.ru/ajax/pvz-list");
+ const json = await apiResponse.json();
+
+ let points = json.filter((point) => !!point.link);
+
+ points = await asyncMap(points, async (point) => {
+ const link = await getFinalURL(point.link).then(u => {
+ const final = new URL(u);
+ final.search = '';
+ return final.toString();
+ })
+
+ return {
+ coordinates: [parseFloat(point["geo_lng"]), parseFloat(point["geo_lat"])],
+ name: point.name,
+ address: point.address,
+ link,
+ operationTime: "пн-вс с 9:00 до 17:45",
+ };
+ });
+
+ await fs.writeFile(
+ OUTPUT_FILE,
+ JSON.stringify(
+ {
+ name: "WOЯЖ",
+ source: "https://login.woyag.ru/map",
+ points,
+ },
+ undefined,
+ 4
+ )
+ );
+}
+
+export default woyag
\ No newline at end of file