113 lines
2.9 KiB
JavaScript
113 lines
2.9 KiB
JavaScript
const express = require("express")
|
|
const bodyParser = require("body-parser")
|
|
const moment = require("moment")
|
|
const Airtable = require("airtable")
|
|
|
|
// Let's load some configuration!
|
|
require("dotenv").config()
|
|
|
|
const port = process.env.SNIPBOT_PORT || 5000
|
|
|
|
// Now it's time for setup!
|
|
Airtable.configure({
|
|
endpointUrl: process.env.SNIPBOT_AIRTABLE_ENDPOINT,
|
|
apiKey: process.env.SNIPBOT_AIRTABLE_API_KEY,
|
|
})
|
|
|
|
const base = Airtable.base(process.env.SNIPBOT_AIRTABLE_BASE_ID)
|
|
|
|
const app = express()
|
|
|
|
app.use(bodyParser.json())
|
|
|
|
app.listen(port, () => {
|
|
console.log(`Server is running on port ${port}.`)
|
|
})
|
|
|
|
app.get("/", (req, res) => {
|
|
res.send({ status: "ok", message: "woof, woof!" })
|
|
})
|
|
|
|
app.post("/add", (req, res) => {
|
|
const { a, b } = req.body
|
|
res.send({ result: a + b })
|
|
})
|
|
|
|
app.post("/edcal", (req, res) => {
|
|
let articles = []
|
|
|
|
base('Articles').select({
|
|
maxRecords: 10,
|
|
view: "Calendar",
|
|
fields: [
|
|
"Title",
|
|
"Author",
|
|
"Due Date",
|
|
"Publish Date",
|
|
"In charge",
|
|
"Status",
|
|
],
|
|
filterByFormula: "NOT({Status} = 'Stalled')",
|
|
sort: [
|
|
{ field: "Publish Date", direction: "desc" },
|
|
{ field: "Status", direction: "asc" },
|
|
],
|
|
}).eachPage(function page(records, fetchNextPage) {
|
|
records.forEach((record) => {
|
|
console.log(`Got ${record.get('Title')}`)
|
|
articles.push({
|
|
title: record.get("Title"),
|
|
author: record.get("Author"),
|
|
due_date: moment(record.get("Due Date")).format("DD MMM"),
|
|
publish_date: moment(record.get("Publish Date")).format("DD MMM YYYY"),
|
|
in_charge: record.get("In charge"),
|
|
status: record.get("Status"),
|
|
})
|
|
})
|
|
|
|
fetchNextPage()
|
|
}, function done(err) {
|
|
if (err) {
|
|
console.error(err)
|
|
res.send({ status: "error", "error": "An error occurred :("})
|
|
return
|
|
}
|
|
|
|
if (req.body.command != 'edcal') {
|
|
let statusToEmoji = new Map([
|
|
['Published', ':grin:'],
|
|
['Scheduled', ':alarm_clock:'],
|
|
['WIP', ':roundpup:'],
|
|
['Waiting for response', ':zzz:'],
|
|
['Stalled', ':clown_face:'],
|
|
])
|
|
|
|
// format the articles into a table
|
|
articleTable = (articles
|
|
.reverse()
|
|
.map(a => `|${a.title}|${a.in_charge.map(u=>u.name[0]).join(',')}|${a.due_date}|${a.publish_date}|${statusToEmoji.get(a.status) || a.status}|`)
|
|
.join("\n"))
|
|
|
|
// an emoji -> status message legend to display at the end
|
|
emojiKey = ([...statusToEmoji.entries()]
|
|
.map((x) => `${x[1]} ${x[0]}`)
|
|
.join(' '))
|
|
|
|
// ...and we're out!
|
|
res.send({
|
|
response_type: "in_channel",
|
|
text: `
|
|
#### Editorial Calendar #are
|
|
|
|
|:roundpup: Title|PP|Due Date|Publish Date|Status|
|
|
|:---------------|:-|:-------|:-----------|:-----|
|
|
${articleTable}
|
|
${emojiKey}
|
|
`,
|
|
})
|
|
} else {
|
|
res.send({ status: "ok", articles: articles.reverse() })
|
|
}
|
|
})
|
|
})
|