Skip to content

Commit 97cf5f6

Browse files
authored
feat(myinstants): search command (#116)
1 parent 21a87c6 commit 97cf5f6

5 files changed

Lines changed: 175 additions & 122 deletions

File tree

config/config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,9 @@
416416
"porn",
417417
"algorithm",
418418
"loud"
419-
]
419+
],
420+
"search_cmd": "!mis",
421+
"max_results": 10
420422
},
421423
"description": "Search MyInstants.com and play a random sound (e.g. !mi faah)."
422424
},

src/torchlight/CommandHandler.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ def Reload(self) -> None:
7474

7575
# @profile
7676
async def HandleCommand(self, line: str, player: Player, from_menu: bool = False) -> int | None:
77-
if from_menu:
78-
message = line.split(sep=" ", maxsplit=2) # 2 because the !search command requires another arg for page
79-
else:
80-
message = line.split(sep=" ", maxsplit=1)
77+
message = line.split(sep=" ", maxsplit=1)
78+
if not message[0].startswith(("!", "#", "_", "$", "@", "%", "^", "&", "*", "-")):
79+
return None
8180

82-
if len(message) < 2:
81+
if len(message) == 1 or not message[1]:
8382
message.append("")
83+
8484
message[1] = message[1].strip()
8585

8686
if message[1] and self.torchlight.last_url:
@@ -89,9 +89,6 @@ async def HandleCommand(self, line: str, player: Player, from_menu: bool = False
8989

9090
level = player.admin.level
9191

92-
if not message[0].startswith(("!", "#", "_", "$", "@", "%", "^", "&", "*", "-")):
93-
return None
94-
9592
ret_message: str | None = None
9693
ret: int | None = None
9794
for command in self.commands:
@@ -130,7 +127,7 @@ async def HandleCommand(self, line: str, player: Player, from_menu: bool = False
130127
ret = ret_temp
131128
else:
132129
ret = await command._func(message, player)
133-
if from_menu and command.__class__.__name__ == "VoiceTrigger" and ret:
130+
if from_menu and command.__class__.__name__ in ("VoiceTrigger", "MyInstantsSearch") and ret:
134131
self.torchlight.SayChat(f"{{olive}}{player.name}: {{default}}{line}")
135132

136133
except Exception as e:

src/torchlight/Commands.py

Lines changed: 137 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,46 @@ def check_disabled(self, player: Player) -> bool:
100100
return True
101101
return False
102102

103+
def get_menu_page_content(
104+
self,
105+
cmd: str,
106+
search: str | None,
107+
res: dict[str, str],
108+
page: int,
109+
max_items: int,
110+
max_pages: int,
111+
) -> tuple[dict[str, str], int, int]:
112+
start = (page - 1) * max_items if page else 0
113+
end = len(res)
114+
if end > max_items:
115+
end = start + max_items
116+
117+
start = (page - 1) * max_items
118+
end = start + max_items
119+
command_items = dict(list(res.items())[start:end])
120+
121+
if not search:
122+
line = cmd
123+
else:
124+
line = f"{cmd} {search}"
125+
126+
items: dict[str, str] = {}
127+
last_item_info: str = ""
128+
last_item_display: str = ""
129+
if page < max_pages:
130+
last_item_info = f"{line} {page + 1}"
131+
last_item_display = "> Next Page"
132+
items[last_item_info] = last_item_display
133+
if page > 1:
134+
last_item_info = f"{line} {page - 1}"
135+
last_item_display = "> Previous Page"
136+
items[last_item_info] = last_item_display
137+
138+
if last_item_info and last_item_display:
139+
items[last_item_info] = last_item_display + "\n "
140+
141+
return {**items, **command_items}, start, end
142+
103143
async def _func(self, message: list[str], player: Player) -> int:
104144
self.logger.debug(sys._getframe().f_code.co_name)
105145
return 0
@@ -751,52 +791,23 @@ def get_sound_path(self, player: Player, voice_trigger: str, trigger_number: str
751791

752792

753793
class Search(BaseCommand):
754-
def get_menu_page_content(
755-
self,
756-
cmd: str,
757-
search: str,
758-
res: dict[str, str],
759-
page: int,
760-
max_items: int,
761-
max_pages: int,
762-
) -> dict[str, str]:
763-
start = (page - 1) * max_items
764-
end = start + max_items
765-
soundsItems = dict(list(res.items())[start:end])
766-
767-
if search == "":
768-
line = cmd
769-
else:
770-
line = f"{cmd} {search}"
771-
772-
items: dict[str, str] = {}
773-
last_item_info: str = ""
774-
last_item_display: str = ""
775-
if page < max_pages:
776-
last_item_info = f"{line} {page + 1}"
777-
last_item_display = "> Next Page"
778-
items[last_item_info] = last_item_display
779-
if page > 1:
780-
last_item_info = f"{line} {page - 1}"
781-
last_item_display = "> Previous Page"
782-
items[last_item_info] = last_item_display
783-
784-
if last_item_info and last_item_display:
785-
items[last_item_info] = last_item_display + "\n "
786-
787-
return {**items, **soundsItems}
788-
789794
async def _func(self, message: list[str], player: Player) -> int:
790795
self.logger.debug(sys._getframe().f_code.co_name + " " + str(message))
791796

792-
voice_trigger = message[1].lower()
797+
# we need to specify the actual page and result if there is any.
798+
page: int = 1
799+
voice_trigger: str = ""
800+
voice_trigger_parts: list[str] = []
801+
if message[1]:
802+
parts = message[1].split(" ")
803+
for part in parts:
804+
if part.isdigit():
805+
page = int(part)
806+
break
807+
voice_trigger_parts.append(part)
793808

794-
page = 1
795-
if voice_trigger.isdigit():
796-
page = int(voice_trigger)
797-
voice_trigger = ""
798-
if len(message) > 2 and message[2].isdigit():
799-
page = int(message[2])
809+
if voice_trigger_parts:
810+
voice_trigger = " ".join(voice_trigger_parts)
800811

801812
res: dict[str, str] = {}
802813

@@ -827,20 +838,14 @@ async def _func(self, message: list[str], player: Player) -> int:
827838
if page < 1:
828839
page = 1
829840

830-
start = (page - 1) * max if page else 0
831-
end = actual_count
832-
833-
if actual_count > max:
834-
end = start + max
835-
836-
res = self.get_menu_page_content(
837-
cmd=message[0],
838-
search=voice_trigger,
839-
res=res,
840-
page=page,
841-
max_items=max,
842-
max_pages=max_pages,
843-
)
841+
res, start, end = self.get_menu_page_content(
842+
cmd=message[0],
843+
search=voice_trigger,
844+
res=res,
845+
page=page,
846+
max_items=max,
847+
max_pages=max_pages,
848+
)
844849

845850
title: str | None = None
846851
if voice_trigger:
@@ -1432,11 +1437,27 @@ async def _func(self, message: list[str], player: Player) -> int:
14321437
)
14331438
return 1
14341439

1435-
search = message[1]
1436-
if search:
1437-
search = search.lower()
1438-
1440+
search_only: bool = False
14391441
command_config = self.get_config()
1442+
if "search_cmd" in command_config["parameters"] and message[0] == command_config["parameters"]["search_cmd"]:
1443+
search_only = True
1444+
1445+
# we need to specify the actual page and result if there is any.
1446+
page: int = 1
1447+
search_parts: list[str] = []
1448+
if message[1]:
1449+
parts = message[1].split(" ")
1450+
for part in parts:
1451+
if part.isdigit():
1452+
page = int(part)
1453+
break
1454+
1455+
search_parts.append(part)
1456+
1457+
search: str | None = None
1458+
1459+
if search_parts:
1460+
search = " ".join(search_parts)
14401461

14411462
keywords_banned: list[str] = []
14421463

@@ -1465,55 +1486,69 @@ async def _func(self, message: list[str], player: Player) -> int:
14651486
if self.torchlight.config["VoiceServer"]["Proxy"]:
14661487
proxy = self.torchlight.config["VoiceServer"]["Proxy"]
14671488

1468-
url = await asyncio.to_thread(myinstants_get_random_sound, search, proxy)
1489+
urls: dict[str, str] | str | None = None
1490+
1491+
urls = await asyncio.to_thread(myinstants_get_random_sound, search, proxy, search_only)
14691492

1470-
if url is None:
1493+
if urls is None:
14711494
if search:
14721495
self.torchlight.SayPrivate(player, f"{{darkred}}[MyInstants]{{default}} No sound found for {search}")
14731496
else:
14741497
self.torchlight.SayPrivate(player, "{{darkred}}[MyInstants]{{default}} No sounds found")
14751498
return 1
14761499

1477-
audio_clip = self.audio_manager.AudioClip(player, url)
1478-
if not audio_clip:
1479-
return 1
1500+
if isinstance(urls, str):
1501+
audio_clip = self.audio_manager.AudioClip(player, urls)
1502+
if not audio_clip:
1503+
return 1
14801504

1481-
self.torchlight.last_url = url
1482-
return audio_clip.Play()
1505+
self.torchlight.last_url = urls
1506+
return audio_clip.Play()
1507+
elif isinstance(urls, dict):
1508+
# get the play cmd
1509+
play_cmd: str = ""
1510+
for cmd in self.triggers:
1511+
if cmd == message[0]:
1512+
continue
1513+
play_cmd = cast(str, cmd)
1514+
break
14831515

1516+
if not play_cmd:
1517+
return 0
14841518

1485-
class Help(BaseCommand):
1486-
def get_menu_page_content(
1487-
self,
1488-
cmd: str,
1489-
res: dict[str, str],
1490-
page: int,
1491-
max_items: int,
1492-
max_pages: int,
1493-
) -> dict[str, str]:
1494-
start = (page - 1) * max_items
1495-
end = start + max_items
1496-
command_items = dict(list(res.items())[start:end])
1519+
urls = {f"{play_cmd} {k}": v for k, v in urls.items()}
1520+
max = 10
1521+
if "parameters" in command_config and "max_results" in command_config["parameters"]:
1522+
max = command_config["parameters"]["max_results"]
14971523

1498-
line = cmd
1524+
actual_count = len(urls)
1525+
max_pages = (actual_count + max - 1) // max
1526+
if page > max_pages:
1527+
page = max_pages
1528+
if page < 1:
1529+
page = 1
14991530

1500-
items: dict[str, str] = {}
1501-
last_item_info: str = ""
1502-
last_item_display: str = ""
1503-
if page < max_pages:
1504-
last_item_info = f"{line} {page + 1}"
1505-
last_item_display = "> Next Page"
1506-
items[last_item_info] = last_item_display
1507-
if page > 1:
1508-
last_item_info = f"{line} {page - 1}"
1509-
last_item_display = "> Previous Page"
1510-
items[last_item_info] = last_item_display
1531+
res, start, end = self.get_menu_page_content(
1532+
cmd=message[0],
1533+
search=search,
1534+
res=urls,
1535+
page=page,
1536+
max_items=max,
1537+
max_pages=max_pages,
1538+
)
15111539

1512-
if last_item_info and last_item_display:
1513-
items[last_item_info] = last_item_display + "\n "
1540+
title = "[Torchlight] [MyInstants] Search results" + (f" for {search}." if search else ".")
1541+
title += f"\nDisplaying {start + 1}-{min(end, actual_count)} of {actual_count} results."
1542+
title += f"\nPlease wait {int(cooldown)}s before you click on any item."
1543+
self.torchlight.CreateMenu(
1544+
player=player,
1545+
title=title,
1546+
options=res,
1547+
)
1548+
return 0
15141549

1515-
return {**items, **command_items}
15161550

1551+
class Help(BaseCommand):
15171552
async def _func(self, message: list[str], player: Player) -> int:
15181553
self.logger.debug(sys._getframe().f_code.co_name + " " + str(message))
15191554

@@ -1570,18 +1605,14 @@ async def _func(self, message: list[str], player: Player) -> int:
15701605
if page < 1:
15711606
page = 1
15721607

1573-
start = (page - 1) * max if page else 0
1574-
end = actual_count
1575-
1576-
if actual_count > max:
1577-
end = start + max
1578-
res = self.get_menu_page_content(
1579-
cmd=message[0],
1580-
res=res,
1581-
page=page,
1582-
max_items=max,
1583-
max_pages=max_pages,
1584-
)
1608+
res, start, end = self.get_menu_page_content(
1609+
cmd=message[0],
1610+
search=None,
1611+
res=res,
1612+
page=page,
1613+
max_items=max,
1614+
max_pages=max_pages,
1615+
)
15851616

15861617
title = "[Torchlight] Commands List"
15871618

0 commit comments

Comments
 (0)