from config import * shells_to_gold=multipliers["shells_to_gold"] hp_multiplier=1 #currently the hp levels are a bit in turmoil [03/03/19] def calculate_game_dynamics(): #I hope this will be an important function, should always stay at top [05/11/18] #decided to leave gold calculations at server_functions.js for now [06/11/18] for name in items.keys(): current=items[name] # 1$ = 120 SHELLS # 1M = 2$ => 120 SHELLS = 500K # Originally 240 SHELLS = 288K # Probably, 120 SHELLS = 160K = BEST - 320,000 / 120 = 1333 ~ 1375 if current.get("cash"): current["g"]=current["cash"]*shells_to_gold #825 from 1375 [15/10/16] 1600 from 825 [22/11/16] 3200 from 1600 [16/12/16] 4800 from 3200 [08/11/17] 32000 from 4800 [03/02/18] if not current.get("g"): logging.error("%s doesn't have g!"%name) current["g"]=1 if hp_multiplier!=1: if current.get("hp"): current["hp"]=round(hp_multiplier*current["hp"]) if current.get("upgrade") and current["upgrade"].get("hp"): current["upgrade"]["hp"]=round(hp_multiplier*current["upgrade"]["hp"]) if current.get("compound") and current["compound"].get("hp"): current["compound"]["hp"]=round(hp_multiplier*current["compound"]["hp"]) calculate_game_dynamics() def monster_analysis(logging=None): if not logging: logging=globals()["logging"] for monster in monsters: current=monsters[monster] gold=monster_gold[monster]*drops["gold"]["base"]+monster_gold[monster]*drops["gold"]["random"]/2 gold+=monster_gold[monster]*10*drops["gold"]["x10"]+monster_gold[monster]*50*drops["gold"]["x50"] logging.info("%s avg.gold: %.1f"%(monster,gold)) for damage in [120,400,800,1600]: logging.info("\nfor %d damage/second in 1 hour"%damage) for monster in monsters: current=monsters[monster] gold=monster_gold[monster]*drops["gold"]["base"]+monster_gold[monster]*drops["gold"]["random"]/2 gold+=monster_gold[monster]*10*drops["gold"]["x10"]+monster_gold[monster]*50*drops["gold"]["x50"] hits=math.ceil(current["hp"]*1.0/damage) kills=60.0*60/hits logging.info("%s kills: %.1f gold: %s xp: %s"%(monster,kills,to_pretty_num(gold*kills),to_pretty_num(current["xp"]*kills))) def calculate_xvalue(name): drop_value=0 for drop in drops[name]: prob=drop[0] name=drop[1] if name=="open": drop_value+=prob*calculate_xvalue(drop[2]) elif name=="shells": drop_value+=prob*drop[2]*shells_to_gold else: drop_value+=items[name]["g"] return drop_value def monster_analysis2(logging=None): if not logging: logging=globals()["logging"] for monster in monsters: current=monsters[monster] gold=monster_gold[monster]*drops["gold"]["base"]+monster_gold[monster]*drops["gold"]["random"]/2 gold+=monster_gold[monster]*10*drops["gold"]["x10"]+monster_gold[monster]*50*drops["gold"]["x50"] mdrops=drops["monsters"].get(monster,[]); drop_value=0 for drop in mdrops: prob=drop[0] name=drop[1] if name=="open": drop_value+=prob*calculate_xvalue(drop[2]) elif name=="shells": drop_value+=prob*drop[2]*shells_to_gold else: drop_value+=prob*items[name]["g"] logging.info("%s 100*gold/hp: %s drops: %s totalgold/hp: %s"%(monster,100*gold/current["hp"],drop_value,100*(gold+drop_value)/current["hp"])) def drop_analysis(logging=None,count=1000,only=None): if not logging: logging=globals()["logging"] for name in drops: try: if not is_array(drops[name]): continue if only and name!=only: continue current=drops[name] # if not current.get("e"): continue # Normally "items" was traversed instead of "drops" dropl=drops[name]; total=0; gold=0; loot={} for drop in dropl: total+=drop[0] for i in xrange(0,count): roll=random.uniform(0,total); current=0 for drop in dropl: current+=drop[0] if roll<=current: if drop[1]=="open": if not loot.get(drop[2]): loot[drop[2]]=0 loot[drop[2]]+=1 else: if not loot.get(drop[1]): loot[drop[1]]=0 loot[drop[1]]+=(len(drop)<3 and 1) or drop[2] break logging.info("%s drops: [x%s]"%(name,count)) for name in loot: logging.info("\t%s %s"%(name,loot[name])) logging.info("\n") except: log_trace(logging) logging.info("\nAnalysis failed for %s\n"%name) def item_value(item): gold=items[item["name"]]["g"] if item.get("q",0): gold*=item.get("q",0) level=item.get("level",0) if items[item["name"]].get("upgrade"): if is_sdk: level=min(level,12) gold*=[1,1,1.1,1.4,1.6,2,4,8,16,50,500,800,1600,20000][level] if items[item["name"]].get("compound"): if is_sdk: level=min(level,5) gold*=[1,3,9,27,81,243,800,3600,15000,50000][level] return gold def total_xp(character): xp=character.xp for i in range(1,character.level): xp+=levels["%s"%i] return xp def total_worth(element,characters=True): gold=element.info.gold i_list=["items"] for i in xrange(64): i_list.append("items%d"%i) for c in i_list: if not gf(element,c,[]): continue for item in gf(element,c,[]): if not item: continue gold+=item_value(item) if element.k(1).startswith("character|"): for slot in gf(element,"slots",{}): item=element.info.slots[slot] if not item: continue gold+=item_value(item) if characters: for c in gf(element,"characters",[]): character=get_by_iid("character|%s"%c["id"]) if not character: continue gold+=total_worth(character) return gold def log_items(element,name,logging=None): if type(element)==type(""): element=get_owner(element) logging.info("%s %s"%(element.k(1),element.name)) i_list=["items"] for i in xrange(64): i_list.append("items%d"%i) for c in i_list: if not gf(element,c,[]): continue for item in gf(element,c,[]): if not item: continue if item["name"]==name: logging.info("STORAGE %s %s"%(c,item)) if element.k(1).startswith("character|"): for slot in gf(element,"slots",{}): item=element.info.slots[slot] if not item: continue if item["name"]==name: logging.info("SLOT %s %s"%(element.name,item)) if gf(element,"p") and element.info.p.get("trade_history"): for i in xrange(len(element.info.p["trade_history"])): if element.info.p["trade_history"][i][2]["name"]==name: logging.info("TRADE %s"%(element.info.p["trade_history"][i])) if not element.k(1).startswith("character|"): for c in gf(element,"characters",[]): character=get_by_iid("character|%s"%c["id"]) if not character: continue log_items(character,name,logging) def refactor_map(map): data=map.info.data if data.get("default") and type(data["default"])!=type(1): current=0; marked=False for tile in data.get("tiles",[]): if tile==data["default"]: data["default"]=current marked=True current+=1 if not marked: data["tiles"].append(data["default"]) data["default"]=len(data["tiles"])-1 current=0 for tile in data.get("tiles",[]): if type(tile[3])==type([]): tile.append(tile[3][1]) tile[3]=tile[3][0] return data def process_map(map): marked={}; last=0; current=0; new_tiles=[]; min_x=900; min_y=900; max_x=-900; max_y=-900; x_lines=[]; y_lines=[] data=map.info.data if data.get("x_lines"): data["x_lines"].sort() if data.get("y_lines"): data["y_lines"].sort() if data.get("default"): marked[data["default"]]=True for animation in data.get("animations",[]): marked[animation[0]]=True for animation in data.get("lights",[]): marked[animation[0]]=True for animation in data.get("nights",[]): marked[animation[0]]=True for group in data.get("groups",[]): for placement in group: if len(placement)==5 and placement[3]==placement[1] and placement[4]==placement[2]: del placement[3:] marked[placement[0]]=True for line in data.get("x_lines",[]): if line[1]!=line[2]: x_lines.append(line) #logging.info("%s / %s"%(len(data["x_lines"]),len(x_lines))) data["x_lines"]=x_lines for line in data.get("y_lines",[]): if line[1]!=line[2]: y_lines.append(line) #logging.info("%s / %s"%(len(data["y_lines"]),len(y_lines))) data["y_lines"]=y_lines for placement in data.get("placements",[]): marked[placement[0]]=True tile=data["tiles"][placement[0]] if len(placement)==5 and placement[3]==placement[1] and placement[4]==placement[2]: del placement[3:] if type(tile[3])==type([]): width,height=tile[3] else: width=height=tile[3] if placement[1]max_x: max_x=placement[3]+width if placement[4]+height>max_y: max_y=placement[4]+height else: if placement[1]+width>max_x: max_x=placement[1]+width if placement[2]+height>max_y: max_y=placement[2]+height for tile in data.get("tiles",[]): if current not in marked: logging.info("%s is unused"%current) else: marked[current]=last last+=1 #logging.info("%s is %s"%(current,marked[current])) new_tiles.append(tile) current+=1 data["tiles"]=new_tiles if data.get("default"): data["default"]=marked[data["default"]] for animation in data.get("animations",[]): animation[0]=marked[animation[0]] for animation in data.get("lights",[]): animation[0]=marked[animation[0]] for animation in data.get("nights",[]): animation[0]=marked[animation[0]] for group in data.get("groups",[]): for placement in group: placement[0]=marked[placement[0]] for placement in data.get("placements",[]): placement[0]=marked[placement[0]] if min_x>max_x: min_x=-10; max_x=10; min_y=-10; max_y=10 data["min_x"]=min_x data["min_y"]=min_y data["max_x"]=max_x data["max_y"]=max_y def render_selection(self,user,domain,level=80,server=None): servers=get_servers(); if not server: server=select_server(self,user,servers); total=0; characters=[]; data=None for s in servers: total+=gf(s,"players") or 0 if user: characters=get_characters(user) domain.characters=characters_to_client(characters) data=get_user_data(user); domain.servers=servers_to_client(domain,servers) if domain.is_cli and (not user or not user.cli_time or user.cli_time=70: domain.is_cli=False; domain.harakiri=True start=datetime.now(); logging.info("User data in: %s"%ssince(start)) return whtml(self,"htmls/index.html",domain=domain,user=user,user_data=data,server=server,servers=servers,total=total,characters=characters) def render_comm(self,user,domain): servers=get_servers(); server=select_server(self,user,servers); total=0; characters=[]; data={} for s in servers: total+=gf(s,"players") or 0 domain.servers=servers_to_client(domain,servers) if user: characters=get_characters(user) domain.characters=characters_to_client(characters) data=get_user_data(user); return whtml(self,"htmls/comm.html",domain=domain,user=user,user_data=data,server=server,servers=servers,total=total,characters=characters) def selection_info(self,user,domain): servers=get_servers(); server=select_server(self,user,servers) return {"type":"content","html":shtml("htmls/contents/selection.html",user=user,domain=domain,server=server,servers=servers,characters=get_characters(user))} def security_threat(request,domain): #return False referer=request.headers.get('Referer') or request.headers.get('Origin') or "" if not referer: return False referer=urlparse(referer).hostname if not referer.endswith(domain.domain): request.response.set_data("Threat detected") return True # if is_production and domain.cf_always_on and not is_cloudflare(self): # conditional_response(self,domain,response,"cloudflare") # st_log(self,"cloudflare") # return True return False def disable_email(email,logging=None): if not logging: logging=globals()["logging"] user=get_user(email=email) if not user: return logging.info("User not found") user.info.dont_send_emails=True user.put() logging.info("Disabled emails for %s"%user) def get_user(request=None,domain=None,email=None,phrase_check=False,api_override=None): if email: try: email=purify_email(email) if phrase_check: mark=get_by_iid("markedphrase|email-%s"%email) if mark: user=get_by_iid("user|%s"%mark.owner) if user: return user return User.query(User.email == email).get() except: logTrace() elif request: auth=get_cookie(request,"auth") or request.values.get("auth") if auth: id,auth=auth.replace('"',"").split("-") get_user_data(id,_async=True) #trigger the get user=get_by_iid("user|%s"%id) if user and (api_override or auth in gf(user,"auths",[])): return user def character_in_transaction_routines(character,flags): if character.referrer and character.level>=50 and not gf(character,"rfreward_50"): character.info.rfreward_50=datetime.now() flags.rf50=character.referrer if character.referrer and character.level>=60 and not gf(character,"rfreward_60"): character.info.rfreward_60=datetime.now() flags.rf60=character.referrer if character.referrer and character.level>=70 and not gf(character,"rfreward_70"): character.info.rfreward_70=datetime.now() flags.rf60=character.referrer def handle_character_flags(flags): if getattr(flags,"rf50"): pass def send_verification_email(domain,user): url="%s/ev/%s/%s"%(domain.base_url,user.k(),user.info.everification) send_email(domain,user.info.email,html=shtml("htmls/email.html",purpose="verification",url=url,domain=domain,user=user),title="Welcome to %s! Verification Link + Early Game Suggestions Inside"%game_name,text="To Verify Your Email: %s"%url) def send_password_reminder_email(domain,user): url="%s/reset/%s/%s"%(domain.base_url,user.k(),user.info.password_key) send_email(domain,user.info.email,html=shtml("htmls/email.html",purpose="password",domain=domain,url=url),title="Password Reminder from %s"%game_name,text="To reset your password, please visit: %s"%url) def is_in_game(character): return character.server and hsince(character.last_sync)<=4 # 5 hours seem logical - instead of 18 hours return character.server and msince(character.last_sync)<12 def ip_in_range(ip,net): try: ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16) netstr, bits = net.split('/') netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16) mask = (0xffffffff << (32 - int(bits))) & 0xffffffff return (ipaddr & mask) == (netaddr & mask) except: log_trace() return False def get_ip(request): ip=request.remote_addr cloudflare_ip=request.headers.get("CF-Connecting-IP") cloudflare_ranges=[ '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22', '104.16.0.0/12', '108.162.192.0/18', '131.0.72.0/22', '141.101.64.0/18', '162.158.0.0/15', '172.64.0.0/13', '173.245.48.0/20', '188.114.96.0/20', '190.93.240.0/20', '197.234.240.0/22', '198.41.128.0/17', ] cloudflare_ranges_v6=[ '2400:cb00::/32', '2405:b500::/32', '2606:4700::/32', '2803:f800::/32', '2c0f:f248::/32', '2a06:98c0::/29', ] if cloudflare_ip: for crange in cloudflare_ranges: if ip.find(":")==-1 and ip_in_range(ip,crange): return cloudflare_ip for crange in cloudflare_ranges_v6: if ip.find(":")!=-1 and ip.startswith(crange[:7]): return cloudflare_ip #not sure 9 or 7 [25/08/13] return request.remote_addr def get_country(request): return request.headers.get("Cf-Ipcountry") or request.headers.get("X-Appengine-Country") or "XX" def get_character(id,phrase_check=False): if id.isdigit() and get_by_iid("character|%s"%id): return get_by_iid("character|%s"%id) else: id=simplify_name(id) if phrase_check: mark=get_by_iid("markedphrase|character-%s"%id) if mark: character=get_by_iid("character|%s"%mark.owner) if character: return character return Character.query(Character.name == id).get() def get_owner(name): char=get_character(name) if char: return get_by_iid("user|%s"%char.owner) def process_user_data(user,data): if hasattr(user,"k"): user=user.k() if not data: data=InfoElement(key=ndb.Key(InfoElement,"userdata-%s"%user),info=GG()) if not gf(data,"completed_tasks"): data.info.completed_tasks=[] #completed tutorial tasks if not gf(data,"tutorial_step"): data.info.tutorial_step=0 #tutorial step calculate_tutorial_step(data) return data def get_user_data(user,_async=False): if hasattr(user,"k"): user=user.k() if _async: return get_by_iid_async("infoelement|userdata-%s"%user) else: data=get_by_iid("infoelement|userdata-%s"%user) data=process_user_data(user,data) return data def delete_user_data(user): if hasattr(user,"k"): user=user.k() ndb.Key(InfoElement,"userdata-%s"%user).delete() def reset_tutorial(user): data=get_user_data(user,_async=False) data.info.completed_tasks=[] #completed tutorial tasks data.info.tutorial_step=0 #tutorial step data.put() return data def add_ip_exception(ip_a,limit=0,explanation=""): limit=max(1,min(limit,10)) if limit==1: return remove_ip_exception(ip_a) ip=get_ip_info(ip_a) ip.info.limit=limit if not ip.random_id: ip.random_id=randomStr(20) ip.exception=True ip.last_exception=datetime.now() ip.info.explanation=explanation or "No Explanation Exception" ip.put() def remove_ip_exception(ip_a): ip=get_ip_info(ip_a) ip.info.limit=1 ip.exception=False ip.put() def get_ip_info(ip): if not is_string(ip): ip=get_ip(ip) info=get_by_iid("ip|%s"%ip) if not info: info=IP(key=ndb.Key(IP,ip),info=cGG(users=[],characters=[],metrics={},last_decay=datetime.now())) decay_ip_info(info) return info def decay_ip_info(ip): hours=hsince(ip.info.last_decay) if hours>12: r=hours/24.0 for k in dir(ip.info): if k.startswith("limit_"): if k=="limit_signups": r/=1.2 setattr(ip.info,k,getattr(ip.info,k)-r) if getattr(ip.info,k)<0: setattr(ip.info,k,0) ip.info.last_decay=datetime.now() def put_ip_info(ip,user=None,character=None): if user and (user.k() not in ip.info.users): ip.info.users.append(user.k()) if character and (character.k() not in ip.info.characters): ip.info.characters.append(character.k()) if len(ip.info.users)>100: ip.info.users=ip.info.users[1:] if len(ip.info.characters)>100: ip.info.characters=ip.info.characters[1:] ip.users=ip.info.users; ip.characters=ip.info.characters ip.put_async() def characters_to_client(characters_data): characters=[] for character in characters_data: characters.append(character_to_dict(character)) characters.sort(key=(lambda x: x["online"]),reverse=True) return characters def servers_to_client(domain,servers_data): servers=[] for server in servers_data: servers.append({"name":server.name,"region":server.region,"players":server.info.players,"key":server.k(),"addr":domain.https and server.ip or server.actual_ip,"port":server.port}) return servers def get_characters(user,_async=False): characters=[] for c in user.info.characters: characters.append(get_by_iid_async("character|%s"%c["id"])) if _async: return characters for i in xrange(len(characters)): characters[i]=characters[i].get_result() return characters def get_stats(characters): stats={"monsters":{}} for character in characters: monsters=gf(character,"p",{}).get("stats",{}).get("monsters",{}) monsters_diff=gf(character,"p",{}).get("stats",{}).get("monsters_diff",{}) for id in monsters: if monsters[id]+monsters_diff.get(id,0)>stats["monsters"].get(id,[0,0])[0]: stats["monsters"][id]=[monsters[id]+monsters_diff.get(id,0),character.info.name] return stats def character_to_dict(character): data={"id":character.k(),"name":character.info.name,"level":character.level,"type":character.type,"online":0} if character.online: data["online"]=mssince(character.last_online) data["server"]=character.server data["secret"]=gf(character,"secret","12") if gf(character,"rip"): data["rip"]=character.info.rip data["skin"]=character.info.skin data["cx"]=gf(character,"cx",{}) data["in"]=gf(character,"in",character.info.map) data["map"]=character.info.map data["x"]=character.info.x data["y"]=character.info.y if gf(character,"p") and "home" in character.info.p: data["home"]=character.info.p["home"] return data def update_user_data(user,data): user.info.gold=data["gold"] user.info.rewards=data.get("rewards",[]) user.info.unlocked=data.get("unlocked",{}) user.info.items0=data["items0"] user.info.items1=data["items1"] user.info.last_sync=datetime.now() for i in range(2,48): setattr(user.info,"items%d"%i,data.get("items%d"%i,False)) def user_to_server(user): info={ "gold":gf(user,"gold",1000), "rewards":gf(user,"rewards",[]), "unlocked":gf(user,"unlocked",{}), "items0":gf(user,"items0",[]), "items1":gf(user,"items1",[]), } for i in range(2,48): info["items%d"%i]=gf(user,"items%d"%i,False) return info def guild_to_info(guild): return { "id":guild.k(), "name":guild.name, "short":guild.short} def update_character(character,data,owner): character.info.x=data["x"] character.info.y=data["y"] character.info.s=data["s"] character.info.q=data.get("q",{}) #character.info.c=data["c"] character.info.map=data["map"] setattr(character.info,"in",data["in"]) character.xp=int(data["xp"] or 0) character.level=int(data["level"]) character.info.hp=data["hp"] character.info.mp=data["mp"] character.info.gold=data["gold"] character.info.items=data["items"] character.info.slots=data["slots"] #character.info.trades=data.get("trades") character.info.rip=data.get("rip") if data.get("p",0): character.info.p=data.get("p") character.info.skin=data.get("skin") character.info.cx=data.get("cx",{}) character.info.afk=data.get("afk") character.private=data.get("private") character.info.owner_name=owner.name def update_pids(character,data,owner): fresh=False; platform="web"; pid="" steam_id=data.get("p",0) and data["p"].get("steam_id","") mas_auth_id=data.get("p",0) and data["p"].get("mas_auth_id","") if data.get("p",0) and data["p"].get("platform","")=="steam" and steam_id: fresh=True platform="steam" pid=steam_id if data.get("p",0) and data["p"].get("platform","")=="mas" and mas_auth_id: fresh=True platform="steam" pid=mas_auth_id if steam_id: character.platform="steam" character.pid=steam_id elif mas_auth_id: character.platform="mas" character.pid=mas_auth_id if fresh and (owner.platform!=platform or owner.pid!=pid): #there's a chance that a player both have mas and steam accounts, so steam priority logic might be good here [03/05/19] user=get_by_iid(owner.k('i')) user.platform=platform user.pid=pid user.put() logging.info("costly operation - changed user platform/pid - %s"%user.k()) elif not fresh and steam_id and not owner.pid: user=get_by_iid(owner.k('i')) user.platform="steam" user.pid=steam_id user.put() logging.info("costly operation - set steam user platform/pid - %s"%user.k()) elif not fresh and mas_auth_id and not owner.pid: user=get_by_iid(owner.k('i')) user.platform="mas" user.pid=mas_auth_id user.put() logging.info("costly operation - set mas user platform/pid - %s"%user.k()) elif not fresh and (owner.platform!=character.platform or owner.pid!=character.pid): character.platform=owner.platform character.pid=owner.pid def character_to_info(character,user=None,ip=None,guild=None): drm=False drm_fail=False if user and user.created>datetime(2019,2,1,0,0) and not gf(user,"legacy_override"): drm=True if gf(user,"drm_fail_pid","not")==character.pid: drm_fail=True info={ "id":character.k(), "name":character.info.name, "friends":character.friends, "level":character.level, #"gender":character.info.gender, "gold":character.info.gold, "type":character.type, "xp":character.xp, "items":character.info.items, "stats":character.info.stats, "slots":gf(character,"slots",{}), "skin":character.info.skin, "cx":gf(character,"cx",[]), "platform":character.platform, "pid":character.pid or user and user.pid, "drm":drm, "drm_fail":drm_fail, "x":character.info.x, "y":character.info.y, "map":character.info.map, "owner":character.owner, "private":character.private, "created":int(time.mktime(character.created.timetuple()))*1000, "hp":gf(character,"hp",0), "mp":gf(character,"mp",0), "afk":gf(character,"afk",0), "s":gf(character,"s",{}), "c":gf(character,"c",{}), "q":gf(character,"q",{}), #"trades":gf(character,"trades",0), "rip":gf(character,"rip",0), "p":gf(character,"p",{"dt":{}}) or {"dt":{}}, #or is to fix the temporary, pre-server update glitch [12/09/16] } if guild: info["guild"]=guild_to_info(guild) if ip and ip.exception: info["ipx"]=ip.info.limit if user: info["cash"]=user.cash info["verified"]=gf(user,"verified",0) return info def character_emit(character,method,data): if character.server: server=get_by_iid("server|%s"%character.server) if server: server_eval_safe(server,"var p=players[name_to_id['%s']]; if(p) p.socket.emit('%s',data);"%(character.info.name,method),data=data) def character_eval(character,code,data={}): if character.server: server=get_by_iid("server|%s"%character.server) if server: server_eval_safe(server,"var player=players[name_to_id['%s']]; if(player) { %s; }"%(character.info.name,code),data=data) def notify_friends(character,server_name): server_list={} servers=get_servers() online=Character.query(Character.friends == character.owner,Character.online == True) for friend in online: if not friend.server: continue server_list[friend.server]=server_list.get(friend.server,[]) server_list[friend.server].append(friend.info.name) for server in servers: if server_list.get(server.k()): server_eval(server,"notify_friends(data)",data={"list":server_list[server.k()],"name":character.info.name,"server":server_name}) def update_characters(user,reason=None,name=None,shells=0): def set_friends(): c=get_by_iid(character.k('i')) c.friends=user.friends c.put() for character in Character.query(Character.online==True,Character.owner==user.k()): if character.server: try: server=get_by_iid("server|%s"%character.server) ip=server.actual_ip if is_sdk: ip="0.0.0.0" if not reason: fetch_url("http://%s:%s"%(ip,server.port),aevent="cupdate",spass=secrets.ACCESS_MASTER,cash=user.cash,id=character.info.name,ncash=shells) elif reason=="friends": try: ndb.transaction(set_friends,xg=True,retries=0) except: log_trace_i() fetch_url("http://%s:%s"%(ip,server.port),aevent="new_friend",spass=secrets.ACCESS_MASTER,name=name,friends=user.friends,id=character.info.name) elif reason=="not_friends": try: ndb.transaction(set_friends,xg=True,retries=0) except: log_trace_i() fetch_url("http://%s:%s"%(ip,server.port),aevent="lost_friend",spass=secrets.ACCESS_MASTER,name=name,friends=user.friends,id=character.info.name) #character_emit(character,"friend",{"event":"update","friends":user.friends}) except: log_trace() def send_system_mail(user,subject,message,type=None,info=None): if not type: type="system" if not hasattr(user,"k"): user=get_by_iid("user|%s"%user) mail=Mail(fro="0",to=user.info.name,type=type,owner=["0",user.k()],info=cGG(message=message,subject=subject,sender="0",receiver=user.k())) mail.put() user_data=get_user_data(user) user_data.info.mail=max(0,gf(user_data,"mail",0)-1) user_data.put() def pretty_timeleft(t): left="" minutes=int((t-datetime.now()).seconds/60.0) days=(t-datetime.now()).days if days: left="%d days"%days if minutes>60: left=left+" %d hours"%(int(minutes/60)) minutes=minutes%(60) left=left+" %d minutes"%minutes return left def gdpr_delete(request,user,logging=None): from api import delete_character_api if not logging: logging=globals()["logging"] if not hasattr(user,"k"): user=get_user(email=user) for c in gf(user,"characters",[]): user.info.last_delete=really_old delete_character_api(user=user,self=request,domain=gdi(request),name=c["name"]) logging.info("Deleted %s"%c["name"]) markedphrase=get_by_iid("markedphrase|%s"%dgt("email",user.info.email)) if markedphrase: markedphrase.key.delete() user.key.delete() logging.info("Deleted %s"%user.info.email) def block_account(name,days,reason="",toggle=False): character=get_character(name) if not character: return "no character" owner=get_by_iid("user|%s"%character.owner) if not owner: return "no owner" if toggle and gf(owner,"blocked_until") and owner.info.blocked_until>datetime.now(): days=-1 if days<=0: owner.info.blocked_until=really_old owner.banned=False owner.put() return "un-blocked %s"%owner.k() else: owner.info.blocked_until=datetime.now()+timedelta(seconds=int(days*24*60*60)) owner.info.blocked_reason=reason owner.banned=True owner.put() servers=get_servers() for server in servers: server_eval(server,"for(var id in players) { if(players[id].owner=='%s') { players[id].socket.emit('disconnect_reason','blocked'); players[id].socket.disconnect(); } }"%owner.k()) return "blocked %s for %s days"%(owner.k(),days) def servers_eval(code,data={}): servers=get_servers() for server in servers: server_eval_safe(server,code,data=data) def chat_analysis(name,logging=None): for m in Message.query(Message.author==get_owner("orlyowl").k()).order(-Message.created).fetch(100): logging.info("%s - %s"%(m.created,m.info.message)) def growth_analysis(name,logging=None,days=50,offset=0): if not logging: logging=globals()["logging"] owner=get_owner(name); owner_ki=owner.k('i') latest={}; last_gold=total_worth(owner,characters=False); last_pgold=owner.info.gold; last_xp=0 logging.info("") logging.info("USER Gold: %s Cash: %s"%(to_pretty_num(owner.info.gold),to_pretty_num(owner.cash))) for character in Character.query(Character.owner == ""+owner.k()): #logging.info("%s[%s] %s"%(character.info.name,character.level,to_pretty_num(character.info.gold))) latest[character.k('i')]=character last_xp+=total_xp(character) last_gold+=total_worth(character) last_pgold+=character.info.gold logging.info("TODAY GOLD %s XP %s"%(to_pretty_num(last_gold),to_pretty_num(last_xp))) for i in range(1,days): cut_off=datetime.now()-timedelta(days=i+offset) b=Backup.query(Backup.backup_item_id==owner_ki).filter(Backup.backup_created <= cut_off).order(-Backup.backup_created).get() if b and (cut_off-b.backup_created).days*24+(cut_off-b.backup_created).seconds/3600<=24: owner=b c_xp=0; c_gold=total_worth(owner,characters=False); c_pgold=owner.info.gold for n in latest: ch=latest[n] c=Backup.query(Backup.backup_item_id==n).filter(Backup.backup_created <= cut_off).order(-Backup.backup_created).get() if c and (cut_off-c.backup_created).days*24+(cut_off-c.backup_created).seconds/3600<=24: latest[n]=c ch=c c_xp+=total_xp(ch) c_gold+=total_worth(ch) c_pgold+=ch.info.gold logging.info("D[%s] GOLD %s PURE GOLD %s XP %s"%(offset+i,to_pretty_num(last_gold-c_gold),to_pretty_num(last_pgold-c_pgold),to_pretty_num(last_xp-c_xp))) last_xp=c_xp last_gold=c_gold last_pgold=c_pgold def character_analysis(name,logging=None): if not logging: logging=globals()["logging"] character=get_character(name) servers=get_servers(); players=[]; ip=""; owners=[character.owner] for server in servers: cip=server_eval(server,"var cip=''; for(var id in players) { var player=players[id]; if(player.name!='%s') continue; cip=get_ip(player); }; output=cip;"%name) if cip: ip=cip for server in servers: splayers=server_eval(server,"var list=[]; for(var id in players) { var player=players[id]; if(get_ip(player)!='%s') continue; list.push({owner:player.owner,name:player.name,ip:get_ip(player),server:region+' '+server_name,type:player.type,level:player.level,age:player.age,cgold:player.t.cgold,dgold:player.t.dgold,txp:player.t.xp,minutes:msince(player.t.start),dps:player.t.mdamage/ssince(player.t.start),gps:(player.t.cgold+player.t.dgold)/ssince(player.t.start),xps:player.t.xp/ssince(player.t.start)}); }; output=list;"%ip) for player in splayers: if player["owner"] not in owners: owners.append(player["owner"]) logging.info("Secondary owner: %s"%player["owner"]) players.append(player) for player in players: logging.info(player) l=[] for owner in owners: oos={} tos={} froms={} owner=get_by_iid("user|"+owner) logging.info("") logging.info("USER Gold: %s Cash: %s"%(to_pretty_num(owner.info.gold),to_pretty_num(owner.cash))) if owner.platform=="steam": result=fetch_url_async("https://partner.steam-api.com/ISteamUser/CheckAppOwnership/v2/",use_get=True,key=steam_publisher_web_apikey,appid="777150",steamid=owner.pid).get_result() if result.content.find('"ownsapp":true')!=-1: logging.info("Steam ownership: YES") else: logging.info(result.content) l.append(owner) l.append(get_user_data(owner)) names={} characters=Character.query(Character.owner == ""+owner.k()).fetch(100) for character in characters: names[character.info.name]=True i_list=[] for i in xrange(64): i_list.append("items%d"%i) for c in i_list: if not gf(owner,c,[]): continue for item in gf(owner,c,[]): if not item: continue oo=None if item.get("gf") and item["gf"] not in names: oo=item["gf"] elif item.get("o") and item["o"] not in names: oo=item["o"] elif item.get("oo") and item["oo"] not in names: oo=item["oo"] if oo: logging.info(item) oos[oo]=[oos.get(oo,[0,0])[0]+1,oos.get(oo,[0,0])[1]+item_value(item)] for character in characters: l.append(character) for item in gf(character,"items",[]): if not item: continue oo=None if item.get("gf") and item["gf"] not in names: oo=item["gf"] elif item.get("o") and item["o"] not in names: oo=item["o"] elif item.get("oo") and item["oo"] not in names: oo=item["oo"] if oo: logging.info(item) oos[oo]=[oos.get(oo,[0,0])[0]+1,oos.get(oo,[0,0])[1]+item_value(item)] for slot in gf(character,"slots",{}): item=character.info.slots[slot] if not item: continue oo=None if item.get("gf") and item["gf"] not in names: oo=item["gf"] elif item.get("o") and item["o"] not in names: oo=item["o"] elif item.get("oo") and item["oo"] not in names: oo=item["oo"] if oo: logging.info(item) oos[oo]=[oos.get(oo,[0,0])[0]+1,oos.get(oo,[0,0])[1]+item_value(item)] logging.info("%s[%s] %s"%(character.info.name,character.level,to_pretty_num(character.info.gold))) for h in gf(character,"p",{}).get("history",[]): if h.get("from") and h.get("from") not in names: e=froms.get(h["from"],[0,0]) e[0]+=1 e[1]+=h.get("amount",0) or h.get("item","") and item_value({"name":h["item"],"level":h.get("level",0)}) or 0 froms[h["from"]]=e if h.get("to") and h.get("to") not in names: e=tos.get(h["to"],[0,0]) e[0]+=1 e[1]+=h.get("amount",0) or h.get("item","") and item_value({"name":h["item"],"level":h.get("level",0)}) or 0 tos[h["to"]]=e logging.info("OOS:") logging.info(oos) logging.info("FROMS:") logging.info(froms) logging.info("TOS:") logging.info(tos) return l def game_analysis(logging=None): if not logging: logging=globals()["logging"] servers=get_servers(True); players=[]; ips={} for server in servers: try: splayers=server_eval(server,"var list=[]; for(var id in players) { var player=players[id]; list.push({owner:player.owner,name:player.name,ip:get_ip(player),type:player.type,level:player.level,age:player.age,map:player.map,gold:to_pretty_num(player.gold),server:region+' '+server_name,dps:player.t.mdamage/ssince(player.t.start),gps:(player.t.cgold+player.t.dgold)/ssince(player.t.start),xps:player.t.xp/ssince(player.t.start)}); }; output=list;") for player in splayers: #player["pvp"]=gf(server,"pvp") player["server"]="%s %s"%(server.region,server.name) players.append(player) except: log_trace_i() for player in players: if not ips.get(player["ip"]): ips[player["ip"]]=[] ips[player["ip"]].append(player) for server in servers: logging.info("%s %s - Gold: %s"%(server.region,server.name,to_pretty_num(gf(server,"data",{}).get("gold",0)))) logging.info("") for ip in ips: logging.info("") owners=[]; dps=0.0001; gps=0 for player in ips[ip]: if player["owner"] not in owners: owners.append(player["owner"]) if len(owners)>1: logging.info("MULTIPLE PLAYERS FROM ONE IP") for player in ips[ip]: logging.info(player) dps+=player.get("dps",0) gps+=player.get("gps",0) logging.info("GPS / DPS: %s"%(gps/dps)) def enforce_limitations(): servers=get_servers() players=[]; ips={}; mips={}; owners={}; mowners={}; ipx={}; ip_type={} to_ipdisconnect=[]; to_ownerdisconnect=[]; to_authdisconnect=[] for server in servers: if server.gameplay!="normal": continue try: splayers=server_eval(server,"var list=[]; for(var id in players) { var player=players[id]; list.push({owner:player.owner,name:player.name,ip:get_ip(player),type:player.type,bot:player.bot||'',free:player.p.free||player.s.licenced||player.role=='gm',ipx:player.ipx||1,temp_auth:player.temp_auth||'',auth_id:player.auth_id||''}); }; output=list;") for player in splayers: player["pvp"]=gf(server,"pvp") players.append(player) server.players=splayers #time.sleep(1) #best not to sleep here, otherwise a server change counts +1 [10/12/17] except: log_trace_i() #logging.info(players) for player in players: #count loop ip_type[player["ip"]]="real" if player["free"]: continue #the bot limitations should be enforced at launch - or re-visited later on [03/08/17] if player["auth_id"]: if player["type"]!="merchant": ips[player["ip"]]=ips.get(player["ip"],0)+1 #so steam/mas logins don't allow separate IP logins else: mips[player["ip"]]=mips.get(player["ip"],0)+1 player["ip"]=player["auth_id"] player["ipx"]=1 ip_type[player["ip"]]="auth" if player["temp_auth"]: if player["type"]!="merchant": ips[player["ip"]]=ips.get(player["ip"],0)+1 #so temporary mas logins don't allow separate IP logins else: mips[player["ip"]]=mips.get(player["ip"],0)+1 player["ip"]=player.owner player["ipx"]=1 ip_type[player["ip"]]="owner" ipx[player["ip"]]=max(ipx.get(player["ip"],0),player["ipx"]) if player["type"]=="merchant": mowners[player["owner"]]=mowners.get(player["owner"],0)+1 mips[player["ip"]]=mips.get(player["ip"],0)+1 else: owners[player["owner"]]=owners.get(player["owner"],0)+1 ips[player["ip"]]=ips.get(player["ip"],0)+1 #for 1+1+1, it makes more sense to use a global 2-ip limit #this new enforce loop handles every player individually, much simpler than previous ip/owner/auth loops [12/05/19] for server in servers: #enforce loop if server.gameplay!="normal": continue to_disconnect=[] for player in server.players: logging.info(player["name"]) if player["free"]: continue #if player["type"]=="merchant": logging.info("%s mips %s mowners %s - ipx %s"%(player["ip"],mips[player["ip"]],mowners[player["owner"]],ipx[player["ip"]])) if player["type"]=="merchant" and (mips[player["ip"]]>1 or mowners[player["owner"]]>1) and player["name"] not in to_disconnect: to_disconnect.append(player["name"]) continue if player["type"]!="merchant" and (ips[player["ip"]]>3*ipx[player["ip"]] or owners[player["owner"]]>3) and player["name"] not in to_disconnect: to_disconnect.append(player["name"]) continue if len(to_disconnect): server_eval(server,"%s.forEach(function(name){ var player=get_player(name); if(!player) return; player.socket.emit('disconnect_reason','limits'); player.socket.disconnect(); });"%json.dumps(to_disconnect)) time.sleep(1) del server.players def verify_steam_installs(): logging.info("verify_steam_installs") owners=[]; bans=[]; checks={} for c in Character.query(Character.platform=="steam").order(-Character.last_online).fetch(1000): if hsince(c.last_online)>=4: break if c.owner not in owners: owners.append(c.owner) checks[c.owner]=fetch_url_async("https://partner.steam-api.com/ISteamUser/CheckAppOwnership/v2/",use_get=True,key=steam_publisher_web_apikey,appid="777150",steamid=c.pid) for id in checks: try: result=checks[id].get_result() if 1/2==0: if result.content.find(b'"ownsapp":true')!=-1: logging.info("%s yes!"%id) elif result.content.find('"ownsapp":false')!=-1: logging.error("%s no!"%id) else: logging.error("%s Unhandled output %s"%(id,result.content)) else: result=checks[id].get_result() if b'"ownsapp":true' in result.content: logging.info("%s yes!"%id) elif b'"ownsapp":false' in result.content: logging.error("%s no!"%id) else: logging.error("%s Unhandled output %s"%(id,result.content)) except: log_trace() def server_eval(server,code,data={}): ip=server.actual_ip if is_sdk: ip="0.0.0.0" return json.loads(fetch_url("http://%s:%s"%(ip,server.port),aevent="eval",spass=secrets.ACCESS_MASTER,code=code.replace("+","%2B"),data=json.dumps(data).replace("+","%2B"))) def server_eval_safe(server,code,data={}): try: ip=server.actual_ip if is_sdk: ip="0.0.0.0" return json.loads(fetch_url("http://%s:%s"%(ip,server.port),aevent="eval",spass=secrets.ACCESS_MASTER,code=code.replace("+","%2B"),data=json.dumps(data).replace("+","%2B"))) except: log_trace() return None def reward_referrer_logic(user): if user.referrer and user.platform in ["steam","mas"] and not gf(user,"reward") and user.pid: def reward_transaction(): entity=get_by_iid(user.k('i')) if not gf(entity,"reward"): entity.info.reward=True entity.put() return True return False if ndb.transaction(reward_transaction,xg=True,retries=0): deferred.defer(add_cash,user.referrer,200,rcash=True,rreward=user.k()) def add_referred(referrer,user,selfic=None): referrer=get_by_iid("user|%s"%referrer) user=get_by_iid("user|%s"%user) def add_referred_transaction(): a=get_by_iid(referrer.k('i')) a.put() ndb.transaction(add_referred_transaction,xg=True,retries=0) def add_referrer_manually(referred_email,referrers_email,logging=None): if not logging: logging=globals()["logging"] a=get_user(email=referred_email) if not a: return logging.info("Referred doesn't exit!") b=get_user(email=referrers_email) if not b: return logging.info("Referrer doesn't exist!") if a.created=20: referrer=get_by_iid("user|%s"%user.referrer) if referrer: add_event(referrer,"referrer_cash",["cashflow","referrer"],info=cGG(message="Referrer: %s received %s shells from %s[%s]"%(referrer.name,int(round(cash*0.10)),user.name,user.k()),source=user.k())) add_cash(referrer,int(round(cash*0.10)),rcash=True) except: log_trace() try: if rreward: InfoElement(key=ndb.Key(InfoElement,"rrewardmark-%s"%referred.pid),info=GG()).put() logging.info("RREWARD EVENT %s"%rreward) add_event(user,"referrer_reward",["cashflow","referrer"],info=cGG(message="Referrer: %s received %s reward shells from %s[%s]"%(user.name,200,referred.name,referred.k()),source=referred.k())) except: log_trace() return 1 else: raise "WTF" def get_characters_old(user): keys=[] for c in gf(user,"characters",[]): keys.append(ndb.Key(Character,to_id(c["id"]))) return ndb.get_multi(keys) def select_server(self,user,servers): if not len(servers): return None #servers.sort(key=lambda server: server.region+server.name) min_dist=99999999999; the_server=None; max_rank=-99999; u_server="" if user and len(gf(user,"characters",[])): for c in gf(user,"characters",[]): if "home" in c: u_server=c["home"] break; logging.info(u_server) try: country=get_country(self) latlon=c_to_ll.get(country.lower(),[0,0]) latlon[0],latlon[1]=float(latlon[0]),float(latlon[1]) for server in servers: dist=abs(server.info.lat-latlon[0])**2+abs(server.info.lon-latlon[1])**2 rank=100+server.info.players/10000.0 if server.info.players>50: rank=10-server.info.players/10000.0 if server.info.pvp: rank=1; dist+=19999999999 if server.port==8098: rank=-1000; dist+=29999999999 logging.info("user %s server %s %s"%(latlon,[server.info.lat,server.info.lon],rank)) if server.region+server.name==u_server: dist=-1; rank=99999999 if distmax_rank: min_dist=dist; the_server=server max_rank=rank if the_server: return the_server except: log_trace() return servers[0] def get_servers(no_cache=False): servers=memcache.get("servers"+(1/2!=0 and "v3" or "")) if not servers or no_cache: servers=[] for server in Server.query(Server.online == True): if msince(server.last_update)<5: servers.append(server) servers.sort(key=lambda s: (s.region=="EU" and "1" or s.region=="US" and "2" or s.region=="ASIA" and "3")+s.name) #logging.info(servers) return servers def set_servers(current=None): servers=[] if current: servers.append(current) for server in Server.query(Server.online == True): if msince(server.last_update)<5 and server.online and not (current and current.k()==server.k()): del server.info.data # otherwise easily exceeds 1MB [13/06/19] servers.append(server) memcache.set("servers"+(1/2!=0 and "v3" or ""),servers) def check_servers(): offlines=[]; servers=[] for server in Server.query(Server.online == True): if not server.last_update or msince(server.last_update)>4: logging.error("Server Unexpectedly Offline: %s"%server) server.online=False server.put() offlines.append(server.k()) if 0: logging.info("Freeing Players") for player in Character.query(Character.server == server.k()): player.server="" player.put() logging.info("Freed %s"%player.name) else: logging.error("Player Freeing Routine is Manually Disabled") else: del server.info.data servers.append(server) logging.info("Server Alive: %s"%server) memcache.set("servers"+(1/2!=0 and "v3" or ""),servers) if offlines: send_email(gdi(),"kaansoral@gmail.com",html="%s"%offlines,title="OFFLINE SERVERS DETECTED") enforce_limitations() def free_servers(): if not is_sdk: return for server in Server.query(Server.online == True): server.online=False server.put() def refactor_all(): for character in Character.query(): if character.type=="wizard": character.type="mage" character.put() def unlock_all(): for character in Character.query(): character.server="" character.put() def delete_all(): if not is_sdk: return for user in User.query(): user.key.delete() for character in Character.query(): character.key.delete() for mark in MarkedPhrase.query(): mark.key.delete() for server in Server.query(): server.key.delete() ndb.Key(InfoElement,"main").delete() def refactor_item(current): if current and (items[current["name"]].get("upgrade","") or items[current["name"]].get("compound","")) and not current.get("level",""): current["level"]=0 if current and items[current["name"]].get("s",""): current["q"]=current.get("quantity",current.get("q",1)) if "quantity" in current: del current["quantity"] def refactor_character_items(character): for i in range(0,len(character.info.items)): current=character.info.items[i] refactor_item(current) for slot in character.info.slots: refactor_item(character.info.slots[slot]) def update_all_characters(): for character in Character.query(): refactor_character_items(character) character.put() def send_map(name): if not is_sdk: return post_task("m=Map(key=ndb.Key(Map,element.key.id()),info=element.info); m.put()",element=get_by_iid("map|%s"%name)) def send_maps(): if not is_sdk: return for m in Map.query(): post_task("m=Map(key=ndb.Key(Map,element.key.id()),info=element.info); m.put()",element=m) def download_map(name,sdk_name=""): if not is_sdk: return if not sdk_name: sdk_name=name element=download_by_iid("map|%s"%name) if element: Map(key=ndb.Key(Map,sdk_name),info=element.info).put() def download_maps(): if not is_sdk: return for m in maps: element=download_by_iid("map|%s"%maps[m]["key"]) if element: Map(key=ndb.Key(Map,maps[m]["key"]),info=element.info).put() def empty_fill_maps(): if not is_sdk: return for m in maps: element=get_by_iid("map|%s"%maps[m]["key"]) if not element: Map(key=ndb.Key(Map,maps[m]["key"]),info=cGG(data={"tiles":[],"placements":[]})).put() def copy_map(fr,to): fr=get_by_iid("map|%s"%fr) m=Map(key=ndb.Key(Map,to),info=fr.info); m.put() def get_server(request,domain): auth=request.values.get("server_auth") if auth: logging.info("get_server auth: %s"%auth) id,auth=auth.split("-") server=get_by_iid("server|%s"%id) if server and gf(server,"auth")==auth: return server def get_referrer(request,ip): referrer=get_cookie(request,"referrer") or ip.referrer if referrer and referrer.replace('"',"")[0] in ["0","1","2","3","4","5","6","7","8","9"]: referrer=get_by_iid("user|%s"%referrer.replace('"',"")) elif referrer: referrer=get_owner(referrer.replace('"',"")) return referrer def get_signupth(): main=get_by_iid("infoelement|main") if not main: return 1 return gf(main,"signupth",1) def increase_signupth(): main=get_by_iid("infoelement|main") if not main: main=InfoElement(key=ndb.Key(InfoElement,"main"),info=GG()) main.info.signupth=2 else: main.info.signupth=gf(main,"signupth",1)+1 try: main.put() except: logTrace() def get_characterth(): main=get_by_iid("infoelement|main") if not main: return 1 return gf(main,"characterth",1) def increase_characterth(): main=get_by_iid("infoelement|main") if not main: main=InfoElement(key=ndb.Key(InfoElement,"main"),info=GG()) main.info.characterth=gf(main,"characterth",1)+1 try: main.put() except: logTrace() def get_new_auth(request,user,domain): auth=randomStr(20) user.info.auths=gf(user,"auths",[]) user.info.last_auth=datetime.now() if len(user.info.auths)>200: user.info.auths=[] user.info.auths.append(auth) return auth def download_by_iid(iid): result=urlfetch.fetch(url="https://twodimensionalgame.appspot.com/tasks/download",payload=urlencode({"password":ELEMENT_PASSWORD,"iid":iid}), method=urlfetch.POST,headers={'Content-Type':'application/x-www-form-urlencoded'},validate_certificate=False) return cPickle.loads(result.content) def post_task(task,element=None,element2=None,element3=None,logging=None): if not logging: logging=globals()["logging"] if not is_sdk: logging.error("sdk only") element=element and cPickle.dumps(element) or "" element2=element2 and cPickle.dumps(element2) or "" element3=element3 and cPickle.dumps(element3) or "" result=urlfetch.fetch(url="https://twodimensionalgame.appspot.com/tasks/post",payload=urlencode({"p":SDK_UPLOAD_PASSWORD,"operation":"upload","obj1":element,"obj2":element2,"obj3":element3,"task_code":task}), method=urlfetch.POST,headers={'Content-Type': 'application/x-www-form-urlencoded'},validate_certificate=False) result=cPickle.loads(str(result.content)) logging.info("post_task result: %s"%result) return result def safe_commit(element): pass #GTODO: Implement def domain_routine(domain): pass #GTODO: Implement def delete_phrase_mark(type,phrase,_async=False): ndb.Key(MarkedPhrase,dgt(type,phrase)).delete() def mark_phrase(owner,phrase_type,phrase,_async=False): MarkedPhrase(key=ndb.Key(MarkedPhrase,dgt(phrase_type,phrase)),type=phrase_type,phrase=str_or_unicode(phrase),owner=to_string_key(owner)).put() def marker_check(id): def marker_transaction(): if ndb.Key(Marker,id).get(): return False Marker(key=ndb.Key(Marker,id)).put() return True return ndb.transaction(marker_transaction,xg=True,retries=12) def whtml(request,path,**dct): #path = os.path.join(os.path.dirname(__file__), pth) start_time=datetime.now() template = j2.get_template(path) if mssince(start_time)>250: logging.warning("JINJA2 WARNING %s took %s ms"%(path,mssince(start_time))) response=template.render(dct) if dct.get("domain","") and dct["domain"].electron: if dct["domain"].https: response=response.replace('="/','="%s/'%dct["domain"].secure_base_url).replace("='/","='%s/"%dct["domain"].secure_base_url) else: response=response.replace('="/','="%s/'%dct["domain"].base_url).replace("='/","='%s/"%dct["domain"].base_url) request.response.set_data(response) return request.response def shtml(path,**dct): #path = os.path.join(os.path.dirname(__file__), pth) start_time=datetime.now() template = j2.get_template(path) if mssince(start_time)>250: logging.warning("JINJA2 WARNING %s took %s ms"%(path,mssince(start_time))) response=template.render(dct) if dct.get("domain","") and dct["domain"].electron: if dct["domain"].https: response=response.replace('="/','="%s/'%dct["domain"].secure_base_url).replace("='/","='%s/"%dct["domain"].secure_base_url) else: response=response.replace('="/','="%s/'%dct["domain"].base_url).replace("='/","='%s/"%dct["domain"].base_url) return response def pre_put_hook(self): try: if hasattr(self,"random_number") and not self.random_number: self.random_number=random.randrange(1,101) if hasattr(self,"has_scatter") and random.randrange(0,10000)==12: self.has_scatter=True if hasattr(self,"server") and hasattr(self,"online"): if self.server: self.online=True else: self.online=False except: logging.error("pre_put_hook exception") def arr_arr_same(ar1,ar2): if len(ar1)!=len(ar2): return False d={} for e in ar1: d[e]=1 for e in ar2: if not d.get(e): return False return True def delete_phrase_mark(type,phrase,_async=False): ndb.Key(MarkedPhrase,dgt(type,phrase)).delete() def mark_phrase(owner,phrase_type,phrase,_async=False): MarkedPhrase(key=ndb.Key(MarkedPhrase,dgt(phrase_type,phrase)),type=phrase_type,phrase=str_or_unicode(phrase),owner=to_string_key(owner)).put() def to_id(id): if id=="": id="8" #to prevent the empty key exceptions [22/07/14] if type(id)==type({}): if id.get("a_t"): id=id.get("a") else: id=id.get("id") if hasattr(id,"k"): id=has_key(id) id=to_str(id) if id.isdigit(): return int(id) return id def k_factory(self,t=""): if t=="h": the_key=self.key.id() if is_int(the_key): return the_key return string_to_int(the_key) if t=="e": return "%s"%has_key(self) or "-1" #as a placeholder mainly for the StuffHandler routines [28/08/14] if t=="s": the_key=has_key(self) else: the_key=self.key.id() try: u"%s"%the_key except: the_key=the_key.decode("utf-8") if t in ["i","s",1]: return dmt(model_name(self),the_key) try: return unicode(the_key) except: return str(the_key) #python3 [27/01/24] def to_model(string): d=globals() if string.title() in d: return d[string.title()] for e in d.keys(): try: if len(e) and e[0].isupper() and e.lower()==string.lower(): return d[e] except: pass def dgt(*list,**dct): lst=[] for i in range(0,len(list)): lst.append(to_str(list[i])) if "sort" in dct: lst.sort() return "-".join(lst) def dge(*list,**dct): lst=[] for i in range(0,len(list)): lst.append(to_str(list[i])) if "sort" in dct: lst.sort() return "".join(lst) def dse(*list,**dct): lst=[] for i in range(0,len(list)): lst.append(to_str(list[i])) if "sort" in dct: lst.sort() return " ".join(lst) def dmt(*list,**dct): lst=[] for i in range(0,len(list)): lst.append(to_str(list[i])) if "sort" in dct: lst.sort() return "|".join(lst) def to_string_key(element): if is_int(element): return str(element) if is_string(element): return element return element.k() def py3_safe_string(s): #Because App Engine is run by a bunch of idiots now. Random things return bytes. Even something like .urlsafe() ... [06/02/24] if 1/2==0: return s try: return s.decode("utf-8") except: return s def str_or_unicode(s): try: return str(s) except: try: return unicode(s) except: return s.decode("utf-8") def model_name(item): if type(item)==type({}): if item.get("a_t"): return "action" return item.get("base_type",item.get("type","")) return item._class_name().lower() def is_int(i): if 1/2 == 0: return type(i) in [types.IntType,types.LongType] else: return isinstance(i,int) def is_string(s): if 1/2 == 0: return isinstance(s, basestring) else: return isinstance(s, str) def is_array(a): if hasattr(a, "__len__"): return True @jrf def get_cx(c): cx=gf(c,"cx",{}) return json.dumps(cx) @jrf def sshorten(name): #Character Selection Name Shortening [20/06/18] if len(name)>9: return name[:9]+".." return name @jrf def get_online_character(domain,key): keys={1:None,2:None,3:None,"merchant":None} order=1 for character in domain.characters: if not character["online"]: continue if character["type"]=="merchant": keys["merchant"]=character else: keys[order]=character order+=1 return keys[key] @jrf def is_user_newb(user): if not user: return True for c in gf(user,"characters",[]): if c.get("level",0)>47: return False return True @jrf def sales_percent(domain): return "%.2f"%(domain.sales*100/10000.0) @jrf def to_slots(data): slots={} for id in data: if id.startswith("trade") or not data[id]: continue current={"name":data[id]["name"]} if "level" in data[id]: current["level"]=data[id]["level"] if "stat_type" in data[id]: current["stat_type"]=data[id]["stat_type"] if "p" in data[id]: current["p"]=data[id]["p"] slots[id]=current return json.dumps(slots) def calculate_tutorial_step(user_data): marked={} for key in user_data.info.completed_tasks: marked[key]=True for i in xrange(len(docs["tutorial"])): done=True for key in docs["tutorial"][i]["tasks"]: if key not in marked: done=False if not done and user_data.info.tutorial_step>i: user_data.info.tutorial_step=i break @jrf def to_tutorial(user_data): return json.dumps(data_to_tutorial(user_data)) def data_to_tutorial(user_data): try: if user_data: if user_data.info.tutorial_step>=len(docs["tutorial"]): return {"step":user_data.info.tutorial_step,"completed":[],"finished":True,"task":False,"progress":100} arr=[]; task=False; percent=100 for key in docs["tutorial"][user_data.info.tutorial_step]["tasks"]: if key in user_data.info.completed_tasks: arr.append(key) elif not task: task=key if task: percent=round(100*len(arr)/len(docs["tutorial"][user_data.info.tutorial_step]["tasks"])) return {"step":user_data.info.tutorial_step,"task":task,"completed":arr,"progress":percent} except: log_trace() return {"step":0,"completed":[]} @jrg def tutorial_data(key): for info in docs["tutorial"]: if info["key"]==key: return info @jrg def task_name(key): return docs["tasks"].get(key,key.title()) @jrf def to_json(e): return json.dumps(e) @jrf def to_repr(e): return "%s"%repr(e) def to_str(s): try: return unicode(s) except: 0 and logging.info("unicode fail %s"%repr(s)); pass try: return s.decode("utf-8") except: 0 and logging.info("decode utf-8 fail %s"%repr(s)); pass try: return str(s) except: 0 and logging.info("str fail %s"%repr(s)); pass return s def split_iid(s): return s.split("|",1) def get_by_iid(iid,_async=False,no_cache=False): mname,id=split_iid(iid) try: k=ndb.Key(to_model(mname),to_id(id)) if _async: return k.get_async() else: if no_cache: return k.get(use_cache=False) return k.get() except: log_trace() return None def get_by_iid_async(iid): return get_by_iid(iid,_async=True) def purify_email(email,check=True): email=email.replace(" ","").replace("\t","").replace("\n","").replace("\r","") email=email.lower() if check and not mail.is_email_valid(email): raise Exception name,domain=email.split("@") if check and len(domain.split("."))<2: raise Exception if check and len(domain.split(".")[1])<2: raise Exception if domain in ["gmail.com","googlemail.com"]: domain="gmail.com"; name=name.replace(".","") email="%s@%s"%(name,domain) logging.info("purify_email %s"%email) return email def gf(element,name,default=None): # as in getattr info fast :) if not hasattr(element,"info") or type(element.info)!=type(GG()): return getattr(element,name,default) return getattr(element.info,name,default) def gt(element,name,default=None): return getattr(element,name,default) def gdmul(request,*lst): gg=[] for l in lst: gg.append(request.values.get(l)) if len(gg)==1: return gg[0] return gg def gdmuld(self,*lst): gg=[] for l in lst: gg.append(self.get(l)) if len(gg)==1: return gg[0] return gg def jfunc(self,func,args=[]): if not self: return if not getattr(self,"_cjsons",0): self._cjsons=[] self._cjsons.append({"type":"func","func":func,"args":args}) def jeval(self,func): if not self: return if not getattr(self,"_cjsons",0): self._cjsons=[] self._cjsons.append({"type":"eval","code":func}) def jjson(self,jsn): if not self: return if not getattr(self,"_cjsons",0): self._cjsons=[] self._cjsons.append(jsn) def jjsons(self,jsns): if not self: return if not getattr(self,"_cjsons",0): self._cjsons=[] self._cjsons.extend(jsns) def jsuccess(self,message,duration=0): if not self: return if not getattr(self,"_cjsons",0): self._cjsons=[] self._cjsons.append({"type":"success","message":message,"duration":duration}) def jhtml(request,jsn=[]): if not request: return if getattr(request,"_cjsons",0): request._cjsons.extend(jsn) #logging.info("CJSONS %s"%request._cjsons) request.response.set_data(json.dumps(request._cjsons)) else: request.response.set_data(json.dumps(jsn)) return request.response def jhtmle(self,err): if not self: return jhtml(self,[{"type":"ui_error","message":err}]) def jhtmlchat(self,s,c=""): if not self: return jhtml(self,[{"type":"chat_message","message":s,"color":c}]) def jhtmlm(self,s): if not self: return jhtml(self,[{"type":"message","message":s}]) def jhtmlc(self,s,c): if not self: return jhtml(self,[{"type":"message","message":s,"color":c}]) def jhtmls(self,s): if not self: return jhtml(self,[{"type":"success","message":s}]) @jrf def dsince(t,ref=None): if not ref: ref=datetime.now() if type(t)==date: t=datetime(t.year,t.month,t.day,0,0) return (ref-t).total_seconds()/(24*3600.0) @jrf def hsince(t,ref=None): if not ref: ref=datetime.now() if type(t)==date: t=datetime(t.year,t.month,t.day,0,0) return (ref-t).total_seconds()/3600.0 @jrf def msince(t,ref=None): if not ref: ref=datetime.now() if type(t)==date: t=datetime(t.year,t.month,t.day,0,0) return (ref-t).total_seconds()/60.0 @jrf def ssince(t,ref=None): if not ref: ref=datetime.now() if type(t)==date: t=datetime(t.year,t.month,t.day,0,0) return (ref-t).total_seconds() def seconds_since(t): return ssince(t) @jrf def mssince(t,ref=None): if not ref: ref=datetime.now() if type(t)==date: t=datetime(t.year,t.month,t.day,0,0) return (ref-t).total_seconds()*1000 def log_trace_i(place="",logger=None): if not logger: logger=logging if place: place="[%s] "%place (exc_type, exc_value, exc_traceback) = sys.exc_info() logger.info("\n\n<<<<<<<<<< log_trace_i %s %s>>>>>>>>>>"%(exc_type,place),exc_info=sys.exc_info()) logger.info("\n") def log_trace(place="",logger=None): if not logger: logger=logging if place: place="[%s] "%place (exc_type, exc_value, exc_traceback) = sys.exc_info() logger.error("\n\n<<<<<<<<<< log_trace %s %s>>>>>>>>>>"%(exc_type,place),exc_info=sys.exc_info()) logger.error("\n") def get_domain(request=None): if not is_sdk: return live_domain else: if request: return (urlparse(request.url)).hostname else: return sdk_domain def get_cookie(request,name): return request.cookies.get(name) def set_cookie(request,name,value): hostname=get_domain(request) request.response.set_cookie(name,to_str(value),max_age=86400*365*5, path='/',domain='.%s'%(hostname),secure=secure_cookies) def delete_cookie(request,name): hostname=get_domain(request) request.response.delete_cookie(name,path='/',domain='.%s'%(hostname)) class StrLogHandler(logging.Handler): def __init__(self, output): logging.Handler.__init__(self) self.output=output def emit(self, record): if hasattr(record,"msg"): self.output["output"]=(self.output.get("output") or "")+"\n"+"%s"%(record.msg,) if record.exc_info: (exc_type, exc_value, exc_traceback) = record.exc_info self.output["output"]=(self.output.get("output") or "")+"\n"+"%s"%exc_type self.output["output"]=(self.output.get("output") or "")+"\n"+"%s"%exc_value self.output["output"]=(self.output.get("output") or "")+"\n"+"%s"%exc_traceback def custom_logging(): logs={} log_handler=StrLogHandler(logs) custom=logging.getLogger('code_logs') custom.setLevel(logging.INFO) custom.addHandler(log_handler) custom.output=lambda: logs.get("output") or "" return custom def to_filename(name): f="" for c in ("%s"%name): if c in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz_-.+ ": f=f+c return f def simplify_name(name): return name.lower() def sint(num): try: return int(num) except: return 9999999998 @jrf def to_pretty_num(num): if not num: return 0 pretty=""; prefix="" if num<0: prefix="-"; num=-num num=int(math.floor(num)) while num: current=num%1000 if not current: current="000" elif current<10 and current!=num: current="00%s"%current elif current<100 and current!=num: current="0%s"%current if not pretty: pretty=current else: pretty="%s,%s"%(current,pretty) num=int(num/1000.0) return "%s%s"%(prefix,pretty) @jrg def randomStr(length,digits_only=False,lowercase_only=False): chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; s="" if digits_only: chars="0123456789" if lowercase_only: chars="abcdefghijklmnopqrstuvwxyz" for i in range(0,length+1): s+=chars[random.randrange(0,len(chars))] return s def add_event(element,type,tags,info=None,backup=False,_async=False,self=None,rowner=None,selfic=None): logging.info("add_event %s %s %s"%(element and element.k('i'),type,tags)) if backup and element: backup=backup_item(element,_async=True) else: backup=None if not info: info=GG() if type not in tags: tags.append(type) event=Event(type=type,tag=tags,info=info,expire_at=datetime.now()+timedelta(days=30*5)) if rowner: event.rowner=rowner #referrer event owner if self: event.info.ip=get_ip(self) event.info.country=get_country(self) if selfic: event.info.ip,event.info.country=selfic if element: event.item_id=element.k('i') if hasattr(element,"region"): event.info.e_name="%s %s"%(element.region,element.name) elif hasattr(element,"name"): event.info.e_name=element.name if _async: return event.put_async() else: if backup: backup.wait() event.put() return event def backup_item(element,rkey=None,_async=False): logging.info("backup_item %s"%element.k('i')) #if not has_key(element): logging.error("Backup: Element doesn't have a key"); return if rkey: backup=Backup(key=ndb.Key(Backup,rkey)) else: backup=Backup(expire_at=datetime.now()+timedelta(days=30*5)) backup.backup_item_id=element.k('i') # element=copy.deepcopy(element) might be needed for k in element._properties.keys(): i=getattr(element,k) if k.startswith("_") or callable(i) or k=="key" or k in []: continue if type(i) == rdatetime.date: i=datetime.combine(i, rdatetime.time(0,0)) #logging.info("%s -> %s"%(k,type(i))) setattr(backup,k,i) backup.backup_info=cGG(original_properties=element._properties) backup.backup_created=datetime.now() if _async: return backup.put_async() else: backup.put() return backup def restore_backup(backup): if not hasattr(backup,"key"): backup=get_by_iid("backup|%s"%backup) if not backup: return logging.error("Backup Not Found!") item_id=backup.backup_item_id element=to_model(item_id.split("|")[0])(key=ndb.Key(to_model(item_id.split("|")[0]),item_id.split("|")[1])) for k in backup._properties.keys(): i=getattr(backup,k) if k.startswith("_") or k.startswith("backup_") or callable(i) or k=="key" or k in []: continue if type(i) == rdatetime.date: i=datetime.combine(i, rdatetime.time(0,0)) #logging.info("%s -> %s"%(k,type(i))) setattr(element,k,i) element.put() _base_js_escapes = ( ('\\', r'\u005C'), ('\'', r'\u0027'), ('"', r'\u0022'), ('>', r'\u003E'), ('<', r'\u003C'), ('&', r'\u0026'), ('=', r'\u003D'), ('-', r'\u002D'), (';', r'\u003B'), (u'\u2028', r'\u2028'), (u'\u2029', r'\u2029') ) # Escape every ASCII character with a value less than 32. _js_escapes = (_base_js_escapes + tuple([('%c' % z, '\\u%04X' % z) for z in range(32)])) @jrf def escapejs(value): """Hex encodes characters for use in JavaScript strings.""" base=str if 1/2 == 0: base=basestring if not isinstance(value, base): value = str(value) for bad, good in _js_escapes: value = value.replace(bad, good) return value @jrf def to_date(created): utc2=created+timedelta(hours=3) return "%.2d/%.2d/%.4d"%(utc2.day,utc2.month,utc2.year) @jrf def to_hour(created): utc2=created+timedelta(hours=3) return "%.2d:%.2d:%.2d"%(utc2.hour,utc2.minute,utc2.second) def he(s): return s.replace("<","<").replace(">",">").replace("&","&") def recursive_datetime_conversion(d): if not type(d)==type({}): return d for key,e in d.items(): if type(e)==type(datetime.now()): d[key]="%s"%e elif type(e)==type({}): recursive_datetime_conversion(e) return d def olen(el): #TODO: consider sys.getsizeof [27/10/13] return len(cPickle.dumps(el,-1)) def size_of(el): size=len(cPickle.dumps(el,-1)) if size>1000000: return "%.2fMB"%(size/1000000.0) if size>1000: return "%.2fKB"%(size/1000.0) return "%dB"%size def ssize_of(el): try: return size_of(el) except: return -1 def safelen(e): try: return len(e) except: return 0 def glenhandle(e): ll=safelen(e) if ll: return "[%s]"%ll; else: return "" def ginspect(o,id="root",force_inspection=0): if force_inspection==3: force_inspection=0 if id=="root": style="" else: style="display: none; " str=u"
"%(style,id); #for e in range(0,indent*5): tabs=tabs+" " if type(o)==type([]): str+="
    " for e in o: str+="
  • "+size_of(e)+" "+ginspect(e)+"
  • " str+="
