From 0fd38ea70c19debb017b1a3c7683b624509c58ad Mon Sep 17 00:00:00 2001 From: randogoth Date: Sat, 10 Jun 2023 01:46:14 +0300 Subject: [PATCH] office writer --- orvani/plugins/office.py | 74 +++++++++++++++++++++++++++++---------- test/.context.yaml | 10 ++++++ test/office.odt | Bin 9201 -> 8954 bytes test/sheet.xlsx | Bin 4379 -> 4720 bytes 4 files changed, 65 insertions(+), 19 deletions(-) diff --git a/orvani/plugins/office.py b/orvani/plugins/office.py index 469b0d6..81fdcfa 100644 --- a/orvani/plugins/office.py +++ b/orvani/plugins/office.py @@ -1,3 +1,4 @@ +import os import re import mimetypes import shutil @@ -6,8 +7,9 @@ from olefile import OleFileIO NAME = 'office' TYPES = ['.doc', '.xls', '.ppt', '.docx', '.xlsx', '.pptx', '.odt', '.ods', '.odp'] -RE_ODT_CTX = r"((.*))<\/meta:keyword>" -RE_ODT_NOTE = r"((.*))<\/dc:description>" +RE_ODT_CTX = r"(?P
)(?P.*?)(?P<\/meta:keyword>)"
+RE_DOCX_CTX = r"(?P
)(?P.*?)(?P<\/cp:keywords>)"
+REGEX = r"(?P
)(?P.*?)(?P<\/dc:description>)"
 
 # Office Document processing inspired by
 # https://github.com/kappapiana/anonymize/blob/master/anonymize.py
@@ -28,6 +30,18 @@ def unzip_file(orig_file, tmp_dir):
     else:
         return type[0]
 
+def get_context(meta_file, re_ctx):
+    tags = note = []
+    meta_content = meta_file.read_text()
+    tagsearch = re.search(re_ctx, meta_content)
+    if tagsearch:
+        tags = tagsearch.group('body').split(' ')
+    notesearch = re.search(REGEX, meta_content)
+    if notesearch:
+        note = [notesearch.group('body')]
+    return [x for x in ' '.join(tags).split(' ') + note if x != '']
+    
+
 def reader(o):
     tmp_folder = Path('unzip__' + o.file.stem)
     file_type = unzip_file(o.file, tmp_folder)
@@ -36,14 +50,7 @@ def reader(o):
     # OpenOffice / LibreOffice / Open Document Format
     if file_type in ['odt', 'ods', 'odp']:
         meta_file = tmp_folder / 'meta.xml'
-        meta_content = meta_file.read_text()
-        tagsearch = re.findall(RE_ODT_CTX, meta_content)
-        if tagsearch:
-            tags = list(set(tagsearch[0]))
-        notesearch = re.findall(RE_ODT_NOTE, meta_content)
-        if notesearch:
-            note = list(set(notesearch[0]))
-        argv = [x for x in ' '.join(tags).split(' ') + note if x != '']
+        argv = get_context(meta_file, RE_ODT_CTX)
         context = o.context(argv)
         shutil.rmtree(tmp_folder)
         return context
@@ -51,14 +58,7 @@ def reader(o):
     # Microsoft Office Format
     elif file_type in ['docx', 'xlsx', 'pptx']:
         meta_file = tmp_folder / 'docProps' / 'core.xml'
-        meta_content = meta_file.read_text()
-        tagsearch = re.findall(RE_ODT_CTX, meta_content)
-        if tagsearch:
-            tags = list(set(tagsearch[0]))
-        notesearch = re.findall(RE_ODT_NOTE, meta_content)
-        if notesearch:
-            note = list(set(notesearch[0]))
-        argv = [x for x in ' '.join(tags).split(' ') + note if x != '']
+        argv = get_context(meta_file, RE_DOCX_CTX)
         context = o.context(argv)
         shutil.rmtree(tmp_folder)
         return context
@@ -74,4 +74,40 @@ def reader(o):
             note = [meta.comments.decode('UTF-8')]
         argv = [x for x in tags + note if x != '']
         context = o.context(argv)
