-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathkittyapi.py
221 lines (181 loc) · 8.54 KB
/
kittyapi.py
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
#!bin/python
import requests
import sys
from operator import itemgetter, attrgetter, methodcaller
class CryptokittieAPI:
def __init__(self):
self.API_URL = "https://api.cryptokitties.co"
self.API_KITTY = self.API_URL+"/kitties/"
self.API_AUCTIONS = self.API_URL + "/auctions?offset=OFF_SET&limit=LIMIT&type=sale&status=open&sorting=young&orderBy=current_price&orderDirection=asc&search=SEARCH"
self.API_OFFSET = 50
def getKitty(self, kittyId):
requestUrl = self.API_KITTY+str(kittyId)
print "[CryptokittieAPI] Getting kitty %s: %s" % (kittyId, requestUrl)
return requests.get(requestUrl).json()
def getAudictionList(self, offset, limit, searchString, sire=False):
requestUrl = self.API_AUCTIONS.replace("OFF_SET", str(offset)).replace("LIMIT", str(limit)).replace("SEARCH", str(searchString))
if sire:
requestUrl = requestUrl.replace("type=sale", "type=sire")
print "[CryptokittieAPI] - Getting auctions: %s" % requestUrl
return requests.get(requestUrl).json();
class CKUtils:
def __init__(self):
self.api = CryptokittieAPI()
def getKittyCattributes(self,kitty):
originalCattributes = kitty['cattributes']
easyCattributes = []
for attr in originalCattributes:
easyCattributes.append(str(attr['description']))
return easyCattributes
class Scanner:
def __init__(self, searchQuery, manager=None):
self.api = CryptokittieAPI()
self.offset = 0
self.limit = 5
self.searchQuery = searchQuery
self.manager = manager
self.found = {}
self.sorted = {}
# change to debug
print "[*] Scanner init"
print str(self.searchQuery)
def nextPage(self):
payload = self.api.getAudictionList(self.offset, self.limit, self.searchQuery.searchQueryString(), self.searchQuery.sire)
return payload
def scanForever(self):
while True:
self.scan()
def getMedianPrice(self):
total = 0
for k in self.found:
total += float(self.found[k]['current_price'])/1000000000000000000
return total/float(len(self.found))
def getResumedKitties(self):
for k in self.found:
self.sorted[self.found[k]['kitty']['id']] = float(self.found[k]['current_price'])/1000000000000000000
for k in sorted(self.sorted.items(), key=itemgetter(1)):
k = k[0]
print "[%s] ETH %f - https://www.cryptokitties.co/kitty/%d" % (self.found[k]['kitty']['id'], float(self.found[k]['current_price'])/1000000000000000000, self.found[k]['kitty']['id'])
def scan(self):
print "[*] Scanner starting"
data = self.nextPage()
while len(data['auctions']) > 0:
print "[SCANNER] Got a total of %d auctions." % len(data['auctions'])
foundAuctions = 0
for auction in data['auctions']:
kitty = self.api.getKitty(auction['kitty']['id'])
if self.isGold(auction, kitty):
if kitty['id'] not in self.found:
self.manager.addGoldKitty(auction, kitty)
self.found[auction['kitty']['id']] = auction
print "[SCANNER] median price: %f" % self.getMedianPrice()
foundAuctions += 1
print "[SCANNER] offset result: %d/%d" % (foundAuctions,len(data['auctions']))
self.offset += self.limit
print "[SCANNER] offset: %d" % self.offset
print "[SCANNER] limit: %d" % self.limit
data = self.nextPage()
print "[SCANNER] Shutting down."
print "[SCANNER] Found %d kitties that match parameters." % len(self.found)
print "[SCANNER] median price for this search: %f" % self.getMedianPrice()
self.getResumedKitties()
def __str__(self):
msg = """[*] Scan offset configs
|_ offset: %s
|_ limit: %s"""
return msg % (self.offset, self.limit)
def isGold(self, auction, kitty):
auctionPrice = float(auction['current_price'])/1000000000000000000
print "[SELECTOR %s] checking price: %f." % (kitty['id'], auctionPrice)
if not (auctionPrice <= self.searchQuery.maxPrice and auctionPrice >= self.searchQuery.minPrice):
print '[SELECTOR %s] Price: %f, bad price range (%f,%f)' %(kitty['id'],auctionPrice, self.searchQuery.maxPrice, self.searchQuery.minPrice)
return False
print "[SELECTOR %s] price ok." % kitty['id']
if self.searchQuery.cattributes:
print "[SELECTOR %s] checking cattributes." % kitty['id']
hasCattributes = False
print "[SELECTOR %s] Scanning for desired cattributes." % kitty['id']
for attr in kitty['cattributes']:
if str(attr['description']) in self.searchQuery.cattributes:
print "[SELECTOR %s] Found %s." % (kitty['id'], attr['description'])
hasCattributes = True
if not hasCattributes:
print "[SELECTOR %s] no good cattributes, discarting." % kitty['id']
return False
print "[SELECTOR %s] cattributes passed." % kitty['id']
if self.searchQuery.mainColor:
print "[SELECTOR %s] checking main color." % kitty['id']
hasMainColor = False
maincolor = str(kitty['color']) in self.searchQuery.mainColor
mainColorInCattributes = str(kitty['color']) in self.searchQuery.cattributes
if maincolor:
print "[SELECTOR %s] Found %s as main color" % (kitty['id'],kitty['color'])
hasMainColor = True
if mainColorInCattributes:
print "[SELECTOR %s] Found as main color %s in cattributes" % (kitty['id'],kitty['color'])
hasMainColor = True
if not hasMainColor:
print "[SELECTOR %s] no good colors, discarting." % kitty['id']
return False
else:
print "[SELECTOR %s] checking main color ok." % kitty['id']
if self.searchQuery.virginOnly:
print "[SELECTOR %s] checking virginity." % kitty['id']
try:
child = kitty['children']
if len(child) > 0:
return False
print "[SELECTOR %s] this safadeenho is not virgin, discarting." % kitty['id']
else:
print "[SELECTOR %s] omg its virgin!" % kitty['id']
return True
except KeyError:
print "[SELECTOR %s] omg its virgin! by key error" % kitty['id']
return True
print self.searchQuery.cooldownMaxIndex
if kitty['status']['cooldown_index'] > self.searchQuery.cooldownMaxIndex:
return False
return True
class SearchQuery:
def __init__(self,gen, maxPrice=float(1), minPrice=float(0), virginOnly=True, goodiesOnly=False, sire=False, cattributes=[], mainColor=[], cooldownMaxIndex=10):
self.gen = gen
self.maxPrice = maxPrice
self.minPrice = minPrice
self.virginOnly = virginOnly
self.searchForGoodies = goodiesOnly
self.sire = sire
self.cattributes = cattributes
self.mainColor = mainColor
self.cooldownMaxIndex = cooldownMaxIndex
def searchQueryString(self):
queryString = ""
if self.gen:
queryString += "gen:"
for g in self.gen:
queryString += str(g) + ","
queryString = queryString[0:-1]
if self.cattributes:
for c in self.cattributes:
queryString = queryString + ("+%s" % c )
if self.mainColor:
if len(self.mainColor)>1:
# set the main color check for the scanner, not the querystring param
# bcz the API accept only 1 main color
for s in self.mainColor:
self.cattributes.append(s)
else:
queryString += ("+%s" % self.mainColor[0])
return queryString;
def __str__(self):
gens = " ".join(str(i) for i in self.gen)
config = """[*] QuerySearch Config: "
|_ gen: %s
|_ maxPrice: %s
|_ minPrice: %s
|_ virgin: %s
|_ goodies: %s
|_ sire: %s
|_ cattributes: %s
|_ mainColor: %s,
|_ cooldownMaxIndex: %s"""
return config % (gens, self.maxPrice, self.minPrice, self.virginOnly, self.searchForGoodies, self.sire, self.cattributes, self.mainColor, self.cooldownMaxIndex)