Skip to content
This repository has been archived by the owner on Mar 7, 2018. It is now read-only.

Upgrade bootstrap to fix Safari Modal not working #36

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
The Conversation
=================

Community link-sharing and discussion app, built for [USV.com](http://www.usv.com).
Community link-sharing and discussion app, originally built for [USV.com](http://www.usv.com).

Public dev list at [https://groups.google.com/forum/#!forum/conversation-app](https://groups.google.com/forum/#!forum/conversation-app)

Technology
===========

Built with:

Expand Down Expand Up @@ -67,4 +72,4 @@ We've written up a heroku-specific deployment recipe here: https://github.com/un
Documentation
------------

Basic business logic, organization details, and other documentation can be found in the documentation folder.
Basic business logic, organization details, and other documentation can be found in the documentation folder.
87 changes: 2 additions & 85 deletions app/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,91 +231,8 @@ def get(self, slug):
###########################
class ReCalculateScores(app.basic.BaseHandler):
def get(self):
# set our config values up
#staff_bonus = int(self.get_argument('staff_bonus', -3))
staff_bonus = -3
#time_penalty_multiplier = float(self.get_argument('time_penalty_multiplier', 2.0))
time_penalty_multiplier = 2.0
#grace_period = float(self.get_argument('grace_period', 6.0))
grace_period = 12.0
#comments_multiplier = float(self.get_argument('comments_multiplier', 3.0))
comments_multiplier = 3.0
#votes_multiplier = float(self.get_argument('votes_multiplier', 1.0))
votes_multiplier = 1.0
#min_votes = float(self.get_argument('min_votes', 2))
min_votes = 2

# get all the posts that have at least the 'min vote threshold'
posts = postsdb.get_posts_with_min_votes(min_votes)

data = []
for post in posts:
# determine how many hours have elapsed since this post was created
tdelta = datetime.datetime.now() - post['date_created']
hours_elapsed = tdelta.seconds/3600 + tdelta.days*24

# determine the penalty for time decay
time_penalty = 0
if hours_elapsed > grace_period:
time_penalty = hours_elapsed - grace_period
if hours_elapsed > 12:
time_penalty = time_penalty * 1.5
if hours_elapsed > 18:
time_penalty = time_penalty * 2

# get our base score from downvotes
#base_score = post['downvotes'] * -1
base_score = 0

# determine if we should assign a staff bonus or not
if post['user']['username'] in settings.get('staff'):
staff_bonus = staff_bonus
else:
staff_bonus = 0

# determine how to weight votes
votes_base_score = 0
if post['votes'] == 1 and post['comment_count'] > 2:
votes_base_score = -2
if post['votes'] > 8 and post['comment_count'] == 0:
votes_base_score = -2

scores = {}
# now actually calculate the score
total_score = base_score

scores['votes'] = (votes_base_score + post['votes'] * votes_multiplier)
total_score += scores['votes']

scores['comments'] = (post['comment_count'] * comments_multiplier)
total_score += scores['comments']

scores['time'] = (time_penalty * time_penalty_multiplier * -1)
total_score += scores['time']

total_score += staff_bonus
post['scores'] = scores

# and save the new score
postsdb.update_post_score(post['slug'], total_score)

data.append({
'username': post['user']['username'],
'title': post['title'],
'slug': post['slug'],
'date_created': post['date_created'],
'hours_elapsed': hours_elapsed,
'votes': post['votes'],
'comment_count': post['comment_count'],
'staff_bonus': staff_bonus,
'time_penalty': time_penalty,
'total_score': total_score,
'scores': scores
})

data = sorted(data, key=lambda k: k['total_score'], reverse=True)

self.render('admin/recalc_scores.html', data=data, staff_bonus=staff_bonus, time_penalty_multiplier=time_penalty_multiplier, grace_period=grace_period, comments_multiplier=comments_multiplier, votes_multiplier=votes_multiplier, min_votes=min_votes)
postsdb.sort_posts()
self.redirect('/')

###########################
### Remove user from blacklist
Expand Down
4 changes: 2 additions & 2 deletions documentation/heroku.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Setting config vars and restarting <your-app-name>... done, v793
1. Create your local settings file. Since we are targeting heroku for deployment, we want to make sure our local build environment handles config variables in a way that works for heroku. Heroku suggests using a .env file and their Foreman deployment app for this, but we've set things up a bit differently. We use a local settings file called settings_local_environ.py, which stores our local development settings. Doing it this way allows us to use Tornado's logging.info() for debugging, which you can't do with Foreman. Phew.

```
% touch settings_local_environment.py
% touch settings_local_environ.py
```
1. In the text editor of your choice, open settings_local_environ.py and add the following:

Expand Down Expand Up @@ -117,4 +117,4 @@ Voila again!





113 changes: 70 additions & 43 deletions lib/emailsdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import urllib2
import datetime
import requests
import math

from werkzeug.datastructures import MultiDict

# track emails sent to users

Expand Down Expand Up @@ -60,64 +63,78 @@ def construct_daily_email(slugs):
def send_daily_email(email):
email_sent = False
recipients = userdb.get_newsletter_recipients()
email_name = "Daily %s" % datetime.datetime.today().strftime("%a %b %d, %Y")

# 1) create the email
# POST https://api.sendgrid.com/api/newsletter/add.json
# @identity (created in advance == the sender's identity), @name (of email), @subject, @text, @html
api_link = 'https://api.sendgrid.com/api/newsletter/add.json'
params = {
'identity': settings.get('sendgrid_sender_identity'),
'name': email_name,
'subject': email['subject'],
'text': '', #to do get text version,
'html': email['body_html']
}
result = do_api_request(api_link, method="POST", params=params)

# New! Uses the sendgrid newsletter API
# =====
# 1) create a "list" for today's email
# 2) create a "list" for today's email
# POST https://api.sendgrid.com/api/newsletter/lists/add.json
# @list (list name)
api_link = 'https://api.sendgrid.com/api/newsletter/lists/add.json'
params = {
'list': "Daily %s" % datetime.datetime.today().strftime("%a %b %d, %Y")
}
list = do_api_request(api_link, method='POST', params=params)
print list
if not list:
return "Could not create List"

# 2) add everyone from our recipients list to the sendgrid list
# POST https://api.sendgrid.com/api/newsletter/lists/email/add.json
# list=ListName data[]={ 'email': '', 'name': '' } & data[]={ 'email': '', 'name': '' }
api_link = 'https://api.sendgrid.com/api/newsletter/lists/email/add.json'
data = []
for user in recipients:
data.append({
'email': user.get('email_address'),
'name': user.get('user').get('username')
})
params = {
'data': json.dumps(data),
'list': "Daily %s" % datetime.datetime.today().strftime("%a %b %d, %Y")
'list': email_name
}
result = do_api_request(api_link, method='POST', params=params)

# 3) create the email
# POST https://api.sendgrid.com/api/newsletter/add.json
# @identity (created in advance == the sender's identity), @name (of email), @subject, @text, @html
api_link = 'https://api.sendgrid.com/api/newsletter/add.json'
# 3) Add your list to the email
# POST https://api.sendgrid.com/api/newsletter/recipients/add.json
# @list (name of the list to assign to this email) @name (name of the email)
api_link = 'https://api.sendgrid.com/api/newsletter/recipients/add.json'
params = {
'identity': settings.get('sendgrid_sender_identity'),
'name': "Daily %s" % datetime.datetime.today().strftime("%a %b %d, %Y"),
'subject': email['subject'],
'text': '', #to do get text version,
'html': email['body_html']
'list': email_name,
'name': email_name,
}
result = do_api_request(api_link, method="POST", params=params)
print result

# 4) add everyone from our recipients list to the sendgrid list
# POST https://api.sendgrid.com/api/newsletter/lists/email/add.json
# list=ListName data[]={ 'email': '', 'name': '' } & data[]={ 'email': '', 'name': '' }
api_link = 'https://api.sendgrid.com/api/newsletter/lists/email/add.json'

num_groups = int(math.ceil(len(recipients) / 50))
recipient_groups = split_seq(recipients, num_groups)

for i, group in enumerate(recipient_groups):
# sendgrid needs list add requests to be < 100 peole
users = MultiDict()
for i, user in enumerate(group):
if user.get('user').get('username') != "" and user.get('email_address') != "":
users.add('data', '{"name":"%s","email":"%s"}' % (user.get('user').get('username'), user.get('email_address')))

# 4) send the email
params = {
'list': email_name,
'data': users.getlist('data')
}

result = do_api_request(api_link, method='POST', params=params)

# 5) send the email
# POST https://api.sendgrid.com/api/newsletter/schedule/add.json
# @email (created in step 3)
# @name (created in step 3)
api_link = 'https://api.sendgrid.com/api/newsletter/schedule/add.json'
params = {
'email': email,
'name': "Daily %s" % datetime.datetime.today().strftime("%a %b %d, %Y")
'name': email_name
}
result = do_api_request(api_link, 'POST', params=params)
#check email sent


# 6) Log it
if email_sent:
log_daily_email(email, recipient_usernames)

#
# Add a daily email to the log
#
Expand All @@ -137,6 +154,13 @@ def get_daily_email_log():
return list(db.email.daily.find({}, sort=[('timestamp', pymongo.DESCENDING)]))


def split_seq(seq, num_pieces):
newseq = []
splitsize = 1.0/num_pieces*len(seq)
for i in range(num_pieces):
newseq.append(seq[int(round(i*splitsize)):int(round((i+1)*splitsize))])
return newseq

#####################################################
#### ACTUALLY HANDLE THE REQUESTS/RESPOSNE TO THE API
#####################################################
Expand Down Expand Up @@ -165,13 +189,16 @@ def do_api_request(api_link, method='GET', params={}):
params=params,
verify=False
)
logging.info(r.url)
response = r.json()
except:
response = {}
if settings.get('environment') == "dev":
logging.info("=================")
logging.info( api_link)
logging.info( json.dumps(params, indent=4))
logging.info( response)
logging.info( "=================")

logging.info("=================")
logging.info( api_link)
logging.info( json.dumps(params, indent=4))
logging.info( response)

logging.info( "=================")

return response
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ beautifulsoup4
tweepy
disqus-python
splinter
selenium
selenium
werkzeug
27 changes: 27 additions & 0 deletions scripts/daily_newsletter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Run by Heroku scheduler every night
# If running locally, uncomment below imports
import sys
sys.path.insert(0, '/Users/nick/dev/usv/usv.com')
import settings
import requests
import logging
from lib import emailsdb
import csv


''''
recipients = userdb.get_newsletter_recipients()
csvfile = open('daily_emails.csv', 'wb')
writer = csv.writer(csvfile)
for user in recipients:
data = [
user['user']['username'],
user['email_address']
]
writer.writerow(data)
csvfile.close()
'''

email = emailsdb.construct_daily_email(['innovation-under-austerity-eben-moglens-call-to-arms-from-freedom-to-connect'])

send = emailsdb.send_daily_email(email)
Loading