" elif type(o)==type({}): str+="
    " keys=sorted(o) for k in keys: e=o[k] cid=randomStr(20) ll=glenhandle(e) str+="
  • KEY_%s (%s) %s: "%(cid,he(to_str(k)),ssize_of(e),ll)+ginspect(e,cid)+"
  • " str+="
" elif type(o) in [type(''),type(u'')]: try: str+=he(o) except: str+="Exception for: "+he(repr(o)); elif type(o) in [type(datetime.now())]: str+="Datetime %s || %s seconds ago || %s minutes ago"%(o,ssince(o),ssince(o)/60.0) else: try: strf="" if issubclass(o.__class__,ndb.Expando) or issubclass(o.__class__,ndb.Model): intentional_bug elif hasattr(o,"__str__"): strf+=o.__str__() elif hasattr(o,"__format__"): strf+=o.__format__() elif hasattr(o,"__repr__"): strf+=o.__repr__() else: goto_except if type(o)==type(type): strf+=o.__doc__ if force_inspection: str+="
"+strf+"
"; goto_except else: str+=strf except: str+="
    " elements=dir(o); elements.sort(); additional=[]; others=[] try: for v in getattr(o,"_values",{}).keys(): if v not in elements: additional.append(v) additional.sort() elements.extend(additional) except: log_trace() for e in elements: try: cid=randomStr(20) if not callable(getattr(o,e)) and e not in ["__doc__","__module__"] and not e.startswith("_"): ll=glenhandle(getattr(o,e)) #logging.info(e) rep="EL" if e in additional: rep="DE" str+="
  • %s_%s (%s) %s: "%\ (cid,rep,he(to_str(e)),ssize_of(getattr(o,e)),ll)+ginspect(getattr(o,e),cid,force_inspection=force_inspection and (force_inspection+1))+"
  • " elif force_inspection and e not in ["__doc__","__module__"] and not e.startswith("_"): others.append(e) except: log_trace_i() for e in others: try: cid=randomStr(20) str+="
  • %s_%s (%s): "%\ (cid,"F",he(to_str(e)),0)+""%(cid,getattr(o,e).__doc__)+"
  • " except: log_trace_i() str+="
