func (r bot) teamInfo(p *robots.Payload, cmd utils.Command) error { teamID := cmd.Arg(0) if teamID == "" { return errors.New("Missing team name. Use `!github teaminfo <team>`") } client, err := r.getClient(p.UserName) if err != nil { return err } id, err := strconv.Atoi(teamID) if err != nil { return err } team, _, err := client.Organizations.GetTeam(id) if err != nil { return err } s := "Members for *" + *team.Name + "*:\n" // opts := &OrganizationListTeamMembersOptions{} users, _, err := client.Organizations.ListTeamMembers(id, nil) if err != nil { return err } for _, u := range users { s += fmt.Sprintf("- %s\n", *u.Login) } r.handler.Send(p, s) return nil }
func (r bot) sendProjects(payload *robots.Payload, cmd utils.Command) error { var ps []pivotal.Project var err error term := cmd.Arg(0) pvt, err := conn(payload.UserName) if err != nil { return err } s := "Projects" if len(term) > 0 { fmt.Printf("Retrieving projects with term \"%s\"...\n\n", term) s += fmt.Sprintf(" matching '%s':\n", term) // ps, err = pvt.SearchProject(term) } else { s += ":\n" fmt.Println("Retrieving projects...\n") ps, err = pvt.Projects() } if err != nil { msg := fmt.Sprintf("Error: %s", err.Error()) r.handler.Send(payload, msg) return nil } r.handler.Send(payload, s+projectTable(ps)) return nil }
func (r bot) addToTeam(p *robots.Payload, cmd utils.Command) error { user := cmd.Arg(0) if user == "" { return errors.New("Missing user name. Use `!github addtoteam <user> <team>`") } team := cmd.Arg(1) if team == "" { return errors.New("Missing team name. Use `!github addtoteam <user> <team>`") } // role := "member" client, err := r.getClient(p.UserName) if err != nil { return err } id, err := strconv.Atoi(team) if err != nil { return err } _, _, err = client.Organizations.AddTeamMembership(id, user) if err != nil { return err } r.handler.Send(p, "User *"+user+"* added to team.") return nil }
func (r bot) addTime(p *robots.Payload, cmd utils.Command) error { args, err := cmd.ParseArgs("mavenlink-id", "time-in-hours") if err != nil { return err } mvnID, timeStr := args[0], args[1] hours, err := strconv.ParseFloat(timeStr, 64) if err != nil { return err } mvn, err := mavenlink.NewFor(p.UserName) if err != nil { return err } story, err := mvn.GetStory(mvnID) if err != nil { return err } minutes := int(hours * 60) _, err = mvn.AddTimeEntry(story, minutes) if err != nil { return err } r.handler.Send(p, fmt.Sprintf("Added *%.1f* hours to story *%s - %s*", hours, story.Id, story.Title)) return nil }
func (r bot) rename(p *robots.Payload, cmd utils.Command) error { old := cmd.Arg(0) new := cmd.Arg(1) if new == "" || old == "" { r.handler.Send(p, "You need to provide the old and new name. Usage: `!project rename <old-name> <new-name>`") return nil } pr, err := db.GetProjectByName(old) if err != nil { return err } if pr == nil { r.handler.Send(p, "Project *"+old+"* not found.") return nil } pr.Name = new err = db.UpdateProject(*pr) if err != nil { return err } r.handler.Send(p, "Project *"+old+"* renamed to *"+new+"*") return nil }
func (r bot) assign(p *robots.Payload, cmd utils.Command) error { res, err := cmd.ParseArgs("pivotal-story-id", "username") if err != nil { return err } storyId, username := res[0], res[1] pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } user, err := db.GetUserByName(username) if err != nil { return err } if user == nil { return errors.New("User *" + username + "* not found") } story, err := pvt.AssignStory(storyId, *user.PivotalId) if err != nil { return err } s := "Story successfully updated:\n" r.handler.SendWithAttachments(p, s, []robots.Attachment{ utils.FmtAttachment("", story.Name, story.Url, ""), }) return nil }
func (r bot) estimate(p *robots.Payload, cmd utils.Command) error { args, err := cmd.ParseArgs("pivotal-id", "estimate") if err != nil { return err } pvtId, estimate := args[0], args[1] pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } // pvtStory, err := pvt.GetStory(pvtId) // if err != nil { // return err // } // numEstimate, err := strconv.Atoi(estimate) if err != nil { return err } story, err := pvt.EstimateStory(pvtId, numEstimate) if err != nil { return err } s := "Story successfully updated:\n" r.handler.SendWithAttachments(p, s, []robots.Attachment{ utils.FmtAttachment("", story.Name, story.Url, ""), }) return nil }
func (r bot) users(p *robots.Payload, cmd utils.Command) error { projectId := cmd.Arg(0) if projectId == "" { r.handler.Send(p, "Missing project id. Use !pvt users <project-id>") return nil } pvt, err := conn(p.UserName) if err != nil { return err } project, err := pvt.GetProject(projectId) if err != nil { return err } if project == nil { r.handler.Send(p, "Project with id "+projectId+" doesn't exist.") return nil } memberships, err := pvt.GetProjectMemberships(projectId) if err != nil { return err } s := "Current users for project *" + project.Name + "*:\n" for _, m := range memberships { pp := m.Person s += fmt.Sprintf("%d - %s (%s)\n", pp.Id, pp.Name, pp.Email) } r.handler.Send(p, s) return nil }
func (r bot) unassigned(p *robots.Payload, cmd utils.Command) error { res, err := cmd.ParseArgs("project") if err != nil { return err } name := res[0] pr, err := getProject(name) if err != nil { return err } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } msg := "Unassigned stories for *" + name + "*:\n" stories, err := pvt.GetUnassignedStories(pr.StrPivotalId()) if len(stories) < 1 { r.handler.Send(p, "No unassigned stories for *"+name+"*") return nil } for _, s := range stories { msg += fmt.Sprintf("%d - %s\n", s.Id, s.Name) } r.handler.Send(p, msg) return nil }
func (r bot) set(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { r.handler.Send(p, "Missing Slack user name. Use `!user set <user-name> [mvn:<mavenlink-id>] [pvt:<pivotal-id>]`") return nil } mvnId := cmd.Param("mvn") pvtId := cmd.Param("pvt") user := db.User{Name: name} if mvnId != "" { mvnInt, err := strconv.ParseInt(mvnId, 10, 64) if err != nil { return err } user.MavenlinkId = &mvnInt } if pvtId != "" { pvtInt, err := strconv.ParseInt(pvtId, 10, 64) if err != nil { return err } user.PivotalId = &pvtInt } if err := db.SaveUser(user); err != nil { return err } r.handler.Send(p, "User *"+name+"* saved") return nil }
func (r bot) startStory(p *robots.Payload, cmd utils.Command) error { title := cmd.StrFrom(0) session, err := db.GetCurrentSession(p.ChannelName) if err != nil { return err } if session == nil { r.handler.Send(p, "No active poker session on *"+p.ChannelName+"*. Use `/poker session` to start a new session.") return nil } story, err := session.GetCurrentStory() if err != nil { return err } if story != nil { r.handler.Send(p, "Cannot start a new story until you estimate *"+story.Title+"*") return nil } err = session.StartPokerStory(title) if err != nil { return err } r.handler.Send(p, "We can now vote for *"+title+"*") return nil }
func StopTimer(bot *UserBot, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { return errors.New("Missing timer name") } timer, err := db.GetStartedTimerByName(bot.lastMessage.User.Name, name) if err != nil { return err } if timer == nil { return errors.New("You have no started timer with name *" + name + "*") } err = timer.Stop() if err != nil { return err } timer, err = timer.Reload() if err != nil { return err } bot.reply("Your timer *" + name + "* has stopped. It ran for *" + timer.Duration() + "*.") return nil }
func (r bot) members(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { err := errors.New( "Missing project name. Use `!project addtask <project> <task-name>`") return err } pr, err := getProject(name) if err != nil { return err } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } if pr == nil { r.handler.Send(p, "Project *"+name+"* not found") return nil } members, err := pvt.GetProjectMemberships(pr.StrPivotalId()) if err != nil { return err } s := "Pivotal members for project *" + pr.Name + "*:\n" for _, m := range members { s += fmt.Sprintf("%d - %s\n", m.Person.Id, m.Person.Name) } r.handler.Send(p, s) return nil }
func (r bot) startTask(p *robots.Payload, cmd utils.Command) error { // pr, err := getProject(cmd.Arg(0)) // if err != nil { // return err // } mvn, err := mavenlink.NewFor(p.UserName) if err != nil { return err } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } if storyId := cmd.Arg(0); storyId != "" { pvtStory, err := pvt.GetStory(storyId) if err != nil { return err } pvtStory, err = pvt.SetStoryState(pvtStory.GetStringId(), "started") if err != nil { return err } if mvnId := pvtStory.GetMavenlinkId(); mvnId != "" { mvnStory, err := mvn.GetStory(mvnId) if err != nil { return err } fmt.Printf(" ** Got story: %+v\n", mvnStory) mvnStory.State = "started" mvnStory, err = mvn.SetStoryState(mvnStory.Id, "started") if err != nil { return err } } r.handler.Send(p, "Story *"+pvtStory.Name+"* started") return nil } // stories, err := mvn.ChildStories(pr.MvnSprintStoryId) // if err != nil { // return err // } // r.handler.Send(p, "Click the story you want to start on *"+pr.Name+"*:") // url := os.Getenv("APP_URL") // atts := mavenlink.CustomFormatStories(stories, url+"selection/startTask/") // for _, a := range atts { // r.handler.SendWithAttachments(p, "", []robots.Attachment{a}) // } return nil }
func (r bot) myStories(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) var pr *db.Project var err error if name == "" { pr, err = db.GetProjectByChannel(p.ChannelName) } else { pr, err = db.GetProjectByName(name) } if err != nil { return err } if pr == nil { r.handler.Send(p, "Missing project name.") return nil } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } user, err := db.GetUserByName(p.UserName) if err != nil { return err } filter := map[string]string{ "owned_by": user.StrPivotalId(), "state": "started,finished", } stories, err := pvt.FilteredStories(pr.StrPivotalId(), filter) if err != nil { return err } if len(stories) < 1 { r.handler.Send(p, "No open stories in project *"+pr.Name+"* for *"+p.UserName+"*") return nil } str := "Current stories in project *" + pr.Name + "* for *" + p.UserName + "*:\n" atts := []robots.Attachment{} for _, s := range stories { fallback := fmt.Sprintf("%d - %s - %s\n", s.Id, s.Name, s.State) title := fmt.Sprintf("%d - %s\n", s.Id, s.Name) a := utils.FmtAttachment(fallback, title, s.Url, s.State) atts = append(atts, a) } r.handler.SendWithAttachments(p, str, atts) return nil }
func (r bot) create(p *robots.Payload, cmd utils.Command) error { alias := cmd.Arg(0) if alias == "" { r.handler.Send(p, "Missing project alias. Usage: `!project createproject <alias> <long-name>`") return nil } name := cmd.StrFrom(1) if name == "" { r.handler.Send(p, "Missing project name. Usage: `!project createproject <alias> <long-name>`") return nil } mvn, err := mavenlink.NewFor(p.UserName) if err != nil { return err } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } pvtProject := pivotal.Project{ Name: name, // PointScale: "1,2,3,4,5,6,7,8,9,10,16,20", } pvtNewProject, err := pvt.CreateProject(pvtProject) if err != nil { return err } mvnProject := mavenlink.Project{ Title: name, Description: fmt.Sprintf("[pvt:%s]", pvtNewProject.Id), CreatorRole: "maven", } mvnNewProject, err := mvn.CreateProject(mvnProject) if err != nil { return err } if mvnNewProject == nil { return errors.New("Mavenlink returned a nil project") } pvtNewProject.Description = "[mvn:" + mvnNewProject.Id + "]" pvtNewProject, err = pvt.UpdateProject(*pvtNewProject) if err != nil { return err } err = r.makeLink(p, alias, mvnNewProject.Id, strconv.FormatInt(pvtNewProject.Id, 10)) if err != nil { return err } r.handler.Send(p, "Project *"+name+"* created on Pivotal and Mavenlink.") return nil }
func (r bot) vote(p *robots.Payload, cmd utils.Command) error { args, err := cmd.ParseArgs("vote") if err != nil { return err } vote := args[0] session, err := db.GetCurrentSession(p.ChannelName) if err != nil { return err } if session == nil { r.handler.Send(p, "No active poker session on *"+p.ChannelName+"*. Use `/poker session` to start a new session.") return nil } story, err := session.GetCurrentStory() if err != nil { return err } if story == nil { r.handler.Send(p, "No current story on *"+p.ChannelName+"*. Use `/poker story` to start a new session.") return nil } err = story.CastVote(p.UserName, vote) if err != nil { return err } r.handler.Send(p, "Vote cast for *"+p.UserName+"*") users := session.Users if users != "" { expUsers := strings.Split(users, ",") votes, err := story.GetVotes() if err != nil { return err } for _, v := range votes { expUsers = utils.RemoveFromSlice(expUsers, v.User) } if len(expUsers) < 1 { r.handler.Send(p, "Everyone voted, revealing votes.") r.revealVotes(p, cmd) r.handler.Send(p, "Now set the estimate for this story with `!poker set <estimate>`") } } return nil }
func StartTimer(bot *UserBot, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { return errors.New("Missing timer name") } err := db.CreateTimer(bot.lastMessage.User.Name, name) if err != nil { return err } bot.reply("Created timer *" + name + "*") return nil }
func (r bot) startSession(p *robots.Payload, cmd utils.Command) error { title := cmd.StrFrom(0) users := cmd.Param("users") err := db.StartPokerSession(p.ChannelName, title, users) if err != nil { return err } r.handler.Send(p, "Started poker session for *"+title+"*") return nil }
func (r bot) addmember(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { err := errors.New( "Missing project name. Use `!project addmember <project> <username>`") return err } username := cmd.Arg(1) if name == "" { err := errors.New( "Missing user name. Use `!project addmember <project> <username>`") return err } pr, err := getProject(name) if err != nil { return err } pvt, err := pivotal.NewFor(p.UserName) if err != nil { return err } if pr == nil { r.handler.Send(p, "Project *"+name+"* not found") return nil } user, err := db.GetUserByName(username) if pr == nil { r.handler.Send(p, "Project *"+name+"* not found") return nil } if user == nil { r.handler.Send(p, "User *"+username+"* not found") return nil } _, err = pvt.CreateProjectMembership(pr.StrPivotalId(), *user.PivotalId, "member") if err != nil { return err } r.handler.Send(p, "New member *"+username+"* added to *"+name+"*") return nil }
func (r bot) setStoryState(p *robots.Payload, cmd utils.Command) error { state := cmd.Command id := cmd.Arg(0) pvt, err := conn(p.UserName) if err != nil { return err } state = fmt.Sprintf("%sed", state) story, err := pvt.SetStoryState(id, state) if err != nil { return err } r.handler.Send(p, fmt.Sprintf("Story %s - %s %s successfully", id, story.Name, state)) return nil }
func (r bot) set(p *robots.Payload, cmd utils.Command) error { s := cmd.Arg(0) parts := strings.Split(s, "=") if len(parts) < 2 { r.handler.Send(p, "Malformed setting. Use /store set PARAM=value.\n") return nil } name := strings.TrimSpace(parts[0]) value := strings.TrimSpace(parts[1]) err := db.SetSetting(p.UserName, name, value) if err != nil { return err } r.handler.Send(p, fmt.Sprintf("Successfully set %s\n", name)) return nil }
func (r bot) sendMyStories(p *robots.Payload, cmd utils.Command) error { args, err := cmd.ParseArgs("pvt-project-id") if err != nil { return err } project := args[0] pvt, err := conn(p.UserName) if err != nil { return err } user, err := db.GetUserByName(p.UserName) if err != nil { return err } filter := map[string]string{ "owned_by": user.StrPivotalId(), "state": "started,finished,delivered", } stories, err := pvt.FilteredStories(project, filter) if err != nil { return err } if len(stories) < 1 { r.handler.Send(p, "No open stories for *"+p.UserName+"*") return nil } str := "Current stories for *" + p.UserName + "*:\n" atts := []robots.Attachment{} for _, s := range stories { fallback := fmt.Sprintf("%d - %s - %s\n", s.Id, s.Name, s.State) title := fmt.Sprintf("%d - %s\n", s.Id, s.Name) a := utils.FmtAttachment(fallback, title, s.Url, s.State) atts = append(atts, a) } r.handler.SendWithAttachments(p, str, atts) return nil }
func (r bot) setEstimation(p *robots.Payload, cmd utils.Command) error { args, err := cmd.ParseArgs("estimation") if err != nil { return err } estimation := args[0] session, err := db.GetCurrentSession(p.ChannelName) if err != nil { return err } if session == nil { r.handler.Send(p, "No active poker session on *"+p.ChannelName+"*. Use `/poker session` to start a new session.") return nil } story, err := session.GetCurrentStory() if err != nil { return err } if story == nil { r.handler.Send(p, "No current story on *"+p.ChannelName+"*. Use `/poker story` to start a new session.") return nil } err = story.UpdateEstimation(estimation) if err != nil { return err } r.handler.Send(p, "Tracked estimation of *"+estimation+"* hours for *"+story.Title+"*") story, err = session.GetCurrentStory() if err != nil { return err } if story != nil { r.nextStory(p, cmd) } return nil }
func (r bot) setSprint(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { r.handler.Send(p, "Missing project name") return nil } id := cmd.Arg(1) if id == "" { r.handler.Send(p, "Missing mavenlink story id to assign as current sprint") return nil } ps, err := db.GetProjectByName(name) if err != nil { return err } mvn, err := mavenlink.NewFor(p.UserName) if err != nil { return err } mvnStory, err := mvn.GetStory(id) if err != nil { return err } if mvnStory == nil { r.handler.Send(p, "Story with id "+id+" wasn't found") return nil } fmt.Println("Got story", mvnStory.Id) ps.MvnSprintStoryId = mvnStory.Id if err := db.UpdateProject(*ps); err != nil { return err } r.handler.Send(p, "Project *"+name+"* updated.") return nil }
func (r bot) remove(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { r.handler.Send(p, "Use /store remove PARAM.\n") return nil } ok, err := db.RemoveSetting(p.UserName, name) if err != nil { return err } if ok { r.handler.Send(p, fmt.Sprintf("Successfully removed %s\n", name)) return nil } r.handler.Send(p, fmt.Sprintf("Setting %s not found\n", name)) return nil }
func TimerStatus(bot *UserBot, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { return errors.New("Missing timer name") } timer, err := db.GetTimerByName(bot.lastMessage.User.Name, name) if err != nil { return err } if timer == nil { return errors.New("You have no started timer with name *" + name + "*") } if timer.IsFinished() { bot.reply("Your timer *" + name + "* is finished. It ran for *" + timer.Duration() + "*.") } else { bot.reply("Your timer *" + name + "* has been running for *" + timer.Duration() + "*") } return nil }
func (r bot) sendStories(p *robots.Payload, cmd utils.Command) error { project := cmd.Arg(0) pvt, err := conn(p.UserName) if err != nil { return err } stories, err := pvt.Stories(project) if err != nil { return err } str := "" for _, s := range stories { str += fmt.Sprintf("%d - %s\n", s.Id, s.Name) } r.handler.Send(p, str) return nil }
func (r bot) setChannel(p *robots.Payload, cmd utils.Command) error { name := cmd.Arg(0) if name == "" { r.handler.Send(p, "Missing project name") return nil } ps, err := db.GetProjectByName(name) if err != nil { return err } ps.Channel = p.ChannelName if err := db.UpdateProject(*ps); err != nil { return err } r.handler.Send(p, "Project *"+name+"* assigned to *"+ps.Channel+"* channel.") return nil }
func (r bot) pullRequests(p *robots.Payload, cmd utils.Command) error { repo := cmd.Arg(0) if repo == "" { return errors.New("Missing repo name. Use `!github prs <repo-name>`") } parts := strings.Split(repo, "/") owner := parts[0] name := parts[1] client, err := r.getClient(p.UserName) if err != nil { return err } prs, _, err := client.PullRequests.List(owner, name, nil) if err != nil { return err } if len(prs) < 1 { r.handler.Send(p, "No open pull requests for *"+repo+"*") return nil } s := "Open pull requests for *" + repo + "*:\n" atts := []robots.Attachment{} for _, pr := range prs { atts = append(atts, utils.FmtAttachment( fmt.Sprintf("%d - %s", *pr.Number, *pr.Title), *pr.Title, *pr.HTMLURL, fmt.Sprintf("#%d %s on %s by %s", *pr.Number, *pr.State, (*pr.CreatedAt).Format("Jan 2, 2006"), *pr.User.Login))) } r.handler.SendWithAttachments(p, s, atts) return nil }