-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathTibiaGuildsGuild.go
More file actions
291 lines (251 loc) · 11.6 KB
/
Copy pathTibiaGuildsGuild.go
File metadata and controls
291 lines (251 loc) · 11.6 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
package main
import (
"fmt"
"net/http"
"regexp"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/tibiadata/tibiadata-api-go/src/validation"
)
// Child of Guild
type Guildhall struct {
Name string `json:"name"` // The name of the house.
World string `json:"world"` // The world the guildhall belongs to.
/*
Town string `json:"town"` // We can collect that from cached info?
Status string `json:"status"` // rented (but maybe also auctioned)
Owner string `json:"owner"` // We can collect that from cached info?
HouseID int `json:"houseid"` // We can collect that from cached info?
*/
PaidUntil string `json:"paid_until"` // The date the last paid rent is due.
}
// Child of Guild
type GuildMember struct {
Name string `json:"name"` // The name of the guild's member.
Title string `json:"title"` // The member's title.
Rank string `json:"rank"` // The rank the member does belong to.
Vocation string `json:"vocation"` // The member's vocation.
Level int `json:"level"` // The member's level.
Joined string `json:"joined"` // The day when the member joined.
Status string `json:"status"` // Whether the member is online or offline.
}
// Child of Guild
type InvitedGuildMember struct {
Name string `json:"name"` // The name of the character.
Date string `json:"date"` // The date the character was invited.
}
// Child of JSONData
type Guild struct {
Name string `json:"name"` // The name of the guild.
World string `json:"world"` // The world the guild belongs to.
LogoURL string `json:"logo_url"` // The URL to the guild's logo.
Description string `json:"description"` // The description of the guild.
Guildhalls []Guildhall `json:"guildhalls"` // The guildhall the guild has as their home.
Active bool `json:"active"` // Whether the guild is active or in formation.
Founded string `json:"founded"` // The day it was founded.
Applications bool `json:"open_applications"` // Whether applications are open or not.
Homepage string `json:"homepage"` // The guild's homepage.
InWar bool `json:"in_war"` // Whether it is currently in war or not.
DisbandedDate string `json:"disband_date"` // The date when the guild will be disbanded, if the condition aren't meet.
DisbandedCondition string `json:"disband_condition"` // The reason why the guild will get disbanded.
PlayersOnline int `json:"players_online"` // The number of online members in the guild.
PlayersOffline int `json:"players_offline"` // The number of offline members in the guild.
MembersTotal int `json:"members_total"` // The number of total members in the guild.
MembersInvited int `json:"members_invited"` // The number of invited members in the guild.
Members []GuildMember `json:"members"` // List of all members in the guild.
Invited []InvitedGuildMember `json:"invites"` // List of invited members.
}
// The base includes two levels: Guild and Information
type GuildResponse struct {
Guild Guild `json:"guild"`
Information Information `json:"information"`
}
var (
GuildLogoRegex = regexp.MustCompile(`.*img src="(.*)" width=.*`)
GuildWorldAndFoundationRegex = regexp.MustCompile(`^The guild was founded on (.*) on (.*).<br/>`)
GuildHomepageRegex = regexp.MustCompile(`<a href="(.*)" target=.*>`)
GuildhallRegex = regexp.MustCompile(` is (.*). The rent is paid until (.*).<br/>`)
GuildDisbaneRegex = regexp.MustCompile(`<b>It will be disbanded on (.*.[0-9]+.[0-9]+) (.*)\.<\/b>.*`)
GuildMemberInformationRegex = regexp.MustCompile(`<td>(.*)<\/td><td><a.*">(.*)<\/a>(.*)<\/td><td>(.*)<\/td><td>([0-9]+)<\/td><td>(.*)<\/td><td class.*class.*">(.*)<\/span><\/td>`)
GuildMemberInvitesInformationRegex = regexp.MustCompile(`<td><a.*">(.*)<\/a><\/td><td>(.*)<\/td>`)
)
func TibiaGuildsGuildImpl(guild string, BoxContentHTML string, url string) (GuildResponse, error) {
// Creating empty vars
var (
MembersData []GuildMember
InvitedData []InvitedGuildMember
GuildGuildhallData []Guildhall
MembersRank, MembersTitle, MembersStatus, GuildDescription, GuildDisbandedDate, GuildDisbandedCondition, GuildHomepage, GuildWorld, GuildLogoURL, GuildFounded string
GuildActive, GuildApplications, GuildInWar, GuildDescriptionFinished bool
MembersCountOnline, MembersCountOffline, MembersCountInvited int
)
// Loading HTML data into ReaderHTML for goquery with NewReader
ReaderHTML, err := goquery.NewDocumentFromReader(strings.NewReader(BoxContentHTML))
if err != nil {
return GuildResponse{}, fmt.Errorf("[error] TibiaGuildsGuildImpl failed at goquery.NewDocumentFromReader, err: %s", err)
}
guildName, err := ReaderHTML.Find("h1").First().Html()
if err != nil {
return GuildResponse{}, fmt.Errorf("[error] TibiaGuildsGuildImpl failed at ReaderHTML.Find, err: %s", err)
}
if guildName == "" {
return GuildResponse{}, validation.ErrorGuildNotFound
}
// Getting data from div.InnerTableContainer and then first p
InnerTableContainerTMPA, err := ReaderHTML.Find(".BoxContent table").Html()
if err != nil {
return GuildResponse{}, fmt.Errorf("[error] TibiaGuildsGuildImpl failed at InnerTableContainerTMPA ReaderHTML.Find, err: %s", err)
}
subma1b := GuildLogoRegex.FindAllStringSubmatch(InnerTableContainerTMPA, -1)
if len(subma1b) > 0 {
GuildLogoURL = subma1b[0][1]
}
// Getting data from div.InnerTableContainer and then first p
InnerTableContainerTMPB, err := ReaderHTML.Find("#GuildInformationContainer").Html()
if err != nil {
return GuildResponse{}, fmt.Errorf("[error] TibiaGuildsGuildImpl failed at InnerTableContainerTMPB ReaderHTML.Find, err: %s", err)
}
for line := range strings.SplitSeq(strings.TrimSuffix(InnerTableContainerTMPB, "\n"), "\n") {
// Guild information
if !GuildDescriptionFinished {
// First line is the description..
GuildDescription += strings.ReplaceAll(line+"\n", "<br/><br/>\n", "")
// Abort loop and continue wiht next section
if strings.Contains(line, "<br/><br/>") {
GuildDescription = strings.TrimSpace(TibiaDataSanitizeEscapedString(GuildDescription))
GuildDescriptionFinished = true
}
}
if GuildDescriptionFinished || strings.HasPrefix(line, "The guild was founded on ") {
// The rest of the Guild information
if strings.HasPrefix(GuildDescription, "The guild was founded on ") {
GuildDescription = ""
GuildDescriptionFinished = true
}
if strings.HasPrefix(line, "The guild was founded on") {
// Regex to get GuildWorld and GuildFounded
subma1b := GuildWorldAndFoundationRegex.FindAllStringSubmatch(line, -1)
if len(subma1b) != 0 {
GuildWorld = subma1b[0][1]
GuildFounded = TibiaDataDate(subma1b[0][2])
}
}
// If to get GuildActive
if strings.HasPrefix(line, "It is currently active") {
GuildActive = true
}
// If open for applications
if strings.HasPrefix(line, "Guild is opened for applications.") {
GuildApplications = true
} else if strings.HasPrefix(line, "Guild is closed for applications during war.") {
GuildInWar = true
}
if strings.HasPrefix(line, "The official homepage is") {
subma1c := GuildHomepageRegex.FindAllStringSubmatch(line, -1)
GuildHomepage = subma1c[0][1]
}
// If guildhall
if strings.HasPrefix(line, "Their home on "+GuildWorld) {
subma1b := GuildhallRegex.FindAllStringSubmatch(line, -1)
GuildGuildhallData = append(GuildGuildhallData, Guildhall{
Name: TibiaDataSanitizeEscapedString(subma1b[0][1]),
World: GuildWorld,
PaidUntil: TibiaDataDate(subma1b[0][2]),
})
}
// If disbanded
if strings.HasPrefix(line, "<b>It will be disbanded on ") {
subma1c := GuildDisbaneRegex.FindAllStringSubmatch(line, -1)
if len(subma1c) > 0 {
GuildDisbandedDate = TibiaDataDate(subma1c[0][1])
GuildDisbandedCondition = subma1c[0][2]
}
}
}
}
var insideError error
// Running query over each div
ReaderHTML.Find(".TableContentContainer .TableContent tbody tr").EachWithBreak(func(index int, s *goquery.Selection) bool {
// Storing HTML into GuildsDivHTML
GuildsDivHTML, err := s.Html()
if err != nil {
insideError = fmt.Errorf("[error] TibiaGuildsGuildImpl failed at GuildsDivHTML, err := s.Html(), err: %s", err)
return false
}
// Removing linebreaks from HTML
GuildsDivHTML = TibiaDataHTMLRemoveLinebreaks(GuildsDivHTML)
// Regex to get data for record values
subma1 := GuildMemberInformationRegex.FindAllStringSubmatch(GuildsDivHTML, -1)
if len(subma1) > 0 {
// Rank name
if TibiaDataSanitizeStrings(subma1[0][1]) != " " {
MembersRank = subma1[0][1]
}
// Title
MembersTitle = strings.ReplaceAll(strings.ReplaceAll(subma1[0][3], " (", ""), ")", "")
// Status
if strings.Contains(subma1[0][7], "online") {
MembersStatus = "online"
MembersCountOnline++
} else {
MembersStatus = "offline"
MembersCountOffline++
}
MembersData = append(MembersData, GuildMember{
Name: TibiaDataSanitizeStrings(subma1[0][2]),
Title: MembersTitle,
Rank: MembersRank,
Vocation: subma1[0][4],
Level: TibiaDataStringToInteger(subma1[0][5]),
Joined: TibiaDataDate(subma1[0][6]),
Status: MembersStatus,
})
} else {
// Regex to get data for record values
subma2 := GuildMemberInvitesInformationRegex.FindAllStringSubmatch(GuildsDivHTML, -1)
if len(subma2) > 0 {
MembersCountInvited++
InvitedData = append(InvitedData, InvitedGuildMember{
Name: TibiaDataSanitizeStrings(subma2[0][1]),
Date: TibiaDataDate(subma2[0][2]),
})
}
}
return true
})
if insideError != nil {
return GuildResponse{}, insideError
}
//
// Build the data-blob
return GuildResponse{
Guild{
Name: guildName,
World: GuildWorld,
LogoURL: GuildLogoURL,
Description: GuildDescription,
Guildhalls: GuildGuildhallData,
Active: GuildActive,
Founded: GuildFounded,
Applications: GuildApplications,
Homepage: GuildHomepage,
InWar: GuildInWar,
DisbandedDate: GuildDisbandedDate,
DisbandedCondition: GuildDisbandedCondition,
PlayersOnline: MembersCountOnline,
PlayersOffline: MembersCountOffline,
MembersTotal: (MembersCountOnline + MembersCountOffline),
MembersInvited: MembersCountInvited,
Members: MembersData,
Invited: InvitedData,
},
Information{
APIDetails: TibiaDataAPIDetails,
Timestamp: TibiaDataDatetime(""),
TibiaURLs: []string{url},
Status: Status{
HTTPCode: http.StatusOK,
},
},
}, nil
}