add conversion for stickers
This commit is contained in:
parent
706852e425
commit
700f8f8ec4
2 changed files with 75 additions and 13 deletions
|
|
@ -257,7 +257,6 @@ async def migrate_messages(
|
|||
if hasattr(format_val, 'name'): # discord.py StickerFormat enum
|
||||
ext = format_val.name.lower()
|
||||
elif isinstance(format_val, int):
|
||||
# Map common StickerFormat values if it's an int
|
||||
format_map = {1: 'png', 2: 'apng', 3: 'lottie', 4: 'gif'}
|
||||
ext = format_map.get(format_val, 'png')
|
||||
else:
|
||||
|
|
@ -265,25 +264,53 @@ async def migrate_messages(
|
|||
|
||||
logger.debug(f"Determined sticker extension: {ext}")
|
||||
|
||||
# Handle Lottie (json) -> Convert to GIF
|
||||
# Fluxer: Convert animated stickers to WebP
|
||||
# Lottie (json) → GIF (via lottie lib) → WebP (via Pillow)
|
||||
if ext == 'lottie':
|
||||
if HAS_LOTTIE:
|
||||
try:
|
||||
logger.debug(f"Converting Lottie sticker {s.name} to GIF...")
|
||||
logger.debug(f"Converting Lottie sticker {s.name} to WebP...")
|
||||
lottie_data = json.loads(sticker_data)
|
||||
animation = Animation.load(lottie_data)
|
||||
output = io.BytesIO()
|
||||
export_gif(animation, output)
|
||||
sticker_data = output.getvalue()
|
||||
ext = 'gif'
|
||||
logger.debug(f"Successfully converted Lottie sticker {s.name} to GIF")
|
||||
gif_buf = io.BytesIO()
|
||||
export_gif(animation, gif_buf)
|
||||
gif_buf.seek(0)
|
||||
# GIF → WebP via Pillow
|
||||
from PIL import Image
|
||||
img = Image.open(gif_buf)
|
||||
webp_buf = io.BytesIO()
|
||||
if getattr(img, 'n_frames', 1) > 1:
|
||||
img.save(webp_buf, format='WEBP', save_all=True, loop=0)
|
||||
else:
|
||||
img.save(webp_buf, format='WEBP')
|
||||
sticker_data = webp_buf.getvalue()
|
||||
ext = 'webp'
|
||||
logger.debug(f"Successfully converted Lottie sticker {s.name} to WebP")
|
||||
except Exception as conv_err:
|
||||
logger.error(f"Failed to convert Lottie sticker {s.name} to GIF: {conv_err}")
|
||||
ext = 'json' # Fallback to json if conversion fails
|
||||
logger.error(f"Failed to convert Lottie sticker {s.name} to WebP: {conv_err}")
|
||||
ext = 'json'
|
||||
else:
|
||||
logger.warning(f"Lottie library not available, sending sticker {s.name} as raw JSON")
|
||||
ext = 'json'
|
||||
|
||||
# APNG / GIF → WebP (via Pillow)
|
||||
elif ext in ('apng', 'gif'):
|
||||
try:
|
||||
logger.debug(f"Converting {ext.upper()} sticker {s.name} to WebP...")
|
||||
from PIL import Image
|
||||
img = Image.open(io.BytesIO(sticker_data))
|
||||
webp_buf = io.BytesIO()
|
||||
if getattr(img, 'n_frames', 1) > 1:
|
||||
img.save(webp_buf, format='WEBP', save_all=True, loop=0)
|
||||
else:
|
||||
img.save(webp_buf, format='WEBP')
|
||||
sticker_data = webp_buf.getvalue()
|
||||
ext = 'webp'
|
||||
logger.debug(f"Successfully converted sticker {s.name} to WebP")
|
||||
except Exception as conv_err:
|
||||
logger.error(f"Failed to convert {ext.upper()} sticker {s.name} to WebP: {conv_err}")
|
||||
# Keep original format as fallback
|
||||
|
||||
filename = f"sticker_{s.name}_{s.id}.{ext}"
|
||||
files.append({"filename": filename, "data": sticker_data})
|
||||
stats["attachments"] += 1
|
||||
|
|
|
|||
|
|
@ -260,7 +260,6 @@ async def migrate_messages(
|
|||
if hasattr(format_val, 'name'): # discord.py StickerFormat enum
|
||||
ext = format_val.name.lower()
|
||||
elif isinstance(format_val, int):
|
||||
# Map common StickerFormat values if it's an int
|
||||
format_map = {1: 'png', 2: 'apng', 3: 'lottie', 4: 'gif'}
|
||||
ext = format_map.get(format_val, 'png')
|
||||
else:
|
||||
|
|
@ -268,7 +267,8 @@ async def migrate_messages(
|
|||
|
||||
logger.debug(f"Determined sticker extension: {ext}")
|
||||
|
||||
# Handle Lottie (json) -> Convert to GIF
|
||||
# Stoat: Convert animated stickers to GIF
|
||||
# Lottie (json) → GIF (via lottie lib)
|
||||
if ext == 'lottie':
|
||||
if HAS_LOTTIE:
|
||||
try:
|
||||
|
|
@ -282,11 +282,46 @@ async def migrate_messages(
|
|||
logger.debug(f"Successfully converted Lottie sticker {s.name} to GIF")
|
||||
except Exception as conv_err:
|
||||
logger.error(f"Failed to convert Lottie sticker {s.name} to GIF: {conv_err}")
|
||||
ext = 'json' # Fallback to json if conversion fails
|
||||
ext = 'json'
|
||||
else:
|
||||
logger.warning(f"Lottie library not available, sending sticker {s.name} as raw JSON")
|
||||
ext = 'json'
|
||||
|
||||
# APNG → GIF (via Pillow, with proper frame disposal)
|
||||
elif ext == 'apng':
|
||||
try:
|
||||
logger.debug(f"Converting APNG sticker {s.name} to GIF...")
|
||||
from PIL import Image
|
||||
img = Image.open(io.BytesIO(sticker_data))
|
||||
gif_buf = io.BytesIO()
|
||||
if getattr(img, 'n_frames', 1) > 1:
|
||||
# Extract each frame onto a clean background to avoid overlap
|
||||
frames = []
|
||||
durations = []
|
||||
for frame_idx in range(img.n_frames):
|
||||
img.seek(frame_idx)
|
||||
# Create fresh background and composite the frame
|
||||
canvas = Image.new('RGBA', img.size, (0, 0, 0, 0))
|
||||
frame = img.convert('RGBA')
|
||||
canvas.paste(frame, (0, 0), frame)
|
||||
# Convert to palette mode for GIF
|
||||
frames.append(canvas.convert('RGBA'))
|
||||
durations.append(img.info.get('duration', 100))
|
||||
# Save with disposal=2 (clear frame before next)
|
||||
frames[0].save(
|
||||
gif_buf, format='GIF', save_all=True,
|
||||
append_images=frames[1:], loop=0,
|
||||
duration=durations, disposal=2, transparency=0
|
||||
)
|
||||
else:
|
||||
img.save(gif_buf, format='GIF')
|
||||
sticker_data = gif_buf.getvalue()
|
||||
ext = 'gif'
|
||||
logger.debug(f"Successfully converted APNG sticker {s.name} to GIF")
|
||||
except Exception as conv_err:
|
||||
logger.error(f"Failed to convert APNG sticker {s.name} to GIF: {conv_err}")
|
||||
# Keep original apng as fallback
|
||||
|
||||
filename = f"sticker_{s.name}_{s.id}.{ext}"
|
||||
files.append({"filename": filename, "data": sticker_data})
|
||||
stats["attachments"] += 1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue