BONUS! Fishing Guide
Catch twenty different species of fish that live around Geese Islands. When you're done, report your findings to Poinsettia McMittens on the Island of Misfit Toys.
BONUS! Fishing Guide
Difficulty: 🎄
Catch twenty different species of fish that live around Geese Islands. When you’re done, report your findings to Poinsettia McMittens on the Island of Misfit Toys.
Hints
Become the Fish
From: Poinsettia McMittens Perhaps there are some clues about the local aquatic life located in the HTML source code.
Solution
I analyzed the source code identifying the comment <!-- <a href='fishdensityref.html'>[DEV ONLY] Fish Density Reference</a> --> and I was able to download the content but it didn’t turn out useful for this challenge. Instead I wrote a python script based on Polle Vanhoof’s santas_little_helper from KringleCon 2019 to automatically fish using websockets:
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
import asyncio
import websocket
import ssl
import json
base_ws_url = 'wss://2023.holidayhackchallenge.com/ws'
fish_ws_url = "wss://2023.holidayhackchallenge.com/sail?dockSlip={}"
login_user = 'HEY! Were you looking at my email?'
login_pass = 'HEY! Were you looking at my password?'
def login(ws, user, password):
print("--> LOGIN")
ws.send('{"type":"WS_CONNECTED","protocol":"43ae08fd-9cf2-4f54-a6a6-8454aef59581"}')
ws.recv()
ws.send('{"type":"WS_LOGIN","usernameOrEmail":"%s","password":"%s"}' % (login_user, login_pass))
userid = list(json.loads(ws.recv())['users'].keys())[0]
print("--> LOGGED IN, USER ID [{}]".format(userid))
return userid
def sail(ws):
# Sail
print("--> GET FISH WS ID")
base_ws.send('{"type":"setSail"}')
ws_response = base_ws.recv()
while not "SET_SAIL" in ws_response:
ws_response = base_ws.recv()
fish_ws_id = json.loads(ws_response)['dockSlip']
print("--> GOT FISH WS ID [{}]".format(fish_ws_id))
return fish_ws_id
if __name__ == "__main__":
print("--> CONNECTING TO BASE WS")
base_ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
base_ws.connect(base_ws_url)
print("--> CONNECTED TO FISH WS")
userid = login(base_ws, login_user, login_pass)
fish_ws_id = sail(base_ws)
print("--> CONNECTING TO FISH WS ID [{}]".format(fish_ws_id))
fish_ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
fish_ws.connect(fish_ws_url.format(fish_ws_id))
print("--> CONNECTED TO FISH WS")
user_evt_start = 'e:{"' + str(userid) + '":'
user_inf_start = 'i:{"uid":' + str(userid)
print("--> GETTING CAUGHT FISH")
userInfo = None
while not userInfo:
ws_response = fish_ws.recv()
if ws_response.startswith(user_inf_start):
userInfo = json.loads(ws_response[2:])
fishCaught = []
for fish in userInfo['fishCaught']:
fishCaught.append(fish['name'])
print("--> CAUGHT [{}] FISHES: {}".format(len(fishCaught), fishCaught))
print("--> POSITION IS x:[{}] y:[{}]".format(userInfo['x'], userInfo['y']))
while True:
print("--> CASTING LINE")
fish_ws.send('cast')
onTheLine = False
while not onTheLine:
ws_response = fish_ws.recv()
if ws_response.startswith(user_evt_start) and "onTheLine" in ws_response:
ws_response = json.loads(ws_response[2:])
onTheLine = ws_response[list(ws_response.keys())[0]]['onTheLine']
print("--> [{}] IS ON THE LINE".format(onTheLine))
print("--> SENDING REEL COMMAND")
fish_ws.send('reel')
ws_response = fish_ws.recv()
while not 'f:{"fish":' in ws_response:
ws_response = fish_ws.recv()
if onTheLine in fishCaught:
print("--> ALREADY HAVE [{}]".format(onTheLine))
else:
fishCaught.append(onTheLine)
print("--> GOT NEW FISH [{}]".format(ws_response))
print("--> CAUGHT [{}] FISHES: {}".format(len(fishCaught), fishCaught))
I let it run for a while and it worked but also it obviously had to crash… so… I could fix the script… or:
1
while true; do python3 fishing.py; done
After a night, I caught almost all the fishes and got the objective by speaking to Poinsettia again.