7 Commits

Author SHA1 Message Date
f825b18d88 Update README.md 2025-02-10 10:06:48 +08:00
3f32cb4de2 fix(cookie): resolve hardcoded cookie issue (oversight fix) 2025-02-04 00:31:30 +08:00
989bb531f9 update readme about cookie 2025-02-03 15:03:19 +08:00
1c25f0d70d Update README.md 2025-02-03 14:43:38 +08:00
061d05dfe8 refactor(api): update authentication and request parameters for enhanced compatibility
- Replace token-based authentication with cookie-based authentication for improved security and usability
- Add support for chat_type field in both request body and content object to align with updated API requirements
- Ensure prompt content remains unchanged while adapting to the new interface specifications
- Update frontend interface to include a dedicated field for cookie input under Token management
This change ensures seamless integration with the updated API while maintaining backward compatibility and user experience.
2025-02-03 14:39:25 +08:00
ec554bc93a refactor(api): update authentication and request parameters for enhanced compatibility 2025-02-03 14:31:27 +08:00
77997c592e Fix some symbol issues at line 1221 2025-02-02 21:17:52 +08:00
4 changed files with 204 additions and 100 deletions

BIN
.gitignore vendored

Binary file not shown.

View File

@ -4,7 +4,10 @@
## 项目展示
![image](https://github.com/user-attachments/assets/9e794686-f914-4fb7-9931-1ada7c22bb2d)
## 测试cookie
```txt
cna=LI8HIAirQyACAWrg3cNOjH8F; _gcl_au=1.1.1200556497.1736728490; xlly_s=1; acw_tc=c2b96feb4d2929a1649ea96dc00590956477696933f61783d23e6c95429ecf74; x-ap=ap-southeast-1; token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjUzZTk0Nzg4LWMwM2QtNDY4Mi05OTNhLWE0ZDNjNGUyZDY0OSIsImV4cCI6MTc0MTE0ODM0MX0.-2hF4l1iJf8r5U6UzoXyc-TFqx0i5luWmtJk0kk8T5o; ssxmod_itna=Yq+hqIxjx=AKi7eitD8IDCWBfbxxl4BtGRDeq7tDRDFqApxDHmLWxoDUxxu2hE80DD0ADnG3BUxGN4tDxiNDAg40iDC4mL37ezTxthtQQhgDCTYCu2rpTCGGE7P3rnTE0M25BA6w3KxxGLDY=DCqhxl4eD4R3Dt4DIDAYDDxDWFeGIDGYD7hb=ymbDm44aYxGy3nbDA3TDbhb5xitYDDUAKeG2igbhDDNheFY49GG7yC0OorHDAqh==GbDjqPD/RxLP+bkXtkh/CTA=BapCeaWxBQD7we3xYE4c=IdqZawfiEwDELx0De/iGKGxdYmPlvzYKGlpVGGoWDqjqQlXnlvnnPDDc=Y9=buiDrP3KYtvS85lmHQDxPoGb0rz0THimDgri0i8B0=nxNCDtYDb30eDBeIG4/g8BvDD; ssxmod_itna2=Yq+hqIxjx=AKi7eitD8IDCWBfbxxl4BtGRDeq7tDRDFqApxDHmLWxoDUxxu2hE80DD0ADnG3BDxDfk7K7e5xDLiARWCTe9A4D/9o1+WeqlSGSWe4dTPhBUq4kzjyE41MPvWM=BtDwWHWiQ4B+GVChGZYlDDoA6gCj2VGnQeqqxeBSiqeT69Cg2Q6qrEGqv/DTQR8MRo3m3E7Gd7mf42Re2lYpNic=beSRp3tCDgWT7khOXGqf2lBpre5BtExlRw6cUwWwDxNSFUl/8Un/RGZz8/jLk2t1XZC79Eb7iRTPTMPn5MTHW2fs1DlsH0z9RxCLW1Rdb2QFhd9biugr+2aTW1oeYAbtORQNMW43+m2Gcb=TuFtQGqhiTqrNfdwSOe8WHSWTr7cRaw833Yzw31d4iN+Q9OO7izUj1uSdYrh4dIvx5CwYD45Vji4EbkiaNQQGbt1hDa8Ymmda3r3lThChY8Nm2IscznS+mS43izuLzUYN94syC3tQi03=u3Q6az931moHSOLY3OFPKoMjqMUDbtebxw=rT2rBAv08uRkWHzFtGp2lUSSb3z41pTZcx/8NB3jD+XnIpLFEw8bv4r58wRLLwubFTQ9cPDv+9k36tvoCYXlso4qGA44E3y737YNBDmUct2Iahxq76iTrlGotG1NBBN=Tx4hkA2Zp887gfc4Tp8V1wGCf49XeA=0Xu3uIKqYQADh0ABmqlQ4w=YVlDPjO9KH2xaG3C8ID5DeY41AxMxR2NIGhSD+5q0UQGx0Ue4dAi0DwbY+f7n1Gwz014LQ2DY+42xI2zG5TmhfDtXehC40aWxfDi0xIGNQ3gGkYeu2fAfADwY31mkAooDxD; SERVERID=da7472215188c88fe194f138f1242089|1738557149|1738556339; SERVERCORSID=da7472215188c88fe194f138f1242089|1738557149|1738556339; isg=BBcXHLltPM7zv7hi-FnT0HW6pothXOu-LIccEmlG4eZGmDrabS7mDq_--ziGPsM2; tfstk=gxYniE986HSQfEpYpd7Icypow5otjW_5cLUReaBrbOW6JLnCehbygKjRyBdPr4XN8gtde9BlrQ9m6x3xkBOCPgkxHqIXCrTVlurzY8QNb_blTz_06LRCPaktd3lv5B9qU3M64alG7_fz8aWFTPlGZsXPz9SzQl5VQT7yU9SaQ617YJzUzRlGNOWPzaJP7jQ8r9CV1FkgVOPK4CrD_6jh3BWH9KLadGrBiO4zzFjfxtuAIzzyS6Ot3kbuo0B2c9IACduT-aANZKfDKRkGzCYBoG8ECzvDIn7G1hMuqtxy9ntPjXueswXhmFI0Zk7H4pTlAHVSGC7eCn6fYcM1seLAqtsgQvR9s9SDqpH_z9KD_djvWRUA7I-GSgozbo5IVz1ZwFr7VM51stK4FEPS3FZLvfcg0MIF16r-sfq7VM51sthisoJlY11U2
```
## 🚀 功能特性
- **图片 OCR**:使用 QwenLM 强大的 OCR 功能从图片中提取文字。
@ -31,12 +34,12 @@
## 🧩 使用说明
1. **设置 Token**
- 前往 [QwenLM](https://chat.qwenlm.ai/) 获取 Bearer后面的Token
![image](https://github.com/user-attachments/assets/9fa3ea04-da2b-4756-a091-83c0665f62f3)
1. **设置 Cookie**
- 前往 [QwenLM](https://chat.qwenlm.ai/) 获取对话请求中的 Cookie
![alt text](image.png)
- 点击右上角的 **⚙️ Token设置** 按钮。
- 输入你的 QwenLM API Token多个 Token 用英文逗号分隔)。
- 点击右上角的 **⚙️ Cookie设置** 按钮。
- 输入你的 Cookie或者使用测试Cookie)。
- 点击 **保存**
2. **上传图片**
@ -139,4 +142,4 @@ curl --location 'https://ocr.doublefenzhuan.me/api/recognize/url' \
![image](https://github.com/user-attachments/assets/bb456075-6107-47ee-a361-a0edba532c38)
## 趋势
[![Star History Chart](https://api.star-history.com/svg?repos=cunninger/ocr-based-qwen&type=Date&v=20251114)](https://star-history.com/#Cunninger/ocr-based-qwen&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=cunninger/ocr-based-qwen&type=Date)](https://star-history.com/#Cunninger/ocr-based-qwen&Date)

BIN
image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

287
worker.js
View File

@ -4,6 +4,7 @@ addEventListener('fetch', event => {
async function handleRequest(request) {
const url = new URL(request.url);
const cookie = request.headers.get('x-custom-cookie') || ''; // 从自定义请求头获取 cookie
// 处理 CORS 预检请求
if (request.method === 'OPTIONS') {
@ -11,7 +12,7 @@ async function handleRequest(request) {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-custom-cookie', // 添加自定义请求头
},
});
}
@ -166,7 +167,7 @@ async function handleFileRecognition(request) {
});
}
return await recognizeImage(token, imageId);
return await recognizeImage(token, imageId, request); // 传递 request 对象
} catch (error) {
return new Response(JSON.stringify({
error: error.message || 'Internal Server Error'
@ -214,16 +215,20 @@ async function handleProxyUpload(request) {
}
// 通用的识别函数
async function recognizeImage(token, imageId) {
async function recognizeImage(token, imageId, request) {
// 从请求头获取 cookie
const response = await fetch('https://chat.qwenlm.ai/api/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'PostmanRuntime/7.43.0',
'accept': '*/*',
'authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'cookie': request.headers.get('x-custom-cookie') || '', // 使用自定义请求头中的 cookie
},
body: JSON.stringify({
stream: false,
chat_type: "t2t",
model: 'qwen2.5-vl-72b-instruct',
messages: [
{
@ -245,9 +250,14 @@ async function recognizeImage(token, imageId) {
'2. 忽略干扰线和噪点\n' +
'3. 注意区分相似字符如0和O、1和l、2和Z等\n' +
'4. 验证码通常为4-6位字母数字组合\n\n' +
'不要输出任何额外的解释或说明'
'不要输出任何额外的解释或说明',
chat_type: "t2t"
},
{
type: 'image',
image: imageId,
chat_type: "t2t"
},
{ type: 'image', image: imageId },
],
},
],
@ -1015,86 +1025,126 @@ function getHTML() {
' width: 100%;',
' }',
' .powered-by {',
' color: #7f8c8d;',
' font-size: 0.9rem;',
' }',
' color: #7f8c8d;',
' font-size: 0.9rem;',
' }',
' .powered-by a {',
' color: #3498db;',
' text-decoration: none;',
' transition: color 0.3s ease;',
' font-weight: 500;',
' }',
' .powered-by a {',
' color: #3498db;',
' text-decoration: none;',
' transition: color 0.3s ease;',
' font-weight: 500;',
' }',
' .powered-by a:hover {',
' color: #2980b9;',
' }',
' .powered-by a:hover {',
' color: #2980b9;',
' }',
' .powered-by {',
' color: #7f8c8d;',
' font-size: 0.9rem;',
' }',
' .powered-by {',
' color: #7f8c8d;',
' font-size: 0.9rem;',
' }',
' .powered-by a {',
' color: #3498db;',
' text-decoration: none;',
' transition: color 0.3s ease;',
' font-weight: 500;',
' }',
' .powered-by a {',
' color: #3498db;',
' text-decoration: none;',
' transition: color 0.3s ease;',
' font-weight: 500;',
' }',
' .powered-by a:hover {',
' color: #2980b9;',
' }',
' .powered-by a:hover {',
' color: #2980b9;',
' }',
' /* 输入控件组样式 */',
' .input-controls {',
' margin-top: 15px;',
' width: 100%;',
' }',
' /* 输入控件组样式 */',
' .input-controls {',
' margin-top: 15px;',
' width: 100%;',
' }',
' .button-group {',
' display: flex;',
' gap: 10px;',
' margin-top: 10px;',
' justify-content: center;',
' }',
' .button-group {',
' display: flex;',
' gap: 10px;',
' margin-top: 10px;',
' justify-content: center;',
' }',
' #urlInput {',
' width: 100%;',
' padding: 10px;',
' border: 1px solid #dcdde1;',
' border-radius: 8px;',
' resize: none;',
' font-size: 14px;',
' }',
' #urlInput {',
' width: 100%;',
' padding: 10px;',
' border: 1px solid #dcdde1;',
' border-radius: 8px;',
' resize: none;',
' font-size: 14px;',
' }',
' .github-link {',
' position: fixed;',
' right: 150px;', // 放在 token 设置按钮左边
' top: 20px;',
' background: #333;', // GitHub 的深色背景
' color: white;',
' border: none;',
' padding: 10px;',
' border-radius: 50%;', // 圆形按钮
' cursor: pointer;',
' z-index: 1001;',
' width: 40px;',
' height: 40px;',
' display: flex;',
' align-items: center;',
' justify-content: center;',
' transition: background 0.3s ease;',
' }',
' .github-link {',
' position: fixed;',
' right: 150px;', // 放在 token 设置按钮左边',
' top: 20px;',
' background: #333;', // GitHub 的深色背景',
' color: white;',
' border: none;',
' padding: 10px;',
' border-radius: 50%;', // 圆形按钮',
' cursor: pointer;',
' z-index: 1001;',
' width: 40px;',
' height: 40px;',
' display: flex;',
' align-items: center;',
' justify-content: center;',
' transition: background 0.3s ease;',
' }',
' .github-link:hover {',
' background: #24292e;', // GitHub hover 颜色
' }',
' .github-link:hover {',
' background: #24292e;', // GitHub hover 颜色',
' }',
' .github-icon {',
' width: 24px;',
' height: 24px;',
' }',
' .github-icon {',
' width: 24px;',
' height: 24px;',
' }',
' .cookie-input-container {',
' margin-bottom: 15px;',
' }',
' #cookieInput {',
' width: 100%;',
' padding: 12px;',
' border: 2px solid #e9ecef;',
' border-radius: 8px;',
' font-size: 0.95rem;',
' resize: vertical;',
' min-height: 120px;',
' font-family: monospace;',
' line-height: 1.4;',
' }',
' #cookieInput:focus {',
' outline: none;',
' border-color: #3498db;',
' }',
' .cookie-info {',
' background: #f8f9fa;',
' padding: 12px;',
' border-radius: 8px;',
' margin-bottom: 15px;',
' }',
' .cookie-info p {',
' margin: 0;',
' color: #2c3e50;',
' font-size: 0.9rem;',
' }',
' #currentTokenDisplay {',
' color: #3498db;',
' font-family: monospace;',
' word-break: break-all;',
' }',
'</style>',
'</head>',
'<body>',
@ -1103,18 +1153,24 @@ function getHTML() {
' <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>',
' </svg>',
'</a>',
'<button class="sidebar-toggle" id="sidebarToggle">⚙️ Token设置</button>',
'<button class="sidebar-toggle" id="sidebarToggle">⚙️ Cookie设置</button>',
'<div class="sidebar" id="sidebar">',
'<div class="sidebar-header">',
'<h2>Token 管理</h2>',
'<h2>Cookie管理</h2>',
'<button class="close-sidebar" id="closeSidebar">×</button>',
'</div>',
'<div class="token-section">',
'<label for="tokenInput">输入Token</label>',
'<textarea id="tokenInput" placeholder="输入Token多个Token请用英文逗号分隔" rows="4"></textarea>',
'<button class="save-btn" id="saveTokens">保存 Token</button>',
'<label for="cookieInput">输入Cookie</label>',
'<div class="cookie-input-container">',
'<textarea id="cookieInput" placeholder="请输入完整的cookie字符串..." rows="8"></textarea>',
'</div>',
'<div class="token-list" id="tokenList"></div>',
'<div class="cookie-info">',
'<p>当前Token: <span id="currentTokenDisplay">未设置</span></p>',
'</div>',
'<button class="save-btn" id="saveTokens">保存设置</button>',
'</div>',
// 添加 tokenList 容器
'<div class="token-list" id="tokenList"></div>', // 添加这一行
'</div>',
'<div class="container">',
@ -1218,7 +1274,7 @@ function getHTML() {
' const timeStr = timestamp.toLocaleString(\'zh-CN\', {',
' year: \'numeric\',',
' month: \'2-digit\',',
' day: \'2-digit\',
' day: \'2-digit\',', // Add comma here
' hour: \'2-digit\',',
' minute: \'2-digit\'',
' });',
@ -1296,6 +1352,11 @@ function getHTML() {
' // 修改 updateTokenList 函数',
' function updateTokenList() {',
' const tokenList = document.getElementById(\'tokenList\');',
' if (!tokenList) {',
' console.error(\'找不到tokenList元素\');',
' return;',
' }',
' tokenList.innerHTML = "";',
' tokens.forEach(function(token, index) {',
' var truncatedToken = token.slice(0, 10) + "..." + token.slice(-10);',
@ -1309,22 +1370,41 @@ function getHTML() {
' historyManager.displayHistory(currentToken);',
' });',
' tokenList.appendChild(div);',
' });',
' tokenInput.value = tokens.join(",");',
' });',
' const tokenInput = document.getElementById(\'tokenInput\');',
' if (tokenInput) {',
' tokenInput.value = tokens.join(",");',
' }',
' }',
' // 保存tokens',
' saveTokensBtn.addEventListener(\'click\', () => {',
' const inputTokens = tokenInput.value.split(\',\').map(t => t.trim()).filter(t => t);',
' if (inputTokens.length > 0) {',
' tokens = inputTokens;',
' localStorage.setItem(\'imageRecognitionTokens\', tokens.join(\',\'));',
' updateTokenList();',
' currentToken = tokens[0];',
' alert(\'Tokens已保存\');',
' } else {',
' alert(\'请至少输入一个有效的Token\');',
' const cookieValue = document.getElementById(\'cookieInput\').value.trim();',
' if (!cookieValue) {',
' alert(\'请输入Cookie\');',
' return;',
' }',
' ',
' // 从cookie中提取token',
' const tokenMatch = cookieValue.match(/token=([^;]+)/);',
' if (!tokenMatch) {',
' alert(\'无法从Cookie中提取token请确保Cookie中包含token字段\');',
' return;',
' }',
' ',
' const token = tokenMatch[1];',
' tokens = [token];',
' currentToken = token;',
' ',
' // 保存cookie和token',
' localStorage.setItem(\'imageRecognitionCookie\', cookieValue);',
' localStorage.setItem(\'imageRecognitionTokens\', token);',
' ',
' // 更新显示',
' document.getElementById(\'currentTokenDisplay\').textContent = ',
' token.slice(0, 10) + "..." + token.slice(-10);',
' ',
' alert(\'设置已保存\');',
' });',
' // 侧边栏开关',
@ -1340,6 +1420,7 @@ function getHTML() {
' return;',
' }',
' const savedCookie = localStorage.getItem(\'imageRecognitionCookie\');',
' // 显示图片预览',
' const reader = new FileReader();',
' let imageData;',
@ -1363,6 +1444,7 @@ function getHTML() {
' method: \'POST\',',
' headers: {',
' \'Authorization\': \'Bearer \' + currentToken,',
' \'x-custom-cookie\': savedCookie || \'\', // 添加 cookie 到请求头',
' },',
' body: formData,',
' });',
@ -1764,6 +1846,25 @@ function getHTML() {
' timeout = setTimeout(later, wait);',
' };',
' }',
' // 加载保存的cookie',
' function loadSettings() {',
' const savedCookie = localStorage.getItem(\'imageRecognitionCookie\');',
' if (savedCookie) {',
' document.getElementById(\'cookieInput\').value = savedCookie;',
' const tokenMatch = savedCookie.match(/token=([^;]+)/);',
' if (tokenMatch) {',
' const token = tokenMatch[1];',
' tokens = [token];',
' currentToken = token;',
' document.getElementById(\'currentTokenDisplay\').textContent = ',
' token.slice(0, 10) + "..." + token.slice(-10);',
' }',
' }',
' }',
' // 初始化时调用loadSettings',
' loadSettings();',
'</script>',
'</body>',
'</html>'