1
+ # -*- coding: utf-8 -*-
2
+
3
+ #!/usr/bin/env python
4
+
5
+ import webapp2
6
+ import json ,math ,sys ,pprint
7
+ from google .appengine .ext import ndb
8
+ from google .appengine .api .memcache import Client
9
+ from google .appengine .api import urlfetch
10
+ from passlib .hash import sha256_crypt
11
+
12
+ class Group (ndb .Model ):
13
+ nrealm = ndb .StringProperty (indexed = True )
14
+ ngroup = ndb .StringProperty (indexed = True )
15
+ groupname = ndb .StringProperty ()
16
+ toons = ndb .StringProperty (repeated = True )
17
+ password = ndb .StringProperty ()
18
+
19
+ @staticmethod
20
+ def normalize (realm ):
21
+ return realm .lower ().replace ('\' ' ,'' ).replace (' ' ,'-' )
22
+
23
+ class Loader (webapp2 .RequestHandler ):
24
+ def get (self , nrealm , ngroup ):
25
+
26
+ # try to load the group info from the database
27
+ db_query = Group .query (Group .nrealm == nrealm , Group .ngroup == ngroup )
28
+ results = db_query .fetch (5 )
29
+
30
+ # if the group doesn't exist, drop into the interface to make a new
31
+ # group
32
+ if (len (results ) == 0 ):
33
+ self .redirect ('/edit/%s/%s' % (nrealm , ngroup ))
34
+
35
+ # if the group exists, load the group from the blizzard API and
36
+ # display it.
37
+ # if the group doesn't exist, show the page to create a new
38
+ # group.
39
+ else :
40
+ self .loadGroup (results [0 ])
41
+
42
+ def post (self , nrealm , ngroup ):
43
+
44
+ # try to load the group info from the database
45
+ db_query = Group .query (Group .nrealm == nrealm , Group .ngroup == ngroup )
46
+ results = db_query .fetch (5 )
47
+
48
+ if ((len (results ) != 0 ) and
49
+ sha256_crypt .verify (self .request .get ('pw' ), results [0 ].password ) != True ):
50
+ self .response .write ('Password did not match for this group!' )
51
+ return
52
+
53
+ group = None
54
+ if (len (results ) != 0 ):
55
+ group = results [0 ]
56
+ else :
57
+ group = Group ()
58
+
59
+ group .nrealm = nrealm
60
+ group .ngroup = ngroup
61
+ group .groupname = self .request .get ('group' ).strip ()
62
+ group .password = sha256_crypt .encrypt (self .request .get ('pw' ))
63
+ toons = self .request .POST .getall ('toons' )
64
+ print 'number of toons saved: %d' % len (toons )
65
+ group .toons = sorted (self .request .POST .getall ('toons' ), key = unicode .lower )
66
+ group .put ()
67
+
68
+ self .loadGroup (group )
69
+
70
+ def loadGroup (self , results ):
71
+
72
+ self .response .write ('<!DOCTYPE html>\n ' )
73
+ self .response .write ('<html>\n ' )
74
+ self .response .write ('<head>\n ' )
75
+ self .response .write ('<title>%s</title>' % results .groupname )
76
+ self .response .write ('<link rel="stylesheet" type="text/css" href="/resources/raidgroup.css"/>\n ' )
77
+ self .response .write ('<script language="javascript" type="text/javascript" src="/resources/folder.js"></script>\n ' )
78
+ self .response .write ('<script language="javascript" type="text/javascript" src="/resources/creategroup.js"></script>\n ' )
79
+ self .response .write ('</head>\n ' )
80
+ self .response .write ('<body>\n ' )
81
+
82
+ # Fill this in with the list of toons in your raid group. It can include toon names with unicode characters
83
+ toons = results .toons
84
+
85
+ # Fill this in with your realm name. Spaces should be replaced with '-'
86
+ realm = results .nrealm
87
+
88
+ jsondata = dict ()
89
+
90
+ totalilvl = 0
91
+ totalilvleq = 0
92
+
93
+ for i in range (len (toons )):
94
+ url = 'http://us.battle.net/api/wow/character/%s/%s?fields=items,guild,professions,progression' % (realm , toons [i ]);
95
+ print url .encode ('utf-8' )
96
+ response = urlfetch .fetch (url )
97
+ jsondata [i ] = json .loads (response .content )
98
+
99
+ if 'status' in jsondata [i ] and jsondata [i ]['status' ] == 'nok' :
100
+ print ('Failed to find toon %s' % toons [i ])
101
+ jsondata [i ]['toon' ] = toons [i ]
102
+ else :
103
+ totalilvl = totalilvl + jsondata [i ]['items' ]['averageItemLevel' ];
104
+ totalilvleq = totalilvleq + jsondata [i ]['items' ]['averageItemLevelEquipped' ]
105
+
106
+ self .response .write ('<div style="font-size: 24px">%s\n ' % results .groupname )
107
+ self .response .write ('<form action="/edit/%s/%s">' %
108
+ (results .nrealm , results .ngroup ))
109
+ self .response .write ('<input type="submit" value="Edit Group">\n ' )
110
+ self .response .write ('</form>' )
111
+ self .response .write ('</div><br/>\n ' )
112
+ self .response .write ('Group Average ilvl: %d<br/>\n ' % (totalilvl / len (toons )))
113
+ self .response .write ('Group Average equipped: %d<br/><br/>\n ' % (totalilvleq / len (toons )))
114
+
115
+ halfgroup = math .ceil (len (jsondata ) / 2.0 )
116
+ self .response .write ('<div class="left">\n ' )
117
+
118
+ for u in range (len (jsondata )):
119
+
120
+ char = jsondata [u ]
121
+
122
+ if (u == halfgroup ):
123
+ self .response .write ('</div>' )
124
+ self .response .write ('<div class="right">\n ' )
125
+
126
+ if 'status' in char and char ['status' ] == 'nok' :
127
+ self .response .write ('Failed to find toon %s (name change? server transfer?)<br/>\n ' % char ['toon' ])
128
+ continue
129
+
130
+ self .response .write ('<a href="http://us.battle.net/wow/en/character/%s/%s/simple">%s</a><br/>\n ' % (realm .encode ('utf-8' ), char ['name' ].encode ('utf-8' ),char ['name' ].encode ('utf-8' )))
131
+
132
+ self .response .write ('<div style="margin-left:30px">\n ' )
133
+ self .response .write ('%s<br/>\n ' % char ['guild' ]['name' ])
134
+ self .response .write ('Average ilvl: %d<br/>\n ' % char ['items' ]['averageItemLevel' ])
135
+ self .response .write ('Average equipped: %d<br/>\n ' % char ['items' ]['averageItemLevelEquipped' ])
136
+
137
+ priprof = char ['professions' ]['primary' ]
138
+
139
+ if (len (priprof ) == 2 ):
140
+ self .response .write ('Profession #1: %s (%d)<br/>\n ' % (priprof [0 ]['name' ], priprof [0 ]['rank' ]))
141
+ self .response .write ('Profession #2: %s (%d)<br/>\n ' % (priprof [1 ]['name' ], priprof [1 ]['rank' ]))
142
+ elif (len (priprof ) == 1 ):
143
+ self .response .write ('Profession #1: %s (%d)<br/>\n ' % (priprof [0 ]['name' ], priprof [0 ]['rank' ]))
144
+ self .response .write ('Profession #2: none<br/>\n ' )
145
+ else :
146
+ self .response .write ('Profession #1: none<br/>\n ' )
147
+ self .response .write ('Profession #2: none<br/>\n ' )
148
+
149
+ self .response .write ('<div>\n ' )
150
+ self .response .write ('<div onclick="togglePanelStatus(\' %s\' )" style="cursor: pointer">\n ' % char ['name' ])
151
+ self .response .write ('<img src="/resources/arrow_right.png" id="slotsimg%s">' % char ['name' ])
152
+ self .response .write ('Gear Slot ilvls\n ' )
153
+ self .response .write ('</div>\n ' )
154
+ self .response .write ('<div id="slots%s" style="display: none;margin-left: 16px">\n ' % char ['name' ])
155
+ self .response .write ('<div class="left">\n ' )
156
+ self .response .write ('Head: %d<br/>\n ' % char ['items' ]['head' ]['itemLevel' ])
157
+ self .response .write ('Neck: %d<br/>\n ' % char ['items' ]['neck' ]['itemLevel' ])
158
+ self .response .write ('Shoulder: %d<br/>\n ' % char ['items' ]['shoulder' ]['itemLevel' ])
159
+ self .response .write ('Back: %d<br/>\n ' % char ['items' ]['back' ]['itemLevel' ])
160
+ self .response .write ('Chest: %d<br/>\n ' % char ['items' ]['chest' ]['itemLevel' ])
161
+ self .response .write ('Wrist: %d<br/>\n ' % char ['items' ]['wrist' ]['itemLevel' ])
162
+ self .response .write ('Hands: %d<br/>\n ' % char ['items' ]['hands' ]['itemLevel' ])
163
+ self .response .write ('Waist: %d<br/>\n ' % char ['items' ]['waist' ]['itemLevel' ])
164
+ self .response .write ('</div>' )
165
+ self .response .write ('<div class="left">\n ' )
166
+ self .response .write ('Legs: %d<br/>\n ' % char ['items' ]['legs' ]['itemLevel' ])
167
+ self .response .write ('Feet: %d<br/>\n ' % char ['items' ]['feet' ]['itemLevel' ])
168
+ self .response .write ('Ring 1: %d<br/>\n ' % char ['items' ]['finger1' ]['itemLevel' ])
169
+ self .response .write ('Ring 2: %d<br/>\n ' % char ['items' ]['finger2' ]['itemLevel' ])
170
+ self .response .write ('Trinket 1: %d<br/>\n ' % char ['items' ]['trinket1' ]['itemLevel' ])
171
+ self .response .write ('Trinket 2: %d<br/>\n ' % char ['items' ]['trinket2' ]['itemLevel' ])
172
+ self .response .write ('Main Hand: %d<br/>\n ' % char ['items' ]['mainHand' ]['itemLevel' ])
173
+ if ('offHand' in char ['items' ]):
174
+ self .response .write ('Off Hand: %d<br/>\n ' % char ['items' ]['offHand' ]['itemLevel' ])
175
+ else :
176
+ self .response .write ('Off Hand: none<br/>\n ' )
177
+ self .response .write ('</div>\n ' )
178
+ self .response .write ('</div><br/>\n ' )
179
+ self .response .write ('</div>\n ' )
180
+ self .response .write ('</div>\n ' )
181
+
182
+ self .response .write ('</div><p/>\n ' );
183
+ self .response .write ('</body>\n </html>' )
184
+
185
+ class Editor (webapp2 .RequestHandler ):
186
+ def get (self , nrealm , ngroup ):
187
+ self .editGroup (nrealm , ngroup )
188
+
189
+ def editGroup (self , nrealm , ngroup ):
190
+
191
+ # try to load the group info from the database
192
+ db_query = Group .query (Group .nrealm == nrealm , Group .ngroup == ngroup )
193
+ queryresults = db_query .fetch (5 )
194
+
195
+ results = None
196
+ if (len (queryresults ) != 0 ):
197
+ results = queryresults [0 ]
198
+
199
+ self .response .write ('<!DOCTYPE html>\n ' )
200
+ self .response .write ('<html>\n ' )
201
+ self .response .write ('<head>\n ' )
202
+
203
+ title = "Editing Group"
204
+ if (results == None ):
205
+ title = "Creating New Group"
206
+
207
+ self .response .write ('<title>%s</title>\n ' % title )
208
+ self .response .write ('<script language="javascript" type="text/javascript" src="/resources/creategroup.js"></script>' )
209
+ self .response .write ('</head>\n \n ' )
210
+ self .response .write ('<body>\n ' )
211
+ self .response .write ('<h1>%s</h1>\n ' % title )
212
+
213
+ self .response .write ('<form action="/%s/%s" method="post" autocomplete="off" onsubmit="selectAllToons();">\n ' % (nrealm , ngroup ))
214
+ if (results == None ):
215
+ self .response .write ('Group name: <input type="text" name="group" id="group"><p/>\n ' )
216
+ else :
217
+ self .response .write ('Group name: <input type="text" name="group" id="group"value="%s"><p/>\n ' % results .groupname )
218
+
219
+ self .response .write ('Group members:<br>\n ' )
220
+ self .response .write ('<select size="10" multiple="multiple" style="width: 300px" name="toons" id="toons">\n ' )
221
+
222
+ if (results != None ):
223
+ for toon in results .toons :
224
+ self .response .write ('<option id="opt%s">%s\n ' % (toon ,toon ))
225
+
226
+ self .response .write ('</select><br>\n ' )
227
+ self .response .write ('Add Toon: <input type="text" name="newtoon" id="newtoon"><br>\n ' )
228
+ self .response .write ('<input type="button" onclick="addToList()" value="Add">' )
229
+ self .response .write ('<input type="button" onclick="removeFromList()" value="Remove" id="removebutton"><p/>\n ' )
230
+ if (results == None ):
231
+ self .response .write ('Enter a password to enable editing the group later:<br>\n ' )
232
+ else :
233
+ self .response .write ('Enter password to save group:<br>\n ' )
234
+ self .response .write ('Password:' )
235
+ self .response .write ('<input type="password" name="pw"><p/>\n ' )
236
+ self .response .write ('<input type="submit" value="Save">\n ' )
237
+ self .response .write ('</form>\n ' )
238
+ self .response .write ('</body>\n ' )
239
+ self .response .write ('</html>' )
0 commit comments