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.
Files changed (23) hide show
  1. {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/PKG-INFO +1 -1
  2. {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/pyproject.toml +1 -1
  3. {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
  4. koi_net_ask_topic_groups_node-0.2.0/src/koi_net_ask_topic_groups_node/knowledge_handlers/ask_thread_handler.py +107 -0
  5. {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
  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/slack_command_handler.py +63 -6
  7. {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
  8. koi_net_ask_topic_groups_node-0.1.0/src/koi_net_ask_topic_groups_node/knowledge_handlers/ask_thread_handler.py +0 -65
  9. {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/README.md +0 -0
  10. {koi_net_ask_topic_groups_node-0.1.0 → koi_net_ask_topic_groups_node-0.2.0}/setup.cfg +0 -0
  11. {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
  12. {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
  13. {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
  14. {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
  15. {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
  16. {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
  17. {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
  18. {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
  19. {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
  20. {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
  21. {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
  22. {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
  23. {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.1.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,6 +1,6 @@
1
1
  [project]
2
2
  name = "koi-net-ask-topic-groups-node"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "Topic groups KOI-net node for the ask network application."
5
5
  authors = [
6
6
  {name = "Luke Miller", email = "luke@metagov.org"}
@@ -21,6 +21,7 @@ class SlackEnvConfig(EnvConfig):
21
21
 
22
22
  class SlackConfig(BaseModel):
23
23
  team_id: str | None = None
24
+ topic_group_prefix: str = "tg-"
24
25
 
25
26
  class AskTopicGroupsConfig(FullNodeConfig):
26
27
  env: SlackEnvConfig = Field(default_factory=SlackEnvConfig)
@@ -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("tg-"):
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 get_user_group(self, ug_id: str):
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
- for usergroup in usergroups:
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("tg-"):
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("tg-"):
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.1.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
-