chatrix 1.0.0.pre → 1.0.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.
@@ -0,0 +1,53 @@
1
+ module Chatrix
2
+ # Describes a message sent in a room.
3
+ class Message
4
+ # Supported message types.
5
+ #
6
+ # `:html` is a special message type parsed in {#parse_body!}.
7
+ TYPES = {
8
+ 'm.text' => :text,
9
+ 'm.emote' => :emote,
10
+ 'm.notice' => :notice
11
+ }.freeze
12
+
13
+ # @!attribute [r] raw
14
+ # @return [Hash] The raw message data (the `content` field).
15
+ # @!attribute [r] type
16
+ # @return [Symbol,nil] The type of message. Will be nil if the type
17
+ # failed to parse.
18
+ # @!attribute [r] sender
19
+ # @return [User] The user who sent this message.
20
+ # @!attribute [r] body
21
+ # @return [String] The text content of the message. If the message is
22
+ # of `:html` type, this will contain HTML format. To get the raw
23
+ # message text, use the `'body'` field of the {#raw} hash.
24
+ attr_reader :raw, :type, :sender, :body
25
+
26
+ # Initializes a new Message instance.
27
+ #
28
+ # @param sender [User] The user who sent the message.
29
+ # @param content [Hash] The message content.
30
+ def initialize(sender, content)
31
+ @raw = content
32
+
33
+ @type = TYPES[@raw['msgtype']]
34
+ @body = @raw['body']
35
+ @sender = sender
36
+
37
+ parse_body!
38
+ end
39
+
40
+ private
41
+
42
+ # Parses the message content to see if there's any special formatting
43
+ # available.
44
+ def parse_body!
45
+ return unless @raw.key? 'format'
46
+ case @raw['format']
47
+ when 'org.matrix.custom.html'
48
+ @type = :html
49
+ @formatted = @raw['formatted_body']
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,93 @@
1
+ require 'chatrix/components/state'
2
+ require 'chatrix/components/timeline'
3
+ require 'chatrix/components/messaging'
4
+ require 'chatrix/components/permissions'
5
+ require 'chatrix/components/admin'
6
+
7
+ module Chatrix
8
+ # Provides functionality for interacting with a room.
9
+ class Room
10
+ include Wisper::Publisher
11
+
12
+ # @!attribute [r] id
13
+ # @return [String] The ID of this room.
14
+ # @!attribute [r] admin
15
+ # @return [Admin] Administration object for carrying out administrative
16
+ # actions like kicking and banning of users.
17
+ # @!attribute [r] messaging
18
+ # @return [Messaging] Handle various message actions through this object.
19
+ attr_reader :id, :state, :timeline, :admin, :messaging
20
+
21
+ # Initializes a new Room instance.
22
+ #
23
+ # @param id [String] The room ID.
24
+ # @param users [Users] The User manager.
25
+ # @param matrix [Matrix] The Matrix API instance.
26
+ def initialize(id, users, matrix)
27
+ @id = id
28
+ @users = users
29
+ @matrix = matrix
30
+
31
+ @state = Components::State.new self, @users
32
+ @timeline = Components::Timeline.new self, @users
33
+ @messaging = Components::Messaging.new self, @matrix
34
+ @admin = Components::Admin.new self, @matrix
35
+ end
36
+
37
+ # Convenience method to get the canonical alias from this room's state.
38
+ # @return [String] The canonical alias for this room.
39
+ def canonical_alias
40
+ @state.canonical_alias
41
+ end
42
+
43
+ # Convenience method to get the name from this room's state.
44
+ # @return [String] The name for this room.
45
+ def name
46
+ @state.name
47
+ end
48
+
49
+ # Process join events for this room.
50
+ # @param data [Hash] Event data containing state and timeline events.
51
+ def process_join(data)
52
+ @state.update data['state'] if data.key? 'state'
53
+ @timeline.update data['timeline'] if data.key? 'timeline'
54
+ end
55
+
56
+ # Process invite events for this room.
57
+ # @param data [Hash] Event data containing special invite data.
58
+ def process_invite(data)
59
+ data['invite_state']['events'].each { |e| process_invite_event e }
60
+ end
61
+
62
+ # Process leave events for this room.
63
+ # @param data [Hash] Event data containing state and timeline events up
64
+ # until the point of leaving the room.
65
+ def process_leave(data)
66
+ @state.update data['state'] if data.key? 'state'
67
+ @timeline.update data['timeline'] if data.key? 'timeline'
68
+ end
69
+
70
+ # Gets a string representation of this room.
71
+ # @return [String] If the room has a name, that name is returned.
72
+ # If it has a canonical alias, the alias is returned.
73
+ # If it has neither a name nor alias, the room ID is returned.
74
+ def to_s
75
+ name || canonical_alias || @id
76
+ end
77
+
78
+ private
79
+
80
+ # Process an invite event for this room.
81
+ # @param event [Hash] Event data.
82
+ def process_invite_event(event)
83
+ return unless event['type'] == 'm.room.member'
84
+ return unless event['content']['membership'] == 'invite'
85
+ @users.process_invite self, event
86
+ sender = @users[event['sender']]
87
+ invitee = @users[event['state_key']]
88
+ # Return early if the user is already in the room
89
+ return if @state.member? invitee
90
+ broadcast(:invited, sender, invitee)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,90 @@
1
+ require 'chatrix/room'
2
+
3
+ require 'wisper'
4
+
5
+ module Chatrix
6
+ # Manages the rooms known to the client.
7
+ class Rooms
8
+ include Wisper::Publisher
9
+
10
+ # Initializes a new Rooms instance.
11
+ #
12
+ # @param users [Users] The User manager.
13
+ # @param matrix [Matrix] The Matrix API instance.
14
+ def initialize(users, matrix)
15
+ @matrix = matrix
16
+
17
+ @users = users
18
+
19
+ # room_id => room
20
+ @rooms = {}
21
+ end
22
+
23
+ # Gets a room by its ID, alias, or name.
24
+ #
25
+ # @return [Room,nil] Returns the room instance if the room was found,
26
+ # otherwise `nil`.
27
+ def [](id)
28
+ return @rooms[id] if id.start_with? '!'
29
+
30
+ if id.start_with? '#'
31
+ res = @rooms.find { |_, r| r.alias == id }
32
+ return res.last if res.respond_to? :last
33
+ end
34
+
35
+ res = @rooms.find { |_, r| r.name == id }
36
+ res.last if res.respond_to? :last
37
+ end
38
+
39
+ # Processes a list of room events from syncs.
40
+ #
41
+ # @param events [Hash] A hash of room events as returned from the server.
42
+ def process_events(events)
43
+ process_join events['join'] if events.key? 'join'
44
+ process_invite events['invite'] if events.key? 'invite'
45
+ process_leave events['leave'] if events.key? 'leave'
46
+ end
47
+
48
+ private
49
+
50
+ # Gets the Room instance associated with a room ID.
51
+ # If there is no Room instance for the ID, one is created and returned.
52
+ #
53
+ # @param id [String] The room ID to get an instance for.
54
+ # @return [Room] An instance of the Room class for the specified ID.
55
+ def get_room(id)
56
+ return @rooms[id] if @rooms.key? id
57
+ room = Room.new id, @users, @matrix
58
+ @rooms[id] = room
59
+ broadcast(:added, room)
60
+ room
61
+ end
62
+
63
+ # Process `join` room events.
64
+ #
65
+ # @param events [Hash{String=>Hash}] Events to process.
66
+ def process_join(events)
67
+ events.each do |room, data|
68
+ get_room(room).process_join data
69
+ end
70
+ end
71
+
72
+ # Process `invite` room events.
73
+ #
74
+ # @param events [Hash{String=>Hash}] Events to process.
75
+ def process_invite(events)
76
+ events.each do |room, data|
77
+ get_room(room).process_invite data
78
+ end
79
+ end
80
+
81
+ # Process `leave` room events.
82
+ #
83
+ # @param events [Hash{String=>Hash}] Events to process.
84
+ def process_leave(events)
85
+ events.each do |room, data|
86
+ get_room(room).process_leave data
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,109 @@
1
+ require 'chatrix/events'
2
+
3
+ require 'wisper'
4
+
5
+ module Chatrix
6
+ # Describes a user.
7
+ class User
8
+ include Wisper::Publisher
9
+
10
+ # @!attribute [r] id
11
+ # @return [String] The user ID of this user.
12
+ # @!attribute [r] displayname
13
+ # @return [String,nil] The display name of this user, if one has
14
+ # been set.
15
+ # @!attribute [r] avatar
16
+ # @return [String,nil] This user's avatar URL, if one has been set.
17
+ attr_reader :id, :displayname, :avatar
18
+
19
+ # Initializes a new User instance.
20
+ # @param id [String] The user ID.
21
+ def initialize(id)
22
+ @id = id
23
+
24
+ # room_id => membership
25
+ @memberships = {}
26
+ end
27
+
28
+ # Get this user's power level in a room.
29
+ #
30
+ # @param room [Room] The room to check.
31
+ # @return [Fixnum] The user's power level in the specified room.
32
+ def power_in(room)
33
+ return 0 unless @memberships.key? room
34
+ @memberships[room][:power] || 0
35
+ end
36
+
37
+ # Process a member event.
38
+ #
39
+ # @param room [Room] The room that sent the event.
40
+ # @param event [Hash] Event data.
41
+ def process_member_event(room, event)
42
+ membership = (@memberships[room] ||= {})
43
+ type = event['content']['membership'].to_sym
44
+
45
+ # Only update the membership status if we are currently not in the room
46
+ # or if the new state is that we have left.
47
+ if membership[:type] != :join || type == :leave
48
+ membership[:type] = type
49
+ broadcast(:membership, self, room, membership)
50
+ end
51
+
52
+ update(event['content'])
53
+
54
+ Events.processed event
55
+ end
56
+
57
+ # Process a power level update in a room.
58
+ #
59
+ # @param room [Room] The room where the level updated.
60
+ # @param level [Fixnum] The new power level.
61
+ def process_power_level(room, level)
62
+ membership = (@memberships[room] ||= {})
63
+ membership[:power] = level
64
+ broadcast(:power_level, self, room, level)
65
+ end
66
+
67
+ # Process an invite to a room.
68
+ # @param room [Room] The room the user was invited to.
69
+ # @param sender [User] The user who sent the invite.
70
+ # @param event [Hash] Event data.
71
+ def process_invite(room, sender, event)
72
+ # Return early if we're already part of this room
73
+ membership = (@memberships[room] ||= {})
74
+ return if membership[:type] == :join
75
+ process_member_event room, event
76
+ broadcast(:invited, self, room, sender)
77
+ end
78
+
79
+ # Converts this User object to a string representation of it.
80
+ # @return [String] Returns the user's display name if one is set,
81
+ # otherwise returns the ID.
82
+ def to_s
83
+ @id
84
+ end
85
+
86
+ private
87
+
88
+ # Updates metadata for this user.
89
+ # @param data [Hash{String=>String}] User metadata.
90
+ def update(data)
91
+ update_avatar(data['avatar_url']) if data.key? 'avatar_url'
92
+ update_displayname(data['displayname']) if data.key? 'displayname'
93
+ end
94
+
95
+ # Sets a new avatar URL for this user.
96
+ # @param url [String] The new URL to set.
97
+ def update_avatar(url)
98
+ @avatar = url
99
+ broadcast(:avatar, self, @avatar)
100
+ end
101
+
102
+ # Sets a new display name for this user.
103
+ # @param name [String] The new name to set.
104
+ def update_displayname(name)
105
+ @displayname = name
106
+ broadcast(:displayname, self, @displayname)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,74 @@
1
+ require 'chatrix/user'
2
+ require 'chatrix/events'
3
+
4
+ require 'wisper'
5
+
6
+ module Chatrix
7
+ # Manages the users known to the client.
8
+ class Users
9
+ include Wisper::Publisher
10
+
11
+ # Initializes a new Users instance.
12
+ def initialize
13
+ # user_id => user
14
+ @users = {}
15
+ end
16
+
17
+ # Gets a user by ID or display name.
18
+ #
19
+ # @param id [String] A user's ID or display name.
20
+ # @return [User,nil] The User instance for the specified user, or
21
+ # `nil` if the user could not be found.
22
+ def [](id)
23
+ return @users[id] if id.start_with? '@'
24
+
25
+ res = @users.find { |_, u| u.displayname == id }
26
+ res.last if res.respond_to? :last
27
+ end
28
+
29
+ # Process a member event.
30
+ #
31
+ # @param room [Room] Which room the events are related to.
32
+ # @param event [Hash] Event data.
33
+ def process_member_event(room, event)
34
+ return if Events.processed? event
35
+ get_user(event['sender']).process_member_event room, event
36
+ end
37
+
38
+ # Process power level updates.
39
+ #
40
+ # @param room [Room] The room this event came from.
41
+ # @param data [Hash{String=>Fixnum}] Power level data, a hash of user IDs
42
+ # and their associated power level.
43
+ def process_power_levels(room, data)
44
+ data.each do |id, level|
45
+ get_user(id).process_power_level room, level
46
+ end
47
+ end
48
+
49
+ # Process an invite event for a room.
50
+ #
51
+ # @param room [Room] The room from which the event originated.
52
+ # @param event [Hash] Event data.
53
+ def process_invite(room, event)
54
+ sender = get_user(event['sender'])
55
+ invitee = get_user(event['state_key'])
56
+ invitee.process_invite room, sender, event
57
+ end
58
+
59
+ private
60
+
61
+ # Get the user instance for a specified user ID.
62
+ # If an instance does not exist for the user, one is created and returned.
63
+ #
64
+ # @param id [String] The user ID to get an instance for.
65
+ # @return [User] An instance of User for the specified ID.
66
+ def get_user(id)
67
+ return @users[id] if @users.key? id
68
+ user = User.new id
69
+ @users[id] = user
70
+ broadcast(:added, user)
71
+ user
72
+ end
73
+ end
74
+ end
@@ -1,4 +1,4 @@
1
1
  module Chatrix
