127 lines
3.7 KiB
Python
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)
|