from core.chat_blob import ChatBlob from core.command_param_types import Any, Int, NamedParameters from core.decorators import instance, command # noinspection SqlCaseVsIf,SqlAggregates @instance() class NanoController: def inject(self, registry): self.db = registry.get_instance("db") self.util = registry.get_instance("util") self.text = registry.get_instance("text") self.command_alias_service = registry.get_instance("command_alias_service") def pre_start(self): self.db.load_sql_file(self.module_dir + "/" + "nanos.sql", pre_optimized=True) self.db.create_view("nanos") def start(self): self.command_alias_service.add_alias("nl", "nanolines") self.command_alias_service.add_alias("nanoline", "nanolines") @command(command="nano", params=[Any("search"), NamedParameters(["page"])], access_level="member", description="Search for a nano") def nano_cmd(self, _, search, named_params): page = int(named_params.page or "1") page_size = 30 offset = (page - 1) * page_size sql = "SELECT n.* " \ "FROM nanos n " \ "WHERE n.nano_name ? group by nano_id " \ "ORDER BY n.profession, n.strain, n.ql DESC, n.crystal_name" data = self.db.query(sql, [search], extended_like=True) count = len(data) paged_data = data[offset:offset + page_size] blob = "" if count == 0: return "No nanos found matching %s." % search elif count == 1: row = data[0] nano = self.make_nano(row) if nano: return f"{nano} {row.strain.replace('_', ' ')}" return f"No nanos found matching {search}." elif count > page_size: if page > 1 and len(paged_data) > 0: blob += " " + self.text.make_chatcmd(f"<< Page {page - 1:d}", self.get_chat_command(search, page - 1)) if offset + page_size < len(data): blob += " Page " + str(page) blob += " " + self.text.make_chatcmd(f"Page {page + 1:d} >>", self.get_chat_command(search, page + 1)) blob += "\n\n" current_nanoline = [] for row in paged_data: if current_nanoline != [row.strain_id, row.profession]: if row.strain: nano = self.text.make_tellcmd(row.strain, f"nanolines {row.profession} {row.strain}") blob += f"\n{row.profession} - {nano}\n" if nano else "" else: blob += "\nUnknown/General\n" current_nanoline = [row.strain_id, row.profession] nano = self.make_nano(row) blob += nano + "\n" if nano else "" blob += self.get_footer() return ChatBlob( f"Nano Search Results for '{search}' ({offset + 1:d} - " f"{min(offset + page_size, count):d} of {count:d})", blob) def format_single_nano(self, row): if str(row.crystal_name).startswith("Nano") \ or str(row.crystal_name).startswith("Shadow") \ or str(row.crystal_name).startswith("Alien") \ or str(row.location).startswith("Arete"): item = self.text.make_item(row.crystal_id, row.crystal_id, row.ql, str(row.crystal_name).replace('_', ' ')) return f"QL {row.ql: >3} {item} {row.location}" return "" @command(command="nanoloc", params=[], access_level="member", description="Show all nano locations") def nanoloc_list_cmd(self, _): data = self.db.query( "SELECT location, COUNT(location) AS cnt " "FROM (SELECT * FROM nanos group by nano_id order by crystal_name) a " "GROUP BY location " "ORDER BY location") blob = "" for row in data: blob += "%s (%d)\n" % (self.text.make_tellcmd(row.location, "nanoloc %s" % row.location), row.cnt) blob += self.get_footer() return ChatBlob("Nano Locations", blob) @command(command="nanoloc", params=[Any("location")], access_level="member", description="Show nanos by location") def nanoloc_show_cmd(self, _, location): sql = "SELECT * " \ "FROM nanos n " \ "WHERE n.location LIKE ? " \ "group by n.nano_id ORDER BY n.profession, n.crystal_name" data = self.db.query(sql, [location]) cnt = len(data) blob = "" prof = "" for row in data: if prof != row.profession: if row.profession: blob += f"\n{row.profession.replace('_', ' ')}\n" else: blob += "\nUnknown/General\n" prof = row.profession blob += "QL %d %s\n" % (row.ql, self.make_nano(row)) return ChatBlob("Nanos for Location '%s' (%d)" % (location, cnt), blob) @command(command="nanolines", params=[], access_level="member", description="Show nanos by nanoline") def nanolines_list_cmd(self, _): data = self.db.query("SELECT DISTINCT profession FROM nanos ORDER BY profession") blob = "" for row in data: blob += self.text.make_tellcmd(row.profession, f"nanolines {row.profession}") + "\n" blob += self.get_footer() return ChatBlob("Nanolines", blob) @command(command="nanolines", params=[Int("nanoline_id")], access_level="member", description="Show nanos by nanoline id") def nanolines_id_cmd(self, _, nanoline_id): nanoline = self.db.query_single("SELECT * FROM nanos WHERE strain_id = ? LIMIT 1", [nanoline_id]) if not nanoline or nanoline_id == 0: return f"Could not find nanoline with ID {nanoline_id:d}." data = self.db.query( "SELECT n.crystal_id, n.ql, n.strain, n.crystal_name, n.location " "FROM nanos n " "where n.strain_id=? " "group by n.nano_id " "ORDER BY n.ql DESC, n.nano_name", [nanoline_id]) blob = "" for row in data: item = self.make_nano(row) blob += item + "\n" if item else "" blob += self.get_footer() return ChatBlob(f"{str(nanoline.strain).replace('_', ' ')} Nanos", blob) @command(command="nanolines", params=[Any("profession"), Any("nanoline")], access_level="member", description="Show nanos by nanoline profession and line name") def nanolines_prof_strain(self, _, prof: str, strain: str): profession = self.util.get_profession(prof) if strain.startswith("Artist"): profession = "Martial Artist" strain = strain[7:] nanoline = self.db.query_single( "SELECT * FROM nanos n WHERE n.strain LIKE ? AND profession =? and type in ('Crystal', 'Misc') LIMIT 1", [strain, profession]) if not nanoline: return f"Could not find nanoline with name {strain}." data = self.db.query( "SELECT n.* FROM nanos n " "where n.strain LIKE ? " "and n.profession = ? " "and type in ('Crystal', 'Misc') " "group by nano_id " "ORDER BY n.strain, n.ql DESC, n.nano_name", ["%" + strain.replace(" ", "%") + "%", profession]) blob = "" strain = "" for row in data: if strain != row.strain: if row.strain: blob += f"\n{row.strain.replace('_', ' ')}\n" else: blob += "\nUnknown/General\n" strain = row.strain item = self.make_nano(row) blob += item + "\n" if item else "" blob += self.get_footer() return ChatBlob("%s %s Nanos" % (nanoline.profession, str(nanoline.strain).replace("_", " ")), blob) # @command(command='disc', params=[Any("search")], access_level="member", # description="Search for the disc to a Crystal, or the other way around.") # def disc_search_command(self, req, search): # pass @command(command="nanolines", params=[Any("profession")], access_level="member", description="Show nanolines by profession") def nanolines_profession_cmd(self, _, prof_name): profession = self.util.get_profession(prof_name) if not profession: return "Could not find profession %s." % prof_name data = self.db.query( "SELECT CASE WHEN strain = 'Composite' THEN 'Composite' ELSE school END as school, strain, profession " "FROM nanos WHERE Profession = ? " "and location not like 'No%longer%drops' " "and type not in ('Tainted') " "GROUP by strain ORDER BY school, strain='Composite', strain", [profession]) blob = "" school = "" for row in data: if school != row.school: if row.strain: blob += f"\n{row.school.replace('_', ' ')}\n" else: blob += "\nUnknown/General\n" school = row.school blob += "" + self.text.make_tellcmd(row.strain, f"nanolines {row.profession} {row.strain}") + "\n" blob += self.get_footer() return ChatBlob("%s Nanolines" % profession, blob) def get_footer(self): return "\n\nNano-DB provided by AOIA+ 2019" def get_chat_command(self, search, page): return "/tell nano %s --page=%d" % (search, page) def make_nano(self, row): return f"QL {row.ql: >3} {row.crystal_name} {row.location}"