Files
whatscli/main.go
2020-11-16 01:49:58 +01:00

289 lines
7.0 KiB
Go

package main
import (
"fmt"
"github.com/Rhymen/go-whatsapp"
"github.com/gdamore/tcell/v2"
"github.com/normen/whatscli/messages"
"github.com/rivo/tview"
"strings"
"time"
)
type textHandler struct{}
type waMsg struct {
Wid string
Text string
}
const CONTACTSUFFIX = "@s.whatsapp.net"
var sendChannel chan waMsg
var textChannel chan whatsapp.TextMessage
var sndTxt string = ""
var currentReceiver string = ""
var textView *tview.TextView
var treeView *tview.TreeView
var textInput *tview.InputField
var topBar *tview.TextView
var connection *whatsapp.Conn
var msgStore messages.MessageDatabase
var contactRoot *tview.TreeNode
var handler textHandler
var app *tview.Application
//var messages map[string]string
func main() {
msgStore = messages.MessageDatabase{}
msgStore.Init()
messages.LoadContacts()
//messages.SetIdName("491732457387"+CONTACTSUFFIX, "Normen")
//messages.SetIdName("4917622723621"+CONTACTSUFFIX, "Lilou")
app = tview.NewApplication()
gridLayout := tview.NewGrid()
gridLayout.SetRows(1, 0, 1)
gridLayout.SetColumns(30, 0, 30)
gridLayout.SetBorders(true)
//list := tview.NewList()
////list.SetTitle("Contacts")
////list.AddItem("List Contacts", "get the contacts", 'a', func() {
//// list.Clear()
//// var ids = msgStore.GetContactIds()
//// for _, element := range ids {
//// //fmt.Fprint(textView, "\n"+element)
//// var elem = element
//// list.AddItem(messages.GetIdName(element), "", '-', func() {
//// currentReceiver = elem
//// textView.Clear()
//// textView.SetText(msgStore.GetMessagesString(elem))
//// fmt.Fprint(textView, "\nNeuer Empfänger: ", elem)
//// })
//// }
////})
//list.ShowSecondaryText(false)
//list.AddItem("Load", "Load Contacts", 'l', LoadContacts)
//list.AddItem("Quit", "Press to exit", 'q', func() {
// app.Stop()
//})
topBar = tview.NewTextView()
topBar.SetDynamicColors(true)
topBar.SetText("[::b] WhatsCLI v0.1.0 [-][::d]Help: /name [Name] = name contact | /quit = exit app | /load = reload contacts | <Tab> = switch input/tree | <Pgup/dn> = scroll history")
textView = tview.NewTextView().
SetDynamicColors(true).
SetRegions(true).
SetWordWrap(true).
SetChangedFunc(func() {
app.Draw()
})
//textView.SetBorder(true)
textInput = tview.NewInputField()
textInput.SetChangedFunc(func(change string) {
sndTxt = change
})
textInput.SetDoneFunc(EnterCommand)
textInput.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyTab {
app.SetFocus(treeView)
return nil
}
if event.Key() == tcell.KeyPgDn {
offset, _ := textView.GetScrollOffset()
offset += 10
textView.ScrollTo(offset, 0)
return nil
}
if event.Key() == tcell.KeyPgUp {
offset, _ := textView.GetScrollOffset()
offset -= 10
textView.ScrollTo(offset, 0)
return nil
}
return event
})
gridLayout.AddItem(topBar, 0, 0, 1, 4, 0, 0, false)
gridLayout.AddItem(MakeTree(), 1, 0, 2, 1, 0, 0, false)
gridLayout.AddItem(textView, 1, 1, 1, 3, 0, 0, false)
gridLayout.AddItem(textInput, 2, 1, 1, 3, 0, 0, false)
app.SetRoot(gridLayout, true)
app.EnableMouse(true)
app.SetFocus(textInput)
go func() {
if err := StartTextReceiver(); err != nil {
fmt.Fprint(textView, err)
}
}()
app.Run()
}
func EnterCommand(key tcell.Key) {
if sndTxt == "" {
return
}
if sndTxt == "/load" {
//command
LoadContacts()
textInput.SetText("")
return
}
if sndTxt == "/quit" {
//command
app.Stop()
return
}
if currentReceiver == "" {
fmt.Fprint(textView, "\nNo recipient set")
return
}
if strings.Index(sndTxt, "/name ") == 0 {
//command
messages.SetIdName(currentReceiver, strings.TrimPrefix(sndTxt, "/name "))
SetDisplayedContact(currentReceiver)
LoadContacts()
textInput.SetText("")
return
}
// send message
msg := waMsg{
Wid: currentReceiver,
Text: sndTxt,
}
sendChannel <- msg
textInput.SetText("")
}
func MakeTree() *tview.TreeView {
rootDir := "Contacts"
contactRoot = tview.NewTreeNode(rootDir).
SetColor(tcell.ColorRed)
treeView = tview.NewTreeView().
SetRoot(contactRoot).
SetCurrentNode(contactRoot)
// If a contact was selected, open it.
treeView.SetChangedFunc(func(node *tview.TreeNode) {
reference := node.GetReference()
if reference == nil {
return // Selecting the root node does nothing.
}
children := node.GetChildren()
if len(children) == 0 {
// Load and show files in this directory.
recv := reference.(string)
SetDisplayedContact(recv)
} else {
// Collapse if visible, expand if collapsed.
node.SetExpanded(!node.IsExpanded())
}
})
treeView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyTab {
app.SetFocus(textInput)
return nil
}
return event
})
return treeView
}
func LoadContacts() {
var ids = msgStore.GetContactIds()
contactRoot.ClearChildren()
for _, element := range ids {
node := tview.NewTreeNode(messages.GetIdName(element)).
SetReference(element).
SetSelectable(true)
if strings.Count(element, CONTACTSUFFIX) > 0 {
node.SetColor(tcell.ColorGreen)
} else {
node.SetColor(tcell.ColorBlue)
}
contactRoot.AddChild(node)
}
}
func SetDisplayedContact(wid string) {
currentReceiver = wid
textView.Clear()
textView.SetTitle(messages.GetIdName(wid))
textView.SetText(msgStore.GetMessagesString(wid))
}
// HandleError implements the handler interface for go-whatsapp
func (t textHandler) HandleError(err error) {
// TODO : handle go routine here
fmt.Fprint(textView, "\nerror in textHandler : %v", err)
return
}
// HandleTextMessage implements the text message handler interface for go-whatsapp
func (t textHandler) HandleTextMessage(msg whatsapp.TextMessage) {
textChannel <- msg
if msg.Info.RemoteJid != currentReceiver {
return
}
PrintTextMessage(msg)
}
func PrintTextMessage(msg whatsapp.TextMessage) {
fmt.Fprint(textView, messages.GetTextMessageString(&msg))
}
// StartTextReceiver starts the handler for the text messages received
func StartTextReceiver() error {
var wac = GetConnection()
err := LoginWithConnection(wac)
if err != nil {
return fmt.Errorf("%v\n", err)
}
handler = textHandler{}
wac.AddHandler(handler)
sendChannel = make(chan waMsg)
textChannel = make(chan whatsapp.TextMessage)
for {
select {
case msg := <-sendChannel:
SendText(msg.Wid, msg.Text)
case rcvd := <-textChannel:
if msgStore.AddTextMessage(rcvd) {
app.QueueUpdateDraw(LoadContacts)
}
}
}
fmt.Fprint(textView, "\n"+"closing the receiver")
wac.Disconnect()
return nil
}
func SendText(wid string, text string) {
msg := whatsapp.TextMessage{
Info: whatsapp.MessageInfo{
RemoteJid: wid,
FromMe: true,
Timestamp: uint64(time.Now().Unix()),
},
Text: text,
}
PrintTextMessage(msg)
//TODO: workaround for error when receiving&sending
connection.RemoveHandlers()
_, err := connection.Send(msg)
msgStore.AddTextMessage(msg)
connection.AddHandler(handler)
if err != nil {
fmt.Fprint(textView, "\nerror sending message: %v", err)
} else {
//fmt.Fprint(textView, "\nSent msg with ID: %v", msgID)
}
}