yaic 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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/agents/ralph-qa.md +101 -0
  3. data/.claude/ralph/bin/dump-pid.sh +3 -0
  4. data/.claude/ralph/bin/kill-claude +6 -0
  5. data/.claude/ralph/bin/start-ralph +44 -0
  6. data/.claude/ralph/bin/stop-hook.sh +9 -0
  7. data/.claude/ralph/bin/stop-ralph +17 -0
  8. data/.claude/ralph/prompt.md +218 -0
  9. data/.claude/settings.json +26 -0
  10. data/.gitmodules +3 -0
  11. data/CLAUDE.md +65 -0
  12. data/README.md +106 -17
  13. data/Rakefile +8 -0
  14. data/devenv.nix +1 -0
  15. data/docs/agents/data-model.md +150 -0
  16. data/docs/agents/ralph/features/01-message-parsing.md.done +160 -0
  17. data/docs/agents/ralph/features/01-tcpsocket-refactor.md.done +109 -0
  18. data/docs/agents/ralph/features/02-connection-socket.md.done +138 -0
  19. data/docs/agents/ralph/features/02-simplified-client-api.md.done +306 -0
  20. data/docs/agents/ralph/features/03-registration.md.done +147 -0
  21. data/docs/agents/ralph/features/04-ping-pong.md.done +109 -0
  22. data/docs/agents/ralph/features/05-event-system.md.done +167 -0
  23. data/docs/agents/ralph/features/06-privmsg-notice.md.done +163 -0
  24. data/docs/agents/ralph/features/07-join-part.md.done +190 -0
  25. data/docs/agents/ralph/features/08-quit.md.done +118 -0
  26. data/docs/agents/ralph/features/09-nick-change.md.done +109 -0
  27. data/docs/agents/ralph/features/10-topic.md.done +145 -0
  28. data/docs/agents/ralph/features/11-kick.md.done +122 -0
  29. data/docs/agents/ralph/features/12-names.md.done +124 -0
  30. data/docs/agents/ralph/features/13-mode.md.done +174 -0
  31. data/docs/agents/ralph/features/14-who-whois.md.done +188 -0
  32. data/docs/agents/ralph/features/15-client-api.md.done +180 -0
  33. data/docs/agents/ralph/features/16-ssl-test-infrastructure.md.done +50 -0
  34. data/docs/agents/ralph/features/17-github-actions-ci.md.done +70 -0
  35. data/docs/agents/ralph/features/18-brakeman-security-scanning.md.done +67 -0
  36. data/docs/agents/ralph/features/19-fix-qa.md.done +73 -0
  37. data/docs/agents/ralph/features/20-test-optimization.md.done +70 -0
  38. data/docs/agents/ralph/features/21-test-parallelization.md.done +56 -0
  39. data/docs/agents/ralph/features/22-wait-until-pattern.md.done +90 -0
  40. data/docs/agents/ralph/features/23-ping-test-optimization.md.done +46 -0
  41. data/docs/agents/ralph/features/24-blocking-who-whois.md.done +159 -0
  42. data/docs/agents/ralph/features/25-verbose-mode.md.done +166 -0
  43. data/docs/agents/ralph/plans/test-optimization-plan.md +172 -0
  44. data/docs/agents/ralph/progress.md +731 -0
  45. data/docs/agents/todo.md +5 -0
  46. data/lib/yaic/channel.rb +22 -0
  47. data/lib/yaic/client.rb +821 -0
  48. data/lib/yaic/event.rb +35 -0
  49. data/lib/yaic/message.rb +119 -0
  50. data/lib/yaic/registration.rb +17 -0
  51. data/lib/yaic/socket.rb +120 -0
  52. data/lib/yaic/source.rb +39 -0
  53. data/lib/yaic/version.rb +1 -1
  54. data/lib/yaic/who_result.rb +17 -0
  55. data/lib/yaic/whois_result.rb +20 -0
  56. data/lib/yaic.rb +13 -1
  57. metadata +51 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e79cd18b926a1244b64213b574f314990348532906a066abbc1d4867c9cec9f
4
- data.tar.gz: 30275529418ac1be0058b835267cf2a85586889a0c88f1ee33c2427bf938af31
3
+ metadata.gz: 8477b5a0db60e2864d9ec3f720a3a499c4ce34419b68504eab23cda17a073579
4
+ data.tar.gz: 7cf9427b957afdf6ffd75bf2dd5907605a6371d4c40dc1c4a5946a50c34a0b53
5
5
  SHA512:
