slk 0.1.0 → 0.2.0

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/README.md +5 -5
  4. data/bin/slk +3 -3
  5. data/lib/{slack_cli → slk}/api/activity.rb +10 -11
  6. data/lib/{slack_cli → slk}/api/bots.rb +5 -4
  7. data/lib/slk/api/client.rb +51 -0
  8. data/lib/{slack_cli → slk}/api/conversations.rb +14 -13
  9. data/lib/slk/api/dnd.rb +41 -0
  10. data/lib/{slack_cli → slk}/api/emoji.rb +4 -3
  11. data/lib/{slack_cli → slk}/api/threads.rb +13 -12
  12. data/lib/{slack_cli → slk}/api/usergroups.rb +2 -1
  13. data/lib/slk/api/users.rb +105 -0
  14. data/lib/slk/cli.rb +157 -0
  15. data/lib/slk/commands/activity.rb +152 -0
  16. data/lib/{slack_cli → slk}/commands/base.rb +67 -41
  17. data/lib/slk/commands/cache.rb +141 -0
  18. data/lib/slk/commands/catchup.rb +411 -0
  19. data/lib/slk/commands/config.rb +114 -0
  20. data/lib/slk/commands/dnd.rb +172 -0
  21. data/lib/slk/commands/emoji.rb +352 -0
  22. data/lib/slk/commands/help.rb +97 -0
  23. data/lib/slk/commands/messages.rb +299 -0
  24. data/lib/slk/commands/presence.rb +109 -0
  25. data/lib/slk/commands/preset.rb +231 -0
  26. data/lib/slk/commands/status.rb +223 -0
  27. data/lib/slk/commands/thread.rb +72 -0
  28. data/lib/slk/commands/unread.rb +305 -0
  29. data/lib/slk/commands/workspaces.rb +168 -0
  30. data/lib/slk/formatters/activity_formatter.rb +148 -0
  31. data/lib/slk/formatters/attachment_formatter.rb +65 -0
  32. data/lib/slk/formatters/block_formatter.rb +57 -0
  33. data/lib/{slack_cli → slk}/formatters/duration_formatter.rb +6 -5
  34. data/lib/slk/formatters/emoji_replacer.rb +141 -0
  35. data/lib/slk/formatters/json_message_formatter.rb +95 -0
  36. data/lib/slk/formatters/mention_replacer.rb +158 -0
  37. data/lib/slk/formatters/message_formatter.rb +174 -0
  38. data/lib/{slack_cli → slk}/formatters/output.rb +7 -6
  39. data/lib/slk/formatters/reaction_formatter.rb +87 -0
  40. data/lib/{slack_cli → slk}/models/channel.rb +12 -10
  41. data/lib/slk/models/duration.rb +94 -0
  42. data/lib/slk/models/message.rb +242 -0
  43. data/lib/slk/models/preset.rb +78 -0
  44. data/lib/{slack_cli → slk}/models/reaction.rb +6 -6
  45. data/lib/{slack_cli → slk}/models/status.rb +6 -6
  46. data/lib/slk/models/user.rb +55 -0
  47. data/lib/slk/models/workspace.rb +54 -0
  48. data/lib/{slack_cli → slk}/runner.rb +22 -19
  49. data/lib/slk/services/activity_enricher.rb +124 -0
  50. data/lib/slk/services/api_client.rb +145 -0
  51. data/lib/{slack_cli → slk}/services/cache_store.rb +20 -17
  52. data/lib/{slack_cli → slk}/services/configuration.rb +9 -8
  53. data/lib/slk/services/emoji_downloader.rb +103 -0
  54. data/lib/slk/services/emoji_searcher.rb +72 -0
  55. data/lib/{slack_cli → slk}/services/encryption.rb +11 -14
  56. data/lib/slk/services/gemoji_sync.rb +97 -0
  57. data/lib/{slack_cli → slk}/services/preset_store.rb +34 -33
  58. data/lib/slk/services/reaction_enricher.rb +82 -0
  59. data/lib/slk/services/setup_wizard.rb +131 -0
  60. data/lib/slk/services/target_resolver.rb +108 -0
  61. data/lib/{slack_cli → slk}/services/token_store.rb +11 -10
  62. data/lib/slk/services/unread_marker.rb +101 -0
  63. data/lib/{slack_cli → slk}/support/error_logger.rb +2 -1
  64. data/lib/{slack_cli → slk}/support/help_formatter.rb +36 -44
  65. data/lib/{slack_cli → slk}/support/inline_images.rb +28 -19
  66. data/lib/slk/support/interactive_prompt.rb +29 -0
  67. data/lib/{slack_cli → slk}/support/slack_url_parser.rb +15 -17
  68. data/lib/slk/support/text_wrapper.rb +57 -0
  69. data/lib/slk/support/user_resolver.rb +141 -0
  70. data/lib/{slack_cli → slk}/support/xdg_paths.rb +6 -5
  71. data/lib/slk/version.rb +5 -0
  72. data/lib/slk.rb +112 -0
  73. metadata +80 -59
  74. data/lib/slack_cli/api/client.rb +0 -49
  75. data/lib/slack_cli/api/dnd.rb +0 -40
  76. data/lib/slack_cli/api/users.rb +0 -101
  77. data/lib/slack_cli/cli.rb +0 -118
  78. data/lib/slack_cli/commands/activity.rb +0 -292
  79. data/lib/slack_cli/commands/cache.rb +0 -116
  80. data/lib/slack_cli/commands/catchup.rb +0 -484
  81. data/lib/slack_cli/commands/config.rb +0 -159
  82. data/lib/slack_cli/commands/dnd.rb +0 -143
  83. data/lib/slack_cli/commands/emoji.rb +0 -412
  84. data/lib/slack_cli/commands/help.rb +0 -76
  85. data/lib/slack_cli/commands/messages.rb +0 -317
  86. data/lib/slack_cli/commands/presence.rb +0 -107
  87. data/lib/slack_cli/commands/preset.rb +0 -239
  88. data/lib/slack_cli/commands/status.rb +0 -194
  89. data/lib/slack_cli/commands/thread.rb +0 -62
  90. data/lib/slack_cli/commands/unread.rb +0 -312
  91. data/lib/slack_cli/commands/workspaces.rb +0 -151
  92. data/lib/slack_cli/formatters/emoji_replacer.rb +0 -143
  93. data/lib/slack_cli/formatters/mention_replacer.rb +0 -154
  94. data/lib/slack_cli/formatters/message_formatter.rb +0 -429
  95. data/lib/slack_cli/models/duration.rb +0 -85
  96. data/lib/slack_cli/models/message.rb +0 -217
  97. data/lib/slack_cli/models/preset.rb +0 -73
  98. data/lib/slack_cli/models/user.rb +0 -56
  99. data/lib/slack_cli/models/workspace.rb +0 -52
  100. data/lib/slack_cli/services/api_client.rb +0 -149
  101. data/lib/slack_cli/services/reaction_enricher.rb +0 -87
  102. data/lib/slack_cli/support/user_resolver.rb +0 -114
  103. data/lib/slack_cli/version.rb +0 -5
  104. data/lib/slack_cli.rb +0 -91
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Boehs
@@ -22,67 +22,88 @@ files:
22
22
  - LICENSE
