Skip to content

Commit

Permalink
[teamup-rocketchat] Added support for custom config file and log path…
Browse files Browse the repository at this point in the history
… location via cli parameters (#13)
  • Loading branch information
roshanlc authored Mar 24, 2023
1 parent b11709b commit cb5ca43
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 63 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ teamup-rocketchat-bot/*.log
teamup-rocketchat-bot/config.yml
teamup-rocketchat-bot/events_tracker.json
teamup-rocketchat-bot/todo.md

teamup-rocketchat-bot/logs
51 changes: 49 additions & 2 deletions teamup-rocketchat-bot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,49 @@
### Currently supports

- Reminding upcoming meeting events
### Configuration
- The configuration file should have the `yml` extension and the following properties.
```bash
# Url of rocket chat server
URL: https://rocket.chat

# bot username
USERNAME: bot

# bot password
PASSWORD: pass

# Use ssl(https)?
USE_SSL: TRUE

# channel/room (Currently supports one)
# Make sure the bot has already been added to the channel
ROOM: try

# meeting calendar read-only link (calendar-code)
MEETINGS_TEAMUP: someMeetingCodexxxxx

# teamup token required for api calls
TOKEN_TEAMUP: someLongCodexxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# run the bot in every X interval (mins)
# Keep it between 5 to 10
# default is 5
REPEAT_IN: 5

# path to keep logfile
# #default LOG_PATH is /tmp folder
# It will be overriden if logpath flag is provided to bot while running the bot
LOG_PATH: /tmp

# name for the log file
# default log file name is teamup-rocket-chat.log
LOG_FILE_NAME: teamup-rocket-chat.log
```
- The application supports parameters for custom logpath and custom configuraion file path
- `--config Point to the configuration (config) file. It overrides the default configuration file located at app directory`
- `--logpath Set the custom logpath. It overrides the log path specified in configuration (config.yml) file`
- `--help Show help and usage screen`
### Run locally

*Note*: Make sure that the bot has already been added to channel or room
Expand All @@ -15,10 +57,15 @@
- Then run the following

```bash
go run main.go
go run .
```

- For more application usage, run
```bash
go run . --help
```

**Note**: It will create extra files which are required for smooth functioning of the bot
**Note**: It will create extra files which are required for smooth functioning of the bot. By default, log file will be created at `/tmp` folder with name `teamup-rocketchat.log`

### Build for cloud or other targets

Expand Down
15 changes: 13 additions & 2 deletions teamup-rocketchat-bot/config.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Doing so will fail the app to start

# Url of rocket chat server
URL: http://localhost:3000
URL: https://rocket.chat:5000

# bot username
USERNAME: bot
Expand All @@ -28,4 +28,15 @@ TOKEN_TEAMUP: jnfjnf993knjnjfnejkfnejnf

# run the bot in every X interval (mins)
# Keep it between 5 to 10
REPEAT_IN: 5
# default is 5
REPEAT_IN: 5


# path to keep logfile
# default LOG_PATH is /var/log folder
# It will be overriden if logpath flag is provided to bot while running the bot
LOG_PATH: /var/log

# name for the log file
# default log file name is teamup-rocket-chat.log
LOG_FILE_NAME: teamup-rocket-chat.log
135 changes: 135 additions & 0 deletions teamup-rocketchat-bot/configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package main

import (
"fmt"
"net/url"
"os"
"path"

"gopkg.in/yaml.v3"
)

// Configuration holds different options
// required to run the bot
type Configuration struct {
URL string `yaml:"URL"`
Username string `yaml:"USERNAME"`
Password string `yaml:"PASSWORD"`
UseSSL bool `yaml:"USE_SSL"`
Room string `yaml:"ROOM"`
MeetingsCode string `yaml:"MEETINGS_TEAMUP"`
TeamupToken string `yaml:"TOKEN_TEAMUP"`
RepeatIn int `yaml:"REPEAT_IN"`
LogPath string `yaml:"LOG_PATH"`
LogFileName string `yaml:"LOG_FILE_NAME"`
}

// Prints beatiful
func (config Configuration) String() string {
return fmt.Sprintf(
"URL:%s\nUsername:%v\nPassword:%s\nUseSSL:%v\nRoom:%s\nMeetingsCode:%s\nTeamupToken:%s\nRepeatIn:%d\nLogPath:%s\nLogFileName:%s\n",
config.URL,
config.Username,
"hidden-for-security-purpose",
config.UseSSL,
config.Room,
"hidden-for-security-purpose",
"hidden-for-security-purpose",
config.RepeatIn,
config.LogPath,
config.LogFileName,
)

}

// IsUrl does basic url checking
// Scheme must not be empty
func isUrl(str string) bool {
u, err := url.Parse(str)
return err == nil && u.Scheme != "" && u.Host != "" && (u.Scheme == "https" || u.Scheme == "http")
}

// checkValidity checks the validity of the loaded configuration
// and returns error if any field value is not valid
func (config *Configuration) checkValidity(isCustomPath bool) (*Configuration, error) {
if !isUrl(config.URL) {
return nil, fmt.Errorf("invalid URL: %s", config.URL)
}

if len(config.Username) == 0 {
return nil, fmt.Errorf("empty USERNAME field")
}

if len(config.Password) == 0 {
return nil, fmt.Errorf("empty PASSWORD field")
}

if len(config.Room) == 0 {
return nil, fmt.Errorf("empty ROOM field")
}

if len(config.MeetingsCode) == 0 {
return nil, fmt.Errorf("empty MEETINGS_TEAMUP field")
}

if len(config.TeamupToken) == 0 {
return nil, fmt.Errorf("empty TOKEN_TEAMUP field")
}

if len(config.Room) == 0 {
return nil, fmt.Errorf("empty ROOM field")
}
// if only custom path is not provided
if !isCustomPath {
if len(config.LogPath) == 0 {
// set to default
config.LogPath = defaultLogFilePath
} else {
config.LogPath = path.Clean(config.LogPath) // Clean the path user provided location only
}
// Check if the log output folder is accessible
_, err := os.Stat(config.LogPath)
if err != nil {
return nil, fmt.Errorf("the log output folder %s is inaccessible because %s", config.LogPath, err.Error())
}
}

if len(config.LogFileName) == 0 {
// set to default
config.LogFileName = defaultLogFileName
}

if config.RepeatIn == 0 {
// set to default
config.RepeatIn = defaultRepeatIn
}
return config, nil
}

// readConfig reads config.yml files
// and returns config or
// corresponding error if any
func readConfig(filePath string, isCustomPath bool) (*Configuration, error) {
config := Configuration{}

yamlData, err := os.ReadFile(filePath)

// Check for errors
if err != nil {
return nil, err
}

err = yaml.Unmarshal(yamlData, &config)

if err != nil {
return nil, err
}

validconfig, err := config.checkValidity(isCustomPath)

if err != nil {
return &config, err
}

return validconfig, nil
}
34 changes: 34 additions & 0 deletions teamup-rocketchat-bot/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"fmt"
)

// banner for the app
const bannerText = `
░░░░▒█░█▀▀▄░█▀▀▄░█░▄░█▀▀▄░█▀▀▄░░▀░░▀▀█▀▀░█▀▀░█▀▄░█░░░
░░░░▒█░█▄▄█░█░▒█░█▀▄░█▄▄█░█▄▄▀░░█▀░░▒█░░░█▀▀░█░░░█▀▀█
░▒█▄▄█░▀░░▀░▀░░▀░▀░▀░▀░░▀░▀░▀▀░▀▀▀░░▒█░░░▀▀▀░▀▀▀░▀░░▀
`
const about = "About:\tA bot that fetches events from teamup calendar and notifies gophers of JankariTech through rocket.chat"

// displayHelpMessage displays help message
func displayHelpMessage(bannerText string) {

msg := "Usage: teamup-rocketchat-bot --option <value>\n\n"
msg += "Options:\n"
msg += "-h, --help \t Show this screen\n"
msg += "--logpath\t Set the custom logpath. It overrides the log path specified in configuration (config.yml) file\n"
msg += "--config\t Point to the configuration (config) file. It overrides the default configuration file located at app directory\n"
msg += "\nExample:\n"
msg += "teamup-rocketchat-bot --config /home/user/.config/bot/config.yml\n\n\tHere, the bot will read configuration from the pointed file\n\n"
msg += "teamup-rocketchat-bot --logpath /tmp/\n\n\tHere, the configuration (config.yml) will be read from default path (i.e the app directory) and\n\t the log path provided will override the path specified in configuration file\n\n"
msg += "teamup-rocketchat-bot --config /home/user/.config/bot/config.yml --logpath /tmp/\n\n\tHere, the configuration (config.yml) will be read from the pointed file and\n\t the log path provided will override the path specified in configuration file\n\n"
msg += "\nNote:\tMake sure the app has necessary premissions required to read or write at custom locations provided\n"
msg += "\tAlso, trying to run the bot without providing config.yml at app directory and without providing --config switch will result in failure of application start.\n"
fmt.Printf("%s\n%s\n%s\n", bannerText, about, msg)
}

func displayHelpMessageWithoutBanner() {
displayHelpMessage("")
}
3 changes: 1 addition & 2 deletions teamup-rocketchat-bot/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ go 1.19
require (
github.com/badkaktus/gorocket v0.1.3
github.com/go-resty/resty/v2 v2.7.0
github.com/go-yaml/yaml v2.1.0+incompatible
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
6 changes: 2 additions & 4 deletions teamup-rocketchat-bot/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ github.com/badkaktus/gorocket v0.1.3 h1:ON4YQeuHGYdV6CuD759bGUJ8oxTDdhL9PTVH6QYy
github.com/badkaktus/gorocket v0.1.3/go.mod h1:tR6QXhjPxNQGDGqmiQo+r5hyvw4lkhqx4C6KXiN8KHw=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
Expand All @@ -24,5 +22,5 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit cb5ca43

Please sign in to comment.