-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
106 lines (87 loc) · 3.97 KB
/
bot.py
File metadata and controls
106 lines (87 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import asyncio
import os
import shelve
from hikari import GuildPublicThread, RESTApp, TokenType
from hikari.impl import RESTClientImpl
from src.utils.data_types import ProjectItemEvent
from src.utils.discord_rest_client import fetch_forum_channel, get_post_id_or_post
from src.utils.error import ForumChannelNotFound
from src.utils.github_api import fetch_item_name
from src.utils.misc import SharedForumChannel, bot_logger, create_item_link, handle_task_exception, retrieve_discord_id
async def run(state: asyncio.Queue[ProjectItemEvent], stop_after_one_event: bool = False):
discord_rest = RESTApp()
await discord_rest.start()
async with discord_rest.acquire(os.getenv("DISCORD_BOT_TOKEN"), token_type=TokenType.BOT) as client:
bot_logger.info("Discord client acquired.")
forum_channel_id = int(os.getenv("FORUM_CHANNEL_ID"))
discord_guild_id = int(os.getenv("DISCORD_GUILD_ID"))
forum_channel = await fetch_forum_channel(client, forum_channel_id)
if forum_channel is None:
raise ForumChannelNotFound(f"Forum channel with ID {forum_channel_id} not found.")
shared_forum_channel = SharedForumChannel(forum_channel)
while True:
event = await state.get()
update_task = asyncio.create_task(
process_update(client, forum_channel_id, discord_guild_id, shared_forum_channel, event)
)
update_task.add_done_callback(lambda task: handle_task_exception(task, "Error processing update:"))
if stop_after_one_event:
break
async def process_update(
client: RESTClientImpl,
forum_channel_id: int,
discord_guild_id: int,
shared_forum_channel: SharedForumChannel,
event: ProjectItemEvent,
):
bot_logger.info(f"Processing event for item: {event.node_id}")
post_id_or_post = await get_post_id_or_post(event.node_id, discord_guild_id, forum_channel_id, client)
author_discord_id = retrieve_discord_id(event.sender)
user_mentions = [author_discord_id] if author_discord_id else []
user_text_mention = f"<@{author_discord_id}>" if author_discord_id else "nieznany użytkownik"
if post_id_or_post is None:
post = await create_post(event, user_text_mention, shared_forum_channel, client, user_mentions)
elif isinstance(post_id_or_post, int):
post = await client.fetch_channel(post_id_or_post)
else:
post = post_id_or_post
if not isinstance(post, GuildPublicThread):
try:
bot_logger.error(f"Post with ID {post.id} is not a GuildPublicThread.")
except AttributeError:
bot_logger.error(f"Post with node_id {event.node_id} is not a GuildPublicThread.")
return
message = await event.process(user_text_mention, post, client, shared_forum_channel, forum_channel_id)
if not message:
return
messages = []
while len(message) > 2000:
messages.append(message[:2000])
message = message[2000:]
messages.append(message)
for msg in messages:
await client.create_message(post.id, msg, user_mentions=user_mentions)
async def create_post(
event: ProjectItemEvent,
user_text_mention: str,
shared_forum_channel: SharedForumChannel,
client: RESTClientImpl,
user_mentions: list[str],
) -> GuildPublicThread:
bot_logger.info(f"Post not found, creating new post for item: {event.node_id}")
item_name = await fetch_item_name(event.node_id)
message = (
f"Nowy task stworzony {item_name} przez: {user_text_mention}.\n"
f" Link do taska: {create_item_link(event.item_id)}"
)
async with shared_forum_channel.lock.reader_lock:
post = await client.create_forum_post(
shared_forum_channel.forum_channel,
item_name,
message,
auto_archive_duration=10080,
user_mentions=user_mentions,
)
with shelve.open(os.getenv("POST_ID_DB_PATH", "post_id.db")) as db:
db[event.node_id] = str(post.id)
return post