Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27d3a48d98 | ||
|
|
9065248d1c |
11
README.md
11
README.md
@@ -8,10 +8,13 @@ A command line interface for whatsapp, based on [go-whatsapp](https://github.com
|
||||
|
||||
Things that work.
|
||||
|
||||
- Sending and receiving WhatsApp messages in a command line app
|
||||
- Connects through the Web App API without a browser
|
||||
- Allows sending and receiving WhatsApp messages in a command line app
|
||||
- Allows downloading and opening image/video/audio/document attachments
|
||||
- Uses QR code for simple setup
|
||||
- Allows downloading and opening image/video/audio/document attachments
|
||||
- Allows sending documents
|
||||
- Allows color customization
|
||||
- Supports desktop notifications
|
||||
- Binaries for Windows, Mac, Linux and RaspBerry Pi
|
||||
|
||||
### Caveats
|
||||
@@ -19,10 +22,8 @@ Things that work.
|
||||
This is a WIP and mainly meant for my personal use. Heres some things you might expect to work that don't. Plus some other things I should mention.
|
||||
|
||||
- Only shows existing chats
|
||||
- Only fetches a few old messages
|
||||
- No incoming message notification / count
|
||||
- No unread message count
|
||||
- No proper connection drop handling
|
||||
- No uploading of images/video/audio/data
|
||||
- FaceBook obviously doesn't endorse or like these kinds of apps and they're likely to break when FaceBook changes stuff in their web app
|
||||
|
||||
## Installation / Usage
|
||||
|
||||
@@ -22,9 +22,11 @@ type IniFile struct {
|
||||
}
|
||||
|
||||
type General struct {
|
||||
DownloadPath string
|
||||
PreviewPath string
|
||||
CmdPrefix string
|
||||
DownloadPath string
|
||||
PreviewPath string
|
||||
CmdPrefix string
|
||||
EnableNotifications bool
|
||||
NotificationTimeout int64
|
||||
}
|
||||
|
||||
type Keymap struct {
|
||||
@@ -64,9 +66,11 @@ type Colors struct {
|
||||
|
||||
var Config = IniFile{
|
||||
&General{
|
||||
DownloadPath: GetHomeDir() + "Downloads",
|
||||
PreviewPath: GetHomeDir() + "Downloads",
|
||||
CmdPrefix: "/",
|
||||
DownloadPath: GetHomeDir() + "Downloads",
|
||||
PreviewPath: GetHomeDir() + "Downloads",
|
||||
CmdPrefix: "/",
|
||||
EnableNotifications: false,
|
||||
NotificationTimeout: 60,
|
||||
},
|
||||
&Keymap{
|
||||
SwitchPanels: "Tab",
|
||||
|
||||
1
go.mod
1
go.mod
@@ -7,6 +7,7 @@ require (
|
||||
github.com/adrg/xdg v0.2.3
|
||||
github.com/gabriel-vasile/mimetype v1.1.2
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591
|
||||
github.com/gen2brain/beeep v0.0.0-20200526185328-e9c15c258e28
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@@ -20,9 +20,14 @@ github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pm
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell/v2 v2.0.0-dev/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.0.0/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gen2brain/beeep v0.0.0-20200526185328-e9c15c258e28 h1:M2Zt3G2w6Q57GZndOYk42p7RvMeO8izO8yKTfIxGqxA=
|
||||
github.com/gen2brain/beeep v0.0.0-20200526185328-e9c15c258e28/go.mod h1:ElSskYZe3oM8kThaHGJ+kiN2yyUMVXMZ7WxF9QqLDS8=
|
||||
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE=
|
||||
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10=
|
||||
github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -41,7 +46,11 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherwasm v1.1.0 h1:fA2uLoctU5+T3OhOn2vYP0DVT6pxc7xhTlBB1paATqQ=
|
||||
github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
@@ -57,6 +66,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -73,6 +84,8 @@ github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EE
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
||||
gitlab.com/tslocum/cbind v0.1.4 h1:cbZXPPcieXspk8cShoT6efz7HAT8yMNQcofYWNizis4=
|
||||
gitlab.com/tslocum/cbind v0.1.4/go.mod h1:RvwYE3auSjBNlCmWeGspzn+jdLUVQ8C2QGC+0nP9ChI=
|
||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -101,6 +114,7 @@ golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
|
||||
13
main.go
13
main.go
@@ -15,7 +15,7 @@ import (
|
||||
"gitlab.com/tslocum/cbind"
|
||||
)
|
||||
|
||||
var VERSION string = "v0.8.6"
|
||||
var VERSION string = "v0.8.7"
|
||||
|
||||
var sndTxt string = ""
|
||||
var currentReceiver string = ""
|
||||
@@ -509,17 +509,6 @@ func UpdateStatusBar(statusInfo messages.SessionStatus) {
|
||||
//infoBar.SetText("🔋: ??%")
|
||||
}
|
||||
|
||||
// notifies about a new message if its recent
|
||||
//func NotifyMsg(msg whatsapp.TextMessage) {
|
||||
//if int64(msg.Info.Timestamp) > time.Now().Unix()-30 {
|
||||
//fmt.Print("\a")
|
||||
//err := beeep.Notify(messages.GetIdName(msg.Info.RemoteJid), msg.Text, "")
|
||||
//if err != nil {
|
||||
// fmt.Fprintln(textView, "[red]error in notification[-]")
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
// sets the current contact, loads text from storage to TextView
|
||||
func SetDisplayedContact(wid string) {
|
||||
currentReceiver = wid
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/gen2brain/beeep"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
@@ -70,6 +71,7 @@ type SessionManager struct {
|
||||
TextChannel chan whatsapp.TextMessage
|
||||
OtherChannel chan interface{}
|
||||
statusInfo SessionStatus
|
||||
lastSent time.Time
|
||||
}
|
||||
|
||||
func (sm *SessionManager) Init(handler UiMessageHandler) {
|
||||
@@ -103,6 +105,25 @@ func (sm *SessionManager) StartManager() error {
|
||||
screen, ids := sm.db.GetMessagesString(sm.currentReceiver)
|
||||
sm.uiHandler.NewScreen(screen, ids)
|
||||
}
|
||||
// notify if contact is in focus and we didn't send a message recently
|
||||
if config.Config.General.EnableNotifications {
|
||||
if int64(msg.Info.Timestamp) > sm.lastSent.Unix()+config.Config.General.NotificationTimeout {
|
||||
err := beeep.Notify(GetIdShort(msg.Info.RemoteJid), msg.Text, "")
|
||||
if err != nil {
|
||||
sm.uiHandler.PrintError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if config.Config.General.EnableNotifications {
|
||||
// notify if message is younger than 30 sec and not in focus
|
||||
if int64(msg.Info.Timestamp) > time.Now().Unix()-30 {
|
||||
err := beeep.Notify(GetIdShort(msg.Info.RemoteJid), msg.Text, "")
|
||||
if err != nil {
|
||||
sm.uiHandler.PrintError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sm.uiHandler.SetContacts(sm.db.GetContactIds())
|
||||
case other := <-sm.OtherChannel:
|
||||
@@ -307,6 +328,7 @@ func (sm *SessionManager) execCommand(command Command) {
|
||||
Content: file,
|
||||
}
|
||||
wac := sm.getConnection()
|
||||
sm.lastSent = time.Now()
|
||||
_, err := wac.Send(msg)
|
||||
if err != nil {
|
||||
sm.uiHandler.PrintError(err)
|
||||
@@ -460,7 +482,7 @@ func (sm *SessionManager) downloadMessage(wid string, preview bool) (string, err
|
||||
}
|
||||
|
||||
// sends text to whatsapp id
|
||||
func (sm SessionManager) sendText(wid string, text string) {
|
||||
func (sm *SessionManager) sendText(wid string, text string) {
|
||||
msg := whatsapp.TextMessage{
|
||||
Info: whatsapp.MessageInfo{
|
||||
RemoteJid: wid,
|
||||
@@ -470,6 +492,7 @@ func (sm SessionManager) sendText(wid string, text string) {
|
||||
Text: text,
|
||||
}
|
||||
|
||||
sm.lastSent = time.Now()
|
||||
_, err := sm.getConnection().Send(msg)
|
||||
if err != nil {
|
||||
sm.uiHandler.PrintError(err)
|
||||
|
||||
Reference in New Issue
Block a user