forked from tech-shrimp/WechatMoments
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gui.py
300 lines (236 loc) · 12.5 KB
/
gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
import os
import tkinter
import tkinter.font
import tkinter.ttk
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional
import tkcalendar
from decrypter.db_decrypt import DatabaseDecrypter
from decrypter.image_decrypt import ImageDecrypter
from decrypter.video_decrypt import VideoDecrypter
from gui.auto_scroll_guide import AutoScrollGuide
from gui.auto_scrolls_single_guide import AutoScrollSingleGuide
from gui.tool_tip import ToolTip
from entity.contact import Contact
from exporter.html_exporter import HtmlExporter
from gui.listbox_with_search import ListboxWithSearch
class Gui:
def __init__(self):
self.restart_note1 = None
self.restart_note2 = None
self.auto_scroll_single_guide = None
self.auto_scroll_guide = None
self.auto_scroll_frame = None
self.search_username = None
self.open_search_guide_image = None
self.open_search_guide = None
self.auto_scroll_button_single = None
self.auto_scroll_button_single_text = None
self.convert_video = None
self.convert_video_var = None
self.html_exporter_thread = None
self.confirm_button_text = None
self.succeed_label_2 = None
self.succeed_label = None
self.auto_scroll_button_text = None
self.warning_label = None
self.root = None
self.waiting_label = None
self.listbox = None
self.begin_calendar = None
self.end_calendar = None
self.end_calendar_label = None
self.begin_calendar_label = None
self.confirm_button = None
self.decrypt_progressbar = None
self.export_progressbar = None
self.next_step_button = None
self.decrypter = None
self.auto_scroll_button = None
self.auto_scrolling_thread = None
self.decrypt_note = None
self.decrypt_note_text = None
self.account_info = None
self.video_decrypter = None
self.image_decrypter = None
self.export_dir_name = None
self.exporting = False
# 1: 自动滚动数据 2: 解密数据库 3: 导出
self.page_stage = 1
def run_gui(self):
self.root = tkinter.Tk()
self.root.geometry('650x650')
self.root.title('朋友圈导出')
self.waiting_label = tkinter.ttk.Label(self.root, text="正在连接微信....",
font=("微软雅黑", 16), anchor='center')
self.waiting_label.place(relx=0.5, rely=0.05, anchor='center')
self.root.mainloop()
def wechat_logged_in(self, account_info):
self.account_info = account_info
self.waiting_label.config(text="微信已登录")
self.auto_scroll_button_text = tkinter.StringVar()
self.auto_scroll_button_text.set("自动浏览全部朋友圈")
self.auto_scroll_button = tkinter.ttk.Button(self.root, textvariable=self.auto_scroll_button_text,
command=self.open_auto_scroll_guide)
self.auto_scroll_button.place(relx=0.35, rely=0.15, anchor='center')
self.auto_scroll_button_single_text = tkinter.StringVar()
self.auto_scroll_button_single_text.set("自动浏览单个朋友")
self.auto_scroll_button_single = tkinter.ttk.Button(self.root, textvariable=self.auto_scroll_button_single_text,
command=self.switch_auto_scroll_single)
self.auto_scroll_button_single.place(relx=0.655, rely=0.15, anchor='center')
self.next_step_button = tkinter.ttk.Button(self.root, text="下一步", command=self.next_step)
self.next_step_button.place(relx=0.65, rely=0.8)
def open_auto_scroll_guide(self):
if self.auto_scroll_single_guide and self.auto_scroll_single_guide.frame:
self.auto_scroll_single_guide.frame.place_forget()
self.auto_scroll_guide = AutoScrollGuide(self.root)
self.auto_scroll_guide.frame.place(relx=0.5, rely=0.5, anchor='center')
def switch_auto_scroll_single(self):
if self.auto_scroll_guide and self.auto_scroll_guide.frame:
self.auto_scroll_guide.frame.place_forget()
self.auto_scroll_single_guide = AutoScrollSingleGuide(self.root)
self.auto_scroll_single_guide.frame.place(relx=0.5, rely=0.5, anchor='center')
def next_step(self):
if self.page_stage == 1:
if self.auto_scroll_guide and self.auto_scroll_guide.auto_thread:
self.auto_scroll_guide.auto_thread.set_scrolling(False)
if self.auto_scroll_single_guide and self.auto_scroll_single_guide.auto_thread:
self.auto_scroll_guide.auto_thread.set_scrolling(False)
self.auto_scroll_button.place_forget()
self.auto_scroll_button_single.place_forget()
if self.auto_scroll_guide and self.auto_scroll_guide.frame:
self.auto_scroll_guide.frame.place_forget()
if self.auto_scroll_single_guide and self.auto_scroll_single_guide.frame:
self.auto_scroll_single_guide.frame.place_forget()
self.restart_note1 = tkinter.Label(self.root, text="请关闭微信客户端", fg="red")
self.restart_note1.place(relx=0.5, rely=0.2, anchor='center')
self.restart_note2 = tkinter.Label(self.root, text="然后点击下一步")
self.restart_note2.place(relx=0.5, rely=0.3, anchor='center')
if self.page_stage == 2:
self.restart_note1.place_forget()
self.restart_note2.place_forget()
self.waiting_label.place_forget()
self.decrypter = DatabaseDecrypter(self, self.account_info.get("filePath"), self.account_info.get("key"))
self.decrypt_note_text = tkinter.StringVar()
self.decrypt_note_text.set("正在复制数据.....")
self.decrypt_note = tkinter.Label(self.root, textvariable=self.decrypt_note_text)
self.decrypt_note.place(relx=0.5, rely=0.2, anchor='center')
self.decrypt_progressbar = tkinter.ttk.Progressbar(self.root)
self.decrypt_progressbar.place(relx=0.5, rely=0.3, anchor='center')
# 进度值最大值
self.decrypt_progressbar['maximum'] = 100
# 进度值初始值
self.decrypt_progressbar['value'] = 0
# 解密过程禁用下一步按钮
self.next_step_button.config(state=tkinter.DISABLED)
self.decrypter.decrypt()
if self.page_stage == 3:
self.decrypt_note.place_forget()
self.decrypt_progressbar.place_forget()
self.init_export_page()
# 不再有下一步按钮
self.next_step_button.place_forget()
# 初始化视频导出器
self.video_decrypter = VideoDecrypter(self, self.account_info.get("filePath"))
# 初始化图片导出器
self.image_decrypter = ImageDecrypter(self, self.account_info.get("filePath"))
self.page_stage = self.page_stage + 1
def init_export_page(self):
from app.DataBase import micro_msg_db
contact_datas = micro_msg_db.get_contact()
contacts = []
for c in contact_datas:
contact = Contact(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11])
contacts.append(contact)
def validate_contact(this_contact: Contact):
c_type = this_contact.type
user_name: str = this_contact.userName
# 不是其他号码
is_misc_account = c_type == 1 or c_type == 33 or c_type == 513
# 不是公众号
is_gh_account = user_name.startswith("gh_")
# 不是聊天群
is_chatroom = user_name.endswith("@chatroom")
# 不是文件传输助手
is_filehelper = this_contact.userName == "filehelper"
return (not is_misc_account) and (not is_gh_account) and (not is_chatroom) and (not is_filehelper)
filtered = filter(validate_contact, contacts)
contacts = list(filtered)
self.listbox = ListboxWithSearch(self.root, contacts)
self.listbox.frame.place(relx=0.05, rely=0.03)
self.begin_calendar_label = tkinter.ttk.Label(text="开始日期")
self.begin_calendar_label.place(relx=0.65, rely=0.15)
# 默认开始时间是100天前
current_date = datetime.now()
half_year_ago = current_date - timedelta(days=100)
self.begin_calendar = tkcalendar.DateEntry(master=self.root, locale="zh_CN", year=half_year_ago.year,
month=half_year_ago.month, day=half_year_ago.day,
maxdate=datetime.now())
self.begin_calendar.place(relx=0.65, rely=0.2)
self.end_calendar_label = tkinter.ttk.Label(text="截止日期")
self.end_calendar_label.place(relx=0.65, rely=0.25)
self.end_calendar = tkcalendar.DateEntry(master=self.root, locale="zh_CN", maxdate=datetime.now())
self.end_calendar.place(relx=0.65, rely=0.3)
self.convert_video_var = tkinter.IntVar(value=0)
self.convert_video = tkinter.ttk.Checkbutton(self.root, text='视频转码', variable=self.convert_video_var)
self.convert_video.place(relx=0.65, rely=0.45)
ToolTip(self.convert_video,
"视频原始格式为H265,只支持\nChrome浏览器播放,勾选后\n将视频转码为H264,支持大\n部分浏览器,但导出速度变慢")
self.confirm_button_text = tkinter.StringVar()
self.confirm_button_text.set("开始导出")
self.confirm_button = tkinter.ttk.Button(self.root, textvariable=self.confirm_button_text,
command=self.confirm_export)
self.confirm_button.place(relx=0.65, rely=0.6)
# 导出成功的提示
self.succeed_label = tkinter.Label(self.root, text="导出结束")
self.succeed_label_2 = tkinter.Label(self.root, text="打开文件夹", fg="#0000FF", cursor="hand2")
self.succeed_label_2.bind("<Button-1>", self.open_target_folder)
# 进度条
self.export_progressbar = tkinter.ttk.Progressbar(self.root, length=150)
def confirm_export(self):
if self.html_exporter_thread and not self.html_exporter_thread.stop_flag:
self.html_exporter_thread.stop()
else:
if not self.warning_label:
self.warning_label = tkinter.Label(self.root, fg="red")
self.warning_label.place(relx=0.65, rely=0.55)
self.warning_label.config(text="")
contacts = self.listbox.get_contacts()
if not contacts:
self.warning_label.config(text=f"请选择至少一个联系人")
return
if self.begin_calendar.get_date() > self.end_calendar.get_date():
self.warning_label.config(text=f"开始时间必须小于截止时间")
return
self.export_progressbar.place(relx=0.64, rely=0.68)
# 进度值最大值
self.export_progressbar['maximum'] = 100
# 进度值初始值
self.export_progressbar['value'] = 0
current_time = datetime.now()
self.export_dir_name = current_time.strftime("%Y_%m_%d_%H%M%S")
contact_map = {contact.userName: contact for contact in contacts}
self.confirm_button_text.set("停止导出")
self.succeed_label.place_forget()
self.succeed_label_2.place_forget()
# 导出线程
self.html_exporter_thread = HtmlExporter(self, self.export_dir_name, contact_map,
self.begin_calendar.get_date(), self.end_calendar.get_date(),
self.convert_video_var.get())
self.html_exporter_thread.start()
def update_decrypt_progressbar(self, progress):
self.decrypt_progressbar['value'] = progress
self.root.update()
def update_export_progressbar(self, progress):
self.export_progressbar['value'] = progress
self.root.update()
def export_succeed(self):
self.confirm_button_text.set("开始导出")
self.succeed_label.place(relx=0.64, rely=0.75)
self.succeed_label_2.place(relx=0.76, rely=0.75)
def open_target_folder(self, event):
folder_path = Path(f"output/{self.export_dir_name}/")
# 转换为绝对路径
absolute_path = folder_path.resolve()
os.startfile(absolute_path)