github.com/Ptt-official-app/go-bbs@v0.12.0/user_comment_record.go (about) 1 package bbs 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 "time" 8 ) 9 10 var ( 11 ErrNotUserComment = fmt.Errorf("data is not a user comment") 12 ErrUserCommentEmptyUserID = fmt.Errorf("user comment has empty name") 13 ErrUserCommentEmptyComment = fmt.Errorf("user comment detail has empty") 14 ) 15 16 var ( 17 userCommentPattern = regexp.MustCompile(`([a-zA-Z][a-zA-Z0-9]+):.*([0-9][0-9]\/[0-9][0-9]\s[0-9][0-9]:[0-9][0-9])`) 18 ) 19 20 type UserCommentRecord interface { 21 CommentOrder() uint32 22 CommentTime() time.Time 23 Owner() string 24 IP() string 25 Comment() string 26 String() string 27 BoardID() string 28 Filename() string 29 } 30 31 var _ UserCommentRecord = &userCommentRecord{} 32 33 type userCommentRecord struct { 34 commentOrder uint32 35 commentTime time.Time 36 owner string 37 ip string 38 boardID string 39 filename string 40 comment string 41 } 42 43 // NewUserCommentRecord parses the data and returns the user comment record. 44 // Return error when input data is not matched the user comment pattern. 45 func NewUserCommentRecord(order uint32, data string, boardID string, ar ArticleRecord) (UserCommentRecord, error) { 46 owner, ctime, comment, err := parseUserComment(data) 47 if err != nil { 48 return nil, err 49 } 50 return &userCommentRecord{ 51 commentOrder: order, 52 commentTime: ctime, 53 owner: owner, 54 ip: "", // TODO 55 boardID: boardID, 56 filename: ar.Filename(), 57 comment: comment, 58 }, nil 59 } 60 61 func (r userCommentRecord) CommentOrder() uint32 { 62 return r.commentOrder 63 } 64 65 func (r userCommentRecord) CommentTime() time.Time { 66 return r.commentTime 67 } 68 69 func (r userCommentRecord) Owner() string { 70 return r.owner 71 } 72 73 func (r userCommentRecord) IP() string { 74 return r.ip 75 } 76 77 func (r userCommentRecord) Comment() string { 78 return r.comment 79 } 80 81 func (r userCommentRecord) String() string { 82 return fmt.Sprintf("order: %d, owner: %s, time: %s", r.commentOrder, r.owner, r.commentTime.Format("01/02 15:04")) 83 } 84 85 func (r userCommentRecord) BoardID() string { 86 return r.boardID 87 } 88 89 func (r userCommentRecord) Filename() string { 90 return r.filename 91 } 92 93 // parseUserComment returns the owner and time of comment data. 94 // Return ErrNotUserComment error when data doesn't match to the pattern. 95 // Return other error when data contains the ambiguous value which can't parse. 96 func parseUserComment(data string) (owner string, ctime time.Time, comment string, err error) { 97 matches := userCommentPattern.FindStringSubmatch(data) 98 // The 1st record is entire matched result of row. 99 // The 2nd record is group owner result, EX: "pichu". 100 const ownerIdx = 1 101 // The 3rd record is group time result, EX: "05/15 01:06". 102 const timeIdx = 2 103 104 const commentIdx = 0 105 106 if len(matches) < 3 { 107 err = ErrNotUserComment 108 return 109 } 110 111 owner = matches[ownerIdx] 112 if len(owner) == 0 { 113 err = ErrUserCommentEmptyUserID 114 return 115 } 116 117 ctimeStr := matches[timeIdx] 118 ctime, err = time.Parse("01/02 15:04", ctimeStr) 119 if err != nil { 120 return 121 } 122 123 commentStr := matches[commentIdx] 124 if len(commentStr) == 0 { 125 err = ErrUserCommentEmptyComment 126 return 127 } 128 129 //TODO: improve get comment 130 ownStr := ":" 131 commentTimeRemoveArr := strings.Split(commentStr, ctimeStr) 132 commentArr := strings.Split(commentTimeRemoveArr[0], ownStr) 133 134 for key, value := range commentArr { 135 //key 0 為使用者名稱,跳過 136 if key == 0 { 137 continue 138 } 139 comment += strings.TrimSpace(value) 140 //key 2 開始才會有重複冒號的問題 141 if key >= 2 { 142 comment += ":" 143 } 144 } 145 146 return owner, ctime, comment, nil 147 }