const { registerJoystreamTypes } = require('@joystream/types'); const { ApiPromise, WsProvider } = require('@polkadot/api'); const TelegramBot = require('node-telegram-bot-api'); // replace yourowntoken below with the Telegram token you receive from @BotFather const token = 'yourowntoken'; const bot = new TelegramBot(token); //replace yourownchat, get chat id here https://stackoverflow.com/questions/32423837/telegram-bot-how-to-get-a-group-chat-id const chatid = 'yourownchat'; async function main () { registerJoystreamTypes() // Create the API and wait until ready const api = await ApiPromise.create({ provider: new WsProvider() }) let proposalcount = (await api.query.proposalsEngine.proposalCount()).toNumber() // let activeproposals = [] // let activeproposals = ((await api.query.proposalsEngine.activeProposalIds()).toJSON())[0] let activeproposals = await getactiveProposals(api) let filteredproposal let tobeexecutedprop = await getpendingProposals(api) let tobeexecutedpropfiltered const unsubscribe = await api.rpc.chain.subscribeNewHeads(async (header) => { const block = header.number.toNumber() const currentproposal = (await api.query.proposalsEngine.proposalCount()).toNumber() console.log(`Current block: ${block}, Current proposal count: ${currentproposal}, Current active proposal : ${activeproposals}`) if (currentproposal>proposalcount) { for (proposalcount+1;proposalcount0) { for (const proposallist of activeproposals){ const proposal = await getproposalDetail(api,proposallist) let propstage = proposal.stage()[0] if (propstage == 'Finalized') { const propstatus = proposal.resultjson() switch (propstatus[0]){ case 'Approved': let graceperiod = proposal.graceperiod() if (graceperiod>0) { bot.sendMessage(chatid, `Proposalid (${proposallist}) status changed to "Finalized" at block ${proposal.finalizedtime()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) filteredproposal = activeproposals.filter(e => e != proposallist) tobeexecutedprop.push(proposallist) } else { bot.sendMessage(chatid, `Proposalid (${proposallist}) status changed to "Finalized and Executed" at block ${proposal.finalizedtime()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) filteredproposal = activeproposals.filter(e => e != proposallist) } break; case 'Expired': case 'Canceled': case 'Cancelled': case 'Rejected': case 'Slashed': case 'Vetoed': // console.log(`Proposal ${proposallist} ${propstatus[0]}`) // bot.sendMessage(chatid, `Proposalid (${proposallist}) status changed to "Finalized:${propstatus[0]}" at block ${proposal.finalizedtime()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) // filteredproposal = activeproposals.filter(e => e != proposallist) // break; default: console.log(`Proposal ${proposallist} changed to other status: ${propstatus[0]}`) bot.sendMessage(chatid, `Proposalid (${proposallist}) status changed to "Finalized:${propstatus[0]}" at block ${proposal.finalizedtime()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) filteredproposal = activeproposals.filter(e => e != proposallist) break; } activeproposals = filteredproposal } } } if (tobeexecutedprop[0]>0) { for (const proposallist of tobeexecutedprop) { const proposal = await getproposalDetail(api,proposallist) let exestatus = Object.getOwnPropertyNames(proposal.resultfull()['Approved'])[0] if (exestatus=='Executed'){ console.log(`Proposal ${proposallist} has been executed`) bot.sendMessage(chatid, `Proposalid (${proposallist}) has been executed at block ${proposal.finalizedtime()+proposal.graceperiod()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) tobeexecutedpropfiltered = tobeexecutedprop.filter(e => e != proposallist) } else { console.log(`Proposal ${proposallist} Execution is failed`) bot.sendMessage(chatid, `Proposalid (${proposallist}) failed to be executed at block ${proposal.finalizedtime()+proposal.graceperiod()}.\r\n ${proposal.postmessage()}`, { parse_mode: 'html' }) tobeexecutedpropfiltered = tobeexecutedprop.filter(e => e != proposallist) } tobeexecutedprop = tobeexecutedpropfiltered } } }) } const getpendingProposals = async (api) => { let tobeexecutedprop = ((await api.query.proposalsEngine.pendingExecutionProposalIds()).toJSON())[0] if (tobeexecutedprop[0]==0){ return [] } else { return tobeexecutedprop } } const getactiveProposals = async (api) => { let activeproposals = ((await api.query.proposalsEngine.activeProposalIds()).toJSON())[0] if (activeproposals[0]==0){ return [] } else { return activeproposals } } const getmemberHandle = async (api,memberid) => { const memberprofile = await api.query.members.memberProfile(memberid) const handler = memberprofile.raw.handle.toJSON() return handler } const getproposalStatus = (propresultraw) => { if (propresultraw.hasOwnProperty('proposalStatus')) { return propresultraw.proposalStatus } else { return {Active:null} } } const getfinalTime = (propresultraw) => { if (propresultraw.hasOwnProperty('finalizedAt')) { return propresultraw.finalizedAt } else { return 0 } } const getproposalDetail = async (api,proposalcount) => { const propdetail = await api.query.proposalsEngine.proposals(proposalcount) const parameters = propdetail.parameters const propposterid = propdetail.proposerId.toJSON() const handler = await getmemberHandle(api,propposterid) const proptype = await api.query.proposalsCodex.proposalDetailsByProposalId(proposalcount) const [deftype] = Object.getOwnPropertyNames(proptype.toJSON()) const proptitle = propdetail.title.toJSON() const propstage = propdetail.status.toJSON() // const propstatus = propdetail.get("status") const propstatus = Object.getOwnPropertyNames(propstage) const propresultraw = propstage[propstatus] const propfinalresultfull = getproposalStatus(propresultraw) // const propfinalresultfull = propresultraw.proposalStatus // const propfinalresultjson = Object.getOwnPropertyNames(propresultraw.proposalStatus) const propfinaltime = getfinalTime(propresultraw) // const propfinaltime = propresultraw.finalizedAt const propfinalresultjson = Object.getOwnPropertyNames(propfinalresultfull) const graceperiod = propdetail.parameters.gracePeriod.toNumber() return { detail : function () { return propdetail; }, parameters : function () { return parameters; }, stage : function () { return propstatus; }, finalizedtime : function () { return propfinaltime; }, graceperiod : function () { return graceperiod; }, resultfull : function () { return propfinalresultfull; }, resultjson : function () { return propfinalresultjson; }, postmessage : function () { return `Type: ${deftype}\r\n Proposer: ${handler}(${propposterid})\r\n Title: ${proptitle.substring(0,100)}\r\n Stage: ${propstatus}\r\n Result: ${JSON.stringify(propfinalresultfull)}`; // postmessage : function () { // return `Type: ${this.deftype()}\r\n Proposer: ${this.handler()}(${this.posterid()})\r\n Title: ${this.title()}\r\n Stage: ${this.stage()}\r\n Result: ${this.result()}`; } } } main()