2025-02-18 01:10:25 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
IRC Bot Plugin for Note Taking using TinyDB.
|
|
|
|
|
|
|
|
This plugin provides a single !note command with subcommands to manage both
|
|
|
|
daily and general notes. It supports the following subcommands:
|
|
|
|
|
|
|
|
today [<content>...]
|
|
|
|
View or update today's daily note.
|
|
|
|
|
|
|
|
daily [--date <date>] [<content>...]
|
|
|
|
View or update a daily note for the specified date (default is today).
|
|
|
|
|
|
|
|
general <title> [--tags <tags>] [<content>...]
|
|
|
|
View or update a general note with the given title.
|
|
|
|
Optionally specify tags.
|
|
|
|
|
|
|
|
list <type>
|
|
|
|
List all notes of the specified type (either 'daily' or 'general').
|
|
|
|
|
|
|
|
search <type> <keyword>
|
|
|
|
Search for a keyword in notes of the specified type.
|
|
|
|
|
|
|
|
summary
|
|
|
|
Display a summary of note counts.
|
|
|
|
|
|
|
|
Notes are stored persistently in the TinyDB database file "notes.json". Daily
|
|
|
|
notes are keyed by date (YYYY-MM-DD) and general notes by a slugified title.
|
|
|
|
|
|
|
|
Dependencies:
|
|
|
|
- irc3
|
|
|
|
- ircstyle
|
|
|
|
- tinydb
|
|
|
|
|
|
|
|
Author: Your Name
|
|
|
|
Version: 1.1
|
|
|
|
Date: 2025-02-17
|
|
|
|
"""
|
|
|
|
|
|
|
|
import re
|
|
|
|
from datetime import datetime, date
|
|
|
|
from tinydb import TinyDB, Query
|
|
|
|
import irc3
|
|
|
|
from irc3.plugins.command import command
|
|
|
|
import ircstyle
|
|
|
|
import logging
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Helper Functions
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
def slugify(text):
|
|
|
|
"""
|
|
|
|
Convert text to a slug (lowercase, underscores, alphanumerics only).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
text (str): The text to slugify.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: A slugified version of the text.
|
|
|
|
"""
|
|
|
|
text = text.lower()
|
|
|
|
text = re.sub(r'\s+', '_', text)
|
|
|
|
text = re.sub(r'[^a-z0-9_-]', '', text)
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
def now_str():
|
|
|
|
"""
|
|
|
|
Return the current datetime as an ISO formatted string.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: The current datetime.
|
|
|
|
"""
|
|
|
|
return datetime.now().isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
def today_str():
|
|
|
|
"""
|
|
|
|
Return today's date in ISO format (YYYY-MM-DD).
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: Today's date.
|
|
|
|
"""
|
|
|
|
return date.today().isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
def default_daily_template(day):
|
|
|
|
"""
|
|
|
|
Generate a default daily note template.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
day (str): The date string (YYYY-MM-DD).
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: Default content for a daily note.
|
|
|
|
"""
|
|
|
|
return f"""# Daily Note for {day}
|
|
|
|
|
|
|
|
## To do:
|
|
|
|
|
|
|
|
## Tomorrow:
|
|
|
|
|
|
|
|
## Reminder:
|
|
|
|
|
|
|
|
## Journal:
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def default_general_template(title, tags):
|
|
|
|
"""
|
|
|
|
Generate a default general note template.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
title (str): The note title.
|
|
|
|
tags (str): Tags for the note.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: Default content for a general note.
|
|
|
|
"""
|
|
|
|
tag_line = f"Tags: {tags}" if tags else ""
|
|
|
|
return f"""# General Note: {title}
|
|
|
|
{tag_line}
|
|
|
|
Created on: {now_str()}
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# NoteTaking Plugin
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@irc3.plugin
|
|
|
|
class NoteTaking:
|
|
|
|
"""
|
|
|
|
IRC3 plugin for unified note taking.
|
|
|
|
|
|
|
|
Provides a single !note command with subcommands to create, update, view,
|
|
|
|
list, and search both daily and general notes stored in TinyDB.
|
|
|
|
"""
|
|
|
|
|
|
|
|
requires = [
|
|
|
|
'irc3.plugins.userlist', # Ensure userlist plugin is loaded, if using user-specific notes
|
|
|
|
]
|
|
|
|
|
|
|
|
def __init__(self, bot):
|
|
|
|
"""
|
|
|
|
Initialize the NoteTaking plugin.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
bot (irc3.IrcBot): The IRC bot instance.
|
|
|
|
"""
|
|
|
|
self.bot = bot
|
|
|
|
# Configuration options with defaults
|
|
|
|
self.db_filename = self.bot.config.get('note_db_filename', 'notes.json')
|
|
|
|
self.daily_template = self.bot.config.get('daily_template', default_daily_template)
|
|
|
|
self.general_template = self.bot.config.get('general_template', default_general_template)
|
|
|
|
|
|
|
|
try:
|
|
|
|
self.db = TinyDB(self.db_filename)
|
|
|
|
self.daily_table = self.db.table('daily')
|
|
|
|
self.general_table = self.db.table('general')
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error initializing TinyDB: {e}")
|
|
|
|
raise # Re-raise to prevent the plugin from loading
|
|
|
|
|
|
|
|
self.User = Query()
|
|
|
|
self.log = logging.getLogger(__name__)
|
|
|
|
|
2025-02-19 03:14:09 +00:00
|
|
|
@command(aliases=['notes'], public=True, options_first=False, use_shlex=True)
|
2025-02-18 01:10:25 +00:00
|
|
|
async def note(self, mask, target, args):
|
|
|
|
"""
|
2025-02-19 03:14:09 +00:00
|
|
|
%%note
|
2025-02-18 01:10:25 +00:00
|
|
|
%%note today [<content>...]
|
2025-02-19 03:14:09 +00:00
|
|
|
%%note daily [<content>...] [--date=<date>]
|
|
|
|
%%note general <title> [<content>...] [--tags <tags>]
|
|
|
|
%%note list <type>
|
2025-02-18 01:10:25 +00:00
|
|
|
%%note search <type> <keyword>
|
|
|
|
%%note summary
|
|
|
|
"""
|
2025-02-19 03:14:09 +00:00
|
|
|
# If no subcommand is provided, show the help message.
|
|
|
|
if not any(args.get(key) for key in ('today', 'daily', 'general', 'list', 'search', 'summary')):
|
|
|
|
self._show_help(target)
|
|
|
|
return
|
|
|
|
|
2025-02-18 01:10:25 +00:00
|
|
|
try:
|
2025-02-19 03:14:09 +00:00
|
|
|
if args.get('today'):
|
2025-02-18 01:10:25 +00:00
|
|
|
await self._note_today(mask, target, args)
|
|
|
|
elif args.get('daily'):
|
|
|
|
await self._note_daily(mask, target, args)
|
|
|
|
elif args.get('general'):
|
|
|
|
await self._note_general(mask, target, args)
|
|
|
|
elif args.get('list'):
|
|
|
|
await self._note_list(target, args)
|
|
|
|
elif args.get('search'):
|
|
|
|
await self._note_search(target, args)
|
|
|
|
elif args.get('summary'):
|
|
|
|
await self._note_summary(target)
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error processing note command: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error processing command: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
2025-02-19 03:14:09 +00:00
|
|
|
def _show_help(self, target):
|
|
|
|
help_lines = [
|
|
|
|
ircstyle.style("Usage: !note <subcommand> [options]", fg="red", bold=True),
|
|
|
|
"Subcommands:",
|
|
|
|
f"{ircstyle.style(' today', fg='yellow')} - View or update today's daily note.",
|
|
|
|
f"{ircstyle.style(' daily [--date <date>]', fg='yellow')} - View or update a daily note for a specific date (default is today).",
|
|
|
|
f"{ircstyle.style(' general <title> [--tags <tags>]', fg='yellow')} - View or update a general note with the given title. Optionally, specify tags.",
|
|
|
|
f"{ircstyle.style(' list [daily|general]', fg='yellow')} - List all notes of a specific type.",
|
|
|
|
f"{ircstyle.style(' search <type> <keyword>', fg='yellow')} - Search for a keyword in notes of a specific type.",
|
|
|
|
f"{ircstyle.style(' summary', fg='yellow')} - Display a summary of note counts.",
|
|
|
|
]
|
|
|
|
|
|
|
|
for line in help_lines:
|
|
|
|
self.bot.privmsg(target, line)
|
|
|
|
|
2025-02-18 01:10:25 +00:00
|
|
|
async def _note_today(self, mask, target, args):
|
|
|
|
"""
|
|
|
|
Handle the 'today' subcommand for daily notes.
|
|
|
|
|
|
|
|
If content is provided, update today's note; otherwise, display it.
|
|
|
|
"""
|
|
|
|
day = today_str()
|
|
|
|
content_list = args.get('<content>')
|
|
|
|
try:
|
|
|
|
note = self._get_daily_note(day)
|
|
|
|
if content_list:
|
|
|
|
new_content = " ".join(content_list)
|
|
|
|
if note:
|
|
|
|
self.daily_table.update(
|
|
|
|
{'content': new_content, 'updated': now_str()},
|
|
|
|
self.User.date == day
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.daily_table.insert({
|
|
|
|
'date': day,
|
|
|
|
'content': new_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str()
|
|
|
|
})
|
|
|
|
msg = ircstyle.style("✅ ", fg="green") + ircstyle.style(
|
|
|
|
f"Daily note for {day} updated.", fg="blue", bold=True
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
if not note:
|
|
|
|
default_content = self.daily_template(day)
|
|
|
|
self.daily_table.insert({
|
|
|
|
'date': day,
|
|
|
|
'content': default_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str()
|
|
|
|
})
|
|
|
|
note = self._get_daily_note(day)
|
|
|
|
msg = ircstyle.style(
|
|
|
|
f"📝 Daily Note for {day}:\n", fg="yellow", bold=True
|
|
|
|
) + note.get('content')
|
|
|
|
self.bot.privmsg(target, msg)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_today: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
async def _note_daily(self, mask, target, args):
|
|
|
|
"""
|
|
|
|
Handle the 'daily' subcommand for daily notes with an optional date.
|
|
|
|
|
|
|
|
If content is provided, update the note; otherwise, display it.
|
|
|
|
"""
|
|
|
|
day = args.get('--date') or today_str()
|
|
|
|
try:
|
|
|
|
datetime.strptime(day, '%Y-%m-%d') # Validate date format
|
|
|
|
except ValueError:
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style("❌ Invalid date format. Use YYYY-MM-DD.", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
content_list = args.get('<content>')
|
2025-02-19 03:14:09 +00:00
|
|
|
|
2025-02-18 01:10:25 +00:00
|
|
|
try:
|
|
|
|
note = self._get_daily_note(day)
|
|
|
|
if content_list:
|
|
|
|
new_content = " ".join(content_list)
|
|
|
|
if note:
|
|
|
|
self.daily_table.update(
|
|
|
|
{'content': new_content, 'updated': now_str()},
|
|
|
|
self.User.date == day
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.daily_table.insert({
|
|
|
|
'date': day,
|
|
|
|
'content': new_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str()
|
|
|
|
})
|
|
|
|
msg = ircstyle.style("✅ ", fg="green") + ircstyle.style(
|
|
|
|
f"Daily note for {day} updated.", fg="blue", bold=True
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
if not note:
|
|
|
|
default_content = self.daily_template(day)
|
|
|
|
self.daily_table.insert({
|
|
|
|
'date': day,
|
|
|
|
'content': default_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str()
|
|
|
|
})
|
|
|
|
note = self._get_daily_note(day)
|
|
|
|
msg = ircstyle.style(
|
|
|
|
f"📝 Daily Note for {day}:\n", fg="yellow", bold=True
|
|
|
|
) + note.get('content')
|
|
|
|
self.bot.privmsg(target, msg)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_daily: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
async def _note_general(self, mask, target, args):
|
|
|
|
"""
|
|
|
|
Handle the 'general' subcommand for general notes.
|
|
|
|
|
|
|
|
If content is provided, update the note; otherwise, display it.
|
|
|
|
"""
|
|
|
|
nick = mask.nick # Get the user's nickname
|
|
|
|
|
|
|
|
# Retrieve <title> as a string (not a list)
|
|
|
|
title = args.get('<title>')
|
|
|
|
if not title:
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style("❌ ", fg="red")
|
|
|
|
+ ircstyle.style("Title is required.", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
slug = slugify(title)
|
|
|
|
tags = args.get('--tags') or ""
|
|
|
|
content_list = args.get('<content>')
|
|
|
|
|
|
|
|
try:
|
|
|
|
# Now filter by owner (nick) so users only access their own general notes
|
|
|
|
note = self._get_general_note(slug, nick)
|
|
|
|
if content_list:
|
|
|
|
new_content = " ".join(content_list)
|
|
|
|
update_fields = {'content': new_content, 'updated': now_str()}
|
|
|
|
if tags:
|
|
|
|
update_fields['tags'] = tags
|
|
|
|
if note:
|
|
|
|
self.general_table.update(
|
|
|
|
update_fields,
|
|
|
|
(self.User.slug == slug) & (self.User.owner == nick)
|
|
|
|
)
|
|
|
|
msg = ircstyle.style("✅ ", fg="green") + ircstyle.style(
|
|
|
|
f"General note '{title}' updated.", fg="blue", bold=True
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.general_table.insert({
|
|
|
|
'title': title,
|
|
|
|
'slug': slug,
|
|
|
|
'tags': tags,
|
|
|
|
'content': new_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str(),
|
|
|
|
'owner': nick # Store the owner of the note
|
|
|
|
})
|
|
|
|
msg = ircstyle.style("✅ ", fg="green") + ircstyle.style(
|
|
|
|
f"General note '{title}' created.", fg="blue", bold=True
|
|
|
|
)
|
|
|
|
|
|
|
|
else:
|
|
|
|
if not note:
|
|
|
|
default_content = self.general_template(title, tags)
|
|
|
|
self.general_table.insert({
|
|
|
|
'title': title,
|
|
|
|
'slug': slug,
|
|
|
|
'tags': tags,
|
|
|
|
'content': default_content,
|
|
|
|
'created': now_str(),
|
|
|
|
'updated': now_str(),
|
|
|
|
'owner': nick # Store the owner of the note
|
|
|
|
})
|
|
|
|
note = self._get_general_note(slug, nick)
|
|
|
|
header = ircstyle.style(
|
|
|
|
f"📝 General Note: {note.get('title')}\n", fg="yellow", bold=True
|
|
|
|
)
|
|
|
|
tag_line = ircstyle.style(
|
|
|
|
f"Tags: {note.get('tags')}\n", fg="cyan"
|
|
|
|
)
|
|
|
|
msg = header + tag_line + note.get('content')
|
|
|
|
self.bot.privmsg(target, msg)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_general: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
async def _note_list(self, target, args):
|
|
|
|
"""
|
|
|
|
Handle the 'list' subcommand to list notes.
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
%%note list [<type>]
|
|
|
|
where <type> is optional and can be 'daily' or 'general'.
|
|
|
|
If <type> is not provided, both daily and general notes are listed.
|
|
|
|
"""
|
|
|
|
note_type = args.get('<type>')
|
|
|
|
try:
|
|
|
|
if not note_type:
|
|
|
|
# List both daily and general notes
|
|
|
|
daily_notes = self.daily_table.all()
|
|
|
|
general_notes = self.general_table.all()
|
|
|
|
|
|
|
|
# Filter valid daily notes
|
|
|
|
valid_daily_dates = [n.get('date') for n in daily_notes if isinstance(n.get('date'), str)]
|
|
|
|
# Filter valid general notes
|
|
|
|
valid_general_titles = [n.get('title') for n in general_notes if isinstance(n.get('title'), str)]
|
|
|
|
|
|
|
|
if not valid_daily_dates and not valid_general_titles:
|
|
|
|
msg = ircstyle.style("No notes found.", fg="red", bold=True)
|
|
|
|
else:
|
|
|
|
msg = ircstyle.style("📝 All Notes:", fg="blue", bold=True) + "\n"
|
|
|
|
if valid_daily_dates:
|
|
|
|
msg += ircstyle.style("📅 Daily Notes:", fg="yellow", bold=True) + "\n"
|
|
|
|
msg += "\n".join([f"• {date}" for date in sorted(valid_daily_dates)]) + "\n"
|
|
|
|
if valid_general_titles:
|
|
|
|
msg += ircstyle.style("📋 General Notes:", fg="cyan", bold=True) + "\n"
|
|
|
|
msg += "\n".join([f"• {title}" for title in sorted(valid_general_titles)])
|
|
|
|
elif note_type == 'daily':
|
|
|
|
notes = self.daily_table.all()
|
|
|
|
# Filter only notes with a valid date string
|
|
|
|
valid_dates = [n.get('date') for n in notes if isinstance(n.get('date'), str)]
|
|
|
|
if not valid_dates:
|
|
|
|
msg = ircstyle.style("No daily notes found.", fg="red", bold=True)
|
|
|
|
else:
|
|
|
|
dates = sorted(valid_dates)
|
|
|
|
msg = ircstyle.style("📅 Daily Notes:", fg="blue", bold=True) + "\n"
|
|
|
|
msg += "\n".join([f"• {date}" for date in dates])
|
|
|
|
elif note_type == 'general':
|
|
|
|
notes = self.general_table.all()
|
|
|
|
if not notes:
|
|
|
|
msg = ircstyle.style("No general notes found.", fg="red", bold=True)
|
|
|
|
else:
|
|
|
|
titles = sorted(n['title'] for n in notes if isinstance(n.get('title'), str))
|
|
|
|
msg = ircstyle.style("📋 General Notes:", fg="blue", bold=True) + "\n"
|
|
|
|
msg += "\n".join([f"• {title}" for title in titles])
|
|
|
|
else:
|
|
|
|
msg = ircstyle.style("Usage: !note list [daily|general]", fg="red", bold=True)
|
|
|
|
for line in msg.split('\n'):
|
|
|
|
self.bot.privmsg(target, line)
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_list: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(target, ircstyle.style(f"❌ Error: {e}", fg="red", bold=True))
|
|
|
|
|
|
|
|
async def _note_search(self, target, args):
|
|
|
|
"""
|
|
|
|
Handle the 'search' subcommand to search notes by keyword.
|
|
|
|
Usage:
|
|
|
|
%%note search <type> <keyword>
|
|
|
|
"""
|
|
|
|
note_type = args.get('<type>')
|
|
|
|
keyword = args.get('<keyword>')
|
|
|
|
|
|
|
|
if note_type not in ('daily', 'general') or not keyword:
|
|
|
|
msg = ircstyle.style("Usage: !note search <daily|general> <keyword>", fg="red", bold=True)
|
|
|
|
self.bot.privmsg(target, msg)
|
|
|
|
return
|
|
|
|
try:
|
|
|
|
if note_type == 'daily':
|
|
|
|
notes = self.daily_table.search(self.User.content.search(keyword, flags=re.IGNORECASE))
|
|
|
|
header = "Daily"
|
|
|
|
else:
|
|
|
|
notes = self.general_table.search(self.User.content.search(keyword, flags=re.IGNORECASE))
|
|
|
|
header = "General"
|
|
|
|
if not notes:
|
|
|
|
msg = ircstyle.style(f"No {note_type} notes found with '{keyword}'.", fg="red", bold=True)
|
|
|
|
else:
|
|
|
|
results = []
|
|
|
|
for n in notes:
|
|
|
|
identifier = n.get('date') if note_type == 'daily' else n.get('title')
|
|
|
|
content_snippet = n.get('content')[:50] + "..." # Show a snippet of the content
|
|
|
|
results.append(f"{identifier} ({content_snippet})")
|
|
|
|
msg = ircstyle.style(f"{header} Notes matching '{keyword}':\n", fg="blue", bold=True) + "\n".join(results)
|
|
|
|
for line in msg.split('\n'):
|
|
|
|
self.bot.privmsg(target, line)
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_search: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
async def _note_summary(self, target):
|
|
|
|
"""
|
|
|
|
Handle the 'summary' subcommand to display note counts.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
daily_count = len(self.daily_table.all())
|
|
|
|
general_count = len(self.general_table.all())
|
|
|
|
lines = [
|
|
|
|
ircstyle.style("===== NOTE SUMMARY =====", fg="teal", bold=True),
|
|
|
|
ircstyle.style(f"Daily notes: {daily_count}", fg="yellow"),
|
|
|
|
ircstyle.style(f"General notes: {general_count}", fg="cyan"),
|
|
|
|
ircstyle.style("===== END SUMMARY =====", fg="teal", bold=True)
|
|
|
|
]
|
|
|
|
for line in lines:
|
|
|
|
self.bot.privmsg(target, line)
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _note_summary: {e}", exc_info=True)
|
|
|
|
self.bot.privmsg(
|
|
|
|
target,
|
|
|
|
ircstyle.style(f"❌ Error: {e}", fg="red", bold=True)
|
|
|
|
)
|
|
|
|
|
|
|
|
def _get_daily_note(self, day):
|
|
|
|
"""
|
|
|
|
Retrieve a daily note for the given day.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
day (str): The date (YYYY-MM-DD).
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
dict or None: The note if found, else None.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
results = self.daily_table.search(self.User.date == day)
|
|
|
|
return results[0] if results else None
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _get_daily_note: {e}", exc_info=True)
|
|
|
|
return None
|
|
|
|
|
|
|
|
def _get_general_note(self, slug, owner=None):
|
|
|
|
"""
|
|
|
|
Retrieve a general note by its slug and (optionally) owner.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
slug (str): The slugified title.
|
|
|
|
owner (str, optional): The owner of the note.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
dict or None: The note if found, else None.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
if owner:
|
|
|
|
results = self.general_table.search((self.User.slug == slug) & (self.User.owner == owner))
|
|
|
|
else:
|
|
|
|
results = self.general_table.search(self.User.slug == slug)
|
|
|
|
return results[0] if results else None
|
|
|
|
except Exception as e:
|
|
|
|
self.bot.log.error(f"Error in _get_general_note: {e}", exc_info=True)
|
|
|
|
return None
|