comparison src/plugins/plugin_comp_file_sharing.py @ 2514:4440ea7047bd

file sharing component: thumbnails integration first draft: if an uploaded file is detected as an image, 2 thumbnails (small and medium size) are generated automatically.
author Goffi <goffi@goffi.org>
date Fri, 02 Mar 2018 17:53:31 +0100
parents 67cc54b01a12
children 353880a5c363
comparison
equal deleted inserted replaced
2513:2d3c9dcec384 2514:4440ea7047bd
25 from sat.tools.common import regex 25 from sat.tools.common import regex
26 from sat.tools import stream 26 from sat.tools import stream
27 from twisted.internet import defer 27 from twisted.internet import defer
28 import os 28 import os
29 import os.path 29 import os.path
30 import mimetypes
30 31
31 32
32 PLUGIN_INFO = { 33 PLUGIN_INFO = {
33 C.PI_NAME: "File sharing component", 34 C.PI_NAME: "File sharing component",
34 C.PI_IMPORT_NAME: "file_sharing", 35 C.PI_IMPORT_NAME: "file_sharing",
35 C.PI_MODES: [C.PLUG_MODE_COMPONENT], 36 C.PI_MODES: [C.PLUG_MODE_COMPONENT],
36 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT, 37 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT,
37 C.PI_PROTOCOLS: [], 38 C.PI_PROTOCOLS: [],
38 C.PI_DEPENDENCIES: ["FILE", "XEP-0234", "XEP-0260", "XEP-0261", "XEP-0329"], 39 C.PI_DEPENDENCIES: ["FILE", "XEP-0234", "XEP-0260", "XEP-0261", "XEP-0264", "XEP-0329"],
39 C.PI_RECOMMENDATIONS: [], 40 C.PI_RECOMMENDATIONS: [],
40 C.PI_MAIN: "FileSharing", 41 C.PI_MAIN: "FileSharing",
41 C.PI_HANDLER: "no", 42 C.PI_HANDLER: "no",
42 C.PI_DESCRIPTION: _(u"""Component hosting and sharing files""") 43 C.PI_DESCRIPTION: _(u"""Component hosting and sharing files""")
43 } 44 }
44 45
45 PROGRESS_ID_KEY = 'progress_id'
46 HASH_ALGO = u'sha-256' 46 HASH_ALGO = u'sha-256'
47 47
48 48
49 class FileSharing(object): 49 class FileSharing(object):
50 50
52 log.info(_(u"File Sharing initialization")) 52 log.info(_(u"File Sharing initialization"))
53 self.host = host 53 self.host = host
54 self._f = host.plugins['FILE'] 54 self._f = host.plugins['FILE']
55 self._jf = host.plugins['XEP-0234'] 55 self._jf = host.plugins['XEP-0234']
56 self._h = host.plugins['XEP-0300'] 56 self._h = host.plugins['XEP-0300']
57 self._t = host.plugins['XEP-0264']
57 host.trigger.add("FILE_getDestDir", self._getDestDirTrigger) 58 host.trigger.add("FILE_getDestDir", self._getDestDirTrigger)
58 host.trigger.add("XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger, priority=1000) 59 host.trigger.add("XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger, priority=1000)
59 self.files_path = host.getLocalPath(None, C.FILES_DIR, profile=False) 60 self.files_path = host.getLocalPath(None, C.FILES_DIR, profile=False)
60 61
61 def profileConnected(self, client): 62 def profileConnected(self, client):
66 if not os.path.exists(path): 67 if not os.path.exists(path):
67 os.makedirs(path) 68 os.makedirs(path)
68 69
69 @defer.inlineCallbacks 70 @defer.inlineCallbacks
70 def _fileTransferedCb(self, dummy, client, peer_jid, file_data, file_path): 71 def _fileTransferedCb(self, dummy, client, peer_jid, file_data, file_path):
72 name = file_data[u'name']
73 extra = {}
74
71 if file_data[u'hash_algo'] == HASH_ALGO: 75 if file_data[u'hash_algo'] == HASH_ALGO:
72 log.debug(_(u"Reusing already generated hash")) 76 log.debug(_(u"Reusing already generated hash"))
73 file_hash = file_data[u'hash_hasher'].hexdigest() 77 file_hash = file_data[u'hash_hasher'].hexdigest()
74 else: 78 else:
75 hasher = self._h.getHasher(HASH_ALGO) 79 hasher = self._h.getHasher(HASH_ALGO)
76 with open('file_path') as f: 80 with open('file_path') as f:
77 file_hash = yield self._h.calculateHash(f, hasher) 81 file_hash = yield self._h.calculateHash(f, hasher)
78 final_path = os.path.join(self.files_path, file_hash) 82 final_path = os.path.join(self.files_path, file_hash)
83
79 if os.path.isfile(final_path): 84 if os.path.isfile(final_path):
80 log.debug(u"file [{file_hash}] already exists, we can remove temporary one".format(file_hash = file_hash)) 85 log.debug(u"file [{file_hash}] already exists, we can remove temporary one".format(file_hash = file_hash))
81 os.unlink(file_path) 86 os.unlink(file_path)
82 else: 87 else:
83 os.rename(file_path, final_path) 88 os.rename(file_path, final_path)
84 log.debug(u"file [{file_hash}] moved to {files_path}".format(file_hash=file_hash, files_path=self.files_path)) 89 log.debug(u"file [{file_hash}] moved to {files_path}".format(file_hash=file_hash, files_path=self.files_path))
90
91 mime_type = file_data.get(u'mime_type')
92 if not mime_type or mime_type == u'application/octet-stream':
93 mime_type = mimetypes.guess_type(name)[0]
94
95 if mime_type is not None and mime_type.startswith(u'image'):
96 thumbnails = extra.setdefault(C.KEY_THUMBNAILS, [])
97 for max_thumb_size in (self._t.SIZE_SMALL, self._t.SIZE_MEDIUM):
98 try:
99 thumb_size, thumb_id = yield self._t.generateThumbnail(final_path,
100 max_thumb_size,
101 # we keep thumbnails for 6 months
102 60*60*24*31*6)
103 except Exception as e:
104 log.warning(_(u"Can't create thumbnail: {reason}").format(reason=e))
105 break
106 thumbnails.append({u'id': thumb_id, u'size': thumb_size})
107
85 self.host.memory.setFile(client, 108 self.host.memory.setFile(client,
86 name=file_data[u'name'], 109 name=name,
87 version=u'', 110 version=u'',
88 file_hash=file_hash, 111 file_hash=file_hash,
89 hash_algo=HASH_ALGO, 112 hash_algo=HASH_ALGO,
90 size=file_data[u'size'], 113 size=file_data[u'size'],
91 path=file_data.get(u'path'), 114 path=file_data.get(u'path'),
92 namespace=file_data.get(u'namespace'), 115 namespace=file_data.get(u'namespace'),
93 owner=peer_jid) 116 mime_type=mime_type,
117 owner=peer_jid,
118 extra=extra)
94 119
95 def _getDestDirTrigger(self, client, peer_jid, transfer_data, file_data, stream_object): 120 def _getDestDirTrigger(self, client, peer_jid, transfer_data, file_data, stream_object):
96 if not client.is_component: 121 if not client.is_component:
97 return True, None 122 return True, None
98 assert stream_object 123 assert stream_object
99 assert 'stream_object' not in transfer_data 124 assert 'stream_object' not in transfer_data
100 assert PROGRESS_ID_KEY in file_data 125 assert C.KEY_PROGRESS_ID in file_data
101 filename = file_data['name'] 126 filename = file_data['name']
102 assert filename and not '/' in filename 127 assert filename and not '/' in filename
103 file_tmp_dir = self.host.getLocalPath(client, C.FILES_TMP_DIR, peer_jid.userhost(), component=True, profile=False) 128 file_tmp_dir = self.host.getLocalPath(client, C.FILES_TMP_DIR, peer_jid.userhost(), component=True, profile=False)
104 file_tmp_path = file_data['file_path'] = os.path.join(file_tmp_dir, file_data['name']) 129 file_tmp_path = file_data['file_path'] = os.path.join(file_tmp_dir, file_data['name'])
105 130