Bot pro KSP Discord
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.9 KiB

11 months ago
from datetime import datetime
import discord
from discord.ext import commands
from discord.utils import get
from markdownify import markdownify
import re
from bs4 import BeautifulSoup
10 months ago
from hrochobot.utils.ksp_utils import ksp_feed, strip_id, KSP_URL
11 months ago
import hrochobot.utils.data as data
NEWS_JSON = "news"
10 months ago
async def get_news_ids():
feed = await ksp_feed()
return list(map(lambda e: e.id, feed.entries))
async def autocomplete_news_ids(ctx):
value = ctx.value.lower()
options = []
for id_ in map(strip_id, await get_news_ids()):
lid = id_.lower()
if lid.startswith(value) or lid.split("_", 1)[1].startswith(value):
options.append(id_)
return options
11 months ago
def guess_color(title):
"""
Automagically guess color of given post.
Not always reliable as all things automagic.
"""
def contains(*regexes):
return any(re.search(regex, title) for regex in regexes)
if contains(r"(\d+)-Z(\d+)", "začátečnic", "KSP-Z"):
return discord.Color.green()
elif contains(r"(\d+)-(\d+)", "seriál", "série", "KSP-H"):
return discord.Color.blue()
else:
return discord.Color.dark_purple()
def format_entry(entry, author=None):
content = "\n\n".join(map(lambda x: x.replace('\n', ' '), entry.summary.split("\n\n")))
embed = discord.Embed(
title=entry.title,
url=entry.link,
description=markdownify(content, strip=["img"]),
color=guess_color(entry.title),
)
soup = BeautifulSoup(content, 'html.parser')
img = soup.find('img')
if img:
embed.set_image(url=img['src'])
if author:
embed.set_author(name=author)
embed.set_thumbnail(url=f"{KSP_URL}/img/hippo_head.png")
11 months ago
date = datetime.fromisoformat(entry.published)
embed.set_footer(text=date.strftime("%-d. %-m. %Y"))
return embed
async def post_news(bot, guild, entry_id):
11 months ago
news_json = data.load_guild_data(guild.id, NEWS_JSON)
if "news_channel" not in news_json:
return "News channel not set."
11 months ago
channel = get(guild.channels, id=news_json["news_channel"])
feed = await ksp_feed()
10 months ago
entries_with_id = list(filter(lambda e: strip_id(e.id) == entry_id, feed.entries))
if len(entries_with_id) == 0:
return f"Entry with id ``{entry_id}`` not found."
await channel.send(embed=format_entry(entries_with_id[0], author=feed.feed.author))
return None
11 months ago
class News(commands.Cog):
def __init__(self, bot):
self.bot = bot
news = discord.SlashCommandGroup(
"news",
"Commands for management of ksp news.",
guild_only=True,
checks=[commands.has_permissions(manage_guild=True)]
)
@news.command(description="Sets channel for posting news.")
@discord.option("channel_id", str, description="Id of the channel for sending news.")
async def set_channel(self, ctx, channel_id: str):
try:
channel_id = int(channel_id)
except ValueError:
return await ctx.respond(f"Channel id must be int.", ephemeral=True)
if not (channel := get(ctx.guild.channels, id=channel_id)):
return await ctx.respond(f"No channel with id ``{channel_id}``.", ephemeral=True)
11 months ago
news_json = data.load_guild_data(ctx.guild.id, NEWS_JSON)
news_json["news_channel"] = channel_id
11 months ago
data.dump_guild_data(ctx.guild.id, NEWS_JSON, news_json)
return await ctx.respond(f"News channel set to {channel.mention}.", ephemeral=True)
@news.command(description="Posts news of given id to set channel.")
10 months ago
@discord.option("id", str, description="Id of entry to send.", autocomplete=autocomplete_news_ids)
async def post_news(self, ctx, id: int):
await ctx.defer(ephemeral=True)
err = await post_news(self.bot, ctx.guild, id)
if err:
return await ctx.respond(err, ephemeral=True)
return await ctx.respond(f"News posted.")
11 months ago
def setup(bot):
bot.add_cog(News(bot))