@@ -31,12 +31,13 @@ type Rules struct {
3131}
3232
3333type Rule struct {
34- Name string `yaml:"name"`
35- Type string `yaml:"type"` // "redirect" or "auto_reply"
36- FromSender string `yaml:"from_sender"`
37- ToReceivers []string `yaml:"to_receivers,omitempty"`
38- ReplyText string `yaml:"reply_text,omitempty"`
39- Enabled bool `yaml:"enabled"`
34+ Name string `yaml:"name"`
35+ Type string `yaml:"type"` // "redirect", "auto_reply", or "auto_reply_after_silence"
36+ FromSender string `yaml:"from_sender"`
37+ ToReceivers []string `yaml:"to_receivers,omitempty"`
38+ ReplyText string `yaml:"reply_text,omitempty"`
39+ SilenceDurationSecs int `yaml:"silence_duration_secs,omitempty"` // Time in seconds before auto-reply triggers
40+ Enabled bool `yaml:"enabled"`
4041}
4142
4243// WebSocket message structures
@@ -75,14 +76,20 @@ type OutgoingMessage struct {
7576}
7677
7778var (
78- conn * websocket.Conn
79- config Config
80- rules Rules
79+ conn * websocket.Conn
80+ config Config
81+ rules Rules
82+ lastConversationMap map [string ]time.Time // Tracks last message time per sender
83+ autoReplyStatusMap map [string ]bool // Tracks if auto-reply was already sent
8184)
8285
8386func main () {
8487 log .Println ("iOSMB-Router starting..." )
8588
89+ // Initialize tracking maps
90+ lastConversationMap = make (map [string ]time.Time )
91+ autoReplyStatusMap = make (map [string ]bool )
92+
8693 // Load configuration from environment or config file
8794 loadConfig ()
8895
@@ -201,9 +208,21 @@ func processMessage(data interface{}) {
201208
202209 msg := msgData .Message [0 ]
203210
211+ // Get sender identifier (prefer ChatID, fallback to Author)
212+ senderID := msg .ChatID
213+ if senderID == "" {
214+ senderID = msg .Author
215+ }
216+
217+ // Update last conversation time for this sender
218+ currentTime := time .Now ()
219+ lastConversationMap [senderID ] = currentTime
220+
204221 // Skip messages sent by you (sender == 1)
205222 if msg .Sender == 1 {
206223 log .Printf ("Skipping own message" )
224+ // Reset auto-reply status when you send a message (conversation resumed)
225+ autoReplyStatusMap [senderID ] = false
207226 return
208227 }
209228
@@ -231,6 +250,8 @@ func processMessage(data interface{}) {
231250 handleRedirect (msg , rule )
232251 case "auto_reply" :
233252 handleAutoReply (msg , rule )
253+ case "auto_reply_after_silence" :
254+ handleAutoReplyAfterSilence (msg , rule , senderID )
234255 default :
235256 log .Printf ("Unknown rule type: %s" , rule .Type )
236257 }
@@ -272,6 +293,48 @@ func handleAutoReply(msg MessageInfo, rule Rule) {
272293 sendMessage (outMsg )
273294}
274295
296+ func handleAutoReplyAfterSilence (msg MessageInfo , rule Rule , senderID string ) {
297+ // Check if auto-reply was already sent during this silence period
298+ if autoReplyStatusMap [senderID ] {
299+ log .Printf ("Auto-reply already sent to %s during this silence period" , msg .Author )
300+ return
301+ }
302+
303+ // Get last conversation time
304+ lastTime , exists := lastConversationMap [senderID ]
305+ if ! exists {
306+ // First message from this sender, don't auto-reply yet
307+ log .Printf ("First message from %s, tracking conversation time" , msg .Author )
308+ return
309+ }
310+
311+ // Calculate time since last conversation
312+ timeSinceLastMsg := time .Since (lastTime )
313+ requiredSilence := time .Duration (rule .SilenceDurationSecs ) * time .Second
314+
315+ log .Printf ("Time since last message from %s: %v (required: %v)" ,
316+ msg .Author , timeSinceLastMsg , requiredSilence )
317+
318+ // Check if enough time has passed
319+ if timeSinceLastMsg >= requiredSilence {
320+ log .Printf ("Auto-replying to %s after %v of silence" , msg .Author , timeSinceLastMsg )
321+
322+ outMsg := OutgoingMessage {
323+ Address : msg .ChatID ,
324+ Text : rule .ReplyText ,
325+ Subject : "" ,
326+ Attachments : []interface {}{},
327+ }
328+
329+ sendMessage (outMsg )
330+
331+ // Mark that auto-reply was sent for this silence period
332+ autoReplyStatusMap [senderID ] = true
333+ } else {
334+ log .Printf ("Not enough silence time for %s, skipping auto-reply" , msg .Author )
335+ }
336+ }
337+
275338func sendMessage (msg OutgoingMessage ) {
276339 // Use HTTP POST like the web client does
277340 protocol := "http"
0 commit comments