2
2
  # The current version of this gem.
3
- VERSION = '1.0.0.pre'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chatrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Hellberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-23 00:00:00.000000000 Z
11
+ date: 2016-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -25,103 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.13'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: wisper
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.12'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.12'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '10.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '10.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rspec
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '3.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '3.0'
69
- - !ruby/object:Gem::Dependency
70
- name: pry
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0.10'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0.10'
83
- - !ruby/object:Gem::Dependency
84
- name: yard
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '0.8'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '0.8'
97
- - !ruby/object:Gem::Dependency
98
- name: redcarpet
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '3.3'
104
- type: :development
33
+ version: '1.6'
34
+ type: :runtime
105
35
  prerelease: false
106
36
  version_requirements: !ruby/object:Gem::Requirement
107
37
  requirements:
108
38
  - - "~>"
109
39
  - !ruby/object:Gem::Version
110
- version: '3.3'
40
+ version: '1.6'
111
41
  - !ruby/object:Gem::Dependency
112
- name: rubocop
42
+ name: bundler
113
43
  requirement: !ruby/object:Gem::Requirement
114
44
  requirements:
115
45
  - - "~>"
116
46
  - !ruby/object:Gem::Version
117
- version: 0.40.0
47
+ version: '1.12'
118
48
  type: :development
