diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 046ad83..fb71d7f 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,4 +1,4 @@
# These are supported funding model platforms
-github: [vastsa]
-custom: [https://share.lanol.cn]
+github: [ vastsa ]
+custom: [ https://share.lanol.cn ]
diff --git a/core/__init__.py b/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/core/database.py b/core/database.py
new file mode 100644
index 0000000..908222f
--- /dev/null
+++ b/core/database.py
@@ -0,0 +1,76 @@
+import datetime
+
+from sqlalchemy import Boolean, Column, Integer, String, DateTime, JSON, Text, select, insert, delete
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.ext.asyncio import create_async_engine
+from sqlalchemy.ext.asyncio.session import AsyncSession
+from settings import settings
+
+engine = create_async_engine(settings.DATABASE_URL)
+
+Base = declarative_base()
+
+
+class Options(Base):
+ __tablename__ = 'options'
+ id = Column(Integer, primary_key=True, index=True)
+ key = Column(String, unique=True, index=True)
+ value = Column(JSON)
+
+
+class Codes(Base):
+ __tablename__ = "codes"
+ id = Column(Integer, primary_key=True, index=True)
+ code = Column(String(10), unique=True, index=True)
+ key = Column(String(30), unique=True)
+ name = Column(String(500))
+ size = Column(Integer)
+ type = Column(String(20))
+ text = Column(Text)
+ used = Column(Boolean, default=False)
+ count = Column(Integer, default=-1)
+ use_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
+ exp_time = Column(DateTime, nullable=True)
+
+
+async def init_models():
+ async with engine.begin() as conn:
+ await conn.run_sync(Base.metadata.create_all)
+ if await conn.scalar(select(Options).filter(Options.key == 'INSTALL')) is None:
+ # 如果没有存在install,则清空表,并插入默认数据
+ await conn.execute(delete(table=Options))
+ await conn.execute(insert(table=Options, values=[
+ {'key': 'INSTALL', 'value': settings.VERSION},
+ {'key': 'BANNERS', 'value': settings.BANNERS},
+ {'key': 'ENABLE_UPLOAD', 'value': settings.ENABLE_UPLOAD},
+ {'key': 'MAX_DAYS', 'value': settings.MAX_DAYS},
+ {'key': 'ERROR_COUNT', 'value': settings.ERROR_COUNT},
+ {'key': 'ERROR_MINUTE', 'value': settings.ERROR_COUNT},
+ {'key': 'UPLOAD_COUNT', 'value': settings.UPLOAD_COUNT},
+ {'key': 'UPLOAD_MINUTE', 'value': settings.UPLOAD_MINUTE},
+ {'key': 'DELETE_EXPIRE_FILES_INTERVAL', 'value': settings.DELETE_EXPIRE_FILES_INTERVAL},
+ {'key': 'ADMIN_ADDRESS', 'value': settings.ADMIN_ADDRESS},
+ {'key': 'ADMIN_PASSWORD', 'value': settings.ADMIN_PASSWORD},
+ {'key': 'FILE_SIZE_LIMIT', 'value': settings.FILE_SIZE_LIMIT},
+ {'key': 'TITLE', 'value': settings.TITLE},
+ {'key': 'DESCRIPTION', 'value': settings.DESCRIPTION},
+ {'key': 'KEYWORDS', 'value': settings.KEYWORDS},
+ {'key': 'STORAGE_ENGINE', 'value': settings.STORAGE_ENGINE},
+ {'key': 'STORAGE_CONFIG', 'value': {}},
+ ]))
+ print(
+ f'初始化数据库成功!\n'
+ f'如您未配置.env文件,将为您随机生成信息\n'
+ f'您的后台地址为:/{settings.ADMIN_ADDRESS}\n'
+ f'您的管理员密码为:{settings.ADMIN_PASSWORD}\n'
+ f'请尽快修改后台信息!\n'
+ f'FileCodeBox https://github.com/vastsa/FileCodeBox'
+ )
+ else:
+ # 从数据库更新缓存中的setting
+ await settings.update(await conn.execute(select(Options).filter()))
+
+
+async def get_session():
+ async with AsyncSession(engine, expire_on_commit=False) as s:
+ yield s
diff --git a/depends.py b/core/depends.py
similarity index 86%
rename from depends.py
rename to core/depends.py
index 40a5f46..4282259 100644
--- a/depends.py
+++ b/core/depends.py
@@ -3,7 +3,7 @@ from datetime import datetime, timedelta
from fastapi import Header, HTTPException, Request
-import settings
+from settings import settings
async def admin_required(pwd: Union[str, None] = Header(default=None), request: Request = None):
@@ -11,6 +11,9 @@ async def admin_required(pwd: Union[str, None] = Header(default=None), request:
if pwd != settings.ADMIN_PASSWORD and not settings.ENABLE_UPLOAD:
raise HTTPException(status_code=403, detail='本站上传功能已关闭,仅管理员可用')
else:
+ print(settings.ADMIN_PASSWORD)
+ if settings.ADMIN_PASSWORD is None:
+ raise HTTPException(status_code=404, detail='您未设置管理员密码,无法使用此功能,请更新配置文件后,重启系统')
if not pwd or pwd != settings.ADMIN_PASSWORD:
raise HTTPException(status_code=401, detail="密码错误,请重新登录")
diff --git a/storage.py b/core/storage.py
similarity index 82%
rename from storage.py
rename to core/storage.py
index caf0978..1d88f4a 100644
--- a/storage.py
+++ b/core/storage.py
@@ -4,11 +4,19 @@ from datetime import datetime
from pathlib import Path
from typing import BinaryIO
from fastapi import UploadFile
-import settings
-import oss2
+
+from core.database import Codes
+from settings import settings
+
+if settings.STORAGE_ENGINE == 'aliyunsystem':
+ try:
+ import oss2
+ except ImportError:
+ os.system('pip install oss2')
+ import oss2
-class AliyunFileStore:
+class AliyunFileStorage:
def __init__(self):
auth = oss2.Auth(settings.KeyId, settings.KeySecret)
self.bucket = oss2.Bucket(auth, settings.OSS_ENDPOINT, settings.BUCKET_NAME)
@@ -21,10 +29,10 @@ class AliyunFileStore:
now = datetime.now()
path = f"FileCodeBox/upload/{now.year}/{now.month}/{now.day}"
text = f"{path}/{f'{key}.{ext}'}"
- return text
+ return f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/{text}"
- async def get_filepath(self, text: str):
- text = text.strip(f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/")
+ async def get_url(self, info: Codes):
+ text = info.text.strip(f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/")
url = self.bucket.sign_url('GET', text, settings.ACCESSTIME, slash_safe=True)
return url
@@ -47,10 +55,10 @@ class AliyunFileStore:
async def save_file(self, file: UploadFile, remote_filepath: str):
now = int(datetime.now().timestamp())
- upload_filepath = settings.DATA_ROOT+str(now)
+ upload_filepath = settings.DATA_ROOT + str(now)
await asyncio.to_thread(self._save, upload_filepath, file.file)
- self.upload_file(upload_filepath,remote_filepath)
- await asyncio.to_thread(os.remove,upload_filepath)
+ self.upload_file(upload_filepath, remote_filepath)
+ await asyncio.to_thread(os.remove, upload_filepath)
async def delete_files(self, texts):
tasks = [self.delete_file(text) for text in texts]
@@ -66,10 +74,14 @@ class FileSystemStorage:
self.DATA_ROOT = Path(settings.DATA_ROOT)
self.STATIC_URL = settings.STATIC_URL
self.NAME = "filesystem"
+ self.DOWN_PATH = '/select'
async def get_filepath(self, text: str):
return self.DATA_ROOT / text.lstrip(self.STATIC_URL + '/')
+ async def get_url(self, info: Codes):
+ return f'{self.DOWN_PATH}?code={info.code}'
+
async def get_text(self, file: UploadFile, key: str):
ext = file.filename.split('.')[-1]
now = datetime.now()
@@ -122,5 +134,5 @@ class FileSystemStorage:
STORAGE_ENGINE = {
"filesystem": FileSystemStorage,
- "aliyunsystem": AliyunFileStore
+ "aliyunsystem": AliyunFileStorage
}
diff --git a/utils.py b/core/utils.py
similarity index 91%
rename from utils.py
rename to core/utils.py
index 6290c40..8b0f949 100644
--- a/utils.py
+++ b/core/utils.py
@@ -3,10 +3,10 @@ import random
import asyncio
from sqlalchemy import or_, select, delete
from sqlalchemy.ext.asyncio.session import AsyncSession
-import settings
-from database import Codes, engine
-from depends import IPRateLimit
-from storage import STORAGE_ENGINE
+from .database import Codes, engine
+from .depends import IPRateLimit
+from .storage import STORAGE_ENGINE
+from settings import settings
storage = STORAGE_ENGINE[settings.STORAGE_ENGINE]()
diff --git a/database.py b/database.py
deleted file mode 100644
index 53c9b9c..0000000
--- a/database.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import datetime
-from sqlalchemy import Boolean, Column, Integer, String, DateTime, JSON, Text
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.ext.asyncio import create_async_engine
-from sqlalchemy.ext.asyncio.session import AsyncSession
-import settings
-
-engine = create_async_engine(settings.DATABASE_URL)
-
-Base = declarative_base()
-
-
-async def init_models():
- async with engine.begin() as conn:
- await conn.run_sync(Base.metadata.create_all)
-
-
-async def get_session():
- async with AsyncSession(engine, expire_on_commit=False) as s:
- yield s
-
-
-class Values(Base):
- __tablename__ = 'values'
- id = Column(Integer, primary_key=True, index=True)
- key = Column(String, unique=True)
- value = Column(JSON)
-
-
-class Codes(Base):
- __tablename__ = "codes"
- id = Column(Integer, primary_key=True, index=True)
- code = Column(String(10), unique=True, index=True)
- key = Column(String(30), unique=True, index=True)
- name = Column(String(500))
- size = Column(Integer)
- type = Column(String(20))
- text = Column(Text)
- used = Column(Boolean, default=False)
- count = Column(Integer, default=-1)
- use_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
- exp_time = Column(DateTime, nullable=True)
diff --git a/main.py b/main.py
index 1172008..43fd831 100644
--- a/main.py
+++ b/main.py
@@ -1,29 +1,18 @@
import datetime
import uuid
-import asyncio
from pathlib import Path
-import os
+from sqlalchemy import select, func, update
+from sqlalchemy.ext.asyncio import AsyncSession
+from starlette.requests import Request
+from starlette.responses import HTMLResponse, FileResponse
+from starlette.staticfiles import StaticFiles
-try:
- from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks
- from starlette.requests import Request
- from starlette.responses import HTMLResponse, FileResponse
- from starlette.staticfiles import StaticFiles
- from sqlalchemy import select, update, func
- from sqlalchemy.ext.asyncio.session import AsyncSession
-except ImportError:
- os.system("pip install -r requirements.txt")
- from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks
- from starlette.requests import Request
- from starlette.responses import HTMLResponse, FileResponse
- from starlette.staticfiles import StaticFiles
- from sqlalchemy import select, update, func
- from sqlalchemy.ext.asyncio.session import AsyncSession
+from core.utils import error_ip_limit, upload_ip_limit, get_code, storage
+from core.depends import admin_required
+from settings import settings
+from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks
-import settings
-from utils import delete_expire_files, storage, get_code, error_ip_limit, upload_ip_limit
-from database import get_session, Codes, init_models, Values
-from depends import admin_required
+from core.database import init_models, Options, Codes, get_session
# 实例化FastAPI
app = FastAPI(debug=settings.DEBUG, docs_url=None, redoc_url=None)
@@ -34,28 +23,30 @@ if not DATA_ROOT.exists():
DATA_ROOT.mkdir(parents=True)
# 静态文件夹,这个固定就行了,静态资源都放在这里
-app.mount(settings.STATIC_URL, StaticFiles(directory='./static'), name="static")
+app.mount('/static', StaticFiles(directory='./static'), name="static")
+# 首页页面
+index_html = open('templates/index.html', 'r', encoding='utf-8').read() \
+ .replace('{{title}}', settings.TITLE) \
+ .replace('{{description}}', settings.DESCRIPTION) \
+ .replace('{{keywords}}', settings.KEYWORDS) \
+ .replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT))
+# 管理页面
+admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \
+ .replace('{{title}}', settings.TITLE) \
+ .replace('{{description}}', settings.DESCRIPTION) \
+ .replace('{{admin_address}}', settings.ADMIN_ADDRESS) \
+ .replace('{{keywords}}', settings.KEYWORDS)
@app.on_event('startup')
async def startup():
# 初始化数据库
await init_models()
- # 启动后台任务,不定时删除过期文件
- asyncio.create_task(delete_expire_files())
-# 首页页面
-index_html = open('templates/index.html', 'r', encoding='utf-8').read() \
- .replace('{{title}}', settings.TITLE) \
- .replace('{{description}}', settings.DESCRIPTION) \
- .replace('{{keywords}}', settings.KEYWORDS) \
- .replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT)) \
- # 管理页面
-admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \
- .replace('{{title}}', settings.TITLE) \
- .replace('{{description}}', settings.DESCRIPTION) \
- .replace('{{keywords}}', settings.KEYWORDS)
+@app.get('/')
+async def index():
+ return HTMLResponse(index_html)
@app.get(f'/{settings.ADMIN_ADDRESS}', description='管理页面')
@@ -65,26 +56,19 @@ async def admin():
@app.post(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='查询数据库列表')
async def admin_post(page: int = Form(default=1), size: int = Form(default=10), s: AsyncSession = Depends(get_session)):
- codes = (await s.execute(select(Codes).offset((page - 1) * size).limit(size))).scalars().all()
- total = (await s.execute(select(func.count(Codes.id)))).scalar()
- return {'detail': '查询成功', 'data': codes, 'paginate': {
- 'page': page,
- 'size': size,
- 'total': total
- }}
+ return {
+ 'detail': '查询成功',
+ 'data': (await s.execute(select(Codes).offset((page - 1) * size).limit(size))).scalars().all(),
+ 'paginate': {
+ 'page': page,
+ 'size': size,
+ 'total': (await s.execute(select(func.count(Codes.id)))).scalar()
+ }}
-@app.patch(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='修改数据库数据')
-async def admin_patch(request: Request, s: AsyncSession = Depends(get_session)):
- # 从数据库获取系统配置
- # 如果不存在config这个key,就创建一个
- value = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none()
- if not value:
- s.add(Values(key='config', value=await request.json()))
- else:
- await s.execute(update(Values).where(Values.key == 'config').values(value=await request.json()))
- await s.commit()
- return {'detail': '修改成功'}
+# @app.patch(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='修改数据库数据')
+# async def admin_patch(request: Request, s: AsyncSession = Depends(get_session)):
+# return {'detail': '修改成功'}
@app.delete(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='删除数据库记录')
@@ -103,11 +87,9 @@ async def admin_delete(code: str, s: AsyncSession = Depends(get_session)):
return {'detail': '删除成功'}
-@app.get('/config', description='获取系统配置', dependencies=[Depends(admin_required)])
+@app.get(f'/{settings.ADMIN_ADDRESS}/config', description='获取系统配置', dependencies=[Depends(admin_required)])
async def config(s: AsyncSession = Depends(get_session)):
- # 从数据库获取系统配置
- data = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none()
- return {'detail': '获取成功', 'data': data.value if data else {'banners': []}}
+ return {'detail': '获取成功', 'data': (await s.execute(select(Options))).scalars().all()}
@app.get('/')
@@ -127,57 +109,25 @@ async def index(code: str, ip: str = Depends(error_ip_limit), s: AsyncSession =
await s.execute(update(Codes).where(Codes.id == info.id).values(count=info.count - 1))
await s.commit()
if info.type != 'text':
- if settings.STORAGE_ENGINE == 'filesystem':
- info.text = f'/select?code={code}'
- return {
- 'detail': f'取件成功,文件将在{settings.DELETE_EXPIRE_FILES_INTERVAL}分钟后删除',
- 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code}
- }
- elif settings.STORAGE_ENGINE == 'aliyunsystem':
- info.text = await storage.get_filepath(info.text)
- return {
- 'detail': f'取件成功,链接将在{settings.ACCESSTIME}秒后失效',
- 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code}
- }
+ info.text = await storage.get_url(info)
+ return {
+ 'detail': f'取件成功,文件将在{settings.DELETE_EXPIRE_FILES_INTERVAL}分钟后删除',
+ 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code}
+ }
+
+
+@app.post(f'/{settings.ADMIN_ADDRESS}/download', dependencies=[Depends(admin_required)])
+async def admin_download_file(filetext: str):
+ return await storage.get_text(filetext)
-@app.post('/adminDownloadFile',dependencies=[Depends(admin_required)], description='管理员获取资源链接')
-async def admindownloadfile(filetext: str, s: AsyncSession = Depends(get_session)):
- if storage.STORAGE_ENGINE == 'aliyunsystem':
- filetext = await storage.get_filepath(filetext)
- return {
- 'detail': f'获取文件链接成功,链接将在{settings.ACCESSTIME}秒后失效',
- 'fileURL': filetext
- }
- elif storage.STORAGE_ENGINE == 'filesystem':
- return {
- 'detail': f'获取文件链接成功',
- 'fileURL':filetext
- }
@app.get('/banner')
-async def banner(request: Request, s: AsyncSession = Depends(get_session)):
+async def banner(request: Request):
# 数据库查询config
- config = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none()
- # 如果存在config,就返回config的value
- if config and config.value.get('banners'):
- return {
- 'detail': '查询成功',
- 'data': config.value['banners'],
- 'enable': request.headers.get('pwd', '') == settings.ADMIN_PASSWORD or settings.ENABLE_UPLOAD,
- }
- # 如果不存在config,就返回默认的banner
return {
- 'detail': 'banner',
+ 'detail': '查询成功',
+ 'data': settings.BANNERS,
'enable': request.headers.get('pwd', '') == settings.ADMIN_PASSWORD or settings.ENABLE_UPLOAD,
- 'data': [{
- 'text': 'FileCodeBox',
- 'url': 'https://github.com/vastsa/FileCodeBox',
- 'src': '/static/banners/img_1.png'
- }, {
- 'text': 'FileCodeBox',
- 'url': 'https://www.lanol.cn',
- 'src': '/static/banners/img_2.png'
- }]
}
@@ -196,10 +146,7 @@ async def get_file(code: str, ip: str = Depends(error_ip_limit), s: AsyncSession
# 如果是文件,返回文件
else:
filepath = await storage.get_filepath(info.text)
- if settings.STORAGE_ENGINE == 'filesystem':
- return FileResponse(filepath, filename=info.name)
- else:
- return {'detail': '查询成功', 'data': filepath}
+ return FileResponse(filepath, filename=info.name)
@app.post('/share', dependencies=[Depends(admin_required)], description='分享文件')
@@ -229,10 +176,7 @@ async def share(background_tasks: BackgroundTasks, text: str = Form(default=None
background_tasks.add_task(storage.save_file, file, _text)
else:
size, _text, _type, name = len(text), text, 'text', '文本分享'
- if settings.STORAGE_ENGINE == 'aliyunsystem':
- _text = f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/"+_text
- info = Codes(code=code, text=_text, size=size, type=_type, name=name, count=exp_count, exp_time=exp_time, key=key)
- s.add(info)
+ s.add(Codes(code=code, text=_text, size=size, type=_type, name=name, count=exp_count, exp_time=exp_time, key=key))
await s.commit()
upload_ip_limit.add_ip(ip)
return {
diff --git a/settings.py b/settings.py
index 8788f9b..9cc1b66 100644
--- a/settings.py
+++ b/settings.py
@@ -1,63 +1,71 @@
+import uuid
from starlette.config import Config
-import os
-import shutil
# 配置文件.env
# 请将.env移动至data目录,方便docker部署
-# 判断根目录下是否存在.env文件
-if os.path.exists('.env'):
- # 将文件复制到data目录
- shutil.copy('.env', 'data/.env')
-
config = Config("data/.env")
-# 是否开启DEBUG模式
-DEBUG = config('DEBUG', cast=bool, default=False)
-# 端口
-PORT = config('PORT', cast=int, default=12345)
-# Sqlite数据库文件
-DATABASE_FILE = config('DATABASE_FILE', cast=str, default='data/database.db')
-# Sqlite套接字
-DATABASE_URL = config('DATABASE_URL', cast=str, default=f"sqlite+aiosqlite:///{DATABASE_FILE}")
-# 数据存储文件夹,文件就不暴露在静态资源里面了
-DATA_ROOT = './data/' + config('DATA_ROOT', cast=str, default=f"static")
-# 静态文件夹URL
-STATIC_URL = config('STATIC_URL', cast=str, default="/static")
-# 开启上传
-ENABLE_UPLOAD = config('ENABLE_UPLOAD', cast=bool, default=True)
-# 最长天数
-MAX_DAYS = config('MAX_DAYS', cast=int, default=7)
-# 错误次数
-ERROR_COUNT = config('ERROR_COUNT', cast=int, default=5)
-# 错误限制分钟数
-ERROR_MINUTE = config('ERROR_MINUTE', cast=int, default=10)
-# 上传次数
-UPLOAD_COUNT = config('UPLOAD_COUNT', cast=int, default=60)
-# 上传限制分钟数
-UPLOAD_MINUTE = config('UPLOAD_MINUTE', cast=int, default=1)
-# 删除过期文件的间隔(分钟)
-DELETE_EXPIRE_FILES_INTERVAL = config('DELETE_EXPIRE_FILES_INTERVAL', cast=int, default=10)
-# 管理地址
-ADMIN_ADDRESS = config('ADMIN_ADDRESS', cast=str, default="admin")
-# 管理密码
-ADMIN_PASSWORD = config('ADMIN_PASSWORD', cast=str, default="admin")
-# 文件大小限制,默认10MB
-FILE_SIZE_LIMIT = config('FILE_SIZE_LIMIT', cast=int, default=10) * 1024 * 1024
-# 网站标题
-TITLE = config('TITLE', cast=str, default="文件快递柜")
-# 网站描述
-DESCRIPTION = config('DESCRIPTION', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件等文件")
-# 网站关键词
-KEYWORDS = config('KEYWORDS', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件等文件")
-# 存储引擎:['aliyunsystem','filesystem']
-STORAGE_ENGINE = config('STORAGE_ENGINE', cast=str, default="filesystem")
-# 如果使用阿里云OSS的话需要创建如下参数
-# 阿里云账号AccessKey
-KeyId = config('KeyId', cast=str, default="阿里云账号AccessKey")
-# 阿里云账号AccessKeySecret
-KeySecret = config('KeySecret', cast=str, default="阿里云账号AccessKeySecret")
-# 阿里云OSS Bucket的地域节点
-OSS_ENDPOINT = config('BUCKET_URL', cast=str, default="阿里云OSS Bucket的地域节点")
-# 阿里云OSS Bucket的BucketName
-BUCKET_NAME = config('BUCKET_NAME', cast=str, default="阿里云OSS Bucket的BucketName")
-# 访问文件的读取时长(s)
-ACCESSTIME = config('ACCESSTIME', cast=int, default=60)
+
+
+class Settings:
+ # 项目版本
+ VERSION: str = config("VERSION", default="1.6")
+ # 是否开启DEBUG模式
+ DEBUG = config('DEBUG', cast=bool, default=False)
+ # 端口
+ PORT = config('PORT', cast=int, default=12345)
+ # Sqlite数据库文件
+ DATABASE_FILE = config('DATABASE_FILE', cast=str, default='data/database.db')
+ # Sqlite套接字
+ DATABASE_URL = config('DATABASE_URL', cast=str, default=f"sqlite+aiosqlite:///{DATABASE_FILE}")
+ # 数据存储文件夹,文件就不暴露在静态资源里面了
+ DATA_ROOT = './data/' + config('DATA_ROOT', cast=str, default=f"static")
+ # 静态文件夹URL
+ STATIC_URL = config('STATIC_URL', cast=str, default="/static")
+ # 开启上传
+ ENABLE_UPLOAD = config('ENABLE_UPLOAD', cast=bool, default=True)
+ # 最长天数
+ MAX_DAYS = config('MAX_DAYS', cast=int, default=7)
+ # 错误次数
+ ERROR_COUNT = config('ERROR_COUNT', cast=int, default=5)
+ # 错误限制分钟数
+ ERROR_MINUTE = config('ERROR_MINUTE', cast=int, default=10)
+ # 上传次数
+ UPLOAD_COUNT = config('UPLOAD_COUNT', cast=int, default=60)
+ # 上传限制分钟数
+ UPLOAD_MINUTE = config('UPLOAD_MINUTE', cast=int, default=1)
+ # 删除过期文件的间隔(分钟)
+ DELETE_EXPIRE_FILES_INTERVAL = config('DELETE_EXPIRE_FILES_INTERVAL', cast=int, default=10)
+ # 管理地址
+ ADMIN_ADDRESS = config('ADMIN_ADDRESS', cast=str, default=uuid.uuid4().hex)
+ # 管理密码
+ ADMIN_PASSWORD = config('ADMIN_PASSWORD', cast=str, default=uuid.uuid4().hex)
+ # 文件大小限制,默认10MB
+ FILE_SIZE_LIMIT = config('FILE_SIZE_LIMIT', cast=int, default=10) * 1024 * 1024
+ # 网站标题
+ TITLE = config('TITLE', cast=str, default="文件快递柜")
+ # 网站描述
+ DESCRIPTION = config('DESCRIPTION', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件")
+ # 网站关键词
+ KEYWORDS = config('KEYWORDS', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件")
+ # 存储引擎:['aliyunsystem','filesystem']
+ STORAGE_ENGINE = config('STORAGE_ENGINE', cast=str, default="filesystem")
+ # 存储引擎配置
+ STORAGE_CONFIG = {}
+ # Banners
+ BANNERS = [{
+ 'text': 'FileCodeBox',
+ 'url': 'https://github.com/vastsa/FileCodeBox',
+ 'src': '/static/banners/img_1.png'
+ }, {
+ 'text': 'LanBlog',
+ 'url': 'https://www.lanol.cn',
+ 'src': '/static/banners/img_2.png'
+ }]
+
+ async def update(self, options) -> None:
+ for i, key, value in options:
+ if hasattr(self, key):
+ setattr(self, key, value)
+
+
+settings = Settings()
diff --git a/templates/admin.html b/templates/admin.html
index ccd006a..09efc1c 100644
--- a/templates/admin.html
+++ b/templates/admin.html
@@ -126,12 +126,11 @@
if (pwd) {
login = true;
this.pwd = pwd;
- axios.get('/config', {
+ axios.get('{{admin_address}}/config', {
headers: {
pwd: pwd
}
}).then(res => {
- console.log(res.data.data)
this.config = res.data.data;
});
this.loginAdmin();
diff --git a/templates/index.html b/templates/index.html
index 68a7349..72111dc 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -11,7 +11,7 @@
-
+