Added timers, error handling, validation on item number #1
2 changed files with 109 additions and 16 deletions
|
@ -2,5 +2,7 @@
|
|||
"MatrixRoom": "!exampleEXAMPLEexample:cyberia.club",
|
||||
"MatrixToken": "syt_exampleEXAMPLE_exampleEXAMPLE_example",
|
||||
"MatrixUsername": "@consensus-bot:cyberia.club",
|
||||
"MatrixURL": "https://matrix.cyberia.club"
|
||||
"MatrixURL": "https://matrix.cyberia.club",
|
||||
"WarningTime": "144h",
|
||||
"ActivationTimeAfterWarning":"24h"
|
||||
}
|
119
main.go
119
main.go
|
@ -10,6 +10,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -25,10 +26,12 @@ const (
|
|||
var config Config
|
||||
|
||||
type Config struct {
|
||||
MatrixRoom string
|
||||
MatrixURL string
|
||||
MatrixUsername string
|
||||
MatrixToken string
|
||||
MatrixRoom string
|
||||
MatrixURL string
|
||||
MatrixUsername string
|
||||
MatrixToken string
|
||||
WarningTime string
|
||||
ActivationTimeAfterWarning string
|
||||
}
|
||||
|
||||
type RecordCount struct {
|
||||
|
@ -38,11 +41,12 @@ type RecordCount struct {
|
|||
}
|
||||
|
||||
type Item struct {
|
||||
author string
|
||||
date time.Time
|
||||
number string
|
||||
name string
|
||||
path string
|
||||
author string
|
||||
date time.Time
|
||||
number string
|
||||
name string
|
||||
path string
|
||||
currentTimer *time.Timer
|
||||
}
|
||||
|
||||
func (i Item) Status() string {
|
||||
|
@ -300,6 +304,47 @@ important: let all items sit for awhile prior to closure
|
|||
return nil
|
||||
}
|
||||
|
||||
func createTriggerOneDayAutoDecide(item Item) func() {
|
||||
//TODO: add functions to extend the timer, and to cancel the timer if the item is closed before it fires
|
||||
return func() {
|
||||
records := countRecords(item.path)
|
||||
if records.approvals != 0 && records.concerns == 0 {
|
||||
handleClose(item.number, "approved")
|
||||
|
||||
}
|
||||
if records.concerns > 0 {
|
||||
handleClose(item.number, "cancelled")
|
||||
}
|
||||
if records.approvals == 0 && records.concerns == 0 {
|
||||
|
||||
openDays := time.Since(item.date).Hours() / 24
|
||||
msg := fmt.Sprintf("consensus item %s is %v days old... but nobody has approved or concerned yet. Let's give it another %s, shall we?", item.number, openDays, config.WarningTime)
|
||||
err := sendMessage(msg)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from notifFunc) sending message for item %s: %v", item.name, err))
|
||||
}
|
||||
notifFunc := createNotifFunc(item)
|
||||
warningTime, _ := time.ParseDuration(config.WarningTime)
|
||||
time.AfterFunc(warningTime, notifFunc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createNotifFunc(item Item) func() {
|
||||
//TODO: add functions to extend the timer, and to cancel the timer if the item is closed before it fires
|
||||
return func() {
|
||||
openDays := time.Since(item.date).Hours() / 24
|
||||
msg := fmt.Sprintf("consensus item %s is now %v days old: %s\nThe item will auto-pass after %s if there is unanimous approval, and auto-fail otherwise! So, now is a good time to weigh in if you haven't yet and have an opinion!", item.number, openDays, item.name, config.ActivationTimeAfterWarning)
|
||||
err := sendMessage(msg)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from notifFunc) sending message for item %s: %v", item.name, err))
|
||||
}
|
||||
triggerOneDayAutoDecide := createTriggerOneDayAutoDecide(item)
|
||||
activationTime, _ := time.ParseDuration(config.ActivationTimeAfterWarning)
|
||||
time.AfterFunc(activationTime, triggerOneDayAutoDecide)
|
||||
}
|
||||
}
|
||||
|
||||
func handleNew(event *gomatrix.Event) error {
|
||||
body, ok := event.Body()
|
||||
if !ok {
|
||||
|
@ -330,6 +375,12 @@ func handleNew(event *gomatrix.Event) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//automatically check-in after time specified in configuration, then after the other time specified in configuration
|
||||
//approve if it has unanimous approval or cancel if any concerns
|
||||
notifFunc := createNotifFunc(item)
|
||||
warningTime, _ := time.ParseDuration(config.WarningTime)
|
||||
time.AfterFunc(warningTime, notifFunc)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -489,6 +540,11 @@ func handleClose(itemNumber string, status string) {
|
|||
sendMessage("please specify an item number. see !help")
|
||||
return
|
||||
}
|
||||
|
||||
if !isValidItemNumber(itemNumber) {
|
||||
return
|
||||
}
|
||||
|
||||
itemPath := recordDir + "/" + itemNumber + ".txt"
|
||||
|
||||
if !fileExists(itemPath) {
|
||||
|
@ -523,12 +579,28 @@ func handleClose(itemNumber string, status string) {
|
|||
sendMessage(msg)
|
||||
}
|
||||
|
||||
func isValidItemNumber(itemNumberCandidate string) bool {
|
||||
_, err := strconv.Atoi(itemNumberCandidate)
|
||||
if err != nil {
|
||||
err = sendMessage("hold yer horses there pard, that ain't no item number like I ever seen before...")
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from isValidItemNumber) sending message: %v", err))
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func handleShow(itemNumber string) {
|
||||
if strings.TrimSpace(itemNumber) == "" {
|
||||
sendMessage("please specify an item number. see !help")
|
||||
return
|
||||
}
|
||||
|
||||
if !isValidItemNumber(itemNumber) {
|
||||
return
|
||||
}
|
||||
|
||||
itemPath := recordDir + "/" + itemNumber + ".txt"
|
||||
if !fileExists(itemPath) {
|
||||
sendMessage("item specified does not exist")
|
||||
|
@ -546,30 +618,49 @@ func handleShow(itemNumber string) {
|
|||
|
||||
func handleComment(event *gomatrix.Event, itemNumber string, comment string, emoji string) {
|
||||
if strings.TrimSpace(itemNumber) == "" {
|
||||
sendMessage("please specify an item number. see !help")
|
||||
err := sendMessage("please specify an item number. see !help")
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from handleComment) sending messag: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(comment) == "" {
|
||||
sendMessage("please specify a comment. see !help")
|
||||
err := sendMessage("please specify a comment. see !help")
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from handleComment) sending messag: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !isValidItemNumber(itemNumber) {
|
||||
return
|
||||
}
|
||||
|
||||
itemPath := recordDir + "/" + itemNumber + ".txt"
|
||||
|
||||
if !fileExists(itemPath) {
|
||||
sendMessage("item specified does not exist")
|
||||
err := sendMessage("item specified does not exist")
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from handleComment) sending messag: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
item, err := loadItemByPath(itemPath)
|
||||
if err != nil {
|
||||
sendMessage("item not found: " + err.Error())
|
||||
err = sendMessage("item not found: " + err.Error())
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from handleComment) sending messag: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !item.isActive() {
|
||||
sendMessage(fmt.Sprintf("item %s (%s) is not active and may not be commented on", item.number, item.name))
|
||||
err = sendMessage(fmt.Sprintf("item %s (%s) is not active and may not be commented on", item.number, item.name))
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error (from handleComment) sending messag: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue