Today = ${todayTotals.orders}, sats = ${todayTotals.satsoshis.toLocaleString()}
26 | ` 27 | 28 | const mailOptions = { 29 | from: process.env.GMAIL_USER, // sender address 30 | to: process.env.GMAIL_USER, // list of receivers 31 | subject: text, 32 | html 33 | } 34 | await send(mailOptions) 35 | return todayTotals; 36 | } 37 | 38 | function getTotals(orders) { 39 | const totalMSats = orders.reduce((accum, order) => { 40 | const {msatoshi} = order; 41 | return parseInt(msatoshi) + accum; 42 | }, 0) 43 | const totalSats = totalMSats / 1000; 44 | return {orders: orders.length, satsoshis: totalSats} 45 | } 46 | 47 | main().then(process.exit).catch(process.exit) 48 | -------------------------------------------------------------------------------- /src/invoices/models/PolloFeedOrder.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | var LightningInvoice_1 = require("./LightningInvoice"); 17 | var PolloFeedOrder = /** @class */ (function (_super) { 18 | __extends(PolloFeedOrder, _super); 19 | function PolloFeedOrder(invoice) { 20 | var _this = _super.call(this, invoice) || this; 21 | _this.feed = true; 22 | _this.acknowledged_at = false; 23 | if (!(_this.id && _this.payreq && _this.status && _this.rhash && _this.pay_index)) { 24 | console.log(_this.id, _this.payreq, _this.status, _this.rhash, _this.pay_index); 25 | throw new Error("Invalid order " + JSON.stringify(_this)); 26 | } 27 | _this.metadata = { feedTimes: _this.metadata && 28 | 'feedTimes' in _this.metadata && _this.metadata.feedTimes || 1 }; 29 | return _this; 30 | } 31 | return PolloFeedOrder; 32 | }(LightningInvoice_1.LightningInvoice)); 33 | exports.PolloFeedOrder = PolloFeedOrder; 34 | -------------------------------------------------------------------------------- /src/invoices/models/LightningInvoice.ts: -------------------------------------------------------------------------------- 1 | import {InvoiceResponse} from "./InvoiceResponse"; 2 | 3 | export class LightningInvoice { 4 | id: string 5 | status: string 6 | msatoshi: number 7 | quoted_currency: string 8 | quoted_amount: number 9 | rhash: string 10 | payreq: string 11 | pay_index: number 12 | description: string 13 | metadata?: any 14 | created_at: Date 15 | expires_at: Date 16 | paid_at?: Date 17 | msatoshi_received: string 18 | constructor({ 19 | id, 20 | msatoshi, 21 | quoted_currency, 22 | quoted_amount, 23 | rhash, 24 | payreq, 25 | pay_index, 26 | description, 27 | metadata = {}, 28 | created_at, 29 | expires_at, 30 | paid_at, 31 | msatoshi_received, 32 | status 33 | } : InvoiceResponse) { 34 | 35 | this.id = id 36 | this.msatoshi = parseInt(msatoshi) 37 | this.quoted_currency = quoted_currency || "" 38 | this.quoted_amount = quoted_amount && parseInt(quoted_amount) || 0 39 | this.rhash = rhash 40 | this.payreq = payreq 41 | this.pay_index = pay_index 42 | this.description = description 43 | this.metadata = metadata 44 | this.created_at = new Date(created_at * 1000) 45 | this.expires_at = new Date(expires_at * 1000) 46 | this.paid_at = new Date(paid_at * 1000) 47 | this.msatoshi_received = msatoshi_received 48 | this.status = status 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /views/about.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | title= settings.title 5 | meta(charset='utf-8') 6 | meta(name='viewport', content='width=device-width, initial-scale=1') 7 | meta(name='apple-mobile-web-app-capable', content='yes') 8 | meta(name="mobile-web-app-capable" content="yes") 9 | link(rel="shortcut icon" href="pollofeed.png") 10 | meta(name="application-name" content="pollofeed") 11 | meta(name="apple-mobile-web-app-title" content="pollofeed") 12 | meta(name="msapplication-starturl" content="/") 13 | meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") 14 | link(rel='stylesheet', href='bootswatch/'+ settings.theme +'/bootstrap.min.css') 15 | link(rel='stylesheet', href="style.css") 16 | link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css') 17 | 18 | body.text-center 19 | h1.text-center About Us 20 | a.ml-2(href="/") 21 | i.fa.fa-home 22 | .container.mb-4 23 | h2.my-2 Karen and Lori 24 | p.my-1 Always together. The oldest 2 Rhode Island Reds. Hatched 15/Aug/2016 25 | img.my-1(class="img-fluid" src="KarenLori.jpg") 26 | 27 | h2.my-2 Parkour 28 | p.my-1 Always jumping around and loves to hit pen with both feet 29 | img.my-1(class="img-fluid" src="Parkour.jpg") 30 | 31 | h2.my-2 Daisy 32 | p.my-1 Because she's lazy. Digs holes and lays in them 33 | img.my-1(class="img-fluid" src="daisy.jpg") 34 | 35 | //RED IS DEAD 36 | //h2.my-2 RED 37 | //p.my-1 Retired Extremely Dangerous (to your toes and legs) 38 | //img.my-1(class="img-fluid" src="RED.jpg") 39 | 40 | h2.my-2 Big Black 41 | p.my-1 The alpha hen. Lord of the Seven Kingdoms and Protector of the Realm 42 | img.my-1(class="img-fluid" src="BigBlack.jpg") 43 | 44 | 45 | -------------------------------------------------------------------------------- /views/index.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | title= settings.title 5 | meta(charset='utf-8') 6 | meta(name="apple-mobile-web-app-status-bar" content="#67c6df") 7 | meta(name="theme-color" content="#67c6df") 8 | meta(name='viewport', content='width=device-width, initial-scale=1') 9 | meta(name='csrf', content=req.csrfToken()) 10 | meta(name='show-bolt11', content=settings.show_bolt11 ? 1 : '') 11 | meta(name='apple-mobile-web-app-capable', content='yes') 12 | meta(name="mobile-web-app-capable" content="yes") 13 | meta(name="application-name" content="pollofeed") 14 | meta(name="apple-mobile-web-app-title" content="pollofeed") 15 | meta(name="msapplication-starturl" content="/") 16 | meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") 17 | link(rel="shortcut icon" href="pollofeed.png") 18 | link(rel='stylesheet', href='bootswatch/' + settings.theme + '/bootstrap.min.css') 19 | link(rel='stylesheet', href="style.css") 20 | link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css') 21 | 22 | body 23 | include header.pug 24 | div.app.container.mb-4 25 | .row 26 | button( 27 | class="btn btn-primary btn-block btn_feed mx-auto mb-4" 28 | type="submit" data-buy-item="pollofeed" 29 | ) 30 | i.fa.fa-bolt.font-weight-bold.mr-1 31 | span.font-weight-bold.text-uppercase feed 32 | .row.mb-4 33 | iframe.rounded.mx-auto.shadow( 34 | title='live stream' 35 | src='https://pollofeed.ngrok.io' 36 | height='480' 37 | style="border: none;" 38 | width="640" 39 | ) 40 | include footer.pug 41 | script(src='script.js') 42 | -------------------------------------------------------------------------------- /src/bin/feeder.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | require('dotenv').config({path: path.resolve(__dirname, '../../.env.development')}) 3 | 4 | const orderDao = require('../invoices/dao') 5 | const feed = require('./feed') 6 | const moment = require('moment') 7 | const calcFeedTimes = require('./calcFeedTimes') 8 | const dbconnect = require('./dbconnect') 9 | 10 | const {send} = require('./email') 11 | 12 | async function main() { 13 | 14 | await dbconnect() 15 | 16 | const todayOrders = await orderDao.getOrdersByDate() 17 | 18 | const yesterday = moment().subtract(1, 'day').toDate(); 19 | const yesterDayOrders = await orderDao.getOrdersByDate(yesterday) 20 | 21 | const feedTimes = calcFeedTimes(new Date().getHours(), todayOrders.length, yesterDayOrders.length) 22 | 23 | const totals = getTotals(todayOrders) 24 | const yTotals = getTotals(yesterDayOrders) 25 | const shouldFeed = feedTimes > 0 26 | if (shouldFeed) await feed(feedTimes) 27 | 28 | let text = `pollofeed - fed ${todayOrders.length} times today.` 29 | if (shouldFeed) text += `\tjust fed ${feedTimes} times.` 30 | const mailOptions = { 31 | from: process.env.GMAIL_USER, // sender address 32 | to: process.env.GMAIL_USER, // list of receivers 33 | subject: text, 34 | html: `36 | Today Orders : ${JSON.stringify(totals, null, 2)} 37 |
38 |39 | Yesterday's Orders: ${JSON.stringify(yTotals, null, 2)} 40 |
41 |