Compare commits

..

No commits in common. "dc1f156025246745d80382fe0e5a069bcce6ec85" and "478804e414a5756fbc1582967104f6da827014c8" have entirely different histories.

5 changed files with 25 additions and 82 deletions

View file

@ -1,4 +1,4 @@
FROM python:3.13.0
FROM python:3
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt

View file

@ -1,33 +0,0 @@
# LiteY
軽量な掲示板です
## デバッグの開始
依存関係をインストールします
```bash
pip install -r requirements.txt
```
データベースを起動します
```bash
docker run --detach \
--name litey-mongo-debug \
--volume litey-mongo-debug:/data/db \
--publish 27017:27017 \
mongo
```
サーバーを起動します
```bash
fastapi dev
```
## デプロイ
今すぐデプロイ!
- https://litey.trade/

64
app.py
View file

@ -1,12 +1,11 @@
from typing import Callable, Awaitable, Optional, List
from datetime import datetime, timezone, timedelta
from datetime import datetime, timezone
from pathlib import Path
from uuid import uuid4
from os import environ
from urllib.parse import urlparse
from base64 import b64encode
from re import escape, compile, IGNORECASE
from pprint import pprint
from requests import get
from fastapi import FastAPI, Request, Response, status
@ -14,7 +13,6 @@ from fastapi.responses import JSONResponse, Response, PlainTextResponse, FileRes
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from pymongo import MongoClient, DESCENDING
from contextlib import asynccontextmanager
# Jinja2
@ -22,7 +20,7 @@ def ip_to_uid(ip: Optional[str]) -> str:
if not ip:
return "-"
return b64encode(ip.encode("utf-8")).decode("utf-8")[-11:]
return b64encode(ip.encode("utf-8")).decode("utf-8")[:11]
def replace_ng_words(src: str, ng_words: List[str]) -> str:
result = src
@ -41,39 +39,21 @@ def content_to_linksets(content: str) -> str:
groups = pattern.findall(content)
return "\n".join(groups)
def is_over_n_hours(src: datetime, hours: int) -> bool:
now = datetime.now()
return now - src.replace(tzinfo=None) > timedelta(hours=hours)
# 初期化
ctx = {}
templates = Jinja2Templates("templates")
@asynccontextmanager
async def lifespan(app: FastAPI):
ctx["templates"] = Jinja2Templates("templates")
templates.env.filters["ip_to_uid"] = ip_to_uid
templates.env.filters["replace_ng_words"] = replace_ng_words
templates.env.filters["content_to_linksets"] = content_to_linksets
ctx["templates"].env.filters["ip_to_uid"] = ip_to_uid
ctx["templates"].env.filters["replace_ng_words"] = replace_ng_words
ctx["templates"].env.filters["content_to_linksets"] = content_to_linksets
ctx["templates"].env.filters["fromisoformat"] = datetime.fromisoformat
ctx["templates"].env.filters["is_over_n_hours"] = is_over_n_hours
mongo_client = MongoClient(
environ.get("MONGO_URI", "mongodb://127.0.0.1:27017/"),
username=environ.get("MONGO_USER"),
password=environ.get("MONGO_PASSWORD")
)
ctx["mongo_client"] = MongoClient(
environ.get("MONGO_URI", "mongodb://127.0.0.1:27017/"),
username=environ.get("MONGO_USER"),
password=environ.get("MONGO_PASSWORD")
)
#uuid重複する考えすぎ
#ctx["mongo_client"].litey.notes.create_index("id", unique=True)
ctx["mongo_client"].litey.ngs.create_index("word", unique=True)
pprint(ctx)
yield
ctx["mongo_client"].close()
ctx.clear()
mongo_client.litey.ngs.create_index("word", unique=True)
# スニペット
@ -115,18 +95,18 @@ def get_ip(req: Request) -> str:
def get_litey_notes(id: str = None) -> List[dict]:
if not id:
cursor = ctx["mongo_client"].litey.notes.find({}, { "_id": False }).sort("date", DESCENDING)
cursor = mongo_client.litey.notes.find({}, { "_id": False }).sort("date", DESCENDING)
return list(cursor)
return ctx["mongo_client"].litey.notes.find_one({ "id": id }, { "_id": False })
return mongo_client.litey.notes.find_one({ "id": id }, { "_id": False })
def get_ng_words() -> List[str]:
cursor = ctx["mongo_client"].litey.ngs.find({}, { "_id": False })
cursor = mongo_client.litey.ngs.find({}, { "_id": False })
return [ng["word"] for ng in list(cursor) if "word" in ng]
# FastAPI
app = FastAPI(lifespan=lifespan)
app = FastAPI()
@app.middleware("http")
async def cors_handler(req: Request, call_next: Callable[[Request], Awaitable[Response]]):
@ -152,7 +132,7 @@ async def api_get(id: str = None):
@app.post("/api/litey/post")
async def api_post(item: LiteYItem, req: Request):
ctx["mongo_client"].litey.notes.insert_one({
mongo_client.litey.notes.insert_one({
"id": str(uuid4()),
"content": item.content,
"date": datetime.now().astimezone(timezone.utc).isoformat(),
@ -163,9 +143,7 @@ async def api_post(item: LiteYItem, req: Request):
@app.post("/api/litey/delete")
async def api_delete(item: LiteYDeleteItem):
ctx["mongo_client"].litey.notes.delete_one({
"id": item.id
})
mongo_client.litey.notes.delete_one({ "id": item.id })
return PlainTextResponse("OK")
@ -192,7 +170,7 @@ async def api_ng_get():
@app.post("/api/ng/post")
async def api_ng_post(item: NGItem):
ctx["mongo_client"].litey.ngs.insert_one({
mongo_client.litey.ngs.insert_one({
"word": item.word
})
@ -200,7 +178,7 @@ async def api_ng_post(item: NGItem):
@app.post("/api/ng/delete")
async def api_ng_delete(item: NGItem):
ctx["mongo_client"].litey.ngs.delete_one({
mongo_client.litey.ngs.delete_one({
"word": item.word
})
@ -208,7 +186,7 @@ async def api_ng_delete(item: NGItem):
@app.get("/")
async def home(req: Request):
res = ctx["templates"].TemplateResponse(req, "index.html", {
res = templates.TemplateResponse(req, "index.html", {
"notes": get_litey_notes(),
"ng_words": get_ng_words()
})

View file

@ -1,4 +1,4 @@
requests==2.32.3
fastapi[standard]==0.115.5
pymongo==4.10.1
fastapi==0.111.0
pymongo==4.7.3
Jinja2==3.1.4

View file

@ -18,9 +18,7 @@
<div>{{ note.content | replace_ng_words(ng_words) }}</div>
<div id="attachments" data-linksets="{{ note.content | content_to_linksets | urlencode() }}"></div>
<code id="date" data-date="{{ note.date | urlencode() }}"></code>
{% if not ("/ninja" in note.content and not note.date | fromisoformat | is_over_n_hours(72)) %}
<input type="submit" value="削除" onclick="noteDelete(this);" data-id="{{ note.id | urlencode() }}" data-preview="{{ note.content | urlencode() }}">
{% endif %}
<input type="submit" value="削除" onclick="noteDelete(this);" data-id="{{ note.id | urlencode() }}" data-preview="{{ note.content | urlencode() }}">
</div>
{% endfor %}
</body>