Skip to content

Commit 3fbfdb6

Browse files
znedwmueslo
authored andcommitted
Issue #66 - add support for ptpimg with very basic config
1 parent 9d81ed5 commit 3fbfdb6

3 files changed

Lines changed: 164 additions & 3 deletions

File tree

pythonbits/bb.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from .torrent import make_torrent
1919
from . import tvdb
2020
from . import imdb
21-
from .imgur import ImgurUploader
21+
from . import imagehosting
2222
from .ffmpeg import FFMpeg
2323
from . import templating as bb
2424
from .submission import (Submission, form_field, finalize,
@@ -292,7 +292,7 @@ def _render_screenshots(self):
292292
return ffmpeg.take_screenshots(ns)
293293

294294
def _finalize_screenshots(self):
295-
return ImgurUploader().upload(self['screenshots'])
295+
return imagehosting.upload_files(self['screenshots'])
296296

297297
def _render_mediainfo(self):
298298
try:
@@ -518,7 +518,7 @@ def _render_cover(self):
518518
return self['summary']['cover']
519519

520520
def _finalize_cover(self):
521-
return ImgurUploader().upload(self['cover'])
521+
return imagehosting.upload_urls(self['cover'])
522522

523523

524524
class TvSubmission(VideoSubmission):

pythonbits/imagehosting.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -*- coding: utf-8 -*-
2+
from .config import config
3+
4+
from .imgur import ImgurUploader
5+
from .ptpimg import PtpImgUploader
6+
7+
config.register('ImageHosting', 'provider',
8+
"Enter a provider for image hosting, supported options are "
9+
"ptpimg or imgur",
10+
ask=True)
11+
12+
13+
def upload_files(images):
14+
provider = config.get('ImageHosting', 'provider')
15+
if provider.lower() == 'imgur':
16+
return ImgurUploader().upload(images)
17+
elif provider.lower() == 'ptpimg':
18+
return PtpImgUploader().upload_files(*images)
19+
20+
21+
def upload_urls(images):
22+
provider = config.get('ImageHosting', 'provider')
23+
if provider.lower() == 'imgur':
24+
return ImgurUploader().upload(images)
25+
elif provider.lower() == 'ptpimg':
26+
return PtpImgUploader().upload_urls(images)

pythonbits/ptpimg.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#!/usr/bin/env python3
2+
# pylint: disable=invalid-name
3+
"""
4+
Upload image file or image URL to the ptpimg.me image hosting.
5+
6+
Borrowed from https://github.com/theirix/ptpimg-uploader/blob/master/ptpimg_uploader.py
7+
8+
"""
9+
10+
import contextlib
11+
import mimetypes
12+
import os
13+
from io import BytesIO
14+
from sys import stdout
15+
from textwrap import dedent
16+
17+
import requests
18+
19+
from .config import config
20+
from .logging import log
21+
22+
mimetypes.init()
23+
24+
config.register(
25+
'PtpImg', 'api_key',
26+
dedent("""\
27+
To find your PTPImg API key, login to https://ptpimg.me,
28+
open the page source (i.e. "View->Developer->View source" menu in Chrome),
29+
find the string api_key and copy the hexademical string from the value attribute.
30+
Your API key should look like 43fe0fee-f935-4084-8a38-3e632b0be68c.
31+
3. Enter the API Key below
32+
API Key"""))
33+
34+
35+
class UploadFailed(Exception):
36+
def __str__(self):
37+
msg, *args = self.args
38+
return msg.format(*args)
39+
40+
41+
class PtpImgUploader:
42+
""" Upload image or image URL to the ptpimg.me image hosting """
43+
44+
def __init__(self, timeout=None):
45+
self.api_key = config.get('PtpImg', 'api_key')
46+
self.timeout = timeout
47+
48+
@staticmethod
49+
def _handle_result(res):
50+
image_url = 'https://ptpimg.me/{0}.{1}'.format(
51+
res['code'], res['ext'])
52+
return image_url
53+
54+
def _perform(self, files=None, **data):
55+
# Compose request
56+
headers = {'referer': 'https://ptpimg.me/index.php'}
57+
data['api_key'] = self.api_key
58+
url = 'https://ptpimg.me/upload.php'
59+
60+
resp = requests.post(
61+
url, headers=headers, data=data, files=files, timeout=self.timeout)
62+
63+
# pylint: disable=no-member
64+
if resp.status_code == requests.codes.ok:
65+
try:
66+
print('Successful response', resp.json())
67+
# r.json() is like this: [{'code': 'ulkm79', 'ext': 'jpg'}]
68+
return [self._handle_result(r) for r in resp.json()]
69+
except ValueError as e:
70+
raise UploadFailed(
71+
'Failed decoding body:\n{0}\n{1!r}', e, resp.content
72+
) from None
73+
else:
74+
raise UploadFailed(
75+
'Failed. Status {0}:\n{1}', resp.status_code, resp.content)
76+
77+
def upload_files(self, *filenames):
78+
log.notice('Got files to upload {} to ptpimg', filenames)
79+
""" Upload files using form """
80+
# The ExitStack closes files for us when the with block exits
81+
with contextlib.ExitStack() as stack:
82+
files = {}
83+
for i, filename in enumerate(filenames):
84+
open_file = stack.enter_context(open(filename, 'rb'))
85+
mime_type, _ = mimetypes.guess_type(filename)
86+
if not mime_type or mime_type.split('/')[0] != 'image':
87+
raise ValueError(
88+
'Unknown image file type {}'.format(mime_type))
89+
90+
name = os.path.basename(filename)
91+
try:
92+
# until https://github.com/shazow/urllib3/issues/303 is
93+
# resolved, only use the filename if it is Latin-1 safe
94+
name.encode('latin1')
95+
except UnicodeEncodeError:
96+
name = 'justfilename'
97+
files['file-upload[{}]'.format(i)] = (
98+
name, open_file, mime_type)
99+
100+
log.notice('Processed and trying to upload {} to ptpimg', files)
101+
return self._perform(files=files)
102+
103+
def upload_urls(self, *urls):
104+
log.notice('Got links to upload {} to ptpimg', urls)
105+
""" Upload image URLs by downloading them before """
106+
with contextlib.ExitStack() as stack:
107+
files = {}
108+
for i, url in enumerate(urls):
109+
resp = requests.get(url, timeout=self.timeout)
110+
if resp.status_code != requests.codes.ok:
111+
raise ValueError(
112+
'Cannot fetch url {} with error {}'.format(url, resp.status_code))
113+
114+
mime_type = resp.headers['content-type']
115+
if not mime_type or mime_type.split('/')[0] != 'image':
116+
raise ValueError(
117+
'Unknown image file type {}'.format(mime_type))
118+
open_file = stack.enter_context(BytesIO(resp.content))
119+
files['file-upload[{}]'.format(i)] = (
120+
'file-{}'.format(i), open_file, mime_type)
121+
122+
return self._perform(files=files)
123+
124+
125+
def _partition(files_or_urls):
126+
files, urls = [], []
127+
for file_or_url in files_or_urls:
128+
if os.path.exists(file_or_url):
129+
files.append(file_or_url)
130+
elif file_or_url.startswith('http'):
131+
urls.append(file_or_url)
132+
else:
133+
raise ValueError(
134+
'Not an existing file or image URL: {}'.format(file_or_url))
135+
return files, urls

0 commit comments

Comments
 (0)