mirror of
https://github.com/element-hq/synapse
synced 2024-09-01 12:10:21 +00:00
Get the code actually working
This commit is contained in:
parent
cc84d3ea78
commit
e5275d856e
6 changed files with 61 additions and 52 deletions
|
@ -37,6 +37,7 @@ class BaseMediaResource(Resource):
|
||||||
|
|
||||||
def __init__(self, hs, filepaths):
|
def __init__(self, hs, filepaths):
|
||||||
Resource.__init__(self)
|
Resource.__init__(self)
|
||||||
|
self.auth = hs.get_auth()
|
||||||
self.client = hs.get_http_client()
|
self.client = hs.get_http_client()
|
||||||
self.clock = hs.get_clock()
|
self.clock = hs.get_clock()
|
||||||
self.server_name = hs.hostname
|
self.server_name = hs.hostname
|
||||||
|
@ -120,6 +121,12 @@ class BaseMediaResource(Resource):
|
||||||
send_cors=True
|
send_cors=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _makedirs(filepath):
|
||||||
|
dirname = os.path.dirname(filepath)
|
||||||
|
if not os.path.exists(dirname):
|
||||||
|
os.makedirs(dirname)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _download_remote_file(self, server_name, media_id):
|
def _download_remote_file(self, server_name, media_id):
|
||||||
file_id = random_string(24)
|
file_id = random_string(24)
|
||||||
|
@ -127,13 +134,13 @@ class BaseMediaResource(Resource):
|
||||||
fname = self.filepaths.remote_media_filepath(
|
fname = self.filepaths.remote_media_filepath(
|
||||||
server_name, file_id
|
server_name, file_id
|
||||||
)
|
)
|
||||||
os.makedirs(os.path.dirname(fname))
|
self._makedirs(fname)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(fname, "wb") as f:
|
with open(fname, "wb") as f:
|
||||||
request_path = "/".join((
|
request_path = "/".join((
|
||||||
"/_matrix/media/v1/download", server_name, media_id,
|
"/_matrix/media/v1/download", server_name, media_id,
|
||||||
)),
|
))
|
||||||
length, headers = yield self.client.get_file(
|
length, headers = yield self.client.get_file(
|
||||||
server_name, request_path, output_stream=f,
|
server_name, request_path, output_stream=f,
|
||||||
)
|
)
|
||||||
|
@ -147,7 +154,7 @@ class BaseMediaResource(Resource):
|
||||||
time_now_ms=self.clock.time_msec(),
|
time_now_ms=self.clock.time_msec(),
|
||||||
upload_name=None,
|
upload_name=None,
|
||||||
media_length=length,
|
media_length=length,
|
||||||
file_id=file_id,
|
filesystem_id=file_id,
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
os.remove(fname)
|
os.remove(fname)
|
||||||
|
@ -158,7 +165,7 @@ class BaseMediaResource(Resource):
|
||||||
"media_length": length,
|
"media_length": length,
|
||||||
"upload_name": None,
|
"upload_name": None,
|
||||||
"created_ts": time_now_ms,
|
"created_ts": time_now_ms,
|
||||||
"file_id": file_id,
|
"filesystem_id": file_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
yield self._generate_remote_thumbnails(
|
yield self._generate_remote_thumbnails(
|
||||||
|
@ -215,7 +222,7 @@ class BaseMediaResource(Resource):
|
||||||
if not requirements:
|
if not requirements:
|
||||||
return
|
return
|
||||||
|
|
||||||
input_path = self.filepaths.local_media_path(media_id)
|
input_path = self.filepaths.local_media_filepath(media_id)
|
||||||
thumbnailer = Thumbnailer(input_path)
|
thumbnailer = Thumbnailer(input_path)
|
||||||
m_width = thumbnailer.width
|
m_width = thumbnailer.width
|
||||||
m_height = thumbnailer.height
|
m_height = thumbnailer.height
|
||||||
|
@ -235,6 +242,7 @@ class BaseMediaResource(Resource):
|
||||||
t_path = self.filepaths.local_media_thumbnail(
|
t_path = self.filepaths.local_media_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method
|
media_id, t_width, t_height, t_type, t_method
|
||||||
)
|
)
|
||||||
|
self._makedirs(t_path)
|
||||||
t_len = thumbnailer.scale(t_path, t_width, t_height, t_type)
|
t_len = thumbnailer.scale(t_path, t_width, t_height, t_type)
|
||||||
yield self.store.store_local_thumbnail(
|
yield self.store.store_local_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method, t_len
|
media_id, t_width, t_height, t_type, t_method, t_len
|
||||||
|
@ -250,6 +258,7 @@ class BaseMediaResource(Resource):
|
||||||
t_path = self.filepaths.local_media_thumbnail(
|
t_path = self.filepaths.local_media_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method
|
media_id, t_width, t_height, t_type, t_method
|
||||||
)
|
)
|
||||||
|
self._makedirs(t_path)
|
||||||
t_len = thumbnailer.crop(t_path, t_width, t_height, t_type)
|
t_len = thumbnailer.crop(t_path, t_width, t_height, t_type)
|
||||||
yield self.store.store_local_thumbnail(
|
yield self.store.store_local_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method, t_len
|
media_id, t_width, t_height, t_type, t_method, t_len
|
||||||
|
@ -264,11 +273,11 @@ class BaseMediaResource(Resource):
|
||||||
def _generate_remote_thumbnails(self, server_name, media_id, media_info):
|
def _generate_remote_thumbnails(self, server_name, media_id, media_info):
|
||||||
media_type = media_info["media_type"]
|
media_type = media_info["media_type"]
|
||||||
file_id = media_info["filesystem_id"]
|
file_id = media_info["filesystem_id"]
|
||||||
requirements = self._get_requirements(media_type)
|
requirements = self._get_thumbnail_requirements(media_type)
|
||||||
if not requirements:
|
if not requirements:
|
||||||
return
|
return
|
||||||
|
|
||||||
input_path = self.filepaths.remote_media_path(server_name, file_id)
|
input_path = self.filepaths.remote_media_filepath(server_name, file_id)
|
||||||
thumbnailer = Thumbnailer(input_path)
|
thumbnailer = Thumbnailer(input_path)
|
||||||
m_width = thumbnailer.width
|
m_width = thumbnailer.width
|
||||||
m_height = thumbnailer.height
|
m_height = thumbnailer.height
|
||||||
|
@ -286,9 +295,9 @@ class BaseMediaResource(Resource):
|
||||||
for t_width, t_height, t_type in scales:
|
for t_width, t_height, t_type in scales:
|
||||||
t_method = "scale"
|
t_method = "scale"
|
||||||
t_path = self.filepaths.remote_media_thumbnail(
|
t_path = self.filepaths.remote_media_thumbnail(
|
||||||
server_name, media_id, file_id,
|
server_name, file_id, t_width, t_height, t_type, t_method
|
||||||
media_id, t_width, t_height, t_type, t_method
|
|
||||||
)
|
)
|
||||||
|
self._makedirs(t_path)
|
||||||
t_len = thumbnailer.scale(t_path, t_width, t_height, t_type)
|
t_len = thumbnailer.scale(t_path, t_width, t_height, t_type)
|
||||||
yield self.store.store_remote_media_thumbnail(
|
yield self.store.store_remote_media_thumbnail(
|
||||||
server_name, media_id, file_id,
|
server_name, media_id, file_id,
|
||||||
|
@ -303,9 +312,9 @@ class BaseMediaResource(Resource):
|
||||||
continue
|
continue
|
||||||
t_method = "crop"
|
t_method = "crop"
|
||||||
t_path = self.filepaths.remote_media_thumbnail(
|
t_path = self.filepaths.remote_media_thumbnail(
|
||||||
server_name, media_id, file_id,
|
server_name, file_id, t_width, t_height, t_type, t_method
|
||||||
t_width, t_height, t_type, t_method
|
|
||||||
)
|
)
|
||||||
|
self._makedirs(t_path)
|
||||||
t_len = thumbnailer.crop(t_path, t_width, t_height, t_type)
|
t_len = thumbnailer.crop(t_path, t_width, t_height, t_type)
|
||||||
yield self.store.store_remote_media_thumbnail(
|
yield self.store.store_remote_media_thumbnail(
|
||||||
server_name, media_id, file_id,
|
server_name, media_id, file_id,
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from .base_media_resource import BaseMediaResource
|
from .base_resource import BaseMediaResource
|
||||||
|
|
||||||
from twisted.web.server import NOT_DONE_YET
|
from twisted.web.server import NOT_DONE_YET
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
@ -52,7 +52,7 @@ class DownloadResource(BaseMediaResource):
|
||||||
media_type = media_info["media_type"]
|
media_type = media_info["media_type"]
|
||||||
file_path = self.filepaths.local_media_filepath(media_id)
|
file_path = self.filepaths.local_media_filepath(media_id)
|
||||||
|
|
||||||
yield self.respond_with_file(request, media_type, file_path)
|
yield self._respond_with_file(request, media_type, file_path)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _respond_remote_file(self, request, server_name, media_id):
|
def _respond_remote_file(self, request, server_name, media_id):
|
||||||
|
@ -72,4 +72,4 @@ class DownloadResource(BaseMediaResource):
|
||||||
server_name, filesystem_id
|
server_name, filesystem_id
|
||||||
)
|
)
|
||||||
|
|
||||||
yield self.respond_with_file(request, media_type, file_path)
|
yield self._respond_with_file(request, media_type, file_path)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
from .upload_resource import UploadResource
|
from .upload_resource import UploadResource
|
||||||
from .download_resource import DownloadResource
|
from .download_resource import DownloadResource
|
||||||
|
from .thumbnail_resource import ThumbnailResource
|
||||||
from .filepath import MediaFilePaths
|
from .filepath import MediaFilePaths
|
||||||
|
|
||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
|
@ -64,3 +65,4 @@ class MediaRepositoryResource(Resource):
|
||||||
filepaths = MediaFilePaths(hs.config.media_store_path)
|
filepaths = MediaFilePaths(hs.config.media_store_path)
|
||||||
self.putChild("upload", UploadResource(hs, filepaths))
|
self.putChild("upload", UploadResource(hs, filepaths))
|
||||||
self.putChild("download", DownloadResource(hs, filepaths))
|
self.putChild("download", DownloadResource(hs, filepaths))
|
||||||
|
self.putChild("thumbnail", ThumbnailResource(hs, filepaths))
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
from .base_media_resource import BaseMediaResource
|
from .base_resource import BaseMediaResource
|
||||||
|
|
||||||
from twisted.web.server import NOT_DONE_YET
|
from twisted.web.server import NOT_DONE_YET
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
@ -59,26 +59,25 @@ class ThumbnailResource(BaseMediaResource):
|
||||||
self._respond_404(request)
|
self._respond_404(request)
|
||||||
return
|
return
|
||||||
|
|
||||||
thumbnail_infos = yield self.store.get_local_thumbnail(media_id)
|
thumbnail_infos = yield self.store.get_local_media_thumbnails(media_id)
|
||||||
|
|
||||||
if thumbnail_infos:
|
if thumbnail_infos:
|
||||||
thumbnail_info = self._select_thumbnail(
|
thumbnail_info = self._select_thumbnail(
|
||||||
width, height, method, m_type, thumbnail_infos
|
width, height, method, m_type, thumbnail_infos
|
||||||
)
|
)
|
||||||
thumbnail_width = thumbnail_info["thumbnail_width"]
|
t_width = thumbnail_info["thumbnail_width"]
|
||||||
thumbnail_height = thumbnail_info["thumbnail_height"]
|
t_height = thumbnail_info["thumbnail_height"]
|
||||||
thumbnail_type = thumbnail_info["thumbnail_type"]
|
t_type = thumbnail_info["thumbnail_type"]
|
||||||
thumbnail_method = thumbnail_info["thumbnail_method"]
|
t_method = thumbnail_info["thumbnail_method"]
|
||||||
|
|
||||||
file_path = self.filepaths.local_media_thumbnail(
|
file_path = self.filepaths.local_media_thumbnail(
|
||||||
media_id, thumbnail_width, thumbnail_height, thumbnail_type,
|
media_id, t_width, t_height, t_type, t_method,
|
||||||
thumbnail_method,
|
|
||||||
)
|
)
|
||||||
yield self._respond_with_file(request, thumbnail_type, file_path)
|
yield self._respond_with_file(request, t_type, file_path)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
yield self._respond_default_thumbnail(
|
yield self._respond_default_thumbnail(
|
||||||
self, request, media_info, width, height, method, m_type,
|
request, media_info, width, height, method, m_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -103,19 +102,19 @@ class ThumbnailResource(BaseMediaResource):
|
||||||
thumbnail_info = self._select_thumbnail(
|
thumbnail_info = self._select_thumbnail(
|
||||||
width, height, method, m_type, thumbnail_infos
|
width, height, method, m_type, thumbnail_infos
|
||||||
)
|
)
|
||||||
thumbnail_width = thumbnail_info["thumbnail_width"]
|
t_width = thumbnail_info["thumbnail_width"]
|
||||||
thumbnail_height = thumbnail_info["thumbnail_height"]
|
t_height = thumbnail_info["thumbnail_height"]
|
||||||
thumbnail_type = thumbnail_info["thumbnail_type"]
|
t_type = thumbnail_info["thumbnail_type"]
|
||||||
thumbnail_method = thumbnail_info["thumbnail_method"]
|
t_method = thumbnail_info["thumbnail_method"]
|
||||||
|
file_id = thumbnail_info["filesystem_id"]
|
||||||
|
|
||||||
file_path = self.filepaths.remote_media_thumbnail(
|
file_path = self.filepaths.remote_media_thumbnail(
|
||||||
server_name, media_id, thumbnail_width, thumbnail_height,
|
server_name, file_id, t_width, t_height, t_type, t_method,
|
||||||
thumbnail_type, thumbnail_method,
|
|
||||||
)
|
)
|
||||||
yield self._respond_with_file(request, thumbnail_type, file_path)
|
yield self._respond_with_file(request, t_type, file_path)
|
||||||
else:
|
else:
|
||||||
yield self._respond_default_thumbnail(
|
yield self._respond_default_thumbnail(
|
||||||
self, request, media_info, width, height, method, m_type,
|
request, media_info, width, height, method, m_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -143,16 +142,15 @@ class ThumbnailResource(BaseMediaResource):
|
||||||
width, height, "crop", m_type, thumbnail_infos
|
width, height, "crop", m_type, thumbnail_infos
|
||||||
)
|
)
|
||||||
|
|
||||||
thumbnail_width = thumbnail_info["thumbnail_width"]
|
t_width = thumbnail_info["thumbnail_width"]
|
||||||
thumbnail_height = thumbnail_info["thumbnail_height"]
|
t_height = thumbnail_info["thumbnail_height"]
|
||||||
thumbnail_type = thumbnail_info["thumbnail_type"]
|
t_type = thumbnail_info["thumbnail_type"]
|
||||||
thumbnail_method = thumbnail_info["thumbnail_method"]
|
t_method = thumbnail_info["thumbnail_method"]
|
||||||
|
|
||||||
file_path = self.filepaths.default_thumbnail(
|
file_path = self.filepaths.default_thumbnail(
|
||||||
top_level_type, sub_type, thumbnail_width, thumbnail_height,
|
top_level_type, sub_type, t_width, t_height, t_type, t_method,
|
||||||
thumbnail_type, thumbnail_method,
|
|
||||||
)
|
)
|
||||||
yield self.respond_with_file(request, thumbnail_type, file_path)
|
yield self.respond_with_file(request, t_type, file_path)
|
||||||
|
|
||||||
def _select_thumbnail(self, desired_width, desired_height, desired_method,
|
def _select_thumbnail(self, desired_width, desired_height, desired_method,
|
||||||
desired_type, thumbnail_infos):
|
desired_type, thumbnail_infos):
|
||||||
|
@ -164,7 +162,7 @@ class ThumbnailResource(BaseMediaResource):
|
||||||
for info in thumbnail_infos:
|
for info in thumbnail_infos:
|
||||||
t_w = info["thumbnail_width"]
|
t_w = info["thumbnail_width"]
|
||||||
t_h = info["thumbnail_height"]
|
t_h = info["thumbnail_height"]
|
||||||
t_method = info["thumnail_method"]
|
t_method = info["thumbnail_method"]
|
||||||
if t_method == "scale" or t_method == "crop":
|
if t_method == "scale" or t_method == "crop":
|
||||||
aspect_quality = abs(d_w * t_h - d_h * t_w)
|
aspect_quality = abs(d_w * t_h - d_h * t_w)
|
||||||
size_quality = abs((d_w - t_w) * (d_h - t_h))
|
size_quality = abs((d_w - t_w) * (d_h - t_h))
|
||||||
|
@ -180,7 +178,7 @@ class ThumbnailResource(BaseMediaResource):
|
||||||
for info in thumbnail_infos:
|
for info in thumbnail_infos:
|
||||||
t_w = info["thumbnail_width"]
|
t_w = info["thumbnail_width"]
|
||||||
t_h = info["thumbnail_height"]
|
t_h = info["thumbnail_height"]
|
||||||
t_method = info["thumnail_method"]
|
t_method = info["thumbnail_method"]
|
||||||
if t_method == "scale" and (t_w >= d_w or t_h >= d_h):
|
if t_method == "scale" and (t_w >= d_w or t_h >= d_h):
|
||||||
size_quality = abs((d_w - t_w) * (d_h - t_h))
|
size_quality = abs((d_w - t_w) * (d_h - t_h))
|
||||||
type_quality = desired_type != info["thumbnail_type"]
|
type_quality = desired_type != info["thumbnail_type"]
|
||||||
|
|
|
@ -23,9 +23,7 @@ from synapse.api.errors import (
|
||||||
from twisted.web.server import NOT_DONE_YET
|
from twisted.web.server import NOT_DONE_YET
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
from .baseresource import BaseMediaResource
|
from .base_resource import BaseMediaResource
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -75,7 +73,7 @@ class UploadResource(BaseMediaResource):
|
||||||
media_id = random_string(24)
|
media_id = random_string(24)
|
||||||
|
|
||||||
fname = self.filepaths.local_media_filepath(media_id)
|
fname = self.filepaths.local_media_filepath(media_id)
|
||||||
os.makedirs(os.path.dirname(fname))
|
self._makedirs(fname)
|
||||||
|
|
||||||
# This shouldn't block for very long because the content will have
|
# This shouldn't block for very long because the content will have
|
||||||
# already been uploaded at this point.
|
# already been uploaded at this point.
|
||||||
|
@ -95,7 +93,7 @@ class UploadResource(BaseMediaResource):
|
||||||
"media_length": content_length,
|
"media_length": content_length,
|
||||||
}
|
}
|
||||||
|
|
||||||
yield self._generate_local_thumbnails(self, media_id, media_info)
|
yield self._generate_local_thumbnails(media_id, media_info)
|
||||||
|
|
||||||
respond_with_json(
|
respond_with_json(
|
||||||
request, 200, {"content_token": media_id}, send_cors=True
|
request, 200, {"content_token": media_id}, send_cors=True
|
||||||
|
|
|
@ -19,6 +19,9 @@ from _base import SQLBaseStore
|
||||||
class MediaRepositoryStore(SQLBaseStore):
|
class MediaRepositoryStore(SQLBaseStore):
|
||||||
"""Persistence for attachments and avatars"""
|
"""Persistence for attachments and avatars"""
|
||||||
|
|
||||||
|
def get_default_thumbnails(self, top_level_type, sub_type):
|
||||||
|
return []
|
||||||
|
|
||||||
def get_local_media(self, media_id):
|
def get_local_media(self, media_id):
|
||||||
"""Get the metadata for a local piece of media
|
"""Get the metadata for a local piece of media
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -47,7 +50,7 @@ class MediaRepositoryStore(SQLBaseStore):
|
||||||
|
|
||||||
def get_local_media_thumbnails(self, media_id):
|
def get_local_media_thumbnails(self, media_id):
|
||||||
return self._simple_select_list(
|
return self._simple_select_list(
|
||||||
"local_media_thumbnails",
|
"local_media_repository_thumbnails",
|
||||||
{"media_id": media_id},
|
{"media_id": media_id},
|
||||||
(
|
(
|
||||||
"thumbnail_width", "thumbnail_height", "thumbnail_method",
|
"thumbnail_width", "thumbnail_height", "thumbnail_method",
|
||||||
|
@ -59,7 +62,7 @@ class MediaRepositoryStore(SQLBaseStore):
|
||||||
thumbnail_height, thumbnail_type,
|
thumbnail_height, thumbnail_type,
|
||||||
thumbnail_method, thumbnail_length):
|
thumbnail_method, thumbnail_length):
|
||||||
return self._simple_insert(
|
return self._simple_insert(
|
||||||
"local_media_thumbnails",
|
"local_media_repository_thumbnails",
|
||||||
{
|
{
|
||||||
"media_id": media_id,
|
"media_id": media_id,
|
||||||
"thumbnail_width": thumbnail_width,
|
"thumbnail_width": thumbnail_width,
|
||||||
|
@ -100,11 +103,10 @@ class MediaRepositoryStore(SQLBaseStore):
|
||||||
def get_remote_media_thumbnails(self, origin, media_id):
|
def get_remote_media_thumbnails(self, origin, media_id):
|
||||||
return self._simple_select_list(
|
return self._simple_select_list(
|
||||||
"remote_media_cache_thumbnails",
|
"remote_media_cache_thumbnails",
|
||||||
{"origin": origin, "media_id": media_id},
|
{"media_origin": origin, "media_id": media_id},
|
||||||
(
|
(
|
||||||
"thumbnail_width", "thumbnail_height", "thumbnail_method"
|
"thumbnail_width", "thumbnail_height", "thumbnail_method",
|
||||||
"thumbnail_type", "thumbnail_length",
|
"thumbnail_type", "thumbnail_length", "filesystem_id",
|
||||||
"filesystem_id"
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue