github.com/matthieudolci/hatcher@v0.2.8/standup/standup.go (about) 1 package standup 2 3 import ( 4 "database/sql" 5 "fmt" 6 "strings" 7 "time" 8 9 log "github.com/Sirupsen/logrus" 10 "github.com/matthieudolci/hatcher/common" 11 "github.com/matthieudolci/hatcher/database" 12 "github.com/slack-go/slack" 13 ) 14 15 func AskStandupYesterday(s *common.Slack, ev *slack.MessageEvent) error { 16 17 t := time.Now().Local().Format("2006-01-02") 18 t2 := time.Now().Local().Format("15:04:05") 19 date := fmt.Sprint(t) 20 times := fmt.Sprint(t2) 21 22 timer := time.NewTimer(10 * time.Minute) 23 ticker := time.NewTicker(3 * time.Second) 24 25 text := ev.Text 26 text = strings.TrimSpace(text) 27 text = strings.ToLower(text) 28 29 acceptedStandup := map[string]bool{ 30 "standup": true, 31 } 32 33 if acceptedStandup[text] { 34 35 uuid := common.CreatesUUID() 36 log.WithFields(log.Fields{ 37 "uuid": uuid, 38 }).Info("Standup uuid generated") 39 40 attachment := slack.Attachment{ 41 Text: "What did you do yesterday?", 42 Color: "#2896b7", 43 CallbackID: fmt.Sprintf("Yesterday_%s", ev.User), 44 } 45 46 params := slack.MsgOptionAttachments(attachment) 47 48 _, timestamp, err := s.Client.PostMessage(ev.Channel, params) 49 if err != nil { 50 log.WithError(err).Error("Failed to post yesterday standup question") 51 } 52 log.WithFields(log.Fields{ 53 "userid": ev.User, 54 "timestamp": timestamp, 55 }).Info("Timestamp of the Standup Yesterday message") 56 57 go postStandupResults(s, ev.User, date, times, uuid) 58 59 loop: 60 for { 61 select { 62 case <-timer.C: 63 err = postStandupCancelTimeout(s, ev.Channel) 64 if err != nil { 65 log.WithError(err).Error("Could not cancel standup") 66 } 67 log.Info("Standup Canceled") 68 break loop 69 case <-ticker.C: 70 params2 := &slack.GetConversationHistoryParameters{ 71 Limit: 1, 72 Oldest: timestamp, 73 ChannelID: ev.Channel, 74 } 75 76 history, err := s.Client.GetConversationHistory(params2) 77 if err != nil { 78 log.WithFields(log.Fields{ 79 "timestamp": timestamp, 80 }).WithError(err).Error("Could not get the IM history of the message") 81 continue 82 } 83 log.WithFields(log.Fields{ 84 "timestamp": timestamp, 85 }).Debug("Getting IM history of the message") 86 87 message := history.Messages 88 89 if len(message) == 0 { 90 91 } 92 if len(message) > 0 { 93 text := history.Messages[0].Msg.Text 94 userid := history.Messages[0].Msg.User 95 stamp := history.Messages[0].Msg.Timestamp 96 switch text { 97 case "cancel": 98 err = postStandupCancel(s, ev.Channel) 99 if err != nil { 100 log.WithError(err).Error("Could not cancel standup") 101 } 102 log.Info("Standup Canceled") 103 104 break loop 105 default: 106 err = yesterdayRegister(text, stamp, date, times, userid, uuid) 107 if err != nil { 108 log.WithError(err).Error("Could not start yesterdayRegister") 109 } 110 log.Info("Starting yesterdayRegister") 111 112 err = askStandupToday(s, ev.Channel, ev.User, date, times, uuid) 113 if err != nil { 114 log.WithError(err).Error("Could not start askStandupToday") 115 } 116 log.Info("Starting askStandupToday") 117 118 break loop 119 } 120 } 121 } 122 } 123 } 124 return nil 125 } 126 127 func AskStandupYesterdayScheduled(s *common.Slack, userid string) error { 128 129 t := time.Now().Local().Format("2006-01-02") 130 t2 := time.Now().Local().Format("15:04:05") 131 date := fmt.Sprint(t) 132 times := fmt.Sprint(t2) 133 134 timer := time.NewTimer(10 * time.Minute) 135 ticker := time.NewTicker(3 * time.Second) 136 137 uuid := common.CreatesUUID() 138 log.WithFields(log.Fields{ 139 "uuid": uuid, 140 }).Info("Standup uuid generated") 141 142 params := &slack.OpenConversationParameters{ 143 Users: []string{userid}, 144 } 145 146 channelid, _, _, err := s.Client.OpenConversation(params) 147 if err != nil { 148 log.WithError(err).Error("OpenIMChannel could not get channel id") 149 } 150 151 attachment := slack.Attachment{ 152 Text: "What did you do yesterday?", 153 Color: "#2896b7", 154 CallbackID: fmt.Sprintf("standupYesterday_%s", userid), 155 } 156 157 params2 := slack.MsgOptionAttachments(attachment) 158 _, timestamp, err := s.Client.PostMessage(channelid.ID, params2) 159 if err != nil { 160 log.WithError(err).Error("Failed to post yesterday standup question") 161 } 162 log.WithFields(log.Fields{ 163 "timestamp": timestamp, 164 }).Info("Timestamp of the standupYesterday message") 165 166 go postStandupResults(s, userid, date, times, uuid) 167 168 loop: 169 for { 170 select { 171 case <-timer.C: 172 err = postStandupCancelTimeout(s, channelid.ID) 173 if err != nil { 174 log.WithError(err).Error("Could not cancel standup") 175 } 176 log.Info("Standup Canceled") 177 178 break loop 179 case <-ticker.C: 180 params2 := &slack.GetConversationHistoryParameters{ 181 Limit: 1, 182 Oldest: timestamp, 183 ChannelID: channelid.ID, 184 } 185 186 history, err := s.Client.GetConversationHistory(params2) 187 if err != nil { 188 log.WithFields(log.Fields{ 189 "timestamp": timestamp, 190 }).WithError(err).Error("Could not get the IM history of the message") 191 continue 192 } 193 log.WithFields(log.Fields{ 194 "timestamp": timestamp, 195 }).Debug("Getting IM history of the message with timestamp") 196 197 message := history.Messages 198 199 if len(message) == 0 { 200 201 } 202 if len(message) > 0 { 203 text := history.Messages[0].Msg.Text 204 userid := history.Messages[0].Msg.User 205 stamp := history.Messages[0].Msg.Timestamp 206 switch text { 207 case "cancel": 208 err = postStandupCancel(s, channelid.ID) 209 if err != nil { 210 log.WithError(err).Error("Could not cancel standup") 211 } 212 log.Info("Standup Canceled") 213 214 break loop 215 default: 216 err = yesterdayRegister(text, stamp, date, times, userid, uuid) 217 if err != nil { 218 log.WithError(err).Error("Could not start yesterdayRegister") 219 } 220 log.Info("Starting yesterdayRegister") 221 222 err = askStandupToday(s, channelid.ID, userid, date, times, uuid) 223 if err != nil { 224 log.WithError(err).Error("Could not start askStandupToday") 225 } 226 log.Info("Starting askStandupToday") 227 break loop 228 } 229 } 230 } 231 } 232 return nil 233 } 234 235 func yesterdayRegister(response, timestamp, date, time, userid, uuid string) error { 236 237 log.Info("Starting import in database of standupYesterday result") 238 239 var id string 240 241 sqlWrite := ` 242 INSERT INTO 243 hatcher.standupyesterday 244 (response, timestamp, date, time, userid, uuid) 245 VALUES ($1, $2, $3, $4, $5, $6) 246 RETURNING id; 247 ` 248 249 err := database.DB.QueryRow( 250 sqlWrite, 251 response, 252 timestamp, 253 date, 254 time, 255 userid, 256 uuid).Scan(&id) 257 if err != nil { 258 log.WithError(err).Error("Couldn't insert in the database the result of AskStandupYesterday") 259 } 260 log.Info("AskStandupYesterday result written in database") 261 return nil 262 } 263 264 func askStandupToday(s *common.Slack, channelid, userid, date, times, uuid string) error { 265 266 attachment := slack.Attachment{ 267 Text: "What are you doing today?", 268 Color: "#41aa3f", 269 CallbackID: "standupToday", 270 } 271 272 params := slack.MsgOptionAttachments(attachment) 273 _, timestamp, err := s.Client.PostMessage(channelid, params) 274 if err != nil { 275 log.WithError(err).Error("Failed to post today standup question") 276 } 277 log.Info("Posting today standup question") 278 279 timer := time.NewTimer(10 * time.Minute) 280 ticker := time.NewTicker(3 * time.Second) 281 282 loop: 283 for { 284 select { 285 case <-timer.C: 286 err = postStandupCancelTimeout(s, channelid) 287 if err != nil { 288 log.WithError(err).Error("Could not cancel standup") 289 } 290 log.Info("Standup Canceled") 291 break loop 292 case <-ticker.C: 293 params2 := &slack.GetConversationHistoryParameters{ 294 Limit: 1, 295 Oldest: timestamp, 296 ChannelID: channelid, 297 } 298 299 history, err := s.Client.GetConversationHistory(params2) 300 if err != nil { 301 log.WithFields(log.Fields{ 302 "timestamp": timestamp, 303 }).WithError(err).Error("Could not get the IM history of the message") 304 continue 305 } 306 log.WithFields(log.Fields{ 307 "timestamp": timestamp, 308 }).Debug("Getting IM history of the message") 309 310 message := history.Messages 311 312 if len(message) == 0 { 313 314 } 315 if len(message) > 0 { 316 text := history.Messages[0].Msg.Text 317 userid := history.Messages[0].Msg.User 318 stamp := history.Messages[0].Msg.Timestamp 319 switch text { 320 case "cancel": 321 err = postStandupCancel(s, channelid) 322 if err != nil { 323 log.WithError(err).Error("Could not cancel standup") 324 } 325 log.Info("Canceled standup") 326 327 break loop 328 default: 329 err := TodayRegister(text, stamp, date, times, userid, uuid) 330 if err != nil { 331 log.WithError(err).Error("Could not start TodayRegister") 332 } 333 log.Info("Starting TodayRegister") 334 335 err = askStandupBlocker(s, channelid, userid, date, times, uuid) 336 if err != nil { 337 log.WithError(err).Error("Could not start askStandupBlocker") 338 } 339 log.Info("Started askStandupBlocker") 340 341 break loop 342 } 343 } 344 } 345 } 346 return nil 347 } 348 349 func TodayRegister(response, timestamp, date, time, userid, uuid string) error { 350 351 log.Info("Starting import in database of AskStandupToday result") 352 353 var id string 354 355 sqlWrite := ` 356 INSERT INTO 357 hatcher.standuptoday 358 (response, timestamp, date, time, userid, uuid) 359 VALUES ($1, $2, $3, $4, $5, $6) 360 RETURNING id; 361 ` 362 363 err := database.DB.QueryRow( 364 sqlWrite, 365 response, 366 timestamp, 367 date, 368 time, 369 userid, 370 uuid).Scan(&id) 371 if err != nil { 372 log.WithError(err).Error("Couldn't insert in the database the result of AskStandupToday") 373 } 374 log.Info("AskStandupToday result written in database") 375 376 return nil 377 } 378 379 func askStandupBlocker(s *common.Slack, channelid, userid, date, times, uuid string) error { 380 381 attachment := slack.Attachment{ 382 Text: "Do you have any blockers?", 383 Color: "#f91b1b", 384 CallbackID: "standupBlocker", 385 } 386 387 params := slack.MsgOptionAttachments(attachment) 388 389 _, timestamp, err := s.Client.PostMessage(channelid, params) 390 if err != nil { 391 log.WithError(err).Error("Failed to post blocker standup question") 392 } 393 log.Info("Posted blocker standup question") 394 395 timer := time.NewTimer(10 * time.Minute) 396 ticker := time.NewTicker(3 * time.Second) 397 398 loop: 399 for { 400 select { 401 case <-timer.C: 402 err = postStandupCancelTimeout(s, channelid) 403 if err != nil { 404 log.WithError(err).Error("Could not cancel standup") 405 } 406 log.Info("Standup Canceled") 407 408 break loop 409 case <-ticker.C: 410 params2 := &slack.GetConversationHistoryParameters{ 411 Limit: 1, 412 Oldest: timestamp, 413 ChannelID: channelid, 414 } 415 416 history, err := s.Client.GetConversationHistory(params2) 417 if err != nil { 418 log.WithFields(log.Fields{ 419 "timestamp": timestamp, 420 }).WithError(err).Error("Could not get the IM history of the message") 421 continue 422 } 423 log.WithFields(log.Fields{ 424 "timestamp": timestamp, 425 }).Debug("Getting IM history of the message") 426 427 message := history.Messages 428 429 if len(message) == 0 { 430 431 } 432 if len(message) > 0 { 433 text := history.Messages[0].Msg.Text 434 userid := history.Messages[0].Msg.User 435 stamp := history.Messages[0].Msg.Timestamp 436 switch text { 437 case "cancel": 438 err := postStandupCancel(s, channelid) 439 if err != nil { 440 log.WithError(err).Error("Could not cancel standup") 441 } 442 log.Info("Standup canceled") 443 444 break loop 445 default: 446 err := BlockerRegister(text, stamp, date, times, userid, uuid) 447 if err != nil { 448 log.WithError(err).Error("Could not start BlockerRegister") 449 } 450 log.Info("Started BlockerRegister") 451 452 err = postStandupDone(s, channelid, userid, date, times, uuid) 453 if err != nil { 454 log.WithError(err).Error("Could not start postStandupDone") 455 } 456 log.Info("Started postStandupDone") 457 458 break loop 459 } 460 } 461 } 462 } 463 return nil 464 } 465 466 func BlockerRegister(response, timestamp, date, time, userid, uuid string) error { 467 468 log.Info("Starting import in database of AskStandupBlocker result") 469 470 var id string 471 472 sqlWrite := ` 473 INSERT INTO 474 hatcher.standupblocker 475 (response, timestamp, date, time, userid, uuid) 476 VALUES ($1, $2, $3, $4, $5, $6) 477 RETURNING id; 478 ` 479 480 err := database.DB.QueryRow( 481 sqlWrite, 482 response, 483 timestamp, 484 date, 485 time, 486 userid, 487 uuid).Scan(&id) 488 if err != nil { 489 log.WithError(err).Error("Couldn't insert in the database the result of AskStandupBlocker") 490 } 491 log.Info("AskStandupBlocker result written in database") 492 493 return nil 494 } 495 496 func postStandupCancel(s *common.Slack, channelid string) error { 497 498 attachment := slack.Attachment{ 499 Text: "Standup canceled!", 500 Color: "#f91b1b", 501 CallbackID: "standupCancel", 502 } 503 504 params := slack.MsgOptionAttachments(attachment) 505 506 _, _, err := s.Client.PostMessage(channelid, params) 507 if err != nil { 508 log.WithError(err).Error("Failed to post standup canceled message") 509 } 510 log.Info("Posted standup canceled message") 511 512 return nil 513 } 514 515 func postStandupCancelTimeout(s *common.Slack, channelid string) error { 516 517 attachment := slack.Attachment{ 518 Text: "The standup was canceled for timeout.\nYou can start a new standup by sending `standup`", 519 Color: "#f91b1b", 520 CallbackID: "standupCancelTimeout", 521 } 522 523 params := slack.MsgOptionAttachments(attachment) 524 525 _, _, err := s.Client.PostMessage(channelid, params) 526 if err != nil { 527 log.WithError(err).Error("Failed to post standup canceled timeout message") 528 } 529 log.Info("Posted standup canceled timeout message") 530 531 return nil 532 } 533 534 func postStandupDone(s *common.Slack, channelid, userid, date, time, uuid string) error { 535 536 attachment := slack.Attachment{ 537 Text: "Standup Done! Your results will be posted in 10 mins\nEditing your answers will edit the results in the standup channel.\nThanks and see you tomorrow :smiley:", 538 Color: "#2896b7", 539 CallbackID: "standupDone", 540 } 541 542 params := slack.MsgOptionAttachments(attachment) 543 544 _, _, err := s.Client.PostMessage(channelid, params) 545 if err != nil { 546 log.WithError(err).Error("Failed to post standup done message") 547 } 548 log.Info("Posted standup done message") 549 550 return nil 551 } 552 553 func getResultsYesterday(userid, date, standupChannel, uuid string) (responseYesterday string) { 554 555 var response string 556 557 rows, err := database.DB.Query("SELECT response FROM hatcher.standupyesterday WHERE userid = $1 and date = $2 and uuid = $3;", userid, date, uuid) 558 if err != nil { 559 if err == sql.ErrNoRows { 560 log.WithError(err).Error("There is no results") 561 } 562 } 563 defer rows.Close() 564 for rows.Next() { 565 err = rows.Scan(&response) 566 if err != nil { 567 log.WithError(err).Error("During the scan") 568 } 569 } 570 return response 571 } 572 573 func getResultsToday(userid, date, standupChannel, uuid string) (responseToday string) { 574 575 var response string 576 577 rows, err := database.DB.Query("SELECT response FROM hatcher.standuptoday WHERE userid = $1 and date = $2 and uuid = $3;", userid, date, uuid) 578 if err != nil { 579 if err == sql.ErrNoRows { 580 log.WithError(err).Error("There is no results") 581 } 582 } 583 defer rows.Close() 584 for rows.Next() { 585 err = rows.Scan(&response) 586 if err != nil { 587 log.WithError(err).Error("During the scan") 588 } 589 } 590 return response 591 } 592 593 func getResultsBlocker(userid, date, standupChannel, uuid string) (responseBlocker string) { 594 595 var response string 596 597 rows, err := database.DB.Query("SELECT response FROM hatcher.standupblocker WHERE userid = $1 and date = $2 and uuid = $3;", userid, date, uuid) 598 if err != nil { 599 if err == sql.ErrNoRows { 600 log.WithError(err).Error("There is no results") 601 } 602 } 603 defer rows.Close() 604 for rows.Next() { 605 606 err = rows.Scan(&response) 607 if err != nil { 608 log.WithError(err).Error("During the scan") 609 } 610 } 611 return response 612 } 613 614 func CheckIfYesterdayMessageEdited(s *common.Slack, ev *slack.MessageEvent) error { 615 616 timestamp := ev.SubMessage.Timestamp 617 text := ev.SubMessage.Text 618 userid := ev.SubMessage.User 619 620 if common.RowExists("SELECT exists (SELECT timestamp FROM hatcher.standupyesterday WHERE timestamp=$1)", timestamp) { 621 err := common.QueryRow("UPDATE hatcher.standupyesterday SET response=$2 WHERE timestamp=$1", timestamp, text) 622 if err != nil { 623 log.WithError(err).Error("Could not edit the yesterday standup row") 624 } 625 log.WithFields(log.Fields{ 626 "timestamp": timestamp, 627 }).Info("The yesterday standup row was edited") 628 629 var standupUUID string 630 631 standupUUID, err = common.QueryUUID("SELECT uuid FROM hatcher.standupyesterday WHERE timestamp=$1", timestamp) 632 if err != nil { 633 log.WithError(err).Error("Could get the standup uuid") 634 } 635 log.WithFields(log.Fields{ 636 "uuid": standupUUID, 637 "timestamp": timestamp, 638 }).Info("The standup uuid was retrieve") 639 640 err = updateStandupResults(s, userid, standupUUID) 641 if err != nil { 642 log.WithError(err).Error("Could not start the standup update for yesterday notes") 643 } 644 645 } else { 646 log.Println("The row doesn't exist") 647 } 648 return nil 649 } 650 651 func CheckIfTodayMessageEdited(s *common.Slack, ev *slack.MessageEvent) error { 652 653 timestamp := ev.SubMessage.Timestamp 654 text := ev.SubMessage.Text 655 userid := ev.SubMessage.User 656 657 if common.RowExists("SELECT exists (SELECT timestamp FROM hatcher.standuptoday WHERE timestamp=$1)", timestamp) { 658 err := common.QueryRow("UPDATE hatcher.standuptoday SET response=$2 WHERE timestamp=$1", timestamp, text) 659 if err != nil { 660 log.WithError(err).Error("Could not edit the today standup row") 661 } 662 log.WithFields(log.Fields{ 663 "timestamp": timestamp, 664 }).Info("The today standup row was edited") 665 666 var standupUUID string 667 668 standupUUID, err = common.QueryUUID("SELECT uuid FROM hatcher.standuptoday WHERE timestamp=$1", timestamp) 669 if err != nil { 670 log.WithError(err).Error("Could get the standup uuid") 671 } 672 log.WithFields(log.Fields{ 673 "uuid": standupUUID, 674 "timestamp": timestamp, 675 }).Info("The standup uuid was retrieve") 676 677 err = updateStandupResults(s, userid, standupUUID) 678 if err != nil { 679 log.WithError(err).Error("Could not start the standup update for Today notes") 680 } 681 682 } else { 683 log.Println("The row doesn't exist") 684 } 685 return nil 686 } 687 688 func CheckIfBlockerMessageEdited(s *common.Slack, ev *slack.MessageEvent) error { 689 690 timestamp := ev.SubMessage.Timestamp 691 text := ev.SubMessage.Text 692 userid := ev.SubMessage.User 693 694 if common.RowExists("SELECT exists (SELECT timestamp FROM hatcher.standupblocker WHERE timestamp=$1)", timestamp) { 695 err := common.QueryRow("UPDATE hatcher.standupblocker SET response=$2 WHERE timestamp=$1", timestamp, text) 696 if err != nil { 697 log.WithError(err).Error("Could not edit the blocker standup row") 698 } 699 log.WithFields(log.Fields{ 700 "timestamp": timestamp, 701 }).Info("The blocker standup row was edited") 702 703 var standupUUID string 704 705 standupUUID, err = common.QueryUUID("SELECT uuid FROM hatcher.standupblocker WHERE timestamp=$1", timestamp) 706 if err != nil { 707 log.WithError(err).Error("Could get the standup uuid") 708 } 709 log.WithFields(log.Fields{ 710 "uuid": standupUUID, 711 "timestamp": timestamp, 712 }).Info("The standup uuid was retrieve") 713 714 err = updateStandupResults(s, userid, standupUUID) 715 if err != nil { 716 log.WithError(err).Error("Could not start the standup update for blocker") 717 } 718 719 } else { 720 log.Println("The row doesn't exist") 721 } 722 return nil 723 } 724 725 func postStandupResults(s *common.Slack, userid, date, times, uuid string) { 726 727 timer := time.NewTimer(10 * time.Minute) 728 729 <-timer.C 730 731 if common.RowExists("SELECT exists (SELECT * FROM hatcher.standupblocker WHERE uuid=$1)", uuid) { 732 rows, err := database.DB.Query("SELECT displayname, standup_channel FROM hatcher.users WHERE userid = $1;", userid) 733 if err != nil { 734 if err == sql.ErrNoRows { 735 log.WithError(err).Error("There is no results") 736 } 737 } 738 defer rows.Close() 739 for rows.Next() { 740 741 var displayname string 742 var standupChannel string 743 744 responseYesterday := getResultsYesterday(userid, date, standupChannel, uuid) 745 responseToday := getResultsToday(userid, date, standupChannel, uuid) 746 responseBlocker := getResultsBlocker(userid, date, standupChannel, uuid) 747 748 err = rows.Scan(&displayname, &standupChannel) 749 if err != nil { 750 log.WithError(err).Error("During the scan") 751 } 752 753 attachment := slack.Attachment{ 754 Title: "What did you do yesterday?", 755 Text: responseYesterday, 756 Color: "#2896b7", 757 CallbackID: fmt.Sprintf("resultsStandupYesterday_%s", userid), 758 } 759 760 attachment2 := slack.Attachment{ 761 Title: "What are you doing today?", 762 Color: "#41aa3f", 763 Text: responseToday, 764 CallbackID: fmt.Sprintf("resultsStandupToday_%s", userid), 765 } 766 767 attachment3 := slack.Attachment{ 768 Title: "Do you have any blockers?", 769 Color: "#f91b1b", 770 Text: responseBlocker, 771 CallbackID: fmt.Sprintf("resultsStandupBlocker_%s", userid), 772 } 773 774 params := slack.MsgOptionAttachments(attachment, attachment2, attachment3) 775 776 text := fmt.Sprintf("%s posted a daily standup note", displayname) 777 _, respTimestamp, err := s.Client.PostMessage( 778 standupChannel, 779 slack.MsgOptionText(text, false), 780 params) 781 if err != nil { 782 log.WithError(err).Error("Failed to post standup results") 783 } 784 log.WithFields(log.Fields{ 785 "timestamp": respTimestamp, 786 }).Info("Standup results posted") 787 788 err = common.QueryRow("INSERT INTO hatcher.standupresults (timestamp, date, time, uuid) VALUES ($1, $2, $3, $4)", respTimestamp, date, times, uuid) 789 if err != nil { 790 log.WithError(err).Error("Could not edit the standup result timestamp row") 791 } 792 log.WithFields(log.Fields{ 793 "timestamp": respTimestamp, 794 }).Info("The standup result timestamp row was edited") 795 } 796 } 797 } 798 799 func updateStandupResults(s *common.Slack, userid, uuid string) error { 800 801 rows, err := database.DB.Query("SELECT userid, displayname, standup_channel FROM hatcher.users WHERE userid = $1;", userid) 802 if err != nil { 803 if err == sql.ErrNoRows { 804 log.WithError(err).Error("There is no results") 805 } 806 } 807 808 defer rows.Close() 809 for rows.Next() { 810 811 var displayname string 812 var standupChannel string 813 var timestamp string 814 var date string 815 816 err := database.DB.QueryRow("SELECT timestamp, date FROM hatcher.standupresults WHERE uuid=$1", uuid).Scan(×tamp, &date) 817 if err != nil && err != sql.ErrNoRows { 818 log.WithError(err).Error("Impossible to get the standup result uuid") 819 } 820 821 responseYesterday := getResultsYesterday(userid, date, standupChannel, uuid) 822 responseToday := getResultsToday(userid, date, standupChannel, uuid) 823 responseBlocker := getResultsBlocker(userid, date, standupChannel, uuid) 824 825 err = rows.Scan(&userid, &displayname, &standupChannel) 826 if err != nil { 827 log.WithError(err).Error("During the scan") 828 } 829 830 attachment := slack.Attachment{ 831 Title: "What did you do yesterday?", 832 Color: "#2896b7", 833 Text: responseYesterday, 834 CallbackID: fmt.Sprintf("resultsStandupYesterday_%s", userid), 835 } 836 837 attachment2 := slack.Attachment{ 838 Title: "What are you doing today?", 839 Color: "#41aa3f", 840 Text: responseToday, 841 CallbackID: fmt.Sprintf("resultsStandupToday_%s", userid), 842 } 843 844 attachment3 := slack.Attachment{ 845 Title: "Do you have any blockers?", 846 Color: "#f91b1b", 847 Text: responseBlocker, 848 CallbackID: fmt.Sprintf("resultsStandupBlocker_%s", userid), 849 } 850 851 text := fmt.Sprintf("%s posted a daily standup note", displayname) 852 _, _, _, err = s.Client.SendMessage( 853 standupChannel, 854 slack.MsgOptionText(text, false), 855 slack.MsgOptionUpdate(timestamp), 856 slack.MsgOptionAttachments( 857 attachment, 858 attachment2, 859 attachment3, 860 ), 861 ) 862 if err != nil { 863 log.WithError(err).Error("Failed to post updated standup results") 864 } 865 log.Info("Updated standup results posted") 866 } 867 return nil 868 }