Skip to content
This repository was archived by the owner on Sep 4, 2019. It is now read-only.

Commit 94c84b5

Browse files
committed
Merge branch 'develop'
2 parents f71da6c + 258e96b commit 94c84b5

File tree

8 files changed

+400
-194
lines changed

8 files changed

+400
-194
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
chadev-ircbot
22
*.swo
33
Chadev_ircbot
4+
.env

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,10 @@ devlunch url (date) (url) | Set live stream url for the dev lunch talks
9898
link to devlunch | Returns the link to the dev lunch live stream
9999
is `username` alive | Returns status of user
100100
\[groups\|meetups\] list | Lists all groups that are known to Ash
101-
\[groups\|meetups\] add (group name): (url) | Adds a new group to Ash
102101
\[group\|meetup\] details | Returns details about a group
103-
\[group\|meetup\] remove (group name) | Removes a group that Ash knows about
102+
`name`\[++|--\] | Adjusts the karma for a user or thing by one point
103+
karma stats `name` | Displays the current karma for the user or thing
104+
mods | Returns a list of channel mods currently online
104105

105106
## Contributing
106107

groups.go

+101-142
Original file line numberDiff line numberDiff line change
@@ -7,119 +7,107 @@ package main
77
import (
88
"encoding/json"
99
"fmt"
10+
"io/ioutil"
11+
"net/http"
1012
"strings"
1113

1214
"github.com/chadev/Chadev_ircbot/meetup"
1315
"github.com/danryan/hal"
16+
"github.com/texttheater/golang-levenshtein/levenshtein"
1417
)
1518

1619
// Groups contains data on the various dev groups.
1720
type Groups struct {
18-
// Name of the group
21+
Group []Group `json:"groups"`
22+
}
23+
24+
// Group contains data from the "groups" array in the JSON object.
25+
type Group struct {
26+
Name string `json:"name"`
27+
GitHub string `json:"github"`
28+
CodeofConduct string `json:"code-of-conduct"`
29+
Urls []URLs `json:"urls"`
30+
meetup string
31+
}
32+
33+
// URLs contains the name and url to the group website
34+
type URLs struct {
1935
Name string `json:"name"`
20-
// URL for the group page/meetup page
21-
URL string `json:"url"`
22-
// Meetup is the group name from the meetup URL
23-
// this is used for Meetup API calls.
24-
Meetup string `json:"meetup_name"`
36+
URL string `json:"url"`
2537
}
2638

