Add telnet file with support to send and receive text from Merc MUD
[midgaard_bot.git] / sessions.go
1 /*
2 midgaard_bot, a Telegram bot which sets a bridge to Midgaard Merc MUD
3 Copyright (C) 2017 by Javier Sancho Fernandez <jsf at jsancho dot org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package main
20
21 import (
22         "context"
23
24         "github.com/go-telegram-bot-api/telegram-bot-api"
25         "github.com/reiver/go-telnet"
26 )
27
28 type Session struct {
29         Chat *tgbotapi.Chat
30         Input chan *tgbotapi.Message
31 }
32
33 var sessions map[int64]*Session
34 var mercHost string
35 var sessionsCtx context.Context
36
37 func initSessions(host string, ctx context.Context) error {
38         sessions = make(map[int64]*Session)
39         mercHost = host
40         sessionsCtx = ctx
41         return nil
42 }
43
44 func getSession(chat *tgbotapi.Chat) *Session {
45         session, ok := sessions[chat.ID]
46         if !ok {
47                 session = newSession(chat)
48         }
49         return session
50 }
51
52 func newSession(chat *tgbotapi.Chat) *Session {
53         session := Session{chat, make(chan *tgbotapi.Message)}
54         sessions[chat.ID] = &session
55         startSession(&session)
56         return &session
57 }
58
59 func startSession(session *Session) {
60         ctx, _ := context.WithCancel(sessionsCtx)
61
62         go func() {
63                 telnetInput, telnetOutput := make(chan string), make(chan string)
64                 caller := TelnetCaller{
65                         Input: telnetInput,
66                         Output: telnetOutput,
67                 }
68
69                 go func() {
70                         for {
71                                 select {
72                                 case msg := <-session.Input:
73                                         if msg.Text != "/start" {
74                                                 telnetInput <- msg.Text
75                                         }
76                                 case body := <-telnetOutput:
77                                         newMsg := tgbotapi.NewMessage(session.Chat.ID, body)
78                                         sendToTelegram(newMsg)
79                                 case <-ctx.Done():
80                                         return
81                                 }
82                         }
83                 }()
84
85                 telnet.DialToAndCall(mercHost, caller)
86         }()
87 }
88
89 func sendToSession(session *Session, message *tgbotapi.Message) {
90         session.Input <- message
91 }