@tanskong/office-assistant 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/officer.py +37 -28
- package/src/server.py +0 -6
package/package.json
CHANGED
package/src/officer.py
CHANGED
|
@@ -3,11 +3,15 @@ import pywintypes
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
import win32com.client
|
|
6
|
+
import pythoncom
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class TheOfficer:
|
|
10
11
|
def __init__(self):
|
|
12
|
+
# 初始化 COM
|
|
13
|
+
pythoncom.CoInitialize()
|
|
14
|
+
|
|
11
15
|
self._excel = None
|
|
12
16
|
self._word = None
|
|
13
17
|
self._outlook = None
|
|
@@ -21,9 +25,9 @@ class TheOfficer:
|
|
|
21
25
|
self._kwpp = None
|
|
22
26
|
self._kwps = None
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
# 使用用户目录,避免硬编码 D 盘
|
|
29
|
+
self._default_folder = os.path.join(os.path.expanduser("~"), "OfficeMCP_Data")
|
|
25
30
|
self.Version = "1.0.5"
|
|
26
|
-
self.Speaker = None
|
|
27
31
|
self.ComObjects = {}
|
|
28
32
|
self._printable = False
|
|
29
33
|
self.Data = OfficerData()
|
|
@@ -50,18 +54,6 @@ class TheOfficer:
|
|
|
50
54
|
self.ComObjects[com_name] = comobject
|
|
51
55
|
return comobject
|
|
52
56
|
|
|
53
|
-
def Speak(self, text: str = "Hello!, I'm Office Assistant.", volume: int = 80, rate: int = 2) -> bool:
|
|
54
|
-
try:
|
|
55
|
-
if self.Speaker is None:
|
|
56
|
-
self.Speaker = self.GetComObject("SAPI.SPVOICE")
|
|
57
|
-
self.Speaker.Volume = volume
|
|
58
|
-
self.Speaker.Rate = rate
|
|
59
|
-
self.Speaker.Speak(text)
|
|
60
|
-
return True
|
|
61
|
-
except Exception as e:
|
|
62
|
-
print(e)
|
|
63
|
-
return False
|
|
64
|
-
|
|
65
57
|
def DownloadImage(self, url: str, save_path: str = None) -> str:
|
|
66
58
|
import datetime
|
|
67
59
|
if save_path is None:
|
|
@@ -130,6 +122,12 @@ class TheOfficer:
|
|
|
130
122
|
return False
|
|
131
123
|
|
|
132
124
|
def Application(self, app_name: str, asNewInstance: bool = False):
|
|
125
|
+
# 确保 COM 已初始化
|
|
126
|
+
try:
|
|
127
|
+
pythoncom.CoInitialize()
|
|
128
|
+
except:
|
|
129
|
+
pass
|
|
130
|
+
|
|
133
131
|
app_name_attr = "_" + app_name.lower()
|
|
134
132
|
if hasattr(self, app_name_attr):
|
|
135
133
|
app = getattr(self, app_name_attr)
|
|
@@ -143,17 +141,21 @@ class TheOfficer:
|
|
|
143
141
|
if not self.IsAppAvailable(app_name):
|
|
144
142
|
return None
|
|
145
143
|
app_full_name = app_name + ".Application"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
self.__dict__[app_name_attr] = app
|
|
149
|
-
return app
|
|
150
|
-
else:
|
|
151
|
-
try:
|
|
152
|
-
app = win32com.client.GetActiveObject(app_full_name)
|
|
153
|
-
except pywintypes.com_error:
|
|
144
|
+
try:
|
|
145
|
+
if asNewInstance:
|
|
154
146
|
app = win32com.client.Dispatch(app_full_name)
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
self.__dict__[app_name_attr] = app
|
|
148
|
+
return app
|
|
149
|
+
else:
|
|
150
|
+
try:
|
|
151
|
+
app = win32com.client.GetActiveObject(app_full_name)
|
|
152
|
+
except pywintypes.com_error:
|
|
153
|
+
app = win32com.client.Dispatch(app_full_name)
|
|
154
|
+
self.__dict__[app_name_attr] = app
|
|
155
|
+
return app
|
|
156
|
+
except Exception as e:
|
|
157
|
+
print(f"[ERROR] Failed to create {app_name} application: {e}")
|
|
158
|
+
return None
|
|
157
159
|
|
|
158
160
|
def RunningApps(self) -> list:
|
|
159
161
|
apps = []
|
|
@@ -225,11 +227,18 @@ class TheOfficer:
|
|
|
225
227
|
return True
|
|
226
228
|
|
|
227
229
|
def FilePath(self, file_name: str = None, subfolder: str = None) -> str:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
+
# 优先使用智能办公区路径
|
|
231
|
+
workspace = os.path.join(os.path.expanduser("~"), "Desktop", "智能办公区")
|
|
232
|
+
if not os.path.exists(workspace):
|
|
233
|
+
workspace = self.RootFolder
|
|
234
|
+
|
|
235
|
+
if subfolder:
|
|
236
|
+
folder = os.path.join(workspace, subfolder)
|
|
230
237
|
else:
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
folder = workspace
|
|
239
|
+
|
|
240
|
+
os.makedirs(folder, exist_ok=True)
|
|
241
|
+
return os.path.join(folder, file_name)
|
|
233
242
|
|
|
234
243
|
def ScreenShot(self, save_path: str = None) -> str:
|
|
235
244
|
import win32gui
|
package/src/server.py
CHANGED
|
@@ -188,12 +188,6 @@ def download(url: str, save_name: str = None) -> str:
|
|
|
188
188
|
return Officer.DownloadURL(url, save_name)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
@mcp.tool()
|
|
192
|
-
def speak(text: str = "Hello", volume: int = 80, rate: int = 0) -> bool:
|
|
193
|
-
"""Text-to-speech. Volume: 0-100, Rate: -10 to 10."""
|
|
194
|
-
return Officer.Speak(text, volume, rate)
|
|
195
|
-
|
|
196
|
-
|
|
197
191
|
@mcp.tool()
|
|
198
192
|
def demonstrate() -> dict:
|
|
199
193
|
"""Run a demonstration of Office automation capabilities."""
|