27-
var groupListHandler = hear(`(groups|meetups) list`, "(groups|meetups) list", "Lists all groups that are known to Ash", func(res *hal.Response) error {
28-
groups, err := res.Robot.Store.Get("GROUPS")
39+
func parseGroups() (Groups, error) {
40+
var g Groups
41+
r, err := http.Get("http://chadev.com/groups.json")
2942
if err != nil {
30-
res.Send("I am currently unaware of any groups, try adding some")
31-
return err
43+
return g, err
44+
}
45+
defer r.Body.Close()
46+
47+
b, err := ioutil.ReadAll(r.Body)
48+
if err != nil {
49+
return g, err
3250
}
3351

34-
var g []Groups
35-
err = json.Unmarshal(groups, &g)
52+
err = json.Unmarshal(b, &g)
3653
if err != nil {
37-
hal.Logger.Errorf("error parsing JSON: %v", err)
38-
return res.Send("I had an error parsing the groups")
54+
return Groups{}, err
55+
}
56+
57+
return g, nil
58+
}
59+
60+
var groupListHandler = hear(`(groups|meetups) list`, "(groups|meetups) list", "Lists all groups that are known to Ash", func(res *hal.Response) error {
61+
g, err := parseGroups()
62+
if err != nil {
63+
hal.Logger.Errorf("failed parsing group list: %v", err)
64+
res.Send("Sorry, I encountered an error while parsing the groups list")
65+
return err
3966
}
4067

4168
var gn []string
42-
for _, val := range g {
69+
for _, val := range g.Group {
4370
gn = append(gn, val.Name)
4471
}
4572
names := strings.Join(gn, ", ")
4673

4774
return res.Send(fmt.Sprintf("Here is a list of groups: %s", names))
4875
})
4976

50-
var groupAddHandler = hear(`(groups|meetups) add (.+): (.+)`, "(groups|meetups) add [group name]: [group url]", "Adds a new group to Ash", func(res *hal.Response) error {
77+
var groupDetailsHandler = hear(`(group|meetup) details (.+)`, "(group|meetup) details [group name]", "Returns details about a group", func(res *hal.Response) error {
5178
name := res.Match[2]
52-
url := res.Match[3]
5379

54-
if name == "" {
55-
hal.Logger.Warn("no group name given")
56-
return res.Send("I need a name for the group to add it.")
57-
}
58-
if url == "" {
59-
hal.Logger.Warn("no group url given")
60-
return res.Send("I need the url for the groups webpage or meetup group")
80+
g, err := parseGroups()
81+
if err != nil {
82+
hal.Logger.Errorf("failed parsing group list: %v", err)
83+
res.Send("Sorry, I encountered an error while parsing the groups list")
84+
return err
6185
}
6286

63-
var g []Groups
64-
groups, err := res.Robot.Store.Get("GROUPS")
65-
if len(groups) > 0 {
66-
err := json.Unmarshal(groups, &g)
67-
if err != nil {
68-
hal.Logger.Errorf("faild to parse json: %v", err)
69-
return res.Send("Failed to parse groups list")
87+
group := searchGroups(g, name)
88+
for _, u := range group.Urls {
89+
if u.Name == "website" || u.Name == "meetup" {
90+
m := parseMeetupName(u.URL)
91+
if m != "" {
92+
group.meetup = m
93+
}
7094
}
7195
}
7296

73-
var meetupName string
74-
if strings.Contains(url, "meetup.com") {
75-
meetupName = parseMeetupName(url)
76-
}
77-
78-
g = append(g, Groups{Name: name, URL: url, Meetup: meetupName})
79-
groups, err = json.Marshal(g)
80-
if err != nil {
81-
hal.Logger.Errorf("faild to build json: %v", err)
82-
return res.Send("Failed write updated groups list")
83-
}
84-
err = res.Robot.Store.Set("GROUPS", groups)
85-
if err != nil {
86-
hal.Logger.Error(err)
87-
return res.Send("Failed writing to the datastore")
88-
}
89-
90-
return res.Send("Added new group")
91-
})
92-
93-
var groupDetailsHandler = hear(`(group|meetup) details (.+)`, "(group|meetup) details [group name]", "Returns details about a group", func(res *hal.Response) error {
94-
name := res.Match[2]
95-
96-
var g []Groups
97-
groups, _ := res.Robot.Store.Get("GROUPS")
98-
if len(groups) > 0 {
99-
err := json.Unmarshal(groups, &g)
97+
var nextEvent string
98+
if group.meetup != "" {
99+
nextEvent, err = meetup.GetNextMeetup(group.meetup)
100100
if err != nil {
101-
hal.Logger.Errorf("faild to parse json: %v", err)
102-
return res.Send("Failed to parse groups list")
101+
hal.Logger.Errorf("failed fetching event from meetup.com: %v", err)
103102
}
104103
}
105104

106-
if len(groups) == 0 {
107-
hal.Logger.Error("no groups currently defined")
108-
return res.Send("I currently don't know of any groups, try adding some first")
109-
}
110-
111-
group := searchGroups(g, strings.ToLower(name))
112-
if group.Name == "" {
113-
hal.Logger.Warnf("no group with the name %s found", name)
114-
return res.Send(fmt.Sprintf("I could not find a group with the name %s", name))
105+
var urls []string
106+
for _, u := range group.Urls {
107+
urls = append(urls, u.URL)
115108
}
116-
117-
nextEvent, err := meetup.GetNextMeetup(group.Meetup)
118-
if err != nil {
119-
hal.Logger.Errorf("failed fetching event from meetup.com: %v", err)
120-
}
121-
122-
res.Send(fmt.Sprintf("Group name: %s URL: %s", group.Name, group.URL))
109+
ul := strings.Join(urls, ", ")
110+
res.Send(fmt.Sprintf("Group name: %s URL: %s", group.Name, ul))
123111
if nextEvent != "" {
124112
res.Send(nextEvent)
125113
}
@@ -130,31 +118,32 @@ var groupDetailsHandler = hear(`(group|meetup) details (.+)`, "(group|meetup) de
130118
var groupRSVPHandler = hear(`(group|meetup) rsvps (.+)`, "(group|meetup) rsvps [group name]", "Gets the RSVP count for the named group's next meeting", func(res *hal.Response) error {
131119
name := res.Match[2]
132120

133-
var g []Groups
134-
groups, _ := res.Robot.Store.Get("GROUPS")
135-
if len(groups) > 0 {
136-
err := json.Unmarshal(groups, &g)
137-
if err != nil {
138-
hal.Logger.Errorf("faild to parse json: %v", err)
139-
return res.Send("Failed to parse groups list")
140-
}
121+
g, err := parseGroups()
122+
if err != nil {
123+
hal.Logger.Errorf("failed parsing group list: %v", err)
124+
res.Send("Sorry, I encountered an error while parsing the groups list")
125+
return err
141126
}
142127

143-
if len(groups) == 0 {
144-
hal.Logger.Error("no groups currently defined")
145-
return res.Send("I currently don't know of any groups, try adding some first")
128+
group := searchGroups(g, name)
129+
for _, u := range group.Urls {
130+
if u.Name == "website" || u.Name == "meetup" {
131+
m := parseMeetupName(u.URL)
132+
if m != "" {
133+
group.meetup = m
134+
}
135+
}
146136
}
147137

148-
group := searchGroups(g, strings.ToLower(name))
149-
if group.Name == "" {
150-
hal.Logger.Warnf("no group with the name %s found", name)
151-
return res.Send(fmt.Sprintf("I could not find a group with the name %s", name))
138+
if group.meetup == "" {
139+
res.Send(fmt.Sprintf("%s is using an unsupported event system, can't fetch RSVP information", group.Name))
140+
return nil
152141
}
153142

154-
rsvp, err := meetup.GetMeetupRSVP(group.Meetup)
143+
rsvp, err := meetup.GetMeetupRSVP(group.meetup)
155144
if err != nil {
156-
hal.Logger.Errorf("failed feching RSVP information: %v", err)
157-
res.Send("I was unable to fetch the latest RSVP information for this group")
145+
hal.Logger.Errorf("failed fetching RSVP information: %v", err)
146+
res.Send("I was unable to fetch the latest RSVP informaion for this group")
158147
return err
159148
}
160149

@@ -164,64 +153,34 @@ var groupRSVPHandler = hear(`(group|meetup) rsvps (.+)`, "(group|meetup) rsvps [
164153
res.Send("There are either no upcoming events or no RSVP for the event yet")
165154
}
166155

167-
return err
168-
})
169-
170-
var groupRemoveHandler = hear(`(group|meetup) remove (.+)`, "(group|meetup) remove [group name]", "Removes a group that ash knows about", func(res *hal.Response) error {
171-
name := res.Match[2]
172-
173-
var g []Groups
174-
groups, err := res.Robot.Store.Get("GROUPS")
175-
if err != nil {
176-
hal.Logger.Error("no groups currently in the datastore")
177-
res.Send("Sorry I don't know of any groups.")
178-
return err
179-
}
180-
181-
err = json.Unmarshal(groups, &g)
182-
if err != nil {
183-
hal.Logger.Errorf("couldn't unmarshal json: %v", err)
184-
res.Send("Sorry I was unable to parse the json object")
185-
return err
186-
}
187-
188-
for i, group := range g {
189-
if group.Name == name {
190-
// remove the group from the slice
191-
var e Groups
192-
g[len(g)-1], g = e, append(g[:i], g[i+1:]...)
193-
}
194-
}
195-
groups, err = json.Marshal(g)
196-
if err != nil {
197-
hal.Logger.Errorf("couldn't marshal json: %v", err)
198-
res.Send("Sorry I was unable to generate json object")
199-
return err
200-
}
201-
err = res.Robot.Store.Set("GROUPS", groups)
202-
if err != nil {
203-
hal.Logger.Errorf("error writing to datastore: %v", err)
204-
res.Send("Sorry I was unable to update group listing")
205-
return err
206-
}
207-
208-
return res.Send("Group list updated")
156+
return nil
209157
})
210158

211159
func parseMeetupName(u string) string {
212160
// meetup URLs are structured as www.meetup.com/(group name)
161+
u = strings.TrimSuffix(u, "/") // trim trailing slash if present
213162
parts := strings.Split(u, "/")
214163

215164
return parts[len(parts)-1]
216165
}
217166

218-
func searchGroups(g []Groups, n string) Groups {
219-
var group Groups
220-
for _, val := range g {
221-
if strings.ToLower(val.Name) == n {
222-
group = val
167+
func searchGroups(g Groups, n string) Group {
168+
distance := int(^uint(0) >> 1) // nitialize to "infinity"
169+
var idx int
170+
n = strings.ToUpper(strings.TrimSpace(n))
171+
172+
for i := 0; i < len(g.Group); i++ {
173+
cleanGroup := strings.ToUpper(strings.TrimSpace(g.Group[i].Name))
174+
if n == cleanGroup {
175+
return g.Group[i]
176+
}
177+
178+
newdistance := levenshtein.DistanceForStrings([]rune(n), []rune(cleanGroup), levenshtein.DefaultOptions)
179+
if newdistance < distance {
180+
distance = newdistance
181+
idx = i
223182
}
224183
}
225184

226-
return group
185+
return g.Group[idx]
227186
}

isalive.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ import (
1212

1313
var isAliveHandler = hear(`is ([A-Za-z0-9\-_\{\}\[\]\\\s]+) alive`, "is (name) alive", "Find out if a user is alive", func(res *hal.Response) error {
1414
name := res.Match[1]
15-
res.Send(fmt.Sprintf("I can't find %s's heartbeat..", name))
16-
res.Send("But let's not jump to conclusions")
15+
_, err := res.Robot.Users.Get(name)
16+
if err != nil {
17+
res.Send(fmt.Sprintf("I can't find %s's heartbeat..", name))
18+
res.Send("But let's not jump to conclusions")
19+
} else {
20+
res.Reply(fmt.Sprintf("I found %s's heartbeat, all is good", name))
21+
}
22+
1723
return nil
1824
})

0 commit comments

Comments
 (0)