-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
122 lines (110 loc) · 3.06 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package cdrcsv
import (
"encoding/csv"
"fmt"
"io"
"os"
"strings"
)
const (
DateFormat = "2006-01-02 15:04:05"
)
type Record struct {
Accountcode string
Src string
Dst string
Dcontext string
CallerId string
Channel string
DstChannel string
LastApp string
LastData string
Start string
Answer string
End string
Duration string
Billsec string
Disposition CallState
AmaFlag AmaFlag
Userfield string
UniqueId string
}
func (c *Record) ToCsvString() string {
//TODO: escape all fields, not only the caller id
escapedCallerId := strings.ReplaceAll(c.CallerId, "\"", "\"\"")
return "\"" + c.Accountcode +
"\",\"" + c.Src + "\",\"" + c.Dst + "\",\"" + c.Dcontext + "\",\"" + escapedCallerId + "\",\"" + c.Channel + "\",\"" + c.DstChannel + "\",\"" + c.LastApp + "\",\"" + c.LastData + "\",\"" + c.Start + "\",\"" + c.Answer + "\",\"" + c.End + "\"," + c.Duration + "," + c.Billsec + ",\"" + string(c.Disposition) + "\",\"" + string(c.AmaFlag) + "\",\"" + c.UniqueId + "\",\"" + c.Userfield + "\""
}
type File struct {
Records []*Record
}
//WriteAsCsvWithoutHeader writes a CDR file in CSV format to the specified writer.
func (f *File) WriteAsCsvWithoutHeader(writer io.Writer) error {
for _, record := range f.Records {
line := record.ToCsvString()
_, err := io.WriteString(writer, line+"\n")
if err != nil {
return fmt.Errorf("could not export record: %v", err)
}
}
return nil
}
func ReadWithoutHeaderFromFile(filename string) (File, error) {
file, err := os.Open(filename)
if err != nil {
return File{}, err
}
defer func() {
_ = file.Close()
}()
return ReadWithoutHeader(file)
}
//ReadWithoutHeader reads a CDR csv-file from the specified reader and returns the record file.
func ReadWithoutHeader(reader io.Reader) (File, error) {
csvReader := csv.NewReader(reader)
csvReader.TrimLeadingSpace = true
csvReader.FieldsPerRecord = 18
lines, err := csvReader.ReadAll()
if err != nil {
return File{}, fmt.Errorf("could not read csv records: %v", err)
}
result := make([]*Record, 0, len(lines))
for _, line := range lines {
record := Record{}
record.Accountcode = line[0]
record.Src = line[1]
record.Dst = line[2]
record.Dcontext = line[3]
record.CallerId = line[4]
record.Channel = line[5]
record.DstChannel = line[6]
record.LastApp = line[7]
record.LastData = line[8]
record.Start = line[9]
record.Answer = line[10]
record.End = line[11]
record.Duration = line[12]
record.Billsec = line[13]
record.Disposition = CallState(line[14])
record.AmaFlag = AmaFlag(line[15])
record.UniqueId = line[16]
record.Userfield = line[17]
result = append(result, &record)
}
return File{Records: result}, nil
}
type CallState string
const (
ANSWERED CallState = "ANSWERED"
NO_ANSWER CallState = "NO_ANSWER"
BUSY CallState = "BUSY"
FAILED CallState = "FAILED"
UNKNOWN CallState = "UNKNOWN"
)
type AmaFlag string
const (
OMIT AmaFlag = "OMIT"
BILLING AmaFlag = "BILLING"
DOCUMENTATION AmaFlag = "DOCUMENTATION"
UNKOWN AmaFlag = "Unkown"
)