Lottsa updates
This commit is contained in:
Родитель
0c5e3de4f2
Коммит
ccbbd274f8
|
@ -37,4 +37,93 @@ node_modules
|
|||
Dockerfile
|
||||
docker-compose.yml
|
||||
.DS_Store
|
||||
/*.env
|
||||
/*.env
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask instance folder
|
||||
instance/
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
3
Procfile
3
Procfile
|
@ -1 +1,2 @@
|
|||
web: node src/web/index.js
|
||||
web: node src/web/index.js
|
||||
clock: python src/clock/clock.py
|
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE accesstokens (
|
||||
id bigserial primary key,
|
||||
token varchar(100) NOT NULL,
|
||||
uid varchar(100) NOT NULL,
|
||||
date_added timestamp default current_timestamp
|
||||
)
|
|
@ -8,7 +8,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ejs": "2.4.1",
|
||||
"express": "4.13.4"
|
||||
"express": "4.13.4",
|
||||
"requestify": "0.1.17",
|
||||
"pg": "4.5.3"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Wade Wegner",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
APScheduler==3.0.0
|
|
@ -0,0 +1,20 @@
|
|||
from datetime import datetime
|
||||
|
||||
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||
|
||||
from urllib2 import Request, urlopen, URLError
|
||||
|
||||
def job_function():
|
||||
print("Hello World")
|
||||
|
||||
request = Request('http://localhost:5000/trigger')
|
||||
response = urlopen(request)
|
||||
kittens = response.read()
|
||||
print(kittens)
|
||||
|
||||
sched = BlockingScheduler()
|
||||
|
||||
# Schedule job_function to be called every two hours
|
||||
sched.add_job(job_function, 'interval', seconds=2)
|
||||
|
||||
sched.start()
|
166
src/web/index.js
166
src/web/index.js
|
@ -1,20 +1,172 @@
|
|||
var express = require('express');
|
||||
var app = express();
|
||||
var pg = require('pg');
|
||||
|
||||
|
||||
// First, checks if it isn't implemented yet.
|
||||
if (!String.prototype.format) {
|
||||
String.prototype.format = function() {
|
||||
var args = arguments;
|
||||
return this.replace(/{(\d+)}/g, function(match, number) {
|
||||
return typeof args[number] != 'undefined'
|
||||
? args[number]
|
||||
: match
|
||||
;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
app.set('port', (process.env.PORT || 5000));
|
||||
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
// views is directory for all template files
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
var clientId = process.env.CLIENT_ID;
|
||||
var clientSecret = process.env.CLIENT_SECRET;
|
||||
var redirectUrl = process.env.REDIRECT_URL;
|
||||
|
||||
var code = '';
|
||||
var accessToken = '';
|
||||
var signinUrl = 'https://untappd.com/oauth/authenticate/?client_id={0}&response_type=code&redirect_url={1}'.format(clientId, redirectUrl);
|
||||
var firstName = '';
|
||||
var lastName = '';
|
||||
var userName = '';
|
||||
|
||||
// index.ejs
|
||||
app.get('/', function(request, response) {
|
||||
response.render('pages/index');
|
||||
response.render('pages/index', {
|
||||
signinUrl: signinUrl,
|
||||
accessToken: accessToken
|
||||
});
|
||||
});
|
||||
|
||||
// profile.ejs
|
||||
app.get('/profile', function(request, response) {
|
||||
response.render('pages/profile', {
|
||||
signinUrl: signinUrl,
|
||||
accessToken: accessToken
|
||||
});
|
||||
});
|
||||
|
||||
// logout
|
||||
app.get('/logout', function(request, response) {
|
||||
accessToken = '';
|
||||
userName = '';
|
||||
response.redirect('/');
|
||||
});
|
||||
|
||||
// trigger
|
||||
app.get('/trigger', function(request, response) {
|
||||
response.send('trigger')
|
||||
});
|
||||
|
||||
|
||||
// oauth callback
|
||||
app.get('/callback', function(request, response) {
|
||||
|
||||
code = request.query.code;
|
||||
|
||||
var url = 'https://untappd.com/oauth/authorize/?client_id={0}&client_secret={1}&response_type=code&redirect_url={2}&code={3}'.format(clientId, clientSecret, redirectUrl, code);
|
||||
|
||||
var requestify = require('requestify');
|
||||
|
||||
requestify.get(url).then(function(response2) {
|
||||
|
||||
accessToken = response2.getBody().response.access_token;
|
||||
|
||||
console.log(accessToken);
|
||||
|
||||
var userInfoUrl = 'https://api.untappd.com/v4/user/info?access_token={0}'.format(accessToken);
|
||||
|
||||
requestify.get(userInfoUrl).then(function(response3) {
|
||||
|
||||
var uid = response3.getBody().response.user.user_name;
|
||||
var id = response3.getBody().response.user.id;
|
||||
var user_name = response3.getBody().response.user.user_name;
|
||||
var first_name = response3.getBody().response.user.first_name;
|
||||
var last_name = response3.getBody().response.user.last_name;
|
||||
var user_avatar = response3.getBody().response.user.user_avatar;
|
||||
var user_avatar_hd = response3.getBody().response.user.user_avatar_hd;
|
||||
var user_cover_photo = response3.getBody().response.user.user_cover_photo;
|
||||
var user_cover_photo_offset = response3.getBody().response.user.user_cover_photo_offset;
|
||||
var location = response3.getBody().response.user.location;
|
||||
var bio = response3.getBody().response.user.bio;
|
||||
var url = response3.getBody().response.user.url;
|
||||
var untappd_url = response3.getBody().response.user.untappd_url;
|
||||
var twitter = response3.getBody().response.user.contact.twitter;
|
||||
var foursquare = response3.getBody().response.user.contact.foursquare;
|
||||
var facebook = response3.getBody().response.user.contact.facebook;
|
||||
var email_address = response3.getBody().response.user.settings.email_address;
|
||||
|
||||
firstName = first_name;
|
||||
lastName = last_name;
|
||||
userName = user_name;
|
||||
|
||||
console.log(process.env.DATABASE_URL);
|
||||
|
||||
pg.defaults.ssl = true;
|
||||
pg.connect(process.env.DATABASE_URL, function(err, client) {
|
||||
if (err) throw err;
|
||||
|
||||
var query = "INSERT INTO salesforce.untappduser__c (" +
|
||||
"uid__c," +
|
||||
"user_name__c," +
|
||||
"facebook__c," +
|
||||
"bio__c," +
|
||||
"location__c," +
|
||||
"email_address__c," +
|
||||
"user_avatar_hd__c," +
|
||||
"user_avatar__c," +
|
||||
"first_name__c," +
|
||||
"foursquare__c," +
|
||||
"untappd_url__c," +
|
||||
"last_name__c," +
|
||||
"twitter__c," +
|
||||
"url__c," +
|
||||
"user_cover_photo__c," +
|
||||
"id__c," +
|
||||
"name) " +
|
||||
"SELECT '" +
|
||||
uid + "','" +
|
||||
user_name + "','" +
|
||||
facebook + "','" +
|
||||
bio + "','" +
|
||||
location + "','" +
|
||||
email_address + "','" +
|
||||
user_avatar_hd + "','" +
|
||||
user_avatar + "','" +
|
||||
first_name + "','" +
|
||||
foursquare + "','" +
|
||||
untappd_url + "','" +
|
||||
last_name + "','" +
|
||||
twitter + "','" +
|
||||
url + "','" +
|
||||
user_cover_photo + "','" +
|
||||
id + "','" +
|
||||
id + "' WHERE NOT EXISTS ( SELECT id__c FROM salesforce.untappduser__c WHERE id__c = '" + id + "' )";
|
||||
|
||||
console.log(query);
|
||||
|
||||
client.query(query, function(err, result) {
|
||||
if (err) throw err;
|
||||
|
||||
console.log(result);
|
||||
});
|
||||
|
||||
var query = "INSERT INTO accesstokens (token, uid) VALUES ('" + accessToken + "','" + uid + "')";
|
||||
|
||||
client.query(query, function(err, result) {
|
||||
if (err) throw err;
|
||||
|
||||
console.log(result);
|
||||
});
|
||||
|
||||
response.redirect('/profile');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(app.get('port'), function() {
|
||||
console.log('Node app is running on port', app.get('port'));
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -1,45 +1,72 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<% include ../partials/header.ejs %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<% include ../partials/nav.ejs %>
|
||||
|
||||
<div class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>An Internet of Beers</h1>
|
||||
<p>Learn your estimated blood alcohol content (BAC) when you check into Untappd.</p>
|
||||
<a type="button" class="btn btn-lg btn-default" href="#"><span class="glyphicon glyphicon-flash"></span> Getting Started</a>
|
||||
<a type="button" class="btn btn-lg btn-primary" href="https://github.com/wadewegner/internet-of-beers"><span class="glyphicon glyphicon-download"></span> Source on GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
This app and service is based on the talk <a href="https://www.thatconference.com/sessions/session/10592" class="alert-link">An Internet of Beers</a> given at ThatConference on Tuesday, August 9, 2016.
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3><span class="glyphicon glyphicon-info-sign"></span> How it works</h3>
|
||||
<ul>
|
||||
<li>TBD</li>
|
||||
</ul>
|
||||
<head>
|
||||
<% include ../partials/header.ejs %>
|
||||
</head>
|
||||
<body>
|
||||
<% include ../partials/nav.ejs %>
|
||||
<div class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>
|
||||
An Internet of Beers
|
||||
</h1>
|
||||
<p>
|
||||
Learn your estimated blood alcohol content (BAC) when you check into Untappd.
|
||||
</p>
|
||||
<a class="btn btn-lg btn-default" href="#" type="button">
|
||||
<span class="glyphicon glyphicon-flash">
|
||||
</span>
|
||||
Getting Started
|
||||
</a>
|
||||
<a class="btn btn-lg btn-primary" href="https://github.com/wadewegner/internet-of-beers" type="button">
|
||||
<span class="glyphicon glyphicon-download">
|
||||
</span>
|
||||
Source on GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3><span class="glyphicon glyphicon-link"></span> Learn More</h3>
|
||||
<ul>
|
||||
<li><a href="https://www.wadewegner.com/home">www.wadewegner.com</a></li>
|
||||
</ul>
|
||||
<div class="container">
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
This app and service is based on the talk
|
||||
<a class="alert-link" href="https://www.thatconference.com/sessions/session/10592">
|
||||
An Internet of Beers
|
||||
</a>
|
||||
given at ThatConference on Tuesday, August 9, 2016.
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>
|
||||
<span class="glyphicon glyphicon-info-sign">
|
||||
</span>
|
||||
How it works
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
TBD
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>
|
||||
<span class="glyphicon glyphicon-link">
|
||||
</span>
|
||||
Learn More
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.wadewegner.com/home">
|
||||
www.wadewegner.com
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- row -->
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
Your actual blood alcohol concentration depends on a variety of additional factors, like genetic makeup, personal health, and recent food consumption. These results are rough estimates and for your personaly enjoyment only. Do not rely on these results to drive or work. Never drink and drive.
|
||||
</div>
|
||||
</hr>
|
||||
</div>
|
||||
</div> <!-- row -->
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
Your actual blood alcohol concentration depends on a variety of additional factors, like genetic makeup, personal health, and recent food consumption. These results are rough estimates and for your personaly enjoyment only. Do not rely on these results to drive or work. Never drink and drive.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<% include ../partials/header.ejs %>
|
||||
</head>
|
||||
<body>
|
||||
<% include ../partials/nav.ejs %>
|
||||
<div class="jumbotron text-center">
|
||||
<div class="container">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -4,14 +4,21 @@
|
|||
<li class="active">
|
||||
<a href="/"><span class="glyphicon glyphicon-home"></span> Home</a>
|
||||
</li>
|
||||
<% if (accessToken) { %>
|
||||
<li>
|
||||
<a href="#"><span class="glyphicon glyphicon-user"></span> Sign In</a>
|
||||
<a href="/profile"><span class="glyphicon glyphicon-book"></span> Profile</a>
|
||||
</li>
|
||||
<
|
||||
<% } %>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="navbar-right">
|
||||
<a href="http://www.wadewegner.com"><span class="glyphicon glyphicon-book"></span> Wade Wegner</a>
|
||||
<% if (accessToken) { %>
|
||||
<a href="/logout"><span class="glyphicon glyphicon-user"></span> Sign Out</a>
|
||||
<% } else { %>
|
||||
<a href="<%= signinUrl %>"><span class="glyphicon glyphicon-user"></span> Sign In</a>
|
||||
<% } %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
Загрузка…
Ссылка в новой задаче