Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[teamup-rocketchat] Added support for custom config file and log path location via cli parameters #13

Merged
merged 4 commits into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
roshanlc marked this conversation as resolved.
Show resolved Hide resolved

# 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 /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
136 changes: 136 additions & 0 deletions teamup-rocketchat-bot/configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
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,
config.Password,
roshanlc marked this conversation as resolved.
Show resolved Hide resolved
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)
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