| from flask import Flask, render_template_string, jsonify, request |
| import sqlite3 |
|
|
| app = Flask(__name__) |
|
|
| |
| def init_db(): |
| conn = sqlite3.connect('markers.db') |
| cursor = conn.cursor() |
| cursor.execute('''CREATE TABLE IF NOT EXISTS markers ( |
| id INTEGER PRIMARY KEY AUTOINCREMENT, |
| name TEXT NOT NULL, |
| description TEXT, |
| telegram_link TEXT, |
| latitude REAL NOT NULL, |
| longitude REAL NOT NULL |
| )''') |
| conn.commit() |
| conn.close() |
|
|
| |
| def get_all_markers(): |
| conn = sqlite3.connect('markers.db') |
| cursor = conn.cursor() |
| cursor.execute('SELECT id, name, description, telegram_link, latitude, longitude FROM markers') |
| markers = cursor.fetchall() |
| conn.close() |
| return markers |
|
|
| |
| def add_marker_to_db(name, description, telegram_link, latitude, longitude): |
| conn = sqlite3.connect('markers.db') |
| cursor = conn.cursor() |
| cursor.execute('INSERT INTO markers (name, description, telegram_link, latitude, longitude) VALUES (?, ?, ?, ?, ?)', |
| (name, description, telegram_link, latitude, longitude)) |
| conn.commit() |
| marker_id = cursor.lastrowid |
| conn.close() |
| return marker_id |
|
|
| |
| def remove_marker_from_db(marker_id): |
| conn = sqlite3.connect('markers.db') |
| cursor = conn.cursor() |
| cursor.execute('DELETE FROM markers WHERE id = ?', (marker_id,)) |
| conn.commit() |
| conn.close() |
|
|
| |
| 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</title> |
| <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"> |
| <style> |
| body { |
| font-family: Arial, sans-serif; |
| background-color: #f7f7f7; |
| margin: 0; |
| padding: 0; |
| } |
| #map { |
| height: 80vh; |
| width: 100%; |
| } |
| h1 { |
| text-align: center; |
| padding: 20px; |
| margin: 0; |
| background-color: #007BFF; |
| color: white; |
| font-size: 24px; |
| } |
| .leaflet-popup-content-wrapper { |
| background-color: #fff; |
| border-radius: 10px; |
| padding: 10px; |
| box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); |
| } |
| .leaflet-popup-content b { |
| color: #007BFF; |
| font-size: 18px; |
| display: block; |
| margin-bottom: 5px; |
| } |
| .leaflet-popup-content a { |
| color: #007BFF; |
| text-decoration: none; |
| } |
| .leaflet-popup-content a:hover { |
| text-decoration: underline; |
| } |
| .popup-form { |
| display: flex; |
| flex-direction: column; |
| width: 200px; |
| } |
| .popup-form input, .popup-form textarea { |
| padding: 5px; |
| margin-bottom: 10px; |
| border: 1px solid #ccc; |
| border-radius: 5px; |
| font-size: 14px; |
| } |
| .popup-form button { |
| background-color: #007BFF; |
| color: white; |
| border: none; |
| padding: 8px 12px; |
| border-radius: 5px; |
| cursor: pointer; |
| } |
| .popup-form button:hover { |
| background-color: #0056b3; |
| } |
| #search-input { |
| margin: 20px; |
| padding: 8px; |
| width: calc(100% - 40px); |
| border: 1px solid #ccc; |
| border-radius: 5px; |
| } |
| #search-button { |
| padding: 8px 12px; |
| background-color: #007BFF; |
| color: white; |
| border: none; |
| border-radius: 5px; |
| cursor: pointer; |
| } |
| #search-button:hover { |
| background-color: #0056b3; |
| } |
| #search-results { |
| margin: 20px; |
| } |
| </style> |
| </head> |
| <body> |
| <h1>GeoGram</h1> |
| <div> |
| <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); |
| |
| // Проверка поддержки геолокации и установка центра карты на текущее местоположение пользователя |
| if (navigator.geolocation) { |
| navigator.geolocation.getCurrentPosition(function(position) { |
| const userLatitude = position.coords.latitude; |
| const userLongitude = position.coords.longitude; |
| map.setView([userLatitude, userLongitude], 13); |
| |
| // Добавление маркера для местоположения пользователя |
| L.marker([userLatitude, userLongitude]).addTo(map) |
| .bindPopup('Вы находитесь здесь').openPopup(); |
| }, function() { |
| alert('Не удалось получить ваше местоположение.'); |
| }); |
| } else { |
| alert('Ваш браузер не поддерживает геолокацию.'); |
| } |
| |
| // Загрузка существующих меток из базы данных |
| fetch('/get_markers') |
| .then(response => response.json()) |
| .then(data => { |
| data.forEach(marker => { |
| const markerObj = L.marker([marker.latitude, marker.longitude]).addTo(map); |
| markerObj.bindPopup(`<b>${marker.name}</b><p>${marker.description}</p><a href="https://t.me/${marker.telegram_link}" target="_blank">Перейти в Telegram</a><br><button onclick="removeMarker(${marker.id})">Удалить</button>`); |
| }); |
| }); |
| |
| // Функция для добавления метки |
| function addMarker(name, description, telegram_link, position) { |
| fetch('/add_marker', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| name: name, |
| description: description, |
| telegram_link: telegram_link, |
| position: [position.lat, position.lng] |
| }) |
| }) |
| .then(response => response.json()) |
| .then(data => { |
| const markerObj = L.marker([data.latitude, data.longitude]).addTo(map); |
| markerObj.bindPopup(`<b>${data.name}</b><p>${data.description}</p><a href="https://t.me/${data.telegram_link}" target="_blank">Перейти в Telegram</a><br><button onclick="removeMarker(${data.id})">Удалить</button>`); |
| }); |
| } |
| |
| // Событие клика по карте для добавления формы |
| 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 = 'Название метки'; |
| |
| const inputDescription = document.createElement('textarea'); |
| inputDescription.placeholder = 'Описание метки'; |
| |
| const inputTelegram = document.createElement('input'); |
| inputTelegram.type = 'text'; |
| inputTelegram.placeholder = 'Имя пользователя Telegram (без https://t.me/)'; |
| |
| const button = document.createElement('button'); |
| button.textContent = 'Добавить метку'; |
| button.onclick = function() { |
| const markerName = inputName.value; |
| const markerDescription = inputDescription.value; |
| const markerTelegram = inputTelegram.value; |
| if (markerName && markerTelegram) { |
| addMarker(markerName, markerDescription, markerTelegram, e.latlng); |
| map.closePopup(); |
| } |
| }; |
| |
| popupContent.appendChild(inputName); |
| popupContent.appendChild(inputDescription); |
| popupContent.appendChild(inputTelegram); |
| popupContent.appendChild(button); |
| |
| const popup = L.popup() |
| .setLatLng(e.latlng) |
| .setContent(popupContent) |
| .openOn(map); |
| }); |
| |
| // Удаление метки |
| function removeMarker(id) { |
| fetch(`/remove_marker/${id}`, { |
| method: 'DELETE' |
| }).then(() => { |
| location.reload(); |
| }); |
| } |
| |
| // Функция для поиска меток |
| function searchMarkers(query) { |
| fetch(`/search_markers?query=${encodeURIComponent(query)}`) |
| .then(response => response.json()) |
| .then(data => { |
| const resultsDiv = document.getElementById('search-results'); |
| resultsDiv.innerHTML = ''; // Очистить предыдущие результаты |
| if (data.length > 0) { |
| data.forEach(marker => { |
| const resultItem = document.createElement('div'); |
| resultItem.innerHTML = `<b>${marker.name}</b>: ${marker.description} <button onclick="showMarker(${marker.id})">Показать на карте</button>`; |
| resultsDiv.appendChild(resultItem); |
| }); |
| } else { |
| resultsDiv.innerHTML = '<p>Нет результатов</p>'; |
| } |
| }); |
| } |
| |
| // Обработчик события для кнопки поиска |
| document.getElementById('search-button').onclick = function() { |
| const query = document.getElementById('search-input').value; |
| searchMarkers(query); |
| }; |
| |
| // Функция для показа метки на карте |
| function showMarker(markerId) { |
| fetch(`/get_markers`) |
| .then(response => response.json()) |
| .then(data => { |
| const marker = data.find(m => m.id === markerId); |
| if (marker) { |
| map.setView([marker.latitude, marker.longitude], 13); |
| L.marker([marker.latitude, marker.longitude]).addTo(map) |
| .bindPopup(`<b>${marker.name}</b><p>${marker.description}</p><a href="https://t.me/${marker.telegram_link}" target="_blank">Перейти в Telegram</a>`); |
| } |
| }); |
| } |
| </script> |
| </body> |
| </html> |
| ''' |
|
|
| @app.route('/') |
| def index(): |
| return render_template_string(html_template) |
|
|
| @app.route('/get_markers', methods=['GET']) |
| def get_markers(): |
| markers = get_all_markers() |
| return jsonify([{ |
| 'id': marker[0], |
| 'name': marker[1], |
| 'description': marker[2], |
| 'telegram_link': marker[3], |
| 'latitude': marker[4], |
| 'longitude': marker[5] |
| } for marker in markers]) |
|
|
| @app.route('/add_marker', methods=['POST']) |
| def add_marker(): |
| data = request.json |
| name = data['name'] |
| description = data['description'] |
| telegram_link = data['telegram_link'] |
| latitude, longitude = data['position'] |
| marker_id = add_marker_to_db(name, description, telegram_link, latitude, longitude) |
| return jsonify({ |
| 'id': marker_id, |
| 'name': name, |
| 'description': description, |
| 'telegram_link': telegram_link, |
| 'latitude': latitude, |
| 'longitude': longitude |
| }) |
|
|
| @app.route('/remove_marker/<int:marker_id>', methods=['DELETE']) |
| def remove_marker(marker_id): |
| remove_marker_from_db(marker_id) |
| return '', 204 |
|
|
| @app.route('/search_markers', methods=['GET']) |
| def search_markers(): |
| query = request.args.get('query', '') |
| conn = sqlite3.connect('markers.db') |
| cursor = conn.cursor() |
| cursor.execute('''SELECT id, name, description, telegram_link, latitude, longitude FROM markers |
| WHERE name LIKE ? OR description LIKE ?''', |
| (f'%{query}%', f'%{query}%')) |
| markers = cursor.fetchall() |
| conn.close() |
| return jsonify([{ |
| 'id': marker[0], |
| 'name': marker[1], |
| 'description': marker[2], |
| 'telegram_link': marker[3], |
| 'latitude': marker[4], |
| 'longitude': marker[5] |
| } for marker in markers]) |
|
|
| if __name__ == '__main__': |
| init_db() |
| app.run(debug=True, host='0.0.0.0', port=7860) |
|
|