main
1package main
2
3import (
4 "bytes"
5 "errors"
6 "fmt"
7 "io"
8 "net/http"
9 "net/url"
10
11 "golang.org/x/net/html"
12)
13
14const (
15 _noAction = ""
16)
17
18func (ic *islandClient) overview(params map[string]string) ([]byte, error) {
19
20 overviewURL := fmt.Sprintf("%s/s_%d/overview.php", _baseURL, ic.Server)
21 parsedURL, err := url.Parse(overviewURL)
22 if err != nil {
23 return nil, fmt.Errorf("failed creating overview url: %w",
24 err)
25 }
26
27 q := parsedURL.Query()
28 q.Add("s", ic.sessionId)
29 for k, v := range params {
30 q.Add(k, v)
31 }
32 parsedURL.RawQuery = q.Encode()
33 //fmt.Println(q.Encode())
34 urlString := parsedURL.String()
35
36 req, err := http.NewRequest("GET", urlString, nil)
37 if err != nil {
38 return nil, fmt.Errorf("failed creating request page=%s: %w",
39 urlString, err)
40 }
41 req = addHeaders(req)
42
43 resp, err := ic.client.Do(req)
44 if err != nil {
45 return nil, fmt.Errorf("failed requesting page=%s: %w",
46 urlString, err)
47 }
48 defer resp.Body.Close()
49
50 bodyBytes, err := io.ReadAll(resp.Body)
51 if err != nil {
52 return nil, fmt.Errorf("failed to read resp bytes page=%s: %w",
53 urlString, err)
54 }
55
56 if loggedOut(bodyBytes) {
57 ic.Login()
58 return ic.overview(params)
59 }
60 return bodyBytes, nil
61}
62
63func (ic *islandClient) Fortress() error {
64 bodyBytes, err := ic.overview(page(_Fortress))
65 if err != nil {
66 return err
67 }
68
69 upgrading, err := currentBuildingUpgrade(bodyBytes)
70 if err != nil && !errors.Is(err, ErrUpgradeNotInProgress) {
71 return fmt.Errorf("failed to query upgrade status: %w", err)
72 }
73 if upgrading != nil {
74 b, buildingExists := ic.Buildings[upgrading.Id]
75 if buildingExists {
76 if b.Upgrade == nil {
77 b.Upgrade = &Resoruces{}
78 }
79 b.Upgrade.Time = upgrading.Upgrade.Time
80 b.Status = "Upgrading"
81 }
82 return nil
83 }
84
85 buildings, err := findBuildingUpgrades(bodyBytes)
86 if err != nil {
87 return err
88 }
89 for _, b := range buildings {
90 _, buildingExists := ic.Buildings[b.Id]
91 if buildingExists {
92 ic.Buildings[b.Id].Upgrade = b.Upgrade
93 }
94
95 }
96 return nil
97}
98
99func (ic *islandClient) UpdateProduction() error {
100
101 production := &Resoruces{}
102
103 gold := page(_info)
104 gold[_building] = _GoldPit
105 goldBody, err := ic.overview(gold)
106 if err != nil {
107 return err
108 }
109 production.Gold, err = findProduction(goldBody)
110 if err != nil {
111 return fmt.Errorf("failed to find gold production rate: %w", err)
112 }
113
114 stone := page(_info)
115 stone[_building] = _StoneBasin
116 stoneBody, err := ic.overview(stone)
117 if err != nil {
118 return err
119 }
120 production.Stone, err = findProduction(stoneBody)
121 if err != nil {
122 return fmt.Errorf("failed to find stone production rate: %w", err)
123 }
124
125 lumber := page(_info)
126 lumber[_building] = _Sawmill
127 lumberBody, err := ic.overview(lumber)
128 if err != nil {
129 return err
130 }
131 production.Lumber, err = findProduction(lumberBody)
132 if err != nil {
133 return fmt.Errorf("failed to find stone production rate: %w", err)
134 }
135
136 ic.Production = production
137 return nil
138
139}
140
141func (ic *islandClient) Overview() error {
142
143 bodyBytes, err := ic.overview(page(_main))
144 if err != nil {
145 return err
146 }
147
148 overviewPage, err := html.Parse(bytes.NewReader(bodyBytes))
149 if err != nil {
150 return fmt.Errorf("failed to parse overview html: %w", err)
151 }
152
153 resources := findResources(overviewPage)
154 ic.Resources = resources
155
156 ic.Buildings, err = findBuildings(bodyBytes)
157 if err != nil {
158 return err
159 }
160
161 return nil
162}
163
164func (ic *islandClient) Login() error {
165
166 // Form data using the url.Values type
167 formData := url.Values{
168 "lang": {"en"},
169 "user": {ic.User},
170 "pw": {ic.password},
171 "server": {fmt.Sprintf("s%d", ic.Server)},
172 }
173 reqBody := bytes.NewBufferString(formData.Encode())
174
175 loginURL := fmt.Sprintf("%s/s_%d/login.php", _baseURL, ic.Server)
176 parsedURL, err := url.Parse(loginURL)
177 if err != nil {
178 return fmt.Errorf("failed creating login url: %w", err)
179 }
180
181 q := parsedURL.Query()
182 q.Add("a", "login")
183 parsedURL.RawQuery = q.Encode()
184
185 req, err := http.NewRequest("POST", parsedURL.String(), reqBody)
186 if err != nil {
187 return fmt.Errorf("failed creating login request: %w", err)
188 }
189 req = addHeaders(req)
190 req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
191
192 resp, err := ic.client.Do(req)
193 if err != nil {
194 return fmt.Errorf("failed to login: %w", err)
195 }
196 defer resp.Body.Close()
197
198 bodyBytes, err := io.ReadAll(resp.Body)
199 if err != nil {
200 return fmt.Errorf("failed to read login bytes: %w", err)
201 }
202
203 loginPage, err := html.Parse(bytes.NewReader(bodyBytes))
204 if err != nil {
205 return fmt.Errorf("failed to parse login html: %w", err)
206 }
207
208 sessionId := findSessionID(loginPage)
209 if sessionId == "" {
210 fmt.Println(string(bodyBytes))
211 fmt.Printf("RESP:\n%+v\n\n", resp)
212 fmt.Printf("REQ:\n%+v\n\n", req)
213 return fmt.Errorf("failed to find session id:")
214 }
215 ic.sessionId = sessionId
216
217 return nil
218}
219
220func addHeaders(req *http.Request) *http.Request {
221 req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:115.0) Gecko/20100101 Firefox/115.0")
222 req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
223 req.Header.Set("Accept-Language", "en-US,en;q=0.5")
224 req.Header.Set("Origin", "https://www.ik-seite.de")
225 req.Header.Set("Connection", "keep-alive")
226 req.Header.Set("Referer", "https://www.ik-seite.de/en/")
227 req.Header.Set("Upgrade-Insecure-Requests", "1")
228 req.Header.Set("Sec-Fetch-Dest", "document")
229 req.Header.Set("Sec-Fetch-Mode", "navigate")
230 req.Header.Set("Sec-Fetch-Site", "none")
231 req.Header.Set("Sec-Fetch-User", "?1")
232 return req
233}