add: auto link feature

This commit is contained in:
h z
2025-01-17 16:33:39 +00:00
parent 00f6895850
commit 26b64f8c15
5 changed files with 49 additions and 23 deletions

View File

@@ -2,10 +2,10 @@ FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
RUN apt-get update &&\
apt-get install -y default-mysql-client &&\
apt-get clean &&\
rm -rf /var/lib/apt/lists/*
#RUN apt-get update &&\
# apt-get install -y default-mysql-client &&\
# apt-get clean &&\
# rm -rf /var/lib/apt/lists/*
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r ./requirements.txt

View File

@@ -1,5 +1,4 @@
import shutil
import zipfile
from datetime import datetime
from flask import Blueprint, send_file, jsonify
@@ -60,6 +59,7 @@ def traverse(path_id, paths):
with open(f"{md.title}.mdmeta", "w") as meta_file:
meta_file.write(f"created_at: {md.created_at}\n")
meta_file.write(f"order: {md.order}\n")
meta_file.write(f"shortcut: {md.shortcut}\n")
children = [c for c in paths.values() if c.parent_id == path_id]
for child in children:
traverse(child.id, paths)

View File

@@ -1,6 +1,5 @@
from flask import Blueprint, request, jsonify
from sqlalchemy import or_
import api
from api import require_auth, etag_response
from contexts.RequestContext import RequestContext
@@ -29,6 +28,7 @@ def get_home():
if markdown is None:
return jsonify({}), 204
return jsonify(markdown.to_dict()), 200
@markdown_bp.route('/by_path/<int:path_id>', methods=['GET'])
@limiter.limit(api.get_rate_limit)
@etag_response
@@ -36,6 +36,7 @@ def get_markdowns_by_path(path_id):
with get_db() as session:
markdowns = session.query(Markdown).filter(Markdown.path_id == path_id).all()
return jsonify([md.to_dict() for md in markdowns]), 200
@markdown_bp.route('/get_index/<int:path_id>', methods=['GET'])
@limiter.limit(api.get_rate_limit)
@etag_response
@@ -66,11 +67,16 @@ def create_markdown():
title = data.get('title')
content = data.get('content')
path_id = data.get('path_id')
shortcut = data.get('shortcut', "")
if not title or not content:
return jsonify({"error": "missing required fields"}), 400
new_markdown = Markdown(title=title, content=content, path_id=path_id)
new_markdown = Markdown(title=title, content=content, path_id=path_id, shortcut=shortcut)
with get_db() as session:
try:
if shortcut != "":
r = session.query(Markdown).filter(Markdown.shortcut == shortcut).all()
if len(r) > 0:
return jsonify({"error": "duplicate shortcut"}), 400
session.add(new_markdown)
session.commit()
return jsonify(new_markdown.to_dict()), 201
@@ -89,10 +95,19 @@ def update_markdown(markdown_id):
if markdown is None:
return jsonify({"error": "file not found"}), 404
data = request.json
if data.get('shortcut', "") != "":
r = session.query(Markdown).filter(
Markdown.shortcut == data.get('shortcut')
).filter(
Markdown.id != markdown_id
).all()
if len(r) > 0:
return jsonify({"error": "duplicate shortcut"}), 400
if request.method == "PUT":
markdown.title = data.get('title')
markdown.content = data.get('content')
markdown.path_id = data.get('path_id')
markdown.shortcut = data.get('shortcut', '')
elif request.method == "PATCH":
if 'title' in data:
markdown.title = data.get('title')
@@ -100,6 +115,8 @@ def update_markdown(markdown_id):
markdown.content = data.get('content')
if 'path_id' in data:
markdown.path_id = data.get('path_id')
if 'shortcut' in data:
markdown.shortcut = data.get('shortcut')
session.commit()
return jsonify(markdown.to_dict()), 200
@@ -157,8 +174,16 @@ def move_backward(markdown_id):
@markdown_bp.route('/search/<string:keyword>', methods=['GET'])
@limiter.limit(api.get_rate_limit)
def search_markdowns(keyword):
with (get_db() as session):
with get_db() as session:
res = session.query(Markdown).filter(
or_(Markdown.title.like(keyword), Markdown.content.like(keyword))
).all()
return jsonify([md.to_dict() for md in res]), 200
@markdown_bp.route('/links', methods=['GET'])
@limiter.limit(api.get_rate_limit)
def get_links():
with get_db() as session:
mds = [md.to_dict() for md in session.query(Markdown).filter(Markdown.shortcut != "").all()]
links = [f"[{md['shortcut']}]: {md['id']}" for md in mds]
return jsonify(links), 200

View File

@@ -21,14 +21,14 @@ def get_db():
finally:
db.close()
def dump_db():
try:
os.environ['MYSQL_PWD'] = DB_PASSWORD
dump_cmd = f"mysqldump --no-tablespaces -h {DB_HOST} -P {DB_PORT} -u {DB_USER} {DB_NAME} > /app/dump/db_dump.sql"
subprocess.run(dump_cmd, shell=True, check=True)
except subprocess.CalledProcessError as e:
print(f"Failed to dump database: {e}")
raise e
# def dump_db():
# try:
# os.environ['MYSQL_PWD'] = DB_PASSWORD
# dump_cmd = f"mysqldump --no-tablespaces -h {DB_HOST} -P {DB_PORT} -u {DB_USER} {DB_NAME} > /app/dump/db_dump.sql"
# subprocess.run(dump_cmd, shell=True, check=True)
# except subprocess.CalledProcessError as e:
# print(f"Failed to dump database: {e}")
# raise e
def clear_db():
with engine.connect() as conn:
@@ -73,11 +73,11 @@ def init_payload():
def setup_db():
if DB_SCHEMA_UPDATED:
try:
dump_db()
print("[ x ] db dumped")
except Exception as e:
print(f"[ x ] Failed to dump database: {e}")
# try:
# dump_db()
# print("[ x ] db dumped")
# except Exception as e:
# print(f"[ x ] Failed to dump database: {e}")
clear_db()
print("[ x ] db cleared")
create_all()

View File

@@ -1,6 +1,6 @@
import uuid
from sqlalchemy import Column, Text, Integer, String, DateTime, ForeignKey, Float, text
from sqlalchemy import Column, Text, Integer, String, DateTime, ForeignKey, Float, text, UniqueConstraint
from db.models import Base
import datetime
@@ -12,7 +12,7 @@ class Markdown(Base):
created_at = Column(DateTime, default=datetime.datetime.utcnow)
path_id = Column(Integer, ForeignKey('path.id'), nullable=False)
order = Column(String(36), default=lambda: str(uuid.uuid4()))
shortcut = Column(String(36), default="")
def to_dict(self):
return {
'id': self.id,
@@ -21,6 +21,7 @@ class Markdown(Base):
'created_at': self.created_at,
'path_id': self.path_id,
'order': self.order,
'shortcut': self.shortcut,
}
__pay_load__ = {
'dev': [