Browse Source

rpdata-logpaste: Added new commandline tool.

module-madness-pointers 1.1.1
Gisle Aune 6 years ago
parent
commit
7e812bd615
  1. 1
      Dockerfile
  2. 78
      cmd/rpdata-logpaste/main.go
  3. 126
      cmd/rpdata-logpaste/post.go

1
Dockerfile

@ -22,6 +22,7 @@ RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-lb2logim
# TODO: RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-wikifileimport ./cmd/rpdata-wikifileimport
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-ensurechannels ./cmd/rpdata-ensurechannels
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-as2storyimport ./cmd/rpdata-as2storyimport
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/rpdata-logpaste ./cmd/rpdata-logpaste
## 2. Distribute
# Use alpine linux

78
cmd/rpdata-logpaste/main.go

@ -0,0 +1,78 @@
package main
import (
"flag"
"log"
"os"
"time"
"git.aiterp.net/rpdata/api/internal/store"
"git.aiterp.net/rpdata/api/models/posts"
"git.aiterp.net/rpdata/api/models/logs"
)
var dateStr string
var tzStr string
var channel string
var fileName string
func main() {
var inputPosts []Post
flag.StringVar(&dateStr, "date", "2013-04-04", "Date in YYYY-MM-DD form.")
flag.StringVar(&tzStr, "tz", "Europe/Oslo", "Time zone for the date.")
flag.StringVar(&channel, "channel", "#RedrockAgency", "Channel it's set in.")
flag.StringVar(&fileName, "file", "-", "File to read from (- = stdin).")
flag.Parse()
tz, err := time.LoadLocation(tzStr)
if err != nil {
log.Fatalln("Parse timezone:", err)
}
date, err := time.ParseInLocation("2006-01-02", dateStr, tz)
if err != nil {
log.Fatalln("Parse date:", err)
}
err = store.Init()
if err != nil {
log.Fatalln("Init store:", err)
}
if fileName != "-" {
file, fileErr := os.Open(fileName)
if fileErr != nil {
log.Fatalln("Open file:", fileErr)
}
inputPosts, err = parsePosts(file, date)
file.Close()
} else {
inputPosts, err = parsePosts(os.Stdin, date)
}
if err != nil {
log.Fatalln("Read inputPosts:", err)
}
if len(inputPosts) == 0 {
log.Fatalln("Input file contained no posts.")
}
l, err := logs.Add(inputPosts[0].Time, channel, "", "", "", false)
if err != nil {
log.Fatalln("Add log:", err)
}
log.Println("Added log", l.ID)
for _, inputPost := range inputPosts {
p, err := posts.Add(l, inputPost.Time, inputPost.Kind, inputPost.Nick, inputPost.Text)
if err != nil {
log.Fatalln("Add post:", err)
}
log.Println("Added post", p.ID)
}
}

126
cmd/rpdata-logpaste/post.go

@ -0,0 +1,126 @@
package main
import (
"bufio"
"errors"
"io"
"strconv"
"strings"
"time"
)
// ErrNotPost is returned by parsePost if the line is empty or not a post.
var ErrNotPost = errors.New("not a post")
// ErrTooShort is returned by parsePost if the line too short to be a post.
var ErrTooShort = errors.New("post too short")
// ErrInvalidTimestamp is returned by parsePost if the line is empty or not a post.
var ErrInvalidTimestamp = errors.New("invalid timestamp")
// A Post is a part of a log.
type Post struct {
Time time.Time
Kind string
Nick string
Text string
}
func parsePosts(reader io.Reader, date time.Time) ([]Post, error) {
prev := Post{}
posts := make([]Post, 0, 8)
bufReader := bufio.NewReader(reader)
for {
line, err := bufReader.ReadString('\n')
if err != nil && err != io.EOF {
return nil, err
}
if len(line) > 8 {
post, err := parsePost(strings.Trim(line, "  \n\r"), date, prev)
if err != nil {
return nil, err
}
posts = append(posts, post)
prev = post
}
if err == io.EOF {
break
}
}
return posts, nil
}
func parsePost(line string, date time.Time, prev Post) (Post, error) {
// Do basic validation
line = strings.Trim(line, "  \t\n\r")
if len(line) == 0 || !strings.HasPrefix(line, "[") {
return Post{}, ErrNotPost
}
// Parse timestamp
tsEndIndex := strings.IndexByte(line, ']')
if tsEndIndex == -1 || len(line) < tsEndIndex+5 {
return Post{}, ErrNotPost
}
tsStr := line[1:tsEndIndex]
tsSplit := strings.Split(tsStr, ":")
tsUnits := make([]int, len(tsSplit))
if len(tsSplit) < 2 {
return Post{}, ErrNotPost
}
for i := range tsSplit {
n, err := strconv.Atoi(tsSplit[i])
if err != nil {
return Post{}, ErrNotPost
}
tsUnits[i] = n
}
if len(tsUnits) == 2 {
tsUnits = append(tsUnits, 0)
}
ts := time.Date(date.Year(), date.Month(), date.Day(), tsUnits[0], tsUnits[1], tsUnits[2], 0, date.Location())
if !prev.Time.IsZero() && prev.Time.After(ts) {
ts = ts.AddDate(0, 0, 1)
}
if line[tsEndIndex+2] == '*' {
split := strings.SplitN(line[tsEndIndex+4:], " ", 2)
post := Post{
Time: ts,
Kind: "action",
Nick: strings.TrimLeft(split[0], "+@!~"),
Text: split[1],
}
if post.Nick[0] == '=' {
post.Kind = "scene"
}
return post, nil
} else if line[tsEndIndex+2] == '<' {
split := strings.SplitN(line[tsEndIndex+2:], " ", 2)
post := Post{
Time: ts,
Kind: "text",
Nick: strings.TrimLeft(split[0][1:len(split[0])-1], "+@!~"),
Text: split[1],
}
if post.Nick[0] == '=' {
post.Kind = "scene"
}
return post, nil
} else {
return Post{}, ErrNotPost
}
}
Loading…
Cancel
Save