diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b5eecd1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Используем официальный образ Python как базовый +FROM python:3.11-slim + +# Устанавливаем системные зависимости для работы с анимацией и SQLite +RUN apt-get update && apt-get install -y \ + libmagic1 \ + && rm -rf /var/lib/apt/lists/* + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файлы приложения в контейнер +COPY . /app + +# Устанавливаем необходимые Python библиотеки +RUN pip install --no-cache-dir -r requirements.txt + +# Открываем порты для работы приложения +EXPOSE 5000 + +# Запускаем приложение +CMD ["hypercorn", "main:app", "--bind", "0.0.0.0:5000"] diff --git a/assets/cross.png b/assets/cross.png deleted file mode 100644 index bfc369c..0000000 Binary files a/assets/cross.png and /dev/null differ diff --git a/assets/image.jpg b/assets/image.jpg deleted file mode 100644 index 6db4313..0000000 Binary files a/assets/image.jpg and /dev/null differ diff --git a/assets/search-icon.png b/assets/search-icon.png deleted file mode 100644 index 478f3bd..0000000 Binary files a/assets/search-icon.png and /dev/null differ diff --git a/assets/stars/0-star.png b/assets/stars/0-star.png deleted file mode 100644 index 8ff3976..0000000 Binary files a/assets/stars/0-star.png and /dev/null differ diff --git a/assets/stars/0-star_large.png b/assets/stars/0-star_large.png deleted file mode 100644 index e15a0f4..0000000 Binary files a/assets/stars/0-star_large.png and /dev/null differ diff --git a/assets/stars/1-star.png b/assets/stars/1-star.png deleted file mode 100644 index 09b27b4..0000000 Binary files a/assets/stars/1-star.png and /dev/null differ diff --git a/assets/stars/1-star_large.png b/assets/stars/1-star_large.png deleted file mode 100644 index 09a69f7..0000000 Binary files a/assets/stars/1-star_large.png and /dev/null differ diff --git a/assets/stars/2-star.png b/assets/stars/2-star.png deleted file mode 100644 index 90fe412..0000000 Binary files a/assets/stars/2-star.png and /dev/null differ diff --git a/assets/stars/2-star_large.png b/assets/stars/2-star_large.png deleted file mode 100644 index 40daf0f..0000000 Binary files a/assets/stars/2-star_large.png and /dev/null differ diff --git a/assets/stars/3-star.png b/assets/stars/3-star.png deleted file mode 100644 index afc2920..0000000 Binary files a/assets/stars/3-star.png and /dev/null differ diff --git a/assets/stars/3-star_large.png b/assets/stars/3-star_large.png deleted file mode 100644 index 41fb2c9..0000000 Binary files a/assets/stars/3-star_large.png and /dev/null differ diff --git a/assets/stars/4-star.png b/assets/stars/4-star.png deleted file mode 100644 index 69c76ed..0000000 Binary files a/assets/stars/4-star.png and /dev/null differ diff --git a/assets/stars/4-star_large.png b/assets/stars/4-star_large.png deleted file mode 100644 index fb1ca82..0000000 Binary files a/assets/stars/4-star_large.png and /dev/null differ diff --git a/assets/stars/5-star.png b/assets/stars/5-star.png deleted file mode 100644 index bf537c3..0000000 Binary files a/assets/stars/5-star.png and /dev/null differ diff --git a/assets/stars/5-star_large.png b/assets/stars/5-star_large.png deleted file mode 100644 index 927df9b..0000000 Binary files a/assets/stars/5-star_large.png and /dev/null differ diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..951a427 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,14 @@ +services: + web: + build: . # Путь к Dockerfile (в текущей директории) + ports: + - "80:5000" # Проброс портов + volumes: + - nas-share:/data + +volumes: + nas-share: + driver_opts: + type: cifs + o: "username=Shaman,password=" + device: "//192.168.31.3/share/public/complete/workshop" \ No newline at end of file diff --git a/frontend/assets/steam-120.ico b/frontend/assets/steam-120.ico new file mode 100644 index 0000000..b1ab654 Binary files /dev/null and b/frontend/assets/steam-120.ico differ diff --git a/frontend/assets/steam-32.ico b/frontend/assets/steam-32.ico new file mode 100644 index 0000000..5d0e158 Binary files /dev/null and b/frontend/assets/steam-32.ico differ diff --git a/frontend/main.css b/frontend/main.css index ea8dc5e..020c740 100644 --- a/frontend/main.css +++ b/frontend/main.css @@ -172,3 +172,76 @@ body { top: 210px; left: 660px; } + + +@media screen and (max-width: 768px) { + body { + flex-direction: column; + align-items: center; + padding: 0 10px; + } + + .main-container { + padding-top: 20px; + } + + .image-wrapper { + width: 100%; + flex-direction: column; + align-items: center; + padding: 10px; + } + + .image-container { + width: 100%; + height: auto; + padding: 0; + } + + .image-container img { + width: 100%; + height: auto; + } + + .details-container { + width: 100%; + margin-top: 15px; + margin-left: 0; + padding: 15px; + } + + .download-btn { + position: static; + margin-top: 15px; + width: 100%; + height: 40px; + font-size: 18px; + } + + .game-mode, + .tags, + .file-size, + .added-time { + position: static; + margin-top: 10px; + width: 100%; + text-align: left; + } + + .dynamic-data { + margin-left: 0; + font-size: 14px; + } + + .youtube-container { + position: static; + margin-top: 15px; + width: 100%; + height: auto; + } + + .youtube-container iframe { + width: 100%; + height: auto; + } +} diff --git a/frontend/main.html b/frontend/main.html index 8c51656..ed98fc0 100644 --- a/frontend/main.html +++ b/frontend/main.html @@ -4,10 +4,12 @@ - Workshop + workshop + +
diff --git a/frontend/workshop.css b/frontend/workshop.css index 016820c..bb0f02c 100644 --- a/frontend/workshop.css +++ b/frontend/workshop.css @@ -6,18 +6,64 @@ body { display: block; } + + +/* кнопка "Связаться" */ +.contact-button { + position: absolute; + top: 10px; + right: 50px; + font-size: 14px; + color: #417A9B; + text-decoration: none; + font-weight: bold; + background-color: transparent; + border: none; + cursor: pointer; +} + +.contact-button:hover { + text-decoration: underline; +} + + .top-bar { background-color: #171D25; width: 100%; height: 105px; display: flex; - justify-content: center; + justify-content: space-between; /* Элементы слева и справа */ align-items: center; position: fixed; top: 0; z-index: 1000; + padding-left: 20px; /* Отступ слева */ + padding-right: 20px; /* Отступ справа */ } +.left-text { + color: white; + font-family: Arial, sans-serif; + font-size: 14px; + margin-right: 15px; /* Отступ справа для текста */ +} + +.left-text p { + margin: 0; + padding: 0; +} + +.center-text { + color: white; + font-family: Arial, sans-serif; + font-size: 28px; + text-align: center; + flex-grow: 1; /* Элемент займет всю доступную ширину */ + margin-left: -500px; /* Это выравнивает текст по правому краю */ + margin-right: auto; /* Это выравнивает текст по левому краю */ +} + + .main-container { display: flex; justify-content: center; @@ -485,3 +531,136 @@ body { cursor: pointer; accent-color: #63AFCD; } + + +@media screen and (max-width: 768px) { + body { + font-size: 14px; + } + + .top-bar { + height: 80px; + } + + .main-container { + flex-direction: column; + align-items: center; + margin-top: 80px; + padding: 0 10px; + } + + .cards-container { + grid-template-columns: 1fr; + grid-gap: 20px; + width: 100%; + justify-items: center; + } + + .card { + width: 90%; /* Карточки занимают почти весь экран */ + max-width: 300px; /* Ограничение по ширине */ + } + + .right-rectangle { + width: 100%; + height: auto; + margin-left: 0; + } + + .game-modes { + position: static; + flex-direction: row; + justify-content: center; + flex-wrap: wrap; + gap: 10px; + } + + @media screen and (max-width: 768px) { + .modal { + width: 90%; + height: auto; + padding: 15px; + max-width: 500px; /* Ограничиваем максимальную ширину для больших мобильных устройств */ + } + + .modal-content { + padding: 15px; + } + + .close-btn { + top: -30px; + right: -10px; + font-size: 25px; + } + + .modal-content h2 { + margin-left: 15px; + font-size: 18px; + } + + .modal-rectangle { + width: 100%; + height: 45px; + padding: 0 15px; + } + + .modal-rectangle .text-left, + .modal-rectangle .text-center { + font-size: 14px; + padding: 5px 0; + } + + .date-input { + width: 100%; + height: 35px; + font-size: 16px; + margin-top: 10px; + } + + .cancel-button, + .ok-button { + position: static; + margin-top: 20px; + width: 100%; + height: 40px; + font-size: 16px; + } + + .cancel-button { + margin-bottom: 10px; + } + + .ok-button { + margin-bottom: 10px; + } +} + + + .pagination { + flex-wrap: wrap; + } + + .filter-stars { + width: 90%; + position: static; + margin: 10px 0; + } + + .search-container { + margin-top: 20px; + } + + .search-input { + width: 90%; + } + + .sort-button-container { + flex-wrap: wrap; + justify-content: center; + } + + .sort-button { + width: auto; + margin: 5px; + } +} diff --git a/frontend/workshop.html b/frontend/workshop.html index bb3dce5..3c4d831 100644 --- a/frontend/workshop.html +++ b/frontend/workshop.html @@ -4,15 +4,26 @@ - Workshop + workshop + -
-

Добро пожаловать в Workshop

+
+
+

Сделал: ©️𝙎𝙃∆𝙈∆𝙉©️

+

Неофициальный сайт
с картами для CS:GO
из мастерской Steam

+

Добро пожаловать в Workshop

+ Связаться +
+ + + + +
diff --git a/main.py b/main.py index f994ffc..389cbca 100644 --- a/main.py +++ b/main.py @@ -5,12 +5,13 @@ import aiosqlite from quart import Quart, render_template, request, send_from_directory, Response from datetime import datetime from babel.dates import format_datetime -import locale -locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8') + + app = Quart(__name__, template_folder='frontend', static_folder='frontend') DB_PATH = 'maps.db' +DATA = "/data" GAME_MODES = { "Classic": "Классический", @@ -45,32 +46,33 @@ async def get_maps(page=1, per_page=30): return maps def get_image_path(filepath): - image_path = os.path.join('J:/public/complete/workshop', filepath) + image_path = os.path.join(DATA, filepath) if not os.path.exists(image_path): - return "http://127.0.0.1:5000/images/image.jpg" - return f"http://127.0.0.1:5000/images/{filepath.split('/')[0]}/{filepath.split('/')[1]}/{filepath.split('/')[1]}.jpg" + return "/images/image.jpg" + return f"/images/{filepath.split('/')[0]}/{filepath.split('/')[1]}/{filepath.split('/')[1]}.jpg" def get_star_image(stars): if stars is None or stars == 0: - return "http://127.0.0.1:5000/stars/0-star.png" - return f"http://127.0.0.1:5000/stars/{stars}-star.png" + return "/stars/0-star.png" + return f"/stars/{stars}-star.png" @app.route('/images/') async def serve_image(filename): - image_path = os.path.join('J:/public/complete/workshop', filename) + image_path = os.path.join(DATA, filename) if os.path.exists(image_path): - return await send_from_directory('J:/public/complete/workshop', filename) + return await send_from_directory(DATA, filename) else: - default_image_path = os.path.join('J:/public/complete/workshop', 'image.jpg') + default_image_path = os.path.join(DATA, 'image.jpg') if os.path.exists(default_image_path): - return await send_from_directory('J:/public/complete/workshop', 'image.jpg') + return await send_from_directory(DATA, 'image.jpg') return "Default image not found", 404 @app.route('/stars/') async def serve_star_image(filename): - star_path = os.path.join('J:/public/complete/workshop/stars', filename) + stars = os.path.join(DATA, 'stars') + star_path = os.path.join(stars, filename) if os.path.exists(star_path): - return await send_from_directory('J:/public/complete/workshop/stars', filename) + return await send_from_directory(stars, filename) else: return "Star image not found", 404 @@ -91,10 +93,10 @@ async def download_bsp(): if not image_path: return "No image path provided", 400 - image_folder = os.path.dirname(image_path.replace("http://127.0.0.1:5000/images/", "")) + image_folder = os.path.dirname(image_path.replace("/images/", "")) bsp_filename = None - for file in os.listdir(os.path.join('J:/public/complete/workshop', image_folder)): + for file in os.listdir(os.path.join(DATA, image_folder)): if file.endswith('.bsp'): bsp_filename = file break @@ -102,7 +104,7 @@ async def download_bsp(): if not bsp_filename: return "No .bsp file found in the same directory", 404 - file_path = os.path.join('J:/public/complete/workshop', image_folder, bsp_filename) + file_path = os.path.join(DATA, image_folder, bsp_filename) SPEED_LIMIT = 40 * 1024 * 1024 // 8 @@ -159,7 +161,7 @@ async def main_page(): tags = 'Не найдено' if file_path: - file_size = os.path.getsize(os.path.join('J:/public/complete/workshop', file_path)) + file_size = os.path.getsize(os.path.join(DATA, file_path)) file_size_mb = file_size / (1024 * 1024) file_size_display = f"{file_size_mb:.2f} MB" else: @@ -282,4 +284,8 @@ async def get_maps_filtered(page=1, selected_game_modes=None, start_date=None, e return maps if __name__ == '__main__': - app.run(host='127.0.0.1', port=5000) + import hypercorn.asyncio + from hypercorn.config import Config + config = Config() + config.bind = ["0.0.0.0:5000"] + hypercorn.asyncio.run(app, config) diff --git a/maps.db-shm b/maps.db-shm deleted file mode 100644 index fe9ac28..0000000 Binary files a/maps.db-shm and /dev/null differ diff --git a/maps.db-wal b/maps.db-wal deleted file mode 100644 index e69de29..0000000 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fb00db7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +aiosqlite~=0.20.0 +Hypercorn~=0.17.3 +Quart~=0.19.6 +babel~=2.16.0 \ No newline at end of file