Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # coding=UTF-8
- # базовый класс бота
- import html, logic, re, sys, time, urllib, urllib2, cookielib
- from sets import Set
- from pprint import pprint
- from FowWS import FowWS
- from threading import Thread
- from select import select
- class Fow:
- title = "Forces of War bot"
- author = "airevent"
- version = "4.1"
- outdated = "Bot is outdated"
- settings_path = "./settings.py"
- accounts_path = "./accounts.py"
- cookies_dir = "./cookies"
- commands = Set(["heal", "info", "invasion"])
- killed = False
- need_eol = False
- def __init__( self ):
- self.notice("Forces of War bot v"+self.version)
- self.configure()
- self.load_cookies()
- self.check_settings()
- self.apply_settings()
- self.start()
- def start( self ):
- self.notice("Executing command: "+self.command)
- getattr(self, "logic_"+self.command)()
- # вход в фейсбук
- def login_stage_1( self, acc ):
- self.notice("Login stage 1 (facebook auth)")
- self.notice("Loading facebook root")
- self.query(acc, self.settings["facebook_root"])
- form = html.get_form_by_action(acc["last_response"], acc["facebook_login_url_regexp"])
- if not form: # уже залогинены
- self.notice("Already logged in facebook")
- return
- try:
- form["inputs"]["email"] = acc["facebook_email"]
- form["inputs"]["pass"] = acc["facebook_pass"]
- except Exception as fail:
- self.error(self.outdated + "; facebook auth form parse failed")
- self.notice("Sending facebook auth form")
- self.query(acc, form["action"], urllib.urlencode(form["inputs"]))
- # вход в приложение
- def login_stage_2( self, acc ):
- self.notice("Login stage 2 (FoW auth)")
- self.notice("Loading fow app url")
- self.query(acc, self.settings["fow_login_url"])
- form = html.get_form_by_action(acc["last_response"], acc["fow_login_url_regexp"])
- if not form:
- self.error(self.outdated + "; fow login form not found")
- return
- self.notice("Sending fow auth form stage 1")
- self.query(acc, form["action"], urllib.urlencode(form["inputs"]))
- try:
- self.notice("Sending fow auth form stage 2")
- url = re.search("[\"'](http[^\"']+)[\"']", acc["last_response"]).group(1)
- self.query(acc, url)
- except Exception as fail:
- self.error(self.outdated + "; " + str(fail))
- # мы ещё залогинены?
- def in_fow( self, acc ):
- return re.search(acc["fow_session_check"], acc["last_response"])
- # авторизация вплоть до главной страницы игры
- def login( self, acc ):
- self.login_stage_1(acc)
- self.login_stage_2(acc)
- self.save_cookies(acc)
- # собрать игровую инфу о персонаже
- def gather_info( self, acc ):
- self.notice("Gathering info")
- self.game_query(acc, acc["fow_root"])
- logic.parse_main_info(acc)
- # результат удара босса
- def check_boss_answer( self, acc, boss ):
- flags = re.IGNORECASE | re.MULTILINE | re.DOTALL
- r = re.search("you are too high a level to fight", acc["last_response"], flags=flags)
- if r: return "highlvl"
- r = re.search("you aren.*? strong enough to fight", acc["last_response"], flags=flags)
- if r: return "lowlvl"
- r = re.search("is already dead!", acc["last_response"], flags=flags)
- if r: return "dead"
- r = re.search("must wait at least 1 second between", acc["last_response"], flags=flags)
- if r: return "1second"
- r = re.search("have any stamina to engage in battle", acc["last_response"], flags=flags)
- if r: return "noammo"
- r = re.search("too weak to battle. You must wait until your health", acc["last_response"], flags=flags)
- if r: return "nohp"
- # ударить босса
- def hit_boss( self, acc, boss ):
- flags = re.IGNORECASE | re.MULTILINE | re.DOTALL
- npc_id = boss["id"]
- self.notice("hitting boss " + str(npc_id) + " by " + acc["accname"])
- self.game_query(acc, acc["fow_root"]+"npc/attack", urllib.urlencode({
- "utf8": "✓",
- "authenticity_token": acc["info"]["csrf-token"],
- "npc_id": npc_id,
- "commit": "ATTACK",
- }), True)
- info = re.search(" ([\-0-9]+).n\s+<[^>]+span>health.*? ([\-0-9]+).n\s+<[^>]+span>dmg", acc["last_response"], flags=flags)
- if not info:
- status = self.check_boss_answer(acc, boss)
- if status=="highlvl":
- self.notice("boss lvl is too low")
- boss["bad"] = True
- elif status=="lowlvl":
- self.notice(acc["accname"] + " is too low for this boss")
- boss["bad"] = True
- elif status=="dead":
- self.notice("boss dead")
- boss["bad"] = True
- elif status=="1second":
- self.notice("1 second attack limit triggered, oops")
- elif status=="noammo":
- self.notice("no ammo, waiting for 5 minutes")
- time.sleep(5*60)
- elif status=="nohp":
- self.notice("no health")
- self.fow.heal(acc, "full")
- return self.hit_boss(acc, boss)
- else:
- pass
- else:
- lost = int(info.group(1))
- dealt = int(info.group(2))
- boss["lost"] += lost
- boss["dealt"] += dealt
- self.notice("hit result: " + str(lost) + " lost; " + str(dealt) + " dealt")
- return self.hit_boss(acc, boss)
- # загрузить инфу о боссе (уровень, возможность ударить)
- def load_boss_info( self, acc, npc_id ):
- flags = re.IGNORECASE | re.MULTILINE | re.DOTALL
- self.notice("getting boss " + str(npc_id) + " info")
- self.game_query(acc, acc["fow_root"]+"villains")
- tr = re.search("<tr npc=."+str(npc_id)+".>(.*?)</tr>", acc["last_response"], flags=flags)
- if not tr: return None
- tr = tr.group(1)
- # если нет кнопки атаки, то level не нужен
- level = re.search(">\s*Level\s*([0-9]+)\s*<.*?<input.*?type=\"submit\"", tr, flags=flags)
- if not level: return None
- return {
- "level": int(level.group(1)),
- }
- # напечатать игровую инфу
- def logic_info( self ):
- acc = self.accounts[self.account]
- self.gather_info(acc)
- pprint(acc["info"])
- # вылечиться
- def heal( self, acc, full=False ):
- url = acc["fow_root"] + "regeneration_chamber/regenerate"
- if full:
- self.notice("healing for full hp")
- url += "?type=full"
- else:
- self.notice("healing for 15%")
- self.game_query(acc, url, urllib.urlencode({
- "utf8": "✓",
- "authenticity_token": acc["info"]["csrf-token"],
- "commit": "heal",
- }), True)
- # лечиться
- def logic_heal( self ):
- acc = self.accounts[self.account]
- self.gather_info(acc)
- self.start_exit_thread()
- acc["ws"] = FowWS(acc)
- acc["ws"].start()
- # добывать золотые слитки
- def logic_invasion( self ):
- acc = self.accounts[self.account]
- self.notice(acc["accname"] + " hp_percent_to_start_hit_boss = " + str(acc["hp_percent_to_start_hit_boss"]))
- self.gather_info(acc)
- self.start_exit_thread()
- acc["ws"] = FowWS(acc)
- acc["ws"].start()
- # начать ожидание ввода команды выхода в отд. потоке
- def start_exit_thread( self ):
- thread = Thread(target = self.wait_for_stop)
- thread.start()
- def wait_for_stop( self ):
- while 1:
- if self.killed: break
- cmd = raw_input()
- if cmd=="stop" or cmd=="exit" or cmd=="quit":
- self.killed = True
- # чтение настроек
- def configure( self ):
- try:
- exec(open(self.settings_path).read())
- exec(open(self.accounts_path).read())
- except Exception as fail:
- self.error("File import failed: " + str(fail))
- try:
- self.command = sys.argv[1]
- except Exception as fail:
- self.error("Command not specified")
- try:
- self.account = sys.argv[2]
- except Exception as fail:
- self.error("Account not specified")
- # проверка настроек
- def check_settings( self ):
- if not self.command in self.commands:
- self.error("Unknown command: "+self.command)
- if not self.account in self.accounts:
- self.error("Unknown account: "+self.account)
- # скопировать дефолтные настройки каждому акку
- def apply_settings( self ):
- for accname in self.accounts:
- if accname=="example": continue
- acc = self.accounts[accname]
- for name in self.settings:
- if not name in acc: acc[name] = self.settings[name]
- # сохранить куки на диск выбранного акка
- def save_cookies( self, acc ):
- cj = acc["cookies"]
- cookies_path = acc["cookies_path"]
- try:
- cj.save(cookies_path, True, True)
- except Exception as fail:
- self.error("Unable to write cookies to file " + cookies_path + "; " + str(fail))
- # запрос с проверкой на игровую сессию
- def game_query( self, acc, url, data=None, ajax=False ):
- self.query(acc, url, data, ajax)
- if not ajax and not self.in_fow(acc):
- self.notice("Session lost, re-logging")
- self.login(acc)
- return self.game_query(acc, url, data, ajax)
- # запрос без проверки на сессию
- def query( self, acc, url, data=None, ajax=False ):
- headers = {
- "User-Agent": self.settings["User-Agent"],
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
- "Accept-Charset": "windows-1251,utf-8;q=0.7,*;q=0.3",
- "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4",
- }
- if "info" in acc and "uken-sesh" in acc["info"]:
- if re.search("\?", url): url += "&"
- else: url += "?"
- url += "u_vln="+acc["info"]["uken-sesh"]
- if ajax:
- headers["Accept"] = "text/javascript, application/javascript, */*"
- headers["X-Requested-With"] = "XMLHttpRequest"
- headers["X-CSRF-Token"] = acc["info"]["csrf-token"]
- headers["Origin"] = acc["fow_root"]
- headers["Referer"] = acc["fow_root"]
- request = urllib2.Request(url, data, headers)
- try:
- r = acc["browser"].open(request)
- acc["last_response"] = r.read()
- except Exception as fail:
- self.notice("Query failed, retrying in 5 seconds; " + str(fail))
- time.sleep(acc["retry_query_pause"])
- if self.fow.killed:
- self.fow.error("stopped by user input")
- return self.query(acc, url, data, ajax) # must be tail recursion
- # загрузить куки всех акков, если файла нет - создать пустые
- def load_cookies( self ):
- for accname in self.accounts:
- if accname=="example": continue
- acc = self.accounts[accname]
- cj = cookielib.MozillaCookieJar()
- cookies_path = self.cookies_dir+"/"+accname+".cookie"
- try:
- cj.load(cookies_path, True, True)
- except:
- pass
- acc["cookies_path"] = cookies_path
- acc["cookies"] = cj
- cp = urllib2.HTTPCookieProcessor(cj)
- if "proxy" in acc:
- self.notice(accname + " will use proxy-server: "+str(acc["proxy"]))
- ph = urllib2.ProxyHandler(acc["proxy"])
- else:
- ph = urllib2.ProxyHandler(None)
- acc["browser"] = urllib2.build_opener(cp, ph)
- acc["accname"] = accname
- acc["last_response"] = ""
- acc["fow"] = self
- acc["info"] = {}
- def add_eol_if_need( self ):
- if self.need_eol:
- print("")
- self.need_eol = False
- def notice( self, msg ):
- self.add_eol_if_need()
- print(time.strftime("%H:%M:%S ") + str(msg))
- self.need_eol = False
- sys.stdout.flush()
- def error( self, msg ):
- self.add_eol_if_need()
- self.notice("Fatal error: " + str(msg))
- self.need_eol = False
- self.killed = True
- sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment