返回提交历史
Added
g4f/gui/server/js_api.py
+95
-0
XFEstudio/gpt4free
Update server
c092acf2
代码差异
1 个文件
+95
-0
@@ -0,0 +1,95 @@
1
from __future__ import annotations
2
3
import logging
4
import json
5
import os.path
6
from typing import Iterator
7
from uuid import uuid4
8
from functools import partial
9
10
import webview
11
import platformdirs
12
from plyer import camera
13
from plyer import filechooser
14
app_storage_path = platformdirs.user_pictures_dir
15
user_select_image = partial(
16
filechooser.open_file,
17
path=platformdirs.user_pictures_dir(),
18
filters=[["Image", "*.jpg", "*.jpeg", "*.png", "*.webp", "*.svg"]],
19
)
20
21
try:
22
from android.runnable import run_on_ui_thread
23
import android.permissions
24
from android.permissions import Permission
25
from android.permissions import _RequestPermissionsManager
26
_RequestPermissionsManager.register_callback()
27
from .android_gallery import user_select_image
28
has_android = True
29
except:
30
run_on_ui_thread = lambda a : a
31
has_android = False
32
33
from .api import Api
34
35
class JsApi(Api):
36
def get_conversation(self, options: dict, **kwargs) -> Iterator:
37
window = webview.windows[0]
38
if hasattr(self, "image") and self.image is not None:
39
kwargs["image"] = open(self.image, "rb")
40
for message in self._create_response_stream(
41
self._prepare_conversation_kwargs(options, kwargs),
42
options.get("conversation_id"),
43
options.get('provider')
44
):
45
if not window.evaluate_js(f"if (!this.abort) this.add_message_chunk({json.dumps(message)}); !this.abort && !this.error;"):
46
break
47
self.image = None
48
self.set_selected(None)
49
50
@run_on_ui_thread
51
def choose_image(self):
52
self.request_permissions()
53
user_select_image(
54
on_selection=self.on_image_selection
55
)
56
57
@run_on_ui_thread
58
def take_picture(self):
59
self.request_permissions()
60
filename = os.path.join(app_storage_path(), f"chat-{uuid4()}.png")
61
camera.take_picture(filename=filename, on_complete=self.on_camera)
62
63
def on_image_selection(self, filename):
64
filename = filename[0] if isinstance(filename, list) and filename else filename
65
if filename and os.path.exists(filename):
66
self.image = filename
67
else:
68
self.image = None
69
self.set_selected(None if self.image is None else "image")
70
71
def on_camera(self, filename):
72
if filename and os.path.exists(filename):
73
self.image = filename
74
else:
75
self.image = None
76
self.set_selected(None if self.image is None else "camera")
77
78
def set_selected(self, input_id: str = None):
79
window = webview.windows[0]
80
if window is not None:
81
window.evaluate_js(
82
f"document.querySelector(`.image-label.selected`)?.classList.remove(`selected`);"
83
)
84
if input_id is not None and input_id in ("image", "camera"):
85
window.evaluate_js(
86
f'document.querySelector(`label[for="{input_id}"]`)?.classList.add(`selected`);'
87
)
88
89
def request_permissions(self):
90
if has_android:
91
android.permissions.request_permissions([
92
Permission.CAMERA,
93
Permission.READ_EXTERNAL_STORAGE,
94
Permission.WRITE_EXTERNAL_STORAGE
95
])