Skip to content

Commit

Permalink
Merge pull request #9 from eastmaels/master
Browse files Browse the repository at this point in the history
Use MongoDB to get overseer info
  • Loading branch information
surpassinggoogle committed Oct 28, 2018
2 parents db286fb + 9df2c6d commit 39dc025
Show file tree
Hide file tree
Showing 5 changed files with 357 additions and 295 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Steem Bot To Enable And Grow Ulogs.org Communities & Ulog-subtags.

Current Version: v0.0.1
Current Version: v1.0.0

License: MIT

Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "ulog-communities",
"version": "0.0.1",
"version": "1.0.0",
"engines": {
"node": ">=7.10.1",
"npm": "=5.3.0"
"npm": ">=5.3.0"
},
"main": "dist/index.js",
"license": "MIT",
Expand All @@ -15,6 +15,8 @@
"dsteem": "^0.8.7",
"event-stream": "^3.3.4",
"jest": "^22.4.3",
"mongodb": "^3.1.8",
"mongoose": "^5.3.7",
"nodemon": "^1.17.1",
"steem": "^0.7.1",
"striptags": "^3.1.1"
Expand All @@ -35,6 +37,8 @@
"@types/dotenv-safe": "^5.0.0",
"@types/es6-promise": "^3.3.0",
"@types/jest": "^22.2.3",
"@types/mongodb": "^3.1.13",
"@types/mongoose": "^5.2.20",
"@types/node": "^9.6.6",
"typescript": "^2.8.3"
}
Expand Down
312 changes: 173 additions & 139 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import * as es from 'event-stream'
import * as util from 'util'
import * as striptags from 'striptags'

const mongoose = require('mongoose')
require('./models/Overseer');
const Overseer = mongoose.model('Overseer');

// file
import { arrayContains, die, getVoteWeight } from './functions'
import { OVERSEERS, FAIL_COMMENT, SUCCESS_COMMENT } from './config'
Expand Down Expand Up @@ -40,8 +44,10 @@ let ADD_ULOG_TEST_ACCOUNTS: boolean
= (process.env.ADD_ULOG_TEST_ACCOUNTS === "true")
// @ts-ignore
let DEFAULT_VOTE_WEIGHT: number = parseInt(process.env.DEFAULT_VOTE_WEIGHT)
// @ts-ignore
let DATABASE: string = process.env.DATABASE
if (BOT === '' || ACCOUNT_KEY === '' || BOT_COMMAND === '' || MAIN_TAG === ''
|| ULOGS_APP === '' || DEFAULT_VOTE_WEIGHT === 0) die('Check .env file')
|| ULOGS_APP === '' || DEFAULT_VOTE_WEIGHT === 0 || DATABASE === '') die('Check .env file')

// Steem Init

Expand All @@ -53,145 +59,173 @@ console.log('Operation started')
console.log('Is simulation?', SIMULATE_ONLY)
console.log('Bot command:', BOT_COMMAND)

