feat(easel): add base template

This commit is contained in:
2026-04-12 17:37:36 +03:00
parent f303d0e1f4
commit ad8144df37
15 changed files with 433 additions and 442 deletions

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View File

@@ -1,19 +1,29 @@
{ {
"folders": [ "folders": [
{ {
"path": "." "path": ".",
} },
], ],
"settings": { "settings": {
"python.testing.pytestArgs": ["tests", "-s"], "python.testing.pytestArgs": ["tests", "-s"],
"python.testing.unittestEnabled": false, "python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true, "python.testing.pytestEnabled": true,
"python-envs.pythonProjects": [
{
"path": ".",
"envManager": "ms-python.python:poetry",
"packageManager": "ms-python.python:poetry",
},
],
"files.associations": {
"*.html": "jinja-html",
},
"files.exclude": { "files.exclude": {
"**/__pycache__": true "**/__pycache__": true,
}, },
"terminal.integrated.env.linux": { "terminal.integrated.env.linux": {
"PYTHONPATH": "${workspaceFolder}" "PYTHONPATH": "${workspaceFolder}",
} },
}, },
"launch": { "launch": {
"version": "0.2.1", "version": "0.2.1",
@@ -27,9 +37,9 @@
"gallery.main:app", "gallery.main:app",
"--reload", "--reload",
"--log-config", "--log-config",
"gallery/logging.yaml" "gallery/logging.yaml",
] ],
} },
] ],
} },
} }

View File

