This commit introduces two main enhancements to Gurt's capabilities: 1. **Tenor GIF Integration:** * The AI can now request Tenor GIFs via a `request_tenor_gif_query` field in its response schema. * `api.py` handles these requests by searching Tenor (using the new `TENOR_API_KEY` from config) and appending the GIF URL to the AI's message content. * System prompts have been updated to instruct the AI on how to request GIFs. 2. **Custom Emoji & Sticker Learning and Usage:** * Introduces an `EmojiManager` (in the new `gurt/emojis.py`) to store and manage mappings of custom emoji/sticker names to their URLs. This data is persisted to `EMOJI_STORAGE_FILE`. * Gurt now automatically learns custom emojis and stickers (and their URLs) from user messages via the `on_message` listener in `listeners.py`. * The AI can be prompted to use these learned emojis/stickers by referencing their `:name:`. * `api.py` processes AI responses to identify known custom emojis/stickers. For stickers, their URL is appended to the content if mentioned. * A `learnemoji` command has been added for manually teaching Gurt emojis/stickers, although automatic learning is the primary mechanism. * System prompts are updated to guide the AI on using custom emojis/stickers.
94 lines
3.9 KiB
Python
94 lines
3.9 KiB
Python
import json
|
|
import os
|
|
from typing import Dict, Optional, Tuple
|
|
|
|
DATA_FILE_PATH = "data/custom_emojis_stickers.json"
|
|
|
|
class EmojiManager:
|
|
def __init__(self, data_file: str = DATA_FILE_PATH):
|
|
self.data_file = data_file
|
|
self.data: Dict[str, Dict[str, str]] = {"emojis": {}, "stickers": {}}
|
|
self._load_data()
|
|
|
|
def _load_data(self):
|
|
"""Loads emoji and sticker data from the JSON file."""
|
|
try:
|
|
if os.path.exists(self.data_file):
|
|
with open(self.data_file, 'r', encoding='utf-8') as f:
|
|
loaded_json = json.load(f)
|
|
if isinstance(loaded_json, dict):
|
|
self.data["emojis"] = loaded_json.get("emojis", {})
|
|
self.data["stickers"] = loaded_json.get("stickers", {})
|
|
print(f"Loaded {len(self.data['emojis'])} emojis and {len(self.data['stickers'])} stickers from {self.data_file}")
|
|
else:
|
|
print(f"Warning: Data in {self.data_file} is not a dictionary. Initializing with empty data.")
|
|
self._save_data() # Initialize with empty structure if format is wrong
|
|
else:
|
|
print(f"{self.data_file} not found. Initializing with empty data.")
|
|
self._save_data() # Create the file if it doesn't exist
|
|
except json.JSONDecodeError:
|
|
print(f"Error decoding JSON from {self.data_file}. Initializing with empty data.")
|
|
self._save_data()
|
|
except Exception as e:
|
|
print(f"Error loading emoji/sticker data: {e}")
|
|
# Ensure data is initialized even on other errors
|
|
if "emojis" not in self.data: self.data["emojis"] = {}
|
|
if "stickers" not in self.data: self.data["stickers"] = {}
|
|
|
|
|
|
def _save_data(self):
|
|
"""Saves the current emoji and sticker data to the JSON file."""
|
|
try:
|
|
os.makedirs(os.path.dirname(self.data_file), exist_ok=True)
|
|
with open(self.data_file, 'w', encoding='utf-8') as f:
|
|
json.dump(self.data, f, indent=4)
|
|
print(f"Saved emoji and sticker data to {self.data_file}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error saving emoji/sticker data: {e}")
|
|
return False
|
|
|
|
async def add_emoji(self, name: str, url: str) -> bool:
|
|
"""Adds a custom emoji."""
|
|
if name in self.data["emojis"]:
|
|
return False # Emoji already exists
|
|
self.data["emojis"][name] = url
|
|
return self._save_data()
|
|
|
|
async def remove_emoji(self, name: str) -> bool:
|
|
"""Removes a custom emoji."""
|
|
if name not in self.data["emojis"]:
|
|
return False # Emoji not found
|
|
del self.data["emojis"][name]
|
|
return self._save_data()
|
|
|
|
async def list_emojis(self) -> Dict[str, str]:
|
|
"""Lists all custom emojis."""
|
|
return self.data["emojis"]
|
|
|
|
async def get_emoji(self, name: str) -> Optional[str]:
|
|
"""Gets a specific custom emoji by name."""
|
|
return self.data["emojis"].get(name)
|
|
|
|
async def add_sticker(self, name: str, url: str) -> bool:
|
|
"""Adds a custom sticker."""
|
|
if name in self.data["stickers"]:
|
|
return False # Sticker already exists
|
|
self.data["stickers"][name] = url
|
|
return self._save_data()
|
|
|
|
async def remove_sticker(self, name: str) -> bool:
|
|
"""Removes a custom sticker."""
|
|
if name not in self.data["stickers"]:
|
|
return False # Sticker not found
|
|
del self.data["stickers"][name]
|
|
return self._save_data()
|
|
|
|
async def list_stickers(self) -> Dict[str, str]:
|
|
"""Lists all custom stickers."""
|
|
return self.data["stickers"]
|
|
|
|
async def get_sticker(self, name: str) -> Optional[str]:
|
|
"""Gets a specific custom sticker by name."""
|
|
return self.data["stickers"].get(name)
|