main
Raw Download raw file
  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}