@@ -29,7 +29,7 @@ def mount(app: FastAPI):
async def get_section_list(request: Request): async def get_section_list(request: Request):
return templates.TemplateResponse( return templates.TemplateResponse(
request=request, request=request,
name="index.html", name="root_index.html",
context={ context={
"version": __version__, "version": __version__,
"sections": SECTIONS, "sections": SECTIONS,

View File

@@ -47,25 +47,32 @@ app
*/ */
.app-container { .app-container {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
flex-wrap: nowrap; flex-wrap: nowrap;
align-items: center; align-items: stretch;
}
.app-menu {
display: flex;
flex-direction: column;
margin: 0.5rem;
}
.app-content {
display: flex;
flex: 1;
flex-direction: column;
} }
.app-header { .app-header {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} gap: 0.5rem;
.app-title {
display: flex;
justify-content: center; justify-content: center;
flex-grow: 1;
} }
.app-link-home > * { .app-link-home > * {
margin-left: 2rem;
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
background-image: url("/static/common/gallery.png"); background-image: url("/static/common/gallery.png");
@@ -81,6 +88,7 @@ app
ul.app-list { ul.app-list {
list-style: none; list-style: none;
padding-left: 0;
} }
ul.app-list > li { ul.app-list > li {

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet"
href="/static/common/style.css?v={{version}}">
<link rel="icon"
href="/static/common/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
</head>
<body class="app-container">
<div class="app-menu">
<a class="app-link-home"
href="/">
<div></div>
</a>
</div>
<div class="app-content">
<h3 class="app-header">
{% block header %}{% endblock %}</span>
</h3>
{% block content %}{% endblock %}
<div class="app-footer">
{% block footer %}{% endblock %}
</div>
</div>
</body>
</html>

View File

@@ -1,41 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>Информация</title>
<link rel="stylesheet"
href="/static/common/style.css?v={{version}}">
<link rel="icon"
href="/static/common/favicon.ico?v={{version}}"
type="image/x-icon">
</head>
<body class="app-container">
<h3 class="app-header">
<a class="app-link-home"
href="/">
<div></div>
</a>
<div class="app-title">
<span>Информация</span>
</div>
</h3>
<ul class="app-list">
{% for section in sections %}
<li>
<a href="{{section.link}}">
<span class="icon"
style="background-image: url(/static/{{section.link}}/{{section.link}}.png);"></span>
<span>{{section.title}}</span>
</a>
</li>
{% endfor %}
</ul>
</body>
</html>

View File

@@ -0,0 +1,21 @@
{% extends "base.html" %}
{% block title %}Информация{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block header %}Информация{% endblock %}
{% block content %}
<ul class="app-list">
{% for section in sections %}
<li>
<a href="{{section.link}}">
<span class="icon"
style="background-image: url(/static/{{section.link}}/{{section.link}}.png);"></span>
<span>{{section.title}}</span>
</a>
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@@ -17,7 +17,12 @@ from .filters import timedelta_format
def mount(app: FastAPI): def mount(app: FastAPI):
base_dir = Path(__file__).parent base_dir = Path(__file__).parent
app.mount("/static/schedule", StaticFiles(directory=base_dir / "static")) app.mount("/static/schedule", StaticFiles(directory=base_dir / "static"))
templates = Jinja2Templates(directory=base_dir / "templates") templates = Jinja2Templates(
directory=[
base_dir.parent / "common/templates",
base_dir / "templates",
]
)
templates.env.filters["timedelta_format"] = timedelta_format templates.env.filters["timedelta_format"] = timedelta_format
@app.get("/schedule", response_class=HTMLResponse) @app.get("/schedule", response_class=HTMLResponse)

View File

@@ -1,57 +1,43 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}
Программа | {{response.channel.name}} | {{response.date.strftime('%a, %d %B %Y')}}
{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
<head> {% block header %}
<meta charset="UTF-8"> <a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
<meta name="viewport" href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
content="width=device-width, initial-scale=1.0"> <a class="button"
<meta http-equiv="X-UA-Compatible" href="../..">⬆️</a>
content="ie=edge"> <span>{{response.channel.name}} | {{response.date.strftime('%a, %d %B %Y')}}</span>
<title>Программа | {{response.channel.name}} | {{response.date.strftime('%a, %d %B %Y')}}</title> <a class="button"
<link rel="stylesheet" href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
href="/static/common/style.css?v={{version}}"> {% endblock %}
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
</head>
<body class="app-container"> {% block content %}
<h3 class="app-header"> <table>
<a class="app-link-home" <thead>
href="/"> <tr>
<div></div> <td></td>
</a> <td></td>
<div class="app-title"> <td></td>
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}" </tr>
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a> </thead>
<a class="button" <tbody>
href="../..">⬆️</a> {% for value in response.values %}
<span>{{response.channel.name}} | {{response.date.strftime('%a, %d %B %Y')}}</span> <tr class="{{'live' if value.live else ''}}">
<a class="button" <td>{{value.start.strftime('%H:%M')}}</td>
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a> <td>{{(value.end - value.start) | timedelta_format}}</td>
</div> <td>{{value.label}}</td>
</h3> </tr>
{% endfor %}
<table> </tbody>
<thead> </table>
<tr> {% endblock %}
<td></td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
{% for value in response.values %}
<tr class="{{'live' if value.live else ''}}">
<td>{{value.start.strftime('%H:%M')}}</td>
<td>{{(value.end - value.start) | timedelta_format}}</td>
<td>{{value.label}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@@ -1,38 +1,21 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}ТВ{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
<head> {% block header %}Телепрограмма{% endblock %}
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>ТВ</title>
<link rel="stylesheet"
href="/static/common/style.css?v={{version}}">
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
</head>
<body class="app-container"> {% block content %}
<h3 class="app-header"> <ul class="app-list">
<a class="app-link-home" <li style="margin-bottom: 0.25rem; font-weight: bold;"><a href="schedule/tag/today">Все</a></li>
href="/"> {% for channel in channels %}
<div></div> <li><a href="schedule/{{channel.id}}">{{channel.name}}</a></li>
</a> {% endfor %}
<div class="app-title"> </ul>
<span>Телепрограмма</span> {% endblock %}
</div>
</h3>
<ul class="app-list">
<li style="margin-bottom: 0.25rem; font-weight: bold;"><a href="schedule/tag/today">Все</a></li>
{% for channel in channels %}
<li><a href="schedule/{{channel.id}}">{{channel.name}}</a></li>
{% endfor %}
</ul>
</body>
</html>

View File

@@ -1,69 +1,57 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}
{{'Прямые трансляции' if live else 'Программа'}} | {{response.date.strftime('%a, %d %B %Y')}}
{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
<head> {% block header %}
<meta charset="UTF-8"> <a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
<meta name="viewport" href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
content="width=device-width, initial-scale=1.0"> <a class="button"
<meta http-equiv="X-UA-Compatible" href="..">⬆️</a>
content="ie=edge"> <span>{{'Прямые трансляции' if live else 'Программа'}} | {{response.date.strftime('%a, %d %B %Y')}}</span>
<title>ТВ</title> <a class="button"
<link rel="stylesheet" href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
href="/static/common/style.css?v={{version}}"> {% endblock %}
<link rel="stylesheet"
href="/static/schedule/style.css?v={{version}}">
<link rel="icon"
href="/static/schedule/favicon.ico?v={{version}}"
type="image/x-icon">
</head>
<body class="app-container"> {% block content %}
<h3 class="app-header"> <div>
<a class="app-link-home" <table class="{{'live' if live else ''}}">
href="/"> <thead>
<div></div> <tr>
</a> <td></td>
<div class="app-title"> <td></td>
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}" <td></td>
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a> </tr>
<a class="button" </thead>
href="..">⬆️</a> <tbody>
<span>{{'Прямые трансляции' if live else 'Программа'}} | {{response.date.strftime('%a, %d %B %Y')}}</span> {% for response in responses %}
<a class="button" {% set values = (response.values|selectattr('live') if live else response.values)|list %}
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a> {% if values|length > 0 %}
</div> <tr>
</h3> <td colspan="3">
<div class="title">{{response.channel.name}}</div>
<table class="{{'live' if live else ''}}"> </td>
<thead> <td></td>
<tr> <td></td>
<td></td> </tr>
<td></td> {% for value in values %}
<td></td> <tr class="{{'live' if not live and value.live else ''}}">
</tr> <td>{{value.start.strftime('%H:%M')}}</td>
</thead> <td>{{(value.end - value.start) | timedelta_format}}</td>
<tbody> <td>{{value.label}}</td>
{% for response in responses %} </tr>
{% set values = (response.values|selectattr('live') if live else response.values)|list %} {% endfor %}
{% if values|length > 0 %} {% endif %}
<tr> {% endfor %}
<td colspan="3"> </tbody>
<div class="title">{{response.channel.name}}</div> </table>
</td> </div>
<td></td> {% endblock %}
<td></td>
</tr>
{% for value in values %}
<tr class="{{'live' if not live and value.live else ''}}">
<td>{{value.start.strftime('%H:%M')}}</td>
<td>{{(value.end - value.start) | timedelta_format}}</td>
<td>{{value.label}}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@@ -19,7 +19,12 @@ from .filters import cloudness_icon, wind_direction_icon
def mount(app: FastAPI): def mount(app: FastAPI):
base_dir = Path(__file__).parent base_dir = Path(__file__).parent
app.mount("/static/weather", StaticFiles(directory=base_dir / "static")) app.mount("/static/weather", StaticFiles(directory=base_dir / "static"))
templates = Jinja2Templates(directory=base_dir / "templates") templates = Jinja2Templates(
directory=[
base_dir.parent / "common/templates",
base_dir / "templates",
]
)
templates.env.filters["wind_direction_icon"] = wind_direction_icon templates.env.filters["wind_direction_icon"] = wind_direction_icon
templates.env.filters["cloudness_icon"] = cloudness_icon templates.env.filters["cloudness_icon"] = cloudness_icon

View File

@@ -1,37 +1,20 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}Погода{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet"
href="/static/weather/style.css?v={{version}}">
<link rel="icon"
href="/static/weather/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
<head> {% block header %}Погода{% endblock %}
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible"
content="ie=edge">
<title>Погода</title>
<link rel="stylesheet"
href="/static/common/style.css?v={{version}}">
<link rel="stylesheet"
href="/static/weather/style.css?v={{version}}">
<link rel="icon"
href="/static/weather/favicon.ico?v={{version}}"
type="image/x-icon">
</head>
<body class="app-container"> {% block content %}
<h3 class="app-header"> <ul class="app-list">
<a class="app-link-home" {% for location in locations %}
href="/"> <li><a href="weather/{{location.id}}">{{location.name}}</a></li>
<div></div> {% endfor %}
</a> </ul>
<div class="app-title"> {% endblock %}
<span>Погода</span>
</div>
</h3>
<ul class="app-list">
{% for location in locations %}
<li><a href="weather/{{location.id}}">{{location.name}}</a></li>
{% endfor %}
</ul>
</body>
</html>

View File

@@ -1,184 +1,171 @@
<!DOCTYPE html> {% extends "base.html" %}
<html lang="en"> {% block title %}Погода | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet"
href="/static/weather/style.css?v={{version}}">
<link rel="icon"
href="/static/weather/favicon.ico?v={{version}}"
type="image/x-icon">
{% endblock %}
<head> {% block header %}
<meta charset="UTF-8"> {% if response.period == 'day' %}
<meta name="viewport" <a class="button {{'disabled' if response.date == datetime.date.today() else ''}}"
content="width=device-width, initial-scale=1.0"> href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a>
<meta http-equiv="X-UA-Compatible" <a class="button"
content="ie=edge"> href="../tag/days-10">⬆️</a>
<title>Погода | {{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</title> <span>{{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</span>
<link rel="stylesheet" <a class="button"
href="/static/common/style.css?v={{version}}"> href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a>
<link rel="stylesheet" {% endif %}
href="/static/weather/style.css?v={{version}}"> {% if response.period == 'days' %}
<link rel="icon" <span>{{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</span>
href="/static/weather/favicon.ico?v={{version}}" {% endif %}
type="image/x-icon"> {% endblock %}
</head>
<body class="app-container"> {% block content %}
<h3 class="app-header"> <div>
<a class="app-link-home" <table style="margin: auto;">
href="/"> <tbody>
<div></div> <!-- date -->
</a> <tr>
<div class="app-title"> {% for value in response.values %}
{% if response.period == 'day' %} {% if response.period == 'day' %}
<a class="button {{'disabled' if response.date == datetime.date.today() else ''}}" <td
href="../tag/{{tag_util.create_tag('day', response.date, -1)}}">⬅️</a> class="date {{'now' if value.date < datetime.datetime.now() and value.date + datetime.timedelta(hours=3) > datetime.datetime.now() else ''}}">
<a class="button" <span class="value">{{value.date.strftime('%H:%M')}}</span>
href="../tag/days-10">⬆️</a> </td>
<span>{{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</span> {% endif %}
<a class="button" {% if response.period == 'days' %}
href="../tag/{{tag_util.create_tag('day', response.date, 1)}}">➡️</a> <td class="date {{'now' if value.date.date() == datetime.date.today() else ''}}">
{% endif %} <span class="value">
{% if response.period == 'days' %} <a href="../tag/{{tag_util.create_tag('day', value.date.date())}}">
<span>{{response.location}} | {{response.date.strftime('%a, %d %B %Y')}}</span> {{value.date.strftime('%a %d')}}
{% endif %} </a>
</div> </span>
</h3> </td>
<table> {% endif %}
<tbody> {% endfor %}
<!-- date --> </tr>
<tr> <!-- cloudness -->
{% for value in response.values %} <tr>
{% if response.period == 'day' %} <td colspan="{{response.values | length}}"
<td class="header">
class="date {{'now' if value.date < datetime.datetime.now() and value.date + datetime.timedelta(hours=3) > datetime.datetime.now() else ''}}"> Облачность
<span class="value">{{value.date.strftime('%H:%M')}}</span> </td>
</td> </tr>
{% endif %} <tr>
{% if response.period == 'days' %} {% for value in response.values %}
<td class="date {{'now' if value.date.date() == datetime.date.today() else ''}}"> <td class="cloudness">
<span class="value"> {% for icon in value.sky | cloudness_icon %}
<a href="../tag/{{tag_util.create_tag('day', value.date.date())}}"> <div class="icon">{{icon}}</div>
{{value.date.strftime('%a %d')}} {% endfor %}
</a> </td>
</span> {% endfor %}
</td> </tr>
{% endif %} <!-- temperature -->
{% endfor %} <tr>
</tr> <td colspan="{{response.values | length}}"
<!-- cloudness --> class="header">
<tr> Температура, °C
<td colspan="{{response.values | length}}" </td>
class="header"> </tr>
Облачность <tr>
</td> {% for value in response.values %}
</tr> <td class="temperature">
<tr> {% for temperature in value.temperature %}
{% for value in response.values %} <div class="value {{'positive' if temperature > 0 else 'negative'}}"
<td class="cloudness"> style="background-color: rgba(255, 128, 128, {{(temperature - 10) * 0.015}});">
{% for icon in value.sky | cloudness_icon %} {{temperature}}
<div class="icon">{{icon}}</div> </div>
{% endfor %} {% endfor %}
</td> </td>
{% endfor %} {% endfor %}
</tr> </tr>
<!-- temperature --> <!-- wind_direction -->
<tr> <tr>
<td colspan="{{response.values | length}}" <td colspan="{{response.values | length}}"
class="header"> class="header">
Температура, °C Направление ветра
</td> </td>
</tr> </tr>
<tr> <tr>
{% for value in response.values %} {% for value in response.values %}
<td class="temperature"> <td class="wind">
{% for temperature in value.temperature %} <span class="icon">{{value.wind_direction | wind_direction_icon}}</span>
<div class="value {{'positive' if temperature > 0 else 'negative'}}" </td>
style="background-color: rgba(255, 128, 128, {{(temperature - 10) * 0.015}});"> {% endfor %}
{{temperature}} </tr>
</div> <!-- wind_speed -->
{% endfor %} <tr>
</td> <td colspan="{{response.values | length}}"
{% endfor %} class="header">
</tr> Скорость ветра, м/с
<!-- wind_direction --> </td>
<tr> </tr>
<td colspan="{{response.values | length}}" <tr>
class="header"> {% for value in response.values %}
Направление ветра <td class="wind"
</td> style="background-color: rgba(128, 128, 128, {{value.wind_speed * 0.05}});">
</tr> <span class="speed">{{value.wind_speed}}</span>
<tr> {% if value.wind_gust != value.wind_speed %}
{% for value in response.values %} <span class="gust">
<td class="wind"> ({{value.wind_gust}})
<span class="icon">{{value.wind_direction | wind_direction_icon}}</span> </span>
</td> {% endif %}
{% endfor %} </td>
</tr> {% endfor %}
<!-- wind_speed --> </tr>
<tr> <!-- precipitation -->
<td colspan="{{response.values | length}}" <tr>
class="header"> <td colspan="{{response.values | length}}"
Скорость ветра, м/с class="header">
</td> Осадки, мм
</tr> </td>
<tr> </tr>
{% for value in response.values %} <tr>
<td class="wind" {% for value in response.values %}
style="background-color: rgba(128, 128, 128, {{value.wind_speed * 0.05}});"> <td class="precipitation"
<span class="speed">{{value.wind_speed}}</span> style="background-color: rgba(0, 128, 255, {{value.precipitation * 0.1}});">
{% if value.wind_gust != value.wind_speed %} <span class="value">{{value.precipitation or ''}}</span>
<span class="gust"> </td>
({{value.wind_gust}}) {% endfor %}
</span> </tr>
{% endif %} <!-- pressure -->
</td> <tr>
{% endfor %} <td colspan="{{response.values | length}}"
</tr> class="header">
<!-- precipitation --> Давление, мм рт. ст.
<tr> </td>
<td colspan="{{response.values | length}}" </tr>
class="header"> <tr>
Осадки, мм {% for value in response.values %}
</td> <td class="pressure">
</tr> {% for pressure in value.pressure %}
<tr> <div class="value"
{% for value in response.values %} style="background-color: rgba(128, 0, 255, {{(pressure - 720) * 0.008}});">
<td class="precipitation" {{pressure}}</div>
style="background-color: rgba(0, 128, 255, {{value.precipitation * 0.1}});"> {% endfor %}
<span class="value">{{value.precipitation or ''}}</span> </td>
</td> {% endfor %}
{% endfor %} </tr>
</tr> <!-- humidity -->
<!-- pressure --> <tr>
<tr> <td colspan="{{response.values | length}}"
<td colspan="{{response.values | length}}" class="header">
class="header"> Влажность, %
Давление, мм рт. ст. </td>
</td> </tr>
</tr> <tr>
<tr> {% for value in response.values %}
{% for value in response.values %} <td class="humidity"
<td class="pressure"> style="background-color: rgba(128, 128, 255, {{value.humidity * 0.005}});">
{% for pressure in value.pressure %} <span class="value">{{value.humidity}}</span>
<div class="value" </td>
style="background-color: rgba(128, 0, 255, {{(pressure - 720) * 0.008}});"> {% endfor %}
{{pressure}}</div> </tr>
{% endfor %} </tbody>
</td> </table>
{% endfor %} </div>
</tr> {% endblock %}
<!-- humidity -->
<tr>
<td colspan="{{response.values | length}}"
class="header">
Влажность, %
</td>
</tr>
<tr>
{% for value in response.values %}
<td class="humidity"
style="background-color: rgba(128, 128, 255, {{value.humidity * 0.005}});">
<span class="value">{{value.humidity}}</span>
</td>
{% endfor %}
</tr>
</tbody>
</table>
</body>
</html>

View File

@@ -29,19 +29,25 @@ class MatchTvApi(ScheduleApi):
async def get_channel_schedule( async def get_channel_schedule(
self, channel_id: str, date: datetime.date self, channel_id: str, date: datetime.date
) -> Schedule: ) -> Schedule:
endpoint = f"channel/{channel_id}/tvguide?date={date:%d-%m-%Y}" endpoint = f"tvguide/{channel_id}?date={date:%Y%m%d}"
data = await self.SOURCE.request(endpoint) data = await self.SOURCE.request(endpoint)
soup = BeautifulSoup(data, features="html.parser") soup = BeautifulSoup(data, features="html.parser")
values = [] values = []
channel_name = soup.select_one(".caption__heading").text.split("|")[0].strip() channel_name = (
soup.select_one(".p-tv-guide-header__title")
.text.replace("Телепрограмма ", "")
.strip()
)
current_day = datetime.datetime.combine( current_day = datetime.datetime.combine(
date.today(), datetime.datetime.min.time() date.today(), datetime.datetime.min.time()
) )
end = current_day + datetime.timedelta(days=1, hours=6) end = current_day + datetime.timedelta(days=1, hours=6)
prev_value: ScheduleValue | None = None prev_value: ScheduleValue | None = None
for item in soup.select(".teleprogram-schedule .teleprogram-schedule__item"): for item in soup.select(
title = item.select_one(".teleprogram-item__title").text.strip() ".p-tv-guide-schedule-channel-carcass__transmissions .p-tv-guide-schedule-channel-transmission"
time_str = item.select_one(".teleprogram-item__time").text.strip() ):
title = item.select_one(".p-tv-guide-schedule-channel-transmission__title").text.strip()
time_str = item.select_one(".p-tv-guide-schedule-channel-transmission__time-block").text.strip()
hours, minutes = map(int, time_str.split(":")) hours, minutes = map(int, time_str.split(":"))
item_date = current_day.replace(hour=hours, minute=minutes) item_date = current_day.replace(hour=hours, minute=minutes)
if prev_value is not None and item_date.hour < prev_value.start.hour: if prev_value is not None and item_date.hour < prev_value.start.hour: