发送图片时支持自动上传图片, 支持sm.msaws s3服务

This commit is contained in:
KimigaiiWuyi 2023-10-31 04:18:08 +08:00
parent c541543035
commit bdcb830d85
9 changed files with 986 additions and 582 deletions

View File

@ -12,7 +12,10 @@ from gsuid_core.models import Message
from gsuid_core.data_store import image_res
from gsuid_core.message_models import Button
from gsuid_core.utils.image.convert import text2pic
from gsuid_core.utils.plugins_config.gs_config import core_plugins_config
from gsuid_core.utils.plugins_config.gs_config import (
pic_upload_config,
core_plugins_config,
)
R_enabled = core_plugins_config.get_config('AutoAddRandomText').data
R_text = core_plugins_config.get_config('RandomText').data
@ -20,6 +23,18 @@ is_text2pic = core_plugins_config.get_config('AutoTextToPic').data
text2pic_limit = core_plugins_config.get_config('TextToPicThreshold').data
enable_pic_srv = core_plugins_config.get_config('EnablePicSrv').data
pic_srv = core_plugins_config.get_config('PicSrv').data
SERVER = pic_upload_config.get_config('PicUploadServer').data
if SERVER == 'smms':
from gsuid_core.utils.upload.smms import SMMS
pclient = SMMS()
elif SERVER == 's3':
from gsuid_core.utils.upload.s3 import S3
pclient = S3()
else:
pclient = None
class MessageSegment:
@ -153,17 +168,29 @@ async def convert_message(
message = [message]
elif isinstance(message, str):
if message.startswith('base64://'):
img = Image.open(BytesIO(b64decode(message[9:])))
bio = BytesIO(b64decode(message[9:]))
img = Image.open(bio)
img_url = None
if pclient is not None:
img_url = await pclient.upload(f'{uuid.uuid4()}.jpg', bio)
message = [
MessageSegment.image(message),
MessageSegment.image(img_url if img_url else message),
MessageSegment.image_size(img.size),
]
else:
message = [MessageSegment.text(message)]
elif isinstance(message, bytes):
img = Image.open(BytesIO(message))
bio = BytesIO(message)
img = Image.open(bio)
img_url = None
if pclient is not None:
img_url = await pclient.upload(f'{uuid.uuid4()}.jpg', bio)
message = [
MessageSegment.image(message),
MessageSegment.image(img_url if img_url else message),
MessageSegment.image_size(img.size),
]
elif isinstance(message, List):

View File

@ -61,5 +61,4 @@ CONIFG_DEFAULT: Dict[str, GSC] = {
'AutoUpdateDep': GsBoolConfig('自动更新依赖', '更新插件时将会自动更新依赖', False),
'EnablePicSrv': GsBoolConfig('将图片转链接发送(需公网)', '发送图片转链接', False),
'PicSrv': GsStrConfig('将图片转链接发送(需公网)', '发送图片转链接', ''),
'PicUpload': GsBoolConfig('自动上传图片', '发送图片是将会自动上传', False),
}

View File

@ -8,6 +8,7 @@ from gsuid_core.data_store import get_res_path
from .models import GSC, GsBoolConfig
from .config_default import CONIFG_DEFAULT
from .pic_server_config import PIC_UPLOAD_CONIFG
class StringConfig:
@ -118,3 +119,7 @@ all_config_list: Dict[str, StringConfig] = {}
core_plugins_config = StringConfig(
'Core', get_res_path() / 'core_config.json', CONIFG_DEFAULT
)
pic_upload_config = StringConfig(
'Core_Pic', get_res_path() / 'pic_upload_config.json', PIC_UPLOAD_CONIFG
)

View File

@ -0,0 +1,14 @@
from typing import Dict
from .models import GSC, GsStrConfig, GsBoolConfig
PIC_UPLOAD_CONIFG: Dict[str, GSC] = {
'PicUpload': GsBoolConfig('自动上传图片', '发送图片时将会自动上传', False),
'PicUploadServer': GsStrConfig('上传图片方式', '可选s3或smms', 'smms'),
'smms_token': GsStrConfig('sm.ms_token', 'sm.ms的token', ''),
's3_endpoint': GsStrConfig('s3_endpoint', '终结点url', ''),
's3_access_key': GsStrConfig('s3_access_key', 'AK', ''),
's3_secret_key': GsStrConfig('s3_secret_key', 'SK', ''),
's3_bucket': GsStrConfig('s3_bucket', 'Bucket', ''),
's3_region': GsStrConfig('s3_region', 'Region', ''),
}

View File

@ -0,0 +1,47 @@
import asyncio
from io import BytesIO
import aioboto3
from gsuid_core.logger import logger
from gsuid_core.utils.plugins_config.gs_config import pic_upload_config
SERVER = pic_upload_config.get_config('PicUploadServer').data
END_POINT = pic_upload_config.get_config('s3_endpoint').data
ACCESS_KEY = pic_upload_config.get_config('s3_access_key').data
SECRET_KEY = pic_upload_config.get_config('s3_secret_key').data
REGION = pic_upload_config.get_config('s3_region').data
DEFAULT_BUCKET = pic_upload_config.get_config('s3_bucket').data
class S3:
def __init__(self, bucket_id: str = DEFAULT_BUCKET):
self.bucket_id = bucket_id
self.temp = "TEMP"
self.session = aioboto3.Session(
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY,
)
async def upload(self, file_name: str, files: BytesIO):
key = f'{self.temp}/{file_name}'
async with self.session.client(
's3',
endpoint_url=END_POINT,
) as s3: # type: ignore
logger.info('[S3 / upload] 开始上传...')
await s3.upload_fileobj(files, self.bucket_id, key)
logger.info('[S3 / upload] 上传成功!')
asyncio.create_task(self.delete(key))
return f'{END_POINT}/{self.bucket_id}/{key}'
async def delete(self, file_key: str):
await asyncio.sleep(30)
async with self.session.client(
's3',
endpoint_url=END_POINT,
) as s3: # type: ignore
logger.info('[S3 / delete] 开始删除...')
await s3.delete_object(Bucket=self.bucket_id, Key=file_key)
logger.info('[S3 / delete] 删除成功!')

View File

@ -0,0 +1,48 @@
import asyncio
from io import BytesIO
from aiohttp.client import ClientSession
from gsuid_core.logger import logger
from gsuid_core.utils.plugins_config.gs_config import pic_upload_config
SERVER = pic_upload_config.get_config('PicUploadServer').data
TOKEN = pic_upload_config.get_config('smms_token').data
API = 'https://sm.ms/api/v2'
class SMMS:
def __init__(self, token: str = TOKEN) -> None:
self.token = token
self.header = {'Authorization': self.token}
async def delete(self, hash_key: str):
await asyncio.sleep(30)
async with ClientSession() as client:
async with client.request(
'GET',
url=f'{API}/delete/{hash_key}',
headers=self.header,
timeout=300,
) as resp:
logger.info('[sm.ms / upload] 开始删除...')
raw_data = await resp.json()
logger.debug(f'[sm.ms / delete] {raw_data}')
async def upload(self, file_name: str, files: BytesIO):
async with ClientSession() as client:
async with client.request(
'POST',
url=f'{API}/upload',
headers=self.header,
data={'smfile': files.getvalue()},
timeout=300,
) as resp:
logger.info('[sm.ms / upload] 开始上传...')
raw_data = await resp.json()
logger.debug(f'[sm.ms / upload] {raw_data}')
if raw_data['success']:
data = raw_data['data']
asyncio.create_task(self.delete(data['hash']))
return data['url']

1356
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@ mpmath = "^1.3.0"
fastapi = "^0.97.0"
trio = "^0.22.0"
apscheduler = "^3.10.1"
aioboto3 = "^12.0.0"
[tool.poetry.group.dev.dependencies]
flake8 = "^6.0.0"

View File

@ -1,66 +1,75 @@
--index-url https://mirrors.bfsu.edu.cn/pypi/web/simple
aioboto3==12.0.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
aiobotocore[boto3]==2.7.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
aiofiles==23.2.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiohttp==3.8.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiosignal==1.3.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
aiohttp==3.8.6 ; python_full_version >= "3.8.1" and python_version < "4.0"
aioitertools==0.11.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
aiosignal==1.3.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
aiosqlite==0.19.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
anyio==4.0.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
apscheduler==3.10.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
async-timeout==4.0.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
attrs==23.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
async-timeout==4.0.3 ; python_full_version >= "3.8.1" and python_version < "4.0"
attrs==23.1.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
backports-zoneinfo==0.2.1 ; python_full_version >= "3.8.1" and python_version < "3.9"
bcrypt==4.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
beautifulsoup4==4.12.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
boto3==1.28.64 ; python_full_version >= "3.8.1" and python_version < "4.0"
botocore==1.31.64 ; python_full_version >= "3.8.1" and python_version < "4.0"
certifi==2023.7.22 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
cffi==1.15.1 ; os_name == "nt" and implementation_name != "pypy" and python_full_version >= "3.8.1" and python_full_version < "4.0.0"
charset-normalizer==3.2.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
cffi==1.16.0 ; os_name == "nt" and implementation_name != "pypy" and python_full_version >= "3.8.1" and python_full_version < "4.0.0"
charset-normalizer==3.3.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
click==8.1.7 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
colorama==0.4.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and (platform_system == "Windows" or sys_platform == "win32")
dnspython==2.4.2 ; python_full_version >= "3.8.1" and python_version < "4.0"
email-validator==2.0.0.post2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
email-validator==2.1.0.post1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
exceptiongroup==1.1.3 ; python_full_version >= "3.8.1" and python_version < "3.11"
fastapi-amis-admin==0.5.8 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-user-auth==0.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi==0.97.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
frozenlist==1.4.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitpython==3.1.36 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
greenlet==2.0.2 ; python_full_version >= "3.8.1" and (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") and python_full_version < "4.0.0"
frozenlist==1.4.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
gitdb==4.0.11 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
gitpython==3.1.40 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
greenlet==3.0.1 ; python_full_version >= "3.8.1" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0"
h11==0.14.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
httpcore==0.18.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
httpx==0.25.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
idna==3.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
idna==3.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
jmespath==1.0.1 ; python_full_version >= "3.8.1" and python_version < "4.0"
loguru==0.6.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
lxml==4.9.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
mpmath==1.3.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
msgspec==0.18.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
multidict==6.0.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
outcome==1.2.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
msgspec==0.18.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
multidict==6.0.4 ; python_full_version >= "3.8.1" and python_version < "4.0"
outcome==1.3.0.post0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
passlib==1.7.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pillow==10.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pillow==10.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pycparser==2.21 ; python_full_version >= "3.8.1" and os_name == "nt" and implementation_name != "pypy" and python_full_version < "4.0.0"
pydantic==1.10.12 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pydantic==1.10.13 ; python_full_version >= "3.8.1" and python_version < "4.0"
pypng==0.20220715.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
python-dateutil==2.8.2 ; python_full_version >= "3.8.1" and python_version < "4.0"
python-multipart==0.0.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
pytz==2023.3.post1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
qrcode[pil]==7.4.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
six==1.16.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
s3transfer==0.7.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
six==1.16.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
smmap==5.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sniffio==1.3.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sortedcontainers==2.4.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
soupsieve==2.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy-database==0.1.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy2-stubs==0.0.2a35 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy==1.4.41 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlmodel==0.0.8 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
sqlalchemy2-stubs==0.0.2a36 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlalchemy==1.4.50 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlmodel==0.0.11 ; python_full_version >= "3.8.1" and python_version < "4.0"
sqlmodelx==0.0.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
starlette==0.27.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
trio==0.22.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
typing-extensions==4.8.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
typing-extensions==4.8.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
tzdata==2023.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and platform_system == "Windows"
tzlocal==5.0.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
urllib3==1.26.16 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
tzlocal==5.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
urllib3==1.26.18 ; python_full_version >= "3.8.1" and python_version < "4.0"
uvicorn==0.23.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
websockets==10.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
win32-setctime==1.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and sys_platform == "win32"
yarl==1.9.2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
wrapt==1.15.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
yarl==1.9.2 ; python_full_version >= "3.8.1" and python_version < "4.0"