Instagram service update; other
This commit is contained in:
1 parent
6655a5fca8
commit
a756d6c5d3
15 files changed
+191
-38
No files matched your search
@@ -11,7 +11,9 @@
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-preset-stage-0": "^6.5.0",
|
||||
"co": "^4.6.0",
|
||||
"ejson": "^2.1.2",
|
||||
"instagram-node": "^0.5.8",
|
||||
"jsonwebtoken": "^5.7.0",
|
||||
"kerberos": "0.0.19",
|
||||
"koa": "^2.0.0-alpha.3",
|
||||
"koa-bodyparser": "^3.0.0",
|
||||
@@ -25,6 +27,7 @@
|
||||
"mz": "^2.3.1",
|
||||
"react": "^0.14.7",
|
||||
"react-dom": "^0.14.7",
|
||||
"react-router": "^2.0.1",
|
||||
"thunkify": "^2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export default class EndPoint{
|
||||
constructor() {
|
||||
|
||||
constructor(request) {
|
||||
this.request = request;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ import EndPoint from './EndPoint';
|
||||
|
||||
export default class Feed extends EndPoint {
|
||||
add(post) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
});
|
||||
return this.request.request('PUT', '/feed', post);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,33 @@
|
||||
import {stringify} from 'ejson';
|
||||
import {EventEmitter} from 'events';
|
||||
import request from 'request-promise';
|
||||
import Feed from './Feed';
|
||||
|
||||
export default class Service extends EventEmitter{
|
||||
constructor(secret) {
|
||||
super();
|
||||
let json = i => stringify(i);
|
||||
|
||||
export default class Service extends EventEmitter{
|
||||
constructor(host, service, secret) {
|
||||
super();
|
||||
this.version = 'v1';
|
||||
this.host = host;
|
||||
this.service = service;
|
||||
this.secret = secret;
|
||||
this.feed = new Feed(this.request);
|
||||
this.feed = new Feed(this);
|
||||
}
|
||||
|
||||
request(){
|
||||
|
||||
request(method, path, data) {
|
||||
let buildPath = path => `${this.host}/api/${this.version}${path}`;
|
||||
let options = {
|
||||
method: method,
|
||||
uri: buildPath(path),
|
||||
headers: {
|
||||
'Content-Type': 'application/ejson',
|
||||
'X-Service-Name': this.service,
|
||||
'X-Service-Token': this.secret
|
||||
},
|
||||
body: json(data)
|
||||
};
|
||||
|
||||
return request(options);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,25 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {render} from 'react-dom';
|
||||
import {Router, Route, browserHistory} from 'react-router';
|
||||
import App from './components/App';
|
||||
|
||||
ReactDOM.render(
|
||||
<App/>,
|
||||
document.querySelector('.app-container')
|
||||
render(
|
||||
(
|
||||
<Router history={browserHistory}>
|
||||
<Route path="/" component={App}>
|
||||
|
||||
</Route>
|
||||
</Router>
|
||||
),
|
||||
document.querySelector('.app-container')
|
||||
);
|
||||
|
||||
// <Route path="login" component={Login}/>
|
||||
// <Route path="logout" component={Logout}/>
|
||||
// <Route path="about" component={About}/>
|
||||
// <Route path="dashboard" component={Dashboard} onEnter={requireAuth}/>
|
||||
|
||||
// render(
|
||||
// <App/>,
|
||||
// document.querySelector('.app-container')
|
||||
// );
|
||||
@@ -1,7 +1,18 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class App extends React.Component{
|
||||
handleClick(event){
|
||||
|
||||
}
|
||||
|
||||
render(){
|
||||
return (<h1>Hi</h1>)
|
||||
return (
|
||||
<div>
|
||||
<h1>Панель управления инстаграмом художки</h1>
|
||||
<p>Чтобы управлять, вы должны быть <a href="https://instagram.com/hudozka">hudozka</a></p>
|
||||
|
||||
<a href="/auth" onClick={this.handleClick.bind(this)}>Войти</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,15 @@ export const clientId = privateData['clientId'];
|
||||
export const clientSecret = privateData['clientSecret'];
|
||||
export const redirectUri = privateData['redirectUri'];
|
||||
|
||||
export const serviceHost = isProduction ? 'http://localhost:1800' : 'http://localhost:8080';
|
||||
export const serviceName = 'instagram';
|
||||
export const serviceSecret = privateData['serviceSecret'];
|
||||
|
||||
export const jwtSecret = privateData['jwtSecret'];
|
||||
|
||||
export const sessionSecret = privateData['sessionSecret'];
|
||||
export const sessionExpirationTime = 60 * 60 * 24 * 2; // two days in seconds
|
||||
|
||||
export const authScope = [
|
||||
'basic',
|
||||
// 'public_content',
|
||||
@@ -27,9 +34,10 @@ export const authScope = [
|
||||
'likes'
|
||||
];
|
||||
|
||||
export const sessionSecret = privateData['sessionSecret'];
|
||||
// export const sessionExpirationTime = 60 * 60 * 24 * 2; // two days in seconds
|
||||
export const sessionExpirationTime = 10; // 10 seconds
|
||||
export const postType = 'instagram-2';
|
||||
export const fetchItemsPerUpdateLoop = 1;
|
||||
export const updateSubscriptionDelay = 1000 * 60 * 60; // one hour in milliseconds
|
||||
export const updateSubscriptionCallbackUrl = isProduction ? `https://art.shburg.org${pathPrefix}/callback/hudozka` : 'http://dev.tmshv.ru/callback/hudozka';
|
||||
|
||||
export const database = {
|
||||
host: 'localhost',
|
||||
@@ -40,4 +48,3 @@ export const database = {
|
||||
};
|
||||
|
||||
export const databaseUri = `mongodb://${database.host}:${database.port}/${database.db}`;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {collection} from './db';
|
||||
import {jwtSecret} from '../config';
|
||||
import {sign} from 'jsonwebtoken';
|
||||
|
||||
/**
|
||||
* {
|
||||
@@ -27,6 +29,7 @@ export async function authorizeUser(accessToken, user) {
|
||||
profile[i] = user[i];
|
||||
});
|
||||
profile.accessToken = accessToken;
|
||||
profile.jwtToken = await createToken(profile);
|
||||
|
||||
await users.update({_id: profile['_id']}, profile);
|
||||
return profile;
|
||||
@@ -34,3 +37,12 @@ export async function authorizeUser(accessToken, user) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function createToken(user){
|
||||
return new Promise((resolve, reject) => {
|
||||
sign(user, jwtSecret, {}, token => {
|
||||
if (!token) return reject();
|
||||
resolve(token);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2,9 +2,9 @@ import {collection} from './db';
|
||||
import {api} from '../instagram';
|
||||
import {postFromInstagramMedia} from '../models/post';
|
||||
import Service from '../api/Service';
|
||||
import {serviceSecret} from '../config';
|
||||
import {serviceHost, serviceName, serviceSecret, fetchItemsPerUpdateLoop as num} from '../config';
|
||||
|
||||
const service = new Service(serviceSecret);
|
||||
const service = new Service(serviceHost, serviceName, serviceSecret);
|
||||
|
||||
var instagramClient;
|
||||
|
||||
@@ -15,14 +15,63 @@ export default async function update(id, data) {
|
||||
let data = await instagram.user.mediaRecent(null, 1, updateTimestamp);
|
||||
let items = data.medias.map(postFromInstagramMedia);
|
||||
|
||||
for (let post of items) {
|
||||
await service.feed.add(post);
|
||||
}
|
||||
return await Promise.all(
|
||||
items.map(post => service.feed.add(post))
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearSubscriptions(callbackUrl) {
|
||||
const instagram = await client();
|
||||
return await instagram.subscriptions.removeAll();
|
||||
}
|
||||
|
||||
export async function updateSubscription(callbackUrl) {
|
||||
const instagram = await client();
|
||||
|
||||
let data = await instagram.subscriptions.list();
|
||||
let activeSubscriptions = data.result;
|
||||
|
||||
console.log(data);
|
||||
|
||||
let objectSubscriptions = activeSubscriptions.filter(i => i.object === 'user' && !i.object_id && i.callback_url === callbackUrl)
|
||||
|
||||
if (!objectSubscriptions.length) {
|
||||
// {
|
||||
// result: {
|
||||
// object: 'tag',
|
||||
// object_id: 'hello_lol',
|
||||
// aspect: 'media',
|
||||
// callback_url: 'http://dev.tmshv.ru/callback/hudozka',
|
||||
// type: 'subscription',
|
||||
// id: '22502218'
|
||||
// },
|
||||
// remaining: 4988,
|
||||
// limit: 5000
|
||||
// }
|
||||
|
||||
// {
|
||||
// result: {
|
||||
// object: 'user',
|
||||
// object_id: null,
|
||||
// aspect: 'media',
|
||||
// callback_url: 'http://dev.tmshv.ru/callback/hudozka',
|
||||
// type: 'subscription',
|
||||
// id: '22501989'
|
||||
// },
|
||||
// remaining: 4995,
|
||||
// limit: 5000
|
||||
// }
|
||||
await instagram.subscriptions.subscribeUser(callbackUrl);
|
||||
// let data = await instagram.subscriptions.subscribeTag('love', callbackUrl);
|
||||
console.log(data);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
async function client() {
|
||||
if (instagramClient) return instagramClient;
|
||||
|
||||
|
||||
@@ -47,7 +47,18 @@ export default class Subscription extends EndPoint {
|
||||
}
|
||||
|
||||
removeAll(){
|
||||
// ig.del_subscription({ all: true }, function(err, subscriptions, remaining, limit){});
|
||||
const m = this.method('del_subscription');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
m({all: true}, (error, result, remaining, limit) => {
|
||||
if (error) return reject(error);
|
||||
resolve({
|
||||
result: result,
|
||||
remaining: remaining,
|
||||
limit: limit
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
remove(id){
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {databaseUri, port} from './config'
|
||||
import {databaseUri, port, updateSubscriptionDelay, updateSubscriptionCallbackUrl} from './config'
|
||||
import {connect} from './core/db';
|
||||
import server from './server';
|
||||
import update from './core/update';
|
||||
import {updateSubscription, clearSubscriptions} from './core/update';
|
||||
|
||||
connect(databaseUri)
|
||||
.catch(error => {
|
||||
@@ -14,14 +15,30 @@ connect(databaseUri)
|
||||
.then(() => {
|
||||
console.log(`Start listening ${port}`);
|
||||
})
|
||||
.then(clearSubscriptions)
|
||||
.then(() => {
|
||||
return update('hudozka', {
|
||||
"changed_aspect": "media",
|
||||
"object": "tag",
|
||||
"object_id": "love",
|
||||
// "time": 1458675620,
|
||||
"time": 1458594000,
|
||||
"subscription_id": 22487204,
|
||||
"data": {}
|
||||
})
|
||||
let repeat = time => fn => setInterval(fn, time);
|
||||
|
||||
updateSubscription(updateSubscriptionCallbackUrl);
|
||||
repeat(updateSubscriptionDelay)(() => {
|
||||
updateSubscription(updateSubscriptionCallbackUrl);
|
||||
});
|
||||
});
|
||||
// .then(() => {
|
||||
// return update('hudozka', {
|
||||
// "changed_aspect": "media",
|
||||
// "object": "tag",
|
||||
// "object_id": "love",
|
||||
// // "time": 1458675620,
|
||||
// "time": 1458594000,
|
||||
// "subscription_id": 22487204,
|
||||
// "data": {}
|
||||
// })
|
||||
// .catch(e => {
|
||||
// console.log(e);
|
||||
// })
|
||||
// .then(result => {
|
||||
// console.log('update done');
|
||||
// console.log(result);
|
||||
// });
|
||||
// })
|
||||
@@ -1,3 +1,5 @@
|
||||
import {postType} from '../config';
|
||||
|
||||
let date = i => new Date(parseInt(i) * 1000);
|
||||
|
||||
/**
|
||||
@@ -61,7 +63,7 @@ let date = i => new Date(parseInt(i) * 1000);
|
||||
*/
|
||||
export const postFromInstagramMedia = i => ({
|
||||
data: i,
|
||||
type: 'instagram',
|
||||
type: postType,
|
||||
date: date(i['created_time']),
|
||||
id: i.id
|
||||
});
|
||||
@@ -30,6 +30,7 @@ export function authCallback() {
|
||||
var accessToken = client.access_token;
|
||||
}
|
||||
|
||||
if(user) ctx.cookies.set('jwt', user.jwtToken);
|
||||
ctx.status = user ? 200 : 401;
|
||||
ctx.session.user = user;
|
||||
ctx.session.accessToken = accessToken;
|
||||
|
||||
@@ -3,6 +3,8 @@ import update from '../core/update';
|
||||
|
||||
export function callbackGet() {
|
||||
return get('/callback/:id', async (ctx, id) => {
|
||||
console.log('challenge', id);
|
||||
|
||||
if(ctx.query['hub.mode'] == 'subscribe'){
|
||||
ctx.body = ctx.query['hub.challenge'];
|
||||
}else{
|
||||
@@ -14,8 +16,12 @@ export function callbackGet() {
|
||||
export function callbackPost() {
|
||||
return post('/callback/:id', async (ctx, id) => {
|
||||
let body = ctx.request.body;
|
||||
console.log(id, body);
|
||||
update(id, body);
|
||||
|
||||
|
||||
ctx.status = 200;
|
||||
ctx.body = '';
|
||||
|
||||
//body example
|
||||
// {
|
||||
// "changed_aspect": "media",
|
||||
|
||||
@@ -5,6 +5,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
|
||||
module.exports = {
|
||||
entry: './src/app.js',
|
||||
watch: true,
|
||||
//resolve: {
|
||||
// modulesDirectories: [
|
||||
// './node_modules'
|
||||
|
||||
Reference in new issue
Block a user