-
Notifications
You must be signed in to change notification settings - Fork 0
/
posts.go
134 lines (126 loc) · 3.16 KB
/
posts.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
123
124
125
126
127
128
129
130
131
132
133
134
package stackoverflow
import (
"encoding/xml"
"fmt"
"log"
"strconv"
"strings"
"time"
)
// http://meta.stackexchange.com/questions/2677/database-schema-documentation-for-the-public-data-dump-and-sede?rq=1
const (
PostQuestion = 1
PostAnswer = 2
PostOrphanedTagWiki = 3
PostTagWikiExcerpt = 4
PostTagWiki = 5
PostModeratorNomination = 6
PostWikiPlaceholder = 7
PostPrivilegeWiki = 8
)
// Post describes a post
type Post struct {
ID int
PostTypeID int
ParentID int // for PostAnswer
AcceptedAnswerID int
CreationDate time.Time
Score int
ViewCount int
Body string
OwnerUserID int
OwnerDisplayName string
LastEditorUserID int
LastEditorDisplayName string
LastEditDate time.Time
LastActivitityDate time.Time
Title string
Tags []string
AnswerCount int
CommentCount int
FavoriteCount int
CommunityOwnedDate time.Time
ClosedDate time.Time
}
var nTagsToShow = 0
func decodeTags(s string) []string {
// tags are in the format: <foo><bar>
s = strings.TrimPrefix(s, "<")
s = strings.TrimSuffix(s, ">")
tags := strings.Split(s, "><")
if nTagsToShow > 0 {
nTagsToShow--
fmt.Printf("tags: '%s' => %v\n", s, tags)
}
return tags
}
func decodePostAttr(attr xml.Attr, p *Post) error {
var err error
name := strings.ToLower(attr.Name.Local)
v := attr.Value
switch name {
case "id":
p.ID, err = strconv.Atoi(v)
case "parentid":
p.ParentID, err = strconv.Atoi(v)
case "posttypeid":
p.PostTypeID, err = strconv.Atoi(v)
case "acceptedanswerid":
p.AcceptedAnswerID, err = strconv.Atoi(v)
case "creationdate":
p.CreationDate, err = decodeTime(v)
case "score":
p.Score, err = strconv.Atoi(v)
case "viewcount":
p.ViewCount, err = strconv.Atoi(v)
case "body":
p.Body = v
case "owneruserid":
p.OwnerUserID, err = strconv.Atoi(v)
case "ownerdisplayname":
p.OwnerDisplayName = v
case "lasteditoruserid":
p.LastEditorUserID, err = strconv.Atoi(v)
case "lasteditordisplayname":
p.LastEditorDisplayName = v
case "lasteditdate":
p.LastEditDate, err = decodeTime(v)
case "lastactivitydate":
p.LastActivitityDate, err = decodeTime(v)
case "title":
p.Title = v
case "tags":
p.Tags = decodeTags(v)
case "answercount":
p.AnswerCount, err = strconv.Atoi(v)
case "commentcount":
p.CommentCount, err = strconv.Atoi(v)
case "favoritecount":
p.FavoriteCount, err = strconv.Atoi(v)
case "communityowneddate":
p.CommunityOwnedDate, err = decodeTime(v)
case "closeddate":
p.ClosedDate, err = decodeTime(v)
default:
err = fmt.Errorf("unknown post field: '%s'", name)
}
return err
}
func validatePost(p *Post) {
if p.PostTypeID < 1 || p.PostTypeID > 8 {
log.Fatalf("invalid PostTypeID: %d\n", p.PostTypeID)
}
}
func decodePostRow(t xml.Token, p *Post) error {
// have been checked before that this is "row" element
*p = Post{}
e, _ := t.(xml.StartElement)
for _, attr := range e.Attr {
err := decodePostAttr(attr, p)
if err != nil {
return err
}
}
validatePost(p)
return nil
}