* NTP-24894 | Text change in slack modal. * NTP-24894 | Adding more constant teamTypes. * NTP-24894 | Added functions to allow for teamType update. * NTP-24894 | Added validation in addTeamRequest. * NTP-24894 | Comment resolution and new functions (#477) * NTP-24894 | Added filter on Reporting teams. * NTP-24894 | Added new function for all teams fetch in team service. * NTP-24894 | sending all teams in response for slack modal. * NTP-24894 | Added tests for UpdateTeam flow. * NTP-24894 | Fixing logic and using util. * NTP-24894 | Using enum-map for teamType validation. * NTP-24894 | Variable name change. * NTP-24894 | Adding teamType to TeamDTOs when fetching using productid. * NTP-24894 | Revisions in function for team population. * NTP-24894 | Removed unneeded function. * NTP-24894 | Removed unneeded interface of function * NTP-24894 | Updated test scripts. * NTP-24894 | Logic changes, modal text change. * NTP-24894 | Using ID for first occurence, updated tests. * NTP-40086 | Selective filtering based on Product. * NTP-40086 | Updated tests for incident_orch. * NTP-40086 | replaced with constants. * NTP-24894 | Moved functions to teamService. * NTP-40086 | added new function in repo for filtering during fetch. * NTP-40086 | Removed unused function. * NTP-40086 | added tests and removed interface of previously removed fuc. * NTP-40086 | Added direct filtering function during data fetch from repo. * NTP-40086 | Refactoring and adding more tests. * NTP-24894 | Text changed in incident summary. * NTP-40086 | Refactoring function. * NTP-40086 | Editting team service for unused functions. * NTP-40086 | Added new util function for generic intersection. * NTP-40086 | Text changed at multiple places. * NTP-40086 | Text change. * NTP-40086 | text change. * NTP-40086 | Added flags for reporter teams fetch. * NTP-240086 | changes in test. * NTP-40086 | Using GenericFilter instead of query based filtering.
356 lines
9.0 KiB
Go
356 lines
9.0 KiB
Go
package util
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/lib/pq"
|
|
"github.com/slack-go/slack"
|
|
"github.com/slack-go/slack/socketmode"
|
|
"golang.org/x/exp/slices"
|
|
"gorm.io/gorm"
|
|
"houston/logger"
|
|
"math"
|
|
"reflect"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
func SplitUntilWord(input, stopWord string) (string, string) {
|
|
// Convert both input and stopWord to lowercase for case-insensitive matching
|
|
lowercaseInput := strings.ToLower(input)
|
|
lowercaseStopWord := strings.ToLower(stopWord)
|
|
|
|
// Find the index of the stopWord in the lowercase input
|
|
stopIndex := strings.Index(lowercaseInput, lowercaseStopWord)
|
|
|
|
if stopIndex == -1 {
|
|
// If stopWord is not found, return the entire input as the first part
|
|
return input, ""
|
|
}
|
|
|
|
// Return the part of the input before the stopWord and the part after the stopWord
|
|
return strings.TrimSpace(input[:stopIndex]), strings.TrimSpace(input[stopIndex+len(stopWord):])
|
|
}
|
|
|
|
func RollbackTransaction(tx *gorm.DB) {
|
|
if r := recover(); r != nil {
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
}
|
|
|
|
func RemoveDuplicate[T string | uint](sliceList []T) []T {
|
|
allKeys := make(map[T]bool)
|
|
list := []T{}
|
|
for _, item := range sliceList {
|
|
if _, value := allKeys[item]; !value {
|
|
allKeys[item] = true
|
|
list = append(list, item)
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
|
|
// GetTimeElapsedInDaysAndHours - returns number of days and hours elapsed since the timestamp passed in argument
|
|
func GetTimeElapsedInDaysAndHours(timestamp time.Time) (int, int) {
|
|
// convert to IST time
|
|
locationName := "Asia/Kolkata"
|
|
location, err := time.LoadLocation(locationName)
|
|
if err != nil {
|
|
logger.Error(fmt.Sprintf("failed to load location for locationName %s", locationName))
|
|
}
|
|
timestampInIST := timestamp.In(location)
|
|
currentTimeInIST := time.Now().In(location)
|
|
// Calculate the time difference
|
|
timeDiff := currentTimeInIST.Sub(timestampInIST)
|
|
|
|
// Convert the duration into days and hours
|
|
days := int(timeDiff.Hours() / 24)
|
|
hours := int(timeDiff.Hours()) % 24
|
|
return days, hours
|
|
}
|
|
|
|
// Difference : finds difference of two slices and returns a new slice
|
|
func Difference(s1, s2 []string) []string {
|
|
combinedSlice := append(s1, s2...)
|
|
m := make(map[string]int)
|
|
for _, v := range combinedSlice {
|
|
if _, ok := m[v]; ok {
|
|
// remove element later as it exist in both slice.
|
|
m[v] += 1
|
|
continue
|
|
}
|
|
// new entry, add in map!
|
|
m[v] = 1
|
|
}
|
|
var result []string
|
|
for k, v := range m {
|
|
if v == 1 {
|
|
result = append(result, k)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func GetDifference[T comparable](s1, s2 []T) []T {
|
|
combinedSlice := append(s1, s2...)
|
|
m := make(map[T]int)
|
|
for _, v := range combinedSlice {
|
|
if _, ok := m[v]; ok {
|
|
// remove element later as it exists in both slices.
|
|
m[v] += 1
|
|
continue
|
|
}
|
|
// new entry, add to the map!
|
|
m[v] = 1
|
|
}
|
|
|
|
var result []T
|
|
for k, v := range m {
|
|
if v == 1 {
|
|
result = append(result, k)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func Intersection(s1, s2 []string) (inter []string) {
|
|
hash := make(map[string]bool)
|
|
for _, e := range s1 {
|
|
hash[e] = true
|
|
}
|
|
for _, e := range s2 {
|
|
// If elements present in the hashmap then append intersection list.
|
|
if hash[e] {
|
|
inter = append(inter, e)
|
|
}
|
|
}
|
|
//Remove dups from slice.
|
|
inter = RemoveDuplicate(inter)
|
|
return
|
|
}
|
|
|
|
func GenericIntersection[T any, K comparable](s1, s2 []T, keyExtractor func(T) K) []T {
|
|
set := make(map[K]struct{})
|
|
var intersect []T
|
|
|
|
for _, v := range s1 {
|
|
set[keyExtractor(v)] = struct{}{}
|
|
}
|
|
|
|
for _, v := range s2 {
|
|
if _, exists := set[keyExtractor(v)]; exists {
|
|
intersect = append(intersect, v)
|
|
}
|
|
}
|
|
return intersect
|
|
}
|
|
|
|
func GenericFilter[T any, K comparable](s1 []T, s2 []K, keyExtractor func(T) K) []T {
|
|
set := make(map[K]struct{})
|
|
var filteredList []T
|
|
|
|
for _, v := range s2 {
|
|
set[v] = struct{}{}
|
|
}
|
|
|
|
for _, v := range s1 {
|
|
if _, exists := set[keyExtractor(v)]; exists {
|
|
filteredList = append(filteredList, v)
|
|
}
|
|
}
|
|
|
|
return filteredList
|
|
}
|
|
|
|
// Contains checks if the given string exists on the slice of string and returns boolean
|
|
func Contains[S ~[]E, E comparable](s S, v E) bool {
|
|
return slices.Contains(s, v)
|
|
}
|
|
|
|
func GetColorBySeverity(severityId uint) string {
|
|
switch severityId {
|
|
case 1:
|
|
return "#fc3838"
|
|
case 2:
|
|
return "#fc9338"
|
|
case 3:
|
|
return "#ebfa1b"
|
|
case 4:
|
|
return "#7288db"
|
|
default:
|
|
return "#203da7"
|
|
}
|
|
}
|
|
|
|
func PostIncidentStatusUpdateMessage(userId, updatedStatus, channelId string, client *socketmode.Client) error {
|
|
msgOption := slack.MsgOptionText(fmt.Sprintf("<@%s> > set status to %s", userId, updatedStatus), false)
|
|
_, _, errMessage := client.PostMessage(channelId, msgOption)
|
|
return errMessage
|
|
}
|
|
|
|
func PostIncidentTypeUpdateMessage(
|
|
userId, updatedTeam, severity, severityDesc, incidentName, incidentTitle, channelId string, client *socketmode.Client) error {
|
|
txt := fmt.Sprintf("<@%s> *>* set the channel topic: *%s · %s (%s) %s* | %s", userId, updatedTeam, severity, severityDesc, incidentName, incidentTitle)
|
|
att := slack.Attachment{
|
|
Text: txt,
|
|
Color: "#808080", // Grey color code
|
|
MarkdownIn: []string{"text"}, // Define which fields support markdown
|
|
}
|
|
_, _, errMessage := client.PostMessage(channelId, slack.MsgOptionAttachments(att))
|
|
return errMessage
|
|
}
|
|
|
|
func RemoveDuplicateStr(strSlice []string) []string {
|
|
allKeys := make(map[string]bool)
|
|
list := []string{}
|
|
for _, item := range strSlice {
|
|
if _, value := allKeys[item]; !value {
|
|
allKeys[item] = true
|
|
list = append(list, item)
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
|
|
func RemoveString(slice []string, strToRemove string) []string {
|
|
result := make([]string, 0)
|
|
for _, str := range slice {
|
|
if str != strToRemove {
|
|
result = append(result, str)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func ExecuteConcurrentAction(waitGroup *sync.WaitGroup, concurrentTask func()) {
|
|
defer waitGroup.Done()
|
|
concurrentTask()
|
|
}
|
|
|
|
func CalculateDifferenceInDays(fromTime, toTime time.Time) int {
|
|
fromDate := time.Date(fromTime.Year(), fromTime.Month(), fromTime.Day(), 0, 0, 0, 0, time.UTC)
|
|
toDate := time.Date(toTime.Year(), toTime.Month(), toTime.Day(), 0, 0, 0, 0, time.UTC)
|
|
return int(math.Abs(toDate.Sub(fromDate).Hours() / 24))
|
|
}
|
|
|
|
func PostMessageToIncidentChannel(message string, channelId string, client *socketmode.Client) error {
|
|
msgOption := slack.MsgOptionText(message, false)
|
|
_, _, errMessage := client.PostMessage(channelId, msgOption)
|
|
return errMessage
|
|
}
|
|
|
|
func ConvertSliceToMapOfString(input []string) map[string]string {
|
|
output := make(map[string]string)
|
|
for _, item := range input {
|
|
output[item] = item
|
|
}
|
|
return output
|
|
}
|
|
|
|
type CompareArrayResults struct {
|
|
UniqueElementsInArrayA []string
|
|
UniqueElementsInArrayB []string
|
|
CommonElements []string
|
|
}
|
|
|
|
// CompareAndGetStringArrayResults Takes two arrays as inputs and returns the common values of two arrays and unique values of both arrays
|
|
func CompareAndGetStringArrayResults(arrayA []string, arrayB []string) CompareArrayResults {
|
|
uniqueInA := make([]string, 0)
|
|
uniqueInB := make([]string, 0)
|
|
common := make([]string, 0)
|
|
map1 := make(map[string]bool)
|
|
map2 := make(map[string]bool)
|
|
for _, val := range arrayA {
|
|
map1[val] = true
|
|
}
|
|
for _, val := range arrayB {
|
|
map2[val] = true
|
|
}
|
|
for key := range map2 {
|
|
if _, ok := map1[key]; !ok {
|
|
uniqueInB = append(uniqueInB, key) //if element not present in map2 append elements in toBeAdded slice
|
|
} else {
|
|
common = append(common, key) // Add common elements
|
|
}
|
|
}
|
|
for key := range map1 {
|
|
if _, ok := map2[key]; !ok {
|
|
uniqueInA = append(uniqueInA, key) //if element not present in map2 append elements in toBeAdded slice
|
|
}
|
|
}
|
|
return CompareArrayResults{uniqueInA, uniqueInB, common}
|
|
}
|
|
|
|
func IsBlank(input string) bool {
|
|
trimmedInput := strings.TrimSpace(input)
|
|
return trimmedInput == ""
|
|
}
|
|
|
|
func GetFileExtensionFromMimeType(mimeType ContentType) string {
|
|
switch mimeType {
|
|
case ContentTypeTextHTML:
|
|
return ".html"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func AreTwoPqInt32ArraysEqual(arrayA pq.Int32Array, arrayB pq.Int32Array) bool {
|
|
if len(arrayA) != len(arrayB) {
|
|
return false
|
|
}
|
|
|
|
for index, value := range arrayA {
|
|
if value != arrayB[index] {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func RemoveDuplicates(slice interface{}, fieldName string) interface{} {
|
|
v := reflect.ValueOf(slice)
|
|
if v.Kind() != reflect.Slice {
|
|
panic("RemoveDuplicates: not a slice")
|
|
}
|
|
|
|
// Create a map to store unique values
|
|
seen := make(map[interface{}]struct{})
|
|
elementType := v.Type().Elem()
|
|
|
|
// Get the field index by name
|
|
fieldIndex := -1
|
|
for i := 0; i < elementType.NumField(); i++ {
|
|
if elementType.Field(i).Name == fieldName {
|
|
fieldIndex = i
|
|
break
|
|
}
|
|
}
|
|
|
|
// If field doesn't exist, panic
|
|
if fieldIndex == -1 {
|
|
panic("RemoveDuplicates: field not found")
|
|
}
|
|
|
|
// Create a new slice without duplicates
|
|
resultSlice := reflect.MakeSlice(reflect.SliceOf(elementType), 0, v.Len())
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
fieldValue := v.Index(i).Field(fieldIndex).Interface()
|
|
|
|
// If value is not seen before, add it to the result slice and mark it as seen
|
|
if _, ok := seen[fieldValue]; !ok {
|
|
resultSlice = reflect.Append(resultSlice, v.Index(i))
|
|
seen[fieldValue] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return resultSlice.Interface()
|
|
}
|
|
|
|
func GetFunctionName(i interface{}) string {
|
|
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
|
}
|