twitch_chatter 0.1.1 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cd70432c7cb5123a7377b95203e38f2c97cdd04d185a59dfd59356e59b4658c
4
- data.tar.gz: 2e46bc4c3fbfffe262716cef079b1e988a5624c31dc9a4fa623ea9021d753b1f
3
+ metadata.gz: fff1b37e345e021646f75631a1ec5515d10f05cbf4f238b4f2136878b5b9b02d
4
+ data.tar.gz: b47c19eaff099c6a439e864f80ed72e85b15a68f4fcbc2d4ef2a85454f47b947
5
5
  SHA512:
6
- metadata.gz: f9387375052d6c148931b7330f26701cefcb6dac48fab53a97ef8741db12833cb4d7a288f8dbc1d081cbf6cbcd802e4fdb7b8f82680cab40d2cc3566ea413645
7
- data.tar.gz: 5b6dc9d6a7cb115effb39016c309bbe1dd310cf1875c634841602238de1a123a9d41bf87f589c18046f5555dfaa2535f962c5b93996171af83b8fd74158b62bf
6
+ metadata.gz: 984d51eda98c57546a8e906cef1b7d2d96dfd7d0d9de91c2c42bb18ff825279f24b9f3d85eab199eaf3f6a427ddb2d446db946102e0a1d17e90aef1559bfafac
7
+ data.tar.gz: 58909f2b18253651a6cc2d37ec36fa5d2381279a5f203f332eebe5b6441cdaffcee71bb488e53212915f8ed1e2b53b37d2f4e9e3cf9bd9973f18dfbd6b525df1
@@ -21,8 +21,6 @@ module Twitch
21
21
  websocket_url: "wss://irc-ws.chat.twitch.tv:443",
22
22
  }.freeze
23
23
 
24
- include Concerns::Channels
25
-
26
24
  def initialize(**options)
27
25
  @nick = options[:nick] || DEFAULT_OPTIONS[:nick]
28
26
  @websocket_url = Async::HTTP::Endpoint.parse(options[:websocket_url] || DEFAULT_OPTIONS[:websocket_url])
@@ -45,8 +43,7 @@ module Twitch
45
43
  Async::WebSocket::Client.connect(@websocket_url) do |ws|
46
44
  @ws = ws
47
45
  ws.write("NICK #{@nick}")
48
- resume_pending
49
- @ready_handle&.call
46
+ dispatch_ready
50
47
 
51
48
  while (ws_message = ws.read)
52
49
  data = ws_message.to_str
@@ -57,14 +54,109 @@ module Twitch
57
54
 
58
55
  next unless data.include?("PRIVMSG")
59
56
 
60
- message = Message.new(data, connection: self)
61
- @message_handle&.call(message)
62
- streams[message.channel.to_sym].each do |block|
63
- block.call(message)
64
- end
57
+ dispatch(Message.new(data, connection: self))
65
58
  end
66
59
  end
67
60
  end
68
61
  end
62
+
63
+ # @return [Array<Symbol>]
64
+ def channels
65
+ streams.keys
66
+ end
67
+
68
+ # @yield
69
+ # @yieldparam streamer [Symbol]
70
+ # @yieldreturn [nil]
71
+ def joined(&block)
72
+ @join_handle = block
73
+ end
74
+
75
+ # @yield
76
+ # @yieldparam streamer [Symbol]
77
+ # @yieldreturn [nil]
78
+ def left(&block)
79
+ @leave_handle = block
80
+ end
81
+
82
+ # @param streamer [Symbol, String]
83
+ # @yield
84
+ # @yieldparam message [Twitch::Message]
85
+ # @yieldreturn [nil]
86
+ # @example
87
+ # bot.join(:twitchgaming) do |message|
88
+ # puts "##{message.channel} #{message.sender}: #{message}"
89
+ # end
90
+ def join(streamer, &block)
91
+ streamer = streamer.to_sym
92
+ unless ready?
93
+ yield_join(streamer, &block)
94
+ return
95
+ end
96
+
97
+ streams[streamer] = [] unless streams.key?(streamer)
98
+ streams[streamer] << block if block_given?
99
+ @ws.write("JOIN ##{streamer}")
100
+ @join_handle&.call(streamer)
101
+ end
102
+
103
+ # @param streamer [Symbol, String]
104
+ # @example
105
+ # bot.leave(:twitchgaming)
106
+ def leave(streamer)
107
+ streamer = streamer.to_sym
108
+ streams[streamer] = []
109
+ @ws.write("PART ##{streamer}")
110
+ @leave_handle&.call(streamer)
111
+ end
112
+
113
+ # @yield
114
+ # @yieldparam message [Twitch::Message]
115
+ # @yieldreturn [nil]
116
+ # @example
117
+ # bot.message do |message|
118
+ # puts "##{message.channel} #{message.sender}: #{message}"
119
+ # end
120
+ def message(&block)
121
+ @message_handle = block
122
+ end
123
+
124
+ alias_method :part, :leave
125
+ alias_method :on_leave, :leave
126
+ alias_method :on_join, :joined
127
+ alias_method :on_message, :message
128
+
129
+ private
130
+
131
+ def dispatch(message)
132
+ @message_handle&.call(message)
133
+ streams[message.channel.to_sym].each do |block|
134
+ block.call(message)
135
+ end
136
+ end
137
+
138
+ def dispatch_ready
139
+ join_all
140
+ @ready_handle&.call
141
+ end
142
+
143
+ def streams
144
+ @streams ||= {}
145
+ end
146
+
147
+ def pending
148
+ @pending ||= {}
149
+ end
150
+
151
+ def yield_join(streamer, &block)
152
+ pending[streamer] = [] if streamer
153
+ pending[streamer] << block
154
+ end
155
+
156
+ def join_all
157
+ pending.each do |streamer, blocks|
158
+ blocks.each { |block| join(streamer, &block) }
159
+ end
160
+ end
69
161
  end
