~singpolyma/signal-sticker-proxy

97396995d72b1d9c269d5753e48c75c03c7f8e3d — Stephen Paul Weber 1 year, 7 months ago adf7a53 master
Convert APNG to WebP

Signal uses APNG for animated stickers, but this is not supported in our apps so
convert to WebP.
2 files changed, 44 insertions(+), 4 deletions(-)

M guix.scm
M main.py
M guix.scm => guix.scm +26 -0
@@ 10,9 10,34 @@
  (gnu packages python-crypto)
  (gnu packages python-web)
  (gnu packages python-xyz)
  (gnu packages fontutils)
  (gnu packages image)
  (ice-9 rdelim)
  (ice-9 popen))

(define-public python-pillow-mine
  (package
    (inherit python-pillow)
    (name "python-pillow-mine")
    (version "9.0.0.post1")
    (source
     (origin
       (method git-fetch)
       (uri (git-reference
             (url "https://github.com/singpolyma/Pillow")
             (commit "float")))
       (file-name (git-file-name name version))
       (sha256
        (base32 "12zhlhqq8vxykndgsppwvgvyn0vnzbjfkc2kj8nh4r80lqjw916g"))))
    (inputs
     (modify-inputs (package-inputs python-pillow)
       (prepend libraqm libimagequant)))
    (arguments '(#:tests? #f))
    (home-page "https://github.com/uploadcare/pillow-simd")
    (synopsis "Fork of the Python Imaging Library (Pillow)")
    (description "This package is a fork of Pillow which adds support for SIMD
parallelism.")))

(define-public python-pymultihash
  (package
    (name "python-pymultihash")


@@ 118,6 143,7 @@
        python-aiohttp
        python-pymultihash
        python-magic
        python-pillow-mine
        python-signalstickers-client))
    (home-page "https://git.singpolyma.net/signal-sticker-proxy")
    (synopsis "")

M main.py => main.py +18 -4
@@ 3,8 3,17 @@ import multihash
import base58
import magic
import sys
import io
from aiohttp import web
from signalstickers_client import StickersClient
from PIL import Image

def to_webp(bytes):
    out = io.BytesIO()
    im = Image.open(io.BytesIO(bytes))
    im.apply_transparency()
    im.save(out, format='WEBP', save_all=True, lossless=True, minimize_size=True, optimize=True)
    return out.getvalue()

async def get_pack(request):
    pack_id = request.match_info.get('pack')


@@ 14,15 23,18 @@ async def get_pack(request):
        pack = await client.get_pack(pack_id, key)
        stickers = []
        for sticker in pack.stickers:
            image_data = sticker.image_data
            if magic.from_buffer(image_data, mime=True) != 'image/webp':
                image_data = to_webp(image_data)
            stickers.append({
                'url': str(request.url) + "/" + str(sticker.id),
                'pack': pack.title,
                'name': sticker.emoji,
                'copyright': pack.author,
                'cids': [
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha1').encode()).decode('utf-8'),
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha2-256').encode()).decode('utf-8'),
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(sticker.image_data, 'sha2-512').encode()).decode('utf-8')
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha1').encode()).decode('utf-8'),
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha2-256').encode()).decode('utf-8'),
                    'z' + base58.b58encode(b'\x01\x55' + multihash.digest(image_data, 'sha2-512').encode()).decode('utf-8')
                ]
            })
        return web.json_response(stickers)


@@ 34,8 46,10 @@ async def get_sticker(request):

    async with StickersClient() as client:
        image_data = await client.download_sticker(sticker_id, pack_id, key)
        if magic.from_buffer(image_data, mime=True) != 'image/webp':
            image_data = to_webp(image_data)
        result = web.Response(body=image_data)
        result.headers['Content-Type'] = magic.from_buffer(image_data, mime=True)
        result.headers['Content-Type'] = 'image/webp'
        return result

app = web.Application()