Passed
Push — master ( 708cb0...cec1f3 )
by Jace
06:26
created

samples()   A

Complexity

Conditions 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
c 0
b 0
f 0
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 3
rs 9.4285
1 1
import logging
2 1
from urllib.parse import unquote
3
4 1
import requests
5 1
from flask import (Response, url_for, render_template, send_file,
6
                   current_app, request)
7
8
9 1
log = logging.getLogger(__name__)
10
11
12 1
def samples(blank=False):
13
    """Generate dictionaries of sample image data for template rendering."""
14 1
    for template in sorted(current_app.template_service.all()):
15 1
        path = "_" if blank else template.sample_path
16 1
        url = route('image.get', key=template.key, path=path,
17
                    preview=True, watermark='none')
18 1
        yield {
19
            'key': template.key,
20
            'name': template.name,
21 1
            'url': url,
22
        }
23 1
24 1
25
def route(*args, **kwargs):
26
    """Unquoted version of Flask's `url_for`."""
27
    for key, value in sorted(kwargs.items()):
28
        if value is True:
29 1
            kwargs[key] = 'true'
30
31
    return _secure(unquote(url_for(*args, **kwargs)))
32
33
34 1
def display(title, path, share=False, raw=False, mimetype='image/jpeg'):
35
    """Render a webpage or raw image based on request."""
36 1
    img = _format_url(request, 'share')
37 1
    img_twitter = _format_url(
38
        request, 'share',
39 1
        width=current_app.config['TWITTER_IMAGE_WIDTH'],
40
        height=current_app.config['TWITTER_IMAGE_HEIGHT'],
41
    )
42
    img_facebook = _format_url(
43
        request, 'share',
44
        width=current_app.config['FACEBOOK_IMAGE_WIDTH'],
45
        height=current_app.config['FACEBOOK_IMAGE_HEIGHT'],
46
    )
47
    url = _format_url(request, 'width', 'height')
48 1
49
    if share:
50
        log.info("Sharing image on page: %s", img)
51 1
52 1
        html = render_template(
53
            'share.html',
54
            title=title,
55 1
            img=_secure(img),
56
            img_twitter=_secure(img_twitter),
57 1
            img_facebook=_secure(img_facebook),
58 1
            url=_secure(url),
59 1
            config=current_app.config,
60
        )
61
        return html if raw else _nocache(Response(html))
62
63
    else:
64
        log.info("Sending image: %s", path)
65
        return send_file(path, mimetype=mimetype)
66
67
68
def track(title):
69
    """Log the requested content, server-side."""
70
    google_url = current_app.config['GOOGLE_ANALYTICS_URL']
71
    google_tid = current_app.config['GOOGLE_ANALYTICS_TID']
72 1
    google_data = dict(
73
        v=1,
74
        tid=google_tid,
75
        cid=request.remote_addr,
76
77 1
        t='pageview',
78 1
        dh='memegen.link',
79
        dp=request.full_path,
80
        dt=str(title),
81
82
        uip=request.remote_addr,
83 1
        ua=request.user_agent.string,
84
    )
85
    if google_tid != 'localhost':
86
        response = requests.post(google_url, data=google_data)
87
        params = _format_query(google_data, as_string=True)
88 1
        log.debug("Tracking POST: %s %s", response.url, params)
89
90 1
    remote_url = current_app.config['REMOTE_TRACKING_URL']
91
    remote_data = dict(
92
        text=str(title),
93 1
        source='memegen.link',
94
        context=unquote(request.url),
95
    )
96 1
    if remote_url:
97
        response = requests.get(remote_url, params=remote_data)
98 1
        log.debug("Tracking GET: %s", response.url)
99
100 1
101 1
def _secure(url):
102
    """Ensure HTTPS is used in production."""
103 1
    if current_app.config['ENV'] == 'prod':
104
        if url.startswith('http:'):
105 1
            url = url.replace('http:', 'https:', 1)
106 1
    return url
107
108 1
109
def _format_url(req, *skip, **add):
110
    """Get a formatted URL with sanitized query parameters."""
111 1
    base = req.base_url
112 1
113 1
    options = {k: v[0] for k, v in dict(req.args).items() if k not in skip}
114 1
    options.update(add)
115
116 1
    params = _format_query(options)
117
118
    if params:
119 1
        return base + "?{}".format("&".join(params))
120
    else:
121
        return base
122
123
124
def _format_query(options, *, as_string=False):
125
    pattern = "{}={!r}" if as_string else "{}={}"
126
    pairs = sorted(pattern.format(k, v) for k, v in options.items())
127
    if as_string:
128
        return ' '.join(pairs)
129
    return pairs
130
131
132
def _nocache(response):
133
    """Ensure a response is not cached."""
134
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
135
    response.headers['Pragma'] = 'no-cache'
136
    response.headers['Expires'] = '0'
137
    return response
138