lbry-wunderbot/bot/modules/claimbot.js
YULIUS KURNIAWAN KRISTIANTO 1770f147cf Update claimbot.js (#214)
2018-08-22 19:13:34 +02:00

251 lines
7.7 KiB
JavaScript

"use strict";
let lbry;
let mongo;
let discordBot;
let moment = require("moment");
let request = require("request");
let sleep = require("sleep");
let config = require("config");
let channels = config.get("claimbot").channels;
const Discord = require("discord.js");
const rp = require("request-promise");
const jsonfile = require("jsonfile");
const path = require("path");
const fs = require("fs");
const appRoot = require("app-root-path");
const fileExists = require("file-exists");
module.exports = {
init: init
};
function init(discordBot_) {
if (lbry) {
throw new Error("init was already called once");
}
discordBot = discordBot_;
const MongoClient = require("mongodb").MongoClient;
MongoClient.connect(config.get("mongodb").url, function(err, db) {
if (err) {
throw err;
}
mongo = db;
console.log("Activating claimbot ");
discordBot.channels.get(channels[0]).send("activating claimbot");
// Check that our syncState file exist.
fileExists(path.join(appRoot.path, "syncState.json"), (err, exists) => {
if (err) {
throw err;
}
if (!exists) {
fs.writeFileSync(path.join(appRoot.path, "syncState.json"), "{}");
}
});
setInterval(function() {
announceClaims();
}, 60 * 1000);
announceClaims();
});
}
async function announceClaims() {
// get last block form the explorer API.
let lastBlockHeight = JSON.parse(
await rp("https://explorer.lbry.io/api/v1/status")
).status.height;
// get the latest claims from chainquery since last sync
let syncState = await getJSON(path.join(appRoot.path, "syncState.json")); // get our persisted state
if (!syncState.LastSyncTime) {
syncState.LastSyncTime = new Date()
.toISOString()
.slice(0, 19)
.replace("T", " ");
}
let claimsSince = JSON.parse(await getClaimsSince(syncState.LastSyncTime))
.data;
// filter out the claims that we should add to discord
let claims = [];
for (let claim of claimsSince) {
claim.value = JSON.parse(claim.value);
if (claim.value.Claim && claim.value.Claim.stream) {
claim.metadata = claim.value.Claim.stream.metadata;
} else {
claim.metadata = null;
}
if (claim.bid_state !== "Spent" || claim.bid_state !== "Expired") {
claims.push(claim);
}
}
for (let claim of claims) {
console.log(claim);
}
// send each claim to discord.
for (let claim of claims) {
console.log(claim);
if (claim.metadata) {
// If its a claim, make a claimEmbed
let claimEmbed = new Discord.RichEmbed()
.setAuthor(
claim.channel
? `New claim from ${claim.channel}`
: "New claim from Anonymous",
"http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif",
`http://open.lbry.io/${
claim.channel
? `${claim.channel}#${claim.channelId}/${claim["name"]}`
: `${claim["name"]}#${claim["claimId"]}`
}`
)
.setTitle(
"lbry://" + (claim.channel ? `${claim.channel}/` : "") + claim["name"]
)
.setURL(
`http://open.lbry.io/${
claim.channel
? `${claim.channel}#${claim.channelId}/${claim["name"]}`
: `${claim["name"]}#${claim["claimId"]}`
}`
)
.setColor(1399626)
.setFooter(
`Block ${claim.height} • Claim ID ${
claim.claimId
} • Data from Chainquery`
);
if (claim.metadata["title"])
claimEmbed.addField("Title", claim.metadata["title"]);
if (claim.channel) claimEmbed.addField("Channel", claim.channel);
if (claim.metadata["description"]) {
claimEmbed.addField(
"Description",
claim.metadata["description"].substring(0, 1020)
);
}
if (claim.metadata["fee"])
claimEmbed.addField(
"Fee",
claim.metadata["fee"].amount + " " + claim.metadata["fee"].currency
);
if (claim.metadata["license"] && claim.metadata["license"].length > 2)
claimEmbed.addField("License", claim.metadata["license"]);
if (!claim.metadata["nsfw"] && claim.metadata["thumbnail"])
claimEmbed.setImage(claim.metadata["thumbnail"]);
if (
claim.bid_state !== "Controlling" &&
claim.height < claim.valid_at_height
) {
// Claim have not taken over the old claim, send approx time to event.
let takeoverTime =
Date.now() + (claim.valid_at_height - lastBlockHeight) * 161 * 1000; // in theory this should be 150, but in practice its closer to 161
claimEmbed.addField(
"Takes effect on approx",
moment(takeoverTime, "x").format("MMMM Do [at] HH:mm [UTC]") +
` • at block height ${claim.valid_at_height}`
);
}
claimEmbed.addField(
"Claimed for",
`${Number.parseFloat(claim.outputValue).toFixed(4)} LBC`
);
discordPost(claimEmbed);
} else if (claim.name.charAt(0) === "@") {
// This is a channel claim
let channelEmbed = new Discord.RichEmbed()
.setAuthor(
"New channel claim",
"http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif",
`http://open.lbry.io/${claim["name"]}#${claim["claimId"]}`
)
.setTitle(
"lbry://" + (claim.channel ? claim.channel + "/" : "") + claim["name"]
)
.setURL(`http://open.lbry.io/${claim["name"]}#${claim["claimId"]}`)
.setColor(1399626)
.setFooter(
`Block ${claim.height} • Claim ID ${
claim.claimId
} • Data from Chainquery`
)
.addField("Channel Name", claim["name"]);
discordPost(channelEmbed);
}
}
// set the last sync time to the db.
syncState.LastSyncTime = new Date()
.toISOString()
.slice(0, 19)
.replace("T", " ");
await saveJSON(path.join(appRoot.path, "syncState.json"), syncState);
}
function getJSON(path) {
return new Promise((resolve, reject) => {
jsonfile.readFile(path, function(err, jsoncontent) {
if (err) {
reject(err);
} else {
resolve(jsoncontent);
}
});
});
}
function saveJSON(path, obj) {
return new Promise((resolve, reject) => {
jsonfile.writeFile(path, obj, function(err, jsoncontent) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
function discordPost(embed) {
channels.forEach(channel => {
discordBot.channels
.get(channel)
.send("", embed)
.catch(console.error);
});
}
function getClaimsSince(time) {
return new Promise((resolve, reject) => {
let query =
`` +
`SELECT ` +
`c.name,` +
`c.valid_at_height,` +
`c.height,` +
`p.name as channel,` +
`c.publisher_id as channelId,` +
`c.bid_state,` +
`c.effective_amount,` +
`c.claim_id as claimId,` +
`c.value_as_json as value, ` +
`c.transaction_hash_id, ` + // txhash and vout needed to leverage old format for comparison.
`c.vout, ` +
`o.value as outputValue ` +
`FROM claim c ` +
`LEFT JOIN claim p on p.claim_id = c.publisher_id ` +
`LEFT JOIN output o on (o.transaction_hash=c.transaction_hash_id and o.vout=c.vout) ` +
`WHERE c.created_at >='` +
time +
`'`;
// Outputs full query to console for copy/paste into chainquery (debugging)
// console.log(query);
rp(`https://chainquery.lbry.io/api/sql?query=` + query)
.then(function(htmlString) {
resolve(htmlString);
})
.catch(function(err) {
console.log("error", "[Importer] Error getting updated claims. " + err);
reject(err);
});
});
}