mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
Implementing alternative pricing with Alipay in China to support dedicated China server.
This commit is contained in:
parent
26b7c65855
commit
b4ea78e5cb
22 changed files with 100 additions and 53 deletions
|
@ -4,7 +4,7 @@ module.exports = handler = StripeCheckout.configure({
|
||||||
key: publishableKey
|
key: publishableKey
|
||||||
name: 'CodeCombat'
|
name: 'CodeCombat'
|
||||||
email: me.get('email')
|
email: me.get('email')
|
||||||
image: '/images/pages/base/logo_square_250.png'
|
image: "https://codecombat.com/images/pages/base/logo_square_250.png"
|
||||||
token: (token) ->
|
token: (token) ->
|
||||||
Backbone.Mediator.publish 'stripe:received-token', { token: token }
|
Backbone.Mediator.publish 'stripe:received-token', { token: token }
|
||||||
locale: 'auto'
|
locale: 'auto'
|
||||||
|
|
|
@ -581,13 +581,14 @@
|
||||||
intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
|
intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
|
||||||
intro_2: "No experience required!"
|
intro_2: "No experience required!"
|
||||||
free_title: "How much does it cost?"
|
free_title: "How much does it cost?"
|
||||||
|
cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 per month for access to our other 120+ levels on our exclusive China servers."
|
||||||
free_1: "CodeCombat Basic is FREE! There are 70+ free levels which cover every concept."
|
free_1: "CodeCombat Basic is FREE! There are 70+ free levels which cover every concept."
|
||||||
free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
|
free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
|
||||||
teacher_subs_title: "Teachers get free subscriptions!"
|
teacher_subs_title: "Teachers get free subscriptions!"
|
||||||
teacher_subs_1: "Please contact"
|
teacher_subs_1: "Please contact"
|
||||||
teacher_subs_2: "to setup a free monthly subscription."
|
teacher_subs_2: "to set up a free monthly subscription."
|
||||||
sub_includes_title: "What is included in the subscription?"
|
sub_includes_title: "What is included in the subscription?"
|
||||||
sub_includes_1: "In additional to the 70+ free levels, students with a monthly subscription get access to these additional features:"
|
sub_includes_1: "In additional to the 70+ basic levels, students with a monthly subscription get access to these additional features:" # {change}
|
||||||
sub_includes_2: "40+ practice levels"
|
sub_includes_2: "40+ practice levels"
|
||||||
sub_includes_3: "Video tutorials"
|
sub_includes_3: "Video tutorials"
|
||||||
sub_includes_4: "Premium email support"
|
sub_includes_4: "Premium email support"
|
||||||
|
@ -597,7 +598,8 @@
|
||||||
who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed."
|
who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed."
|
||||||
who_for_2: "We've designed CodeCombat to appeal to both boys and girls."
|
who_for_2: "We've designed CodeCombat to appeal to both boys and girls."
|
||||||
material_title: "How much material is there?"
|
material_title: "How much material is there?"
|
||||||
material_1: "Approximately 8 hours of free content, and an additional 14 hours of subscriber content."
|
material_china: "Approximately 22 hours of gameplay spread over 120+ subscriber-only levels so far, with 5 new levels every week."
|
||||||
|
material_1: "Approximately 8 hours of free content and an additional 14 hours of subscriber content, with 5 new levels every week." # {change}
|
||||||
concepts_title: "What concepts are covered?"
|
concepts_title: "What concepts are covered?"
|
||||||
how_much_title: "How much does a monthly subscription cost?"
|
how_much_title: "How much does a monthly subscription cost?"
|
||||||
how_much_1: "A"
|
how_much_1: "A"
|
||||||
|
|
|
@ -304,6 +304,7 @@ _.extend UserSchema.properties,
|
||||||
|
|
||||||
siteref: { type: 'string' }
|
siteref: { type: 'string' }
|
||||||
referrer: { type: 'string' }
|
referrer: { type: 'string' }
|
||||||
|
chinaVersion: { type: 'boolean' }
|
||||||
|
|
||||||
c.extendBasicProperties UserSchema, 'user'
|
c.extendBasicProperties UserSchema, 'user'
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ block header
|
||||||
a(href="/")
|
a(href="/")
|
||||||
span.glyphicon.glyphicon-home
|
span.glyphicon.glyphicon-home
|
||||||
a(href="/about", data-i18n="nav.about")
|
a(href="/about", data-i18n="nav.about")
|
||||||
a(href='/play/ladder', data-i18n="home.multiplayer").multiplayer-nav-link
|
//a(href='/play/ladder', data-i18n="home.multiplayer").multiplayer-nav-link
|
||||||
a(href='/community', data-i18n="nav.community")
|
a(href='/community', data-i18n="nav.community")
|
||||||
a(href='http://blog.codecombat.com/', data-i18n="nav.blog")
|
a(href='http://blog.codecombat.com/', data-i18n="nav.blog")
|
||||||
a(href='http://discourse.codecombat.com/', data-i18n="nav.forum")
|
a(href='http://discourse.codecombat.com/', data-i18n="nav.forum")
|
||||||
|
|
|
@ -78,6 +78,7 @@ block content
|
||||||
a(href="/contribute/artisan")
|
a(href="/contribute/artisan")
|
||||||
img(src="/images/pages/community/artisan.png")
|
img(src="/images/pages/community/artisan.png")
|
||||||
|
|
||||||
|
if !me.get('chinaVersion')
|
||||||
a(href="/contribute/adventurer")
|
a(href="/contribute/adventurer")
|
||||||
img(src="/images/pages/community/adventurer.png")
|
img(src="/images/pages/community/adventurer.png")
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ block content
|
||||||
p(data-i18n="classes.artisan_summary")
|
p(data-i18n="classes.artisan_summary")
|
||||||
| Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program.
|
| Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program.
|
||||||
|
|
||||||
|
if !me.get('chinaVersion')
|
||||||
a(href="/contribute/adventurer")
|
a(href="/contribute/adventurer")
|
||||||
div.class_tile
|
div.class_tile
|
||||||
img.tile-img(src="/images/pages/contribute/tile_adventurer.png", alt="")
|
img.tile-img(src="/images/pages/contribute/tile_adventurer.png", alt="")
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th
|
th
|
||||||
|
if !me.get('chinaVersion')
|
||||||
th(data-i18n="subscribe.free")
|
th(data-i18n="subscribe.free")
|
||||||
th
|
th
|
||||||
//- TODO: find a better way to localize '$9.99/month'
|
//- TODO: find a better way to localize '$9.99/month'
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="subscribe.feature1")
|
span(data-i18n="subscribe.feature1")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
td.center-ok
|
td.center-ok
|
||||||
|
@ -36,30 +38,35 @@
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="[html]subscribe.feature2")
|
span(data-i18n="[html]subscribe.feature2")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td
|
td
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="subscribe.feature3")
|
span(data-i18n="subscribe.feature3")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td
|
td
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="[html]subscribe.feature4")
|
span(data-i18n="[html]subscribe.feature4")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td
|
td
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="subscribe.feature5")
|
span(data-i18n="subscribe.feature5")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td
|
td
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
tr
|
tr
|
||||||
td.feature-description
|
td.feature-description
|
||||||
span(data-i18n="subscribe.feature6")
|
span(data-i18n="subscribe.feature6")
|
||||||
|
if !me.get('chinaVersion')
|
||||||
td
|
td
|
||||||
td.center-ok
|
td.center-ok
|
||||||
span.glyphicon.glyphicon-ok
|
span.glyphicon.glyphicon-ok
|
||||||
|
|
|
@ -49,10 +49,11 @@ block content
|
||||||
span.spl(data-i18n="legal.email_description_suffix")
|
span.spl(data-i18n="legal.email_description_suffix")
|
||||||
| or through links in the emails we send,
|
| or through links in the emails we send,
|
||||||
| you can change your preferences and easily unsubscribe at any time.
|
| you can change your preferences and easily unsubscribe at any time.
|
||||||
|
if !me.get('chinaVersion')
|
||||||
h4(data-i18n="legal.cost_title")
|
h4(data-i18n="legal.cost_title")
|
||||||
| Cost
|
| Cost
|
||||||
p(data-i18n="legal.cost_description")
|
p(data-i18n="legal.cost_description")
|
||||||
| CodeCombat is free to play in the dungeon campaign, with a $9.99 USD/mo subscription for access to later campaigns and 3500 bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee.
|
| CodeCombat is free to play for all of its core levels, with a $9.99 USD/mo subscription for access to extra level branches and 3500 bonus gems per month. You can cancel with a click, and we offer a 100% money-back guarantee.
|
||||||
|
|
||||||
h2(data-i18n="legal.copyrights_title")
|
h2(data-i18n="legal.copyrights_title")
|
||||||
| Copyrights and Licenses
|
| Copyrights and Licenses
|
||||||
|
|
|
@ -10,7 +10,7 @@ if docs.length === 1
|
||||||
div
|
div
|
||||||
!= docs[0].html
|
!= docs[0].html
|
||||||
|
|
||||||
if (me.get('preferredLanguage') || 'en-US').substr(0, 2) == 'en'
|
if (!me.isPremium() || me.isAdmin()) && (me.get('preferredLanguage') || 'en-US').substr(0, 2) == 'en'
|
||||||
hr
|
hr
|
||||||
h3 Want more programming lessons?
|
h3 Want more programming lessons?
|
||||||
ul
|
ul
|
||||||
|
|
|
@ -11,6 +11,9 @@ block content
|
||||||
p(data-i18n="teachers.intro_2")
|
p(data-i18n="teachers.intro_2")
|
||||||
|
|
||||||
h3(data-i18n="teachers.free_title")
|
h3(data-i18n="teachers.free_title")
|
||||||
|
if me.get('chinaVersion')
|
||||||
|
p(data-i18n="teachers.cost_china")
|
||||||
|
else
|
||||||
p(data-i18n="teachers.free_1")
|
p(data-i18n="teachers.free_1")
|
||||||
p(data-i18n="teachers.free_2")
|
p(data-i18n="teachers.free_2")
|
||||||
|
|
||||||
|
@ -35,6 +38,9 @@ block content
|
||||||
p(data-i18n="teachers.who_for_2")
|
p(data-i18n="teachers.who_for_2")
|
||||||
|
|
||||||
h3(data-i18n="teachers.material_title")
|
h3(data-i18n="teachers.material_title")
|
||||||
|
if me.get('chinaVersion')
|
||||||
|
p(data-i18n="teachers.material_china")
|
||||||
|
else
|
||||||
p(data-i18n="teachers.material_1")
|
p(data-i18n="teachers.material_1")
|
||||||
|
|
||||||
h3(data-i18n="teachers.concepts_title")
|
h3(data-i18n="teachers.concepts_title")
|
||||||
|
|
|
@ -53,7 +53,7 @@ module.exports = class InvoicesView extends RootView
|
||||||
amount: @amount
|
amount: @amount
|
||||||
description: @description
|
description: @description
|
||||||
bitcoin: true
|
bitcoin: true
|
||||||
alipay: 'auto'
|
alipay: if me.get('chinaVersion') or me.get('preferredLanguage')[...2] is 'zh' then true else 'auto'
|
||||||
|
|
||||||
onStripeReceivedToken: (e) ->
|
onStripeReceivedToken: (e) ->
|
||||||
data = {
|
data = {
|
||||||
|
|
|
@ -247,7 +247,7 @@ class RecipientSubs
|
||||||
options = {
|
options = {
|
||||||
description: "#{@recipientEmails.length} " + $.i18n.t('subscribe.stripe_description', defaultValue: 'Monthly Subscriptions')
|
description: "#{@recipientEmails.length} " + $.i18n.t('subscribe.stripe_description', defaultValue: 'Monthly Subscriptions')
|
||||||
amount: amount
|
amount: amount
|
||||||
alipay: 'auto'
|
alipay: if me.get('chinaVersion') or me.get('preferredLanguage')[...2] is 'zh' then true else 'auto'
|
||||||
alipayReusable: true
|
alipayReusable: true
|
||||||
}
|
}
|
||||||
@state = 'start subscribe'
|
@state = 'start subscribe'
|
||||||
|
|
|
@ -112,7 +112,7 @@ module.exports = class SubscribeModal extends ModalView
|
||||||
options = {
|
options = {
|
||||||
description: $.i18n.t('subscribe.stripe_description')
|
description: $.i18n.t('subscribe.stripe_description')
|
||||||
amount: @product.amount
|
amount: @product.amount
|
||||||
alipay: 'auto'
|
alipay: if me.get('chinaVersion') or me.get('preferredLanguage')[...2] is 'zh' then true else 'auto'
|
||||||
alipayReusable: true
|
alipayReusable: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -432,7 +432,9 @@ module.exports = class CampaignView extends RootView
|
||||||
levelOriginal = levelElement.data('level-original')
|
levelOriginal = levelElement.data('level-original')
|
||||||
level = _.find _.values(@campaign.get('levels')), slug: levelSlug
|
level = _.find _.values(@campaign.get('levels')), slug: levelSlug
|
||||||
|
|
||||||
if level.requiresSubscription and @requiresSubscription and not @levelStatusMap[level.slug] and not level.adventurer
|
requiresSubscription = level.requiresSubscription or (me.get('chinaVersion') and not (level.slug in ['dungeons-of-kithgard', 'gems-in-the-deep', 'shadow-guard', 'forgetful-gemsmith', 'signs-and-portents', 'true-names']))
|
||||||
|
canPlayAnyway = not @requiresSubscription or level.adventurer
|
||||||
|
if requiresSubscription and not canPlayAnyway
|
||||||
@openModalView new SubscribeModal()
|
@openModalView new SubscribeModal()
|
||||||
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'map level clicked', level: levelSlug
|
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'map level clicked', level: levelSlug
|
||||||
else
|
else
|
||||||
|
|
|
@ -111,7 +111,7 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
|
|
||||||
onClickStartSubscription: (e) ->
|
onClickStartSubscription: (e) ->
|
||||||
@openModalView new SubscribeModal()
|
@openModalView new SubscribeModal()
|
||||||
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'level loading', level: @options.level.get('slug')
|
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'level loading', level: @level?.get('slug') or @options.level?.get('slug')
|
||||||
|
|
||||||
onSubscribed: ->
|
onSubscribed: ->
|
||||||
document.location.reload()
|
document.location.reload()
|
||||||
|
|
|
@ -70,7 +70,7 @@ module.exports = class BuyGemsModal extends ModalView
|
||||||
description: $.t(product.i18n)
|
description: $.t(product.i18n)
|
||||||
amount: product.amount
|
amount: product.amount
|
||||||
bitcoin: true
|
bitcoin: true
|
||||||
alipay: 'auto'
|
alipay: if me.get('chinaVersion') or me.get('preferredLanguage')[...2] is 'zh' then true else 'auto'
|
||||||
})
|
})
|
||||||
|
|
||||||
@productBeingPurchased = product
|
@productBeingPurchased = product
|
||||||
|
|
22
scripts/mongodb/unsubmit-ladder.js
Normal file
22
scripts/mongodb/unsubmit-ladder.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
var levelID = 'zero-sum';
|
||||||
|
var sessions = db.level.sessions.find({levelID: levelID, submitted: true}).toArray();
|
||||||
|
for (var i = 0; i < sessions.length; ++i) {
|
||||||
|
var session = sessions[i];
|
||||||
|
if (session.creatorName == 'The AI') continue;
|
||||||
|
if (!session.submittedCode) continue;
|
||||||
|
print("Unsubmitting " + session.creatorName + " " + session.team);
|
||||||
|
session.submitted = false;
|
||||||
|
db.level.sessions.save(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Resubmit
|
||||||
|
// var levelID = 'zero-sum';
|
||||||
|
// var sessions = db.level.sessions.find({levelID: levelID, submitted: false}).toArray();
|
||||||
|
// for (var i = 0; i < sessions.length; ++i) {
|
||||||
|
// var session = sessions[i];
|
||||||
|
// if (session.creatorName == 'The AI') continue;
|
||||||
|
// if (!session.submittedCode) continue;
|
||||||
|
// print("Resubmitting " + session.creatorName + " " + session.team);
|
||||||
|
// session.submitted = true; // false;
|
||||||
|
// db.level.sessions.save(session);
|
||||||
|
// }
|
|
@ -82,6 +82,7 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
|
|
||||||
fetchLevelByIDAndHandleErrors: (id, req, res, callback) ->
|
fetchLevelByIDAndHandleErrors: (id, req, res, callback) ->
|
||||||
|
# TODO: this could probably be faster with projections, right?
|
||||||
@getDocumentForIdOrSlug id, (err, level) =>
|
@getDocumentForIdOrSlug id, (err, level) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
return @sendNotFoundError(res) unless level?
|
return @sendNotFoundError(res) unless level?
|
||||||
|
@ -103,7 +104,9 @@ LevelHandler = class LevelHandler extends Handler
|
||||||
Session.findOne(sessionQuery).exec (err, doc) =>
|
Session.findOne(sessionQuery).exec (err, doc) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
return @sendSuccess(res, doc) if doc?
|
return @sendSuccess(res, doc) if doc?
|
||||||
return @sendPaymentRequiredError(res, err) if (not req.user.isPremium()) and level.get('requiresSubscription') and not level.get('adventurer')
|
requiresSubscription = level.get('requiresSubscription') or (req.user.get('chinaVersion') and level.get('campaign') and not (level.slug in ['dungeons-of-kithgard', 'gems-in-the-deep', 'shadow-guard', 'forgetful-gemsmith', 'signs-and-portents', 'true-names']))
|
||||||
|
canPlayAnyway = req.user.isPremium() or level.get 'adventurer'
|
||||||
|
return @sendPaymentRequiredError(res, err) if requiresSubscription and not canPlayAnyway
|
||||||
@createAndSaveNewSession sessionQuery, req, res
|
@createAndSaveNewSession sessionQuery, req, res
|
||||||
|
|
||||||
createAndSaveNewSession: (sessionQuery, req, res) =>
|
createAndSaveNewSession: (sessionQuery, req, res) =>
|
||||||
|
|
|
@ -202,3 +202,4 @@ module.exports.makeNewUser = makeNewUser = (req) ->
|
||||||
lang = languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
|
lang = languages.languageCodeFromAcceptedLanguages req.acceptedLanguages
|
||||||
user.set 'preferredLanguage', lang if lang[...2] isnt 'en'
|
user.set 'preferredLanguage', lang if lang[...2] isnt 'en'
|
||||||
user.set 'lastIP', req.connection.remoteAddress
|
user.set 'lastIP', req.connection.remoteAddress
|
||||||
|
user.set 'chinaVersion', true if req.chinaVersion
|
||||||
|
|
|
@ -728,7 +728,7 @@ sendNextStepsEmail = (user, now, daysAgo) ->
|
||||||
possibleAdditionalOffers = ['code-school', 'one-month', 'learnable', 'pluralsight']
|
possibleAdditionalOffers = ['code-school', 'one-month', 'learnable', 'pluralsight']
|
||||||
for offer in _.sample possibleAdditionalOffers, nAdditionalOffers
|
for offer in _.sample possibleAdditionalOffers, nAdditionalOffers
|
||||||
offers[offer] = true
|
offers[offer] = true
|
||||||
|
# TODO: adjust template to not include any offers if user.isPremium()
|
||||||
# TODO: do something with the preferredLanguage?
|
# TODO: do something with the preferredLanguage?
|
||||||
context =
|
context =
|
||||||
email_id: sendwithus.templates.next_steps_email
|
email_id: sendwithus.templates.next_steps_email
|
||||||
|
|
|
@ -136,10 +136,11 @@ UserSchema.statics.updateServiceSettings = (doc, callback) ->
|
||||||
groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]
|
groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]
|
||||||
'new-email': doc.get('email')
|
'new-email': doc.get('email')
|
||||||
}
|
}
|
||||||
|
#params.merge_vars.chinaVersion = true if doc.get('chinaVersion') # ???
|
||||||
params.update_existing = true
|
params.update_existing = true
|
||||||
|
|
||||||
onSuccess = (data) ->
|
onSuccess = (data) ->
|
||||||
data.email = doc.get('email') # Make sure that we don't spam opt-in emails even if MailChimp doesn't udpate the email it gets in this object until they have confirmed.
|
data.email = doc.get('email') # Make sure that we don't spam opt-in emails even if MailChimp doesn't update the email it gets in this object until they have confirmed.
|
||||||
doc.set('mailChimp', data)
|
doc.set('mailChimp', data)
|
||||||
doc.updatedMailChimp = true
|
doc.updatedMailChimp = true
|
||||||
doc.save()
|
doc.save()
|
||||||
|
@ -291,7 +292,7 @@ UserSchema.statics.hashPassword = (password) ->
|
||||||
UserSchema.statics.privateProperties = [
|
UserSchema.statics.privateProperties = [
|
||||||
'permissions', 'email', 'mailChimp', 'firstName', 'lastName', 'gender', 'facebookID',
|
'permissions', 'email', 'mailChimp', 'firstName', 'lastName', 'gender', 'facebookID',
|
||||||
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement',
|
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement',
|
||||||
'emailSubscriptions', 'emails', 'activity', 'stripe', 'stripeCustomerID'
|
'emailSubscriptions', 'emails', 'activity', 'stripe', 'stripeCustomerID', 'chinaVersion'
|
||||||
]
|
]
|
||||||
UserSchema.statics.jsonSchema = jsonschema
|
UserSchema.statics.jsonSchema = jsonschema
|
||||||
UserSchema.statics.editableProperties = [
|
UserSchema.statics.editableProperties = [
|
||||||
|
|
|
@ -79,19 +79,18 @@ setupPassportMiddleware = (app) ->
|
||||||
app.use(authentication.session())
|
app.use(authentication.session())
|
||||||
|
|
||||||
setupChinaRedirectMiddleware = (app) ->
|
setupChinaRedirectMiddleware = (app) ->
|
||||||
isInChina = (req) ->
|
shouldRedirectToChinaVersion = (req) ->
|
||||||
|
speaksChinese = req.acceptedLanguages[0]?.indexOf('zh') isnt -1
|
||||||
unless config.tokyo
|
unless config.tokyo
|
||||||
ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
|
ip = req.headers['x-forwarded-for'] or req.connection.remoteAddress
|
||||||
geo = geoip.lookup(ip)
|
geo = geoip.lookup(ip)
|
||||||
if geo?.country isnt "CN" then return false
|
return geo?.country is "CN" and speaksChinese
|
||||||
firstAcceptedLanguage = req.acceptedLanguages[0]
|
|
||||||
isChinese = firstAcceptedLanguage?.indexOf? "zh"
|
|
||||||
return isChinese? and isChinese isnt -1
|
|
||||||
else
|
else
|
||||||
return false #If the user is already redirected, don't redirect them!
|
req.chinaVersion = true
|
||||||
|
return false # If the user is already redirected, don't redirect them!
|
||||||
|
|
||||||
app.use (req, res, next) ->
|
app.use (req, res, next) ->
|
||||||
if isInChina req
|
if shouldRedirectToChinaVersion req
|
||||||
res.writeHead 302, "Location": config.chinaDomain + req.url
|
res.writeHead 302, "Location": config.chinaDomain + req.url
|
||||||
res.end()
|
res.end()
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue