twitch_chatter 0.1.0 → 0.1.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 +4 -4
- data/lib/twitch_chatter/bot.rb +70 -0
- data/lib/twitch_chatter/concerns/channels.rb +98 -0
- data/lib/twitch_chatter/concerns.rb +5 -0
- data/lib/twitch_chatter/models/channel.rb +50 -0
- data/lib/twitch_chatter/models/message.rb +39 -0
- data/lib/twitch_chatter/models.rb +6 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0cd70432c7cb5123a7377b95203e38f2c97cdd04d185a59dfd59356e59b4658c
|
4
|
+
data.tar.gz: 2e46bc4c3fbfffe262716cef079b1e988a5624c31dc9a4fa623ea9021d753b1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9387375052d6c148931b7330f26701cefcb6dac48fab53a97ef8741db12833cb4d7a288f8dbc1d081cbf6cbcd802e4fdb7b8f82680cab40d2cc3566ea413645
|
7
|
+
data.tar.gz: 5b6dc9d6a7cb115effb39016c309bbe1dd310cf1875c634841602238de1a123a9d41bf87f589c18046f5555dfaa2535f962c5b93996171af83b8fd74158b62bf
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
# @example
|
5
|
+
# bot = Twitch::Bot.new
|
6
|
+
#
|
7
|
+
# bot.ready do
|
8
|
+
# puts "Ready!"
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# bot.join(:twitchgaming) do |message|
|
12
|
+
# puts "#{message.channel} #{message.user}: #{message.text}"
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# bot.start
|
16
|
+
class Bot
|
17
|
+
# Default options for Twitch websocket. Nicknames starting with "justinfan" are considered anonymous.
|
18
|
+
# @api private
|
19
|
+
DEFAULT_OPTIONS = {
|
20
|
+
nick: "justinfan0735",
|
21
|
+
websocket_url: "wss://irc-ws.chat.twitch.tv:443",
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
include Concerns::Channels
|
25
|
+
|
26
|
+
def initialize(**options)
|
27
|
+
@nick = options[:nick] || DEFAULT_OPTIONS[:nick]
|
28
|
+
@websocket_url = Async::HTTP::Endpoint.parse(options[:websocket_url] || DEFAULT_OPTIONS[:websocket_url])
|
29
|
+
end
|
30
|
+
|
31
|
+
# @yield
|
32
|
+
# @yieldparam
|
33
|
+
def ready(&block)
|
34
|
+
@ready_handle = block
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Boolean]
|
38
|
+
def ready?
|
39
|
+
@ws != nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Async::Task]
|
43
|
+
def start
|
44
|
+
Async do
|
45
|
+
Async::WebSocket::Client.connect(@websocket_url) do |ws|
|
46
|
+
@ws = ws
|
47
|
+
ws.write("NICK #{@nick}")
|
48
|
+
resume_pending
|
49
|
+
@ready_handle&.call
|
50
|
+
|
51
|
+
while (ws_message = ws.read)
|
52
|
+
data = ws_message.to_str
|
53
|
+
if data.start_with?("PING")
|
54
|
+
ws.write("PONG :tmi.twitch.tv")
|
55
|
+
next
|
56
|
+
end
|
57
|
+
|
58
|
+
next unless data.include?("PRIVMSG")
|
59
|
+
|
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
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,98 @@
|
|
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
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
# @!attribute [r] name
|
5
|
+
# @return [Symbol] Name of the channel
|
6
|
+
# @example
|
7
|
+
# channel = Twitch::Channel.new("twitchgaming")
|
8
|
+
class Channel
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# @param name [String, Symbol]
|
12
|
+
# @param connection [Bot, nil] For internal usage
|
13
|
+
def initialize(name, connection: nil)
|
14
|
+
@name = name.to_sym
|
15
|
+
@connection = connection
|
16
|
+
end
|
17
|
+
|
18
|
+
# @yield
|
19
|
+
# @yieldparam message [Twitch::Message]
|
20
|
+
# @return [nil]
|
21
|
+
def join(&block)
|
22
|
+
@connection.join(@name, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [nil]
|
26
|
+
def leave
|
27
|
+
@connection.leave(@name)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Symbol]
|
31
|
+
def to_sym
|
32
|
+
@name
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
def to_s
|
37
|
+
@name.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param other [Channel, Symbol]
|
41
|
+
# @return [Boolean]
|
42
|
+
def ==(other)
|
43
|
+
if other.is_a?(Channel)
|
44
|
+
return @name == other.name
|
45
|
+
end
|
46
|
+
|
47
|
+
@name == other.to_sym
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
# @!attribute [r] sender
|
5
|
+
# @return [Channel] Sender of the message
|
6
|
+
# @!attribute [r] channel
|
7
|
+
# @return [Channel] Channel the message was sent to
|
8
|
+
# @!attribute [r] content
|
9
|
+
# @return [String] Content of the message
|
10
|
+
# @!attribute [r] raw
|
11
|
+
# @return [String] Raw message from Twitch
|
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
|
16
|
+
# message.content # => "Hello world!"
|
17
|
+
# message.raw # => ":ttlnow!ttlnow@ttlnow.tmi.twitch.tv PRIVMSG #ttlnow :Hello world!\r\n"
|
18
|
+
class Message < String
|
19
|
+
attr_reader :sender, :channel, :content, :raw
|
20
|
+
|
21
|
+
# @param raw [String] Raw IRC websocket message from Twitch
|
22
|
+
# @param connection [Bot, nil] For internal usage
|
23
|
+
# @example
|
24
|
+
# message = Twitch::Message.new(":ttlnow!ttlnow@ttlnow.tmi.twitch.tv PRIVMSG #ttlnow :Hello world!\r\n")
|
25
|
+
def initialize(raw, connection: nil)
|
26
|
+
split = raw.split(" ")
|
27
|
+
content = split[3..-1].join(" ")[1..-1]
|
28
|
+
super(content)
|
29
|
+
|
30
|
+
@content = content
|
31
|
+
@channel = Channel.new(split[2][1..-1], connection: connection)
|
32
|
+
@sender = Channel.new(split[0].split("!")[0][1..-1])
|
33
|
+
@raw = raw
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method :text, :content
|
37
|
+
alias_method :streamer, :channel
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twitch_chatter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dylan Hackworth
|
@@ -9,7 +9,21 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2024-05-21 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: async-websocket
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.26.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.26.1
|
13
27
|
description: A Ruby gem for Twitch's chat IRC websocket
|
14
28
|
email: me@dylhack.dev
|
15
29
|
executables: []
|
@@ -17,6 +31,12 @@ extensions: []
|
|
17
31
|
extra_rdoc_files: []
|
18
32
|
files:
|
19
33
|
- lib/twitch_chatter.rb
|
34
|
+
- lib/twitch_chatter/bot.rb
|
35
|
+
- lib/twitch_chatter/concerns.rb
|
36
|
+
- lib/twitch_chatter/concerns/channels.rb
|
37
|
+
- lib/twitch_chatter/models.rb
|
38
|
+
- lib/twitch_chatter/models/channel.rb
|
39
|
+
- lib/twitch_chatter/models/message.rb
|
20
40
|
homepage: https://github.com/dylhack/twitch-chat-gem
|
21
41
|
licenses:
|
22
42
|
- MIT
|
@@ -30,7 +50,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
30
50
|
requirements:
|
31
51
|
- - ">="
|
32
52
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.1.
|
53
|
+
version: 3.1.1
|
34
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
55
|
requirements:
|
36
56
|
- - ">="
|