base instagram supporting;

This commit is contained in:
tmshv committed 2015-03-14 04:23:43 +03:00
1 parent 17923e3730
commit 1ebfcea16b
14 files changed
+528 -103

No files matched your search

+2
View File
@@ -5,8 +5,10 @@
var config = require("../config");
var db = require("../core/db");
var server = require("../server");
var instagram = require("../instagram");
db.init(config.db.uri)
.then(instagram)
.then(function () {
server(config.port);
});
+28
View File
@@ -0,0 +1,28 @@
/**
* Created by tmshv on 06/11/14.
*/
angular.module("hudozhka.instagram", [])
.controller("InstagramController", function($scope, $http, $window){
//$scope.auth = function() {
// $http.get("/instagram/auth/url")
// .success(function (data) {
// $window.location.href = data.url;
// });
//};
$http.get("/instagram/user")
.error(function() {
})
.success(function (user) {
$scope.user = user;
});
$scope.invite = function() {
$http.get("/instagram/invite")
.success(function (data) {
$scope.inviteCode = data.code;
});
};
});
+1 -1
View File
@@ -23,7 +23,7 @@ var config = {
uri: "mongodb://localhost:27017/hudozka"
},
tags: ["shlb_hudozka"]
tag: "shlb_hudozka"
};
module.exports = Object.keys(privateData)
-59
View File
@@ -1,59 +0,0 @@
/**
* Created by tmshv on 22/11/14.
*/
var config = require("../config");
var instagram = require("instagram-node");
var auth_clients = {};
module.exports = {
client: function(code){
if(code && code in auth_clients) {
return auth_clients[code].client;
}else{
return createClient();
}
},
user: function(code){
if(code in auth_clients) {
return auth_clients[code].user;
}else{
return null;
}
},
authorize: function(code){
return new Promise(function(resolve, reject){
var api = createClient();
api.authorize_user(code, config.instagram.redirect_uri, function (err, result) {
if (err) return reject(err);
else {
var user = result.user;
var token = result.access_token;
var client = createClient(token);
auth_clients[code] = {
client: client,
user: user
};
resolve(client);
}
});
});
}
};
function createClient(token) {
var client = instagram.instagram({}, {});
if (token) {
client.use({access_token: token});
} else {
client.use({
client_id: config.instagram.client_id,
client_secret: config.instagram.client_secret
});
}
return client;
}
+7
View File
@@ -50,6 +50,13 @@ gulp.task("compile", function(){
}))
.pipe(uglify())
.pipe(gulp.dest("public"));
gulp.src("client/instagram.js")
.pipe(browserify({
transform: [annotate]
}))
.pipe(uglify())
.pipe(gulp.dest("public"));
});
gulp.task("imagemin", function(){
+39
View File
@@ -0,0 +1,39 @@
/**
* Created by tmshv on 12/03/15.
*/
var db = require("../core/db");
var co = require("co");
var instagram = require("./instagram");
var publish = require("./publish");
var config = require("../config");
module.exports = function () {
return loadUsers()
.then(publish)
.then(updateSubscription)
};
function loadUsers() {
return new Promise(function (resolve, reject) {
db.c("users").find({provider: "instagram"})
.toArray()
.then(function (users) {
users.forEach(function (u) {
return instagram.initUser(u);
});
return users;
})
.then(resolve);
});
}
function updateSubscription() {
var tags = [config["tag"]];
return tags.map(function (tag) {
var cb = config.instagram["tag_callback"];
return co(function *() {
return yield instagram.api.subscribe(tag, cb);
})
});
}
+172
View File
@@ -0,0 +1,172 @@
/**
* Created by tmshv on 22/11/14.
*/
var EventEmitter = require("events").EventEmitter;
var thunkify = require("thunkify");
var config = require("../config");
var db = require("../core/db");
var instagram = require("instagram-node");
function Instagram(options) {
this.client_id = options.client_id;
this.client_secret = options.client_secret;
this.redirect_uri = options.redirect_uri;
this.default_user = options.default_user;
this.clients = {};
this.users = {};
EventEmitter.call(this);
}
Instagram.prototype = Object.create(EventEmitter.prototype);
Instagram.prototype.authorizationURL = function (scope, state) {
var params = {};
params.scope = scope || ["basic"];
if (state) {
params.state = state;
}
var client = createClient();
return client["get_authorization_url"](this.redirect_uri, params);
};
Instagram.prototype.addClient = function *(code, params) {
var token = params.access_token;
var item = params.user;
item.code = code;
item.access_token = token;
item.provider = "instagram";
yield db.c("users").update({provider: "instagram", id: params.user.id}, item, {upsert: true});
return this.initUser(item);
};
Instagram.prototype.initUser = function (user) {
var token = user.access_token;
this.clients[user.code] = createClient(token);
this.users[user.code] = user;
return this;
};
Instagram.prototype.getUsers = function () {
var users = this.users;
return Object.keys(users)
.map(function (code) {
return users[code];
});
};
Instagram.prototype.update = function (body) {
this.emit("update", body);
};
Instagram.prototype.client = function (code) {
if (code && code in this.clients) {
return this.clients[code];
} else {
return createClient();
}
};
Instagram.prototype.user = function (code) {
if (code && code in this.users) {
return this.users[code];
} else {
return null;
}
};
Instagram.prototype.authorize = function *(code) {
var api = createClient();
var authorize = thunkify(api["authorize_user"]);
var result = yield authorize(code, this.redirect_uri);
if (result) {
yield this.addClient(code, result);
}
return result;
};
Instagram.prototype.getUser = function *() {
if (this.default_user) {
var du = yield db.c("users").findOne({username: this.default_user});
if (du) {
return du;
}
}
return yield db.c("users").findOne({provider: "instagram"});
};
Instagram.prototype.getUsers = function *() {
return yield db.c("users").find({provider: "instagram"}).toArray();
};
Instagram.prototype.api = {
subscriptions: function *() {
var ig = createClient();
var subs = thunkify(ig["subscriptions"]);
try {
var s = yield subs();
return s[0];
} catch (error) {
return null;
}
},
subscribe: function *(tag, callbackURL) {
var ig = createClient();
var sub = thunkify(ig["add_tag_subscription"]);
try {
var s = yield sub(tag, callbackURL);
return s[0];
} catch (error) {
return null;
}
},
unsubscribe: function *(id) {
var ig = createClient();
var sub = thunkify(ig["del_subscription"]);
try {
var s = yield sub({id: id});
return s[0];
} catch (error) {
return null;
}
},
tagMediaRecent: function *(client, tag, count) {
var tag_media_recent = thunkify(client["tag_media_recent"]);
try{
var result = yield tag_media_recent(tag, {count: count});
return {
medias: result[0],
pagination: result[1],
remaining: result[2],
limit: result[3]
}
}catch(error){
return null;
}
}
};
module.exports = new Instagram(config.instagram);
function createClient(token) {
var client = instagram.instagram({}, {});
if (token) {
client.use({access_token: token});
} else {
client.use({
client_id: config.instagram.client_id,
client_secret: config.instagram.client_secret
});
}
return client;
}
+70
View File
@@ -0,0 +1,70 @@
/**
* Created by tmshv on 10/03/15.
*/
var co = require("co");
var instagram = require("./instagram");
var config = require("../config");
var db = require("../core/db");
module.exports = function () {
return co(function *() {
instagram.on("update", function (data) {
var tag = config["tag"];
co(function *() {
var user = yield instagram.getUser();
if (user) {
var client = instagram.client(user.code);
var permitted_users = yield instagram.getUsers();
permitted_users = permitted_users.map(function (user) {
return user["username"];
});
var medias = yield fbt(client, tag);
medias = medias.filter(function (gram) {
return permitted_users.indexOf(gram.data.author) > -1;
});
return medias;
}
})
.then(function (posts) {
return posts.map(function (g) {
console.log(g);
return db.c("posts").update({"data.id": g.data.id}, g, {upsert: true})
.catch(function (error) {
console.log(error);
});
});
})
.catch(function (error) {
console.log(error);
});
});
});
};
function *fbt(client, tag) {
var param = yield instagram.api.tagMediaRecent(client, tag, 10);
return param.medias.map(toInstagram);
}
function toInstagram(gram) {
var post = {};
post.body = gram.caption.text;
post.type = "instagram";
post.tags = gram.tags;
post.date = new Date(parseInt(gram["created_time"]) * 1000);
post.data = {
id: gram.id,
author: gram.user["username"],
image: gram.images,
url: gram.link
};
return post;
}
+162
View File
@@ -0,0 +1,162 @@
/**
* Created by tmshv on 22/11/14.
*/
var path = require("path");
var route = require("koa-route");
var router = require("../routes");
var instagram = require("../instagram/instagram");
module.exports = function (app) {
app.use(function *(next) {
var code = this.cookies.get("instagram_code");
if (code) {
var client = instagram.client(code);
var user = instagram.user(code);
if (client && user) {
this.instagram = {
client: client,
user: user
}
}
}
yield* next;
});
app.use(
route.get("/instagram", function *() {
var invite = this.cookies.get("invite_code") || this.query.code;
if(!this.instagram) {
if(invite == undefined){
this.body = "invite required";
this.status = 401;
}else if(invite == "LOL"){
this.cookies.set("invite_code", invite, {expires: expire()});
//todo: invalidate invite
yield router.index(
path.join(__dirname, "../templates/instagram.html")
);
}else{
this.body = "invite ist correct";
this.status = 401;
}
}else{
yield router.index(
path.join(__dirname, "../templates/instagram.html")
);
}
})
);
app.use(
route.get("/instagram/auth", function *() {
var invite = this.cookies.get("invite_code");
if(invite) {
var url = instagram.authorizationURL(null, "/instagram");
this.redirect(url);
}else{
this.status = 401;
this.body = "invite required";
}
})
);
app.use(
route.get("/instagram/user", function *() {
var code = this.cookies.get("instagram_code");
var user = instagram.user(code);
if(user) {
this.body = user;
}else{
this.status = 404;
}
})
);
app.use(
route.get("/instagram/auth/callback", function *() {
var state = this.query.state || "/";
var code = this.query.code;
var client = yield instagram.authorize(code);
if (client) {
this.cookies.set("instagram_code", code, {expires: expire()});
this.redirect(state);
} else {
this.status = 401;
this.redirect(state);
}
})
);
app.use(route.get("/instagram/subscription/list", function *() {
var result = yield instagram.api.subscriptions();
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/subscription/add", function *() {
var tag = this.query.tag;
var cu = this.query.url;
var result = yield instagram.api.subscribe(tag, cu);
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/subscription/delete", function *() {
var id = this.query.id;
var result = yield instagram.api.unsubscribe(id);
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/callback/:rnd", function *() {
if(this.query["hub.mode"] == "subscribe"){
this.body = this.query["hub.challenge"];
}else{
this.status = 400;
}
}));
app.use(route.post("/instagram/callback/:rnd", function *(rnd) {
var sign = this.header["x-hub-signature"];
//console.log(this.headers);
var body = this.request.body;
//var hmac = crypto.createHmac("sha1", instagram.client_secret);
//hmac.update(body);
//var shasum = hmac.digest("hex");
//console.log("X-Hub-Signature", sign);
//console.log("Hmac", shasum);
//console.log();
//if(shasum.digest("hex") == sign) {
instagram.update(body);
//}
this.body = "";
}));
};
function expire(time){
return time || new Date(Date.now() + 1000 * 60 * 60 * 24 * 7);
}
+2 -1
View File
@@ -14,9 +14,10 @@
"author": "Roman Timashev",
"license": "ISC",
"dependencies": {
"co": "^4.4.0",
"instagram-node": "^0.5.1",
"koa": "^0.18.0",
"koa-bodyparser": "^1.4.0",
"koa-bodyparser": "^1.4.1",
"koa-conditional-get": "^1.0.2",
"koa-etag": "^2.0.0",
"koa-helmet": "0.0.3",
-42
View File
@@ -1,42 +0,0 @@
/**
* Created by tmshv on 22/11/14.
*/
var Router = require("express").Router;
var instagram = require("../core/instagram");
module.exports = function (app) {
var router;
router = new Router();
router.route("/auth/instagram/callback")
.get(function (req, res) {
var code = req.query.code;
instagram.authorize(code)
.catch(function(error){
console.log(error.body);
res.status(500).send('');
})
.then(function (client) {
res.cookie("instagram_code", code);
res.redirect("/");
});
});
app.use(router);
//http://your-callback.com/url/?hub.mode=subscribe&hub.challenge=15f7d1a91c1f40f8a748fd134752feb3&hub.verify_token=myVerifyToken
router = new Router();
router.route("/instagram/tag/:tag")
.get(function (req, res) {
var hub_challenge = req.query["hub.challenge"];
//var hub_verify_token = req.query["hub.verify_token"];
console.log("real time get", req.param("tag"), hub_challenge);
res.send(hub_challenge);
})
.post(function (req, res) {
console.log("real time tag", req.param("tag"));
console.log(req.body);
res.send("");
});
app.use(router);
};
+4
View File
@@ -8,6 +8,7 @@ var conditional = require("koa-conditional-get");
var etag = require("koa-etag");
var prerender = require("koa-prerender");
var helmet = require('koa-helmet');
var bodyParser = require("koa-bodyparser");
var config = require("./config");
var routes = require("./routes");
@@ -15,6 +16,7 @@ var routes = require("./routes");
var app = koa();
app.proxy = true;
app.use(bodyParser());
app.use(logger());
app.use(conditional());
app.use(etag());
@@ -55,6 +57,8 @@ require("./routes/news")(app);
require("./routes/404")(app);
require("./instagram/router")(app);
if (process.env["NODE_ENV"] === "development") {
app.use(route.get("/debug", function *() {
var out = {};
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html ng-app="hudozhka.instagram">
<head>
<base href="/">
<meta name="fragment" content="!">
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />
<title ng-bind="title">ДШХ Шлиссельбурга</title>
<link rel="stylesheet" href="/style.css">
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/instagram.js"></script>
</head>
<body ng-controller="InstagramController">
<div class="controls">
<a href="/instagram/auth" ng-show="!user">Instagram</a>
<a href="//instagram.com/{{user.username}}" ng-show="user">{{user.full_name}}</a>
<button ng-click="invite()">Invite</button>
{{inviteCode}}
</div>
</body>
</html>
+17
View File
@@ -0,0 +1,17 @@
/**
* Created by tmshv on 13/03/15.
*/
var co = require("co");
var should = require("should");
var instagram = require("../instagram/instagram");
var db = require("../core/db");
var config = require("../config");
describe("Instagram", function () {
describe("getUser()", function () {
it("should return default user if exists", function () {
});
});
});