def outgoing_org_message_event(self, event_type, event_data): if isinstance(event_data.message, ChatBlob): pages = self.text.paginate( ChatBlob(event_data.message.title, event_data.message.msg), self.setting_service.get( "org_channel_max_page_length").get_value()) if len(pages) < 4: for page in pages: message = "{org} {message}".format( org=self.ORG_CHANNEL_PREFIX, message=page) self.message_hub_service.send_message( self.MESSAGE_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), page, message) else: message = "{org} {message}".format( org=self.ORG_CHANNEL_PREFIX, message=event_data.message.title) self.message_hub_service.send_message( self.MESSAGE_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), event_data.message.title, message) else: message = "{org} {message}".format(org=self.ORG_CHANNEL_PREFIX, message=event_data.message) self.message_hub_service.send_message( self.MESSAGE_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), event_data.message, message)
def public_channel_message(self, conn: Conn, packet: server_packets.PublicChannelMessage): if not conn.is_main: return if conn.org_channel_id == packet.channel_id: char_name = self.character_service.get_char_name(packet.char_id) if packet.extended_message: message = packet.extended_message.get_message() else: message = packet.message self.logger.log_chat(conn, "Org Channel", char_name, message) if conn.char_id == packet.char_id: return if not self.handle_public_channel_command(conn, packet): self.event_service.fire_event(self.ORG_CHANNEL_MESSAGE_EVENT, DictObject({"char_id": packet.char_id, "name": char_name, "message": message, "extended_message": packet.extended_message, "conn": conn})) elif packet.channel_id == self.ORG_MSG_CHANNEL_ID: char_name = self.character_service.get_char_name(packet.char_id) if packet.extended_message: message = packet.extended_message.get_message() else: message = packet.message self.logger.log_chat(conn, "Org Msg", char_name, message) self.event_service.fire_event(self.ORG_MSG_EVENT, DictObject({"char_id": packet.char_id, "name": char_name, "message": packet.message, "extended_message": packet.extended_message, "conn": conn}))
def loot_add_item_cmd(self, request, _, item, item_count: int): if not self.leader_controller.can_use_command(request.sender.char_id, request.conn): return LeaderController.NOT_LEADER_MSG items_added = [] if item_count is None: item_count = 1 items = re.findall( r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)", item) if items: for _1, _2, low_id, high_id, ql, name, _3 in items: obj = DictObject({ "low_id": int(low_id), "high_id": int(high_id), "ql": int(ql), "name": name, "icon": 0 }) row = self.items_controller.get_by_item_id(high_id, ql) if row: obj.icon = row.icon loot_item = self.add_item_to_loot(obj, None, item_count, request.conn) items_added.append(loot_item.get_item_str()) else: loot_item = self.add_item_to_loot(item, None, item_count, request.conn) items_added.append(loot_item.get_item_str()) self.send_loot_message( "%s added to loot list." % ", ".join(items_added), request.conn)
def process_update(self, char_id, old_mode, new_mode): if not old_mode: if new_mode == self.MODE_ADD_AUTO or new_mode == self.MODE_ADD_MANUAL: self.add_org_member(char_id, new_mode) elif old_mode == self.MODE_ADD_AUTO: if new_mode == self.MODE_REM_MANUAL: self.update_org_member(char_id, new_mode) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, DictObject({"char_id": char_id})) elif new_mode == self.MODE_REM_AUTO: self.remove_org_member(char_id) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, DictObject({"char_id": char_id})) elif old_mode == self.MODE_ADD_MANUAL: if new_mode == self.MODE_ADD_AUTO: self.update_org_member(char_id, new_mode) elif new_mode == self.MODE_REM_MANUAL: self.remove_org_member(char_id) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, DictObject({"char_id": char_id})) elif old_mode == self.MODE_REM_MANUAL: if new_mode == self.MODE_ADD_MANUAL: self.update_org_member(char_id, new_mode) elif new_mode == self.MODE_REM_AUTO: self.remove_org_member(char_id)
def test_update(self): d = DictObject({"test1": 2, "test2": 2}) d["test1"] = 3 d.test2 = 4 self.assertEqual(3, d["test1"]) self.assertEqual(3, d.test1) self.assertEqual(4, d["test2"]) self.assertEqual(4, d.test2)
def test_empty_update(self): d = DictObject() d["test1"] = 1 d.test2 = 2 self.assertEqual(1, d["test1"]) self.assertEqual(1, d.test1) self.assertEqual(2, d["test2"]) self.assertEqual(2, d.test2)
def test_len(self): d = DictObject() self.assertEqual(0, len(d)) d["test1"] = 1 self.assertEqual(1, len(d)) d.test2 = 2 self.assertEqual(2, len(d)) d["test2"] = 3 self.assertEqual(2, len(d))
def format_result(self): org_ranks = {} for rank_name in self.governing_types[ self.orglist.org_info.governing_type]: org_ranks[rank_name] = DictObject({ "online_members": [], "offline_members": [] }) org_ranks["Inactive"] = DictObject({ "online_members": [], "offline_members": [] }) for char_id, org_member in self.orglist.finished_org_members.items(): if org_member.online == 2: org_ranks["Inactive"].offline_members.append(org_member) elif org_member.online == 1: org_ranks[org_member.org_rank_name].online_members.append( org_member) else: org_ranks[org_member.org_rank_name].offline_members.append( org_member) blob = "" num_online = 0 num_total = 0 for rank_name, rank_info in org_ranks.items(): rank_num_online = len(rank_info.online_members) rank_num_total = len(rank_info.offline_members) + rank_num_online blob += "<header2>%s (%d / %d)</header2>\n" % ( rank_name, rank_num_online, rank_num_total) num_online += rank_num_online num_total += rank_num_total for org_member in sorted(rank_info.online_members, key=lambda x: x.name): level = org_member.level if org_member.ai_level == 0 else "%d/<green>%d</green>" % ( org_member.level, org_member.ai_level) blob += "%s (Level <highlight>%s</highlight>, %s %s <highlight>%s</highlight>)\n" % ( org_member.name, level, org_member.gender, org_member.breed, org_member.profession) if rank_num_total < 200: blob += "<font color='#555555'>" + ", ".join( map( lambda x: x.name, sorted(rank_info.offline_members, key=lambda x: x.name))) + "</font>" blob += "\n" else: blob += "<font color='#555555'>Offline members omitted for brevity</font>\n" blob += "\n" return ChatBlob( "Orglist for '%s' (%d / %d)" % (self.orglist.org_info.name, num_online, num_total), blob)
def outgoing_private_channel_message_event(self, event_type, event_data): org = ( "[" + self.relay_controller.get_org_channel_prefix() + "]") if self.setting_service.get_value("prefix_org") == "1" else "" priv = "[Private]" if isinstance(event_data.message, ChatBlob): pages = self.text.paginate( ChatBlob(event_data.message.title, event_data.message.msg), self.setting_service.get( "org_channel_max_page_length").get_value()) if len(pages) < 4: for page in pages: message = self.getresp("module/private_channel", "relay_from_priv", { "org": org, "priv": priv, "message": page, "char": "" }) #message = "[%s][Private] %s" % (self.relay_controller.get_org_channel_prefix(), page) self.relay_hub_service.send_message( self.RELAY_HUB_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), message) else: message = self.getresp( "module/private_channel", "relay_from_priv", { "org": org, "priv": priv, "message": event_data.message.title, "char": "" }) self.relay_hub_service.send_message( self.RELAY_HUB_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), message) else: message = self.getresp( "module/private_channel", "relay_from_priv", { "org": org, "priv": priv, "message": event_data.message, "char": "" }) #message = "[%s][Private] %s" % (self.relay_controller.get_org_channel_prefix(), event_data.message) self.relay_hub_service.send_message( self.RELAY_HUB_SOURCE, DictObject({ "name": self.bot.char_name, "char_id": self.bot.char_id }), message)
def get_fling_shot_info(self, weapon_attack, fling_shot_skill): result = DictObject() result.hard_cap = weapon_attack + 5 result.skill_cap = ((weapon_attack * 16) - result.hard_cap) * 100 recharge = (weapon_attack * 16) - (fling_shot_skill / 100) if recharge < result.hard_cap: recharge = result.hard_cap result.recharge = recharge return result
def run(self): self.ws = create_connection(self.url) self.logger.info("Connected to Websocket Relay!") self.inbound_queue.append(DictObject({"type": "connected"})) result = self.ws.recv() while result: obj = DictObject(json.loads(result)) self.inbound_queue.append(obj) result = self.ws.recv() self.ws.close()
def get_victory_event(self, packet: server_packets.PublicChannelMessage): match = self.VICTORY_1.match(packet.message) if match: return None t = int(time.time()) match = self.VICTORY_2.match(packet.message) if match: return DictObject({ "type": "attack", "timestamp": t, "winner": { "faction": match.group(1).capitalize(), "org_name": match.group(2) }, "loser": { "faction": match.group(3).capitalize(), "org_name": match.group(4) }, "location": { "playfield": { "long_name": match.group(5) } } }) if packet.extended_message and [ packet.extended_message.category_id, packet.extended_message.instance_id ] == self.VICTORY_3: params = packet.extended_message.params return DictObject({ "type": "terminated", "timestamp": t, "winner": { "faction": params[0].capitalize(), "org_name": params[1] }, "loser": { "faction": params[0].capitalize(), "org_name": params[1] }, "location": { "playfield": { "long_name": params[2] } } }) # Unknown victory self.logger.warning("Unknown tower victory: " + str(packet)) return None
def get_attack_event(self, packet: server_packets.PublicChannelMessage): t = int(time.time()) if packet.extended_message and [ packet.extended_message.category_id, packet.extended_message.instance_id ] == self.ATTACK_1: params = packet.extended_message.params return DictObject({ "timestamp": t, "attacker": { "name": params[2], "faction": params[0].capitalize(), "org_name": params[1] }, "defender": { "faction": params[3].capitalize(), "org_name": params[4] }, "location": { "playfield": { "long_name": params[5] }, "x_coord": params[6], "y_coord": params[7] } }) else: match = self.ATTACK_2.match(packet.message) if match: return DictObject({ "timestamp": t, "attacker": { "name": match.group(1), "faction": "", "org_name": "" }, "defender": { "faction": match.group(2).capitalize(), "org_name": match.group(3) }, "location": { "playfield": { "long_name": match.group(4) }, "x_coord": match.group(5), "y_coord": match.group(6) } }) # Unknown attack self.logger.warning("Unknown tower attack: " + str(packet)) return None
def __init__(self): super().__init__() self.logger = Logger(__name__) self.ready = False self.packet_handlers = {} self.superadmin = None self.status: BotStatus = BotStatus.SHUTDOWN self.dimension = None self.last_timer_event = 0 self.start_time = int(time.time()) self.version = "0.5-beta" self.incoming_queue = FifoQueue() self.mass_message_queue = None self.conns = DictObject()
def get_burst_info(self, weapon_attack, weapon_recharge, burst_recharge, burst_skill): result = DictObject() result.hard_cap = round(weapon_attack + 8) result.skill_cap = math.floor( ((weapon_recharge * 20) + (burst_recharge / 100) - 8) * 25) recharge = math.floor((weapon_recharge * 20) + (burst_recharge / 100) - (burst_skill / 25) + weapon_attack) if recharge < result.hard_cap: recharge = result.hard_cap result.recharge = recharge return result
def handle_queue_event(self, event_type, event_data): while self.queue: obj = DictObject(json.loads(self.queue.pop(0))) if obj.type == "message": payload = obj.payload if self.encrypter: payload = self.encrypter.decrypt(payload.encode('utf-8')) payload = DictObject(json.loads(payload)) # message = ("[Relay] <channel_color>[%s]<end> <sender_color>%s<end>: <message_color>%s<end>" % (payload.channel, payload.sender.name, payload.message))\ # .replace("<channel_color>", self.websocket_channel_color().get_font_color())\ # .replace("<message_color>", self.websocket_message_color().get_font_color())\ # .replace("<sender_color>", self.websocket_sender_color().get_font_color()) message = payload.message self.message_hub_service.send_message(self.MESSAGE_SOURCE, obj.get("sender", None), message)
def send_org_message(self, msg, add_color=True, fire_outgoing_event=True): org_channel_id = self.public_channel_service.org_channel_id if org_channel_id is None: self.logger.debug( "ignoring message to org channel since the org_channel_id is unknown" ) else: color = self.setting_service.get( "org_channel_color").get_font_color() if add_color else "" pages = self.get_text_pages( msg, self.setting_service.get( "org_channel_max_page_length").get_value()) for page in pages: packet = client_packets.PublicChannelMessage( org_channel_id, color + page, "") self.packet_queue.enqueue(packet) self.check_outgoing_message_queue() if fire_outgoing_event: self.event_service.fire_event( self.OUTGOING_ORG_MESSAGE_EVENT, DictObject({ "org_channel_id": org_channel_id, "message": msg }))
def process_update(self, char_id, old_mode, new_mode, conn): name = self.character_service.get_char_name(char_id) event_data = DictObject({ "char_id": char_id, "name": name, "conn": conn }) if not old_mode: if new_mode == self.MODE_ADD_AUTO or new_mode == self.MODE_ADD_MANUAL: self.add_org_member(char_id, new_mode, conn.org_id) elif old_mode == self.MODE_ADD_AUTO: if new_mode == self.MODE_REM_MANUAL: self.update_org_member(char_id, new_mode, conn.org_id) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, event_data) elif new_mode == self.MODE_REM_AUTO: self.remove_org_member(char_id) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, event_data) elif old_mode == self.MODE_ADD_MANUAL: if new_mode == self.MODE_ADD_AUTO: self.update_org_member(char_id, new_mode, conn.org_id) elif new_mode == self.MODE_REM_MANUAL: self.remove_org_member(char_id) self.event_service.fire_event(self.ORG_MEMBER_LOGOFF_EVENT, event_data) elif old_mode == self.MODE_REM_MANUAL: if new_mode == self.MODE_ADD_MANUAL: self.update_org_member(char_id, new_mode, conn.org_id) elif new_mode == self.MODE_REM_AUTO: self.remove_org_member(char_id)
def load_character_info(self, char_id): char_info = self.get_character_info(char_id) if not char_info: char_info = DictObject({ "name": "Unknown:" + str(char_id), "char_id": char_id, "first_name": "", "last_name": "", "level": 0, "breed": "", "dimension": self.bot.dimension, "gender": "", "faction": "", "profession": "", "profession_title": "", "ai_rank": "", "ai_level": 0, "pvp_rating": 0, "pvp_title": "", "head_id": 0, "org_id": 0, "org_name": "", "org_rank_name": "", "org_rank_id": 6, "source": "stub" }) self.save_character_info(char_info)
def outgoing_private_channel_message_event(self, event_type, event_data): sender = None if event_data.name: sender = DictObject({ "char_id": event_data.char_id, "name": event_data.name }) if isinstance(event_data.message, ChatBlob): pages = self.text.paginate( ChatBlob(event_data.message.title, event_data.message.msg), event_data.conn, self.setting_service.get( "org_channel_max_page_length").get_value()) if len(pages) < 4: for page in pages: self.message_hub_service.send_message( self.MESSAGE_SOURCE, sender, self.get_private_channel_prefix(), page) else: self.message_hub_service.send_message( self.MESSAGE_SOURCE, sender, self.get_private_channel_prefix(), event_data.message.title) else: self.message_hub_service.send_message( self.MESSAGE_SOURCE, sender, self.get_private_channel_prefix(), event_data.message)
def pre_start(self): database = DictObject({ "type": "sqlite", "file": "database.db", "path": "/path/to/master/tyrbot/data/" }) # database = DictObject({"type": "mysql", # "name": "my-database", # "username": "******", # "password": "******", # "host": "localhost" # "port": 3306}) self.db2 = DB() if database.type == "sqlite": full_path = database.path + database.file if os.path.isfile(full_path): self.db2.connect_sqlite(full_path) else: raise Exception(f"File '{full_path}' does not exist") elif database.type == "mysql": self.db2.connect_mysql(database.host, database.port, database.username, database.password, database.name) else: raise Exception("Unknown database type '%s'" % database.type) self.share_notes() self.share_news() self.share_quotes() self.share_timers() self.share_alts()
def orgmember_add_cmd(self, request, _, char): if not char.char_id: return self.getresp("global", "char_not_found", {"char": char.name}) org_member = self.get_org_member(char.char_id) if org_member and (org_member.mode == self.MODE_ADD_AUTO or org_member.mode == self.MODE_ADD_MANUAL): return self.getresp("module/org_members", "notify_add_fail", {"char": char.name}) self.process_update(char.char_id, org_member.mode if org_member else None, self.MODE_ADD_MANUAL, request.conn) # fire org_member logon event if self.buddy_service.is_online(char.char_id): org_member = self.get_org_member(char.char_id) self.event_service.fire_event( self.ORG_MEMBER_LOGON_EVENT, DictObject({ "char_id": org_member.char_id, "name": char.name, "conn": request.conn })) return self.getresp("module/org_members", "notify_add_success", {"char": char.name})
def register_message_destination(self, destination, callback, default_sources, invalid_sources=[]): """ Call during start Args: destination: str callback: (ctx) -> void default_sources: [str...] invalid_sources: [str...] """ if len(inspect.signature(callback).parameters) != 1: raise Exception("Incorrect number of arguments for handler '%s.%s()'" % (callback.__module__, callback.__name__)) if destination in self.hub: raise Exception("Message hub destination '%s' already subscribed" % destination) for source in default_sources: if source not in self.sources: self.logger.warning("Could not subscribe destination '%s' to source '%s' because source does not exist" % (destination, source)) # raise Exception("Could not subscribe destination '%s' to source '%s' because source does not exist" % (destination, source)) self.hub[destination] = (DictObject({"name": destination, "callback": callback, "sources": default_sources, "invalid_sources": invalid_sources})) self.reload_mapping(destination)
def whois_cmd(self, request, char, dimension, flag_params): dimension = dimension or self.bot.dimension force_update = flag_params.force_update if dimension == self.bot.dimension and char.char_id: online_status = self.buddy_service.is_online(char.char_id) if online_status is None: self.bot.register_packet_handler(BuddyAdded.id, self.handle_buddy_status) self.waiting_for_update[char.char_id] = DictObject({ "char_id": char.char_id, "name": char.name, "callback": partial(self.show_output, char, dimension, force_update, reply=request.reply, conn=request.conn) }) self.buddy_service.add_buddy(char.char_id, self.BUDDY_IS_ONLINE_TYPE) else: self.show_output(char, dimension, force_update, online_status, request.reply, request.conn) else: self.show_output(char, dimension, force_update, None, request.reply, request.conn)
def raffle_start_cmd(self, request, _, item, duration): duration = duration or 180 # 3 minutes if self.raffle: return "There is already a raffle in progress." t = int(time.time()) self.raffle = DictObject({ "owner": request.sender, "item": self.get_item_name(item), "started_at": t, "duration": duration, "finished_at": t + duration, "members": [], "reply": request.reply, "scheduled_job_id": self.job_scheduler.scheduled_job(self.alert_raffle_status, t + 60) }) chatblob = self.get_raffle_display(t) self.spam_raffle_channels(chatblob)
def send_private_message(self, char, msg, add_color=True, fire_outgoing_event=True): char_id = self.character_service.resolve_char_to_id(char) if char_id is None: self.logger.warning( "Could not send message to %s, could not find char id" % char) else: color = self.setting_service.get( "private_message_color").get_font_color() if add_color else "" pages = self.get_text_pages( msg, self.setting_service.get( "private_message_max_page_length").get_value()) for page in pages: self.logger.log_tell( "To", self.character_service.get_char_name(char_id), page) packet = client_packets.PrivateMessage(char_id, color + page, "\0") self.packet_queue.enqueue(packet) self.check_outgoing_message_queue() if fire_outgoing_event: self.event_service.fire_event( self.OUTGOING_PRIVATE_MESSAGE_EVENT, DictObject({ "char_id": char_id, "message": msg }))
def send_private_channel_message(self, msg, private_channel=None, add_color=True, fire_outgoing_event=True): if private_channel is None: private_channel = self.char_id private_channel_id = self.character_service.resolve_char_to_id( private_channel) if private_channel_id is None: self.logger.warning( "Could not send message to private channel %s, could not find private channel" % private_channel) else: color = self.setting_service.get( "private_channel_color").get_font_color() if add_color else "" pages = self.get_text_pages( msg, self.setting_service.get( "private_channel_max_page_length").get_value()) for page in pages: packet = client_packets.PrivateChannelMessage( private_channel_id, color + page, "\0") self.send_packet(packet) if fire_outgoing_event and private_channel_id == self.char_id: self.event_service.fire_event( self.OUTGOING_PRIVATE_CHANNEL_MESSAGE_EVENT, DictObject({ "private_channel_id": private_channel_id, "message": msg }))
def get_character_history(self, name, server_num): cache_key = "%s.%d.json" % (name, server_num) # check cache for fresh value cache_result = self.cache_service.retrieve(self.CACHE_GROUP, cache_key, self.CACHE_MAX_AGE) if cache_result: # TODO set cache age result = json.loads(cache_result) else: url = "http://pork.budabot.jkbff.com/pork/history.php?server=%d&name=%s" % (server_num, name) try: r = requests.get(url, timeout=5) result = r.json() except ReadTimeout: self.logger.warning("Timeout while requesting '%s'" % url) result = None except Exception as e: self.logger.error("Error requesting history for url '%s'" % url, e) result = None if result: # store result in cache self.cache_service.store(self.CACHE_GROUP, cache_key, json.dumps(result)) else: # check cache for any value, even expired # TODO set cache age cache_obj = self.cache_service.retrieve(self.CACHE_GROUP, cache_key) if cache_obj: result = json.loads(cache_obj) if result: return map(lambda x: DictObject(x), result) else: return None
def handle_org_message_event(self, event_type, event_data): if event_data.char_id == self.bot.char_id or self.ban_service.get_ban( event_data.char_id): return if event_data.extended_message: message = event_data.extended_message.get_message() else: message = event_data.message sender = None if event_data.char_id == 4294967295 or event_data.char_id == 0: message = "[%s] %s" % ( self.relay_controller.get_org_channel_prefix(), message) else: char_name = self.character_service.resolve_char_to_name( event_data.char_id) sender = DictObject({ "char_id": event_data.char_id, "name": char_name }) message = "[%s] %s: %s" % ( self.relay_controller.get_org_channel_prefix(), self.text.make_charlink(char_name), message) self.relay_hub_service.send_message(self.RELAY_HUB_SOURCE, sender, message)
def orgmember_remove_cmd(self, request, _, char): if not char.char_id: return self.getresp("global", "char_not_found", {"char": char.name}) org_member = self.get_org_member(char.char_id) if not org_member or org_member.mode == self.MODE_REM_MANUAL: return self.getresp("module/org_members", "notify_rem_fail", {"char": char.name}) self.process_update(char.char_id, org_member.mode if org_member else None, self.MODE_REM_MANUAL, request.conn) # fire org_member logoff event self.event_service.fire_event( self.ORG_MEMBER_LOGOFF_EVENT, DictObject({ "char_id": org_member.char_id, "name": char.name, "conn": request.conn })) return self.getresp("module/org_members", "notify_rem_success", {"char": char.name})