fix
This commit is contained in:
parent
a21e6f47f8
commit
60aa58844c
@ -28,7 +28,7 @@ REFRESH_TOKEN_EXPIRE_DAYS = 170
|
|||||||
TOKEN_TTL_DAYS = 7
|
TOKEN_TTL_DAYS = 7
|
||||||
ACCESS_COOKIE = "access_token"
|
ACCESS_COOKIE = "access_token"
|
||||||
REFRESH_COOKIE = "refresh_token"
|
REFRESH_COOKIE = "refresh_token"
|
||||||
RABBITMQ_HOST = "rabbitmq-0.rabbitmq.kultmost.svc.cluster.local" if PROD else "rabbit.spiritofweb.ru:31023"
|
RABBITMQ_HOST = "rabbit.spiritofweb.ru:31023"
|
||||||
EMAIL_SUBJECT = 'Культмост'
|
EMAIL_SUBJECT = 'Культмост'
|
||||||
PROTECTED_FIELDS_USER = {"_id", "img", 'original_img', "hashed_password", "password", "roles"}
|
PROTECTED_FIELDS_USER = {"_id", "img", 'original_img', "hashed_password", "password", "roles"}
|
||||||
VK_CLIENT_ID = os.getenv("VK_CLIENT_ID")
|
VK_CLIENT_ID = os.getenv("VK_CLIENT_ID")
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# ignore\n",
|
"#ignore\n",
|
||||||
"import os\n",
|
"import os\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def load_env(file_path):\n",
|
"def load_env(file_path):\n",
|
||||||
|
|||||||
@ -1,3 +1,35 @@
|
|||||||
|
#ignore
|
||||||
|
import os
|
||||||
|
|
||||||
|
def load_env(file_path):
|
||||||
|
"""Загружает переменные окружения из файла .env с поддержкой булевых значений."""
|
||||||
|
with open(file_path) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
key, value = line.split('=', 1)
|
||||||
|
key = key.strip()
|
||||||
|
value = value.strip('"\' ')
|
||||||
|
# Преобразование строковых значений в булевые
|
||||||
|
if value.lower() in ['true', '1', 'yes']:
|
||||||
|
value = True
|
||||||
|
elif value.lower() in ['false', '0', 'no']:
|
||||||
|
value = False
|
||||||
|
|
||||||
|
# Проверка, что ключ не пустой
|
||||||
|
if key:
|
||||||
|
os.environ[key] = str(value) # Храним как строку
|
||||||
|
except ValueError:
|
||||||
|
print(f"Ошибка: неверный формат в строке '{line}'")
|
||||||
|
|
||||||
|
try:
|
||||||
|
load_env('env')
|
||||||
|
except:
|
||||||
|
load_env('env_example')
|
||||||
|
|
||||||
import smtplib
|
import smtplib
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|||||||
17
main.ipynb
17
main.ipynb
@ -2701,8 +2701,9 @@
|
|||||||
" user: Dict = Security(get_current_user, scopes=[\"create:super_items\"])\n",
|
" user: Dict = Security(get_current_user, scopes=[\"create:super_items\"])\n",
|
||||||
"): \n",
|
"): \n",
|
||||||
" competition = await competitions_col.find_one({'_id': ObjectId(competition_id)})\n",
|
" competition = await competitions_col.find_one({'_id': ObjectId(competition_id)})\n",
|
||||||
|
" data = json.dumps(competition, cls=MongoJSONEncoder, ensure_ascii=False)\n",
|
||||||
" return templates.TemplateResponse(\n",
|
" return templates.TemplateResponse(\n",
|
||||||
" request=request, name=\"form/competition_edit.html\", context={\"competition\": competition, \"user\": user}\n",
|
" request=request, name=\"form/competition_edit.html\", context={\"competition\": str(data), \"user\": user}\n",
|
||||||
" )\n"
|
" )\n"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -2815,17 +2816,6 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"import json\n",
|
|
||||||
"from datetime import datetime, date\n",
|
|
||||||
"from bson import ObjectId\n",
|
|
||||||
"\n",
|
|
||||||
"class MongoJSONEncoder(json.JSONEncoder):\n",
|
|
||||||
" def default(self, o):\n",
|
|
||||||
" if isinstance(o, ObjectId):\n",
|
|
||||||
" return str(o)\n",
|
|
||||||
" if isinstance(o, (datetime, date)):\n",
|
|
||||||
" return o.isoformat()\n",
|
|
||||||
" return super().default(o)\n",
|
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
"@app.get(\"/form/exhibition/{exhibition_id}\", response_class=HTMLResponse)\n",
|
"@app.get(\"/form/exhibition/{exhibition_id}\", response_class=HTMLResponse)\n",
|
||||||
@ -2835,8 +2825,7 @@
|
|||||||
" user: Dict = Security(get_current_user)\n",
|
" user: Dict = Security(get_current_user)\n",
|
||||||
"):\n",
|
"):\n",
|
||||||
" exhibition = await exhibition_collection.find_one({'_id': ObjectId(exhibition_id)},{'posts':0,'vk':0,'tg':0,'fb':0,'inst':0,'max':0})\n",
|
" exhibition = await exhibition_collection.find_one({'_id': ObjectId(exhibition_id)},{'posts':0,'vk':0,'tg':0,'fb':0,'inst':0,'max':0})\n",
|
||||||
" data= json.dumps(exhibition, cls=MongoJSONEncoder, ensure_ascii=False)\n",
|
" data = json.dumps(exhibition, cls=MongoJSONEncoder, ensure_ascii=False)\n",
|
||||||
" print(data)\n",
|
|
||||||
" return templates.TemplateResponse(\n",
|
" return templates.TemplateResponse(\n",
|
||||||
" request=request, name=\"form/exhibition_edit.html\", context={\"id\": 1, \"user\": user, \"exhibition\": str(data)}\n",
|
" request=request, name=\"form/exhibition_edit.html\", context={\"id\": 1, \"user\": user, \"exhibition\": str(data)}\n",
|
||||||
" )"
|
" )"
|
||||||
|
|||||||
17
main.py
17
main.py
@ -2028,8 +2028,9 @@ async def form_(
|
|||||||
user: Dict = Security(get_current_user, scopes=["create:super_items"])
|
user: Dict = Security(get_current_user, scopes=["create:super_items"])
|
||||||
):
|
):
|
||||||
competition = await competitions_col.find_one({'_id': ObjectId(competition_id)})
|
competition = await competitions_col.find_one({'_id': ObjectId(competition_id)})
|
||||||
|
data = json.dumps(competition, cls=MongoJSONEncoder, ensure_ascii=False)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
request=request, name="form/competition_edit.html", context={"competition": competition, "user": user}
|
request=request, name="form/competition_edit.html", context={"competition": str(data), "user": user}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -2104,17 +2105,6 @@ async def form_exhibition(
|
|||||||
request=request, name="form/exhibition.html", context={"id": 1, "user": user}
|
request=request, name="form/exhibition.html", context={"id": 1, "user": user}
|
||||||
)
|
)
|
||||||
|
|
||||||
import json
|
|
||||||
from datetime import datetime, date
|
|
||||||
from bson import ObjectId
|
|
||||||
|
|
||||||
class MongoJSONEncoder(json.JSONEncoder):
|
|
||||||
def default(self, o):
|
|
||||||
if isinstance(o, ObjectId):
|
|
||||||
return str(o)
|
|
||||||
if isinstance(o, (datetime, date)):
|
|
||||||
return o.isoformat()
|
|
||||||
return super().default(o)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/form/exhibition/{exhibition_id}", response_class=HTMLResponse)
|
@app.get("/form/exhibition/{exhibition_id}", response_class=HTMLResponse)
|
||||||
@ -2124,8 +2114,7 @@ async def form_exhibition(
|
|||||||
user: Dict = Security(get_current_user)
|
user: Dict = Security(get_current_user)
|
||||||
):
|
):
|
||||||
exhibition = await exhibition_collection.find_one({'_id': ObjectId(exhibition_id)},{'posts':0,'vk':0,'tg':0,'fb':0,'inst':0,'max':0})
|
exhibition = await exhibition_collection.find_one({'_id': ObjectId(exhibition_id)},{'posts':0,'vk':0,'tg':0,'fb':0,'inst':0,'max':0})
|
||||||
data= json.dumps(exhibition, cls=MongoJSONEncoder, ensure_ascii=False)
|
data = json.dumps(exhibition, cls=MongoJSONEncoder, ensure_ascii=False)
|
||||||
print(data)
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
request=request, name="form/exhibition_edit.html", context={"id": 1, "user": user, "exhibition": str(data)}
|
request=request, name="form/exhibition_edit.html", context={"id": 1, "user": user, "exhibition": str(data)}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,24 +2,6 @@
|
|||||||
{% import "components/checkbox.html" as checkbox %}
|
{% import "components/checkbox.html" as checkbox %}
|
||||||
|
|
||||||
{% macro section(user, competition) -%}
|
{% macro section(user, competition) -%}
|
||||||
<script>
|
|
||||||
var type = '{{competition.type_}}';
|
|
||||||
|
|
||||||
function toggleType(clickedId) {
|
|
||||||
const artist = document.getElementById('artistCheck');
|
|
||||||
const paint = document.getElementById('paintCheck');
|
|
||||||
if (clickedId === 'artistCheck') {
|
|
||||||
artist.checked = clickedId === 'artistCheck';
|
|
||||||
paint.checked = clickedId === 'paintCheck';
|
|
||||||
type = 'artist';
|
|
||||||
} else if (clickedId === 'paintCheck') {
|
|
||||||
artist.checked = clickedId === 'artistCheck';
|
|
||||||
paint.checked = clickedId === 'paintCheck';
|
|
||||||
type = 'paint';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<form class="c_sbrxk">
|
<form class="c_sbrxk">
|
||||||
<div class="c_dtjoh">
|
<div class="c_dtjoh">
|
||||||
<h3>Выбор</h3>
|
<h3>Выбор</h3>
|
||||||
@ -28,7 +10,6 @@
|
|||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
id="artistCheck"
|
id="artistCheck"
|
||||||
class="offer-checkbox"
|
class="offer-checkbox"
|
||||||
{% if competition.type_ == 'artist'%}checked{%endif%}
|
|
||||||
onchange="toggleType('artistCheck')">
|
onchange="toggleType('artistCheck')">
|
||||||
<span class="offer-text">Художников</span>
|
<span class="offer-text">Художников</span>
|
||||||
</label>
|
</label>
|
||||||
@ -37,7 +18,6 @@
|
|||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
id="paintCheck"
|
id="paintCheck"
|
||||||
class="offer-checkbox"
|
class="offer-checkbox"
|
||||||
{% if competition.type_ == 'paint'%}checked{%endif%}
|
|
||||||
onchange="toggleType('paintCheck')">
|
onchange="toggleType('paintCheck')">
|
||||||
<span class="offer-text">Картин</span>
|
<span class="offer-text">Картин</span>
|
||||||
</label>
|
</label>
|
||||||
@ -168,26 +148,24 @@
|
|||||||
<input type="number" id="max_val" name="max_paintings" class="c_l8kil" value="10" min="1" max="99">
|
<input type="number" id="max_val" name="max_paintings" class="c_l8kil" value="10" min="1" max="99">
|
||||||
<!-- <input type="range" id="select_val" name="selected_count" class="c_5qh93" min="1" max="10" value="3"> -->
|
<!-- <input type="range" id="select_val" name="selected_count" class="c_5qh93" min="1" max="10" value="3"> -->
|
||||||
</div>
|
</div>
|
||||||
<!-- {% if competition.get('publish') is none %}
|
<!--
|
||||||
<div class="fl">
|
<div class="fl">
|
||||||
<span class="c_2fr39 b_tfnz2">Публикация запланирована на</span>
|
<span class="c_2fr39 b_tfnz2">Публикация запланирована на</span>
|
||||||
</div>
|
</div>
|
||||||
{{ (competition.datetime_start.strftime('%Y.%m.%d %H:%M' )) if competition.datetime_start else ''}}
|
|
||||||
|
|
||||||
<label class="offer-label">
|
<label class="offer-label">
|
||||||
<input type="checkbox" id="emailsNotify" class="offer-checkbox" {% if competition.emailsNotify %}checked{% endif %}>
|
<input type="checkbox" id="emailsNotify" class="offer-checkbox">
|
||||||
<span class="offer-text">Рассылка художникам приглашения на почту</span>
|
<span class="offer-text">Рассылка художникам приглашения на почту</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="offer-label">
|
<label class="offer-label">
|
||||||
<input type="checkbox" id="serviceSocial" class="offer-checkbox" {% if competition.serviceSocial %}checked{% endif %}>
|
<input type="checkbox" id="serviceSocial" class="offer-checkbox">
|
||||||
<span class="offer-text">Публикация в соц. сетях сервиса</span>
|
<span class="offer-text">Публикация в соц. сетях сервиса</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="offer-label">
|
<label class="offer-label">
|
||||||
<input type="checkbox" id="userSocial" class="offer-checkbox" {% if competition.userSocial %}checked{% endif %}>
|
<input type="checkbox" id="userSocial" class="offer-checkbox">
|
||||||
<span class="offer-text">Публикация в личных соц. сетях</span>
|
<span class="offer-text">Публикация в личных соц. сетях</span>
|
||||||
</label>
|
</label>
|
||||||
|
-->
|
||||||
{% endif %} -->
|
|
||||||
<button class="c_aq9et" id="createBtn">
|
<button class="c_aq9et" id="createBtn">
|
||||||
<span class="c_som9s">Сохранить изменения</span>
|
<span class="c_som9s">Сохранить изменения</span>
|
||||||
</button>
|
</button>
|
||||||
@ -202,7 +180,7 @@
|
|||||||
style="position:absolute;inset:0;filter:blur(3px)">
|
style="position:absolute;inset:0;filter:blur(3px)">
|
||||||
</div>
|
</div>
|
||||||
<picture>
|
<picture>
|
||||||
<img id="preview_poster" src="/b/competition/{{competition.poster_file_id}}" crossorigin="anonymous" fetchpriority="high" loading="eager" alt="Загрузите афишу" class="b_ornr9">
|
<img id="preview_poster" crossorigin="anonymous" fetchpriority="high" loading="eager" alt="Загрузите афишу" class="b_ornr9">
|
||||||
</picture>
|
</picture>
|
||||||
</div>
|
</div>
|
||||||
<div class="c_z3dpx b_73p10">
|
<div class="c_z3dpx b_73p10">
|
||||||
@ -210,9 +188,9 @@
|
|||||||
<span class="c_95csi b_0jst1">Формируется</span>
|
<span class="c_95csi b_0jst1">Формируется</span>
|
||||||
</div>
|
</div>
|
||||||
<header class="c_m876y b_9xtz9">
|
<header class="c_m876y b_9xtz9">
|
||||||
<h3 class="c_hysjg b_8f3uh" id="preview_title">{{competition.title or ""}}</h3>
|
<h3 class="c_hysjg b_8f3uh" id="preview_title"></h3>
|
||||||
</header>
|
</header>
|
||||||
<p class="c_2fr39 b_tfnz2" id="preview_topic">{{competition.topic or ""}}</p>
|
<p class="c_2fr39 b_tfnz2" id="preview_topic"></p>
|
||||||
<div class="c_dbbe4 b_otttb">
|
<div class="c_dbbe4 b_otttb">
|
||||||
{% if user %}
|
{% if user %}
|
||||||
<img crossorigin="anonymous" fetchpriority="high" loading="eager" class="c_pm80w b_a68fq" src="/a/{{user._id}}" alt="{{ user.username | e }}">
|
<img crossorigin="anonymous" fetchpriority="high" loading="eager" class="c_pm80w b_a68fq" src="/a/{{user._id}}" alt="{{ user.username | e }}">
|
||||||
@ -221,7 +199,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<p class="c_sihck b_s6ool" id="preview_desc">{{competition.short_desc or ""}}</p>
|
<p class="c_sihck b_s6ool" id="preview_desc"></p>
|
||||||
<p class="c_2fr39 b_tfnz2">Подробнее</p>
|
<p class="c_2fr39 b_tfnz2">Подробнее</p>
|
||||||
<p class="c_drpqj b_mp1wb">Дата создания</p>
|
<p class="c_drpqj b_mp1wb">Дата создания</p>
|
||||||
</div>
|
</div>
|
||||||
@ -365,12 +343,51 @@ function bindLinkValidation({
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script defer>
|
<script defer>
|
||||||
document.getElementById('title').value = `{{competition.title or ""}}`;
|
const competition = JSON.parse({{competition|tojson}})
|
||||||
document.getElementById('short_desc').value = `{{competition.short_desc or ""}}`;
|
const competitionId = competition._id
|
||||||
document.getElementById('address').value = `{{competition.address or ""}}`;
|
|
||||||
document.getElementById('topic').value = `{{competition.topic or ""}}`;
|
document.getElementById('title').value = competition.title;
|
||||||
document.getElementById('rules_link').value = `{{competition.get('rules_link') or ""}}`;
|
document.getElementById('preview_title').textContent = competition.title;
|
||||||
{% if competition.get('rules_link') %}
|
|
||||||
|
function setDateOrDateTimeLocal(elId, isoString) {
|
||||||
|
if (!isoString) return;
|
||||||
|
|
||||||
|
const s = isoString.replace(/^"|"$/g, ""); // на случай двойных кавычек
|
||||||
|
const [datePart, timePart = "00:00:00"] = s.split("T");
|
||||||
|
|
||||||
|
const [y, m, d] = datePart.split("-").map(Number);
|
||||||
|
const [hh, mm, ss = "0"] = timePart.split(":");
|
||||||
|
|
||||||
|
// Date constructor: month is 0-based
|
||||||
|
const dt = new Date(y, m - 1, d, Number(hh), Number(mm), Number(ss));
|
||||||
|
|
||||||
|
// Подготовим строку для input (локальное время)
|
||||||
|
const pad = (n) => String(n).padStart(2, "0");
|
||||||
|
const value = `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())}` +
|
||||||
|
`T${pad(dt.getHours())}:${pad(dt.getMinutes())}:${pad(dt.getSeconds())}`;
|
||||||
|
|
||||||
|
document.getElementById(elId).value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDateOnly(elId, isoString) {
|
||||||
|
if (!isoString) return;
|
||||||
|
const s = isoString.replace(/^"|"$/g, "");
|
||||||
|
const datePart = s.split("T")[0];
|
||||||
|
document.getElementById(elId).value = datePart; // YYYY-MM-DD
|
||||||
|
}
|
||||||
|
|
||||||
|
setDateOnly("date_finish", competition.date_finish);
|
||||||
|
setDateOrDateTimeLocal("datetime_start", competition.datetime_start);
|
||||||
|
|
||||||
|
document.getElementById('short_desc').value = competition.short_desc ;
|
||||||
|
document.getElementById('preview_desc').textContent = competition.short_desc ;
|
||||||
|
|
||||||
|
document.getElementById('address').value = competition.address;
|
||||||
|
document.getElementById('topic').value = competition.topic;
|
||||||
|
document.getElementById('preview_topic').textContent = competition.topic;
|
||||||
|
|
||||||
|
if (competition.rules_link){
|
||||||
|
document.getElementById('rules_link').value = competition.rules_link;
|
||||||
document.getElementById('file-block').style.display = 'none';
|
document.getElementById('file-block').style.display = 'none';
|
||||||
document.getElementById('link-block').style.display = 'flex';
|
document.getElementById('link-block').style.display = 'flex';
|
||||||
const select = document.querySelectorAll('.toggle-option')
|
const select = document.querySelectorAll('.toggle-option')
|
||||||
@ -378,38 +395,57 @@ document.getElementById('rules_link').value = `{{competition.get('rules_link') o
|
|||||||
select[1].classList.add('active');
|
select[1].classList.add('active');
|
||||||
select[0].querySelector('input').checked=false
|
select[0].querySelector('input').checked=false
|
||||||
select[1].querySelector('input').checked=true
|
select[1].querySelector('input').checked=true
|
||||||
{% endif %}
|
}
|
||||||
document.getElementById('nominations').dataset.value = `{{competition.nominations | safe or []}}`;
|
if (competition.type_ == 'artist'){
|
||||||
document.getElementById('nominations').dataset.list = `{{competition.nominations | safe or []}}`;
|
document.getElementById('artistCheck').checked = true
|
||||||
|
}
|
||||||
|
if (competition.type_ == 'paint'){
|
||||||
|
document.getElementById('paintCheck').checked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const inputEl = document.getElementById('nominations');
|
const inputEl = document.getElementById('nominations');
|
||||||
|
|
||||||
const raw = inputEl.getAttribute('data-list') || '[]';
|
const list = competition.nominations;
|
||||||
const fixed = raw.replace(/'/g, '"');
|
|
||||||
const list = JSON.parse(fixed);
|
|
||||||
|
|
||||||
inputEl.dataset.list = fixed
|
inputEl.dataset.list = list
|
||||||
inputEl.dataset.value = fixed
|
inputEl.dataset.value = list
|
||||||
|
|
||||||
document.getElementById('nominations').value = list.join(', ');
|
document.getElementById('nominations').value = list.join(', ');
|
||||||
|
|
||||||
document.getElementById('min_val').value = `{{competition.min_paintings or ""}}`;
|
document.getElementById('min_val').value = competition.min_paintings;
|
||||||
document.getElementById('max_val').value = `{{competition.max_paintings or ""}}`;
|
document.getElementById('max_val').value = competition.max_paintings;
|
||||||
document.getElementById('date_finish').value = `{{competition.date_finish or ""}}`;
|
|
||||||
document.getElementById('datetime_start').value = `{{competition.datetime_start or ""}}`;
|
|
||||||
document.getElementById('preview_poster').src = '/b/competition/{{competition.poster_file_id}}'
|
|
||||||
const competitionId = '{{competition._id}}'
|
|
||||||
const input = document.getElementById('datetime_start');
|
|
||||||
const date_finish = document.getElementById('date_finish');
|
|
||||||
const date_finish_date = new Date(`{{competition.date_finish or ""}}`);
|
|
||||||
const datetime_start_date = new Date('{{competition.datetime_start or ""}}');
|
|
||||||
const MOSCOW_OFFSET_MS = 3 * 60 * 60 * 1000;
|
|
||||||
const moscowInstant = new Date(datetime_start_date.getTime() + MOSCOW_OFFSET_MS);
|
|
||||||
|
|
||||||
input.value = moscowInstant.toISOString().slice(0, 16);
|
|
||||||
|
|
||||||
date_finish.value = date_finish_date.toISOString().slice(0, 10);
|
document.getElementById('preview_poster').src = `/b/competition/${competition.poster_file_id}`
|
||||||
|
|
||||||
|
// const input = document.getElementById('datetime_start');
|
||||||
|
// const date_finish = document.getElementById('date_finish');
|
||||||
|
// const date_finish_date = new Date(competition.date_finish);
|
||||||
|
// const datetime_start_date = new Date(competition.datetime_start);
|
||||||
|
// const MOSCOW_OFFSET_MS = 3 * 60 * 60 * 1000;
|
||||||
|
// const moscowInstant = new Date(datetime_start_date.getTime() + MOSCOW_OFFSET_MS);
|
||||||
|
|
||||||
|
// input.value = moscowInstant.toISOString().slice(0, 16);
|
||||||
|
|
||||||
|
// date_finish.value = date_finish_date.toISOString().slice(0, 10);
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var type = competition.type_;
|
||||||
|
|
||||||
|
function toggleType(clickedId) {
|
||||||
|
const artist = document.getElementById('artistCheck');
|
||||||
|
const paint = document.getElementById('paintCheck');
|
||||||
|
if (clickedId === 'artistCheck') {
|
||||||
|
artist.checked = clickedId === 'artistCheck';
|
||||||
|
paint.checked = clickedId === 'paintCheck';
|
||||||
|
type = 'artist';
|
||||||
|
} else if (clickedId === 'paintCheck') {
|
||||||
|
artist.checked = clickedId === 'artistCheck';
|
||||||
|
paint.checked = clickedId === 'paintCheck';
|
||||||
|
type = 'paint';
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script defer>
|
<script defer>
|
||||||
const minInput = document.getElementById('min_val');
|
const minInput = document.getElementById('min_val');
|
||||||
|
|||||||
13
utils.py
13
utils.py
@ -2,7 +2,7 @@ from fastapi import HTTPException, Request
|
|||||||
from fastapi.security import OAuth2PasswordBearer
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
from passlib.context import CryptContext
|
from passlib.context import CryptContext
|
||||||
import jwt
|
import jwt
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone, date
|
||||||
import hashlib
|
import hashlib
|
||||||
from typing import List, Dict, Optional, Set, Any
|
from typing import List, Dict, Optional, Set, Any
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@ -17,6 +17,8 @@ import httpx
|
|||||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
|
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
|
||||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
|
||||||
@ -25,6 +27,15 @@ OP_MAP = {"like_in": "like"}
|
|||||||
ENC_KEY = base64.b64decode(ENC_KEY_B64)
|
ENC_KEY = base64.b64decode(ENC_KEY_B64)
|
||||||
|
|
||||||
|
|
||||||
|
class MongoJSONEncoder(json.JSONEncoder):
|
||||||
|
def default(self, o):
|
||||||
|
if isinstance(o, ObjectId):
|
||||||
|
return str(o)
|
||||||
|
if isinstance(o, (datetime, date)):
|
||||||
|
return o.isoformat()
|
||||||
|
return super().default(o)
|
||||||
|
|
||||||
|
|
||||||
def encrypt(plaintext: bytes) -> str:
|
def encrypt(plaintext: bytes) -> str:
|
||||||
aesgcm = AESGCM(ENC_KEY)
|
aesgcm = AESGCM(ENC_KEY)
|
||||||
|
|
||||||
|
|||||||
4
vk.ipynb
4
vk.ipynb
@ -15,11 +15,11 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# ignore\n",
|
"#ignore\n",
|
||||||
"import os\n",
|
"import os\n",
|
||||||
"\n",
|
"\n",
|
||||||
"def load_env(file_path):\n",
|
"def load_env(file_path):\n",
|
||||||
" \"\"\"Загружает переменные окружения из файла .env с поддержкой булевых значений.\"\"\"\n",
|
" \"\"\"Загружает переменные окружения из файла env с поддержкой булевых значений.\"\"\"\n",
|
||||||
" with open(file_path) as f:\n",
|
" with open(file_path) as f:\n",
|
||||||
" for line in f:\n",
|
" for line in f:\n",
|
||||||
" line = line.strip()\n",
|
" line = line.strip()\n",
|
||||||
|
|||||||
34
vk.py
34
vk.py
@ -1,5 +1,39 @@
|
|||||||
# VK
|
# VK
|
||||||
|
|
||||||
|
#ignore
|
||||||
|
import os
|
||||||
|
|
||||||
|
def load_env(file_path):
|
||||||
|
"""Загружает переменные окружения из файла env с поддержкой булевых значений."""
|
||||||
|
with open(file_path) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
key, value = line.split('=', 1)
|
||||||
|
key = key.strip()
|
||||||
|
value = value.strip('"\' ')
|
||||||
|
|
||||||
|
# Преобразование строковых значений в булевые
|
||||||
|
if value.lower() in ['true', '1', 'yes']:
|
||||||
|
value = True
|
||||||
|
elif value.lower() in ['false', '0', 'no']:
|
||||||
|
value = False
|
||||||
|
|
||||||
|
# Проверка, что ключ не пустой
|
||||||
|
if key:
|
||||||
|
os.environ[key] = str(value) # Храним как строку
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
print(f"Ошибка: неверный формат в строке '{line}'")
|
||||||
|
|
||||||
|
try:
|
||||||
|
load_env('env')
|
||||||
|
except:
|
||||||
|
load_env('env_example')
|
||||||
|
|
||||||
## Class
|
## Class
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user