koi-net-ask-topic-groups-node 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/PKG-INFO +1 -1
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/pyproject.toml +1 -1
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/config.py +1 -0
- koi_net_ask_topic_groups_node-0.2.0/src/koi_net_ask_topic_groups_node/knowledge_handlers/ask_thread_handler.py +107 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/knowledge_handlers/slack_usergroup_handler.py +3 -1
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/slack_command_handler.py +63 -6
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node.egg-info/PKG-INFO +1 -1
- koi_net_ask_topic_groups_node-0.1.0/src/koi_net_ask_topic_groups_node/knowledge_handlers/ask_thread_handler.py +0 -65
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/README.md +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/setup.cfg +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/__init__.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/__main__.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/core.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/models.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/rid_types.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/slack_config_manager.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/slack_event_handler.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/socket_mode.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node/user_group_sensor.py +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node.egg-info/SOURCES.txt +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node.egg-info/dependency_links.txt +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node.egg-info/requires.txt +0 -0
- {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/src/koi_net_ask_topic_groups_node.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: koi-net-ask-topic-groups-node
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Topic groups KOI-net node for the ask network application.
|
|
5
5
|
Author-email: Luke Miller <luke@metagov.org>
|
|
6
6
|
Project-URL: Homepage, https://github.com/metagov/koi-net-ask-topic-groups-node
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from koi_net.components import Cache, KobjQueue
|
|
4
|
+
from koi_net.components.interfaces import KnowledgeHandler, HandlerType
|
|
5
|
+
from koi_net.protocol.knowledge_object import KnowledgeObject
|
|
6
|
+
from rid_lib.ext import Bundle
|
|
7
|
+
from rid_lib.types import SlackMessage
|
|
8
|
+
from slack_bolt import App
|
|
9
|
+
|
|
10
|
+
from ..models import ThreadLinkModel, TopicGroupModel
|
|
11
|
+
from ..rid_types import AskCoreThread, AskTopicGroup, ThreadLink
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class AskThreadHandler(KnowledgeHandler):
|
|
16
|
+
slack_app: App
|
|
17
|
+
cache: Cache
|
|
18
|
+
kobj_queue: KobjQueue
|
|
19
|
+
|
|
20
|
+
handler_type = HandlerType.Network
|
|
21
|
+
rid_types = (AskCoreThread,)
|
|
22
|
+
|
|
23
|
+
def ensure_bot_in_channel(self, channel_id: str):
|
|
24
|
+
try:
|
|
25
|
+
result = self.slack_app.client.conversations_info(channel=channel_id)
|
|
26
|
+
channel = result["channel"]
|
|
27
|
+
|
|
28
|
+
if not channel.get("is_member", False):
|
|
29
|
+
self.slack_app.client.conversations_join(channel=channel_id)
|
|
30
|
+
self.log.info(f"Joined channel #{channel_id}")
|
|
31
|
+
|
|
32
|
+
except Exception as e:
|
|
33
|
+
self.log.error(f"Unhandled exception joining channel: {e}")
|
|
34
|
+
|
|
35
|
+
def handle(self, kobj: KnowledgeObject):
|
|
36
|
+
thread: AskCoreThread = kobj.rid
|
|
37
|
+
|
|
38
|
+
self.ensure_bot_in_channel(channel_id=thread.channel_id)
|
|
39
|
+
|
|
40
|
+
topic_group_names = []
|
|
41
|
+
for rid in self.cache.list_rids(rid_types=(AskTopicGroup,)):
|
|
42
|
+
bundle = self.cache.read(rid)
|
|
43
|
+
topic_group = bundle.validate_contents(TopicGroupModel)
|
|
44
|
+
topic_group_names.append(topic_group.name)
|
|
45
|
+
|
|
46
|
+
result = self.slack_app.client.chat_postMessage(
|
|
47
|
+
channel=thread.channel_id,
|
|
48
|
+
thread_ts=thread.ts,
|
|
49
|
+
blocks=[
|
|
50
|
+
{
|
|
51
|
+
"type": "rich_text",
|
|
52
|
+
"elements": [
|
|
53
|
+
{
|
|
54
|
+
"type": "rich_text_section",
|
|
55
|
+
"elements": [
|
|
56
|
+
{
|
|
57
|
+
"type": "text",
|
|
58
|
+
"text": "React to "
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"type": "text",
|
|
62
|
+
"text": "this message",
|
|
63
|
+
"style": {
|
|
64
|
+
"bold": True
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"type": "text",
|
|
69
|
+
"text": " to tag a topic group!"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "rich_text_list",
|
|
75
|
+
"style": "bullet",
|
|
76
|
+
"indent": 0,
|
|
77
|
+
"border": 0,
|
|
78
|
+
"elements": [
|
|
79
|
+
{
|
|
80
|
+
"type": "rich_text_section",
|
|
81
|
+
"elements": [
|
|
82
|
+
{
|
|
83
|
+
"type": "text",
|
|
84
|
+
"text": topic_group_name
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
} for topic_group_name in topic_group_names
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
slack_msg = SlackMessage(
|
|
95
|
+
team_id=thread.team_id,
|
|
96
|
+
channel_id=thread.channel_id,
|
|
97
|
+
ts=result["ts"]
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
thread_link = ThreadLinkModel(thread=thread, message=slack_msg)
|
|
101
|
+
self.kobj_queue.push(bundle=Bundle.generate(
|
|
102
|
+
rid=ThreadLink(slack_msg.team_id, slack_msg.channel_id, slack_msg.ts),
|
|
103
|
+
contents=thread_link.model_dump()
|
|
104
|
+
))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
@@ -7,6 +7,7 @@ from rid_lib.ext import Bundle
|
|
|
7
7
|
from rid_lib.types import SlackUser, SlackUserGroup
|
|
8
8
|
from slack_bolt import App
|
|
9
9
|
|
|
10
|
+
from ..config import AskTopicGroupsConfig
|
|
10
11
|
from ..models import TopicGroupModel
|
|
11
12
|
from ..rid_types import AskTopicGroup
|
|
12
13
|
|
|
@@ -15,6 +16,7 @@ from ..rid_types import AskTopicGroup
|
|
|
15
16
|
class SlackUserGroupHandler(KnowledgeHandler):
|
|
16
17
|
slack_app: App
|
|
17
18
|
cache: Cache
|
|
19
|
+
config: AskTopicGroupsConfig
|
|
18
20
|
kobj_queue: KobjQueue
|
|
19
21
|
|
|
20
22
|
handler_type = HandlerType.Network
|
|
@@ -27,7 +29,7 @@ class SlackUserGroupHandler(KnowledgeHandler):
|
|
|
27
29
|
ug_users: list[str] = kobj.contents["users"]
|
|
28
30
|
ug_description: str = kobj.contents["description"]
|
|
29
31
|
|
|
30
|
-
if not ug_handle.startswith(
|
|
32
|
+
if not ug_handle.startswith(self.config.slack.topic_group_prefix):
|
|
31
33
|
return
|
|
32
34
|
|
|
33
35
|
tg_rid = AskTopicGroup(ug_rid.team_id, ug_rid.subteam_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
from logging import Logger
|
|
3
|
-
import re
|
|
4
4
|
|
|
5
5
|
from slack_bolt import App, Respond
|
|
6
6
|
from slack_sdk import WebClient
|
|
@@ -21,15 +21,72 @@ class SlackCommandHandler:
|
|
|
21
21
|
def register_handlers(self):
|
|
22
22
|
self.slack_app.command("/join-topic")(self.topic_group_join)
|
|
23
23
|
self.slack_app.command("/leave-topic")(self.topic_group_leave)
|
|
24
|
+
self.slack_app.command("/my-topics")(self.topic_group_check)
|
|
24
25
|
|
|
25
|
-
def
|
|
26
|
+
def get_user_groups(self):
|
|
26
27
|
resp = self.slack_app.client.usergroups_list()
|
|
27
28
|
usergroups = resp["usergroups"]
|
|
29
|
+
return usergroups
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
def get_user_group(self, ug_id: str):
|
|
32
|
+
for usergroup in self.get_user_groups():
|
|
30
33
|
if usergroup["id"] == ug_id:
|
|
31
34
|
return usergroup
|
|
32
|
-
|
|
35
|
+
|
|
36
|
+
def topic_group_check(self, ack, respond: Respond, command):
|
|
37
|
+
ack()
|
|
38
|
+
|
|
39
|
+
user_id = command["user_id"]
|
|
40
|
+
|
|
41
|
+
member_usergroups = []
|
|
42
|
+
for usergroup in self.get_user_groups():
|
|
43
|
+
ug_name: str = usergroup["name"]
|
|
44
|
+
ug_handle: str = usergroup["handle"]
|
|
45
|
+
|
|
46
|
+
if not ug_handle.startswith(self.config.slack.topic_group_prefix):
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
ug_users: list[str] = self.slack_app.client.usergroups_users_list(
|
|
50
|
+
usergroup=usergroup["id"])['users']
|
|
51
|
+
|
|
52
|
+
if user_id in ug_users:
|
|
53
|
+
member_usergroups.append(ug_name)
|
|
54
|
+
|
|
55
|
+
if member_usergroups:
|
|
56
|
+
respond(blocks=[{
|
|
57
|
+
"type": "rich_text",
|
|
58
|
+
"elements": [
|
|
59
|
+
{
|
|
60
|
+
"type": "rich_text_section",
|
|
61
|
+
"elements": [
|
|
62
|
+
{
|
|
63
|
+
"type": "text",
|
|
64
|
+
"text": "You are currently a member of:"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "rich_text_list",
|
|
70
|
+
"style": "bullet",
|
|
71
|
+
"indent": 0,
|
|
72
|
+
"border": 0,
|
|
73
|
+
"elements": [
|
|
74
|
+
{
|
|
75
|
+
"type": "rich_text_section",
|
|
76
|
+
"elements": [
|
|
77
|
+
{
|
|
78
|
+
"type": "text",
|
|
79
|
+
"text": topic_group_name
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
} for topic_group_name in member_usergroups
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}])
|
|
87
|
+
else:
|
|
88
|
+
respond("You are not currently a member of any user groups")
|
|
89
|
+
|
|
33
90
|
def topic_group_join(self, ack, respond: Respond, command):
|
|
34
91
|
ack()
|
|
35
92
|
|
|
@@ -43,7 +100,7 @@ class SlackCommandHandler:
|
|
|
43
100
|
ug_name: str = usergroup["name"]
|
|
44
101
|
ug_handle: str = usergroup["handle"]
|
|
45
102
|
|
|
46
|
-
if ug_handle.startswith(
|
|
103
|
+
if ug_handle.startswith(self.config.slack.topic_group_prefix):
|
|
47
104
|
ug_users: list[str] = self.slack_app.client.usergroups_users_list(usergroup=ug_id)['users']
|
|
48
105
|
|
|
49
106
|
if user_id not in ug_users:
|
|
@@ -69,7 +126,7 @@ class SlackCommandHandler:
|
|
|
69
126
|
ug_name: str = usergroup["name"]
|
|
70
127
|
ug_handle: str = usergroup["handle"]
|
|
71
128
|
|
|
72
|
-
if ug_handle.startswith(
|
|
129
|
+
if ug_handle.startswith(self.config.slack.topic_group_prefix):
|
|
73
130
|
ug_users: list[str] = self.slack_app.client.usergroups_users_list(usergroup=ug_id)['users']
|
|
74
131
|
|
|
75
132
|
if user_id in ug_users:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: koi-net-ask-topic-groups-node
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Topic groups KOI-net node for the ask network application.
|
|
5
5
|
Author-email: Luke Miller <luke@metagov.org>
|
|
6
6
|
Project-URL: Homepage, https://github.com/metagov/koi-net-ask-topic-groups-node
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
from koi_net.components import KobjQueue
|
|
4
|
-
from koi_net.components.interfaces import KnowledgeHandler, HandlerType
|
|
5
|
-
from koi_net.protocol.knowledge_object import KnowledgeObject
|
|
6
|
-
from rid_lib.ext import Bundle
|
|
7
|
-
from rid_lib.types import SlackMessage
|
|
8
|
-
from slack_bolt import App
|
|
9
|
-
|
|
10
|
-
from ..models import ThreadLinkModel
|
|
11
|
-
from ..rid_types import AskCoreThread, ThreadLink
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@dataclass
|
|
15
|
-
class AskThreadHandler(KnowledgeHandler):
|
|
16
|
-
slack_app: App
|
|
17
|
-
kobj_queue: KobjQueue
|
|
18
|
-
|
|
19
|
-
handler_type = HandlerType.Network
|
|
20
|
-
rid_types = (AskCoreThread,)
|
|
21
|
-
|
|
22
|
-
def ensure_bot_in_channel(self, channel_id: str):
|
|
23
|
-
try:
|
|
24
|
-
result = self.slack_app.client.conversations_info(channel=channel_id)
|
|
25
|
-
channel = result["channel"]
|
|
26
|
-
|
|
27
|
-
if not channel.get("is_member", False):
|
|
28
|
-
self.slack_app.client.conversations_join(channel=channel_id)
|
|
29
|
-
self.log.info(f"Joined channel #{channel_id}")
|
|
30
|
-
|
|
31
|
-
except Exception as e:
|
|
32
|
-
self.log.error(f"Unhandled exception joining channel: {e}")
|
|
33
|
-
|
|
34
|
-
def handle(self, kobj: KnowledgeObject):
|
|
35
|
-
thread: AskCoreThread = kobj.rid
|
|
36
|
-
|
|
37
|
-
self.ensure_bot_in_channel(channel_id=thread.channel_id)
|
|
38
|
-
|
|
39
|
-
result = self.slack_app.client.chat_postMessage(
|
|
40
|
-
channel=thread.channel_id,
|
|
41
|
-
thread_ts=thread.ts,
|
|
42
|
-
blocks=[
|
|
43
|
-
{
|
|
44
|
-
"type": "section",
|
|
45
|
-
"text": {
|
|
46
|
-
"type": "mrkdwn",
|
|
47
|
-
"text": "React to this message to tag a topic group!"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
)
|
|
52
|
-
slack_msg = SlackMessage(
|
|
53
|
-
team_id=thread.team_id,
|
|
54
|
-
channel_id=thread.channel_id,
|
|
55
|
-
ts=result["ts"]
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
thread_link = ThreadLinkModel(thread=thread, message=slack_msg)
|
|
59
|
-
self.kobj_queue.push(bundle=Bundle.generate(
|
|
60
|
-
rid=ThreadLink(slack_msg.team_id, slack_msg.channel_id, slack_msg.ts),
|
|
61
|
-
contents=thread_link.model_dump()
|
|
62
|
-
))
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|