|
|
from flask import Flask, render_template_string, jsonify, request |
|
|
import json |
|
|
import os |
|
|
import math |
|
|
from datetime import datetime, timedelta |
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
|
|
|
|
def init_db(): |
|
|
if not os.path.exists('markers.json'): |
|
|
with open('markers.json', 'w', encoding='utf-8') as f: |
|
|
json.dump([], f, ensure_ascii=False, indent=4) |
|
|
|
|
|
|
|
|
def load_markers(): |
|
|
with open('markers.json', 'r', encoding='utf-8') as f: |
|
|
return json.load(f) |
|
|
|
|
|
|
|
|
def save_markers(markers): |
|
|
with open('markers.json', 'w', encoding='utf-8') as f: |
|
|
json.dump(markers, f, ensure_ascii=False, indent=4) |
|
|
|
|
|
|
|
|
def get_all_markers(): |
|
|
return load_markers() |
|
|
|
|
|
|
|
|
def add_marker_to_db(name, description, telegram_link, logo_link, latitude, longitude, delete_password): |
|
|
markers = load_markers() |
|
|
new_id = max((marker["id"] for marker in markers), default=0) + 1 |
|
|
new_marker = { |
|
|
"id": new_id, |
|
|
"name": name, |
|
|
"description": description, |
|
|
"telegram_link": telegram_link, |
|
|
"logo_link": logo_link, |
|
|
"latitude": latitude, |
|
|
"longitude": longitude, |
|
|
"delete_password": delete_password, |
|
|
"premium": 0, |
|
|
"premium_start_date": None |
|
|
} |
|
|
markers.append(new_marker) |
|
|
save_markers(markers) |
|
|
return new_id |
|
|
|
|
|
|
|
|
def remove_marker_from_db(marker_id): |
|
|
markers = load_markers() |
|
|
markers = [marker for marker in markers if marker["id"] != marker_id] |
|
|
save_markers(markers) |
|
|
|
|
|
|
|
|
def activate_premium(marker_id): |
|
|
markers = load_markers() |
|
|
current_date = datetime.now().isoformat() |
|
|
for marker in markers: |
|
|
if marker["id"] == marker_id: |
|
|
marker["premium"] = 1 |
|
|
marker["premium_start_date"] = current_date |
|
|
break |
|
|
save_markers(markers) |
|
|
|
|
|
|
|
|
def check_premium_status(): |
|
|
markers = load_markers() |
|
|
updated = False |
|
|
for marker in markers: |
|
|
if marker["premium"] == 1 and marker["premium_start_date"]: |
|
|
premium_start_date = datetime.fromisoformat(marker["premium_start_date"]) |
|
|
current_date = datetime.now() |
|
|
if (current_date - premium_start_date).days > 30: |
|
|
marker["premium"] = 0 |
|
|
marker["premium_start_date"] = None |
|
|
updated = True |
|
|
if updated: |
|
|
save_markers(markers) |
|
|
|
|
|
|
|
|
html_template = ''' |
|
|
<!DOCTYPE html> |
|
|
<html lang="ru"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>GeoGram 2070</title> |
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"> |
|
|
<style> |
|
|
/* Общие стили */ |
|
|
body { |
|
|
font-family: 'Roboto', sans-serif; |
|
|
background: linear-gradient(135deg, #0f0c29, #302b63, #24243e); |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
color: #fff; |
|
|
overflow-x: hidden; |
|
|
} |
|
|
h1 { |
|
|
text-align: center; |
|
|
padding: 20px; |
|
|
margin: 0; |
|
|
background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
font-size: 32px; |
|
|
letter-spacing: 4px; |
|
|
text-shadow: 0 0 10px rgba(255, 0, 204, 0.8), 0 0 20px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
#map { |
|
|
height: 90vh; |
|
|
width: 100%; |
|
|
margin-bottom: 20px; |
|
|
} |
|
|
|
|
|
/* Поиск */ |
|
|
#search-container { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
margin: 20px; |
|
|
} |
|
|
#search-input { |
|
|
padding: 15px; |
|
|
width: 300px; |
|
|
border: none; |
|
|
border-radius: 30px 0 0 30px; |
|
|
font-size: 16px; |
|
|
background: #24243e; |
|
|
color: #fff; |
|
|
outline: none; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
#search-input:focus { |
|
|
background: #302b63; |
|
|
} |
|
|
#search-button { |
|
|
padding: 15px 30px; |
|
|
background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
border-radius: 0 30px 30px 0; |
|
|
cursor: pointer; |
|
|
font-size: 16px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
#search-button:hover { |
|
|
background: linear-gradient(135deg, #333399, #ff00cc); |
|
|
} |
|
|
|
|
|
/* Результаты поиска */ |
|
|
#search-results { |
|
|
margin: 20px; |
|
|
text-align: center; |
|
|
} |
|
|
.result-item { |
|
|
background: linear-gradient(135deg, #24243e, #302b63); |
|
|
border: 1px solid rgba(255, 0, 204, 0.5); |
|
|
border-radius: 15px; |
|
|
margin: 10px auto; |
|
|
padding: 20px; |
|
|
max-width: 500px; |
|
|
transition: transform 0.3s ease, box-shadow 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.result-item:hover { |
|
|
transform: translateY(-5px); |
|
|
box-shadow: 0 0 20px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.result-item b { |
|
|
color: #ff00cc; |
|
|
font-size: 18px; |
|
|
} |
|
|
.result-item p { |
|
|
color: #ecf0f1; |
|
|
margin: 5px 0; |
|
|
} |
|
|
.result-item a { |
|
|
color: #ff00cc; |
|
|
text-decoration: none; |
|
|
font-weight: bold; |
|
|
} |
|
|
.result-item a:hover { |
|
|
text-decoration: underline; |
|
|
} |
|
|
.result-item button { |
|
|
background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 10px 20px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.result-item button:hover { |
|
|
background: linear-gradient(135deg, #333399, #ff00cc); |
|
|
} |
|
|
|
|
|
/* Окно добавления метки */ |
|
|
.popup-form { |
|
|
background: linear-gradient(135deg, #24243e, #302b63); |
|
|
border-radius: 15px; |
|
|
padding: 20px; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
width: 300px; |
|
|
} |
|
|
.popup-form input, |
|
|
.popup-form textarea { |
|
|
padding: 12px; |
|
|
margin-bottom: 10px; |
|
|
border: none; |
|
|
border-radius: 10px; |
|
|
font-size: 14px; |
|
|
background: #302b63; |
|
|
color: #fff; |
|
|
outline: none; |
|
|
transition: background 0.3s ease; |
|
|
} |
|
|
.popup-form input:focus, |
|
|
.popup-form textarea:focus { |
|
|
background: #ff00cc; |
|
|
} |
|
|
.popup-form button { |
|
|
background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 12px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.popup-form button:hover { |
|
|
background: linear-gradient(135deg, #333399, #ff00cc); |
|
|
} |
|
|
|
|
|
/* Попапы на карте */ |
|
|
.leaflet-popup-content-wrapper { |
|
|
background: linear-gradient(135deg, #24243e, #302b63); |
|
|
border-radius: 15px; |
|
|
padding: 15px; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.leaflet-popup-content { |
|
|
color: #fff; |
|
|
} |
|
|
.leaflet-popup-content b { |
|
|
color: #ff00cc; |
|
|
font-size: 18px; |
|
|
display: block; |
|
|
margin-bottom: 5px; |
|
|
} |
|
|
.leaflet-popup-content a { |
|
|
color: #ff00cc; |
|
|
text-decoration: none; |
|
|
} |
|
|
.leaflet-popup-content a:hover { |
|
|
text-decoration: underline; |
|
|
} |
|
|
.leaflet-popup-content button { |
|
|
background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 10px 20px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
.leaflet-popup-content button:hover { |
|
|
background: linear-gradient(135deg, #333399, #ff00cc); |
|
|
} |
|
|
|
|
|
/* Маркеры */ |
|
|
.marker-logo { |
|
|
width: 30px; |
|
|
height: 30px; |
|
|
border-radius: 50%; |
|
|
border: 2px solid #ff00cc; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8); |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<h1>GeoGram 2070</h1> |
|
|
<div id="search-container"> |
|
|
<input type="text" id="search-input" placeholder="Поиск по названию или описанию" /> |
|
|
<button id="search-button">Поиск</button> |
|
|
</div> |
|
|
<div id="search-results"></div> |
|
|
<div id="map"></div> |
|
|
|
|
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script> |
|
|
<script> |
|
|
const map = L.map('map').setView([55.75, 37.61], 13); |
|
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
|
maxZoom: 19, |
|
|
}).addTo(map); |
|
|
|
|
|
let userLatitude = 55.75; |
|
|
let userLongitude = 37.61; |
|
|
|
|
|
if (navigator.geolocation) { |
|
|
navigator.geolocation.getCurrentPosition(function(position) { |
|
|
userLatitude = position.coords.latitude; |
|
|
userLongitude = position.coords.longitude; |
|
|
map.setView([userLatitude, userLongitude], 13); |
|
|
|
|
|
L.marker([userLatitude, userLongitude]).addTo(map) |
|
|
.bindPopup('<span style="color:white;">Вы находитесь здесь</span>').openPopup(); |
|
|
}, function() { |
|
|
alert('Не удалось получить ваше местоположение.'); |
|
|
}); |
|
|
} else { |
|
|
alert('Ваш браузер не поддерживает геолокацию.'); |
|
|
} |
|
|
|
|
|
let markersOnMap = {}; |
|
|
|
|
|
fetch('/get_markers') |
|
|
.then(response => response.json()) |
|
|
.then(data => { |
|
|
data.forEach(marker => { |
|
|
const customIcon = L.divIcon({ |
|
|
className: 'custom-icon', |
|
|
html: `<img src="${marker.logo_link || 'https://simpleicon.com/wp-content/uploads/map-marker-1.png'}" class="marker-logo"/>`, |
|
|
iconSize: [30, 30], |
|
|
iconAnchor: [15, 30] |
|
|
}); |
|
|
|
|
|
const markerObj = L.marker([marker.latitude, marker.longitude], {icon: customIcon}).addTo(map); |
|
|
markersOnMap[marker.id] = markerObj; |
|
|
|
|
|
let premiumLabel = ''; |
|
|
if (marker.premium) { |
|
|
const premiumStartDate = new Date(marker.premium_start_date); |
|
|
const currentDate = new Date(); |
|
|
const daysLeft = Math.max(0, Math.floor((premiumStartDate.getTime() + (30 * 24 * 60 * 60 * 1000) - currentDate.getTime()) / (1000 * 60 * 60 * 24))); |
|
|
premiumLabel = `<span style="color: gold;">Премиум метка (${daysLeft} дней осталось)</span><br>`; |
|
|
} |
|
|
|
|
|
markerObj.bindPopup(` |
|
|
<div class="leaflet-popup-content"> |
|
|
${premiumLabel} |
|
|
<b>${marker.name}</b> |
|
|
<p>${marker.description}</p> |
|
|
<button style="background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 10px 20px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8);" |
|
|
onclick="window.open('https://t.me/${marker.telegram_link}', '_blank')"> |
|
|
Перейти в Telegram |
|
|
</button><br> |
|
|
<button onclick="buyPremium(${marker.id})">Купить премиум</button> |
|
|
<button onclick="removeMarker(${marker.id}, '${marker.delete_password}')">Удалить</button> |
|
|
</div> |
|
|
`); |
|
|
}); |
|
|
}); |
|
|
|
|
|
function buyPremium(markerId) { |
|
|
const activationCode = prompt("Введите код активации премиума:"); |
|
|
|
|
|
if (activationCode === "morshenadmin87132") { |
|
|
fetch('/activate_premium', { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
body: JSON.stringify({id: markerId}) |
|
|
}).then(() => { |
|
|
alert("Премиум активирован!"); |
|
|
location.reload(); |
|
|
}); |
|
|
} else { |
|
|
alert("Неверный код активации!"); |
|
|
} |
|
|
} |
|
|
|
|
|
function addMarker(name, description, telegram_link, logo_link, position) { |
|
|
const deletePassword = prompt("Введите пароль для удаления метки:"); |
|
|
|
|
|
const finalLogoLink = logo_link || 'https://icons.veryicon.com/png/o/miscellaneous/high-icon-library/geo-fence.png'; |
|
|
|
|
|
fetch('/add_marker', { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
body: JSON.stringify({ |
|
|
name: name, |
|
|
description: description, |
|
|
telegram_link: telegram_link, |
|
|
logo_link: finalLogoLink, |
|
|
position: [position.lat, position.lng], |
|
|
delete_password: deletePassword |
|
|
}) |
|
|
}) |
|
|
.then(response => response.json()) |
|
|
.then(data => { |
|
|
const customIcon = L.divIcon({ |
|
|
className: 'custom-icon', |
|
|
html: `<img src="${data.logo_link}" class="marker-logo"/>`, |
|
|
iconSize: [30, 30], |
|
|
iconAnchor: [15, 30] |
|
|
}); |
|
|
|
|
|
const markerObj = L.marker([data.latitude, data.longitude], {icon: customIcon}).addTo(map); |
|
|
markersOnMap[data.id] = markerObj; |
|
|
|
|
|
let premiumLabel = data.premium ? '<span style="color: gold;">Премиум метка</span><br>' : ''; |
|
|
|
|
|
markerObj.bindPopup(` |
|
|
<div class="leaflet-popup-content"> |
|
|
${premiumLabel} |
|
|
<b>${data.name}</b> |
|
|
<p>${data.description}</p> |
|
|
<button style="background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 10px 20px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8);" |
|
|
onclick="window.open('https://t.me/${data.telegram_link}', '_blank')"> |
|
|
Перейти в Telegram |
|
|
</button><br> |
|
|
<button onclick="buyPremium(${data.id})">Купить премиум</button> |
|
|
<button onclick="removeMarker(${data.id}, '${data.delete_password}')">Удалить</button> |
|
|
</div> |
|
|
`); |
|
|
}); |
|
|
} |
|
|
|
|
|
map.on('click', function(e) { |
|
|
const popupContent = document.createElement('div'); |
|
|
popupContent.classList.add('popup-form'); |
|
|
|
|
|
const inputName = document.createElement('input'); |
|
|
inputName.type = 'text'; |
|
|
inputName.placeholder = 'Название '; |
|
|
popupContent.appendChild(inputName); |
|
|
|
|
|
const inputDescription = document.createElement('textarea'); |
|
|
inputDescription.placeholder = 'Ваши товары/услуги'; |
|
|
popupContent.appendChild(inputDescription); |
|
|
|
|
|
const inputTelegram = document.createElement('input'); |
|
|
inputTelegram.type = 'text'; |
|
|
inputTelegram.placeholder = 'Telegram канал (без @)'; |
|
|
popupContent.appendChild(inputTelegram); |
|
|
|
|
|
const inputLogoLink = document.createElement('input'); |
|
|
inputLogoLink.type = 'text'; |
|
|
inputLogoLink.placeholder = 'Ссылка на логотип (необязательно)'; |
|
|
popupContent.appendChild(inputLogoLink); |
|
|
|
|
|
const submitButton = document.createElement('button'); |
|
|
submitButton.textContent = 'Добавить метку'; |
|
|
submitButton.onclick = function() { |
|
|
const name = inputName.value; |
|
|
const description = inputDescription.value; |
|
|
const telegram_link = inputTelegram.value; |
|
|
const logo_link = inputLogoLink.value; |
|
|
if(name && description && telegram_link) { |
|
|
addMarker(name, description, telegram_link, logo_link, e.latlng); |
|
|
} |
|
|
map.closePopup(); |
|
|
}; |
|
|
popupContent.appendChild(submitButton); |
|
|
|
|
|
L.popup() |
|
|
.setLatLng(e.latlng) |
|
|
.setContent(popupContent) |
|
|
.openOn(map); |
|
|
}); |
|
|
|
|
|
function removeMarker(markerId, markerPassword) { |
|
|
const universalPassword = "morshenadmin87132"; |
|
|
const passwordInput = prompt("Введите пароль для удаления метки:"); |
|
|
|
|
|
if (passwordInput === universalPassword || passwordInput === markerPassword) { |
|
|
fetch('/remove_marker', { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
body: JSON.stringify({id: markerId}) |
|
|
}).then(() => { |
|
|
location.reload(); |
|
|
}); |
|
|
} else { |
|
|
alert("Неверный пароль!"); |
|
|
} |
|
|
} |
|
|
|
|
|
// Обновленная функция поиска с приоритетом премиум меток |
|
|
document.getElementById('search-button').addEventListener('click', function() { |
|
|
const searchTerm = document.getElementById('search-input').value.toLowerCase(); |
|
|
fetch('/get_markers') |
|
|
.then(response => response.json()) |
|
|
.then(data => { |
|
|
const resultsContainer = document.getElementById('search-results'); |
|
|
resultsContainer.innerHTML = ''; |
|
|
|
|
|
// Вычисление расстояния до каждого маркера |
|
|
data.forEach(marker => { |
|
|
marker.distance = calculateDistance(userLatitude, userLongitude, marker.latitude, marker.longitude); |
|
|
}); |
|
|
|
|
|
// Фильтрация результатов по поисковому запросу |
|
|
const results = data.filter(marker => |
|
|
marker.name.toLowerCase().includes(searchTerm) || |
|
|
marker.description.toLowerCase().includes(searchTerm) |
|
|
); |
|
|
|
|
|
// Сортировка результатов: сначала премиум метки, затем обычные, |
|
|
// и внутри каждой категории сортировка по расстоянию |
|
|
results.sort((a, b) => { |
|
|
if (a.premium !== b.premium) { |
|
|
return b.premium - a.premium; // Премиум метки идут первыми |
|
|
} |
|
|
return a.distance - b.distance; // Сортировка по расстоянию |
|
|
}); |
|
|
|
|
|
// Отображение результатов |
|
|
results.forEach(marker => { |
|
|
const resultItem = document.createElement('div'); |
|
|
resultItem.classList.add('result-item'); |
|
|
|
|
|
let premiumLabel = ''; |
|
|
if (marker.premium) { |
|
|
const premiumStartDate = new Date(marker.premium_start_date); |
|
|
const currentDate = new Date(); |
|
|
const daysLeft = Math.max(0, Math.floor((premiumStartDate.getTime() + (30 * 24 * 60 * 60 * 1000) - currentDate.getTime()) / (1000 * 60 * 60 * 24))); |
|
|
premiumLabel = ` (${daysLeft} дней осталось)`; |
|
|
} |
|
|
|
|
|
resultItem.innerHTML = ` |
|
|
<b>${marker.name}</b> |
|
|
<p>${marker.description}</p> |
|
|
<p>Расстояние: ${marker.distance.toFixed(2)} км</p> |
|
|
<p>Статус: ${marker.premium ? 'Премиум' + premiumLabel : 'Обычная'}</p> |
|
|
<button style="background: linear-gradient(135deg, #ff00cc, #333399); |
|
|
color: white; |
|
|
border: none; |
|
|
padding: 10px 20px; |
|
|
border-radius: 30px; |
|
|
cursor: pointer; |
|
|
font-size: 14px; |
|
|
transition: background 0.3s ease; |
|
|
box-shadow: 0 0 10px rgba(255, 0, 204, 0.8);" |
|
|
onclick="window.open('https://t.me/${marker.telegram_link}', '_blank')"> |
|
|
Перейти в Telegram |
|
|
</button> |
|
|
<button onclick="showOnMap(${marker.id}, ${marker.latitude}, ${marker.longitude}); hideResults()">Показать на карте</button>`; |
|
|
|
|
|
resultsContainer.appendChild(resultItem); |
|
|
}); |
|
|
|
|
|
if (results.length === 0) { |
|
|
resultsContainer.innerHTML = '<p style="color:white;">Нет результатов</p>'; |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
function showOnMap(markerId, lat, lng) { |
|
|
map.setView([lat, lng], 13); |
|
|
if (markersOnMap[markerId]) { |
|
|
markersOnMap[markerId].openPopup(); |
|
|
} |
|
|
} |
|
|
|
|
|
function hideResults() { |
|
|
const resultsContainer = document.getElementById('search-results'); |
|
|
resultsContainer.innerHTML = ''; |
|
|
} |
|
|
|
|
|
function calculateDistance(lat1, lon1, lat2, lon2) { |
|
|
const R = 6371; |
|
|
const dLat = (lat2 - lat1) * Math.PI / 180; |
|
|
const dLon = (lon2 - lon1) * Math.PI / 180; |
|
|
const a = |
|
|
0.5 - Math.cos(dLat) / 2 + |
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * |
|
|
(1 - Math.cos(dLon)) / 2; |
|
|
|
|
|
return R * 2 * Math.asin(Math.sqrt(a)); |
|
|
} |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
''' |
|
|
|
|
|
|
|
|
@app.route('/') |
|
|
def index(): |
|
|
check_premium_status() |
|
|
return render_template_string(html_template) |
|
|
|
|
|
|
|
|
@app.route('/get_markers') |
|
|
def get_markers_route(): |
|
|
markers = get_all_markers() |
|
|
|
|
|
for marker in markers: |
|
|
if not marker.get("logo_link"): |
|
|
marker["logo_link"] = "https://simpleicon.com/wp-content/uploads/map-marker-1.png" |
|
|
return jsonify(markers) |
|
|
|
|
|
|
|
|
@app.route('/add_marker', methods=['POST']) |
|
|
def add_marker(): |
|
|
data = request.json |
|
|
name = data['name'] |
|
|
description = data['description'] |
|
|
telegram_link = data['telegram_link'] |
|
|
logo_link = data['logo_link'] if data['logo_link'] else 'https://simpleicon.com/wp-content/uploads/map-marker-1.png' |
|
|
latitude, longitude = data['position'] |
|
|
delete_password = data['delete_password'] |
|
|
|
|
|
marker_id = add_marker_to_db(name, description, telegram_link, logo_link, latitude, longitude, delete_password) |
|
|
|
|
|
return jsonify({ |
|
|
'id': marker_id, |
|
|
'name': name, |
|
|
'description': description, |
|
|
'telegram_link': telegram_link, |
|
|
'logo_link': logo_link, |
|
|
'latitude': latitude, |
|
|
'longitude': longitude, |
|
|
'delete_password': delete_password, |
|
|
'premium': 0, |
|
|
'premium_start_date': None |
|
|
}) |
|
|
|
|
|
|
|
|
@app.route('/remove_marker', methods=['POST']) |
|
|
def remove_marker_route(): |
|
|
data = request.json |
|
|
marker_id = data['id'] |
|
|
remove_marker_from_db(marker_id) |
|
|
return jsonify({'success': True}) |
|
|
|
|
|
|
|
|
@app.route('/activate_premium', methods=['POST']) |
|
|
def activate_premium_route(): |
|
|
data = request.json |
|
|
marker_id = data['id'] |
|
|
activate_premium(marker_id) |
|
|
return jsonify({'success': True}) |
|
|
|
|
|
if __name__ == '__main__': |
|
|
init_db() |
|
|
app.run(debug=True, host='0.0.0.0', port=7860) |