23
23
  - README.md
24
24
  - bin/slk
25
- - lib/slack_cli.rb
26
- - lib/slack_cli/api/activity.rb
27
- - lib/slack_cli/api/bots.rb
28
- - lib/slack_cli/api/client.rb
29
- - lib/slack_cli/api/conversations.rb
30
- - lib/slack_cli/api/dnd.rb
31
- - lib/slack_cli/api/emoji.rb
32
- - lib/slack_cli/api/threads.rb
33
- - lib/slack_cli/api/usergroups.rb
34
- - lib/slack_cli/api/users.rb
35
- - lib/slack_cli/cli.rb
36
- - lib/slack_cli/commands/activity.rb
37
- - lib/slack_cli/commands/base.rb
38
- - lib/slack_cli/commands/cache.rb
39
- - lib/slack_cli/commands/catchup.rb
40
- - lib/slack_cli/commands/config.rb
41
- - lib/slack_cli/commands/dnd.rb
42
- - lib/slack_cli/commands/emoji.rb
43
- - lib/slack_cli/commands/help.rb
44
- - lib/slack_cli/commands/messages.rb
45
- - lib/slack_cli/commands/presence.rb
46
- - lib/slack_cli/commands/preset.rb
47
- - lib/slack_cli/commands/status.rb
48
- - lib/slack_cli/commands/thread.rb
49
- - lib/slack_cli/commands/unread.rb
50
- - lib/slack_cli/commands/workspaces.rb
51
- - lib/slack_cli/formatters/duration_formatter.rb
52
- - lib/slack_cli/formatters/emoji_replacer.rb
53
- - lib/slack_cli/formatters/mention_replacer.rb
54
- - lib/slack_cli/formatters/message_formatter.rb
55
- - lib/slack_cli/formatters/output.rb
56
- - lib/slack_cli/models/channel.rb
57
- - lib/slack_cli/models/duration.rb
58
- - lib/slack_cli/models/message.rb
59
- - lib/slack_cli/models/preset.rb
60
- - lib/slack_cli/models/reaction.rb
61
- - lib/slack_cli/models/status.rb
62
- - lib/slack_cli/models/user.rb
63
- - lib/slack_cli/models/workspace.rb
64
- - lib/slack_cli/runner.rb
65
- - lib/slack_cli/services/api_client.rb
66
- - lib/slack_cli/services/cache_store.rb
67
- - lib/slack_cli/services/configuration.rb
68
- - lib/slack_cli/services/encryption.rb
69
- - lib/slack_cli/services/preset_store.rb
70
- - lib/slack_cli/services/reaction_enricher.rb
71
- - lib/slack_cli/services/token_store.rb
72
- - lib/slack_cli/support/error_logger.rb
73
- - lib/slack_cli/support/help_formatter.rb
74
- - lib/slack_cli/support/inline_images.rb
75
- - lib/slack_cli/support/slack_url_parser.rb
76
- - lib/slack_cli/support/user_resolver.rb
77
- - lib/slack_cli/support/xdg_paths.rb
78
- - lib/slack_cli/version.rb
79
- homepage: https://github.com/ericboehs/slack-cli
25
+ - lib/slk.rb
26
+ - lib/slk/api/activity.rb
27
+ - lib/slk/api/bots.rb
28
+ - lib/slk/api/client.rb
29
+ - lib/slk/api/conversations.rb
30
+ - lib/slk/api/dnd.rb
31
+ - lib/slk/api/emoji.rb
32
+ - lib/slk/api/threads.rb
33
+ - lib/slk/api/usergroups.rb
34
+ - lib/slk/api/users.rb
35
+ - lib/slk/cli.rb
36
+ - lib/slk/commands/activity.rb
37
+ - lib/slk/commands/base.rb
38
+ - lib/slk/commands/cache.rb
39
+ - lib/slk/commands/catchup.rb
40
+ - lib/slk/commands/config.rb
41
+ - lib/slk/commands/dnd.rb
42
+ - lib/slk/commands/emoji.rb
43
+ - lib/slk/commands/help.rb
44
+ - lib/slk/commands/messages.rb
45
+ - lib/slk/commands/presence.rb
46
+ - lib/slk/commands/preset.rb
47
+ - lib/slk/commands/status.rb
48
+ - lib/slk/commands/thread.rb
49
+ - lib/slk/commands/unread.rb
50
+ - lib/slk/commands/workspaces.rb
51
+ - lib/slk/formatters/activity_formatter.rb
52
+ - lib/slk/formatters/attachment_formatter.rb
53
+ - lib/slk/formatters/block_formatter.rb
54
+ - lib/slk/formatters/duration_formatter.rb
55
+ - lib/slk/formatters/emoji_replacer.rb
56
+ - lib/slk/formatters/json_message_formatter.rb
57
+ - lib/slk/formatters/mention_replacer.rb
58
+ - lib/slk/formatters/message_formatter.rb
59
+ - lib/slk/formatters/output.rb
60
+ - lib/slk/formatters/reaction_formatter.rb
61
+ - lib/slk/models/channel.rb
62
+ - lib/slk/models/duration.rb
63
+ - lib/slk/models/message.rb
64
+ - lib/slk/models/preset.rb
65
+ - lib/slk/models/reaction.rb
66
+ - lib/slk/models/status.rb
67
+ - lib/slk/models/user.rb
68
+ - lib/slk/models/workspace.rb
69
+ - lib/slk/runner.rb
70
+ - lib/slk/services/activity_enricher.rb
71
+ - lib/slk/services/api_client.rb
72
+ - lib/slk/services/cache_store.rb
73
+ - lib/slk/services/configuration.rb
74
+ - lib/slk/services/emoji_downloader.rb
75
+ - lib/slk/services/emoji_searcher.rb
76
+ - lib/slk/services/encryption.rb
77
+ - lib/slk/services/gemoji_sync.rb
78
+ - lib/slk/services/preset_store.rb
79
+ - lib/slk/services/reaction_enricher.rb
80
+ - lib/slk/services/setup_wizard.rb
81
+ - lib/slk/services/target_resolver.rb
82
+ - lib/slk/services/token_store.rb
83
+ - lib/slk/services/unread_marker.rb
84
+ - lib/slk/support/error_logger.rb
85
+ - lib/slk/support/help_formatter.rb
86
+ - lib/slk/support/inline_images.rb
87
+ - lib/slk/support/interactive_prompt.rb
88
+ - lib/slk/support/slack_url_parser.rb
89
+ - lib/slk/support/text_wrapper.rb
90
+ - lib/slk/support/user_resolver.rb
91
+ - lib/slk/support/xdg_paths.rb
92
+ - lib/slk/version.rb
93
+ homepage: https://github.com/ericboehs/slk
80
94
  licenses:
