hotdog/hotdog/command/post.py

127 lines
3.7 KiB
Python

from datetime import datetime, timezone
import postillon
from ..functions import clamp, localizedtz, reply
from ..models import Message
HELP = """Postillon Newsticker.
!post [how many|search terms ...]
!post find [search terms ...]
!post random [how many]
!post more
"""
def init(bot):
bot.on_command("post", handle)
bot.shared.setdefault("post.finds", {})
if "post.store" not in bot.shared:
bot.shared["post.store"] = postillon.Store(bot.config.get("postillon.storage"))
bot.shared["post.store"].connect()
def post_as_plain(post, tzname: str, lc: str):
parts = []
if post.content:
parts.append(f"+++ {post.content} +++")
if post.date:
now = datetime.now(tz=timezone.utc)
since = now - post.date
fmt = ""
if since.days < 1:
fmt = "%X"
else:
if since.days < 7:
fmt += "%A, "
fmt += "%x %X"
parts.append("(" + localizedtz(post.date, fmt, tzname=tzname, lc=lc) + ")")
return " ".join(parts)
def post_as_html(post, tzname: str, lc: str):
parts = []
if post.content:
content = post.content.strip()
sep = ": " if ": " in content else "? " if "? " in content else None
if not sep:
parts.append(f"+++ {post.content} +++")
else:
q, a = content.split(sep, 2)
parts.append(f"+++ <b>{q}{sep}</b>{a} +++")
if post.date:
now = datetime.now(tz=timezone.utc)
since = now - post.date
fmt = ""
if since.days < 1:
fmt = "%X"
else:
if since.days < 7:
fmt += "%A, "
fmt += "%x %X"
parts.append("(" + localizedtz(post.date, fmt, tzname=tzname, lc=lc) + ")")
return " ".join(parts)
async def handle(message: Message):
bot = message.app
poststore = bot.shared["post.store"]
finds = bot.shared["post.finds"] # used to page through find results
max_results = 5
mode = message.args.str(0)
args = message.args
if mode in ("find", "random", "more"):
args = args[1:]
else:
# Time for magic!
if not args:
if finds.get(message.room.room_id, (None, 0))[0] is not None:
mode = "more"
else:
mode = "random"
else:
if len(args) == 1 and args.str(0).isdecimal():
mode = "random"
else:
mode = "find"
if mode == "find":
term = "%".join(args)
posts = poststore.search(f"%{term}%")
finds[message.room.room_id] = (term, 0)
elif mode == "random":
finds[message.room.room_id] = (None, 0)
count = clamp(1, args.int(0), max_results)
posts = [poststore.random_post() for _ in range(count)]
elif mode == "more":
term, page = finds.get(message.room.room_id, (None, 0))
if term is None:
return
page += 1
posts = poststore.search(f"%{term}%", skip=page * max_results)
finds[message.room.room_id] = (term, page)
else:
return
roomconf = bot.config.l6n[message.room.room_id]
i = None
for i, post in enumerate(posts):
if i >= max_results:
await reply(
message,
html=f"<i>Für weitere Ergebnisse</i>: <code>{bot.config.command_prefix}post more</code>",
in_thread=True,
)
break
text = post_as_html(
post,
tzname=roomconf["timezone"],
lc=roomconf["locale"],
)
await reply(message, html=text)
else:
finds[message.room.room_id] = (None, 0)
if i is None:
await reply(message, html="<i>Keine weiteren Ergebnisse.</i>", in_thread=True)