Last active
January 4, 2016 04:39
-
-
Save ndreckshage/8569553 to your computer and use it in GitHub Desktop.
snapsecret v2 (not everything included...)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.ApplicationController = Ember.Controller.extend | |
countdownWarning: false | |
countdown: 60 | |
stats: | |
totalRead: if !!window.secretStats and !!window.secretStats.totalRead then window.secretStats.totalRead else null | |
totalSpilled: if !!window.secretStats and !!window.secretStats.totalSpilled then window.secretStats.totalSpilled else null | |
warnAtTen: (() -> | |
if @countdown == 10 | |
@set 'countdownWarning', true | |
else if @countdown > 10 | |
@set 'countdownWarning', false | |
).observes('countdown') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.ConfessController = Ember.ObjectController.extend | |
needs: ['index', 'messages'] | |
message: '' | |
validate: () -> | |
message = @get('message') || '' | |
wordCount = (message.match(/\S+/g) || []).length | |
if 500 >= wordCount >= 10 | |
@set 'isValid', true | |
@get('controllers.messages').set('failureMessages', []) | |
else | |
@set 'isValid', false | |
error = if wordCount < 10 then "a secret with less then 10 words is hardly a secret." else "500 words max. this isnt wikileaks. (you entered #{wordCount})" | |
@get('controllers.messages').set('failureMessages', [error]) | |
formatTime: (time_in_minutes) -> | |
time_in_minutes = 1 if time_in_minutes is 0 | |
hours = Math.floor(time_in_minutes / 60) | |
minutes = time_in_minutes % 60 | |
message = "" | |
if hours > 0 | |
message += "#{hours} hour" | |
message += "s" unless hours is 1 | |
if minutes > 0 | |
message += " and " unless hours is 0 | |
message += "#{minutes} minute" | |
message += "s" unless minutes is 1 | |
message | |
handleErrors: (model) -> | |
if model.errors | |
if model.errors.message and model.errors.tooManySecrets | |
errors = $.merge(model.errors.message, model.errors.tooManySecrets) | |
else if model.errors.message | |
errors = model.errors.message | |
else if model.errors.tooManySecrets | |
errors = model.errors.tooManySecrets | |
@get('controllers.messages').set 'failureMessages', errors | |
handleSuccess: (model) -> | |
@set 'message', '' | |
data = model.get('data') | |
queued_secrets = data.queue_estimate | |
queued_minutes = @formatTime(queued_secrets) | |
secrets = if queued_secrets is 1 then "secret" else "secrets" | |
if queued_secrets is 0 and @get('controllers.index').get('model.secret.message') is null | |
@get('controllers.messages').set 'successMessage', "Spilling your secret as we speak..." | |
window.activeSecret = { secret: data } | |
else | |
@get('controllers.messages').set 'successMessage', "Secret set to be spilled in #{queued_minutes}, after #{queued_secrets} #{secrets}." | |
@transitionToRoute('index') | |
actions: | |
confessSecret: () -> | |
@validate() | |
if @get 'isValid' | |
@store.createRecord('secret', { | |
message: @get 'message' | |
}).save().then ((model) => @handleSuccess model | |
), (model) => @handleErrors model | |
previewMarkdown: () -> | |
@set 'previewMarkdown', true | |
hideMarkdown: () -> | |
@set 'previewMarkdown', false | |
markdownLink: () -> | |
window.open('http://daringfireball.net/projects/markdown/') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.ConfessRoute = Ember.Route.extend | |
model: () -> {} | |
renderTemplate: (controller, model) -> | |
@controllerFor('messages').set('successMessage', null) | |
@render('messages', { | |
outlet: 'messages' | |
}) | |
@render('confess') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.IndexController = Ember.ObjectController.extend | |
needs: ['application', 'messages'] | |
needsConfirmation: false | |
defaultCountdown: 60 | |
defaultConfirm: 5 | |
secretsSpilled: 1 | |
secretsRead: 1 | |
updateModel: () -> | |
@get('controllers.messages').set 'successMessage', null | |
window.SnapSecret.Secret.find().then (data) => | |
_data = if data then data else { secret: { message: null }} | |
@set 'model', _data | |
@updateComplete() | |
updateComplete: () -> | |
@set 'fetchingSecret', false | |
application = @get('controllers.application') | |
application.set 'countdown', @get('defaultCountdown') | |
stats = @get 'secret.stats' | |
application.set('stats', stats) if stats | |
secretsSpilled = @get 'secretsSpilled' | |
@set 'secretsSpilled', ++secretsSpilled | |
secretsRead = @get 'secretsRead' | |
@set 'secretsRead', ++secretsRead | |
@countdownInterval = setInterval $.proxy(@contentCountdown, @), 1000 | |
contentCountdown: () -> | |
application = @get('controllers.application') | |
counter = application.get('countdown') | |
counter-- | |
application.set 'countdown', counter | |
if counter is 0 | |
clearInterval @countdownInterval | |
if @get('secretsSpilled') >= @get('defaultConfirm') | |
@set 'needsConfirmation', true | |
else | |
@set 'fetchingSecret', true | |
@updateModel() | |
reset: () -> | |
clearInterval @countdownInterval | |
application = @get('controllers.application') | |
application.set 'countdown', @get('defaultCountdown') | |
@set 'secretsSpilled', 1 | |
@set 'needsConfirmation', false | |
actions: | |
startTheClock: () -> | |
@countdownInterval = setInterval $.proxy(@contentCountdown, @), 1000 | |
stopTheClock: () -> | |
@reset() | |
confirmNSA: () -> | |
window.location.href = 'http://www.whitehouse.gov/our-government/the-constitution' | |
confirmNotNSA: () -> | |
@set 'needsConfirmation', false | |
@set 'secretsSpilled', 0 | |
@updateModel() | |
checkAgain: () -> | |
@reset() | |
@set 'fetchingSecret', true | |
@updateModel() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.IndexRoute = Ember.Route.extend | |
model: () -> window.activeSecret | |
setupController: (controller, model) -> | |
model = { secret: { message: null }} unless model | |
controller.set 'model', model | |
controller.send 'startTheClock' | |
deactivate: () -> | |
@controller.send('stopTheClock') | |
renderTemplate: (controller, model) -> | |
@controllerFor('messages').set('failureMessages', []) | |
@render('messages', { | |
outlet: 'messages' | |
}) | |
@render('index') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.SnapSecret.Secret = DS.Model.extend | |
message: DS.attr('string') | |
window.SnapSecret.Secret.reopenClass | |
find: () -> $.getJSON('/api/v1/secrets.json').then (data) => | |
window.activeSecret = if data then data else { secret: { message: null }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Secret < ActiveRecord::Base | |
validate :two_secrets_per_hour | |
validates :message, length: { | |
minimum: 10, | |
maximum: 500, | |
tokenizer: lambda { |str| str.scan(/\w+/) }, | |
too_short: "a secret with less then %{count} words is hardly a secret.", | |
too_long: "%{count} words max. this isnt wikileaks." | |
} | |
scope :unseen, -> { where(displayed: false).order(:id) } | |
scope :seen, -> { where(displayed: true).order(:id) } | |
scope :from_past_hour, -> { where('created_at > ?', Time.now - 1.hour) } | |
scope :with_ip_address, -> (ip_address) { where('ip_address = ?', ip_address) } | |
def self.get_from_cache | |
secret = Rails.cache.fetch('secret', expires_in: 50.seconds) { self.get } | |
secret.increment_view_count if secret | |
secret | |
end | |
def self.get_stats_from_cache | |
Rails.cache.fetch('secret_stats', expires_in: 1.minutes) { self.get_stats } | |
end | |
def self.get_queue | |
unseen.count | |
end | |
def increment_view_count | |
previous = Rails.cache.read([self, 'view_count']) || self.view_count | |
current = previous += 1 | |
Rails.cache.write([self, 'view_count'], current) | |
self.view_count = current | |
save | |
end | |
private | |
def self.get | |
previous = self.seen.last | |
current = self.unseen.first | |
current.update_attribute(:displayed, true) unless current.nil? | |
current | |
end | |
def self.get_stats | |
totalSpilled = Secret.count | |
totalRead = Secret.sum(:view_count).to_i | |
{ totalSpilled: totalSpilled, totalRead: totalRead } | |
end | |
def two_secrets_per_hour | |
if self.class.unseen.present? and self.class.from_past_hour.with_ip_address(self.ip_address).length > 1 | |
errors.add(:too_many_secrets, "easy there, snowden. two secrets per hour.") | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Api::V1::SecretsController < ApplicationController | |
respond_to :json | |
def index | |
respond_with Secret.get_from_cache | |
end | |
def create | |
@secret = Secret.new(secret_params.merge({ | |
ip_address: request.remote_ip, | |
queue_estimate: Secret.get_queue | |
})) | |
if @secret.save | |
render json: @secret, status: :created | |
else | |
render json: { errors: @secret.errors }, status: :unprocessable_entity | |
end | |
end | |
private | |
def secret_params | |
params.fetch(:secret, {}).permit(:message, :queue_estimate, :ip_address) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment