guess I'm to blame
[svn42.git] / go / r3-netstatus / main.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6     "./r3xmppbot"
7     pubsub "github.com/tuxychandru/pubsub"
8     "flag"
9     "time"
10     "fmt"
11     //~ "./brain"
12 )
13
14 type SpaceState struct {
15     present           bool
16     buttonpress_until int64
17     door_locked bool
18     door_shut bool
19 }
20
21 var (
22     presence_socket_path_ string
23     xmpp_presence_events_chan_     chan interface{}
24     xmpp_login_ struct {jid string; pass string}
25     xmpp_bot_authstring_ string
26     xmpp_state_save_dir_ string
27     button_press_timeout_ int64 = 3600
28 )
29
30 //-------
31
32 func init() {
33     flag.StringVar(&xmpp_login_.jid, "xjid", "realrauminfo@realraum.at/Tuer", "XMPP Bot Login JID")
34     flag.StringVar(&xmpp_login_.pass, "xpass", "", "XMPP Bot Login Password")
35     flag.StringVar(&xmpp_bot_authstring_, "xbotauth", "", "String that user use to authenticate themselves to the bot")
36     flag.StringVar(&presence_socket_path_,"presencesocket", "/var/run/tuer/presence.socket",  "Path to presence socket")
37     flag.StringVar(&xmpp_state_save_dir_,"xstatedir","/flash/var/lib/r3netstatus/",  "Directory to save XMPP bot state in")
38     flag.Parse()
39 }
40
41 //-------
42
43 func IfThenElseStr(c bool, strue, sfalse string) string {
44     if c {return strue} else {return sfalse}
45 }
46
47 func composeMessage(present, locked, shut bool, who string, ts int64) string {
48     return fmt.Sprintf("%s (Door is %s and %s and was last used%s at %s)",
49         IfThenElseStr(present,  "Somebody is present!" , "Everybody left."),
50         IfThenElseStr(locked, "locked","unlocked"),
51         IfThenElseStr(shut, "shut","ajar"),
52         IfThenElseStr(len(who) == 0,"", " by " + who),
53         time.Unix(ts,0).String())
54 }
55
56 func EventToXMPP(ps *pubsub.PubSub, xmpp_presence_events_chan_ chan <- interface{}) {
57     events := ps.Sub("presence","door","buttons","updateinterval")
58
59     defer func() {
60         if x := recover(); x != nil {
61             fmt.Printf("handleIncomingXMPPStanzas: run time panic: %v", x)
62             ps.Unsub(events, "presence","door","buttons","updateinterval")
63             close(xmpp_presence_events_chan_)
64         }
65     }()
66
67     var present, locked, shut bool = false, true, true
68     var last_buttonpress int64 = 0
69     var who string
70     button_msg := "The button has been pressed ! Propably someone is bored and in need of company ! ;-)"
71     present_status := r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowOnline,"Somebody is present"}
72     notpresent_status := r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowNotAvailabe,"Nobody is here"}
73     button_status := r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowFreeForChat, "The button has been pressed :-)"}
74     
75     xmpp_presence_events_chan_ <- r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowNotAvailabe, "Nobody is here"}
76     
77     for eventinterface := range(events) {
78         switch event := eventinterface.(type) {
79             case PresenceUpdate:
80                 present = event.Present
81                 xmpp_presence_events_chan_ <- r3xmppbot.XMPPMsgEvent{Msg: composeMessage(present, locked, shut, who, event.Ts), DistributeLevel: r3xmppbot.R3OnlineOnlyInfo, RememberAsStatus: true}
82                 if present {
83                     xmpp_presence_events_chan_ <- present_status
84                 } else {
85                     xmpp_presence_events_chan_ <- notpresent_status
86                 }           
87             case DoorCommandEvent:
88                 if len(event.Who) > 0 && len(event.Using) > 0 {
89                     who = fmt.Sprintf("%s (%s)",event.Who, event.Using)
90                 } else {
91                     who = event.Who
92                 }
93                 xmpp_presence_events_chan_ <- fmt.Sprintln("DoorCommand:",event.Command, "using", event.Using, "by", event.Who, time.Unix(event.Ts,0))
94             case DoorStatusUpdate:
95                 locked = event.Locked
96                 shut = event.Shut
97                 xmpp_presence_events_chan_ <- r3xmppbot.XMPPMsgEvent{Msg: composeMessage(present, locked, shut, who, event.Ts), DistributeLevel: r3xmppbot.R3DebugInfo, RememberAsStatus: true}
98             case ButtonPressUpdate:
99                 xmpp_presence_events_chan_ <- r3xmppbot.XMPPMsgEvent{Msg: button_msg, DistributeLevel: r3xmppbot.R3OnlineOnlyInfo}
100                 xmpp_presence_events_chan_ <- button_status
101                 last_buttonpress = event.Ts
102             case TimeTick:
103                 if present && last_buttonpress > 0 && time.Now().Unix() - last_buttonpress > button_press_timeout_ {
104                     xmpp_presence_events_chan_ <- present_status
105                     last_buttonpress = 0
106                 }
107         }
108         }
109 }
110
111 func main() {
112     var xmpperr error
113     var bot *r3xmppbot.XmppBot
114     bot, xmpp_presence_events_chan_, xmpperr = r3xmppbot.NewStartedBot(xmpp_login_.jid, xmpp_login_.pass, xmpp_bot_authstring_, xmpp_state_save_dir_, true)
115
116     newlinequeue := make(chan string, 1)
117     ps := pubsub.New(1)
118     //~ brn := brain.New()
119     defer close(newlinequeue)
120     defer ps.Shutdown()
121     //~ defer brn.Shutdown()
122
123     go EventToWeb(ps)
124     if xmpperr == nil {
125         defer bot.StopBot()
126         go EventToXMPP(ps, xmpp_presence_events_chan_)
127     } else {
128         fmt.Println(xmpperr)
129         fmt.Println("XMPP Bot disabled")
130     }
131     go ReadFromUSocket(presence_socket_path_, newlinequeue)
132     ticker := time.NewTicker(time.Duration(7) * time.Minute)
133
134     for {
135     select {
136         case e := <-newlinequeue:
137             ParseSocketInputLine(e, ps) //, brn)
138         case <-ticker.C:
139             ps.Pub(TimeTick{time.Now().Unix()}, "updateinterval")
140         }
141     }
142 }