213 lines
7.3 KiB
Python
213 lines
7.3 KiB
Python
"""
|
||
This plugin provides a command to fetch definitions from Urban Dictionary.
|
||
"""
|
||
|
||
import logging
|
||
import requests
|
||
import simplematrixbotlib as botlib
|
||
import html
|
||
|
||
URBAN_API_URL = "https://api.urbandictionary.com/v0/define"
|
||
RANDOM_API_URL = "https://api.urbandictionary.com/v0/random"
|
||
|
||
|
||
def format_definition(term, definition, example, author, thumbs_up, thumbs_down, permalink, index=None, total=None):
|
||
"""
|
||
Format an Urban Dictionary definition for display.
|
||
|
||
Args:
|
||
term (str): The term being defined.
|
||
definition (str): The definition text.
|
||
example (str): Example usage.
|
||
author (str): Author of the definition.
|
||
thumbs_up (int): Number of upvotes.
|
||
thumbs_down (int): Number of downvotes.
|
||
permalink (str): URL to the definition.
|
||
index (int, optional): Current definition index.
|
||
total (int, optional): Total number of definitions.
|
||
|
||
Returns:
|
||
str: Formatted HTML message.
|
||
"""
|
||
# Clean up the text - Urban Dictionary uses [brackets] for links
|
||
definition = definition.replace('[', '<strong>').replace(']', '</strong>')
|
||
example = example.replace('[', '<em>').replace(']', '</em>')
|
||
|
||
# Escape any HTML that might be in the original text
|
||
term = html.escape(term)
|
||
author = html.escape(author)
|
||
|
||
# Build the message
|
||
header = f"<strong>📖 Urban Dictionary: {term}</strong>"
|
||
if index is not None and total is not None:
|
||
header += f" (Definition {index}/{total})"
|
||
|
||
message = f"""{header}
|
||
<strong>Definition:</strong>
|
||
{definition}
|
||
"""
|
||
if example and example.strip():
|
||
message += f"""
|
||
<strong>Example:</strong>
|
||
<em>{example}</em>
|
||
"""
|
||
message += f"""
|
||
<strong>Author:</strong> {author} | 👍 {thumbs_up} 👎 {thumbs_down}
|
||
<a href="{permalink}">View on Urban Dictionary</a>
|
||
"""
|
||
|
||
return message
|
||
|
||
|
||
async def handle_command(room, message, bot, prefix, config):
|
||
"""
|
||
Function to handle the !ud (Urban Dictionary) command.
|
||
|
||
Args:
|
||
room (Room): The Matrix room where the command was invoked.
|
||
message (RoomMessage): The message object containing the command.
|
||
bot (Bot): The bot object.
|
||
prefix (str): The command prefix.
|
||
config (dict): Configuration parameters.
|
||
|
||
Returns:
|
||
None
|
||
"""
|
||
match = botlib.MessageMatch(room, message, bot, prefix)
|
||
if match.is_not_from_this_bot() and match.prefix() and match.command("ud"):
|
||
logging.info("Received !ud command")
|
||
|
||
args = match.args()
|
||
|
||
try:
|
||
# Case 1: No arguments - get random definition
|
||
if len(args) == 0:
|
||
logging.info("Fetching random Urban Dictionary definition")
|
||
response = requests.get(RANDOM_API_URL, timeout=10)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
|
||
if not data.get('list'):
|
||
await bot.api.send_text_message(room.room_id, "No random definition found.")
|
||
return
|
||
|
||
# Get first random entry
|
||
entry = data['list'][0]
|
||
formatted = format_definition(
|
||
term=entry['word'],
|
||
definition=entry['definition'],
|
||
example=entry.get('example', ''),
|
||
author=entry['author'],
|
||
thumbs_up=entry['thumbs_up'],
|
||
thumbs_down=entry['thumbs_down'],
|
||
permalink=entry['permalink']
|
||
)
|
||
|
||
await bot.api.send_markdown_message(room.room_id, formatted)
|
||
logging.info(f"Sent random definition: {entry['word']}")
|
||
return
|
||
|
||
# Case 2: One or more arguments - search for term
|
||
# Check if last argument is a number (definition index)
|
||
index = None
|
||
search_term = ' '.join(args)
|
||
|
||
if args[-1].isdigit():
|
||
index = int(args[-1])
|
||
search_term = ' '.join(args[:-1])
|
||
|
||
if not search_term:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
"Usage: !ud [term] [index]\nExamples:\n !ud - random definition\n !ud yeet - first definition of 'yeet'\n !ud yeet 2 - second definition of 'yeet'"
|
||
)
|
||
return
|
||
|
||
logging.info(f"Searching Urban Dictionary for: {search_term}")
|
||
params = {'term': search_term}
|
||
response = requests.get(URBAN_API_URL, params=params, timeout=10)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
|
||
definitions = data.get('list', [])
|
||
|
||
if not definitions:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"No definition found for '{search_term}'"
|
||
)
|
||
logging.info(f"No definition found for: {search_term}")
|
||
return
|
||
|
||
total = len(definitions)
|
||
|
||
# If no index specified, use first definition
|
||
if index is None:
|
||
index = 1
|
||
|
||
# Validate index
|
||
if index < 1 or index > total:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"Invalid index. '{search_term}' has {total} definition(s). Use !ud {search_term} [1-{total}]"
|
||
)
|
||
return
|
||
|
||
# Get the requested definition (convert to 0-based index)
|
||
entry = definitions[index - 1]
|
||
|
||
formatted = format_definition(
|
||
term=entry['word'],
|
||
definition=entry['definition'],
|
||
example=entry.get('example', ''),
|
||
author=entry['author'],
|
||
thumbs_up=entry['thumbs_up'],
|
||
thumbs_down=entry['thumbs_down'],
|
||
permalink=entry['permalink'],
|
||
index=index,
|
||
total=total
|
||
)
|
||
|
||
await bot.api.send_markdown_message(room.room_id, formatted)
|
||
logging.info(f"Sent definition {index}/{total} for: {search_term}")
|
||
|
||
except requests.exceptions.Timeout:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
"Request timed out. Urban Dictionary may be slow or unavailable."
|
||
)
|
||
logging.error("Urban Dictionary API timeout")
|
||
|
||
except requests.exceptions.RequestException as e:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"Error fetching from Urban Dictionary: {e}"
|
||
)
|
||
logging.error(f"Error fetching from Urban Dictionary: {e}")
|
||
|
||
except Exception as e:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
"An error occurred while processing the Urban Dictionary request."
|
||
)
|
||
logging.error(f"Unexpected error in Urban Dictionary plugin: {e}", exc_info=True)
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Plugin Metadata
|
||
# ---------------------------------------------------------------------------
|
||
|
||
__version__ = "1.0.0"
|
||
__author__ = "Funguy Bot"
|
||
__description__ = "Urban Dictionary definitions"
|
||
__help__ = """
|
||
<details>
|
||
<summary><strong>!ud</strong> – Urban Dictionary</summary>
|
||
<ul>
|
||
<li><code>!ud</code> – Random definition</li>
|
||
<li><code>!ud <term></code> – Top definition</li>
|
||
<li><code>!ud <term> <index></code> – Nth definition</li>
|
||
</ul>
|
||
</details>
|
||
"""
|