-        return context
\ No newline at end of file
+        return context
+    
+
+def writer(o):
+    string = ' '.join([x for x in o.collect(o.context) if x != None])
+    tmp_folder = Path('unzip__' + o.file.stem)
+    file_type = unzip_file(o.file, tmp_folder)
+    regex = re.compile(REGEX)
+    string = f"\\g
{string}\\g"
+
+    # OpenOffice / LibreOffice / Open Document Format
+    if file_type in ['odt', 'ods', 'odp']:
+        meta_file = tmp_folder / 'meta.xml'
+        with meta_file.open('r+') as file:
+            content = regex.sub(string, file.read())
+            file.seek(0, 0)
+            file.write(content)
+        shutil.make_archive(o.file, "zip", tmp_folder)
+        output_file_zip = str(o.file) + ".zip"
+        os.rename(output_file_zip, o.file)
+        shutil.rmtree(tmp_folder)
+
+    # Microsoft Office Format
+    elif file_type in ['docx', 'xlsx', 'pptx']:
+        meta_file = tmp_folder / 'docProps' / 'core.xml'
+        with meta_file.open('r+') as file:
+            content = regex.sub(string, file.read())
+            file.seek(0, 0)
+            file.write(content)
+        shutil.make_archive(o.file, "zip", tmp_folder)
+        output_file_zip = str(o.file) + ".zip"
+        os.rename(output_file_zip, o.file)
+        shutil.rmtree(tmp_folder) 
+
+    # Legacy Microsoft Office Format
+    elif file_type in ['application/msword', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint']:
+        print('unsupported file format')
diff --git a/test/.context.yaml b/test/.context.yaml
index 013efa8..77d5e61 100644
--- a/test/.context.yaml
+++ b/test/.context.yaml
@@ -6,6 +6,16 @@ config:
       projects: album
       tags: genre
 items:
+  office.odt:
+    contexts: []
+    projects:
+    - orvani
+    tags: []
+  sheet.xlsx:
+    contexts: []
+    projects:
+    - orvani
+    tags: []
   sub:
     contexts:
     - folder
diff --git a/test/office.odt b/test/office.odt
index f2a6e82e5ba4dbc4640de9e3cc3427eec29c7a10..5f5748e5bdc350d6b3bae55b507d222702f6f73d 100644
GIT binary patch
delta 2615
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

diff --git a/test/sheet.xlsx b/test/sheet.xlsx
index 656c7d04435e52d33c8188f274b4c18f00ea73bf..cfa167b9caee52c5948b826c2ddb42b2b2b85174 100644
GIT binary patch
delta 1516
zcmbQO^g*RQz?+#xgaHJ~xK4$EXc%T=U|@(ZO3f+O$E}8wfq@|yW(Ed^
ziX6B(91I}4A|9R(_2gt^U^vghz#z;p`GbJy=JmYZjA9T6K@_E}YTEvQfq}uAX`;mE
zdWZ}ISUb#_AR6S1iX44HuH}O`qddPTyEr2?wFKd0h-KXs#&5qfGBD&ZGcfQY)F$QU
zXX{nu=Jam%VfumUydM8Hk!B_ahGfCbSu8V{P@LY+#Kf?dfq`KL<77j|`%)0MLoDLC
z$*b?o%)k)F&cGnSFj-eXYO@==D>I7rPw&GU%NQ9LzA#PR$faEG5_^mHSjbjcrY*vg
zCv4+9qN{RGEaS4q$9?~7J$IK0zj3(Q{Pz2woa27Se{bU0mat|`h})w$7p8zcLP2Yd
zHqG!qB*>{_q#6;ZdEx}4j^y)j&Fh@&dG^fmYIfu_D{wlc7L%URyF%DYH{SVV&UwQr
z%+sf8N?KiCvm))!?6nQw7T0HZcsr;`7`HIF{lb4f~
zIn56UxIAE)v@E835AVEr&xI#_U;Iy@r!CQB)_3;K|L^UCerez5HY-al>Ypc*UeCSZ
zjz@1^`%mB0Z9XR-G;VHUzs_;3_Qkcx^tr~hX$P-lJvN)z%q6~g)}_`zecWkfngTo=6D`K#(G935oX+329zEd7z7ypI)YfRB#B!O
zDD8q&LiDJhW+-gh+##w#c?!Y;+2svMt^wXK9T2yJ^B6pfL6n2YEsZ?~lv3q(00
zw=pnqgVaIsmd0m{u);tOR3sqm!JZi*`alkQ&jil;IKrVGq7Y1iawnJp4m>etus)Q$
zit0D?+zQdlz_6v!385F3cM%ST_!OFPjTw>!85nqBS{XpP(^$ba7nfA#q!xqnJ(}Lh
z0sN9ITN*_;Cg<`ia)DC<*v!cS0w8ft&dIt0^7RPuFhovfU=T#Hs)+}w_)N|(O2uMb
s7&!fblOHIFAoOo(ROds|o>))-(aj1fxcM1)8F(3Zm>C%SKqVOi0J$}bAOHXW

delta 1167
zcmeyMGFwR^z?+#xgn@&DgMnl5i7*B@nEa3Nvl=@`+N!4Q4;UC2teF@Xa4OZ|xUa^}
z(a*%hu$O^>VFn{^rJJLe`Iyw$Il3#1-+pIgV8~;}qqdH921sp>f15}%69YrCARe`f
zoXN~;>>NBddG(!{85qLYajTs?i$}RW?=rtc@YXVp3w}OMNx~h`9((mJEDLSDWXk#vNuVWVDIh
zdD+jaEvu)POU0Eec38~tI8re)Xr0j}w-C*xZR;1NscqoNJQ%t-yY1Rl)zF^$%|aP6
zZS~4g%$u4N7yDfZZ&tGO604aIA{|@G#JW7dkynVfx2a>^4vt-B;=)!>dLp^+Xz%cN
zd$4h@agxHeToz9O
zH;!>TnzD1F^a;mbr?2-JwcN?mPAkY;pP;&+;>PVR@ub@BuZG|LOXgpC@h#_A+=A6>
z61DFbJ_`&lDTuwE_W38P3_rht#WlA^QJF(~e?E8kEFa*_&cU#5A5%Uf1H&7X1jL7$
z*f!hq2{Nj&b4Wfnef5)pfngS&B($+5g)xksBjVxtP)|k%hVv|-m}X=WVL+r}