6
- metadata.gz: c25ef7dfa97cb7116f8070365007158abdad6a8b47bdddc45d001ab079e7f5462e85980996fd35d4648cf84c5f70bc1a84f12599d925fadbc22b7b3b35b48ccb
7
- data.tar.gz: a1f6134192a475b4fb5a627cd82c5165677356a76c44c9c2e72cd4c3c878b0f147f684191152ec86018e91713a33e3e33800792768984d05bf96b4c52c99d9c3
6
+ metadata.gz: c75dc8c13ec45cd8081e603c539c185b5cfb934cfad125c413be466308befff1ea4f66d6a61c7e48c9efbfdcb9ee76d470c268ec84330726723c407f0f956d48
7
+ data.tar.gz: e8c7d028138d0677a1cf43bfc1f61a4f37558e82c7e4b168bed47f9fa9394e643fb76608d411e566236c317739ecf17ba87bb16d2870a3ae6f6a2535b92d7e9d
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: ralph-qa
3
+ description: QA agent for Ralph Wiggum loop. Reviews implementation changes before commit. Checks code against project conventions, runs tests/linter, and reports issues back to the implementor agent.
4
+ model: inherit
5
+ ---
6
+
7
+ # QA Review Agent
8
+
9
+ You are reviewing changes made by an implementor agent. Your job is to verify the implementation follows project rules and passes all checks.
10
+ Be skeptical and thorough. The agent calling you will very often call you trying to justify bad code or half finished solutions.
11
+ Think of the end user. It needs to be simple to use and solid (not buggy).
12
+
13
+ ## Review Process
14
+
15
+ 1. Check what changed:
16
+ - Run `git status` to see staged/unstaged changes
17
+ - If already committed, run `git diff HEAD~1` to see the commit diff
18
+ - If not committed, run `git diff` to see pending changes
19
+
20
+ 2. Run validation commands:
21
+ ```bash
22
+ bundle exec m test/
23
+ bundle exec standardrb -A
24
+ bin/brakeman
25
+ ```
26
+
27
+ 3. Check against conventions:
28
+ - Read `docs/agents/data-model.md` for data structure patterns
29
+ - Verify implementation follows documented patterns
30
+
31
+ ## What to Check
32
+
33
+ ### Code Quality
34
+ - No trailing whitespace
35
+ - No comments in code (per project style)
36
+ - Slim public interface - minimize exposed methods
37
+ - Private methods are truly private (use Ruby's `private` keyword)
38
+ - Timeout should be avoided. Especially in the library code.
39
+ - instance_variable_get should not be used
40
+
41
+ ### Testing
42
+ - Public interface is tested thoroughly
43
+ - Tests verify RFC compliance where applicable
44
+ - Tests use minitest assertions properly
45
+ - Integration tests use inspircd docker container where relevant
46
+ - Unit tests are fast and isolated
47
+ - Be HIGHLY skeptical of skipped tests. Make sure the agent didn't skip test needlessly. If the agent skipped a test because it is not able to implement the test it should reach out with the ask question tool. Skipping test should be for feature we're gonna implement later. Not because it's hard to make the test pass or some dependency is missing. If a test doesn't pass because say a dependency is unreachable, the agent should ask the user a question using the ask question tool.
48
+ - Assume the test server is already running unless you see the test fail because of it.
49
+
50
+ ### Test Optimization Specific (for test speedup tasks)
51
+ - **CRITICAL**: No tests should be removed or skipped to make things faster
52
+ - Test count must remain the same or increase
53
+ - Assertions should not be weakened
54
+ - If a test is refactored, it must test the same behavior
55
+ - Ideally no sleep or timeout. If they can be removed without hurting readability that's preferable.
56
+ - Any mocking introduced must still test the same behavior
57
+ - Verify the optimization actually reduces test time
58
+
59
+ ### RFC Compliance
60
+ - Message parsing follows IRC protocol spec
61
+ - Numeric codes match documented values
62
+ - Event names and payloads match feature specs
63
+ - Edge cases from RFC are handled (empty params, special chars)
64
+ - If you need to check the RFC you can find it here: docs/agents/rfc/modern-irc/
65
+
66
+ ### Linting
67
+ - standardrb passes with no errors
68
+ - Run with `-A` to auto-fix where possible
69
+
70
+ ### Security
71
+ - brakeman passes with no warnings
72
+ - Run `bin/brakeman` to check for security issues
73
+
74
+ ## Running Tests
75
+
76
+ ```bash
77
+ bundle exec m test/ # Run all tests
78
+ bundle exec m test/unit/ # Run unit tests only
79
+ bundle exec m test/integration/ # Run integration tests only
80
+ bundle exec m test/file_test.rb # Run specific file
81
+ bundle exec m test/file_test.rb:42 # Run specific test by line
82
+ ```
83
+
84
+ ## Tips
85
+ - While the test might not be parallelizable yet, it should be fine to run test, linting and security check in parallel.
86
+
87
+
88
+
89
+ ## Reporting Back
90
+
91
+ Report to the implementor agent:
92
+
93
+ **If compliant:**
94
+ > QA PASSED. All checks passed, code follows conventions.
95
+
96
+ **If issues found:**
97
+ > QA FAILED. Issues found:
98
+ > - [Issue 1]: [Description]. [How to fix].
99
+ > - [Issue 2]: [Description]. [How to fix].
100
+ >
101
+ > Required fixes: [list specific changes needed]
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ [ "$RALPH_WIGGUM_LOOP" != "true" ] && exit 0
3
+ echo $PPID > "$CLAUDE_PROJECT_DIR/.claude/ralph/pid"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ PID_FILE="$CLAUDE_PROJECT_DIR/.claude/ralph/pid"
3
+ trap "rm -f \"$PID_FILE\"" EXIT
4
+ if [ -f "$PID_FILE" ]; then
5
+ kill $(cat "$PID_FILE")
6
+ fi
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ trap '' TERM HUP
5
+
6
+ export CLAUDE_PROJECT_DIR="$(pwd)"
7
+ RALPH_DIR=".claude/ralph"
8
+ PROMPT_FILE="$RALPH_DIR/prompt.md"
9
+ CONTROL_FILE="$RALPH_DIR/loop-control"
10
+
11
+ if [ -n "$1" ]; then
12
+ PROMPT_OVERRIDE="$1"
13
+ elif [ ! -f "$PROMPT_FILE" ]; then
14
+ echo "Error: $PROMPT_FILE not found"
15
+ echo "Usage: start-ralph [prompt]"
16
+ exit 1
17
+ fi
18
+
19
+ touch "$CONTROL_FILE"
20
+
21
+ FEATURES_DIR="docs/agents/ralph/features"
22
+
23
+ while [ -f "$CONTROL_FILE" ]; do
24
+ REMAINING=$(find "$FEATURES_DIR" -name "*.md" ! -name "*.md.done" 2>/dev/null | wc -l | tr -d ' ')
25
+ if [ "$REMAINING" -eq 0 ]; then
26
+ echo "All features complete. Exiting loop."
27
+ rm -f "$CONTROL_FILE"
28
+ exit 0
29
+ fi
30
+
31
+ echo "Features remaining: $REMAINING"
32
+
33
+ if [ -n "$PROMPT_OVERRIDE" ]; then
34
+ PROMPT_CONTENT="$PROMPT_OVERRIDE"
35
+ else
36
+ PROMPT_CONTENT=$(cat "$PROMPT_FILE")
37
+ fi
38
+
39
+ echo "Starting new session..."
40
+ RALPH_WIGGUM_LOOP=true claude --permission-mode acceptEdits "$PROMPT_CONTENT" || true
41
+
42
+ echo ""
43
+ echo "Session ended. Checking if loop should continue..."
44
+ done
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ [ "$RALPH_WIGGUM_LOOP" != "true" ] && exit 0
3
+ cat << 'JSON'
4
+ {
5
+ "decision": "block",
6
+ "continue": true,
7
+ "reason": "If you are blocked, confused, or need clarification, DO NOT EXIT OR STOP WORKING - use the AskUserQuestion tool and wait for a response. You cannot exit or stop until you have COMPLETED a feature or the user quit for you. If you have completed a feature (tests pass, QA passed, feature marked .done), exit by calling .claude/ralph/bin/kill-claude."
8
+ }
9
+ JSON
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+ CONTROL_FILE=".claude/ralph/loop-control"
3
+ PID_FILE=".claude/ralph/pid"
4
+
5
+ if [ ! -f "$CONTROL_FILE" ]; then
6
+ echo "No running loop found."
7
+ exit 1
8
+ fi
9
+
10
+ rm "$CONTROL_FILE"
11
+
12
+ if [ -f "$PID_FILE" ]; then
13
+ kill $(cat "$PID_FILE") 2>/dev/null
14
+ rm -f "$PID_FILE"
15
+ fi
16
+
17
+ echo "Loop stopped."
@@ -0,0 +1,218 @@
1
+ # Feature Implementor
2
+
3
+ You are implementing features for YAIC (Yet Another IRC Client), a low-level Ruby IRC client library. Work through features one at a time, following the specs exactly.
4
+
5
+ ## Configuration
6
+
7
+ ```
8
+ EXIT_SCRIPT: .claude/ralph/bin/kill-claude
9
+ ```
10
+
11
+ ## Project Context
12
+
13
+ - **Data model**: See `docs/agents/data-model.md`
14
+ - **RFC reference**: See `docs/agents/rfc/modern-irc/` (large, query specific files as needed)
15
+ - **Features**: See `docs/agents/ralph/features/`
16
+ - **Progress**: See `docs/agents/ralph/progress.md`
17
+
18
+ ## Running Things
19
+
20
+ ```bash
21
+ bundle exec m test/
22
+ bundle exec m test/unit/
23
+ bundle exec m test/integration/
24
+ bundle exec m test/file_test.rb
25
+ bundle exec m test/file_test.rb:42
26
+
27
+ bundle exec standardrb -A
28
+ ```
29
+
30
+ ## Integration Test Server
31
+
32
+ For integration tests, use the inspircd Docker container:
33
+
34
+ ```bash
35
+ docker run -d --name inspircd -p 6667:6667 -p 6697:6697 inspircd/inspircd-docker
36
+ ```
37
+
38
+ Configure tests to connect to localhost:6667 (plain) or localhost:6697 (SSL).
39
+
40
+ **IMPORTANT**: Assume the IRC server is already running. Do NOT check if it's running before running tests. If tests fail with connection errors suggesting the server is not running, use `AskUserQuestion` to ask the user if the server is running.
41
+
42
+ ## Project Style
43
+
44
+ - No trailing whitespace
45
+ - No comments in code
46
+ - Slim public interface - minimize exposed methods
47
+ - Use Ruby's `private` keyword for internal methods
48
+ - Use standardrb for linting (run with -A to auto-fix)
49
+ - UTF-8 encoding throughout
50
+
51
+ ## Workflow
52
+
53
+ ### 1. Check Progress
54
+
55
+ Read `docs/agents/ralph/progress.md` to see:
56
+ - What's been done
57
+ - What to work on next
58
+ - Any notes from previous sessions
59
+
60
+ ### 2. Pick a Feature
61
+
62
+ Choose from `.claude/ralph/features/`. Pick a `.md` file (not `.md.done`) whose dependencies are satisfied.
63
+
64
+ If unclear which to pick, check `docs/agents/ralph/progress.md` for suggestions.
65
+
66
+ ### 3. Implement the Feature
67
+
68
+ Read the feature spec thoroughly. It contains:
69
+ - Description of the behavior
70
+ - Models/data involved
71
+ - Test descriptions
72
+ - Implementation notes
73
+ - Dependencies
74
+
75
+ Implement:
76
+ 1. Write tests first (based on spec's test descriptions)
77
+ 2. Write code to make tests pass
78
+ 3. Run tests to verify
79
+ 4. Run linter
80
+
81
+ ### 4. QA Review (REQUIRED)
82
+
83
+ **A feature CANNOT be marked as done unless QA approves it.**
84
+
85
+ After tests pass, run the QA agent:
86
+
87
+ ```bash
88
+ claude --agent-prompt .claude/agents/ralph-qa.md
89
+ ```
90
+
91
+ Wait for QA to complete. The QA agent will review your implementation and either:
92
+ - **APPROVE**: You may proceed to commit and mark complete
93
+ - **FAIL**: You must fix the issues and re-run QA
94
+
95
+ **If QA fails:**
96
+ 1. Read the QA feedback carefully
97
+ 2. Fix all issues identified
98
+ 3. Run tests again
99
+ 4. Re-run the QA agent
100
+ 5. Repeat until QA approves
101
+
102
+ Do NOT proceed to commit until QA has approved the implementation.
103
+
104
+ ### 5. Mark Complete
105
+
106
+ When feature is done, tests pass, and **QA has approved**:
107
+
108
+ 1. Rename the feature file:
109
+ ```bash
110
+ mv docs/agents/ralph/features/feature-name.md docs/agents/ralph/features/feature-name.md.done
111
+ ```
112
+
113
+ 2. Update `docs/agents/ralph/progress.md`:
114
+ - Add entry to Session History
115
+ - Update Current State
116
+ - Suggest next feature
117
+
118
+ 3. Commit your changes:
119
+ ```bash
120
+ git add -A
121
+ git commit --no-gpg-sign -m "Implement [feature-name]"
122
+ ```
123
+
124
+ **CRITICAL: Always commit before exiting. Never exit without committing your work.**
125
+
126
+ ### 6. Exit
127
+
128
+ **ONLY after QA has approved and the feature is marked complete**, exit by running:
129
+
130
+ ```bash
131
+ .claude/ralph/bin/kill-claude
132
+ ```
133
+
134
+ **IMPORTANT**: The kill script must be run with the sandbox disabled (`dangerouslyDisableSandbox: true`) because it needs to send signals to processes.
135
+
136
+ The loop will restart you with fresh context.
137
+
138
+ **CRITICAL: NEVER call the exit script if you are blocked or have a question. Use `AskUserQuestion` instead and wait for the human to respond.**
139
+
140
+ ## Rules
141
+
142
+ ### Do
143
+
144
+ - Follow the spec exactly
145
+ - Write tests based on the spec's test descriptions
146
+ - Use `AskUserQuestion` if something is unclear or blocking
147
+ - Update progress.md with useful notes for future sessions
148
+ - Exit after each feature (keeps context fresh)
149
+ - Test for RFC compliance
150
+
151
+ ### Don't
152
+
153
+ - Change test assertions without asking first
154
+ - Skip tests
155
+ - Implement features out of dependency order
156
+ - Stay in one session for multiple features (exit and restart)
157
+ - Exit without updating progress.md
158
+ - Exit without committing your work
159
+ - Add comments to code
160
+ - Create documentation files unless explicitly asked
161
+ - Mark a feature complete without QA approval
162
+ - Skip QA or proceed after QA failure without fixing issues
163
+ - **NEVER call the exit script when blocked or confused - use AskUserQuestion instead**
164
+
165
+ ## If Blocked
166
+
167
+ If you can't proceed:
168
+ 1. Use `AskUserQuestion` to ask the human
169
+ 2. Wait for their response
170
+ 3. Continue working after they answer
171
+
172
+ **DO NOT exit when blocked. DO NOT call the kill script. Stay in the session and use AskUserQuestion.**
173
+
174
+ ## Session Notes Format
175
+
176
+ When updating progress.md, use this format:
177
+
178
+ ```markdown
179
+ ### Session [DATE]
180
+
181
+ **Feature**: [feature-name]
182
+ **Status**: Completed | Blocked | In Progress
183
+
184
+ **What was done**:
185
+ - [bullet points]
186
+
187
+ **Notes for next session**:
188
+ - [anything important to know]
189
+ ```
190
+
191
+ ## File Structure
192
+
193
+ Expected project structure after implementation:
194
+
195
+ ```
196
+ lib/
197
+ yaic.rb
198
+ yaic/
199
+ version.rb
200
+ client.rb
201
+ message.rb
202
+ source.rb
203
+ socket.rb
204
+ event.rb
205
+ channel.rb
206
+ ...
207
+
208
+ test/
209
+ test_helper.rb
210
+ unit/
211
+ message_test.rb
212
+ source_test.rb
213
+ ...
214
+ integration/
215
+ connection_test.rb
216
+ channel_test.rb
217
+ ...
218
+ ```
@@ -0,0 +1,26 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/ralph/bin/dump-pid.sh"
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "Stop": [
15
+ {
16
+ "matcher": "",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/ralph/bin/stop-hook.sh"
21
+ }
22
+ ]
23
+ }
24
+ ]
25
+ }
26
+ }
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "docs/agents/rfc/modern-irc"]
2
+ path = docs/agents/rfc/modern-irc
3
+ url = https://github.com/ircdocs/modern-irc.git
data/CLAUDE.md ADDED
@@ -0,0 +1,65 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Yaic (Yet Another IRC Client) is a Ruby gem that provides an IRC client library. It handles IRC protocol messaging, event handling, channel management, and connection state.
8
+
9
+ **Minimum Ruby version: 3.2**
10
+
11
+ ## Commands
12
+
13
+ ### Testing
14
+ ```bash
15
+ rake test # Run all tests
16
+ rake test_unit # Run unit tests only
17
+ rake test_integration # Run integration tests only
18
+ m test/unit/message_test.rb:42 # Run single test by line number
19
+ ```
20
+
21
+ ### Linting
22
+ ```bash
23
+ bundle exec standardrb -A # Run linter with auto-fix
24
+ ```
25
+
26
+ ### Security
27
+ ```bash
28
+ bin/brakeman # Run security scanner
29
+ ```
30
+
31
+ ### Integration Test Setup
32
+ Integration tests require a running IRC server (InspIRCd via Docker):
33
+ ```bash
34
+ bin/start-irc-server # Start IRC server container (ports 6667/6697)
35
+ bin/stop-irc-server # Stop IRC server container
36
+ ```
37
+
38
+ ## Architecture
39
+
40
+ ### Core Components
41
+
42
+ - **Client** (`lib/yaic/client.rb`): Main IRC client class. Manages connection state, handles incoming IRC messages, maintains channel/user state, and provides event emission system with `on`/`off` handlers.
43
+
44
+ - **Message** (`lib/yaic/message.rb`): Parses and serializes IRC protocol messages (source, command, params).
45
+
46
+ - **Socket** (`lib/yaic/socket.rb`): TCP socket wrapper with SSL support.
47
+
48
+ - **Channel** (`lib/yaic/channel.rb`): Tracks channel state including users, modes, and topic.
49
+
50
+ - **Event** (`lib/yaic/event.rb`): Event objects emitted for IRC events (`:message`, `:join`, `:part`, etc.).
51
+
52
+ ### Event System
53
+
54
+ Client uses an event-based model:
55
+ ```ruby
56
+ client.on(:message) { |event| handle_message(event) }
57
+ client.on(:join) { |event| handle_join(event) }
58
+ ```
59
+
60
+ Events: `:raw`, `:connect`, `:disconnect`, `:message`, `:notice`, `:join`, `:part`, `:quit`, `:kick`, `:nick`, `:topic`, `:mode`, `:names`, `:who`, `:whois`, `:error`
61
+
62
+ ### Test Structure
63
+
64
+ - `test/unit/` - Unit tests mocking the socket layer
65
+ - `test/integration/` - Integration tests against real IRC server (InspIRCd)
data/README.md CHANGED
@@ -1,39 +1,128 @@
1
1
  # Yaic
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/yaic`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Yet Another IRC Client - A Ruby IRC client library.
6
4
 
7
5
  ## Installation
8
6
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
7
+ Add to your Gemfile:
8
+
9
+ ```ruby
10
+ gem "yaic"
11
+ ```
10
12
 
11
- Install the gem and add to the application's Gemfile by executing:
13
+ Or install directly:
12
14
 
13
15
  ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
16
+ gem install yaic
15
17
  ```
