1
+ """Django signal plumbing for the donate app."""
2
+
1
3
import random
2
4
import logging
3
5
25
27
26
28
def show_to_geo (promo , country_code ):
27
29
# Remove promo's that exclude this country.
28
- for filter in promo .geo_filters .all ():
29
- if filter . filter_type == INCLUDE :
30
- if country_code in filter .codes :
30
+ for geo_filter in promo .geo_geo_filters .all ():
31
+ if geo_filter . geo_filter_type == INCLUDE :
32
+ if country_code in geo_filter .codes :
31
33
continue
32
34
else :
33
35
return False
34
- if filter . filter_type == EXCLUDE :
35
- if country_code in filter .codes :
36
+ if geo_filter . geo_filter_type == EXCLUDE :
37
+ if country_code in geo_filter .codes :
36
38
return False
37
39
38
40
return True
@@ -141,70 +143,89 @@ def get_promo(country_code, programming_language, theme, gold_project=False, gol
141
143
return promo_obj
142
144
143
145
146
+ def is_gold_user (user ):
147
+ """Return True if the user is a Gold supporter."""
148
+ return user .is_authenticated () and (
149
+ user .gold .count () or
150
+ user .goldonce .count ()
151
+ )
152
+
153
+
154
+ def is_gold_project (project ):
155
+ """Return True if the project has been mapped by a Gold supporter."""
156
+ return project .gold_owners .count ()
157
+
158
+
159
+ def get_user_country (request ):
160
+ """Return the ISO country code from geo-IP data, or None if not found."""
161
+ if not PROMO_GEO_PATH :
162
+ return None
163
+ ip = request .META .get ('REMOTE_ADDR' )
164
+ if not ip :
165
+ return None
166
+ try :
167
+ geo_response = geo_reader .city (ip )
168
+ return geo_response .country .iso_code
169
+ except (AddressNotFoundError , ValueError ): # Invalid IP
170
+ return None
171
+
172
+
144
173
@receiver (footer_response )
145
- def attach_promo_data (sender , ** kwargs ):
146
- request = kwargs ['request' ]
147
- context = kwargs ['context' ]
148
- resp_data = kwargs ['resp_data' ]
174
+ def attach_promo_data (sender , request , context , resp_data , ** __ ):
175
+ """Insert promotion data keys into the footer API response."""
176
+ del sender # unused
149
177
150
178
project = context ['project' ]
151
179
theme = context ['theme' ]
152
180
153
- # Bail out early if promo's are disabled.
154
- use_promo = getattr (settings , 'USE_PROMOS' , True )
155
- if not use_promo :
181
+ if getattr (settings , 'USE_PROMOS' , True ):
182
+ promo = lookup_promo (request , project , theme )
183
+ else :
184
+ promo = None
185
+
186
+ if promo :
187
+ resp_data .update ({
188
+ 'promo' : True ,
189
+ 'promo_data' : promo ,
190
+ })
191
+ else :
156
192
resp_data ['promo' ] = False
157
- return
158
193
159
- gold_user = gold_project = False
160
- promo_obj = country_code = None
161
194
162
- show_promo = project .allow_promos
195
+ def lookup_promo (request , project , theme ):
196
+ """Look up a promo to show for the given project.
197
+
198
+ Return a dict of promo_data for inclusion in the footer response, or None
199
+ if no promo should be shown.
163
200
164
- # The request is by a GoldUser
165
- if request .user .is_authenticated ():
166
- if request .user .gold .count () or request .user .goldonce .count ():
167
- gold_user = True
201
+ """
202
+ if not project .allow_promos :
203
+ return None
168
204
169
- # A GoldUser has mapped this project
170
- if project .gold_owners .count ():
171
- gold_project = True
205
+ gold_user = is_gold_user (request .user )
206
+ gold_project = is_gold_project (project )
172
207
173
- # Don't show gold users promos.
174
- # This will get overridden if we have specific promos for them below.
208
+ # Don't show promos to gold users or on gold projects for now
209
+ # (Some day we may show them something customised for them)
175
210
if gold_user or gold_project :
176
- show_promo = False
177
-
178
- if PROMO_GEO_PATH :
179
- # Get geo information from the IP, but don't record it anywhere
180
- ip = request .META .get ('REMOTE_ADDR' )
181
- if ip :
182
- try :
183
- geo_response = geo_reader .city (ip )
184
- country_code = geo_response .country .iso_code
185
- except (AddressNotFoundError , ValueError ): # Invalid IP
186
- country_code = None
187
-
188
- # Try to get a promo if we should be using one.
189
- if show_promo :
190
- promo_obj = get_promo (
191
- country_code = country_code ,
192
- programming_language = project .programming_language ,
193
- theme = theme ,
194
- gold_project = gold_project ,
195
- gold_user = gold_user ,
196
- )
211
+ return None
212
+
213
+ promo_obj = get_promo (
214
+ country_code = get_user_country (request ),
215
+ programming_language = project .programming_language ,
216
+ theme = theme ,
217
+ gold_project = gold_project ,
218
+ gold_user = gold_user ,
219
+ )
197
220
198
221
# If we don't have anything to show, don't show it.
199
222
if not promo_obj :
200
- show_promo = False
201
-
202
- if show_promo :
203
- promo_dict = offer_promo (promo_obj = promo_obj , project = project )
204
- resp_data ['promo_data' ] = promo_dict
223
+ return None
205
224
206
- # Set promo object on return JSON
207
- resp_data ['promo' ] = show_promo
225
+ return offer_promo (
226
+ promo_obj = promo_obj ,
227
+ project = project
228
+ )
208
229
209
230
210
231
@receiver (footer_response )
@@ -217,6 +238,7 @@ def index_theme_data(sender, **kwargs):
217
238
This will allow us to give people fair warning before we put ads on their docs.
218
239
219
240
"""
241
+ del sender # unused
220
242
context = kwargs ['context' ]
221
243
222
244
project = context ['project' ]
0 commit comments