-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommands.py
More file actions
149 lines (132 loc) · 5.67 KB
/
commands.py
File metadata and controls
149 lines (132 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import discord
from discord.ext import commands
import json
import logging
from io import BytesIO
import aiohttp
import re
from dune_logic import search as dune_search
logger = logging.getLogger(__name__)
def setup_commands(bot):
@bot.command(name="bothelp")
async def bothelp(ctx):
embed = discord.Embed(
title="Dune Bot Help",
description="Available commands:",
color=0x00ff00,
timestamp=discord.utils.utcnow()
)
embed.add_field(
name="Commands",
value=(
"`!bothelp` - Show this help\n"
"`!savememory <text>` - Save a memory\n"
"`!wipe` - Clear chat history\n"
"`!search <query>` - Search Dune data\n"
"`!item <name>` - Lookup item\n"
"`!skill <name>` - Lookup skill\n"
"`!contract <name>` - Lookup contract\n"
"`!npc <name>` - Lookup NPC"
),
inline=False
)
embed.add_field(
name="Model",
value=f"{bot.memory_manager.api_client.config.default_model} (default)",
inline=False
)
embed.set_footer(text="Pollinations.ai")
await ctx.send(embed=embed)
@bot.command(name="savememory")
async def savememory(ctx, *, memory_text):
channel_id = str(ctx.channel.id)
user_id = str(ctx.author.id)
bot.memory_manager.add_memory(channel_id, memory_text)
await bot.data_manager.save_data_async(bot.memory_manager)
embed = discord.Embed(
title="Memory Saved",
description=f"Saved: {memory_text}",
color=0x00ff00,
timestamp=discord.utils.utcnow()
)
await ctx.send(f"<@{user_id}>", embed=embed)
async def _send_response(ctx, final_message, user_id):
files = []
for url in final_message.get("images", []):
try:
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
if resp.status == 200:
data = await resp.read()
filename = url.split("/")[-1].split("?")[0] or "image.png"
if not re.search(r"\.(png|jpg|jpeg|gif|webp)$", filename, re.IGNORECASE):
filename += ".png"
files.append(discord.File(BytesIO(data), filename=filename))
except Exception as e:
logger.warning(f"Failed to fetch image {url}: {e}")
content = final_message.get("content", "")
if not content and not files:
await ctx.send(f"<@{user_id}> (No content)")
return
if content and len(content) <= 2000:
await ctx.send(content, files=files if files else None)
elif content and len(content) <= 4096:
embed = discord.Embed(description=content[:4096])
await ctx.send(embed=embed, files=files if files else None)
else:
if content:
buffer = BytesIO(content.encode("utf-8"))
text_file = discord.File(buffer, filename="response.txt")
files = files + [text_file]
await ctx.send(f"<@{user_id}> Response too long, attached as file and images:", files=files)
async def _dune_query(ctx, query: str, data: dict):
user_id = str(ctx.author.id)
guild_id = str(ctx.guild.id) if ctx.guild else "DM"
model = bot.memory_manager.get_user_model(guild_id, user_id)
guardrails = (
"Use ONLY the following GameData JSON for Dune Awakening specifics. "
"If something is missing, say so briefly."
)
messages = [
{"role": "system", "content": f"{bot.config.system_instructions}\n{guardrails}\nGameData:\n{json.dumps(data, ensure_ascii=False)}"},
{"role": "user", "content": query},
]
try:
ai_response = await bot.api_client.send_message(messages, model)
except Exception as e:
await ctx.send(f"<@{user_id}> Error: Failed to fetch response - {e}")
return
ai_response_clean = bot.message_handler.clean_response(ai_response) or "Got it."
final_message = bot.message_handler.build_message(ai_response_clean)
await _send_response(ctx, final_message, user_id)
@bot.command(name="search")
async def search_cmd(ctx, *, query: str):
locale = "en"
results = await dune_search.search_autocomplete(locale, query, [])
data = {"results": results[:5]}
await _dune_query(ctx, query, data)
async def _lookup_and_query(ctx, query: str, types: list):
locale = "en"
results = await dune_search.search_autocomplete(locale, query, types)
if not results:
await ctx.send(f'No results found for "{query}".')
return
path = results[0].get("path")
try:
_, card = await dune_search.route_path(locale, path)
except Exception:
await ctx.send(f'Could not retrieve data for "{query}".')
return
await _dune_query(ctx, query, card)
@bot.command(name="item")
async def item_cmd(ctx, *, query: str):
await _lookup_and_query(ctx, query, ["items"])
@bot.command(name="skill")
async def skill_cmd(ctx, *, query: str):
await _lookup_and_query(ctx, query, ["skills"])
@bot.command(name="contract")
async def contract_cmd(ctx, *, query: str):
await _lookup_and_query(ctx, query, ["contracts"])
@bot.command(name="npc")
async def npc_cmd(ctx, *, query: str):
await _lookup_and_query(ctx, query, ["npcs"])