[pyKoL-users] SF.net SVN: pykol: [25] trunk
Brought to you by:
scelis
From: <mi...@us...> - 2007-08-17 10:59:41
|
Revision: 25 http://pykol.svn.sourceforge.net/pykol/?rev=25&view=rev Author: misza13 Date: 2007-08-17 03:59:35 -0700 (Fri, 17 Aug 2007) Log Message: ----------- Standarising repository layout. Created /trunk, /branches and /tags. Moved all files under /trunk. Added Paths: ----------- branches/ tags/ trunk/ trunk/.svnignore trunk/LICENSE trunk/adventure.py trunk/bots/ trunk/campground.py trunk/kolsite.py trunk/mall.py trunk/test.py Removed Paths: ------------- .svnignore LICENSE adventure.py bots/ campground.py kolsite.py mall.py test.py Deleted: .svnignore =================================================================== --- .svnignore 2007-06-03 22:25:53 UTC (rev 24) +++ .svnignore 2007-08-17 10:59:35 UTC (rev 25) @@ -1,2 +0,0 @@ -*.pyc -*.conf Deleted: LICENSE =================================================================== --- LICENSE 2007-06-03 22:25:53 UTC (rev 24) +++ LICENSE 2007-08-17 10:59:35 UTC (rev 25) @@ -1,19 +0,0 @@ -Copyright (C) Misza <mi...@mi...>, 2007 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. Deleted: adventure.py =================================================================== --- adventure.py 2007-06-03 22:25:53 UTC (rev 24) +++ adventure.py 2007-08-17 10:59:35 UTC (rev 25) @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (C) Misza <mi...@mi...>, 2007 -# -# Distributed under the terms of the MIT license. -# - -import re - -class AutoAdventurer: - def __init__(self, site): - self.site = site - - def adventure(self, snarfblat): - print 'Starting adventure...' - response, data = self.site.getPage('adventure.php?snarfblat='+snarfblat) - - if response.getheader('location')=='fight.php': - self.fighting = True - while self.fighting: - self.fight() - - def fight(self): - response, data = self.site.getPage('fight.php') - - monRX = re.search(r"You're fighting <span id='monname'>(?P<monname>.*?)</span>",data) - print "You're fighting %s" % monRX.group('monname') - - tackRX = re.search(r"<input id='tack' class=button type=submit value=\"Attack with your (?P<tackitem>.*?)\">",data) - - formdata = { - 'action' : 'attack', - 'tack' : 'Attack with your ' + tackRX.group('tackitem'), - } - response, data = self.site.postForm('fight.php',formdata) - - if "You win the fight!" in data: - print "You win the fight!" - self.fighting = False - else: - self.fighting = True Deleted: campground.py =================================================================== --- campground.py 2007-06-03 22:25:53 UTC (rev 24) +++ campground.py 2007-08-17 10:59:35 UTC (rev 25) @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (C) Misza <mi...@mi...>, 2007 -# -# Distributed under the terms of the MIT license. -# - -import re - -class Campground: - def __init__(self, site): - self.site = site - - - def rest(self, count=1): - #Function will return cumulative gains: - cHPgain = 0 - cMPgain = 0 - for i in range(count): - print 'Now resting...' - response, data = self.site.getPage('campground.php?action=rest') - - if "You don't need to rest." in data: - print "You don't need to rest." - break - else: - rx = re.search(r'You sleep.*?You gain (?P<hp>\d+).*?You gain (?P<mp>\d+)',data) - if rx: - HPgain = int(rx.group('hp')) - MPgain = int(rx.group('mp')) - print 'You gained %d HP, %d MP' % (HPgain,MPgain) - return (cHPgain,cMPgain) Deleted: kolsite.py =================================================================== --- kolsite.py 2007-06-03 22:25:53 UTC (rev 24) +++ kolsite.py 2007-08-17 10:59:35 UTC (rev 25) @@ -1,156 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (C) Misza <mi...@mi...>, 2007 -# -# Distributed under the terms of the MIT license. -# -import re, urllib, httplib - -try: - import hashlib - new_md5 = hashlib.md5 -except ImportError: #Old python? - import md5 - new_md5 = md5.md5 - - -def urlEncode(query): - """This can encode a query so that it can be sent as a query using - a http POST request""" - if not query: - return None - l = [] - for key, value in query.iteritems(): - key = urllib.quote(key) - value = urllib.quote(value) - l.append(key + '=' + value) - return '&'.join(l) - - -def challengePassword(challenge,password): - m = new_md5() - m.update(password) - hashedpw = m.hexdigest() - m = new_md5() - m.update(hashedpw+':'+challenge) - return m.hexdigest() - - -class LoginError: - def __init__(self,reason='None'): - self.reason = reason - - def __repr__(self): - return 'LoginError{%s}' % self.reason - - -class KoLSite: - def __init__(self): - self.hostname = 'www.kingdomofloathing.com' - self.cookie = None - - - def getPage(self, address, data=''): - #print 'GET http://' + self.hostname + '/' + address - conn = httplib.HTTPConnection(self.hostname) - - conn.putrequest('GET', '/' + address) - if self.cookie: - conn.putheader('Cookie', self.cookie) - conn.endheaders() - conn.send('') - - response = conn.getresponse() - data = response.read().decode('utf-8') - conn.close() - return response, data - - - def postForm(self, address, formdata): - data = urlEncode(formdata) - return self.postData(address, data) - - - def postData(self, address, data=''): - #print 'POST http://' + self.hostname + '/' + address - conn = httplib.HTTPConnection(self.hostname) - - conn.putrequest('POST', '/' + address) - if self.cookie: - conn.putheader('Cookie', self.cookie) - conn.putheader('Content-Length', str(len(data))) - conn.putheader('Content-Type', 'application/x-www-form-urlencoded') - conn.endheaders() - conn.send(data) - - response = conn.getresponse() - data = response.read().decode('utf-8') - conn.close() - return response, data - - - def doLogin(self, nick, password): - try: - cookie = file('cookie','r').readlines() - self.cookie = cookie[1][:-1] - self.hostname = cookie[0][:-1] - except: - self.cookie = None - - if self.cookie: - print 'Trying a recovered cookie...' - response, data = self.getPage('main.php') - if data or response.getheader('location')=='fight.php': - print "Successfully recovered cookie file." - return - - challenge = self.getChallenge() - - formFields = {} - formFields['loggingin'] = 'Yup.' - formFields['loginname'] = nick - if challenge: - print 'Logging in using challenge...' - formFields['challenge'] = challenge - formFields['response'] = challengePassword(challenge,password) - else: - print 'Logging in without challenge...' - formFields['password'] = password - formFields['secure'] = '1' - - response, data = self.postForm('login.php',formFields) - - if response.status == 302: - self.cookie = response.getheader('set-cookie') - file('cookie','w+').write('%s\n%s\n' % (self.hostname,self.cookie)) - print 'Saved cookie file.' - return - - if re.search('Bad password.',data): - raise LoginError, 'Bad password.' - elif re.search('Too many login failures from this IP.',data): - raise LoginError, 'Too many login failures from this IP.' - elif re.search('Too many login attempts',data): - raise LoginError, 'Too many login attempts.' - else: - raise LoginError, data - - - def getChallenge(self): - print 'Getting login challenge...' - response, data = self.getPage('') - while response.status == 302: - #We got redirected - locRE = re.search('http://(www\d?.kingdomofloathing.com)/(.*)',response.getheader('location')) - if locRE: #Bounced off to a different server? - self.hostname = locRE.group(1) - response, data = self.getPage(locRE.group(2)) - else: #Same server, getting loginid= - response, data = self.getPage(response.getheader('location')) - - #We're there. Looking for challenge... - challenge = re.search('<input type=hidden name=challenge value="([0-9a-f]+)">',data) - if challenge: - return challenge.group(1) - else: - return '' Deleted: mall.py =================================================================== --- mall.py 2007-06-03 22:25:53 UTC (rev 24) +++ mall.py 2007-08-17 10:59:35 UTC (rev 25) @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (C) Misza <mi...@mi...>, 2007 -# -# Distributed under the terms of the MIT license. -# -import re - -import kolsite - -class Mall: - def __init__(self, Site): - self.Site = Site - - def searchItem(self, what, limit=None): - formdata = {'whichitem' : what} - if limit: - formdata['cheaponly'] = '1' - formdata['shownum'] = str(limit) - response, data = self.Site.postForm('searchmall.php',formdata) - - offset = re.search('Price:',data).start() - itemRX = re.compile(r'<b>(?P<itemname>.+?)</b> \((?P<itemcount>\d+)\)(?: \((?P<limit>\d+) / day\))?.*?mallstore.php\?whichstore=(?P<whichstore>\d+).*?>(?P<shopname>.+)</a>.*?>(?P<price>[0-9,]+) ') - for itemM in itemRX.finditer(data,offset): - result = {} - for v in ['itemname','itemcount','limit','whichstore','shopname','price']: - if v == 'itemcount': - result[v] = int(itemM.group('itemcount').replace(',','')) - elif v == 'limit' and itemM.group('limit'): - result[v] = int(itemM.group('limit').replace(',','')) - elif v == 'price': - result[v] = int(itemM.group('price').replace(',','')) - elif v == 'whichstore': - result[v] = int(itemM.group('whichstore').replace(',','')) - else: - result[v] = itemM.group(v) - yield result - Deleted: test.py =================================================================== --- test.py 2007-06-03 22:25:53 UTC (rev 24) +++ test.py 2007-08-17 10:59:35 UTC (rev 25) @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (C) Misza <mi...@mi...>, 2007 -# -# Distributed under the terms of the MIT license. -# -import sys, random -from kolsite import KoLSite -from mall import Mall - - -def main(): - if len(sys.argv) < 2: - print 'Please specify a config file!' - return - config = {} - execfile(sys.argv[1]) - if not config.has_key('nick') or not config.has_key('password'): - print 'Nick or password not specified in config!' - return - - Site = KoLSite() - Site.doLogin(config['nick'],config['password']) - - #response, data = Site.getPage('main.html') - #print response.status - #print data - - M = Mall(Site) - for s in M.searchItem('tiny plastic sword'): - print s - -if __name__ == '__main__': - main() Copied: trunk/.svnignore (from rev 24, .svnignore) =================================================================== --- trunk/.svnignore (rev 0) +++ trunk/.svnignore 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,2 @@ +*.pyc +*.conf Copied: trunk/LICENSE (from rev 24, LICENSE) =================================================================== --- trunk/LICENSE (rev 0) +++ trunk/LICENSE 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,19 @@ +Copyright (C) Misza <mi...@mi...>, 2007 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. Copied: trunk/adventure.py (from rev 24, adventure.py) =================================================================== --- trunk/adventure.py (rev 0) +++ trunk/adventure.py 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# (C) Misza <mi...@mi...>, 2007 +# +# Distributed under the terms of the MIT license. +# + +import re + +class AutoAdventurer: + def __init__(self, site): + self.site = site + + def adventure(self, snarfblat): + print 'Starting adventure...' + response, data = self.site.getPage('adventure.php?snarfblat='+snarfblat) + + if response.getheader('location')=='fight.php': + self.fighting = True + while self.fighting: + self.fight() + + def fight(self): + response, data = self.site.getPage('fight.php') + + monRX = re.search(r"You're fighting <span id='monname'>(?P<monname>.*?)</span>",data) + print "You're fighting %s" % monRX.group('monname') + + tackRX = re.search(r"<input id='tack' class=button type=submit value=\"Attack with your (?P<tackitem>.*?)\">",data) + + formdata = { + 'action' : 'attack', + 'tack' : 'Attack with your ' + tackRX.group('tackitem'), + } + response, data = self.site.postForm('fight.php',formdata) + + if "You win the fight!" in data: + print "You win the fight!" + self.fighting = False + else: + self.fighting = True Copied: trunk/bots (from rev 24, bots) Copied: trunk/campground.py (from rev 24, campground.py) =================================================================== --- trunk/campground.py (rev 0) +++ trunk/campground.py 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# (C) Misza <mi...@mi...>, 2007 +# +# Distributed under the terms of the MIT license. +# + +import re + +class Campground: + def __init__(self, site): + self.site = site + + + def rest(self, count=1): + #Function will return cumulative gains: + cHPgain = 0 + cMPgain = 0 + for i in range(count): + print 'Now resting...' + response, data = self.site.getPage('campground.php?action=rest') + + if "You don't need to rest." in data: + print "You don't need to rest." + break + else: + rx = re.search(r'You sleep.*?You gain (?P<hp>\d+).*?You gain (?P<mp>\d+)',data) + if rx: + HPgain = int(rx.group('hp')) + MPgain = int(rx.group('mp')) + print 'You gained %d HP, %d MP' % (HPgain,MPgain) + return (cHPgain,cMPgain) Copied: trunk/kolsite.py (from rev 24, kolsite.py) =================================================================== --- trunk/kolsite.py (rev 0) +++ trunk/kolsite.py 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# +# (C) Misza <mi...@mi...>, 2007 +# +# Distributed under the terms of the MIT license. +# +import re, urllib, httplib + +try: + import hashlib + new_md5 = hashlib.md5 +except ImportError: #Old python? + import md5 + new_md5 = md5.md5 + + +def urlEncode(query): + """This can encode a query so that it can be sent as a query using + a http POST request""" + if not query: + return None + l = [] + for key, value in query.iteritems(): + key = urllib.quote(key) + value = urllib.quote(value) + l.append(key + '=' + value) + return '&'.join(l) + + +def challengePassword(challenge,password): + m = new_md5() + m.update(password) + hashedpw = m.hexdigest() + m = new_md5() + m.update(hashedpw+':'+challenge) + return m.hexdigest() + + +class LoginError: + def __init__(self,reason='None'): + self.reason = reason + + def __repr__(self): + return 'LoginError{%s}' % self.reason + + +class KoLSite: + def __init__(self): + self.hostname = 'www.kingdomofloathing.com' + self.cookie = None + + + def getPage(self, address, data=''): + #print 'GET http://' + self.hostname + '/' + address + conn = httplib.HTTPConnection(self.hostname) + + conn.putrequest('GET', '/' + address) + if self.cookie: + conn.putheader('Cookie', self.cookie) + conn.endheaders() + conn.send('') + + response = conn.getresponse() + data = response.read().decode('utf-8') + conn.close() + return response, data + + + def postForm(self, address, formdata): + data = urlEncode(formdata) + return self.postData(address, data) + + + def postData(self, address, data=''): + #print 'POST http://' + self.hostname + '/' + address + conn = httplib.HTTPConnection(self.hostname) + + conn.putrequest('POST', '/' + address) + if self.cookie: + conn.putheader('Cookie', self.cookie) + conn.putheader('Content-Length', str(len(data))) + conn.putheader('Content-Type', 'application/x-www-form-urlencoded') + conn.endheaders() + conn.send(data) + + response = conn.getresponse() + data = response.read().decode('utf-8') + conn.close() + return response, data + + + def doLogin(self, nick, password): + try: + cookie = file('cookie','r').readlines() + self.cookie = cookie[1][:-1] + self.hostname = cookie[0][:-1] + except: + self.cookie = None + + if self.cookie: + print 'Trying a recovered cookie...' + response, data = self.getPage('main.php') + if data or response.getheader('location')=='fight.php': + print "Successfully recovered cookie file." + return + + challenge = self.getChallenge() + + formFields = {} + formFields['loggingin'] = 'Yup.' + formFields['loginname'] = nick + if challenge: + print 'Logging in using challenge...' + formFields['challenge'] = challenge + formFields['response'] = challengePassword(challenge,password) + else: + print 'Logging in without challenge...' + formFields['password'] = password + formFields['secure'] = '1' + + response, data = self.postForm('login.php',formFields) + + if response.status == 302: + self.cookie = response.getheader('set-cookie') + file('cookie','w+').write('%s\n%s\n' % (self.hostname,self.cookie)) + print 'Saved cookie file.' + return + + if re.search('Bad password.',data): + raise LoginError, 'Bad password.' + elif re.search('Too many login failures from this IP.',data): + raise LoginError, 'Too many login failures from this IP.' + elif re.search('Too many login attempts',data): + raise LoginError, 'Too many login attempts.' + else: + raise LoginError, data + + + def getChallenge(self): + print 'Getting login challenge...' + response, data = self.getPage('') + while response.status == 302: + #We got redirected + locRE = re.search('http://(www\d?.kingdomofloathing.com)/(.*)',response.getheader('location')) + if locRE: #Bounced off to a different server? + self.hostname = locRE.group(1) + response, data = self.getPage(locRE.group(2)) + else: #Same server, getting loginid= + response, data = self.getPage(response.getheader('location')) + + #We're there. Looking for challenge... + challenge = re.search('<input type=hidden name=challenge value="([0-9a-f]+)">',data) + if challenge: + return challenge.group(1) + else: + return '' Copied: trunk/mall.py (from rev 24, mall.py) =================================================================== --- trunk/mall.py (rev 0) +++ trunk/mall.py 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# (C) Misza <mi...@mi...>, 2007 +# +# Distributed under the terms of the MIT license. +# +import re + +import kolsite + +class Mall: + def __init__(self, Site): + self.Site = Site + + def searchItem(self, what, limit=None): + formdata = {'whichitem' : what} + if limit: + formdata['cheaponly'] = '1' + formdata['shownum'] = str(limit) + response, data = self.Site.postForm('searchmall.php',formdata) + + offset = re.search('Price:',data).start() + itemRX = re.compile(r'<b>(?P<itemname>.+?)</b> \((?P<itemcount>\d+)\)(?: \((?P<limit>\d+) / day\))?.*?mallstore.php\?whichstore=(?P<whichstore>\d+).*?>(?P<shopname>.+)</a>.*?>(?P<price>[0-9,]+) ') + for itemM in itemRX.finditer(data,offset): + result = {} + for v in ['itemname','itemcount','limit','whichstore','shopname','price']: + if v == 'itemcount': + result[v] = int(itemM.group('itemcount').replace(',','')) + elif v == 'limit' and itemM.group('limit'): + result[v] = int(itemM.group('limit').replace(',','')) + elif v == 'price': + result[v] = int(itemM.group('price').replace(',','')) + elif v == 'whichstore': + result[v] = int(itemM.group('whichstore').replace(',','')) + else: + result[v] = itemM.group(v) + yield result + Copied: trunk/test.py (from rev 24, test.py) =================================================================== --- trunk/test.py (rev 0) +++ trunk/test.py 2007-08-17 10:59:35 UTC (rev 25) @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# +# (C) Misza <mi...@mi...>, 2007 +# +# Distributed under the terms of the MIT license. +# +import sys, random +from kolsite import KoLSite +from mall import Mall + + +def main(): + if len(sys.argv) < 2: + print 'Please specify a config file!' + return + config = {} + execfile(sys.argv[1]) + if not config.has_key('nick') or not config.has_key('password'): + print 'Nick or password not specified in config!' + return + + Site = KoLSite() + Site.doLogin(config['nick'],config['password']) + + #response, data = Site.getPage('main.html') + #print response.status + #print data + + M = Mall(Site) + for s in M.searchItem('tiny plastic sword'): + print s + +if __name__ == '__main__': + main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |