Skip to content

Commit

Permalink
344 fixed timer bug
Browse files Browse the repository at this point in the history
  • Loading branch information
hollesse committed Mar 24, 2024
1 parent fe9c42f commit ba857e6
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 245 deletions.
229 changes: 15 additions & 214 deletions mob.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,11 @@ package main

import (
"bufio"
"bytes"
"crypto/tls"
x509 "crypto/x509"
"encoding/json"
"errors"
"fmt"
config "github.com/remotemobprogramming/mob/v4/configuration"
"github.com/remotemobprogramming/mob/v4/help"
"github.com/remotemobprogramming/mob/v4/open"
"github.com/remotemobprogramming/mob/v4/say"
"io"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -310,10 +302,13 @@ func execute(command string, parameter []string, configuration config.Configurat
return
}
if len(parameter) > 0 {
timer := parameter[0]
startTimer(timer, configuration)
if err := startTimer(parameter[0], configuration); err != nil {
exit(1)
}
} else if configuration.Timer != "" {
startTimer(configuration.Timer, configuration)
if err := startTimer(configuration.Timer, configuration); err != nil {
exit(1)
}
} else {
say.Info("It's now " + currentTime() + ". Happy collaborating! :)")
}
Expand All @@ -340,17 +335,22 @@ func execute(command string, parameter []string, configuration config.Configurat
say.Error(fmt.Sprintf("Could not open webtimer: %s", err.Error()))
}
} else {
timer := parameter[0]
startTimer(timer, configuration)
if err := startTimer(parameter[0], configuration); err != nil {
exit(1)
}
}
} else if configuration.Timer != "" {
startTimer(configuration.Timer, configuration)
if err := startTimer(configuration.Timer, configuration); err != nil {
exit(1)
}
} else {
help.Help(configuration)
}
case "break":
if len(parameter) > 0 {
startBreakTimer(parameter[0], configuration)
if err := startBreakTimer(parameter[0], configuration); err != nil {
exit(1)
}
} else {
help.Help(configuration)
}
Expand All @@ -371,22 +371,6 @@ func execute(command string, parameter []string, configuration config.Configurat
}
}

func openTimerInBrowser(configuration config.Configuration) error {
timerurl := configuration.TimerUrl
if timerurl == "" {
return fmt.Errorf("Timer url is not configured")
}
if configuration.TimerRoom != "" {
if !strings.HasSuffix(configuration.TimerUrl, "/") {
timerurl += "/"
}
timerurl += configuration.TimerRoom
} else {
say.Warning("Timer Room is not configured. To open specific room please configure timer room variable.")
}
return open.OpenInBrowser(timerurl)
}

