goopypanther / saucebot-discord

17 stars 13 forks source link

Pixiv image attachments incompatible with iOS (webp/VP8 encoding) #12

Open carter-yagemann opened 4 years ago

carter-yagemann commented 4 years ago

Summary

The bot is currently downloading Pixiv images in an encoding that is not supported by some versions of iOS, causing images to not display in the Discord app and browsers.

Details

In two locations, the bot uses the requests module to fetch Pixiv images:

https://github.com/JeremyRuhland/saucebot-discord/blob/c7a348a57e1ced49abffcfad5cb9fe0c5e10c488/saucebot-discord.py3#L259

https://github.com/JeremyRuhland/saucebot-discord/blob/c7a348a57e1ced49abffcfad5cb9fe0c5e10c488/saucebot-discord.py3#L275

The Pixiv CDN responds with a webp/VP8 encoded JPEG:

$ file 77756873_p0_master1200.jpg
77756873_p0_master1200.jpg: RIFF (little-endian) data, Web/P image, VP8 encoding, 600x365, Scaling: [none]x[none], YUV color, decoders should clamp

which cannot be decoded in at least some versions of iOS:

image

Same problem occurs if the image URL is opened in iOS browsers (tested: safari, chrome).

Proposed Solution

The download() method in pixivpy3 retrieves images in a more widely compatible encoding:

$ file *
74829993_p0.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=1, orientation=upper-left], baseline, precision 8, 1000x1178, components 3
75346272_p0.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 903x1200, components 3
75569616_p0.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=1, orientation=upper-left], baseline, precision 8, 800x1131, components 3
77912671_p0.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=1, orientation=upper-left], baseline, precision 8, 2894x4093, components 3

Thus, I propose using this in place of requests.

If this sounds good, I can open a pull request, thanks.

goopypanther commented 4 years ago

Hi, yes this sounds great. Feel free to issue a pull request.

carter-yagemann commented 4 years ago

Digging into the problem deeper, it turns out the pixiv library also uses requests under the hood in the same way this project does, so the problem is more interesting than I initially realized.

It turns out that depending on which API you use, the pixiv library will return a different set of image URLs, even for the same illustration:

>>> api = pixivpy3.AppPixivAPI()  # what sauncebot uses
>>> api.illust_detail(77756873).illust.image_urls
{'square_medium': 'https://i.pximg.net/c/540x540_10_webp/img-master/img/2019/11/11/01/21/28/77756873_p0_square1200.jpg', 'medium': 'https://i.pximg.net/c/540x540_70/img-master/img/2019/11/11/01/21/28/77756873_p0_master1200.jpg', 'large': 'https://i.pximg.net/c/600x1200_90_webp/img-master/img/2019/11/11/01/21/28/77756873_p0_master1200.jpg'}
>>> api = pixivpy3.PixivAPI()  # an alternative "public" API in the same library
>>> api.works(77756873).response[0].image_urls
{'px_128x128': 'https://i.pximg.net/c/128x128/img-master/img/2019/11/11/01/21/28/77756873_p0_square1200.jpg', 'small': 'https://i.pximg.net/c/150x150/img-master/img/2019/11/11/01/21/28/77756873_p0_master1200.jpg', 'medium': 'https://i.pximg.net/c/600x600/img-master/img/2019/11/11/01/21/28/77756873_p0_master1200.jpg', 'large': 'https://i.pximg.net/img-original/img/2019/11/11/01/21/28/77756873_p0.png', 'px_480mw': 'https://i.pximg.net/c/480x960/img-master/img/2019/11/11/01/21/28/77756873_p0_master1200.jpg'}

When the App API is used, some of the image URLs contain the _webp suffix, which are the problematic ones for iOS. For some reason, I've never encountered a webp encoded image URL using the public API.

I guess the best solution for this project is to switch APIs, which shouldn't be too painful.