" return str+"
" def get_image_size_advanced(blob_key): #TODO: Improve the image routines to eliminate the need to manually reverse the dimensions [26/06/14] size=cGG(metadata={},location=None,exception=False) img=images.Image(blob_key=blob_key) img.im_feeling_lucky() img.execute_transforms(output_encoding=images.JPEG,parse_source_metadata=True) logging.info(img.get_original_metadata()) size.width=img.width size.height=img.height try: size.metadata=img.get_original_metadata() if size.metadata.get("orientation",size.metadata.get("Orientation",None)) in [5,6,7,8,"5","6","7","8"]: t=size.width; size.width=size.height; size.height=t; size.reversal=True except: log_trace() return size def get_image_size_simple(blob_key): size=cGG(metadata={},location=None,exception=False) data = blobstore.fetch_data(blob_key, 0, 50000) img=images.Image(image_data=data) size.width=img.width; size.height=img.height return size def filetype_to_image_encoding(filetype): if filetype in ["image/png","image/gif"]: return images.PNG return images.JPEG def get_image_size(blob_key,encoding=images.JPEG,exception=True): try: if encoding!=images.JPEG: # or is_appengine: try: return get_image_size_simple(blob_key) except: log_trace_i() return get_image_size_advanced(blob_key) else: try: return get_image_size_advanced(blob_key) except: log_trace_i() return get_image_size_simple(blob_key) except: log_trace() if exception: raise Exception return cGG(width=images.IMG_SERVING_SIZES_LIMIT,height=images.IMG_SERVING_SIZES_LIMIT,exception=True,location=None,metadata={}) def handle_image_url(url): url=url.replace("localhost","thegame.com").replace("127.0.0.1","thegame.com").replace("0.0.0.0","thegame.com").replace(" ","").replace(":8080","").replace(":80","") gg=re.findall("=s.*",url) if gg: url=url.replace(gg[0],"") return url def get_serving_url(blob_key,**dct): for i in xrange(3): try: url=images.get_serving_url(blob_key,**dct) logging.info(url) return handle_image_url(url) except: (i==2 and log_trace()) or log_trace_i(); time.sleep(2) raise "improved_get_serving_url failed" def encode_unicodes(args): if args and type(args)==type({}): for key,value in args.items(): if type(value)==type(u""): args[key]=value.encode("utf-8") def fetch_url(url_u,**dct): if url_u.startswith("/"): if is_sdk: url_u="http://thegame.com"+url_u else: url_u="https://adventure.land"+url_u if dct or dct.pop("use_post",""): encode_unicodes(dct) data = urlencode(dct) return urlfetch.fetch(url=url_u,payload=data,method=urlfetch.POST,validate_certificate=is_production).content else: return urlfetch.fetch(url=url_u,method=urlfetch.GET,validate_certificate=is_production).content def fetch_url_async(url_u,**dct): rpc=urlfetch.create_rpc(deadline=40) if dct.pop("use_get",""): urlfetch.make_fetch_call(rpc,url_u+"?"+urlencode(dct),method=urlfetch.GET,validate_certificate=False) else: data = urlencode(dct) urlfetch.make_fetch_call(rpc,url_u,payload=data,method=urlfetch.POST,headers={'Content-Type': 'application/x-www-form-urlencoded'},validate_certificate=False) return rpc def send_email(domain,email="kaansoral@gmail.com",title="Default Title",html="Default HTML",text="An email from the game",sender="hello@adventure.land",reply_to=""): logging.info("send_email %s - %s - %s"%(email,sender,title)) if not reply_to: reply_to="hello@adventure.land" if is_sdk: message=amazon_ses.EmailMessage() message.subject=title message.bodyHtml=html message.bodyText=text ses=amazon_ses.AmazonSES(secrets.amazon_ses_user,secrets.amazon_ses_key) #logging.info(ses.listVerifiedEmailAddresses().members) try: ses.sendEmail("pr@createandspread.com","kaansoral@gmail.com",message) except amazon_ses.AmazonError as e: logging.info(e.errorType); logging.info(e.code); logging.info(e.message); log_trace() elif always_amazon_ses: message=amazon_ses.EmailMessage() message.subject=title message.bodyHtml=html message.bodyText=text ses=amazon_ses.AmazonSES(secrets.amazon_ses_user,secrets.amazon_ses_key) #logging.info(ses.listVerifiedEmailAddresses().members) try: ses.sendEmail("hello@adventure.land",email,message) except amazon_ses.AmazonError as e: logging.info(e.errorType); logging.info(e.code); logging.info(e.message); log_trace() else: try: mail.send_mail(sender,email,title,text,html=html,reply_to=reply_to) except: log_trace() import hmac,hashlib from struct import Struct from operator import xor from itertools import starmap try: from itertools import izip except: izip=zip _pack_int = Struct('>I').pack #https://code.google.com/p/googleappengine/issues/detail?id=5303 and https://github.com/mitsuhiko/python-pbkdf2/blob/master/pbkdf2.py def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None): """Like :func:`pbkdf2_bin` but returns a hex encoded string.""" return pbkdf2_bin(data, salt, iterations, keylen, hashfunc).encode('hex') def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None): """Returns a binary digest for the PBKDF2 hash algorithm of `data` with the given `salt`. It iterates `iterations` time and produces a key of `keylen` bytes. By default SHA-1 is used as hash function, a different hashlib `hashfunc` can be provided. """ hashfunc = hashfunc or hashlib.sha1 mac = hmac.new(data, None, hashfunc) def _pseudorandom(x, mac=mac): h = mac.copy() h.update(x) return map(ord, h.digest()) buf = [] for block in xrange(1, -(-keylen // mac.digest_size) + 1): rv = u = _pseudorandom(salt + _pack_int(block)) for i in xrange(iterations - 1): u = _pseudorandom(''.join(map(chr, u))) rv = starmap(xor, izip(rv, u)) buf.extend(rv) return ''.join(map(chr, buf))[:keylen] if 1/2!=0: # big thanks to https://github.com/mitsuhiko/python-pbkdf2/issues/8 [07/02/24] try: from itertools import izip as zip except ImportError: pass # py3 try: range = xrange except NameError: pass # py3 _pack_int = Struct('>I').pack def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None): salt=bytes(salt,'utf-8') """Like :func:`pbkdf2_bin` but returns a hex encoded string.""" return str(''.join('%02x'%(v if type(v) is int else ord(v)) for v in pbkdf2_bin(data, salt, iterations, keylen, hashfunc))) def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None): """Returns a binary digest for the PBKDF2 hash algorithm of `data` with the given `salt`. It iterates `iterations` time and produces a key of `keylen` bytes. By default SHA-1 is used as hash function, a different hashlib `hashfunc` can be provided. """ hashfunc = hashfunc or hashlib.sha1 mac = hmac.new(data, None, hashfunc) buf = [] for block in range(1, -(-keylen // mac.digest_size) + 1): h = mac.copy() h.update(salt + _pack_int(block)) u = h.digest() rv = list(bytearray(u)) # needs further testing on py2 and could possibly be more performant for i in range(iterations - 1): h = mac.copy() h.update(bytes(u)) u = h.digest() rv = starmap(xor, zip(rv, list(bytearray(u)))) buf.extend(rv) return ''.join(map(chr, buf))[:keylen] def hash_password(password,salt): password=password.replace(" ","").encode('utf8') return pbkdf2_hex(password,salt,iterations=160) def cGG(**dct): gg=GG() for k,e in dct.items(): setattr(gg,k,e) return gg from models import *