personal/q3k/lelegram: changes by zagura

  * Log high verbose debug messages
  * New cli parameter irc_login
  * Change regex for IRC nicks
  * IRC channel names case insensitive
  * IRC usernames truncated to 9 chars without Telegram suffix

Signed-off-by: Michał Zagórski <zagura6@gmail.com>
Change-Id: Ifa32279580a4378cc3b9e255f0311216998e02c9
diff --git a/personal/q3k/lelegram/irc/conn.go b/personal/q3k/lelegram/irc/conn.go
index 5ec3c62..8846716 100644
--- a/personal/q3k/lelegram/irc/conn.go
+++ b/personal/q3k/lelegram/irc/conn.go
@@ -53,7 +53,7 @@
 	connected int64
 }
 
-var reIRCNick = regexp.MustCompile(`[^A-Za-z0-09]`)
+var reIRCNick = regexp.MustCompile(`[^A-Za-z0-9]`)
 
 // Say is called by the Manager when a message should be sent out by the
 // connection.
@@ -74,8 +74,23 @@
 	text string
 }
 
-func NewConn(server, channel, user string, backup bool, h func(e *event)) (*ircconn, error) {
-	glog.Infof("Connecting to IRC/%s/%s/%s...", server, channel, user)
+func NewConn(server, channel, userTelegram string, backup bool, h func(e *event)) (*ircconn, error) {
+	// Generate IRC nick from username.
+	nick := reIRCNick.ReplaceAllString(userTelegram, "")
+	username := nick
+	if len(username) > 9 {
+		username = username[:9]
+	}
+	nick = strings.ToLower(nick)
+	if len(nick) > 13 {
+		nick = nick[:13]
+	}
+	if len(nick) == 0 {
+		glog.Errorf("Could not create IRC nick for %q", userTelegram)
+		nick = "wtf"
+	}
+	nick += "[t]"
+	glog.Infof("Connecting to IRC/%s/%s/%s as %s from %s...", server, channel, userTelegram, nick, username)
 	conn, err := net.Dial("tcp", server)
 	if err != nil {
 		return nil, fmt.Errorf("Dial(_, %q): %v", server, err)
@@ -84,7 +99,7 @@
 	i := &ircconn{
 		server:  server,
 		channel: channel,
-		user:    user,
+		user:    userTelegram,
 
 		eventHandler: h,
 
@@ -102,22 +117,14 @@
 		connected: int64(0),
 	}
 
-	// Generate IRC nick from username.
-	nick := reIRCNick.ReplaceAllString(user, "")
-	if len(nick) > 13 {
-		nick = nick[:13]
-	}
-	if len(nick) == 0 {
-		glog.Errorf("Could not create IRC nick for %q", user)
-		nick = "wtf"
-	}
-	nick += "[t]"
+
+
 
 	// Configure IRC client to populate the IRC Queue.
 	config := irc.ClientConfig{
 		Nick: nick,
-		User: user,
-		Name: user,
+		User: username,
+		Name: userTelegram,
 		Handler: irc.HandlerFunc(func(c *irc.Client, m *irc.Message) {
 			i.iq <- m
 		}),
@@ -221,6 +228,9 @@
 				glog.V(1).Infof("IRC/%s/debug: %+v", i.user, m)
 			}
 
+			glog.V(16).Infof("irc/debug16: Message: cmd(%s), channel(%s)", m.Command, m.Params[0])
+			glog.V(16).Infof("irc/debug16: Current: channel(%s), command(%s)", i.channel, "PRIVMSG")
+			glog.V(16).Infof("irc/debug16: Current: channel-eq(%t), command-eq(%t)", i.channel == m.Params[0], "PRIVMSG" == m.Command)
 			switch {
 			case m.Command == "001":
 				glog.Infof("IRC/%s/info: joining %s...", i.user, i.channel)
@@ -250,8 +260,8 @@
 				glog.Infof("IRC/%s/info: got kicked", i.user)
 				die(nil)
 				return
-
-			case m.Command == "PRIVMSG" && m.Params[0] == i.channel:
+			case m.Command == "PRIVMSG" && strings.ToLower(m.Params[0]) == i.channel:
+				glog.V(8).Infof("IRC/%s/debug8: received message on %s", i.user, i.channel)
 				go i.eventHandler(&event{
 					message: &eventMessage{i, m.Prefix.Name, m.Params[1]},
 				})
diff --git a/personal/q3k/lelegram/irc/manager.go b/personal/q3k/lelegram/irc/manager.go
index 4e8365d..da1d3e3 100644
--- a/personal/q3k/lelegram/irc/manager.go
+++ b/personal/q3k/lelegram/irc/manager.go
@@ -24,6 +24,8 @@
 type Manager struct {
 	// maximum IRC sessions to maintain
 	max int
+	// IRC bot's username
+	login string
 	// IRC server address
 	server string
 	// IRC channel name
@@ -45,9 +47,10 @@
 	runctx context.Context
 }
 
-func NewManager(max int, server, channel string) *Manager {
+func NewManager(max int, server, channel string, login string) *Manager {
 	return &Manager{
 		max:     max,
+		login:	 login,
 		server:  server,
 		channel: channel,
 		ctrl:    make(chan *control),
@@ -142,7 +145,7 @@
 		if len(m.conns) == 0 {
 			// Noone said anything on telegram, make backup
 			glog.Infof("No receiver found, making backup")
-			name := "lelegram"
+			name := m.login
 			c, err := m.newconn(ctx, name, true)
 			if err != nil {
 				glog.Errorf("Could not make backup receiver: %v", err)
diff --git a/personal/q3k/lelegram/irc/manager_conns.go b/personal/q3k/lelegram/irc/manager_conns.go
index 6427ec6..b578f0d 100644
--- a/personal/q3k/lelegram/irc/manager_conns.go
+++ b/personal/q3k/lelegram/irc/manager_conns.go
@@ -14,13 +14,13 @@
 
 // getconn either gets a connection by username, or creates a new one (after
 // evicting the least recently used connection).
-func (m *Manager) getconn(ctx context.Context, user string) (*ircconn, error) {
+func (m *Manager) getconn(ctx context.Context, userTelegram string) (*ircconn, error) {
 	// Is the user shitlisted?
-	if t, ok := m.shitlist[user]; ok && time.Now().Before(t) {
+	if t, ok := m.shitlist[userTelegram]; ok && time.Now().Before(t) {
 		return nil, errBanned
 	}
 	// Do we already have a connection?
-	c, ok := m.conns[user]
+	c, ok := m.conns[userTelegram]
 	if ok {
 		// Bump and return.
 		c.last = time.Now()
@@ -46,17 +46,17 @@
 	}
 
 	// Allocate new connection
-	return m.newconn(ctx, user, false)
+	return m.newconn(ctx, userTelegram, false)
 }
 
 // newconn creates a new IRC connection as a given user, and saves it to the
 // conns map.
-func (m *Manager) newconn(ctx context.Context, user string, backup bool) (*ircconn, error) {
-	c, err := NewConn(m.server, m.channel, user, backup, m.Event)
+func (m *Manager) newconn(ctx context.Context, userTelegram string, backup bool) (*ircconn, error) {
+	c, err := NewConn(m.server, m.channel, userTelegram, backup, m.Event)
 	if err != nil {
 		return nil, err
 	}
-	m.conns[user] = c
+	m.conns[userTelegram] = c
 
 	go c.Run(m.runctx)
 
diff --git a/personal/q3k/lelegram/irc/manager_event.go b/personal/q3k/lelegram/irc/manager_event.go
index 399915c..07d978c 100644
--- a/personal/q3k/lelegram/irc/manager_event.go
+++ b/personal/q3k/lelegram/irc/manager_event.go
@@ -77,8 +77,10 @@
 
 // doevent handles incoming events.
 func (m *Manager) doevent(ctx context.Context, e *event) {
+	glog.V(16).Infof("event/debug16: New event handling")
 	switch {
 	case e.nick != nil:
+		glog.V(8).Infof("event/debug8: nick (%s)", e.nick.nick)
 		// Nick update from connection
 
 		// Ensure this connection is still used.
diff --git a/personal/q3k/lelegram/main.go b/personal/q3k/lelegram/main.go
index f4360a9..9e8f977 100644
--- a/personal/q3k/lelegram/main.go
+++ b/personal/q3k/lelegram/main.go
@@ -27,6 +27,7 @@
 	flagIRCMaxConnections int
 	flagIRCServer         string
 	flagIRCChannel        string
+	flagIRCLogin          string
 )
 
 // server is responsible for briding IRC and Telegram.
@@ -76,6 +77,7 @@
 	flag.IntVar(&flagIRCMaxConnections, "irc_max_connections", 10, "How many simulataneous connections can there be to IRC before they get recycled")
 	flag.StringVar(&flagIRCServer, "irc_server", "chat.freenode.net:6667", "The address (with port) of the IRC server to connect to")
 	flag.StringVar(&flagIRCChannel, "irc_channel", "", "The channel name (including hash(es)) to bridge")
+	flag.StringVar(&flagIRCLogin, "irc_login", "lelegram[t]", "The login of irc user used by bot")
 	flag.Parse()
 
 	if flagTelegramToken == "" {
@@ -85,7 +87,10 @@
 	if flagIRCChannel == "" {
 		glog.Exitf("irc_channel must be set")
 	}
-
+	if flagIRCLogin == "" {
+		flagIRCLogin = "lelegram"
+	}
+	glog.Infof("dabug: Backup login in IRC: %s", flagIRCLogin)
 	// Parse given group ID.
 	// If not set, start server in 'lame' mode, ie. one that will not actually
 	// perform any bridging, but will let you figure out the IDs of groups that
@@ -107,8 +112,9 @@
 		glog.Exitf("Listen(): %v", err)
 	}
 
-	mgr := irc.NewManager(flagIRCMaxConnections, flagIRCServer, flagIRCChannel)
-
+	// https://tools.ietf.org/html/rfc2812#section-1.3 "Channel names are case insensitive"
+	mgr := irc.NewManager(flagIRCMaxConnections, flagIRCServer, strings.ToLower(flagIRCChannel), flagIRCLogin)
+	glog.V(4).Infof("telegram/debug4: Linking to group: %d", groupId)
 	s, err := newServer(groupId, mgr)
 	if err != nil {
 		glog.Exitf("newServer(): %v", err)
@@ -140,17 +146,17 @@
 func (s *server) bridge(ctx context.Context) {
 	nickmap := make(map[string]string)
 	for {
+		glog.V(32).Info("bridge/debug32: New element in queue")
 		select {
 		case <-ctx.Done():
 			return
-
 		case m := <-s.telLog:
 			// Event from Telegram (message). Translate Telegram names into IRC names.
 			text := m.text
 			for t, i := range nickmap {
 				text = strings.ReplaceAll(text, "@"+t, i)
 			}
-			glog.Infof("telegram/%s: %v", m.user, text)
+			glog.Infof("telegram/info/%s: %v", m.user, text)
 
 			// Attempt to route message to IRC twice.
 			// This blocks until success or failure, making sure the log stays
@@ -166,6 +172,7 @@
 			cancel()
 
 		case n := <-s.ircLog:
+			glog.V(4).Infof("bridge/irc/debug4: Get message from irc: %s", n.Message)
 			// Notification from IRC (message or new nickmap)
 			switch {
 			case n.Nickmap != nil:
diff --git a/personal/q3k/lelegram/telegram.go b/personal/q3k/lelegram/telegram.go
index e6b673c..7d234ff 100644
--- a/personal/q3k/lelegram/telegram.go
+++ b/personal/q3k/lelegram/telegram.go
@@ -21,29 +21,31 @@
 	if err != nil {
 		return fmt.Errorf("GetUpdatesChan(%+v): %v", u, err)
 	}
+	glog.V(8).Infof("telegram/debug8: New update")
 
 	for {
 		select {
 		case <-ctx.Done():
 			return ctx.Err()
-		case u, ok := <-updates:
+		case update, ok := <-updates:
 			if !ok {
 				return fmt.Errorf("Updates channel closed")
 			}
 
 			// Dispatch update.
 			switch {
-			case u.Message != nil:
-				if u.Message.Chat.ID != s.groupId {
-					glog.Infof("[ignored group %d] <%s> %v", u.Message.Chat.ID, u.Message.From, u.Message.Text)
+			case update.Message != nil:
+				glog.V(4).Infof("telegram/debug4: New message: %d", update.Message.Chat.ID)
+				if update.Message.Chat.ID != s.groupId {
+					glog.Infof("[ignored group %d] <%s> %v", update.Message.Chat.ID, update.Message.From, update.Message.Text)
 					continue
 				}
-				date := time.Unix(int64(u.Message.Date), 0)
+				date := time.Unix(int64(update.Message.Date), 0)
 				if time.Since(date) > 2*time.Minute {
-					glog.Infof("[old message] <%s> %v", u.Message.From, u.Message.Text)
+					glog.Infof("[old message] <%s> %v", update.Message.From, update.Message.Text)
 					continue
 				}
-				if msg := plainFromTelegram(s.tel.Self.ID, &u); msg != nil {
+				if msg := plainFromTelegram(s.tel.Self.ID, &update); msg != nil {
 					s.telLog <- msg
 				}
 			}
@@ -54,6 +56,7 @@
 // telegramLoop maintains a telegramConnection.
 func (s *server) telegramLoop(ctx context.Context) {
 	for {
+		glog.V(4).Info("telegram/debug4: Starting telegram connection loop")
 		err := s.telegramConnection(ctx)
 		if err == ctx.Err() {
 			glog.Infof("Telegram connection closing: %v", err)