Skip to content

Instantly share code, notes, and snippets.

@khaosdoctor
Created September 9, 2019 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khaosdoctor/33abcf8564393c4b24f465ed5f8de4d5 to your computer and use it in GitHub Desktop.
Save khaosdoctor/33abcf8564393c4b24f465ed5f8de4d5 to your computer and use it in GitHub Desktop.
Neo4J loading scripts
const axios = require('axios')
const n4j = require('neo4j-driver').v1
const qs = require('qs')
const driver = n4j.driver('bolt://localhost:7687', n4j.auth.basic('jsuser', '123456'))
const session = driver.session()
const user = process.env.twitterUser
const secret = process.env.twitterKey
const baseUrl = 'https://api.twitter.com/1.1'
async function getFollowers (handler) {
const token = await authenticate(user, secret)
return axios.get(`${baseUrl}/followers/list.json`, {
params: {
screen_name: handler,
cursor: -1,
count: 200,
skip_status: true,
include_user_entities: false
},
headers: {
Authorization: `Bearer ${token}`
}
}).then(({ data }) => data)
.catch(({ response }) => {
if (response && response.status === 401) {
console.log('Follower list is blocked')
return { users: [] }
}
throw response
})
}
async function getFollowing (handler) {
const token = await authenticate(user, secret)
return axios.get(`${baseUrl}/friends/list.json`, {
params: {
screen_name: handler,
cursor: -1,
count: 200,
skip_status: true,
include_user_entities: false
},
headers: {
Authorization: `Bearer ${token}`
}
}).then(({ data }) => data)
.catch(({ response }) => {
if (response && response.status === 401) {
console.log('Friends list is blocked')
return { users: [] }
}
throw response
})
}
async function getUserInfo (handler) {
const token = await authenticate(user, secret)
return axios.get(`${baseUrl}/users/show.json`, {
params: {
screen_name: handler,
include_entities: false
},
headers: {
Authorization: `Bearer ${token}`
}
}).then(({ data }) => data)
}
async function authenticate (user, pass) {
return axios.post('https://api.twitter.com/oauth2/token',
qs.stringify({ grant_type: 'client_credentials' }),
{
auth: {
username: user,
password: pass
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(({ data }) => data.access_token)
}
async function runQuery (query, params = {}) {
return session.run(query, params).then((result) => {
session.close()
return result
})
}
function delay (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function start () {
try {
const handler = process.argv[2]
console.log('Getting user info')
const handlerInfo = await getUserInfo(handler)
const me = {
handler: handlerInfo.screen_name,
cypher: `(:Person { id: ${handlerInfo.id}, name: '${handlerInfo.name}', handler: '${handlerInfo.screen_name}'})`
}
const userFriends = await session.run(`MATCH ${me.cypher}-[:FOLLOWS]->(b) RETURN count(b)`)
if (userFriends.records[0].get(0).low < 200) {
console.log('Getting user friends')
const { users: myFriends } = await getFollowing(me.handler)
const myFriendsMap = myFriends.map((user) => ({
handler: user.screen_name,
name: user.name,
cypher: `(:Person { id: ${user.id}, name: $name, handler: $handler})`
}))
for (let friend of myFriendsMap) {
console.log(`Processing user friend ${friend.handler}`)
await runQuery(`MERGE ${friend.cypher}`, { name: friend.name, handler: friend.handler })
await runQuery(`
MATCH (me:Person), (friend:Person)
WHERE me.handler = $me AND friend.handler = $friend
MERGE (me)-[:FOLLOWS]->(friend)`, { friend: friend.handler, me: me.handler })
}
}
console.log('Getting user followers')
const { users } = await getFollowers(handler)
const followers = users.map((user) => ({
handler: user.screen_name,
following: user.friends_count,
name: user.name,
cypher: `(:Person { id: ${user.id}, name: $name, handler: $handler})`
}))
await runQuery(`MERGE ${me.cypher}`)
for (let follower of followers) {
console.log(`Processing ${follower.handler}`)
await runQuery(`MERGE ${follower.cypher}`, { name: follower.name, handler: follower.handler })
await runQuery(`
MATCH (me:Person), (follower:Person)
WHERE me.handler = $me AND follower.handler = $follower
MERGE (follower)-[:FOLLOWS]->(me)`, { me: me.handler, follower: follower.handler })
// Check if already processed
const followerRelations = await session.run(`MATCH (n:Person {handler: '${follower.handler}'})-[:FOLLOWS]->(b) RETURN n.handler, count(b)`)
if (followerRelations.records[0].get(1).low > 1) {
console.log(`Already processed ${follower.handler}`);
continue
}
console.log('Getting friends')
const { users: followerFriends } = await getFollowing(follower.handler)
const following = followerFriends.map((user) => ({
handler: user.screen_name,
name: user.name,
cypher: `(:Person { id: ${user.id}, name: $name, handler: $handler})`
}))
for (let friend of following) {
console.log(`Processing follower ${follower.handler} friend ${friend.handler}`)
await runQuery(`MERGE ${friend.cypher}`, { name: friend.name, handler: friend.handler })
await runQuery(`
MATCH (follower:Person), (friend:Person)
WHERE follower.handler = $follower AND friend.handler = $friend
MERGE (follower)-[:FOLLOWS]->(friend)`, { friend: friend.handler, follower: follower.handler })
}
}
driver.close()
} catch (error) {
if (error.status && error.data) console.error(error.status, error.statusText, error.data.errors)
else console.log(error)
if (error.status === 429) {
console.log('Rate limiting exceeded, waiting...')
await delay(60000)
return start()
}
process.exit(1)
}
}
start().then(console.log).catch(console.error)
const axios = require('axios')
const n4j = require('neo4j-driver').v1
const qs = require('qs')
const driver = n4j.driver('bolt://localhost:7687', n4j.auth.basic('jsuser', '123456'))
const session = driver.session()
const user = process.env.twitterUser
const secret = process.env.twitterKey
const baseUrl = 'https://api.twitter.com/1.1'
async function getFollowing (handler) {
const token = await authenticate(user, secret)
return axios.get(`${baseUrl}/friends/list.json`, {
params: {
screen_name: handler,
cursor: -1,
count: 200,
skip_status: true,
include_user_entities: false
},
headers: {
Authorization: `Bearer ${token}`
}
}).then(({ data }) => data)
}
async function getUserInfo (handler) {
const token = await authenticate(user, secret)
return axios.get(`${baseUrl}/users/show.json`, {
params: {
screen_name: handler,
include_entities: false
},
headers: {
Authorization: `Bearer ${token}`
}
}).then(({ data }) => data)
}
async function authenticate (user, pass) {
return axios.post('https://api.twitter.com/oauth2/token',
qs.stringify({ grant_type: 'client_credentials' }),
{
auth: {
username: user,
password: pass
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(({ data }) => data.access_token)
}
async function runQuery (query, params = {}) {
return session.run(query, params).then((result) => {
session.close()
return result
})
}
(async function () {
try {
const handler = process.argv[2]
console.log('Getting user info')
const handlerInfo = await getUserInfo(handler)
const me = {
handler: handlerInfo.screen_name,
cypher: `(:Person { id: ${handlerInfo.id}, name: '${handlerInfo.name}', handler: '${handlerInfo.screen_name}'})`
}
console.log('Getting friends')
const { users: myFriends } = await getFollowing(me.handler)
const myFriendsMap = myFriends.map((user) => ({
handler: user.screen_name,
name: user.name,
cypher: `(:Person { id: ${user.id}, name: $name, handler: $handler})`
}))
for (let friend of myFriendsMap) {
console.log(`Processing person ${me.handler} friend ${friend.handler}`)
await runQuery(`MERGE ${friend.cypher}`, { name: friend.name, handler: friend.handler })
await runQuery(`
MATCH (me:Person), (friend:Person)
WHERE me.handler = $me AND friend.handler = $friend
MERGE (me)-[:FOLLOWS]->(friend)`, { friend: friend.handler, me: me.handler })
}
driver.close()
} catch (error) {
console.error(error.response)
console.error(error.response.data.errors)
process.exit(1)
}
})()
<html>
<head>
<title>DataViz</title>
<style type="text/css">
#viz {
width: 100%;
height: 100%;
}
</style>
<script src="https://rawgit.com/neo4j-contrib/neovis.js/master/dist/neovis.js"></script>
</head>
<script>
function draw() {
var config = {
container_id: "viz",
server_url: "bolt://localhost:7687",
server_user: "jsuser",
server_password: "123456",
labels: {
"Person": {
caption: "handler",
size: "pageRank",
community: "community"
}
},
arrows: true,
relationships: {
"FOLLOWS": {
caption: false,
thickness: "thick"
}
},
initial_cypher: "MATCH (p:Person)-[r:FOLLOWS]->(:Person) RETURN p, r"
}
var viz = new NeoVis.default(config);
viz.render();
}
</script>
<body onload="draw()">
<div id="viz"></div>
</body>
</html>
{
"name": "n4j",
"version": "1.0.0",
"description": "",
"main": "test.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.19.0",
"neo4j-driver": "^1.7.5",
"qs": "^6.7.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment