Passed
Push — master ( dce2be...48a46d )
by Viktor
01:42
created

bot.GetPlayerByID   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
package bot
2
3
import (
4
	"encoding/json"
5
	"errors"
6
	"fmt"
7
	"github.com/bwmarrin/discordgo"
8
	"net/http"
9
	"strings"
10
	"time"
11
)
12
13
// SearchResult contains search response
0 ignored issues
show
introduced by
comment on exported type AlbionSearchResult should be of the form "AlbionSearchResult ..." (with optional leading article)
Loading history...
14
type AlbionSearchResult struct {
15
	Guilds  []AlbionGuildSearch  `json:"guilds"`
16
	Players []AlbionPlayerSearch `json:"players"`
17
}
18
19
// GuildSearch contains guild data from search response
0 ignored issues
show
introduced by
comment on exported type AlbionGuildSearch should be of the form "AlbionGuildSearch ..." (with optional leading article)
Loading history...
20
type AlbionGuildSearch struct {
21
	ID           string `json:"Id"`
22
	Name         string `json:"Name"`
23
	AllianceID   string `json:"AllianceId"`
24
	AllianceName string `json:"AllianceName"`
25
	KillFame     int    `json:"KillFame"`
26
	DeathFame    int    `json:"DeathFame"`
27
}
28
29
// PlayerSearch contains player data from search response
0 ignored issues
show
introduced by
comment on exported type AlbionPlayerSearch should be of the form "AlbionPlayerSearch ..." (with optional leading article)
Loading history...
30
type AlbionPlayerSearch struct {
31
	ID           string  `json:"Id"`
32
	Name         string  `json:"Name"`
33
	AllianceID   string  `json:"AllianceId"`
34
	AllianceName string  `json:"AllianceName"`
35
	KillFame     int     `json:"KillFame"`
36
	DeathFame    int     `json:"DeathFame"`
37
	Avatar       string  `json:"Avatar"`
38
	AvatarRing   string  `json:"AvatarRing"`
39
	FameRation   float64 `json:"FameRatio"`
40
	TotalKills   int     `json:"totalKills"`
41
	GVGKills     int     `json:"gvgKills"`
42
	GVGWon       int     `json:"gvgWon"`
43
}
44
45
// Player data
0 ignored issues
show
introduced by
comment on exported type AlbionPlayer should be of the form "AlbionPlayer ..." (with optional leading article)
Loading history...
46
type AlbionPlayer struct {
47
	AverageItemPower float64         `json:"AverageItemPower"`
48
	Equipment        AlbionEquipment `json:"Equipment"`
49
	Inventory        []AlbionItem    `json:"Inventory"`
50
	Name             string          `json:"Name"`
51
	Id               string          `json:"Id"`
0 ignored issues
show
introduced by
struct field Id should be ID
Loading history...
52
	GuildName        string          `json:"GuildName"`
53
	GuildId          string          `json:"GuildId"`
0 ignored issues
show
introduced by
struct field GuildId should be GuildID
Loading history...
54
	AllianceName     string          `json:"AllianceName"`
55
	AllianceId       string          `json:"AllianceId"`
0 ignored issues
show
introduced by
struct field AllianceId should be AllianceID
Loading history...
56
	AllianceTag      string          `json:"AllianceTag"`
57
	Avatar           string          `json:"Avatar"`
58
	AvatarRing       string          `json:"AvatarRing"`
59
	DeathFame        int             `json:"DeathFame"`
60
	KillFame         int             `json:"KillFame"`
61
	FameRatio        float64         `json:"FameRatio"`
62
	DamageDone       float64         `json:"DamageDone"`
63
}
64
65
// Equipment contains items in slots
0 ignored issues
show
introduced by
comment on exported type AlbionEquipment should be of the form "AlbionEquipment ..." (with optional leading article)
Loading history...
66
type AlbionEquipment struct {
67
	MainHand AlbionItem `json:"MainHand"`
68
	OffHand  AlbionItem `json:"OffHand"`
69
	Head     AlbionItem `json:"Head"`
70
	Armor    AlbionItem `json:"Armor"`
71
	Shoes    AlbionItem `json:"Shoes"`
72
	Bag      AlbionItem `json:"Bag"`
73
	Cape     AlbionItem `json:"Cape"`
74
	Mount    AlbionItem `json:"Mount"`
75
	Potion   AlbionItem `json:"Potion"`
76
	Food     AlbionItem `json:"Food"`
77
}
78
79
// Item contains item data
0 ignored issues
show
introduced by
comment on exported type AlbionItem should be of the form "AlbionItem ..." (with optional leading article)
Loading history...
80
type AlbionItem struct {
81
	Type    string `json:"Type"`
82
	Count   int    `json:"Count"`
83
	Quality int    `json:"Quality"`
84
}
85
86
// Kill contains kill data
0 ignored issues
show
introduced by
comment on exported type AlbionKill should be of the form "AlbionKill ..." (with optional leading article)
Loading history...
87
type AlbionKill struct {
88
	GroupMemberCount     int            `json:"groupMemberCount"`
89
	NumberOfParticipants int            `json:"numberOfParticipants"`
90
	EventID              int            `json:"EventId"`
91
	TimeStamp            string         `json:"TimeStamp"`
92
	Version              int            `json:"Version"`
93
	Killer               AlbionPlayer   `json:"Killer"`
94
	Victim               AlbionPlayer   `json:"Victim"`
95
	TotalVictimKillFame  int            `json:"TotalVictimKillFame"`
96
	Location             string         `json:"Location"`
97
	Participants         []AlbionPlayer `json:"Participants"`
98
	GroupMembers         []AlbionPlayer `json:"GroupMembers"`
99
	BattleID             int            `json:"BattleId"`
100
	Type                 string         `json:"Type"`
101
}
102
103
type AlbionUpdater struct {
0 ignored issues
show
introduced by
exported type AlbionUpdater should have comment or be unexported
Loading history...
104
	Players map[string]*AlbionPlayerUpdater
105
}
106
107
type AlbionPlayerUpdater struct {
0 ignored issues
show
introduced by
exported type AlbionPlayerUpdater should have comment or be unexported
Loading history...
108
	PlayerID string
109
	UserID   string
110
	LastKill int64
111
	StartAt  int64
112
}
113
114
// SearchPlayers returns player list by name
0 ignored issues
show
introduced by
comment on exported function AlbionSearchPlayers should be of the form "AlbionSearchPlayers ..."
Loading history...
115
func AlbionSearchPlayers(name string) (result *AlbionSearchResult, err error) {
116
	var sResult AlbionSearchResult
117
	resp, err := http.Get(fmt.Sprintf("https://gameinfo.albiononline.com/api/gameinfo/search?q=%v", name))
118
	if err != nil {
119
		return nil, err
120
	}
121
122
	if resp.StatusCode != 200 {
123
		return nil, errors.New("status " + resp.Status)
124
	}
125
126
	err = json.NewDecoder(resp.Body).Decode(&sResult)
127
	if err != nil {
128
		return nil, err
129
	}
130
131
	return &sResult, nil
132
}
133
134
// GetPlayerKills returns array of kills by player id
0 ignored issues
show
introduced by
comment on exported function AlbionGetPlayerKills should be of the form "AlbionGetPlayerKills ..."
Loading history...
135
func AlbionGetPlayerKills(id string) (result []AlbionKill, err error) {
136
	var kills []AlbionKill
137
	resp, err := http.Get(fmt.Sprintf("https://gameinfo.albiononline.com/api/gameinfo/players/%v/topkills?range=month&offset=0&limit=20", id))
138
	if err != nil {
139
		return nil, err
140
	}
141
142
	if resp.StatusCode != 200 {
143
		return nil, errors.New("status " + resp.Status)
144
	}
145
146
	err = json.NewDecoder(resp.Body).Decode(&kills)
147
	if err != nil {
148
		return nil, err
149
	}
150
151
	return kills, nil
152
}
153
154
func AlbionGetKillID(id string) (kill *AlbionKill, err error) {
0 ignored issues
show
introduced by
exported function AlbionGetKillID should have comment or be unexported
Loading history...
155
	var result AlbionKill
156
	resp, err := http.Get(fmt.Sprintf("https://gameinfo.albiononline.com/api/gameinfo/events/%v", id))
157
	if err != nil {
158
		return nil, err
159
	}
160
161
	if resp.StatusCode != 200 {
162
		return nil, errors.New("status " + resp.Status)
163
	}
164
165
	err = json.NewDecoder(resp.Body).Decode(&result)
166
	if err != nil {
167
		return nil, err
168
	}
169
170
	return &result, nil
171
}
172
173
// ShowKills sends embed message in discord
0 ignored issues
show
introduced by
comment on exported method Context.AlbionShowKills should be of the form "AlbionShowKills ..."
Loading history...
174
func (ctx *Context) AlbionShowKills() {
175
	search, err := AlbionSearchPlayers(ctx.Args[1])
176
	if err != nil {
177
		fmt.Println("Error:" + err.Error())
178
		return
179
	}
180
	fmt.Println("Founded players")
181
	if len(search.Players) > 0 {
182
		fmt.Println("Players more then 0")
183
		kills, err := AlbionGetPlayerKills(search.Players[0].ID)
184
		fmt.Println("Searching kills of " + search.Players[0].Name + search.Players[0].ID)
185
		if err != nil {
186
			fmt.Println("Error: " + err.Error())
187
			return
188
		}
189
		fmt.Println("Founded kills of " + search.Players[0].Name)
190
		if len(kills) > 0 {
191
			fmt.Println("Kills more then 0")
192
			embed := NewEmbed("Albion Killboard")
193
			embed.Desc(fmt.Sprintf("[%v](https://albiononline.com/ru/killboard/player/%v)", search.Players[0].Name, search.Players[0].ID)) // "https://assets.albiononline.com/assets/images/icons/favicon.ico")
194
			embed.Color(ctx.GuildConf().EmbedColor)
195
			for _, k := range kills {
196
				fmt.Println("Killed " + k.Victim.Name)
197
				var timeString string
198
				t, err := time.Parse("2006-01-02T15:04:05.000000000Z", k.TimeStamp)
199
				if err == nil {
200
					timeString = fmt.Sprintf("%v.%v.%v %v:%v", t.Day(), t.Month().String(), t.Year(), t.Hour(), t.Minute())
201
				} else {
202
					fmt.Println("Parse time: ", err.Error())
203
				}
204
				embed.Field(
205
					k.Victim.Name,
206
					fmt.Sprintf("%v [[%v](https://albiononline.com/ru/killboard/kill/%v)]",
207
						fmt.Sprintf(ctx.Loc("albion_kill_short"),
0 ignored issues
show
introduced by
can't check non-constant format in call to Sprintf
Loading history...
208
							k.Victim.DeathFame,
209
							k.Victim.AverageItemPower,
210
							timeString),
211
						k.EventID,
212
						k.EventID), false)
213
			}
214
			embed.Send(ctx)
215
		}
216
217
	}
218
}
219
220
func (ctx *Context) AlbionShowKill() {
0 ignored issues
show
introduced by
exported method Context.AlbionShowKill should have comment or be unexported
Loading history...
221
	kill, err := AlbionGetKillID(ctx.Args[1])
222
	if err != nil {
223
		fmt.Println("Error:" + err.Error())
224
		return
225
	}
226
227
	embed := NewEmbed(fmt.Sprintf("Show on killboard #%v", kill.EventID))
228
	embed.Desc(fmt.Sprintf("%v :crossed_swords: %v", kill.Killer.Name, kill.Victim.Name))
229
	embed.Color(ctx.GuildConf().EmbedColor)
230
	embed.URL(fmt.Sprintf("https://albiononline.com/ru/killboard/kill/%v", kill.EventID))
231
	embed.AttachThumbURL("https://assets.albiononline.com/assets/images/header/logo.png")
232
	embed.Author("Albion Killboard", "https://albiononline.com/ru/killboard", "")
233
	embed.TimeStamp(kill.TimeStamp)
234
	embed.Field(ctx.Loc("albion_guild"), kill.Victim.GuildName, true)
235
	embed.Field(ctx.Loc("albion_fame"), fmt.Sprintf("%v", kill.Victim.DeathFame), true)
236
	embed.Field(ctx.Loc("albion_item_power"), fmt.Sprintf("%.3f", kill.Victim.AverageItemPower), true)
237
	embed.Field(ctx.Loc("albion_killer_item_power"), fmt.Sprintf("%.3f", kill.Killer.AverageItemPower), true)
238
	if len(kill.Participants) > 0 {
239
		var names []string
240
		for _, p := range kill.Participants {
241
			names = append(names, fmt.Sprintf("%v (%.0f)", p.Name, p.DamageDone))
242
		}
243
		embed.Field(ctx.Loc("albion_participants"), strings.Join(names, ", "), true)
244
	}
245
	embed.Send(ctx)
246
}
247
248
func SendKill(session *discordgo.Session, conf *Config, kill *AlbionKill, userID string) {
0 ignored issues
show
introduced by
exported function SendKill should have comment or be unexported
Loading history...
249
	embed := NewEmbed(fmt.Sprintf("Show on killboard #%v", kill.EventID))
250
	embed.Desc(fmt.Sprintf("%v :crossed_swords: %v", kill.Killer.Name, kill.Victim.Name))
251
	embed.Color(4460547)
252
	embed.URL(fmt.Sprintf("https://albiononline.com/ru/killboard/kill/%v", kill.EventID))
253
	embed.AttachThumbURL("https://assets.albiononline.com/assets/images/header/logo.png")
254
	embed.Author("Albion Killboard", "https://albiononline.com/ru/killboard", "")
255
	embed.TimeStamp(kill.TimeStamp)
256
	embed.Field(conf.GetLocale("albion_guild"), kill.Victim.GuildName, true)
257
	embed.Field(conf.GetLocale("albion_fame"), fmt.Sprintf("%v", kill.Victim.DeathFame), true)
258
	embed.Field(conf.GetLocale("albion_item_power"), fmt.Sprintf("%.3f", kill.Victim.AverageItemPower), true)
259
	embed.Field(conf.GetLocale("albion_killer_item_power"), fmt.Sprintf("%.3f", kill.Killer.AverageItemPower), true)
260
	if len(kill.Participants) > 0 {
261
		var names []string
262
		for _, p := range kill.Participants {
263
			names = append(names, fmt.Sprintf("%v (%.0f)", p.Name, p.DamageDone))
264
		}
265
		embed.Field(conf.GetLocale("albion_participants"), strings.Join(names, ", "), true)
266
	}
267
	ch, err := session.UserChannelCreate(userID)
268
	if err != nil {
269
		fmt.Println("Error whilst creating private channel, ", err)
270
		return
271
	}
272
	_, err = session.ChannelMessageSendEmbed(ch.ID, embed.GetEmbed())
273
	if err != nil {
274
		fmt.Println("Error whilst sending embed message, ", err)
275
		return
276
	}
277
}
278
279
func GetPlayerByID(name string) string {
0 ignored issues
show
introduced by
exported function GetPlayerByID should have comment or be unexported
Loading history...
280
	search, err := AlbionSearchPlayers(name)
281
	if err == nil {
282
		if len(search.Players) > 0 {
283
			return search.Players[0].ID
284
		}
285
	}
286
	return ""
287
}
288
289
func AlbionGetUpdater(db *DBWorker) *AlbionUpdater {
0 ignored issues
show
introduced by
exported function AlbionGetUpdater should have comment or be unexported
Loading history...
290
	var updater = &AlbionUpdater{Players: make(map[string]*AlbionPlayerUpdater)}
291
	var players []AlbionPlayerUpdater
292
	players = db.GetAlbionPlayers()
293
	for _, p := range players {
294
		updater.Players[p.UserID] = &p
295
	}
296
	return updater
297
}
298
299
func SendPlayerKills(session *discordgo.Session, worker *DBWorker, conf *Config, updater *AlbionUpdater, userID string) {
0 ignored issues
show
introduced by
exported function SendPlayerKills should have comment or be unexported
Loading history...
300
	startTime := time.Unix(updater.Players[userID].StartAt, 0)
301
	lastTime := time.Unix(updater.Players[userID].LastKill, 0)
302
	if startTime.Add(time.Hour * 24).Unix() < time.Now().Unix() {
303
		worker.RemoveAlbionPlayer(updater.Players[userID].UserID)
304
		delete(updater.Players, updater.Players[userID].UserID)
305
		return
306
	} else {
0 ignored issues
show
introduced by
if block ends with a return statement, so drop this else and outdent its block
Loading history...
307
		kills, err := AlbionGetPlayerKills(updater.Players[userID].PlayerID)
308
		if err != nil {
309
			return
310
		}
311
		var newKillTime int64
312
		for i, k := range kills {
313
			killTime, err := time.Parse("2006-01-02T15:04:05.000000000Z", k.TimeStamp)
314
			if err != nil {
315
				fmt.Println("Kill time parse error: ", err.Error())
316
				continue
317
			}
318
			if killTime.Unix() > lastTime.Unix() {
319
				if killTime.Unix() > newKillTime {
320
					newKillTime = killTime.Unix()
321
				}
322
				SendKill(session, conf, &kills[i], userID)
323
			}
324
		}
325
		if newKillTime > lastTime.Unix() {
326
			worker.UpdateAlbionPlayerLast(userID, newKillTime)
327
			updater.Players[userID].LastKill = newKillTime
328
		}
329
	}
330
}
331
332
func (u *AlbionUpdater) Update(session *discordgo.Session, worker *DBWorker, conf *Config) {
0 ignored issues
show
introduced by
exported method AlbionUpdater.Update should have comment or be unexported
Loading history...
333
	for _, p := range u.Players {
334
		//go SendPlayerKills(session, worker, conf, u, p.UserID)
335
		startTime := time.Unix(u.Players[p.UserID].StartAt, 0)
336
		lastTime := time.Unix(u.Players[p.UserID].LastKill, 0)
337
		if startTime.Add(time.Hour * 24).Unix() < time.Now().Unix() {
338
			worker.RemoveAlbionPlayer(p.UserID)
339
			delete(u.Players, p.UserID)
340
			return
341
		} else {
0 ignored issues
show
introduced by
if block ends with a return statement, so drop this else and outdent its block
Loading history...
342
			kills, err := AlbionGetPlayerKills(p.PlayerID)
343
			if err != nil {
344
				return
345
			}
346
			var newKillTime int64
347
			for i, k := range kills {
348
				killTime, err := time.Parse("2006-01-02T15:04:05.000000000Z", k.TimeStamp)
349
				if err != nil {
350
					fmt.Println("Kill time parse error: ", err.Error())
351
					continue
352
				}
353
				if killTime.Unix() > lastTime.Unix() {
354
					if killTime.Unix() > newKillTime {
355
						newKillTime = killTime.Unix()
356
					}
357
					SendKill(session, conf, &kills[i], p.UserID)
358
				}
359
			}
360
			if newKillTime > lastTime.Unix() {
361
				worker.UpdateAlbionPlayerLast(p.UserID, newKillTime)
362
				u.Players[p.UserID].LastKill = newKillTime
363
			}
364
		}
365
	}
366
}
367
368
func (ctx *Context) AlbionAddPlayer() error {
0 ignored issues
show
introduced by
exported method Context.AlbionAddPlayer should have comment or be unexported
Loading history...
369
	if len(ctx.Args) > 1 {
370
		search, err := AlbionSearchPlayers(ctx.Args[1])
371
		if err != nil {
372
			fmt.Println("Error searching Albion player: ", err.Error())
373
			return errors.New("error searching Albion player")
374
		}
375
		if _, ok := ctx.Albion.Players[ctx.User.ID]; !ok {
376
			kills, err := AlbionGetPlayerKills(search.Players[0].ID)
377
			if err != nil {
378
				fmt.Println("Error getting Albion kills: ", err.Error())
379
				return errors.New("error getting Albion kills")
380
			}
381
			var lastKill int64
382
			for _, k := range kills {
383
				killTime, err := time.Parse("2006-01-02T15:04:05.000000000Z", k.TimeStamp)
384
				if err != nil {
385
					continue
386
				}
387
				if killTime.Unix() > lastKill {
388
					lastKill = killTime.Unix()
389
				}
390
			}
391
			player := &AlbionPlayerUpdater{search.Players[0].ID, ctx.User.ID, lastKill, time.Now().Unix()}
392
			ctx.Albion.Players[ctx.User.ID] = player
393
			ctx.DB.AddAlbionPlayer(player)
394
			return nil
395
		}
396
	}
397
	return errors.New("error")
398
}
399