119
49
  prerelease: false
120
50
  version_requirements: !ruby/object:Gem::Requirement
121
51
  requirements:
122
52
  - - "~>"
123
53
  - !ruby/object:Gem::Version
124
- version: 0.40.0
54
+ version: '1.12'
125
55
  description:
126
56
  email:
127
57
  - sharparam@sharparam.com
@@ -142,8 +72,27 @@ files:
142
72
  - bin/setup
143
73
  - chatrix.gemspec
144
74
  - lib/chatrix.rb
75
+ - lib/chatrix/api/api_component.rb
76
+ - lib/chatrix/api/media.rb
77
+ - lib/chatrix/api/push.rb
78
+ - lib/chatrix/api/room_actions.rb
79
+ - lib/chatrix/api/rooms.rb
80
+ - lib/chatrix/api/session.rb
81
+ - lib/chatrix/api/users.rb
82
+ - lib/chatrix/client.rb
83
+ - lib/chatrix/components/admin.rb
84
+ - lib/chatrix/components/messaging.rb
85
+ - lib/chatrix/components/permissions.rb
86
+ - lib/chatrix/components/state.rb
87
+ - lib/chatrix/components/timeline.rb
145
88
  - lib/chatrix/errors.rb
89
+ - lib/chatrix/events.rb
146
90
  - lib/chatrix/matrix.rb
91
+ - lib/chatrix/message.rb
92
+ - lib/chatrix/room.rb
93
+ - lib/chatrix/rooms.rb
94
+ - lib/chatrix/user.rb
95
+ - lib/chatrix/users.rb
147
96
  - lib/chatrix/version.rb
148
97
  homepage: https://github.com/Sharparam/chatrix
149
98
  licenses:
@@ -160,9 +109,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
109
  version: '0'
161
110
  required_rubygems_version: !ruby/object:Gem::Requirement
162
111
  requirements:
163
- - - ">"
112
+ - - ">="
164
113
  - !ruby/object:Gem::Version
165
- version: 1.3.1
114
+ version: '0'
166
115
  requirements: []
167
116
  rubyforge_project:
168
117
  rubygems_version: 2.5.1