From 119b08202495c3669b4c0f4237051bed18666a3b Mon Sep 17 00:00:00 2001 From: wuyanyun Date: Wed, 3 Jan 2024 21:11:23 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=B7=B2=E8=BF=87=E6=9C=9F?= =?UTF-8?q?=E6=88=96=E4=B8=A2=E5=A4=B1=E6=96=87=E4=BB=B6=E7=9A=84=E5=A4=84?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E5=92=8C?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=92=8C=E7=B1=BB=E5=9E=8B=E7=AD=89=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E9=9B=86=E4=B8=AD=E5=A4=84=E7=90=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E7=94=A8=E5=88=B0=E7=9A=84=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/DataBase/exporter_html.py | 63 +++++++++++++++++--------- app/DataBase/output.py | 34 +++++++------- app/resources/data/icons/csv.png | Bin 0 -> 6549 bytes app/resources/data/icons/excel.png | Bin 0 -> 6094 bytes app/resources/data/icons/file.png | Bin 0 -> 568 bytes app/resources/data/icons/pause.png | Bin 0 -> 1684 bytes app/resources/data/icons/pdf.png | Bin 0 -> 5474 bytes app/resources/data/icons/play.png | Bin 0 -> 1875 bytes app/resources/data/icons/ppt.png | Bin 0 -> 5126 bytes app/resources/data/icons/txt.png | Bin 0 -> 4937 bytes app/resources/data/icons/word.png | Bin 0 -> 6367 bytes app/resources/data/icons/zip.png | Bin 0 -> 6641 bytes app/resources/data/pause.png | Bin 386 -> 0 bytes app/resources/data/play.png | Bin 716 -> 0 bytes app/resources/data/template.html | 70 +++++++++++++---------------- app/util/compress_content.py | 58 ++++++++++++++++++++++++ app/util/file.py | 16 +++---- 17 files changed, 158 insertions(+), 83 deletions(-) create mode 100644 app/resources/data/icons/csv.png create mode 100644 app/resources/data/icons/excel.png create mode 100644 app/resources/data/icons/file.png create mode 100644 app/resources/data/icons/pause.png create mode 100644 app/resources/data/icons/pdf.png create mode 100644 app/resources/data/icons/play.png create mode 100644 app/resources/data/icons/ppt.png create mode 100644 app/resources/data/icons/txt.png create mode 100644 app/resources/data/icons/word.png create mode 100644 app/resources/data/icons/zip.png delete mode 100644 app/resources/data/pause.png delete mode 100644 app/resources/data/play.png diff --git a/app/DataBase/exporter_html.py b/app/DataBase/exporter_html.py index 9e468b2..ebc35d4 100644 --- a/app/DataBase/exporter_html.py +++ b/app/DataBase/exporter_html.py @@ -12,13 +12,24 @@ from app.DataBase.package_msg import PackageMsg from app.log import logger from app.person import Me from app.util import path -from app.util.compress_content import parser_reply, share_card, music_share +from app.util.compress_content import parser_reply, share_card, music_share, file from app.util.emoji import get_emoji_url -from app.util.file import get_file from app.util.image import get_image_path, get_image from app.util.music import get_music_path +icon_files = { + './icon/word.png': ['doc', 'docx'], + './icon/excel.png': ['xls', 'xlsx'], + './icon/csv.png': ['csv'], + './icon/txt.png': ['txt'], + './icon/zip.png': ['zip', '7z','rar'], + './icon/ppt.png': ['ppt', 'pptx'], + './icon/pdf.png': ['pdf'], +} + + + class HtmlExporter(ExporterBase): def text(self, doc, message): type_ = message[2] @@ -95,21 +106,33 @@ class HtmlExporter(ExporterBase): def file(self, doc, message): origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" bytesExtra = message[10] + compress_content = message[11] str_time = message[8] is_send = message[4] timestamp = message[5] is_chatroom = 1 if self.contact.is_chatroom else 0 avatar = self.get_avatar_path(is_send, message) display_name = self.get_display_name(is_send, message) - link = get_file(bytesExtra, thumb=True, output_path=origin_docx_path + '/file') - file_name = '' - file_path = './icon/file.png' - if link != "": - file_name = os.path.basename(link) - link = './file/' + file_name - doc.write( - f'''{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',link: '{link}',sub_type:6,file_name: '{file_name}'}},''' - ) + file_info = file(bytesExtra, compress_content, output_path=origin_docx_path + '/file') + if file_info.get('is_error') == False: + icon_path = None + for icon, extensions in icon_files.items(): + if file_info.get('file_ext') in extensions: + icon_path = icon + break + # 如果没有与文件后缀匹配的图标,则使用默认图标 + if icon_path is None: + default_icon = './icon/file.png' + icon_path = default_icon + file_path = file_info.get('file_path') + if file_path != "": + file_path = './file/' + file_info.get('file_name') + doc.write( + f'''{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp} + ,is_chatroom:{is_chatroom},displayname:'{display_name}',icon_path: '{icon_path}' + ,sub_type:6,file_name: '{file_info.get('file_name')}',file_size: '{file_info.get('file_len')}' + ,app_name: '{file_info.get('app_name')}'}},''' + ) def refermsg(self, doc, message): """ @@ -200,16 +223,16 @@ class HtmlExporter(ExporterBase): timestamp = message[5] content = music_share(message[11]) music_path = '' - if content.get('audio_url') != '': - music_path = get_music_path(content.get('audio_url'), content.get('title'), - output_path=origin_docx_path + '/music') - if music_path != '': - music_path = f'./music/{os.path.basename(music_path)}' - music_path = music_path.replace('\\', '/') - is_chatroom = 1 if self.contact.is_chatroom else 0 - avatar = self.get_avatar_path(is_send, message) - display_name = self.get_display_name(is_send, message) if content.get('is_error') == False: + if content.get('audio_url') != '': + music_path = get_music_path(content.get('audio_url'), content.get('title'), + output_path=origin_docx_path + '/music') + if music_path != '': + music_path = f'./music/{os.path.basename(music_path)}' + music_path = music_path.replace('\\', '/') + is_chatroom = 1 if self.contact.is_chatroom else 0 + avatar = self.get_avatar_path(is_send, message) + display_name = self.get_display_name(is_send, message) doc.write( f'''{{ type:49, text:'{music_path}',is_send:{is_send},avatar_path:'{avatar}',link_url:'{content.get('link_url')}', timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',sub_type:3,title:'{content.get('title')}', diff --git a/app/DataBase/output.py b/app/DataBase/output.py index 88d01aa..e8dd1e8 100644 --- a/app/DataBase/output.py +++ b/app/DataBase/output.py @@ -5,6 +5,7 @@ import shutil import sys import time import traceback +import filecmp from re import findall import docx @@ -51,21 +52,24 @@ def makedirs(path): os.makedirs(os.path.join(path, 'avatar'), exist_ok=True) os.makedirs(os.path.join(path, 'music'), exist_ok=True) os.makedirs(os.path.join(path, 'icon'), exist_ok=True) - file = './app/resources/data/file.png' - if not os.path.exists(file): - resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) - file = os.path.join(resource_dir, 'app', 'resources', 'data', 'file.png') - shutil.copy(file, path + '/icon/file.png') - play_file = './app/resources/data/play.png' - if not os.path.exists(play_file): - resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) - play_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'play.png') - shutil.copy(play_file, path + '/icon/play.png') - pause_file = './app/resources/data/pause.png' - if not os.path.exists(pause_file): - resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) - pause_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'pause.png') - shutil.copy(pause_file, path + '/icon/pause.png') + resource_dir = os.path.join('app', 'resources', 'data', 'icons') + target_folder = os.path.join(path, 'icon') + # 拷贝一些必备的图标 + for root, dirs, files in os.walk(resource_dir): + relative_path = os.path.relpath(root, resource_dir) + target_path = os.path.join(target_folder, relative_path) + + # 遍历文件夹中的文件 + for file in files: + source_file_path = os.path.join(root, file) + target_file_path = os.path.join(target_path, file) + if not os.path.exists(target_file_path): + shutil.copy(source_file_path, target_file_path) + else: + # 比较文件内容 + if not filecmp.cmp(source_file_path, target_file_path, shallow=False): + # 文件内容不一致,进行覆盖拷贝 + shutil.copy(source_file_path, target_file_path) def escape_js_and_html(input_str): diff --git a/app/resources/data/icons/csv.png b/app/resources/data/icons/csv.png new file mode 100644 index 0000000000000000000000000000000000000000..28b84e21b45dd71616d77a0db943a5fd87f0cea4 GIT binary patch literal 6549 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 O!es`&ZGtt1$NmpFZSdA`o;+}Ax%u3DQP*azOn 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 literal 0 HcmV?d00001 diff --git a/app/resources/data/icons/pause.png b/app/resources/data/icons/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..5cdcf61ccb1762cfc6159ce23c1305069167d1bf GIT binary patch literal 1684 zcmV;F25b3=P)BOgQB-%G;Gy?1^mGn2XZoJ&|CjvYJpd`nA9A2aU)&;?*KfOY^I zWRu4L9s&3rz&#?$nx;9COeXKI#Pw-8ogUZXAz z1rmuw`~Xe>I0!(ATb4Bg078hid_LcyD9Tm<+lgqOyn7zm z-vV$Iz?boOJhQ5SL?V%m08RnucjN&~F!Q&wv$I#m#>O7iGhQGNXm4$8Jw!x@0rcVD zpvD25j>qGF)jC$qfrLV#BSMJJ0ki?g6H#h@e*WC(=;&|t$X7zw_0FcIrsK@40Z;+V zSeEtK$jHdowe+tV$iTor^W5Cr5D~o#0L(logcyv)VpGdgFHbZY-Cs|7C zy@O}Zo_(@ZKV_+tnx?g>s`?cXy$+zj%)_}{?xSQf`S%LCFCd*xKj`Y}`r7ODT12#u zh;|l>#g{ufJHMZrnwqcFui_m!di3aqmX?-p0PF&gW9G177(cCsd?mu+a4!)V0DJ(l zrfI%+;lhQ-<=U1FWME*R`N@+f=K&l5aKBhAzMn`W?yjD4WrD%rRz*=R0(c(4wdUsL z56V4eVsTesZf4od zD!W!ClgZ@v?AbF3;4l&G?CI&bpUGrym9|+BNF);3NJQrWG%@pVJRVQ2rSMXu)9F9` ze!n21ULxARd-v{3>2!L=IsfdVbqYWmGf(Dnxif34TAf@jcZQiKVSmd`m7aSVh@5ux z1IP;@22-h2acwoLlS-wELWn^Cc>w*=8Nk9jasmK|DAnl4E*K2Hsq1=YwRXC$cLsyO zHygP|EEbz0BIl7m;T#u$J&T1s0W8eV&!21L0^xADTTzsRs;a})+N!ELtSCw%91eFk zaxLjt0B}&c+kp^Kzx;io(Ycclq6Gk$xusfLr;XF6UZmp$03qG&K;(J?%=~R51G|Ca z>bMJC*Ehjl6cuJ?XRo*^R}a#)0AQQ0>zjnfWE@p$$N zB69%V%R7p&YK17lnqo>opw*D zF-n}<1!UgI$#$$KN}M;8U5~6s1ndkTgb-~myVOmI^J4)!jfs3d-{GE8W0W{Q60mcz zkQu;rMTzt80)Ufm-R_dla&VmQ2_nh@01@qTQK%stXClf9(=;alfSGp%0)cjS)oLdY z2(-&2I84)=5VAgT2Y{!wwe^s@dbJ~6Jpk?`lgaze!s@d8dDu<4dT?AFcV}TW4!b_l zSIe5a9F}F7a$vIt3A40My-3GC0G4#O1Cf=Ys{lMrO-;ue8Qd_8NoEcK_@svBpD=UC zFpSAYt|c8k0IoV!uBW+QnOgY{cJ1S>)hZh-muNJ)gPFgFT|;@>sct=;YsmxS094De zhBQrEvgF_fnx-k1Wevd&V!X6O_w1zcG=Lc*>h}43C)ZN47JNS6Nm&4zf$jQ~1%LH) zIz7|V)AN9c-XNlVe!u^hOeXWkTFO>J)=Gu|2+OiQH4J0H(tOe5lgVUm`ThPEiD)Mg zz24p3{lkqLHy*B;aT$Wa;8r2TMF6eLd}(B4gzV*Y!;vk7vJ3idWru#>~GK3WXm> eM@Ls==I{@g`?|lZIZ3(z0000Mnxcq z6zK?g0Rx7r6d|F_#cyWtoBuPv=0~0<&pCVVwf5TUoSWQ)>lUUgr}$4%QBkp&T{ePH zQBi}AJ`8lgN_f=s5GpEeX)~isH^VYlrdR{4hO^%N+Hhsl%3@hveagZpO+s$Gi47AypX% z+gP?s4)tbJJRHfR1cjXmm8%xhIg!(C3t4OK^W9B>%nBOYQEl7U$Tjfmhn|(?nf+fg zGzSX5a=KPe6n>`R6OnQ`8$>S@{=Lfk%Nw=b64|PIMm#SAq{BZ}Hnlc4s}JiaWLb=M z->#>AQdrtBa>Xv%sd+0eUjD3YcY3m^kDs)NmPXoQmiwTIAuU%Hoi}CCYCcxZu6f$A z{otR3;03=F1@Sz{x>WQ0;^N83P`J84O19_yGj0f!?hc`%Jt}f4C7!+FyLop(3BPRV z;+1B&MkgwXW79XFVADH1YO_0#WcGAILv9u!HUbjg&~>Q z#ockq4!B}Bn}8Z>4$ve_I-gtbJZ@2Iw6t+S5#WaeV}??gc)nezZwf~ z(jz;6ow<*a;Or!0F0(@11l%%s)KrP4HOU_{wCmqGurUZ<%?_hDG`7nmN+B-Cc7)sf zyef)=*n=GGrNfPis$18oT?Tmt-f=#n1G87mnstjSJ#&%SG8$k6s<0VjhWbPf`&e^! zI-7E;{JnS6K<{6A#9BGNMCwub8*ziSdbaeUcQB|CsI10?;|C1*^5Y<6VWd;jyGbJj&%3 zhng!O=TEaf5{EL_RwGcFlarA-ejcyvw|{=4uHv_8g`Z4ezcx*6S@USi+AZL~t zIp`r2G|v|!ZRq*{Ch8GL5B8lq&3fwym;-@&3)R#D+5?+oxCZ!-T1n>m+dYa509#2p z=wed_c58*RvgLP<>tkvF0{Ia}>KObs;~a35efua|@F<%f)FC8%z;*Oh5Y*8z81ods zG-E}I*~S1psfZv@Dz*wy3#$pmgpl2`nlm7vKA8hF+%VIwIr6#nt>*Vc6eAB}{st!1 z5hS!OBn)89+hJ~Y4IC-{0tc}hDc|qNb02<|?tJ}d&l_{|F)x@CPc}mh2pemaNL$e)4)j>`H%2Z?r4!q{o{T18kR{b3qSH%zl zwb}du(guA4@J5{hS(P3E+oI{fX}9YDJZn4-;$L}dHxRtPR|;ubO*#q_23eW^;UM=A zhK3{@K^rh4C&IukyMZZ|lZ)_c{n zL55WT1Gym>NmBdTh(c?NA34efpRW#}@^}H~r>F6cG(16=RR2Gue&8T$Z6jXUuY!lI z(zP3BoZJ)#fM7K*AJpqzf&yO32W$VQ`>D3J`DQpA&!B5`gzC`dsXSLbe8+x8;+DZK zlftq?$QKRM(Z)u9WXDHQD8qDhqW^_Xhrp(%xsFb4&E8Yr;tUtz_4ThG9&Nf?yuK}O z|LZKDUPl$!Fw%m8jOn&dlvL`p;hdON7A=ChCkKW6%58@9g2xFZ!TX|Z`*^9I>1wzT}&}lzgDyTf~Wc%)e6d5u@0%q zW=$VX;!b?@kBI0kjH8`TE#vLxpxgKnu8fUY#m5(QUr?iA+WC065_A97o?g`}OEdIKZ-$*8mAIEm@M(iB%wp65|F+X~EPkCNhRkh|J&Z90m zjHn0F+?|Q>PwmJTgX-%=_|6>Ai+J(q^pyH=jvhJj!aLKc$lhujd%rI`^XjgQh65h^ zKi+uvwf;;H(Uwm%zJ$4d=||;^P5PAcxy+bskh4?=_J}-PwR)DC$a6|+lk0d^CbiyE zY$9r*SF7j@JnSs=9oy!JvKAcv8oY*0k*jd#k_CK<=`!;EB&VL?qL3r!gu6a%U;BFw zNg-Rw9~tP~1*HManS8$aHUH+9oM1V}=G~T-?ER76_$I*iCu(weFR!JZ{1v0PT6>4m z*zS2c8y{Ga_qO$jN=@MaCAVzy-nS_iFAHtlJ@SP2XZNQ1^;{L(^Msvefl5!ga3_Ka zdCl9~izhenS_yOQVTG@?7fuC_rCYe$1XA%Han={6`1_*wA=1G+-#I_?V)rCBn&!Nk z>P&w~YFj#iu43+=_<_uHkVc;<+YDsABsJEH6{3s$Tpiy%$&q`>!8b>P*)qm(? zXP*bm=RFCfBNTLRNnJ+==O4ljdM6$+ORCzA6Hq|VhM70EZn7uuL&U%AO|-1M{Dz2w zQ3uHQ{?_sws1)jZ#lQxlvS0^MO`nBQwO+zdg~h_Cf70Pj{KJBveJ4P}bRRf$RQ^EF z{|Edp>Oj11)lL%CeZyLh}7I?mH&s~FaYa)n`v6$lN z5m3QwKX1&ExNL9F_VjttrKBn&_n{vHcPIsApD)Fab|u^KyRiHmLGo-ck(DhvvJC~E zjo^d7q*;zJAWu@>V}F<~x!$}-LBz~c1gV-8(>~Z*|BznN1A#%T=bYH8m>OSN2ByI{#9rEb)Ez7mMId(fDqu zquP(OCW$%SxeDu6HK;WIx@4|$W}WOg%GtZg^VeUHe7(Hzk*C3oxS)3pHA@d}MB#|w z#&0HR&(vJJ&%ge4c8W?$njxXAnfB%o!D zP0lhf)E1l+tnua%K@jizx+$nYPm-8oW|wb8{i+$KeBi0I4rL8S5eUW@x*O+a`1L|c zH5S)z-RdlJi;f~ZAeW5KC&4=6VHz;I@q*LVpFWP)_L_lt1v2g(tlp+8)6+raHaI(5 z&jhi{O$u_9@34XBePknb2fC2hF5d+f5}_<6Mt=5`^(Tph5z87{jneWf$hacC^n-hr z)xDy)C#-)uG~IvCf7$7udM4g3j{w=C%r{>HbKb_HHs4Ow5x4Cc8#Z5!JdrLo4m~@q z7EdFqOVdL=iC@)(MobUcj8+M(ceGWLtZUKLW+vli2AI?Xdy2M?zmmse)hbN%hz6s~v)TCiu`rhBc> z*X9NP7jj{v{m1Z*Phsdp*T#SnxtI3YhJy%{PoEhn0qL#Kbkl@fdyKlkk!Wz`@P+Bs z;X*Sd%8e#%dON|{Q%Fru636&fmSh2ryE)D6m`0x@&m#=2Z2AT=nZJA{lx540TW({% zM@p|jLjw9s6nc8h`nLoPxG!u}nNa(32!@`qnCT)yr}Y1AUp9Rq={t;Nd)`3aF8SnN zBMeS37Ojlf2noKwtj2QgPn5Jy-rbTVDJG2_zkj1at}!+tt|Mxrsw8N7LN$`J_oIuK zdFDT;#W(F8u*v<)O(qy0c+Y25B{SBMfR;xQ$>rIg4B2BNv@8K6PDE2E9rMJ<)t8o` z$-*F2c#nV~*6!6(UxxEBAY7C;Q?!kDeJn$<*EO&X)12;I;mK3vY}LI^Xr{#>;WAg@zXYpgiH_)>r3-JJ(sjr z{T5<~5yVt1Q^*lbenjTNyg^pqepdf36H(`1I#8J$7mEgsr-s-B7%g-dfM(W{Vzq zjgY=p?_fY&A2S(@b&HHPhZEMr;l0N`ucW^grFqVo$$$f)`c3O0`2g!1d>J$QFHy+Y z`?JZLFc$cVD>ksY*BMLT1pW#E9t}ls3+X%<33Wd;weJ{+M=Rm8d`~l4-}^%{3ufFI zN>H%s>P8;B7RX@PAIiL?;KRSJ)-RKj*rx1r3`8T#|H0RRoAT}NwX%SSBnQ@p$?xly zcVhp#O*qTn|ET>c52``DXXDQsK>e-s>iF5foJ61r;Gnr3sOXY@mC%R@lA0NOj``7iL zfP#@sJ&4T$MLEAy0WsaV*$UWFLA7Ns>@K$6uN@*QT=+3CIyEw#j(W_Y%)mdz7Q@N~#5sA;6 z?*nHC%YQE{tZ-v}%f}A9^jYLHZEcMxW1^o^Fg$WcjO`ZYrc1c7?E%$&g7?^#g=<#AvH<#%Vp_&k&8R|V zYW-098v;BlUO7Hu9KIO5tVmLEST*&1T{OKwXnmgwdx8q|Dltv@>$x`jI4aoZXz?#z zVeY&9e8ysfFjX5Hk+IsAC2_tJ_xS?f9mF^iMt;lknE+epB1LZRK~LqYaa1Re=CA9S z;Mg1IKXe%hgT8d0$j#S2lo4Ntp+BuZQFHlxF`SCQQf8|*E^CF;l}lP3S6Wi4+@|xQ zn@#_*nC@8ij0AKMxsG>-oQuk5rlyft46dRC^OQ%WFW&V>7VFvaP}7JGE53i4$u^9- zcv6E2Iok?4d*OK~t#T$EIPkX?+vA&yp&I?VP9|S29=$WrM<@Q~$jk%Yd_D1?MwMQy zh8Qy;n^CQ|tM?wMcd_X+UKXfz9jJu!WQe_t<{HH+&wTa%Zc3aod}oJ#US~FJ9CdCt z;E6D(eoc(DIw@hx+apF*RVXYN_^yj=={S^G0Y#+!>K+-n@}73*>{hOimCp6$iqeDI zEY>Cjvm*2=`CL|IN=M*2RTA^$6`A@wMiJkAD=p}Hjl~edIiJeZhaJ)_G8jEwN{NgX zNpcsS!>PZJ0;OwjIR^WpQ^#AKBEG+oFe+^)Q1`Bg3YBNI)C2EMsmzQmj4BOai2ne~ C@Hk`u literal 0 HcmV?d00001 diff --git a/app/resources/data/icons/play.png b/app/resources/data/icons/play.png new file mode 100644 index 0000000000000000000000000000000000000000..596fcdcc4782b3f0fa90b356a48519afeab56215 GIT binary patch literal 1875 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 literal 0 HcmV?d00001 diff --git a/app/resources/data/icons/txt.png b/app/resources/data/icons/txt.png new file mode 100644 index 0000000000000000000000000000000000000000..f2fc0608b8dbc031584d4c16032ffb0c60820d00 GIT binary patch literal 4937 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 N(bqkv^FRv|^)GA_GK2sC literal 0 HcmV?d00001 diff --git a/app/resources/data/pause.png b/app/resources/data/pause.png deleted file mode 100644 index cdf0cf46c15b79ea00d7dbe024aef64a565c8898..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 386 zcmV-|0e$|7P)Px$JV``BR5(wiQ$cQnFc6$|6qHW{Ij6!aN?uZUNs^a@z9jS&kQ0=Aq9T&FS_@Oh zLNrxlTm(Qe|1{Okj90Gbe?|Fs2a-L~MUh@#JmII?WTRR0-cE|YsO zk~7Dmk@O}bV=l~Gq_=xHS$Q01E^eF)&7zfEMK4T02?Rd9WFlnwkVcyez0t~;gP%Yd gGZTG4sWJ@NH)YxMaK?Ep)&Kwi07*qoM6N<$f@j&Be*gdg diff --git a/app/resources/data/play.png b/app/resources/data/play.png deleted file mode 100644 index 09f6fe269bc75ecbcb85b65ce841ab8cb1d21fd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 716 zcmV;-0yF)IP)Px%hDk(0R9HvFS8Zs|=B1bCp|4&Xl^Hc(Z~qWP>ZNvasY zel~d(0M7uRG65O{__H`1UrT^w0qpPZUW5=^c9;&J|5Mhqgiyo=0%&H2RRkmn;O}g* zWrsG1xLJIhcCpNKc>t7X+cgNW)EEIaDK?@2-tX_;>>-G&RNxSxp=4{r#{6)64DAa7 zV8I)da&@V&Odw)Jblsa~1z`8m@U0as=RgHlfYx8o@1y zvydCV6b=AeH^h4Wae4~YR!x=cx-}vytg1~ZL#C|0C>;PL*?XNqPPXf$Bp`iDM%G?U zmxCT07JL9m@6Qj%Xm?luh_&ew0Lb?IAjn<|Oj|aP5noKLCNTqm1O-)9lPwDX+iocr zv}IsoJOk*hcAYa04#0SW&aQ2@4kLY*PFak`cnk|5ba1GgseJ>B#0ELyNbw<-uM40T z8qJNM@gxC+=qY6&Qi73#CQD!)FyR3N=qDl!mG3OV-nXeuMz!NiMA|Sr_2>-dGml1~ zt`7_oFlEEulp}+$v8ssfv=Om;1@{@(iW8pg441y;XkHXg$|5V~<1^<6Dckj*@d@j@ zY-$|;=q|t*Gc&-kVDmia`K-nFVt%N3Q7=UZ7*+CN-+cxu9aC$E~_00X> z88ii=^Gzu?-167*@%KO@0BZX&qSFxiTY-V4zeUVt0nka74aDDU;>Dy;6gVlu%*{qY y+b+$=2<_Eu(2{bOGbI1)A_huT|DAm|2k-^V*a|;lF?f{#0000${message.file_name}` - }else{ - messageFileTag.innerHTML = `
文件已丢失
`; + messageFileTag.onclick = function (event) { + if (message.text !== '') { + window.open(message.text, '_blank'); + }else{ + alert("文件可能丢失、过期或不存放在该主机上") + } } + if (message.file_name.length >= 26) { + message.file_name = message.file_name.slice(0, 25) + '...' + } + messageFileTag.innerHTML = `
+
+
${message.file_name}
+
${message.file_size}
+
+
+ +
+
+

${message.app_name}

` return messageFileTag; } diff --git a/app/util/compress_content.py b/app/util/compress_content.py index 8ff8b2f..94742e0 100644 --- a/app/util/compress_content.py +++ b/app/util/compress_content.py @@ -4,10 +4,13 @@ import xml.etree.ElementTree as ET import lz4.block import requests +import re from urllib.parse import urlparse from bs4 import BeautifulSoup from app.DataBase.hard_link import parseBytes +from ..util.file import get_file + def decompress_CompressContent(data): @@ -206,3 +209,58 @@ def get_audio_url(url): except Exception as e: print(f"Get Audio Url Error: {e}") return path + + +def file(bytes_extra, compress_content, output_path): + xml_content = decompress_CompressContent(compress_content) + if not xml_content: + return { + 'type': 6, + 'title': "发生错误", + "is_error": True + } + try: + root = ET.XML(xml_content) + appmsg = root.find('appmsg') + msg_type = int(appmsg.find('type').text) + file_name = appmsg.find('title').text + pattern = r'[\\/:*?"<>|\r\n]+' + file_name = re.sub(pattern, "_", file_name) + appattach = appmsg.find('appattach') + file_len = int(appattach.find('totallen').text) + app_name = '' + file_len = format_bytes(file_len) + file_ext = appattach.find('fileext').text + if root.find("appinfo") is not None: + app_info = root.find('appinfo') + app_name = app_info.find('appname').text + if app_name is None: + app_name = '' + file_path = get_file(bytes_extra, file_name, output_path) + return { + 'type': msg_type, + 'file_name': file_name, + 'file_len': file_len, + 'file_ext': file_ext, + 'file_path': file_path, + 'app_name': app_name, + "is_error": False + } + except Exception as e: + print(f"File Get Info Error: {e}") + return { + 'type': 6, + 'title': "发生错误", + "is_error": True + } + + +def format_bytes(size): + units = ["B", "KB", "MB", "GB"] + + def convert_bytes(size, unit_index): + if size < 1024 or unit_index >= len(units) - 1: + return size, unit_index + return convert_bytes(size / 1024, unit_index + 1) + final_size, final_unit_index = convert_bytes(size, 0) + return f"{final_size:.2f} {units[final_unit_index]}" diff --git a/app/util/file.py b/app/util/file.py index e2d8c56..8c8562f 100644 --- a/app/util/file.py +++ b/app/util/file.py @@ -20,25 +20,21 @@ class File: self.open_flag = False -def get_file(bytes_extra, thumb=False, output_path=root_path) -> str: +def get_file(bytes_extra, file_name, output_path=root_path) -> str: try: msg_bytes = MessageBytesExtra() msg_bytes.ParseFromString(bytes_extra) - file_original_path = '' file_path = '' - file_name = '' real_path = '' if len(msg_bytes.message2) > 0: - file_field = msg_bytes.message2[-1].field2 - if file_field.find('sec_msg_node') == -1: - file_original_path = file_field - file_name = os.path.basename(file_original_path) - if file_name != '' and file_name != Me().wxid: + for filed in msg_bytes.message2: + if filed.field1 == 4: + file_original_path = filed.field2 file_path = os.path.join(output_path, file_name) if os.path.exists(file_path): - print('文件' + file_path + '已存在') + # print('文件' + file_path + '已存在') return file_path - if os.path.isabs(file_original_path): + if os.path.isabs(file_original_path): # 绝对路径可能迁移过文件目录,也可能存在其他位置 if os.path.exists(file_original_path): real_path = file_original_path else: # 如果没找到再判断一次是否是迁移了目录