init
This commit is contained in:
commit
57cfa2b160
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# created by virtualenv automatically
|
||||||
|
|
||||||
|
|
||||||
|
/config.toml
|
9
.idea/.gitignore
vendored
Normal file
9
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
|
14
.idea/deployment.xml
Normal file
14
.idea/deployment.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
|
||||||
|
<serverData>
|
||||||
|
<paths name="pi@zero.cn:22 password">
|
||||||
|
<serverdata>
|
||||||
|
<mappings>
|
||||||
|
<mapping local="$PROJECT_DIR$" web="/" />
|
||||||
|
</mappings>
|
||||||
|
</serverdata>
|
||||||
|
</paths>
|
||||||
|
</serverData>
|
||||||
|
</component>
|
||||||
|
</project>
|
10
.idea/gitea_push2qq.iml
Normal file
10
.idea/gitea_push2qq.iml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
61
.idea/inspectionProfiles/Project_Default.xml
Normal file
61
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredUrls">
|
||||||
|
<list>
|
||||||
|
<option value="http://localhost" />
|
||||||
|
<option value="http://127.0.0.1" />
|
||||||
|
<option value="http://0.0.0.0" />
|
||||||
|
<option value="http://www.w3.org/" />
|
||||||
|
<option value="http://json-schema.org/draft" />
|
||||||
|
<option value="http://java.sun.com/" />
|
||||||
|
<option value="http://xmlns.jcp.org/" />
|
||||||
|
<option value="http://javafx.com/javafx/" />
|
||||||
|
<option value="http://javafx.com/fxml" />
|
||||||
|
<option value="http://maven.apache.org/xsd/" />
|
||||||
|
<option value="http://maven.apache.org/POM/" />
|
||||||
|
<option value="http://www.springframework.org/schema/" />
|
||||||
|
<option value="http://www.springframework.org/tags" />
|
||||||
|
<option value="http://www.springframework.org/security/tags" />
|
||||||
|
<option value="http://www.thymeleaf.org" />
|
||||||
|
<option value="http://www.jboss.org/j2ee/schema/" />
|
||||||
|
<option value="http://www.jboss.com/xml/ns/" />
|
||||||
|
<option value="http://www.ibm.com/webservices/xsd" />
|
||||||
|
<option value="http://activemq.apache.org/schema/" />
|
||||||
|
<option value="http://schema.cloudfoundry.org/spring/" />
|
||||||
|
<option value="http://schemas.xmlsoap.org/" />
|
||||||
|
<option value="http://cxf.apache.org/schemas/" />
|
||||||
|
<option value="http://primefaces.org/ui" />
|
||||||
|
<option value="http://tiles.apache.org/" />
|
||||||
|
<option value="http://tb.himg.baidu.com" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="customHeaders">
|
||||||
|
<set>
|
||||||
|
<option value=" "id"" />
|
||||||
|
<option value=" "value"" />
|
||||||
|
<option value="}" />
|
||||||
|
<option value="{" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="ignoredPackages">
|
||||||
|
<value>
|
||||||
|
<list size="6">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="opencv-contrib-python-headless" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="opencv-python-headless" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="aiotieba" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="aiotieba-reviewer" />
|
||||||
|
<item index="4" class="java.lang.String" itemvalue="aiohttp" />
|
||||||
|
<item index="5" class="java.lang.String" itemvalue="sanic" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
7
.idea/misc.xml
Normal file
7
.idea/misc.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.11 (gitea_push2qq)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (gitea_push2qq)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/gitea_push2qq.iml" filepath="$PROJECT_DIR$/.idea/gitea_push2qq.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
启动前自行准备config.toml文件
|
||||||
|
|
||||||
|
开发使用这个启动
|
||||||
|
|
||||||
|
```shell
|
||||||
|
python server.py
|
||||||
|
```
|
||||||
|
|
||||||
|
生产环境
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sanic server:app --host=0.0.0.0 --port=80
|
||||||
|
```
|
63
model.py
Normal file
63
model.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Optional, List, Union, Literal
|
||||||
|
|
||||||
|
from lib_not_dr.types import Options
|
||||||
|
from socketio import AsyncClient
|
||||||
|
|
||||||
|
|
||||||
|
class AtElement(Options):
|
||||||
|
text: str
|
||||||
|
id: Union[int, Literal['all']] = 'all'
|
||||||
|
|
||||||
|
|
||||||
|
class ReplyMessage(Options):
|
||||||
|
id: str
|
||||||
|
username: str = ''
|
||||||
|
content: str = ''
|
||||||
|
files: list = []
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return {
|
||||||
|
'_id': self.id,
|
||||||
|
'username': self.username,
|
||||||
|
'content': self.content,
|
||||||
|
'files': self.files
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Message(Options):
|
||||||
|
content: str
|
||||||
|
room_id: Optional[int] = None
|
||||||
|
room: Optional[int] = None # room id 和 room 二选一 ( 实际上直接填 room id 就行了 )
|
||||||
|
file: None = None # 上传文件
|
||||||
|
reply_to: Optional[ReplyMessage] = None # 源码 给了一个 any 回复消息
|
||||||
|
b64_img: Optional[str] = None # 发送图片
|
||||||
|
at: Optional[List[AtElement]] = [] # @某人
|
||||||
|
sticker: Optional[None] = None # 发送表情
|
||||||
|
message_type: Optional[str] = None # 消息类型
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return {
|
||||||
|
'content': self.content,
|
||||||
|
'roomId': self.room_id,
|
||||||
|
'room': self.room,
|
||||||
|
'file': self.file,
|
||||||
|
'replyMessage': self.reply_to.to_json() if self.reply_to else None,
|
||||||
|
'b64img': self.b64_img,
|
||||||
|
'at': self.at,
|
||||||
|
'sticker': self.sticker,
|
||||||
|
'messageType': self.message_type
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SioConfig:
|
||||||
|
HOST: str
|
||||||
|
KEY: str
|
||||||
|
SELF_ID: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Ctx:
|
||||||
|
sio: AsyncClient
|
||||||
|
sio_config: SioConfig
|
65
server.py
Normal file
65
server.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import tomllib
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from nacl.signing import SigningKey
|
||||||
|
from sanic import Sanic, Request
|
||||||
|
from sanic.log import logger, Colors
|
||||||
|
from sanic.response import json
|
||||||
|
from socketio import AsyncClient
|
||||||
|
|
||||||
|
from model import Ctx, SioConfig, Message
|
||||||
|
|
||||||
|
app = Sanic('GiteaPush', ctx=Ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def get_config() -> SioConfig:
|
||||||
|
with open('config.toml', 'rb') as f:
|
||||||
|
config = tomllib.load(f)
|
||||||
|
return SioConfig(config['host'], config['private_key'], config['self_id'])
|
||||||
|
|
||||||
|
|
||||||
|
@app.before_server_start
|
||||||
|
async def setup_before_start(_app):
|
||||||
|
_app.ctx.sio_config = get_config()
|
||||||
|
_app.ctx.sio = AsyncClient()
|
||||||
|
|
||||||
|
start_sio_listener()
|
||||||
|
|
||||||
|
await _app.ctx.sio.connect(_app.ctx.sio_config.HOST)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post('/receive')
|
||||||
|
async def receive(rqt: Request):
|
||||||
|
data = rqt.json
|
||||||
|
ctx = data['issue']['body']
|
||||||
|
message = Message(content=f'webhook test: {ctx}', room_id=-777186831)
|
||||||
|
await app.ctx.sio.emit('sendMessage', message.to_json())
|
||||||
|
return json({})
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
以下为QQ监听部分
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def start_sio_listener():
|
||||||
|
@app.ctx.sio.on('connect')
|
||||||
|
def connect():
|
||||||
|
logger.info(f'{Colors.GREEN}icalingua 已连接{Colors.END}')
|
||||||
|
|
||||||
|
@app.ctx.sio.on('requireAuth')
|
||||||
|
async def require_auth(salt: str, versions: Dict[str, str]):
|
||||||
|
logger.info(
|
||||||
|
f"{Colors.BLUE}versions: {Colors.PURPLE}{versions} {Colors.BLUE}with type {type(salt)}|{salt=}{Colors.END}")
|
||||||
|
# 准备数据
|
||||||
|
sign = SigningKey(bytes.fromhex(app.ctx.sio_config.KEY))
|
||||||
|
signature = sign.sign(bytes.fromhex(salt))
|
||||||
|
|
||||||
|
# 发送数据
|
||||||
|
logger.info(f"{len(signature.signature)=} {type(signature.signature)=}{Colors.END}")
|
||||||
|
await app.ctx.sio.emit('auth', signature.signature)
|
||||||
|
logger.info(f"{Colors.BLUE}send auth emit{Colors.END}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host='0.0.0.0', port=80, dev=True)
|
Loading…
Reference in New Issue
Block a user