diff --git a/application/lib/dictionary/stardict/stardict.py b/application/lib/dictionary/stardict/stardict.py index 695775f4..8c1ea837 100644 --- a/application/lib/dictionary/stardict/stardict.py +++ b/application/lib/dictionary/stardict/stardict.py @@ -58,7 +58,7 @@ def definition(self, word, language=''): ret = ret.decode('utf-8') #每条释义的前面添加一个换行 ret = re.sub(r'(\s*\d+)', r'
\1', ret, flags=re.IGNORECASE) - lines = [line.strip() for line in str(ret).split('\n') if line.strip()] + lines = [line.strip() for line in str(ret).splitlines() if line.strip()] if lines and lines[0] in (word, f'{word}'): #去掉开头的词条 lines = lines[1:] diff --git a/application/lib/ebook_tts/html_audiolator.py b/application/lib/ebook_tts/html_audiolator.py index c4ed9f2d..6f1dc231 100644 --- a/application/lib/ebook_tts/html_audiolator.py +++ b/application/lib/ebook_tts/html_audiolator.py @@ -142,7 +142,7 @@ def split_strings(self, strings, max_len): for item in step1: if len(item) > max_len + 1: #拆分 subItems = [] - for line in item.split('\n'): #按照回车进行分割 + for line in item.splitlines(): #按照回车进行分割 if len(line) > max_len: #再按照空格进行分割 words = line.split() diff --git a/application/lib/simple_ai_provider.py b/application/lib/simple_ai_provider.py index 29f3bb7f..d176a4d2 100644 --- a/application/lib/simple_ai_provider.py +++ b/application/lib/simple_ai_provider.py @@ -29,7 +29,7 @@ {'name': 'claude-3', 'rpm': 5, 'context': 200000}, {'name': 'claude-2.1', 'rpm': 5, 'context': 100000},], 'Grok': [ - {'name': 'grok-beta', 'rpm': 10, 'context': 128000},], + {'name': 'grok-beta', 'rpm': 60, 'context': 128000},], 'Mistral': [ {'name': 'open-mistral-7b', 'rpm': 60, 'context': 32000}, {'name': 'mistral-small-latest', 'rpm': 60, 'context': 32000}, @@ -135,15 +135,23 @@ def _openai_chat(self, message, defaultUrl='https://api.openai.com/v1/chat/compl #anthropic的chat接口 def _anthropic_chat(self, message): url = self.api_host if self.api_host else 'https://api.anthropic.com/v1/complete' - headers = {'Accept': 'application/json', - 'Anthropic-Version': '2023-06-01', - 'Content-Type': 'application/json', - 'x-api-key': self.api_key} - payload = { - "prompt": f"\n\nHuman: {message}\n\nAssistant:", - "model": self._model, - "max_tokens_to_sample": 256, - } + headers = {'Accept': 'application/json', 'Anthropic-Version': '2023-06-01', + 'Content-Type': 'application/json', 'x-api-key': self.api_key} + + if isinstance(message, list): #将openai的payload格式转换为anthropic的格式 + msg = [] + for item in message: + role = 'Human' if (item.get('role') != 'assistant') else 'Assistant' + content = item.get('content', '') + msg.append(f"\n\n{role}: {content}") + prompt = ''.join(msg) + "\n\nAssistant:" + payload = {"prompt": prompt, "model": self.model, "max_tokens_to_sample": 256} + elif isinstance(message, dict): + payload = message + else: + prompt = f"\n\nHuman: {message}\n\nAssistant:" + payload = {"prompt": prompt, "model": self.model, "max_tokens_to_sample": 256} + response = self.opener.post(url, headers=headers, json=payload) response.raise_for_status() return response.json()["completion"] @@ -154,7 +162,18 @@ def _gemini_chat(self, message): url = f'{self.api_host}?key={self.api_key}' else: url = f'https://generativelanguage.googleapis.com/v1beta/models/{self._model}:generateContent?key={self.api_key}' - payload = {'contents': [{'parts': [{'text': message}]}]} + + if isinstance(message, list): #将openai的payload格式转换为gemini的格式 + msg = [] + for item in message: + role = 'user' if (item.get('role') != 'assistant') else 'model' + content = item.get('content', '') + msg.append({'role': role, 'parts': [{'text': content}]}) + payload = {'contents': msg} + elif isinstance(message, dict): + payload = message + else: + payload = {'contents': [{'role': 'user', 'parts': [{'text': message}]}]} response = self.opener.post(url, json=payload) response.raise_for_status() contents = response.json()["candidates"][0]["content"] diff --git a/application/view/adv.py b/application/view/adv.py index 7b5f97b1..a5044e34 100644 --- a/application/view/adv.py +++ b/application/view/adv.py @@ -2,7 +2,7 @@ # -*- coding:utf-8 -*- #一些高级设置功能页面 #Author: cdhigh -import re, io, textwrap, json +import re, io, textwrap, json, base64 from urllib.parse import unquote, urljoin, urlparse from bs4 import BeautifulSoup from html import escape @@ -440,26 +440,47 @@ def AdvProxyPost(user: KeUser): return adv_render_template('adv_proxy.html', 'proxy', proxy=proxy, user=user, tips=tips) #测试代理是否正常 -@bpAdv.route("/fwd", endpoint='AdvFwdRoute') -@login_required() -def AdvFwdRoute(user: KeUser): - UrlOpener.set_proxy(user.cfg('proxy')) - url = request.args.get('url') - if url: - url = unquote(url) - if not url.startswith('http'): - url = 'https://' + url - try: - resp = UrlOpener().open(url) - headers = dict(resp.headers) - headers.pop('Transfer-Encoding', None) - headers.pop('Content-Encoding', None) - return Response(resp.content, status=resp.status_code, headers=headers) - except Exception as e: - return str(e) - else: - return 'param "url" is empty' +#这个函数很强大,简单的利用都可以用来临时翻墙了 +#登录状态只需要 url 一个参数,否则需要 url, username, key, enc(可选) +@bpAdv.route("/fwd", methods=['GET', 'POST']) +def AdvFwdRoute(): + #要不是正在登录状态,要不就传递用户名和分享密码 + user = get_login_user() + args = request.args + url = args.get('url') + enc = args.get('enc') + if not user: + name = args.get('username') + user = KeUser.get_or_none(KeUser.name == name) if name else None + if user and user.share_links.get('key') != args.get('key'): + user = None + + if not url or not user: + return _("Some parameters are missing or wrong."), 400 + + #为避免url泄露,可以在客户端简单"加密" + if enc == 'base64': + url = base64.b64decode(url).decode('utf-8') + elif enc == 'ke': + url = ke_decrypt(url, user.cfg('secret_key')) + UrlOpener.set_proxy(user.cfg('proxy')) + url = unquote(url) + if not url.startswith('http'): + url = 'https://' + url + inHeaders = {k: v for k, v in request.headers if k != 'Host'} + try: + if request.method == 'GET': + resp = UrlOpener().get(url, headers=inHeaders) + else: + resp = UrlOpener().post(url, data=request.data, headers=inHeaders) + headers = dict(resp.headers) + headers.pop('Transfer-Encoding', None) + headers.pop('Content-Encoding', None) + return Response(resp.content, status=resp.status_code, headers=headers) + except Exception as e: + return f"Unexpected error: {str(e)}", 500 + #设置calibre的参数 @bpAdv.route("/adv/calibre", endpoint='AdvCalibreOptions') @login_required() diff --git a/application/view/inbound_email.py b/application/view/inbound_email.py index e63d9e62..133ce231 100644 --- a/application/view/inbound_email.py +++ b/application/view/inbound_email.py @@ -283,7 +283,7 @@ def ConvertTextToHtml(subject, text): #转换纯文本到html时需要将里面的文本链接变成tag a bodyUrls = [] - for line in text.split('\n'): + for line in text.splitlines(): line = line.strip() if not line: continue diff --git a/docker/compose_up.sh b/docker/compose_up.sh deleted file mode 100644 index a1a58701..00000000 --- a/docker/compose_up.sh +++ /dev/null @@ -1,2 +0,0 @@ -sudo docker-compose rm -fs -sudo docker-compose up -d diff --git a/docker/dockerd b/docker/dockerd deleted file mode 100644 index 3bfbdaa4..00000000 --- a/docker/dockerd +++ /dev/null @@ -1,5 +0,0 @@ -FROM --platform=$TARGETPLATFORM golang:latest -LABEL maintainer="cppla " -WORKDIR /app -RUN go install github.com/dmulholl/mp3cat@latest -CMD ["sh"] \ No newline at end of file diff --git a/main.py b/main.py index 3646e27d..35a12296 100644 --- a/main.py +++ b/main.py @@ -4,7 +4,7 @@ # Visit for the latest version # Author: cdhigh -__Version__ = '3.2.1' +__Version__ = '3.2.2' import os, sys, builtins, logging from application.lib import clogging