70
162
  end
@@ -37,7 +37,7 @@ module Twitch
37
37
  @name.to_s
38
38
  end
39
39
 
40
- # @param other [Channel, Symbol]
40
+ # @param other [Channel, String, Symbol]
41
41
  # @return [Boolean]
42
42
  def ==(other)
43
43
  if other.is_a?(Channel)
@@ -10,24 +10,25 @@ module Twitch
10
10
  # @!attribute [r] raw
11
11
  # @return [String] Raw message from Twitch
12
12
  # @example
13
- # message = Twitch::Message.new(":ttlnow!ttlnow@ttlnow.tmi.twitch.tv PRIVMSG #ttlnow :Hello world!\r\n")
14
- # message.sender.name # => :ttlnow
15
- # message.channel.name # => :ttlnow
13
+ # message = Twitch::Message.new(":justinfan!justinfan@justinfan.tmi.twitch.tv PRIVMSG #twitchgaming :Hello world!\r\n")
14
+ # message.sender.name # => :justinfan
15
+ # message.channel.name # => :twitchgaming
16
16
  # message.content # => "Hello world!"
17
- # message.raw # => ":ttlnow!ttlnow@ttlnow.tmi.twitch.tv PRIVMSG #ttlnow :Hello world!\r\n"
17
+ # message.raw # => ":justinfan!justinfan@justinfan.tmi.twitch.tv PRIVMSG #justinfan :Hello world!\r\n"
18
18
  class Message < String
19
19
  attr_reader :sender, :channel, :content, :raw
20
20
 
21
21
  # @param raw [String] Raw IRC websocket message from Twitch
22
22
  # @param connection [Bot, nil] For internal usage
23
23
  # @example
24
- # message = Twitch::Message.new(":ttlnow!ttlnow@ttlnow.tmi.twitch.tv PRIVMSG #ttlnow :Hello world!\r\n")
24
+ # message = Twitch::Message.new(":justinfan!justinfan@justinfan.tmi.twitch.tv PRIVMSG #twitchgaming :Hello world!\r\n")
25
25
  def initialize(raw, connection: nil)
26
26
  split = raw.split(" ")
27
27
  content = split[3..-1].join(" ")[1..-1]
28
28
  super(content)
29
29
 
30
30
  @content = content
31
+ @connection = connection
31
32
  @channel = Channel.new(split[2][1..-1], connection: connection)
32
33
  @sender = Channel.new(split[0].split("!")[0][1..-1])
33
34
  @raw = raw
@@ -35,5 +36,38 @@ module Twitch
35
36
 
36
37
  alias_method :text, :content
37
38
  alias_method :streamer, :channel