getCertifiedUloggers(client).then(res => {
let certifiedUloggers: string[] = []
res.forEach((obj: any) => certifiedUloggers.push(obj.following))
if(ADD_ULOG_TEST_ACCOUNTS) {
console.log('adding uloggers for testing')
certifiedUloggers.push('eastmael', 'east.autovote')
}

// Stream Steem Blockchain
stream.on('data', async operation => {
// Look for comment type of transaction
if (operation.op[0] == 'comment') {
let txData = operation.op[1]

// check if reply (return if post)
if (txData.parent_author === '') return

// get post data
let summoner: string = txData.author
let permlink: string = txData.permlink
let post = await getPostData(summoner, permlink).catch(() =>
console.error("Couldn't fetch post data with SteemJS")
)

let splitBody = striptags(post.body.toLowerCase().replace("<br/>", " ")).split(" ")
if (summoner === "eastmael") console.log('split body arry', splitBody)
// check if summoned by specific command
if (splitBody.indexOf(BOT_COMMAND.toLowerCase()) < 0) return

// #################### CHECKS #######################
// 2) check if certified ulogger
let isCertifiedUlogger = arrayContains(summoner, certifiedUloggers)

// 2b) check summon is a direct reply under the post
let isReplyToPost = (post.root_author === post.parent_author
&& post.root_permlink === post.parent_permlink)
console.log('is reply directly under post:', isReplyToPost)

// get root post (to get all tags)
let rootPost = await getPostData(post.root_author, post.root_permlink)
.catch(() =>
console.error("Couldn't fetch ROOT post data with SteemJS")
)

// 3) posted using 'ulogs' app
let app: string = ''
try {
app = JSON.parse(rootPost.json_metadata).app
} catch (e) {
console.error('Invalid app')
return
}
console.log('posted using ulogs: ', app.indexOf(ULOGS_APP) >= 0)
let isUlogApp = app.indexOf(ULOGS_APP) >= 0

// 4) First tag is 'ulogs'
let rootTags: string[]
try {
rootTags = JSON.parse(rootPost.json_metadata).tags
} catch (e) {
console.error('Invalid root tags')
return
}
console.log('first tag is main tag: ', rootTags[0] === MAIN_TAG)
let isFirstTagUlog = (rootTags[0] === MAIN_TAG)

// 5) Summoner is overseer of sub-tag
// TODO: Change to map
let overseerInfo = OVERSEERS[summoner]
let subtags = overseerInfo.tags
// 7a) Is an overseer?
console.log('summoner is an overseer? ', subtags);
let isOverseer = (subtags && subtags.length > 0)

// 7b) Is an overseer of sub-tag?
console.log('summoner is an overseer of sub-tag? ',
arrayContains(rootTags[1], subtags));
let isSubtagOverseer = (isOverseer && arrayContains(rootTags[1], subtags))

// 8) is valid param weight
let isValidWeight = (isNaN(parseInt(splitBody[1])) === false)
console.log('is integer vote weight: ', isValidWeight)

// 9) is already upvoted
let isAlreadyVoted = rootPost.active_votes.some((r:any) => {
return BOT === r.voter
})
console.log('is already voted: ', isAlreadyVoted)

// 10) is past curation window
let isPastCurationWindow = true
console.log('is past curation window: ', isPastCurationWindow)

let isSuccess = isCertifiedUlogger && isUlogApp && isFirstTagUlog && isOverseer
&& isSubtagOverseer && isReplyToPost && isValidWeight && !isAlreadyVoted && isPastCurationWindow
let commentTemplate: string = ''
if (isSuccess) {
commentTemplate = SUCCESS_COMMENT(summoner, BOT)
} else {
commentTemplate = FAIL_COMMENT(
summoner,
BOT,
rootTags[1],
{
isCertifiedUlogger,
isUlogApp,
isFirstTagUlog,
isSubtagOverseer,
isReplyToPost,
isValidWeight,
isAlreadyVoted,
isPastCurationWindow,
}
)
// Initialize mongoose then connect
mongoose.connect(process.env.DATABASE, { useNewUrlParser: true })
mongoose.Promise = global.Promise
mongoose.connection
.on('connected', () => {
console.log('Mongoose connection open...');

getCertifiedUloggers(client).then(res => {
let certifiedUloggers: string[] = []
res.forEach((obj: any) => certifiedUloggers.push(obj.following))
if(ADD_ULOG_TEST_ACCOUNTS) {
console.log('adding uloggers for testing')
certifiedUloggers.push('eastmael', 'east.autovote')
}

if (SIMULATE_ONLY) {
console.log('simulation only...')
console.log(commentTemplate)
} else {
console.log('sending comment...')
// Send Comment
comment(client, summoner, permlink, key, BOT, commentTemplate)
.then(() => {

if(isSuccess) {
let voteweight = getVoteWeight(parseInt(splitBody[1]), overseerInfo.maxweight)
console.log('voting with weight...', voteweight)
// Vote post
vote(client, BOT, post.root_author, post.root_permlink,
voteweight, key).catch(() =>
console.error("Couldn't vote on the violated post")
// Stream Steem Blockchain
stream.on('data', async operation => {
// Look for comment type of transaction
if (operation.op[0] == 'comment') {
let txData = operation.op[1]

// check if reply (return if post)
if (txData.parent_author === '') return

// get post data
let summoner: string = txData.author
let permlink: string = txData.permlink
let post = await getPostData(summoner, permlink).catch(() =>
console.error("Couldn't fetch post data with SteemJS")
)

let splitBody = striptags(post.body.toLowerCase().replace("<br/>", " ")).split(" ")
if (summoner === "eastmael") console.log('split body arry', splitBody)
// check if summoned by specific command
if (splitBody.indexOf(BOT_COMMAND.toLowerCase()) < 0) return

// #################### CHECKS #######################
// 2) check if certified ulogger
let isCertifiedUlogger = arrayContains(summoner, certifiedUloggers)

// 2b) check summon is a direct reply under the post
let isReplyToPost = (post.root_author === post.parent_author
&& post.root_permlink === post.parent_permlink)
console.log('is reply directly under post:', isReplyToPost)

// get root post (to get all tags)
let rootPost = await getPostData(post.root_author, post.root_permlink)
.catch(() =>
console.error("Couldn't fetch ROOT post data with SteemJS")
)

// 3) posted using 'ulogs' app
let app: string = ''
try {
app = JSON.parse(rootPost.json_metadata).app
} catch (e) {
console.error('Invalid app')
return
}
}).catch(() => {
console.error("Couldn't comment on the violated post")
})
}
}
return
})
})
console.log('posted using ulogs: ', app.indexOf(ULOGS_APP) >= 0)
let isUlogApp = app.indexOf(ULOGS_APP) >= 0

// 4) First tag is 'ulogs'
let rootTags: string[]
try {
rootTags = JSON.parse(rootPost.json_metadata).tags
} catch (e) {
console.error('Invalid root tags')
return
}
console.log('first tag is main tag: ', rootTags[0] === MAIN_TAG)
let isFirstTagUlog = (rootTags[0] === MAIN_TAG)

// Query overseer info
Overseer.find()
.then((result: any) => {

let overseersMap: {[key:string]: any} = {}
result.forEach((overseer: any) => {
overseersMap[overseer.name] = { tags: overseer.tags, maxweight: overseer.maxweight }
})
console.log('overseers map size:', Object.keys(overseersMap).length)

// 5) Summoner is overseer of sub-tag
let overseerInfo = overseersMap[summoner]
console.log('overseer info:', overseerInfo)

let subtags = overseerInfo.tags
// 7a) Is an overseer?
console.log('summoner is an overseer? ', subtags);
let isOverseer = (subtags && subtags.length > 0)

// 7b) Is an overseer of sub-tag?
console.log('summoner is an overseer of sub-tag? ',
arrayContains(rootTags[1], subtags));
let isSubtagOverseer = (isOverseer && arrayContains(rootTags[1], subtags))

// 8) is valid param weight
let isValidWeight = (isNaN(parseInt(splitBody[1])) === false)
console.log('is integer vote weight: ', isValidWeight)

// 9) is already upvoted
let isAlreadyVoted = rootPost.active_votes.some((r:any) => {
return BOT === r.voter
})
console.log('is already voted: ', isAlreadyVoted)

// 10) is past curation window
let isPastCurationWindow = true
console.log('is past curation window: ', isPastCurationWindow)

let isSuccess = isCertifiedUlogger && isUlogApp && isFirstTagUlog && isOverseer
&& isSubtagOverseer && isReplyToPost && isValidWeight && !isAlreadyVoted && isPastCurationWindow
let commentTemplate: string = ''
if (isSuccess) {
commentTemplate = SUCCESS_COMMENT(summoner, BOT)
} else {
commentTemplate = FAIL_COMMENT(
summoner,
BOT,
rootTags[1],
{
isCertifiedUlogger,
isUlogApp,
isFirstTagUlog,
isSubtagOverseer,
isReplyToPost,
isValidWeight,
isAlreadyVoted,
isPastCurationWindow,
}
)
}

if (SIMULATE_ONLY) {
console.log('simulation only...')
console.log(commentTemplate)
} else {
console.log('sending comment...')
// Send Comment
comment(client, summoner, permlink, key, BOT, commentTemplate)
.then(() => {

if(isSuccess) {
let voteweight = getVoteWeight(parseInt(splitBody[1]), overseerInfo.maxweight)
console.log('voting with weight...', voteweight)
// Vote post
vote(client, BOT, post.root_author, post.root_permlink,
voteweight, key).catch(() =>
console.error("Couldn't vote on the violated post")
)
}
}).catch(() => {
console.error("Couldn't comment on the violated post")
})
}
})
.catch(() => { console.log('Something went wrong in fetching overseers.') }) // end: Overseer.find()
} // end: if (operation.op[0] == 'comment') {}
return

}) // end: stream.on()

}) // end: getCertifiedUloggers()

}) // end: mongo.connection on:connected
.on('error', (err: any) => {
console.log(`Connection error: ${err.message}`);
}) // end: mongo.connection on:error

15 changes: 15 additions & 0 deletions src/models/Overseer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Document, Schema, Model, model} from "mongoose"

export interface IOverseerModel extends Document {
name?: string
tags?: string[]
maxweight?: number
}

export var OverseerSchema: Schema = new Schema({
name: String,
tags: [],
maxweight: Number,
})

export const Overseer: Model<IOverseerModel> = model<IOverseerModel>("Overseer", OverseerSchema)

0 comments on commit 39dc025

Please sign in to comment.