Config data locations with environment variables
3 files changed, 33 insertions(+), 36 deletions(-)

M README.md
M go.mod
M main.go
M README.md +5 -7
@@ 1,13 1,13 @@ 
-icsmailer
+icsinvite
 =========
 
 In OSS, it appears nobody wants to be responsible for sending email invitations.
-icsmailer does this for you.
+icsinvite does this for you.
 
 Features
 ========
 
-icsmailer is designed to watch a calendar collection and send invites to
+icsinvite is designed to watch a calendar collection and send invites to
 attendees when it detects changes.
 
 -  The collection can be either a directory full of calendar events or a WebDAV calendar

          
@@ 24,7 24,7 @@ Non-features
 ============
 
 -  Event changes (e.g. reacting to reschedule events)
--  Encrypted emails (must be decrypted before icsmailer)
+-  Encrypted emails (must be decrypted before icsinvite)
 
 
 Design

          
@@ 33,7 33,6 @@ Design
 icsmailer stands on the shoulders of:
 
 - https://github.com/arran4/golang-ical
-- https://github.com/timshannon/bolthold
 - https://github.com/jordan-wright/email
  
 Alts 

          
@@ 41,5 40,4 @@ Alts
 
 - https://github.com/prologic/bitcask
 - https://github.com/emersion/go-message
-
-
+- https://github.com/timshannon/bolthold

          
M go.mod +1 -1
@@ 1,4 1,4 @@ 
-module ser1.net/icsmailer
+module ser1.net/icsinvite
 
 go 1.16
 

          
M main.go +27 -28
@@ 14,7 14,6 @@ import (
 	"os"
 )
 
-// TODO environment configuration for DB and calendar locations
 // TODO -C 	 	-- send only to changed attendees
 // TODO -e 	 	-- input is an email
 // TODO -d <path> 	-- database path

          
@@ 49,13 48,19 @@ func processFlags(args ...string) {
 			var err error
 			in, err = os.Open(send.One)
 			if err != nil {
-				// TODO handle panic
-				panic(err)
+				fmt.Errorf("unable to process input data: %s\n", err)
+				return
 			}
 		}
-		if err := send.parseSend(in); err != nil {
-			// TODO handle panic
-			panic(err)
+		// Process confirmation
+		if send.MailInput {
+			// TODO: email confirmation handling
+			// Get confirmation from email
+			// Get sender from email
+			// Find ICS in calendar
+			// Update RSVP in ICS file
+		} else if err := send.sendInvites(in); err != nil {
+			fmt.Errorf("error processing calendar event: %s\n", err)
 		}
 		return
 	}

          
@@ 73,7 78,7 @@ func processFlags(args ...string) {
 			if err != nil {
 				return err
 			}
-			if err = send.parseSend(in); err != nil {
+			if err = send.sendInvites(in); err != nil {
 				return err
 			}
 		}

          
@@ 111,17 116,17 @@ func calStats(path string) CalStats {
 var VERSION string = "dev"
 
 type Send struct {
-	One         string `names:"-f" usage:"process a single event; filename, or - for stdin"`
-	Version     bool   `names:"-V" usage:"print version (& exit)"`
-	Query       bool   `names:"-Q" usage:"print DB & calendar statistics"`
-	NOP         bool   `names:"-N" usage:"do nothing"`
-	NoEmail     bool   `names:"-S" usage:"do not send emails (but maybe persist to DB)"`
-	OnlyChanged bool   `names:"-C" usage:"only send emails to changed attendees"`
-	Debug       bool   `names:"-D" usage:"be verbose"`
-	DbPath      string `names:"-d" usage:"the path to the database"`
-	CalPath     string `names:"-c" usage:"the path to the calendar"`
+	One         string `names:"-f" usage:"Process a single event; filename, or - for stdin"`
+	Version     bool   `names:"-V" usage:"Print version (& exit)"`
+	Query       bool   `names:"-Q" usage:"Print DB & calendar statistics"`
+	NOP         bool   `names:"-N" usage:"Do nothing"`
+	NoEmail     bool   `names:"-S" usage:"Do not send emails (but maybe persist to DB)"`
+	OnlyChanged bool   `names:"-C" usage:"Only send emails to changed attendees" env:"ICS_ONLY_CHANGED"`
+	Debug       bool   `names:"-D" usage:"Be verbose"`
+	DbPath      string `names:"-d" usage:"The path to the database" env:"ICS_DB"`
+	CalPath     string `names:"-c" usage:"The path to the calendar" env:"ICS_DIR"`
+	MailInput   bool   `names:"-e" usage:"Input data is an email containing an RSVP response"`
 	//NoPersist   bool   `names:"-Z" usage:"do not record actions to database (but maybe send emails)"`
-	mailInput bool `names:"-e" usage:"input data is an email containing an RSVP response"`
 }
 
 func (t *Send) Metadata() map[string]flag.Flag {

          
@@ 162,7 167,7 @@ func (t *Send) Metadata() map[string]fla
 		},
 		"-e": {
 			Desc: `
-			Usefel only with -f; ignored otherwise. The input is expected to be an email with
+			Useful only with -f; ignored otherwise. The input is expected to be an email with
 			an RSVP response either in the body, or as an attachment. The ICS file will be
 			updated with the RSVP response.
 			`,

          
@@ 171,30 176,23 @@ func (t *Send) Metadata() map[string]fla
 			Desc: `
 			The database is a tsv file in the form of:
 			<ICS UUID><tab>[<attendee>[,<attendee>]*]?
-
 			Example: icsmailer -d ~/.icsmailer.tsv
 			`,
 		},
 		"-c": {
 			Desc: `
-			The calendar is a directory of .ics files, such as one managed by vdirsyncer. Example:
-			icsmailer -c ~/.calendars/defaultcalendar/
+			The calendar is a directory of .ics files, such as one managed by vdirsyncer.
+			Example: icsmailer -c ~/.calendars/defaultcalendar/
 			`,
 		},
 	}
 }
 
-func (s Send) parseSend(in io.Reader) error {
+func (s Send) sendInvites(in io.Reader) error {
 	cal, err := ics.ParseCalendar(in)
 	if err != nil {
 		return err
 	}
-	s.sendInvites(cal)
-	return nil
-}
-
-// TODO optionally send
-func (s Send) sendInvites(cal *ics.Calendar) error {
 	var valid = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
 	for _, e := range cal.Events() {
 		id := e.Id()

          
@@ 229,6 227,7 @@ func (s Send) sendInvites(cal *ics.Calen
 		if !s.NoEmail {
 			// TODO actually send
 		}
+		// TODO record in DB
 	}
 	return nil
 }