16
18
 
17
- If bundler is not being used to manage dependencies, install the gem by executing:
19
+ ## Quick Start
18
20
 
19
- ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
21
+ ```ruby
22
+ require "yaic"
23
+
24
+ client = Yaic::Client.new(
25
+ server: "irc.libera.chat",
26
+ port: 6697,
27
+ ssl: true,
28
+ nickname: "mynick",
29
+ username: "myuser",
30
+ realname: "My Real Name"
31
+ )
32
+
33
+ client.on(:message) { |event| puts "#{event.source.nick}: #{event.text}" }
34
+
35
+ client.connect
36
+ client.join("#ruby")
37
+ client.privmsg("#ruby", "Hello!")
38
+ client.quit
21
39
  ```
22
40
 
23
- ## Usage
41
+ ## Events
24
42
 
25
- TODO: Write usage instructions here
43
+ Subscribe to events with `on`:
26
44
 
27
- ## Development
45
+ ```ruby
46
+ client.on(:message) { |event| ... }
47
+ client.on(:join) { |event| ... }
48
+ ```
28
49
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
50
+ Unsubscribe with `off`:
30
51
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
52
+ ```ruby
53
+ client.off(:message)
54
+ ```
32
55
 
33
- ## Contributing
56
+ | Event | Attributes |
57
+ |-------|------------|
58
+ | `:raw` | `message` - Raw IRC message |
59
+ | `:connect` | `server` - Server name |
60
+ | `:disconnect` | - |
61
+ | `:message` | `source`, `target`, `text` |
62
+ | `:notice` | `source`, `target`, `text` |
63
+ | `:join` | `channel`, `user` |
64
+ | `:part` | `channel`, `user`, `reason` |
65
+ | `:quit` | `user`, `reason` |
66
+ | `:kick` | `channel`, `user`, `by`, `reason` |
67
+ | `:nick` | `old_nick`, `new_nick` |
68
+ | `:topic` | `channel`, `topic`, `setter` |
69
+ | `:mode` | `target`, `modes`, `args` |
70
+ | `:names` | `channel`, `users` |
71
+ | `:who` | `channel`, `user`, `host`, `server`, `nick`, `away`, `realname` |
72
+ | `:whois` | `result` (WhoisResult object) |
73
+ | `:error` | `numeric`, `message` |
74
+
75
+ ## Commands
76
+
77
+ ```ruby
78
+ client.connect # Connect and register
79
+ client.quit("Goodbye") # Disconnect with optional message
80
+
81
+ client.join("#channel") # Join a channel
82
+ client.join("#channel", "key") # Join with key
83
+ client.part("#channel") # Leave a channel
84
+ client.part("#channel", "reason") # Leave with reason
85
+
86
+ client.privmsg("#channel", "Hi") # Send message to channel
87
+ client.privmsg("nick", "Hello") # Send private message
88
+ client.msg("#channel", "Hi") # Alias for privmsg
89
+ client.notice("#channel", "Info") # Send notice
90
+
91
+ client.nick("newnick") # Change nickname
92
+ client.topic("#channel") # Request topic
93
+ client.topic("#channel", "New") # Set topic
94
+ client.kick("#channel", "nick") # Kick user
95
+ client.mode("#channel", "+o", "nick") # Set mode
96
+
97
+ client.who("#channel") # WHO query
98
+ client.whois("nick") # WHOIS query
99
+ client.names("#channel") # NAMES query
100
+ ```
34
101
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/yaic.
102
+ ## Threading
103
+
104
+ The client spawns a background thread to read incoming messages. Event handlers are called from this thread. All public methods are thread-safe.
105
+
106
+ ## Channel State
107
+
108
+ Access joined channels:
109
+
110
+ ```ruby
111
+ client.channels["#ruby"] # => Channel object
112
+ client.channels["#ruby"].users # => {"nick" => Set[:op, :voice], ...}
113
+ client.channels["#ruby"].topic # => "Ruby programming"
114
+ client.channels["#ruby"].modes # => {:moderated => true, ...}
115
+ ```
116
+
117
+ ## Development
118
+
119
+ ```bash
120
+ rake test # Run all tests
121
+ rake test_unit # Run unit tests only
122
+ rake test_integration # Run integration tests (requires IRC server)
123
+ bundle exec standardrb -A # Run linter
124
+ ```
36
125
 
37
126
  ## License
38
127
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
128
+ MIT License
data/Rakefile CHANGED
@@ -5,6 +5,14 @@ require "minitest/test_task"
5
5
 
6
6
  Minitest::TestTask.create
7
7
 
8
+ Minitest::TestTask.create(:test_unit) do |t|
9
+ t.test_globs = ["test/unit/**/*_test.rb", "test/test_yaic.rb"]
10
+ end
11
+
12
+ Minitest::TestTask.create(:test_integration) do |t|
13
+ t.test_globs = ["test/integration/**/*_test.rb"]
14
+ end
15
+
8
16
  require "standard/rake"
9
17
 
10
18
  task default: %i[test standard]
data/devenv.nix CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  env = {
6
6
  LD_LIBRARY_PATH = "${config.devenv.profile}/lib";
7
+ RUBOCOP_CACHE_ROOT = "${config.devenv.state}/rubocop_cache";
7
8
  };
8
9
 
9
10
  packages = with pkgs; [