81
95
  - MIT
82
96
  metadata:
83
- homepage_uri: https://github.com/ericboehs/slack-cli
84
- source_code_uri: https://github.com/ericboehs/slack-cli
85
- changelog_uri: https://github.com/ericboehs/slack-cli/blob/master/CHANGELOG.md
97
+ homepage_uri: https://github.com/ericboehs/slk
98
+ source_code_uri: https://github.com/ericboehs/slk
99
+ changelog_uri: https://github.com/ericboehs/slk/blob/master/CHANGELOG.md
100
+ rubygems_mfa_required: 'true'
101
+ post_install_message: |
102
+ slk 0.2.0: Config directory changed from slack-cli to slk
103
+
104
+ If upgrading from 0.1.x, migrate your config:
105
+ mv ${XDG_CONFIG_HOME:-~/.config}/slack-cli ${XDG_CONFIG_HOME:-~/.config}/slk
106
+ mv ${XDG_CACHE_HOME:-~/.cache}/slack-cli ${XDG_CACHE_HOME:-~/.cache}/slk
86
107
  rdoc_options: []
87
108
  require_paths:
88
109
  - lib
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SlackCli
4
- module Api
5
- class Client
6
- def initialize(api_client, workspace)
7
- @api = api_client
8
- @workspace = workspace
9
- end
10
-
11
- def counts
12
- @api.post(@workspace, "client.counts")
13
- end
14
-
15
- def auth_test
16
- @api.post(@workspace, "auth.test")
17
- end
18
-
19
- def team_id
20
- @team_id ||= auth_test["team_id"]
21
- end
22
-
23
- def unread_channels
24
- response = counts
25
- channels = response.dig("channels") || []
26
-
27
- channels.select { |ch| (ch["mention_count"] || 0) > 0 || ch["has_unreads"] }
28
- end
29
-
30
- def unread_dms
31
- response = counts
32
- dms = response.dig("ims") || []
33
- mpims = response.dig("mpims") || []
34
-
35
- (dms + mpims).select { |dm| (dm["mention_count"] || 0) > 0 || dm["has_unreads"] }
36
- end
37
-
38
- def total_unread_count
39
- response = counts
40
-
41
- channel_count = (response.dig("channels") || []).sum { |c| c["mention_count"] || 0 }
42
- dm_count = (response.dig("ims") || []).sum { |d| d["mention_count"] || 0 }
43
- mpim_count = (response.dig("mpims") || []).sum { |m| m["mention_count"] || 0 }
44
-
45
- channel_count + dm_count + mpim_count
46
- end
47
- end
48
- end
49
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SlackCli
4
- module Api
5
- class Dnd
6
- def initialize(api_client, workspace)
7
- @api = api_client
8
- @workspace = workspace
9
- end
10
-
11
- def info
12
- @api.post(@workspace, "dnd.info")
13
- end
14
-
15
- def set_snooze(duration)
16
- minutes = duration.to_minutes
17
- @api.post(@workspace, "dnd.setSnooze", { num_minutes: minutes })
18
- end
19
-
20
- def end_snooze
21
- @api.post(@workspace, "dnd.endSnooze")
22
- end
23
-
24
- def snoozing?
25
- info["snooze_enabled"] == true
26
- end
27
-
28
- def snooze_remaining
29
- data = info
30
- return nil unless data["snooze_enabled"]
31
-
32
- endtime = data["snooze_endtime"]
33
- return nil unless endtime
34
-
35
- remaining = endtime - Time.now.to_i
36
- remaining > 0 ? Models::Duration.new(seconds: remaining) : nil
37
- end
38
- end
39
- end
40
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SlackCli
4
- module Api
5
- class Users
6
- def initialize(api_client, workspace, on_debug: nil)
7
- @api = api_client
8
- @workspace = workspace
9
- @on_debug = on_debug
10
- end
11
-
12
- def get_profile
13
- response = @api.post(@workspace, "users.profile.get")
14
- response["profile"]
15
- end
16
-
17
- def get_status
18
- profile = get_profile
19
- Models::Status.new(
20
- text: profile["status_text"] || "",
21
- emoji: profile["status_emoji"] || "",
22
- expiration: profile["status_expiration"] || 0
23
- )
24
- end
25
-
26
- def set_status(text:, emoji: nil, duration: nil)
27
- expiration = duration&.to_expiration || 0
28
-
29
- @api.post(@workspace, "users.profile.set", {
30
- profile: {
31
- status_text: text,
32
- status_emoji: emoji || "",
33
- status_expiration: expiration
34
- }
35
- })
36
- end
37
-
38
- def clear_status
39
- set_status(text: "", emoji: "", duration: nil)
40
- end
41
-
42
- def get_presence
43
- response = @api.post(@workspace, "users.getPresence")
44
- {
45
- presence: response["presence"],
46
- manual_away: response["manual_away"],
47
- online: response["online"]
48
- }
49
- end
50
-
51
- def set_presence(presence)
52
- @api.post(@workspace, "users.setPresence", { presence: presence })
53
- end
54
-
55
- def list(cursor: nil, limit: 1000)
56
- params = { limit: limit }
57
- params[:cursor] = cursor if cursor
58
- @api.post(@workspace, "users.list", params)
59
- end
60
-
61
- def info(user_id)
62
- @api.post_form(@workspace, "users.info", { user: user_id })
63
- end
64
-
65
- def get_prefs
66
- @api.post(@workspace, "users.prefs.get")
67
- end
68
-
69
- def muted_channels
70
- prefs = get_prefs
71
-
72
- # First try the legacy muted_channels format (comma-separated string)
73
- muted = prefs.dig("prefs", "muted_channels")
74
- if muted.is_a?(String) && !muted.empty?
75
- return muted.split(",").reject(&:empty?)
76
- end
77
-
78
- # New format: muted channels are in all_notifications_prefs JSON string
79
- # Structure: {"channels": {"C123": {"muted": true}, ...}}
80
- notifications_prefs = prefs.dig("prefs", "all_notifications_prefs")
81
- if notifications_prefs.is_a?(String) && !notifications_prefs.empty?
82
- begin
83
- parsed = JSON.parse(notifications_prefs)
84
- channels = parsed["channels"] || {}
85
- return channels.select { |_id, opts| opts["muted"] == true }.keys
86
- rescue JSON::ParserError => e
87
- @on_debug&.call("Failed to parse notification prefs: #{e.message}")
88
- end
89
- end
90
-
91
- []
92
- end
93
-
94
- def conversations(cursor: nil, limit: 1000)
95
- params = { limit: limit, types: "public_channel,private_channel,mpim,im" }
96
- params[:cursor] = cursor if cursor
97
- @api.post_form(@workspace, "users.conversations", params)
98
- end
99
- end
100
- end
101
- end
data/lib/slack_cli/cli.rb DELETED
@@ -1,118 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SlackCli
4
- class CLI
5
- COMMANDS = {
6
- "status" => Commands::Status,
7
- "presence" => Commands::Presence,
8
- "dnd" => Commands::Dnd,
9
- "messages" => Commands::Messages,
10
- "thread" => Commands::Thread,
11
- "unread" => Commands::Unread,
12
- "catchup" => Commands::Catchup,
13
- "activity" => Commands::Activity,
14
- "preset" => Commands::Preset,
15
- "workspaces" => Commands::Workspaces,
16
- "cache" => Commands::Cache,
17
- "emoji" => Commands::Emoji,
18
- "config" => Commands::Config,
19
- "help" => Commands::Help
20
- }.freeze
21
-
22
- def initialize(argv, output: nil)
23
- @argv = argv.dup
24
- @output = output || Formatters::Output.new
25
- end
26
-
27
- def run
28
- command_name, *args = @argv
29
-
30
- # Handle version flags
31
- if command_name.nil? || command_name == "--help" || command_name == "-h"
32
- return run_command("help", [])
33
- end
34
-
35
- if command_name == "--version" || command_name == "-V" || command_name == "version"
36
- @output.puts "slk v#{VERSION}"
37
- return 0
38
- end
39
-
40
- # Look up command
41
- if (command_class = COMMANDS[command_name])
42
- run_command(command_name, args)
43
- elsif preset_exists?(command_name)
44
- # Treat as preset shortcut
45
- run_command("preset", [command_name] + args)
46
- else
47
- @output.error("Unknown command: #{command_name}")
48
- @output.puts
49
- @output.puts "Run 'slk help' for available commands."
50
- 1
51
- end
52
- rescue ConfigError => e
53
- @output.error(e.message)
54
- log_error(e)
55
- 1
56
- rescue EncryptionError => e
57
- @output.error("Encryption error: #{e.message}")
58
- log_error(e)
59
- 1
60
- rescue ApiError => e
61
- @output.error("API error: #{e.message}")
62
- log_error(e)
63
- 1
64
- rescue Interrupt
65
- @output.puts
66
- @output.puts "Interrupted."
67
- 130
68
- rescue StandardError => e
69
- @output.error("Unexpected error: #{e.message}")
70
- log_path = log_error(e)
71
- @output.puts "Details logged to: #{log_path}" if log_path
72
- 1
73
- end
74
-
75
- private
76
-
77
- def run_command(name, args)
78
- command_class = COMMANDS[name]
79
- return 1 unless command_class
80
-
81
- verbose = args.include?("-v") || args.include?("--verbose")
82
-
83
- # Create output with verbose flag
84
- output = Formatters::Output.new(verbose: verbose)
85
- runner = Runner.new(output: output)
86
-
87
- # Set up API call logging if verbose
88
- if verbose
89
- runner.api_client.on_request = ->(method, count) {
90
- output.debug("[API ##{count}] #{method}")
91
- }
92
- end
93
-
94
- command = command_class.new(args, runner: runner)
95
- result = command.execute
96
-
97
- # Show API call count if verbose
98
- if verbose && runner.api_client.call_count > 0
99
- output.debug("Total API calls: #{runner.api_client.call_count}")
100
- end
101
-
102
- result
103
- ensure
104
- # Clean up HTTP connections
105
- runner&.api_client&.close
106
- end
107
-
108
- def preset_exists?(name)
109
- # PresetStore handles JSON parse errors internally via on_warning callback
110
- # ConfigError should propagate as it indicates a real configuration problem
111
- Services::PresetStore.new.exists?(name)
112
- end
113
-
114
- def log_error(error)
115
- Support::ErrorLogger.log(error)
116
- end
117
- end
118
- end