From 42be8613640d449cc48ffe4372e762fb98485456ef64a978bf8cb84be845674c Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 16:02:45 -0400 Subject: [PATCH 01/59] fix --- templates/paintings/paint.html | 50 +++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/templates/paintings/paint.html b/templates/paintings/paint.html index cc68419..ddf5eac 100644 --- a/templates/paintings/paint.html +++ b/templates/paintings/paint.html @@ -145,7 +145,11 @@ .c_la1ap { color: rgba(58, 58, 58, 0.75); font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; } .c_w6ecf { -webkit-box-orient: vertical; -webkit-line-clamp: 1; align-self: stretch; color: #000; display: -webkit-box; font-family: Inter; font-size: 20px; font-style: normal; font-weight: 700; line-height: normal; overflow: hidden; text-overflow: ellipsis; } .c_m3jeo { align-content: flex-start; align-items: flex-start; background: #FFF; display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; width: 1600px; } -} +} +.b_gagrr { align-items: center; align-self: stretch; display: flex; justify-content: space-between; } +.b_rhbo8 { color: #5F1798; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; } +.c_eiyz0{cursor: pointer;} + {{ footer.style() }} {% endblock %} @@ -182,14 +186,20 @@

{{paint.description or ''}}

{{ (paint._id.generation_time.strftime('%d.%m.%Y')) if paint._id else ''}}

+ {% if user and user._id == post.user._id %} +
+ Редактировать + +
+ {% else %} Обсудить покупку картины + {% endif %}
{{ share.share('/paintings/{}'.format(paint._id), paint.title, '/b/posts/{}'.format(paint.medias[0])) }}

👁 {{total_watch_count}} (+{{today_watch_count}} Сегодня)

- - - - - - + {{ footer.section(user) }} {% endblock %} From c0a006531ad40c67ed675fcbec5557a6ea07390e8d141a29d872509f0f806fde Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 16:11:10 -0400 Subject: [PATCH 02/59] fix --- main.ipynb | 389 ++++++++++++++++++----------------------------------- 1 file changed, 131 insertions(+), 258 deletions(-) diff --git a/main.ipynb b/main.ipynb index f85b285..59110f4 100644 --- a/main.ipynb +++ b/main.ipynb @@ -46,8 +46,7 @@ " load_env('env')\n", "except:\n", " load_env('env_example')" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -108,8 +107,7 @@ "\n", "logging.basicConfig(level=logging.INFO)\n", "logger = logging.getLogger(__name__)" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -139,8 +137,7 @@ ")\n", "app.include_router(delivery_router)\n", "app.include_router(vk.router, prefix='/api/v1/social', tags=[\"Auth\"])" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -171,8 +168,7 @@ "\n", "def transliterate(text: str) -> str:\n", " return ''.join(RUS_TO_LAT.get(ch, '' if ch not in string.ascii_letters else ch) for ch in text)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -190,8 +186,7 @@ " doc[\"published_at\"] = published.isoformat()\n", " docs.append(doc)\n", " return docs\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -246,8 +241,7 @@ " {'_id': ObjectId(user.get('_id'))},\n", " {'$set': {'img': str(new_id), 'original_img': str(original_img_id)}}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -277,8 +271,7 @@ " 'poster_file_id': new_id\n", " }}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -308,8 +301,7 @@ " 'poster_file_id': new_id\n", " }}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -349,8 +341,7 @@ " 'medias': new_ids\n", " }}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -387,8 +378,7 @@ " 'medias': new_ids\n", " }}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -425,8 +415,7 @@ " 'media': new_ids\n", " }}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -453,8 +442,7 @@ " return str(file_id)\n", " finally:\n", " await upload.close()\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -470,8 +458,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/posts.html\", context={ \"user\": user, 'cards': data}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -490,8 +477,7 @@ " {\"$set\": {\"status\": 2}},\n", " )\n", " return {}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -501,8 +487,7 @@ "outputs": [], "source": [ "# await notify_collection.delete_many({'title':'Доставка картины'})" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -512,8 +497,7 @@ "outputs": [], "source": [ "# await notify_collection.update_many({'title':'Доставка картины'},{'$set':{'type':'delivery'}})" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -539,8 +523,7 @@ "# ))\n", "# print(notify)\n", "# await delivery_collection.update_one({'_id': existing.get('_id')},{'$set':{'notify': notify.upserted_id}})" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -659,8 +642,7 @@ " if exhibition_to_start.get(\"vk\") == [] or exhibition_to_start.get(\"tg\") == []:\n", " await service_social_exhibition(bson_clear(exhibition_to_start))\n", " return {}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -674,8 +656,7 @@ "# {\"prod\": True, \"datetime_start\": {\"$lt\": datetime.now(timezone.utc) + timedelta(hours=3)}},\n", "# {\"$set\": {\"status\": 1}}, return_document=False)\n", "# await service_social_exhibition(exhibition)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -811,8 +792,7 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -895,8 +875,7 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -931,8 +910,7 @@ " max_age=int(refresh_exp_delta.total_seconds())\n", " )\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1038,8 +1016,7 @@ " next_url = '/'\n", "\n", " return RedirectResponse(next_url,headers=response.headers)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1160,8 +1137,7 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1229,8 +1205,7 @@ " max_age=int(refresh_exp_delta.total_seconds())\n", " )\n", " return {'ok': True}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1327,8 +1302,7 @@ " \"token_type\": \"bearer\",\n", " \"refresh_token\": new_refresh\n", " }" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1365,8 +1339,7 @@ " )\n", "\n", " return {\"message\": \"Logged out from all sessions\"}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1379,8 +1352,7 @@ "async def get_me(response: Response, current_user: Dict = Security(get_current_user, scopes=[\"read:self\"])):\n", " user = display_user(current_user)\n", " return bson_clear(user)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1404,8 +1376,7 @@ " raise HTTPException(status_code=500, detail=f\"Redis is unhealthy: {str(e)}\")\n", "\n", " return {}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1422,8 +1393,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"registration.html\", context={'next': next}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1465,8 +1435,7 @@ " results.append(doc)\n", " \n", " return results\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1508,8 +1477,7 @@ "\n", " cursor = competition_request_col.aggregate(pipeline)\n", " return await cursor.to_list(length=None)" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1563,8 +1531,7 @@ "# cursor = posts_collection.find({\"_id\": {\"$in\": posts_ids}})\n", "# return await cursor.to_list(length=None)\n", "\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1596,8 +1563,7 @@ " cursor = competition_request_col.aggregate(pipeline)\n", " unique_posts = await cursor.to_list(length=None) # Fetch all unique posts\n", " return [unique_post[\"post\"] for unique_post in unique_posts] if unique_posts else []\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1620,8 +1586,7 @@ " )\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1645,8 +1610,7 @@ " )\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1676,8 +1640,7 @@ " raise HTTPException(status_code=307, headers={\"Location\": f'/competition/{competition._id}'}, detail=\"Участник не найден\")\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1707,8 +1670,7 @@ " },{'fb':0,'inst':0,'max':0,'tg':0,'vk':0}).sort('_id',-1).limit(32):\n", " competitions.append(bson_clear(doc))\n", " return competitions" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1737,8 +1699,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"exhibitions.html\", context={\"id\": 1, \"user\": user, \"exhibitions\": exhibitions}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1768,8 +1729,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"competitions.html\", context={\"id\": 1, \"user\": user, \"competitions\": competitions}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1845,13 +1805,13 @@ " # 7. Асинхронная отправка email\n", " try:\n", " email_task.notify.delay(\n", - " recipient=user['email'],\n", - " context={\n", + " user['email'],\n", + " {\n", " 'link': reset_link, \n", " 'email': user['email']\n", " },\n", - " subject='Восстановление пароля',\n", - " template_name='restore.html'\n", + " 'Восстановление пароля',\n", + " 'restore.html'\n", " )\n", " except Exception as e:\n", " # Логирование ошибки\n", @@ -1914,8 +1874,7 @@ "\n", "\n", "app.include_router(router, tags=['Восстановление пароля'])" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1940,8 +1899,7 @@ " name=\"login.html\",\n", " context=context,\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1955,8 +1913,7 @@ " response: Response,user: Dict = Security(get_current_user)):\n", " await users_collection.update_one({'_id':ObjectId(user.get('_id'))},{'$set':{'profile':'' if user.get('profile',False) else 'partner'}})\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1975,8 +1932,7 @@ " {'$set': {'description': data.description}}\n", " )\n", " return {'ok': True}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -1998,8 +1954,7 @@ " for i in exhibition.get('vk',[]):\n", " vk.delete_wall.delay(i.get('response',{}).get('post_id'), i.get('doc'))\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2021,8 +1976,7 @@ " for i in competition.get('vk',[]):\n", " vk.delete_wall.delay(i.get('response',{}).get('post_id'), i.get('doc'))\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2041,8 +1995,7 @@ " {'$set': {'status': 2}},\n", " )\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2061,8 +2014,7 @@ " {'$set': {'status': 1}},\n", " )\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2108,8 +2060,7 @@ " return {'ok': True}\n", " else:\n", " return {'ok': False}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2190,8 +2141,7 @@ "\n", "\n", " return {'ok': True}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2212,8 +2162,7 @@ " coros = [_update_post_description(p) for p in posts]\n", " if coros:\n", " await asyncio.gather(*coros)" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2308,8 +2257,7 @@ " response[\"message\"] = f\"Исключено {excluded_count} уже использованных постов\"\n", "\n", " return response" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2327,8 +2275,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/news.html\", context={ \"user\": user, 'news': news}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2345,8 +2292,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/form.html\", context={ \"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2362,8 +2308,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/competitions.html\", context={ \"user\": user, 'cards': data}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2380,8 +2325,7 @@ " await users_collection.update_one({'_id':ObjectId(user.get('_id'))},{'$set':{'profile':'partner'}})\n", " user['profile'] = 'partner'\n", " return await competitions(user,request)" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2427,8 +2371,7 @@ " for post in posts:\n", " post['competition'] = oid\n", " return posts\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2467,8 +2410,7 @@ " results.append(doc)\n", " \n", " return results\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2494,8 +2436,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/competition.html\", context={ \"user\": user, \"competition\": competition, 'posts': posts, \"members\": members}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2526,8 +2467,7 @@ " request=request, name=\"profile/partner/competition_member.html\", context={ \"user\": user, \"social_vk\":social_vk, \"competition\": competition, 'posts': posts, \"member\": member}\n", " )\n", " " - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2555,8 +2495,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/competition.html\", context={ \"user\": user, 'competitions': competitions}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2599,8 +2538,7 @@ " # return templates.TemplateResponse(\n", " # request=request, name=\"profile/form.html\", context={ \"user\": user, 'notify':{'text':'В начале заполните анкету под звездочками','status':'error','duration':8000}}\n", " # )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2665,8 +2603,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/exhibition.html\", context={\"user\": user, \"data\": data, \"now\": datetime.now()}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2689,8 +2626,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"about.html\", context={\"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2705,8 +2641,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"news.html\", context={\"user\": user, \"news\": news}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2735,8 +2670,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"index.html\", context={\"user\": user, \"news\": news, 'pwa':True}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2754,8 +2688,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"partner/galerist.html\", context={\"id\": 1, \"user\": user, \"partner\": partner}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2772,8 +2705,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"partner/index.html\", context={\"id\": 1, \"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2791,8 +2723,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/index.html\", context={\"id\": 1, \"user\":user, \"users\": users}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2829,8 +2760,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/user.html\", context={\"id\": 1, \"user\":user, \"find\": find, \"cards\": cards,\"total_watch_count\": total_watch_count,\"today_watch_count\": today_watch_count,}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2867,8 +2797,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/user.html\", context={\"id\": 1, \"user\":user, \"find\": find, \"cards\": cards,\"total_watch_count\": total_watch_count,\"today_watch_count\": today_watch_count,}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2885,8 +2814,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/competition.html\", context={\"id\": 1, \"user\": user}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2906,8 +2834,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/competition_edit.html\", context={\"competition\": str(data), \"competition_id\": competition_id, \"user\": user}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2933,8 +2860,7 @@ " return templates.TemplateResponse(\n", " request=requset, name='news/index.html', context={\"user\":user, \"news\": news}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2966,8 +2892,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/post_edit.html\", context={\"post\": data, \"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -2995,8 +2920,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/news_edit.html\", context={\"news\": news, \"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3013,8 +2937,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/exhibition.html\", context={\"id\": 1, \"user\": user}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3034,8 +2957,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/exhibition_edit.html\", context={\"id\": 1, \"user\": user, \"exhibition\": str(data)}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3058,8 +2980,7 @@ " return {'ok': True}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3094,8 +3015,7 @@ " raise\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3148,8 +3068,7 @@ " if not doc:\n", " raise HTTPException(status_code=404, detail=\"Картина не найдена\")\n", " return RedirectResponse(url=f\"/paintings/{doc.get('_id')}\", status_code=301)" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3165,8 +3084,7 @@ "):\n", " await posts_collection.delete_one({'_id': ObjectId(post_id), 'user._id': current_user.get('_id')})\n", " return {'ok': True} \n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3226,8 +3144,7 @@ " except Exception as e:\n", " print(e)\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3297,8 +3214,7 @@ " background_tasks.add_task(update_social_post, doc_out)\n", " background_tasks.add_task(replace_new_medias, bson_clear(doc_out), links_media)\n", " return doc_out\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3399,8 +3315,7 @@ " return {\"post_medias\": post_medias}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3442,8 +3357,7 @@ " return doc_out\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3491,8 +3405,7 @@ " }\n", " doc_out = bson_clear(doc_out)\n", " return doc_out\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3511,8 +3424,7 @@ " return {'media': media}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3527,8 +3439,7 @@ "):\n", " await notify_collection.update_many({'user_id':user.get('_id')},{'$set':{'read':False}})\n", " return {}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3590,8 +3501,7 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3651,8 +3561,7 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3722,8 +3631,7 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3745,8 +3653,7 @@ " },{'vk': 0,'max': 0,'tg': 0,'fb': 0,'inst': 0}).sort('_id',-1).limit(1000):\n", " exhibitions.append(bson_clear(doc))\n", " return exhibitions" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3808,8 +3715,7 @@ " except Exception as e:\n", " logging.error(str(e))\n", " raise HTTPException(status_code=500, detail=str(e))" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3886,8 +3792,7 @@ " except Exception as e:\n", " logging.error(str(e))\n", " raise HTTPException(status_code=500, detail=str(e))" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -3996,8 +3901,7 @@ " if file_length is not None:\n", " headers[\"Content-Length\"] = str(file_length)\n", " return StreamingResponse(iterator(), media_type=content_type, headers=headers)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4060,8 +3964,7 @@ " \n", " \n", " \"\"\"\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4081,8 +3984,7 @@ " 'users': users \n", " }\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4198,8 +4100,7 @@ " \"all_city\": len(await users_collection.distinct(\"living_place\", filter={ 'roles': \"user\" }))\n", " }\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4215,8 +4116,7 @@ " if item:\n", " update_spec = {\"$push\": {\"tg\": result}}\n", " await mongo_client[item.get('db')][item.get('col')].update_one({'_id': ObjectId(item.get('_id'))}, update_spec)" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4234,8 +4134,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/social.html\", context={\"user\": user, 'socials': socials}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4278,8 +4177,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitation.html\", context={ \"user\": user, \"doc\": data, \"data\": posts}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4298,8 +4196,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitations.html\", context={ \"user\": user, \"data\": data, \"now\": datetime.now()}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4317,8 +4214,7 @@ "):\n", " await social_collection.update_one({'_id': ObjectId(id), 'user_id': user.get('_id')},{'$set': {key:check}})\n", " return {'ok': True}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4344,8 +4240,7 @@ "\n", " data = [doc async for doc in cursor]\n", " return data[0] if data else False" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4385,8 +4280,7 @@ " today_watch_count = await redis_client.incr(daily_key)\n", " return {\"totalViews\":total_watch_count,\"todayViews\":today_watch_count}\n", " return {\"totalViews\":0,\"todayViews\":0}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4477,8 +4371,7 @@ " 'last_page': post_count / per_page,\n", " 'per_page': per_page\n", " }" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4496,8 +4389,7 @@ " return {\"statistics\":await users_collection.count_documents({ 'roles': \"user\" }),\"additional_stats\":len(await users_collection.distinct(\"living_place\", filter={ 'roles': \"user\" }))}\n", " else:\n", " return {\"statistics\":await posts_collection.count_documents({}),\"additional_stats\":await users_collection.count_documents({ 'roles': \"user\" })}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4524,8 +4416,7 @@ " user.pop('phone')\n", " user.pop('email')\n", " return {'data':bson_clear(user)}" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4550,8 +4441,7 @@ " post['name'] = post['title']\n", " post['media'] = photos\n", " return bson_clear(post)" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -4580,8 +4470,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitation/competition.html\", context={ \"user\": user, \"competition\": competition, \"req\": req}\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4601,8 +4490,7 @@ "\n", " await accept_invitations(invitations_id, posts_ids)\n", " return {'ok': True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4626,8 +4514,7 @@ " \"data\": data,\n", " }\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4668,8 +4555,7 @@ "# \"data\": data,\n", "# }\n", "# )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4709,8 +4595,7 @@ " \"data\": data,\n", " }\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4751,8 +4636,7 @@ " \"data\": data,\n", " }\n", " )" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4825,8 +4709,7 @@ " \"active_section\": \"delivery\"\n", " }\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4844,8 +4727,7 @@ " background_tasks.add_task(exhibition_send_invitations, exhibition_id)\n", " logging.info(f\"send exh inv {exhibition_id}\")\n", " return {\"ok\": True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4880,8 +4762,7 @@ " ]\n", " )\n", " return {\"ok\": True}\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4955,8 +4836,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibition catalog.html\", context={\"now\": datetime.now(), \"user\": user, \"galerists\": galerists, \"genres\": genres, \"living_places\": living_places, \"exhibition\": exhibition, \"posts\": posts}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -4993,8 +4873,7 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibitions.html\", context={\"now\": datetime.now(), \"user\": user, \"data\": data}\n", " )\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -5033,8 +4912,7 @@ "\n", " with open(f'{filename_without_extension}.py', 'w') as f:\n", " f.write('\\n\\n'.join(app))\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -5048,8 +4926,7 @@ "outputs": [], "source": [ "!uvicorn main:app --host 0.0.0.0 --port 8005 --reload" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -5060,8 +4937,7 @@ "source": [ "import uvicorn\n", "uvicorn.run('main:app', host='0.0.0.0', port=8005, reload=True)\n" - ], - "display_name": ".venv" + ] }, { "cell_type": "markdown", @@ -5083,8 +4959,7 @@ "outputs": [], "source": [ "!pip freeze > req.txt" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -5095,8 +4970,7 @@ "source": [ "import sys\n", "sys.executable" - ], - "display_name": ".venv" + ] }, { "cell_type": "code", @@ -5108,8 +4982,7 @@ "import sys\n", "sys.executable\n", "!{sys.executable} -m pip install -r requirements-api.txt" - ], - "display_name": ".venv" + ] } ], "metadata": { From 478f658dea5f226c5a504eef102fa87aa19d128ba7c2bbb965833ba02b38071f Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 16:28:10 -0400 Subject: [PATCH 03/59] fix --- main.ipynb | 6 +----- static/service-worker.js | 2 +- static/sw.js | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/main.ipynb b/main.ipynb index 59110f4..7d164d6 100644 --- a/main.ipynb +++ b/main.ipynb @@ -1777,11 +1777,7 @@ " ]})\n", " \n", " if not user:\n", - " # Безопасность: всегда возвращать одинаковое время ответа/структуру сообщения, если возможно\n", - " # Но для удобства использования мы можем сказать \"не найден\".\n", - " # Чтобы предотвратить перечисление, некоторые приложения всегда возвращают \"OK\", но отправляют письмо только если найдено.\n", - " # Здесь мы придерживаемся вашей оригинальной логики, но помните о риске перечисления.\n", - " raise HTTPException(status_code=404, detail=\"Пользователь с таким email не найден\")\n", + " return {'ok': True}\n", " \n", " # 4. Генерация токена\n", " token = secrets.token_urlsafe(32)\n", diff --git a/static/service-worker.js b/static/service-worker.js index 7c4bb9a..958a026 100644 --- a/static/service-worker.js +++ b/static/service-worker.js @@ -2,7 +2,7 @@ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox workbox.setConfig({ debug: false }); -const CACHE_NAME = 'app-cache-v2.1.4'; +const CACHE_NAME = 'app-cache-v2.1.5'; const MIN_VALID_SIZE = 500; const ASSETS_TO_CACHE = [ diff --git a/static/sw.js b/static/sw.js index 7c4bb9a..958a026 100644 --- a/static/sw.js +++ b/static/sw.js @@ -2,7 +2,7 @@ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox workbox.setConfig({ debug: false }); -const CACHE_NAME = 'app-cache-v2.1.4'; +const CACHE_NAME = 'app-cache-v2.1.5'; const MIN_VALID_SIZE = 500; const ASSETS_TO_CACHE = [ From bb8cb1aa73c40790ae2d26311dc3d8db65f986eb35950d6abde9306dda6efe1d Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 16:37:55 -0400 Subject: [PATCH 04/59] hotfix --- templates/paintings/paint.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/paintings/paint.html b/templates/paintings/paint.html index ddf5eac..cda178a 100644 --- a/templates/paintings/paint.html +++ b/templates/paintings/paint.html @@ -186,10 +186,10 @@

{{paint.description or ''}}

{{ (paint._id.generation_time.strftime('%d.%m.%Y')) if paint._id else ''}}

- {% if user and user._id == post.user._id %} + {% if user and user._id == paint.user._id %}
- Редактировать - + Редактировать +
{% else %} Обсудить покупку картины From 0c418e57eb5a9de71cfe9a4c37cbe85b956d5b7e1aed3e7447c36f2dadf0c0fd Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 16:39:25 -0400 Subject: [PATCH 05/59] style --- templates/paintings/paint.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/paintings/paint.html b/templates/paintings/paint.html index cda178a..34df428 100644 --- a/templates/paintings/paint.html +++ b/templates/paintings/paint.html @@ -187,7 +187,7 @@

{{paint.description or ''}}

{{ (paint._id.generation_time.strftime('%d.%m.%Y')) if paint._id else ''}}

{% if user and user._id == paint.user._id %} -
+ From 1d444068a0b9f9a72219940eedd6a8cca9d23aa0c51837b6caaf27299e074421 Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 17:04:39 -0400 Subject: [PATCH 06/59] fix --- main.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.ipynb b/main.ipynb index 7d164d6..f6e5935 100644 --- a/main.ipynb +++ b/main.ipynb @@ -1801,13 +1801,13 @@ " # 7. Асинхронная отправка email\n", " try:\n", " email_task.notify.delay(\n", - " user['email'],\n", - " {\n", + " to_email=user['email'],\n", + " data={\n", " 'link': reset_link, \n", " 'email': user['email']\n", " },\n", - " 'Восстановление пароля',\n", - " 'restore.html'\n", + " subject='Восстановление пароля',\n", + " template='restore.html'\n", " )\n", " except Exception as e:\n", " # Логирование ошибки\n", From d071e226e7dd52629da1957639c8de5c0f2b1dcc159cfd5392d0fcfe86ea30ef Mon Sep 17 00:00:00 2001 From: vladislav Date: Mon, 31 Aug 2026 23:36:52 -0400 Subject: [PATCH 07/59] fix --- migrate.ipynb | 85 --------------------------------------------------- migrate.py | 3 -- 2 files changed, 88 deletions(-) delete mode 100644 migrate.ipynb delete mode 100644 migrate.py diff --git a/migrate.ipynb b/migrate.ipynb deleted file mode 100644 index c5ae839..0000000 --- a/migrate.ipynb +++ /dev/null @@ -1,85 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "90b31bac", - "metadata": {}, - "outputs": [], - "source": [ - "# ignore\n", - "import os\n", - "\n", - "def load_env(file_path):\n", - " \"\"\"Загружает переменные окружения из файла .env с поддержкой булевых значений.\"\"\"\n", - " with open(file_path) as f:\n", - " for line in f:\n", - " line = line.strip()\n", - " if not line or line.startswith('#'):\n", - " continue\n", - " \n", - " try:\n", - " key, value = line.split('=', 1)\n", - " key = key.strip()\n", - " value = value.strip('\"\\' ')\n", - " # Преобразование строковых значений в булевые\n", - " if value.lower() in ['true', '1', 'yes']:\n", - " value = True\n", - " elif value.lower() in ['false', '0', 'no']:\n", - " value = False\n", - " \n", - " # Проверка, что ключ не пустой\n", - " if key:\n", - " os.environ[key] = str(value) # Храним как строку\n", - " except ValueError:\n", - " print(f\"Ошибка: неверный формат в строке '{line}'\")\n", - "\n", - "try:\n", - " load_env('env')\n", - "except:\n", - " load_env('env_example')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3f5835c", - "metadata": {}, - "outputs": [], - "source": [ - "from db import *" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d80807dd", - "metadata": {}, - "outputs": [], - "source": [ - "await posts_collection.update_many({'status':'publish'},{'$set':{'status':'В каталоге'}})" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.13.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/migrate.py b/migrate.py deleted file mode 100644 index 33a1ba1..0000000 --- a/migrate.py +++ /dev/null @@ -1,3 +0,0 @@ -from db import * - -await posts_collection.update_many({'status':'publish'},{'$set':{'status':'В каталоге'}}) \ No newline at end of file From 439d824f70d12701582d2af183cd82283042d8b87cd062d10058e7d6e7ab4ff1 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 04:06:31 -0400 Subject: [PATCH 08/59] fix --- templates/profile/exhibition.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/profile/exhibition.html b/templates/profile/exhibition.html index 61c73c8..c413d6e 100644 --- a/templates/profile/exhibition.html +++ b/templates/profile/exhibition.html @@ -18,7 +18,7 @@
{% for i in data %}
- +
Загрузите афишу @@ -26,7 +26,7 @@
- +
{% if now > i.date_finish %} Закончилась From 4d400fc12b4eec72f7425c0bf8b8fdeadf9b09eab3bea18fd69f3286d37fc101 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 04:09:53 -0400 Subject: [PATCH 09/59] style --- templates/articles.html | 1 - templates/base.html | 1 - 2 files changed, 2 deletions(-) diff --git a/templates/articles.html b/templates/articles.html index 20ea670..47f7582 100644 --- a/templates/articles.html +++ b/templates/articles.html @@ -37,7 +37,6 @@ max-width: 100%; overflow-wrap: break-word; word-break: break-word; - hyphens: auto; } .c_qx7jk{margin: 100px 0;} .c_h9bsw{width: 100%;object-fit: scale-down;} diff --git a/templates/base.html b/templates/base.html index 8057ce9..ab85e47 100644 --- a/templates/base.html +++ b/templates/base.html @@ -18,7 +18,6 @@ h1,h2,h3,p { max-width: 100%; overflow-wrap: break-word; word-break: break-word; - hyphens: auto; } html{display: flex;justify-content: center;} input, button {touch-action: manipulation;} From dd5f79c73da4d9516fd4c64307c2c2632ea809bb498626ec607aeaeff8a17830 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 04:20:20 -0400 Subject: [PATCH 10/59] fix --- main.ipynb | 385 +++++++++++++++++++++++++++++++++++------------------ main.py | 16 +-- 2 files changed, 262 insertions(+), 139 deletions(-) diff --git a/main.ipynb b/main.ipynb index f6e5935..5a687df 100644 --- a/main.ipynb +++ b/main.ipynb @@ -46,7 +46,8 @@ " load_env('env')\n", "except:\n", " load_env('env_example')" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -107,7 +108,8 @@ "\n", "logging.basicConfig(level=logging.INFO)\n", "logger = logging.getLogger(__name__)" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -137,7 +139,8 @@ ")\n", "app.include_router(delivery_router)\n", "app.include_router(vk.router, prefix='/api/v1/social', tags=[\"Auth\"])" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -168,7 +171,8 @@ "\n", "def transliterate(text: str) -> str:\n", " return ''.join(RUS_TO_LAT.get(ch, '' if ch not in string.ascii_letters else ch) for ch in text)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -186,7 +190,8 @@ " doc[\"published_at\"] = published.isoformat()\n", " docs.append(doc)\n", " return docs\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -241,7 +246,8 @@ " {'_id': ObjectId(user.get('_id'))},\n", " {'$set': {'img': str(new_id), 'original_img': str(original_img_id)}}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -271,7 +277,8 @@ " 'poster_file_id': new_id\n", " }}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -301,7 +308,8 @@ " 'poster_file_id': new_id\n", " }}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -341,7 +349,8 @@ " 'medias': new_ids\n", " }}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -378,7 +387,8 @@ " 'medias': new_ids\n", " }}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -415,7 +425,8 @@ " 'media': new_ids\n", " }}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -442,7 +453,8 @@ " return str(file_id)\n", " finally:\n", " await upload.close()\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -458,7 +470,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/posts.html\", context={ \"user\": user, 'cards': data}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -477,7 +490,8 @@ " {\"$set\": {\"status\": 2}},\n", " )\n", " return {}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -487,7 +501,8 @@ "outputs": [], "source": [ "# await notify_collection.delete_many({'title':'Доставка картины'})" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -497,7 +512,8 @@ "outputs": [], "source": [ "# await notify_collection.update_many({'title':'Доставка картины'},{'$set':{'type':'delivery'}})" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -523,7 +539,8 @@ "# ))\n", "# print(notify)\n", "# await delivery_collection.update_one({'_id': existing.get('_id')},{'$set':{'notify': notify.upserted_id}})" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -642,7 +659,8 @@ " if exhibition_to_start.get(\"vk\") == [] or exhibition_to_start.get(\"tg\") == []:\n", " await service_social_exhibition(bson_clear(exhibition_to_start))\n", " return {}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -656,7 +674,8 @@ "# {\"prod\": True, \"datetime_start\": {\"$lt\": datetime.now(timezone.utc) + timedelta(hours=3)}},\n", "# {\"$set\": {\"status\": 1}}, return_document=False)\n", "# await service_social_exhibition(exhibition)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -792,7 +811,8 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -875,7 +895,8 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -910,7 +931,8 @@ " max_age=int(refresh_exp_delta.total_seconds())\n", " )\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1016,7 +1038,8 @@ " next_url = '/'\n", "\n", " return RedirectResponse(next_url,headers=response.headers)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1137,7 +1160,8 @@ " \"user_id\": user_id_str,\n", " \"token_type\": \"bearer\"\n", " }\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1205,7 +1229,8 @@ " max_age=int(refresh_exp_delta.total_seconds())\n", " )\n", " return {'ok': True}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1302,7 +1327,8 @@ " \"token_type\": \"bearer\",\n", " \"refresh_token\": new_refresh\n", " }" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1339,7 +1365,8 @@ " )\n", "\n", " return {\"message\": \"Logged out from all sessions\"}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1352,7 +1379,8 @@ "async def get_me(response: Response, current_user: Dict = Security(get_current_user, scopes=[\"read:self\"])):\n", " user = display_user(current_user)\n", " return bson_clear(user)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1376,7 +1404,8 @@ " raise HTTPException(status_code=500, detail=f\"Redis is unhealthy: {str(e)}\")\n", "\n", " return {}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1393,7 +1422,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"registration.html\", context={'next': next}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1435,7 +1465,8 @@ " results.append(doc)\n", " \n", " return results\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1477,7 +1508,8 @@ "\n", " cursor = competition_request_col.aggregate(pipeline)\n", " return await cursor.to_list(length=None)" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1531,7 +1563,8 @@ "# cursor = posts_collection.find({\"_id\": {\"$in\": posts_ids}})\n", "# return await cursor.to_list(length=None)\n", "\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1563,7 +1596,8 @@ " cursor = competition_request_col.aggregate(pipeline)\n", " unique_posts = await cursor.to_list(length=None) # Fetch all unique posts\n", " return [unique_post[\"post\"] for unique_post in unique_posts] if unique_posts else []\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1586,7 +1620,8 @@ " )\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1610,7 +1645,8 @@ " )\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1640,7 +1676,8 @@ " raise HTTPException(status_code=307, headers={\"Location\": f'/competition/{competition._id}'}, detail=\"Участник не найден\")\n", " else:\n", " raise HTTPException(status_code=307, headers={\"Location\": '/competitions'}, detail=\"Конкурс не найден\")" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1670,7 +1707,8 @@ " },{'fb':0,'inst':0,'max':0,'tg':0,'vk':0}).sort('_id',-1).limit(32):\n", " competitions.append(bson_clear(doc))\n", " return competitions" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1699,7 +1737,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"exhibitions.html\", context={\"id\": 1, \"user\": user, \"exhibitions\": exhibitions}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1729,7 +1768,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"competitions.html\", context={\"id\": 1, \"user\": user, \"competitions\": competitions}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1870,7 +1910,8 @@ "\n", "\n", "app.include_router(router, tags=['Восстановление пароля'])" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1895,7 +1936,8 @@ " name=\"login.html\",\n", " context=context,\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1909,7 +1951,8 @@ " response: Response,user: Dict = Security(get_current_user)):\n", " await users_collection.update_one({'_id':ObjectId(user.get('_id'))},{'$set':{'profile':'' if user.get('profile',False) else 'partner'}})\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1928,7 +1971,8 @@ " {'$set': {'description': data.description}}\n", " )\n", " return {'ok': True}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1950,7 +1994,8 @@ " for i in exhibition.get('vk',[]):\n", " vk.delete_wall.delay(i.get('response',{}).get('post_id'), i.get('doc'))\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1972,7 +2017,8 @@ " for i in competition.get('vk',[]):\n", " vk.delete_wall.delay(i.get('response',{}).get('post_id'), i.get('doc'))\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -1991,7 +2037,8 @@ " {'$set': {'status': 2}},\n", " )\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2010,7 +2057,8 @@ " {'$set': {'status': 1}},\n", " )\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2056,7 +2104,8 @@ " return {'ok': True}\n", " else:\n", " return {'ok': False}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2137,7 +2186,8 @@ "\n", "\n", " return {'ok': True}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2158,7 +2208,8 @@ " coros = [_update_post_description(p) for p in posts]\n", " if coros:\n", " await asyncio.gather(*coros)" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2253,7 +2304,8 @@ " response[\"message\"] = f\"Исключено {excluded_count} уже использованных постов\"\n", "\n", " return response" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2271,7 +2323,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/news.html\", context={ \"user\": user, 'news': news}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2288,7 +2341,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/form.html\", context={ \"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2304,7 +2358,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/competitions.html\", context={ \"user\": user, 'cards': data}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2321,7 +2376,8 @@ " await users_collection.update_one({'_id':ObjectId(user.get('_id'))},{'$set':{'profile':'partner'}})\n", " user['profile'] = 'partner'\n", " return await competitions(user,request)" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2367,7 +2423,8 @@ " for post in posts:\n", " post['competition'] = oid\n", " return posts\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2406,7 +2463,8 @@ " results.append(doc)\n", " \n", " return results\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2432,7 +2490,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/competition.html\", context={ \"user\": user, \"competition\": competition, 'posts': posts, \"members\": members}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2463,7 +2522,8 @@ " request=request, name=\"profile/partner/competition_member.html\", context={ \"user\": user, \"social_vk\":social_vk, \"competition\": competition, 'posts': posts, \"member\": member}\n", " )\n", " " - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2491,7 +2551,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/competition.html\", context={ \"user\": user, 'competitions': competitions}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2534,7 +2595,8 @@ " # return templates.TemplateResponse(\n", " # request=request, name=\"profile/form.html\", context={ \"user\": user, 'notify':{'text':'В начале заполните анкету под звездочками','status':'error','duration':8000}}\n", " # )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2599,7 +2661,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/exhibition.html\", context={\"user\": user, \"data\": data, \"now\": datetime.now()}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2622,7 +2685,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"about.html\", context={\"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2637,7 +2701,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"news.html\", context={\"user\": user, \"news\": news}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2666,7 +2731,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"index.html\", context={\"user\": user, \"news\": news, 'pwa':True}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2684,7 +2750,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"partner/galerist.html\", context={\"id\": 1, \"user\": user, \"partner\": partner}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2701,7 +2768,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"partner/index.html\", context={\"id\": 1, \"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2719,7 +2787,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/index.html\", context={\"id\": 1, \"user\":user, \"users\": users}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2756,7 +2825,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/user.html\", context={\"id\": 1, \"user\":user, \"find\": find, \"cards\": cards,\"total_watch_count\": total_watch_count,\"today_watch_count\": today_watch_count,}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2793,7 +2863,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"users/user.html\", context={\"id\": 1, \"user\":user, \"find\": find, \"cards\": cards,\"total_watch_count\": total_watch_count,\"today_watch_count\": today_watch_count,}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2810,7 +2881,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/competition.html\", context={\"id\": 1, \"user\": user}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2830,7 +2902,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/competition_edit.html\", context={\"competition\": str(data), \"competition_id\": competition_id, \"user\": user}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2856,7 +2929,8 @@ " return templates.TemplateResponse(\n", " request=requset, name='news/index.html', context={\"user\":user, \"news\": news}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2888,7 +2962,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/post_edit.html\", context={\"post\": data, \"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2916,7 +2991,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/news_edit.html\", context={\"news\": news, \"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2933,7 +3009,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/exhibition.html\", context={\"id\": 1, \"user\": user}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2953,7 +3030,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"form/exhibition_edit.html\", context={\"id\": 1, \"user\": user, \"exhibition\": str(data)}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -2976,7 +3054,8 @@ " return {'ok': True}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3011,7 +3090,8 @@ " raise\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3064,7 +3144,8 @@ " if not doc:\n", " raise HTTPException(status_code=404, detail=\"Картина не найдена\")\n", " return RedirectResponse(url=f\"/paintings/{doc.get('_id')}\", status_code=301)" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3080,7 +3161,8 @@ "):\n", " await posts_collection.delete_one({'_id': ObjectId(post_id), 'user._id': current_user.get('_id')})\n", " return {'ok': True} \n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3140,7 +3222,8 @@ " except Exception as e:\n", " print(e)\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3210,7 +3293,8 @@ " background_tasks.add_task(update_social_post, doc_out)\n", " background_tasks.add_task(replace_new_medias, bson_clear(doc_out), links_media)\n", " return doc_out\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3311,7 +3395,8 @@ " return {\"post_medias\": post_medias}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3353,7 +3438,8 @@ " return doc_out\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3401,7 +3487,8 @@ " }\n", " doc_out = bson_clear(doc_out)\n", " return doc_out\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3420,7 +3507,8 @@ " return {'media': media}\n", " except Exception as e:\n", " raise HTTPException(status_code=500, detail=str(e))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3435,7 +3523,8 @@ "):\n", " await notify_collection.update_many({'user_id':user.get('_id')},{'$set':{'read':False}})\n", " return {}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3497,7 +3586,8 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3557,7 +3647,8 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3627,7 +3718,8 @@ " except Exception as exc:\n", " logging.error(str(exc))\n", " raise HTTPException(status_code=500, detail=str(exc))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3649,7 +3741,8 @@ " },{'vk': 0,'max': 0,'tg': 0,'fb': 0,'inst': 0}).sort('_id',-1).limit(1000):\n", " exhibitions.append(bson_clear(doc))\n", " return exhibitions" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3711,7 +3804,8 @@ " except Exception as e:\n", " logging.error(str(e))\n", " raise HTTPException(status_code=500, detail=str(e))" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3788,7 +3882,8 @@ " except Exception as e:\n", " logging.error(str(e))\n", " raise HTTPException(status_code=500, detail=str(e))" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3897,7 +3992,8 @@ " if file_length is not None:\n", " headers[\"Content-Length\"] = str(file_length)\n", " return StreamingResponse(iterator(), media_type=content_type, headers=headers)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3960,7 +4056,8 @@ " \n", " \n", " \"\"\"\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -3980,7 +4077,8 @@ " 'users': users \n", " }\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4096,7 +4194,8 @@ " \"all_city\": len(await users_collection.distinct(\"living_place\", filter={ 'roles': \"user\" }))\n", " }\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4112,7 +4211,8 @@ " if item:\n", " update_spec = {\"$push\": {\"tg\": result}}\n", " await mongo_client[item.get('db')][item.get('col')].update_one({'_id': ObjectId(item.get('_id'))}, update_spec)" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4130,7 +4230,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/social.html\", context={\"user\": user, 'socials': socials}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4173,7 +4274,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitation.html\", context={ \"user\": user, \"doc\": data, \"data\": posts}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4192,7 +4294,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitations.html\", context={ \"user\": user, \"data\": data, \"now\": datetime.now()}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4210,7 +4313,8 @@ "):\n", " await social_collection.update_one({'_id': ObjectId(id), 'user_id': user.get('_id')},{'$set': {key:check}})\n", " return {'ok': True}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4236,7 +4340,8 @@ "\n", " data = [doc async for doc in cursor]\n", " return data[0] if data else False" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4276,7 +4381,8 @@ " today_watch_count = await redis_client.incr(daily_key)\n", " return {\"totalViews\":total_watch_count,\"todayViews\":today_watch_count}\n", " return {\"totalViews\":0,\"todayViews\":0}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4309,8 +4415,8 @@ " field = 'user.username'\n", " if field == 'name':\n", " field = 'title'\n", - " if op == \"like\":\n", - " return {field: {\"$regex\": value, \"$options\": \"i\"}}\n", + " # if op == \"like\":\n", + " # return {field: {\"$regex\": value, \"$options\": \"i\"}}\n", " return {field: value}\n", " mongo_query = mql_to_mongo(mql)\n", " for post in [doc async for doc in posts_collection.find(mongo_query).sort({\"_id\":-1}).limit(per_page * page + 8)][per_page * page - per_page:per_page * page]:\n", @@ -4367,7 +4473,8 @@ " 'last_page': post_count / per_page,\n", " 'per_page': per_page\n", " }" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4385,7 +4492,8 @@ " return {\"statistics\":await users_collection.count_documents({ 'roles': \"user\" }),\"additional_stats\":len(await users_collection.distinct(\"living_place\", filter={ 'roles': \"user\" }))}\n", " else:\n", " return {\"statistics\":await posts_collection.count_documents({}),\"additional_stats\":await users_collection.count_documents({ 'roles': \"user\" })}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4412,7 +4520,8 @@ " user.pop('phone')\n", " user.pop('email')\n", " return {'data':bson_clear(user)}" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4437,7 +4546,8 @@ " post['name'] = post['title']\n", " post['media'] = photos\n", " return bson_clear(post)" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -4466,7 +4576,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/invitation/competition.html\", context={ \"user\": user, \"competition\": competition, \"req\": req}\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4486,7 +4597,8 @@ "\n", " await accept_invitations(invitations_id, posts_ids)\n", " return {'ok': True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4510,7 +4622,8 @@ " \"data\": data,\n", " }\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4551,7 +4664,8 @@ "# \"data\": data,\n", "# }\n", "# )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4591,7 +4705,8 @@ " \"data\": data,\n", " }\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4632,7 +4747,8 @@ " \"data\": data,\n", " }\n", " )" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4705,7 +4821,8 @@ " \"active_section\": \"delivery\"\n", " }\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4723,7 +4840,8 @@ " background_tasks.add_task(exhibition_send_invitations, exhibition_id)\n", " logging.info(f\"send exh inv {exhibition_id}\")\n", " return {\"ok\": True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4758,7 +4876,8 @@ " ]\n", " )\n", " return {\"ok\": True}\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4832,7 +4951,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibition catalog.html\", context={\"now\": datetime.now(), \"user\": user, \"galerists\": galerists, \"genres\": genres, \"living_places\": living_places, \"exhibition\": exhibition, \"posts\": posts}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4869,7 +4989,8 @@ " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibitions.html\", context={\"now\": datetime.now(), \"user\": user, \"data\": data}\n", " )\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -4908,7 +5029,8 @@ "\n", " with open(f'{filename_without_extension}.py', 'w') as f:\n", " f.write('\\n\\n'.join(app))\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4922,7 +5044,8 @@ "outputs": [], "source": [ "!uvicorn main:app --host 0.0.0.0 --port 8005 --reload" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4933,7 +5056,8 @@ "source": [ "import uvicorn\n", "uvicorn.run('main:app', host='0.0.0.0', port=8005, reload=True)\n" - ] + ], + "display_name": ".venv" }, { "cell_type": "markdown", @@ -4955,7 +5079,8 @@ "outputs": [], "source": [ "!pip freeze > req.txt" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4966,7 +5091,8 @@ "source": [ "import sys\n", "sys.executable" - ] + ], + "display_name": ".venv" }, { "cell_type": "code", @@ -4978,7 +5104,8 @@ "import sys\n", "sys.executable\n", "!{sys.executable} -m pip install -r requirements-api.txt" - ] + ], + "display_name": ".venv" } ], "metadata": { diff --git a/main.py b/main.py index 0c3d59f..025d6b8 100644 --- a/main.py +++ b/main.py @@ -1350,11 +1350,7 @@ async def restore_api( ]}) if not user: - # Безопасность: всегда возвращать одинаковое время ответа/структуру сообщения, если возможно - # Но для удобства использования мы можем сказать "не найден". - # Чтобы предотвратить перечисление, некоторые приложения всегда возвращают "OK", но отправляют письмо только если найдено. - # Здесь мы придерживаемся вашей оригинальной логики, но помните о риске перечисления. - raise HTTPException(status_code=404, detail="Пользователь с таким email не найден") + return {'ok': True} # 4. Генерация токена token = secrets.token_urlsafe(32) @@ -1378,13 +1374,13 @@ async def restore_api( # 7. Асинхронная отправка email try: email_task.notify.delay( - recipient=user['email'], - context={ + to_email=user['email'], + data={ 'link': reset_link, 'email': user['email'] }, subject='Восстановление пароля', - template_name='restore.html' + template='restore.html' ) except Exception as e: # Логирование ошибки @@ -3388,8 +3384,8 @@ async def get_posts( field = 'user.username' if field == 'name': field = 'title' - if op == "like": - return {field: {"$regex": value, "$options": "i"}} + # if op == "like": + # return {field: {"$regex": value, "$options": "i"}} return {field: value} mongo_query = mql_to_mongo(mql) for post in [doc async for doc in posts_collection.find(mongo_query).sort({"_id":-1}).limit(per_page * page + 8)][per_page * page - per_page:per_page * page]: From 613c1199decfbc60738d47cb8182f1a401698ecb7942552582b9c121b31bc635 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 04:30:14 -0400 Subject: [PATCH 11/59] fix --- main.ipynb | 4 ++-- main.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main.ipynb b/main.ipynb index 5a687df..c0be89d 100644 --- a/main.ipynb +++ b/main.ipynb @@ -4415,8 +4415,8 @@ " field = 'user.username'\n", " if field == 'name':\n", " field = 'title'\n", - " # if op == \"like\":\n", - " # return {field: {\"$regex\": value, \"$options\": \"i\"}}\n", + " if op == \"like\":\n", + " return {field: {\"$regex\": safe_strip(value), \"$options\": \"i\"}}\n", " return {field: value}\n", " mongo_query = mql_to_mongo(mql)\n", " for post in [doc async for doc in posts_collection.find(mongo_query).sort({\"_id\":-1}).limit(per_page * page + 8)][per_page * page - per_page:per_page * page]:\n", diff --git a/main.py b/main.py index 025d6b8..872b1af 100644 --- a/main.py +++ b/main.py @@ -3384,8 +3384,8 @@ async def get_posts( field = 'user.username' if field == 'name': field = 'title' - # if op == "like": - # return {field: {"$regex": value, "$options": "i"}} + if op == "like": + return {field: {"$regex": safe_strip(value), "$options": "i"}} return {field: value} mongo_query = mql_to_mongo(mql) for post in [doc async for doc in posts_collection.find(mongo_query).sort({"_id":-1}).limit(per_page * page + 8)][per_page * page - per_page:per_page * page]: From d4159eb1d2bbcaee331fc0a2e26175a25c535d458136a85c3c1b87b907e1bc40 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 08:11:57 -0400 Subject: [PATCH 12/59] fix --- templates/profile/invitations.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/profile/invitations.html b/templates/profile/invitations.html index 98adb82..dfd2191 100644 --- a/templates/profile/invitations.html +++ b/templates/profile/invitations.html @@ -45,8 +45,8 @@ href="{% if doc.get('exhibition') and doc.get('exhibition').get('tizer_link') %}{{doc.get('exhibition').tizer_link}}{% else %}/b/exhibition/{{ doc.get('exhibition').tizer_file_id }}{% endif %}" style="width: 100%;">Релиз выставки {% endif %} -

Принять условия нужно до {{doc.get('exhibition').datetime_start.strftime('%d.%m.%Y')}}

- {% if doc.get('accept') == False and now < doc.get('exhibition').datetime_start %} +

Принять условия нужно до {{doc.get('exhibition').date_finish.strftime('%d.%m.%Y')}}

+ {% if doc.get('accept') == False and now < doc.get('exhibition').date_finish %} Открыть {% else %} From f4f981233b67000b28e300de190ab6b629adb3aedf181a95f4df6c96c9ea7c8d Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 09:48:44 -0400 Subject: [PATCH 13/59] fix --- templates/profile/invitations.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/profile/invitations.html b/templates/profile/invitations.html index dfd2191..98adb82 100644 --- a/templates/profile/invitations.html +++ b/templates/profile/invitations.html @@ -45,8 +45,8 @@ href="{% if doc.get('exhibition') and doc.get('exhibition').get('tizer_link') %}{{doc.get('exhibition').tizer_link}}{% else %}/b/exhibition/{{ doc.get('exhibition').tizer_file_id }}{% endif %}" style="width: 100%;">Релиз выставки {% endif %} -

Принять условия нужно до {{doc.get('exhibition').date_finish.strftime('%d.%m.%Y')}}

- {% if doc.get('accept') == False and now < doc.get('exhibition').date_finish %} +

Принять условия нужно до {{doc.get('exhibition').datetime_start.strftime('%d.%m.%Y')}}

+ {% if doc.get('accept') == False and now < doc.get('exhibition').datetime_start %} Открыть {% else %} From 58316d87ec896917c6addc97617917ec3c11adf73416531c22cabd989a5644dc Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 10:25:19 -0400 Subject: [PATCH 14/59] feat --- main.ipynb | 5 +++++ main.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/main.ipynb b/main.ipynb index c0be89d..245ac9c 100644 --- a/main.ipynb +++ b/main.ipynb @@ -4948,6 +4948,11 @@ "\n", " galerists = [{\"_id\": uname, \"count\": counts_by_username.get(uname, '')} for uname in usernames]\n", " posts = [doc async for doc in posts_collection.find().sort('_id', -1).limit(32)]\n", + " d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list()\n", + " for post in posts:\n", + " for doc in d_posts:\n", + " if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')):\n", + " post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')})\n", " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibition catalog.html\", context={\"now\": datetime.now(), \"user\": user, \"galerists\": galerists, \"genres\": genres, \"living_places\": living_places, \"exhibition\": exhibition, \"posts\": posts}\n", " )\n" diff --git a/main.py b/main.py index 872b1af..9192fcc 100644 --- a/main.py +++ b/main.py @@ -3802,6 +3802,11 @@ async def profile_partner_exhibitions_catalog( galerists = [{"_id": uname, "count": counts_by_username.get(uname, '')} for uname in usernames] posts = [doc async for doc in posts_collection.find().sort('_id', -1).limit(32)] + d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list() + for post in posts: + for doc in d_posts: + if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')): + post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')}) return templates.TemplateResponse( request=request, name="profile/partner/exhibition catalog.html", context={"now": datetime.now(), "user": user, "galerists": galerists, "genres": genres, "living_places": living_places, "exhibition": exhibition, "posts": posts} ) From d84fb01ad8b7426f442c859e626d2324aee8b3e8d059fb63438608400317b4d5 Mon Sep 17 00:00:00 2001 From: vladislav Date: Tue, 1 Sep 2026 11:15:50 -0400 Subject: [PATCH 15/59] feat --- main.ipynb | 21 ++++++++++-- main.py | 12 +++++-- templates/exhibition/index.html | 42 ++++++++++++++++++++++- templates/profile/partner/exhibition.html | 41 ++++++++++++++++++++++ 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/main.ipynb b/main.ipynb index 245ac9c..0bd8dbf 100644 --- a/main.ipynb +++ b/main.ipynb @@ -3225,6 +3225,23 @@ ], "display_name": ".venv" }, + { + "cell_type": "code", + "execution_count": null, + "id": "8feec4b3", + "metadata": {}, + "outputs": [], + "source": [ + "@app.put(\"/api/post/{post_id}/sale\", response_model=dict)\n", + "async def sale_painting(\n", + " post_id: str,\n", + " current_user: Dict = Security(get_current_user, scopes=[\"create:posts\"])\n", + " ):\n", + " await posts_collection.update_one({'_id': ObjectId(post_id), 'user._id': current_user.get('_id')}, {'$set': {\"status\": \"Продано\"}})\n", + " return {'ok': True}" + ], + "display_name": ".venv" + }, { "cell_type": "code", "execution_count": null, @@ -4951,7 +4968,7 @@ " d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list()\n", " for post in posts:\n", " for doc in d_posts:\n", - " if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')):\n", + " if str(post.get('_id')) == doc.get('post_id') and post.get('status') != 'Продано' and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')):\n", " post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')})\n", " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibition catalog.html\", context={\"now\": datetime.now(), \"user\": user, \"galerists\": galerists, \"genres\": genres, \"living_places\": living_places, \"exhibition\": exhibition, \"posts\": posts}\n", @@ -4978,7 +4995,7 @@ " d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list()\n", " for post in posts:\n", " for doc in d_posts:\n", - " if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')):\n", + " if str(post.get('_id')) == doc.get('post_id') and post.get('status') != 'Продано' and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')):\n", " post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')})\n", " return templates.TemplateResponse(\n", " request=request, name=\"profile/partner/exhibition.html\", context={\"now\": datetime.now(), \"user\": user, \"exhibition\": exhibition, \"posts\": posts}\n", diff --git a/main.py b/main.py index 9192fcc..7c3d905 100644 --- a/main.py +++ b/main.py @@ -2398,6 +2398,14 @@ async def post_painting( raise HTTPException(status_code=500, detail=str(e)) +@app.put("/api/post/{post_id}/sale", response_model=dict) +async def sale_painting( + post_id: str, + current_user: Dict = Security(get_current_user, scopes=["create:posts"]) + ): + await posts_collection.update_one({'_id': ObjectId(post_id), 'user._id': current_user.get('_id')}, {'$set': {"status": "Продано"}}) + return {'ok': True} + @app.put("/api/post/{post_id}", response_model=dict) async def put_painting( background_tasks: BackgroundTasks, @@ -3805,7 +3813,7 @@ async def profile_partner_exhibitions_catalog( d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list() for post in posts: for doc in d_posts: - if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')): + if str(post.get('_id')) == doc.get('post_id') and post.get('status') != 'Продано' and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')): post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')}) return templates.TemplateResponse( request=request, name="profile/partner/exhibition catalog.html", context={"now": datetime.now(), "user": user, "galerists": galerists, "genres": genres, "living_places": living_places, "exhibition": exhibition, "posts": posts} @@ -3824,7 +3832,7 @@ async def profile_partner_exhibitions( d_posts = await delivery_collection.find({'post_id':{'$in':[str(i.get('_id')) for i in posts]}}).to_list() for post in posts: for doc in d_posts: - if str(post.get('_id')) == doc.get('post_id') and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')): + if str(post.get('_id')) == doc.get('post_id') and post.get('status') != 'Продано' and doc.get('receiver') and doc.get('receiver').get('_id') == str(user.get('_id')): post.update({'status':doc.get('status'), 'receiver': doc.get('receiver'), 'd_id':doc.get('_id')}) return templates.TemplateResponse( request=request, name="profile/partner/exhibition.html", context={"now": datetime.now(), "user": user, "exhibition": exhibition, "posts": posts} diff --git a/templates/exhibition/index.html b/templates/exhibition/index.html index 0b1c5b7..7ea08ad 100644 --- a/templates/exhibition/index.html +++ b/templates/exhibition/index.html @@ -95,6 +95,15 @@

{{post.title}}

+

{{post.city or ''}}

@@ -109,7 +118,38 @@ {% endfor %}
- + {# {%endif%} {% if doc.get('type_')=='paint' %} {% set statuses = ['Ожидает отправки', 'Возврат художнику'] %} @@ -220,14 +251,7 @@ {{ render_doc(doc) }} {% endfor %} {# Sticky bottom action bar #} -
- - -
+ +