func helpRequested(parameter []string) bool {
for i := 0; i < len(parameter); i++ {
element := parameter[i]
Expand Down Expand Up @@ -507,189 +491,6 @@ func executeCommandsInBackgroundProcess(commands ...string) (err error) {
return err
}

func startTimer(timerInMinutes string, configuration config.Configuration) {
timeoutInMinutes := toMinutes(timerInMinutes)

timeoutInSeconds := timeoutInMinutes * 60
timeOfTimeout := time.Now().Add(time.Minute * time.Duration(timeoutInMinutes)).Format("15:04")
say.Debug(fmt.Sprintf("Starting timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes))

room := getMobTimerRoom(configuration)
startRemoteTimer := room != ""
startLocalTimer := configuration.TimerLocal

if !startRemoteTimer && !startLocalTimer {
say.Error("No timer configured, not starting timer")
exit(1)
}

if startRemoteTimer {
timerUser := getUserForMobTimer(configuration.TimerUser)
err := httpPutTimer(timeoutInMinutes, room, timerUser, configuration.TimerUrl, configuration.TimerInsecure)
if err != nil {
say.Error("remote timer couldn't be started")
say.Error(err.Error())
exit(1)
}
}

if startLocalTimer {
err := executeCommandsInBackgroundProcess(getSleepCommand(timeoutInSeconds), getVoiceCommand(configuration.VoiceMessage, configuration.VoiceCommand), getNotifyCommand(configuration.NotifyMessage, configuration.NotifyCommand), "echo \"mobTimer\"")

if err != nil {
say.Error(fmt.Sprintf("timer couldn't be started on your system (%s)", runtime.GOOS))
say.Error(err.Error())
exit(1)
}
}

say.Info("It's now " + currentTime() + ". " + fmt.Sprintf("%d min timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)")
}

func getMobTimerRoom(configuration config.Configuration) string {
if !isGit() {
say.Debug("timer not in git repository, using MOB_TIMER_ROOM for room name")
return configuration.TimerRoom
}

currentWipBranchQualifier := configuration.WipBranchQualifier
if currentWipBranchQualifier == "" {
currentBranch := gitCurrentBranch()
currentBaseBranch, _ := determineBranches(currentBranch, gitBranches(), configuration)

if currentBranch.IsWipBranch(configuration) {
wipBranchWithoutWipPrefix := currentBranch.removeWipPrefix(configuration).Name
currentWipBranchQualifier = removePrefix(removePrefix(wipBranchWithoutWipPrefix, currentBaseBranch.Name), configuration.WipBranchQualifierSeparator)
}
}

if configuration.TimerRoomUseWipBranchQualifier && currentWipBranchQualifier != "" {
say.Info("Using wip branch qualifier for room name")
return currentWipBranchQualifier
}

return configuration.TimerRoom
}

func startBreakTimer(timerInMinutes string, configuration config.Configuration) {
timeoutInMinutes := toMinutes(timerInMinutes)

timeoutInSeconds := timeoutInMinutes * 60
timeOfTimeout := time.Now().Add(time.Minute * time.Duration(timeoutInMinutes)).Format("15:04")
say.Debug(fmt.Sprintf("Starting break timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes))

room := getMobTimerRoom(configuration)
startRemoteTimer := room != ""
startLocalTimer := configuration.TimerLocal

if !startRemoteTimer && !startLocalTimer {
say.Error("No break timer configured, not starting break timer")
exit(1)
}

if startRemoteTimer {
timerUser := getUserForMobTimer(configuration.TimerUser)
err := httpPutBreakTimer(timeoutInMinutes, room, timerUser, configuration.TimerUrl, configuration.TimerInsecure)

if err != nil {
say.Error("remote break timer couldn't be started")
say.Error(err.Error())
exit(1)
}
}

if startLocalTimer {
err := executeCommandsInBackgroundProcess(getSleepCommand(timeoutInSeconds), getVoiceCommand("mob start", configuration.VoiceCommand), getNotifyCommand("mob start", configuration.NotifyCommand), "echo \"mobTimer\"")

if err != nil {
say.Error(fmt.Sprintf("break timer couldn't be started on your system (%s)", runtime.GOOS))
say.Error(err.Error())
exit(1)
}
}

say.Info("It's now " + currentTime() + ". " + fmt.Sprintf("%d min break timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)")
}

func getUserForMobTimer(userOverride string) string {
if userOverride == "" {
return gitUserName()
}
return userOverride
}

func toMinutes(timerInMinutes string) int {
timeoutInMinutes, _ := strconv.Atoi(timerInMinutes)
if timeoutInMinutes < 0 {
timeoutInMinutes = 0
}
return timeoutInMinutes
}

func httpPutTimer(timeoutInMinutes int, room string, user string, timerService string, disableSSLVerification bool) error {
putBody, _ := json.Marshal(map[string]interface{}{
"timer": timeoutInMinutes,
"user": user,
})
return sendRequest(putBody, "PUT", timerService+room, disableSSLVerification)
}

func httpPutBreakTimer(timeoutInMinutes int, room string, user string, timerService string, disableSSLVerification bool) error {
putBody, _ := json.Marshal(map[string]interface{}{
"breaktimer": timeoutInMinutes,
"user": user,
})
return sendRequest(putBody, "PUT", timerService+room, disableSSLVerification)
}

func sendRequest(requestBody []byte, requestMethod string, requestUrl string, disableSSLVerification bool) error {
say.Info(requestMethod + " " + requestUrl + " " + string(requestBody))

responseBody := bytes.NewBuffer(requestBody)
request, requestCreationError := http.NewRequest(requestMethod, requestUrl, responseBody)

httpClient := http.DefaultClient
if disableSSLVerification {
transCfg := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient = &http.Client{Transport: transCfg}
}

if requestCreationError != nil {
return fmt.Errorf("failed to create the http request object: %w", requestCreationError)
}

request.Header.Set("Content-Type", "application/json")
response, responseErr := httpClient.Do(request)
if e, ok := responseErr.(*url.Error); ok {
switch e.Err.(type) {
case x509.UnknownAuthorityError:
say.Error("The timer.mob.sh SSL certificate is signed by an unknown authority!")
say.Fix("HINT: You can ignore that by adding MOB_TIMER_INSECURE=true to your configuration or environment.",
"echo MOB_TIMER_INSECURE=true >> ~/.mob")
return fmt.Errorf("failed, to amke the http request: %w", responseErr)

default:
return fmt.Errorf("failed to make the http request: %w", responseErr)

}
}

if responseErr != nil {
return fmt.Errorf("failed to make the http request: %w", responseErr)
}
defer response.Body.Close()
body, responseReadingErr := io.ReadAll(response.Body)
if responseReadingErr != nil {
return fmt.Errorf("failed to read the http response: %w", responseReadingErr)
}
if string(body) != "" {
say.Info(string(body))
}
return nil
}

func currentTime() string {
return time.Now().Format("15:04")
}
Expand Down
31 changes: 0 additions & 31 deletions mob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1723,37 +1723,6 @@ func TestHelpRequested(t *testing.T) {
equals(t, true, helpRequested([]string{"s", "10", "-h"}))
}

func TestOpenTimerInBrowserWithTimerRoom(t *testing.T) {
mockOpenInBrowser()
output, configuration := setup(t)
configuration.TimerRoom = "testroom"

err := openTimerInBrowser(configuration)

assertOutputNotContains(t, output, "Timer Room is not configured.")
assertNoError(t, err)
}

func TestOpenTimerInBrowserWithoutTimerRoom(t *testing.T) {
mockOpenInBrowser()
output, configuration := setup(t)

err := openTimerInBrowser(configuration)

assertOutputContains(t, output, "Timer Room is not configured.")
assertNoError(t, err)
}

func TestOpenTimerInBrowserError(t *testing.T) {
mockOpenInBrowser()
_, configuration := setup(t)
configuration.TimerUrl = ""

err := openTimerInBrowser(configuration)

assertError(t, err, "Timer url is not configured")
}

func TestMobClean(t *testing.T) {
_, configuration := setup(t)

Expand Down
Loading

0 comments on commit ba857e6

Please sign in to comment.