39
+ alias_method :user, :sender
40
+
41
+ USERNAME = /[a-zA-Z0-9_]{4,25}/
42
+ # @return [Array<Twitch::Channel>] List of usernames mentioned in the message
43
+ def mentions
44
+ return @mentions if @mentions
45
+
46
+ @mentions = []
47
+ @content.split(" ").each do |word|
48
+ match = word.match(/@#{USERNAME}/)
49
+ next unless match
50
+
51
+ @mentions << Channel.new(match[0][1..-1], connection: @connection)
52
+ end
53
+
54
+ @mentions
55
+ end
56
+
57
+ LINK = %r{(https?://[^\s]+)}
58
+ # @return [Array<String>] List of links mentioned in the message
59
+ def links
60
+ return @links if @links
61
+
62
+ @links = []
63
+ @content.split(" ").each do |word|
64
+ match = word.match(LINK)
65
+ next unless match
66
+
67
+ @links << match[0]
68
+ end
69
+
70
+ @links
71
+ end
38
72
  end
39
73
  end
@@ -3,7 +3,6 @@
3
3
  require "async"
4
4
  require "async/http/endpoint"
5
5
  require "async/websocket/client"
6
- require_relative "twitch_chatter/concerns"
7
6
  require_relative "twitch_chatter/models"
8
7
  require_relative "twitch_chatter/bot"
9
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twitch_chatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Hackworth
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-21 00:00:00.000000000 Z
11
+ date: 2024-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-websocket
@@ -32,17 +32,15 @@ extra_rdoc_files: []
32
32
  files:
33
33
  - lib/twitch_chatter.rb
34
34
  - lib/twitch_chatter/bot.rb
35
- - lib/twitch_chatter/concerns.rb
36
- - lib/twitch_chatter/concerns/channels.rb
37
35
  - lib/twitch_chatter/models.rb
38
36
  - lib/twitch_chatter/models/channel.rb
39
37
  - lib/twitch_chatter/models/message.rb
40
- homepage: https://github.com/dylhack/twitch-chat-gem
38
+ homepage: https://github.com/dylhack/twitch_chatter
41
39
  licenses:
42
40
  - MIT
43
41
  metadata:
44
- source_code_uri: https://github.com/dylhack/twitch-chat-gem
45
- post_install_message:
42
+ source_code_uri: https://github.com/dylhack/twitch_chatter
43
+ post_install_message:
46
44
  rdoc_options: []
47
45
  require_paths:
48
46
  - lib
@@ -58,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
56
  version: '0'
59
57
  requirements: []
60
58
  rubygems_version: 3.5.9
61
- signing_key:
59
+ signing_key:
62
60
  specification_version: 4
63
61
  summary: Read-only Twitch chat client.
64
62
  test_files: []
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Twitch
4
- # Mixin modules
5
- # @private
6
- module Concerns
7
- # Mixin for channel-related methods
8
- # @private
9
- module Channels
10
- # @return [Array<Symbol>]
11
- def channels
12
- streams.keys
13
- end
14
-
15
- # @yield
16
- # @yieldparam streamer [Symbol]
17
- # @yieldreturn [nil]
18
- def joined(&block)
19
- @join_handle = block
20
- end
21
-
22
- # @yield
23
- # @yieldparam streamer [Symbol]
24
- # @yieldreturn [nil]
25
- def left(&block)
26
- @leave_handle = block
27
- end
28
-
29
- # @param streamer [Symbol, String]
30
- # @yield
31
- # @yieldparam message [Twitch::Message]
32
- # @yieldreturn [nil]
33
- # @example
34
- # bot.join(:twitchgaming) do |message|
35
- # puts "##{message.channel} #{message.sender}: #{message}"
36
- # end
37
- def join(streamer, &block)
38
- streamer = streamer.to_sym
39
- unless ready?
40
- yield_join(streamer, &block)
41
- return
42
- end
43
-
44
- streams[streamer] = [] unless streams.key?(streamer)
45
- streams[streamer] << block if block_given?
46
- @ws.write("JOIN ##{streamer}")
47
- @join_handle&.call(streamer)
48
- end
49
-
50
- # @param streamer [Symbol, String]
51
- # @example
52
- # bot.leave(:twitchgaming)
53
- def leave(streamer)
54
- streamer = streamer.to_sym
55
- streams[streamer] = []
56
- @ws.write("PART ##{streamer}")
57
- @leave_handle&.call(streamer)
58
- end
59
-
60
- # @yield
61
- # @yieldparam message [Twitch::Message]
62
- # @yieldreturn [nil]
63
- # @example
64
- # bot.message do |message|
65
- # puts "##{message.channel} #{message.sender}: #{message}"
66
- # end
67
- def message(&block)
68
- @message_handle = block
69
- end
70
-
71
- alias_method :part, :leave
72
- alias_method :on_leave, :leave
73
- alias_method :on_join, :joined
74
- alias_method :on_message, :message
75
-
76
- private
77
-
78
- def streams
79
- @streams ||= {}
80
- end
81
-
82
- def pending
83
- @pending ||= {}
84
- end
85
-
86
- def yield_join(streamer, &block)
87
- pending[streamer] = [] if streamer
88
- pending[streamer] << block
89
- end
90
-
91
- def resume_pending
92
- pending.each do |streamer, blocks|
93
- blocks.each { |block| join(streamer, &block) }
94
- end
95
- end
96
- end
97
- end
98
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Twitch
4
- require_relative "concerns/channels"
5
- end