etwin 0.0.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/.travis.yml +6 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +82 -0
- data/README.md +30 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/etwin.gemspec +37 -0
- data/lib/etwin.rb +27 -0
- data/lib/etwin/_auth.rb +4 -0
- data/lib/etwin/auth.rb +14 -0
- data/lib/etwin/auth/_auth_context.rb +30 -0
- data/lib/etwin/auth/auth_context.rb +9 -0
- data/lib/etwin/auth/auth_scope.rb +25 -0
- data/lib/etwin/auth/auth_type.rb +26 -0
- data/lib/etwin/auth/guest_auth_context.rb +71 -0
- data/lib/etwin/auth/user_auth_context.rb +83 -0
- data/lib/etwin/client.rb +11 -0
- data/lib/etwin/client/auth.rb +66 -0
- data/lib/etwin/client/etwin_client.rb +17 -0
- data/lib/etwin/client/http_etwin_client.rb +36 -0
- data/lib/etwin/core.rb +10 -0
- data/lib/etwin/core/object_type.rb +35 -0
- data/lib/etwin/hammerfest.rb +13 -0
- data/lib/etwin/hammerfest/hammerfest_server.rb +27 -0
- data/lib/etwin/hammerfest/hammerfest_user_id.rb +57 -0
- data/lib/etwin/hammerfest/hammerfest_username.rb +57 -0
- data/lib/etwin/hammerfest/short_hammerfest_user.rb +103 -0
- data/lib/etwin/link.rb +15 -0
- data/lib/etwin/link/hammerfest_link.rb +106 -0
- data/lib/etwin/link/link_action.rb +93 -0
- data/lib/etwin/link/twinoid_link.rb +106 -0
- data/lib/etwin/link/versioned_hammerfest_link.rb +93 -0
- data/lib/etwin/link/versioned_links.rb +123 -0
- data/lib/etwin/link/versioned_twinoid_link.rb +93 -0
- data/lib/etwin/twinoid.rb +12 -0
- data/lib/etwin/twinoid/short_twinoid_user.rb +93 -0
- data/lib/etwin/twinoid/twinoid_user_display_name.rb +57 -0
- data/lib/etwin/twinoid/twinoid_user_id.rb +57 -0
- data/lib/etwin/user.rb +15 -0
- data/lib/etwin/user/short_user.rb +93 -0
- data/lib/etwin/user/user.rb +123 -0
- data/lib/etwin/user/user_display_name.rb +57 -0
- data/lib/etwin/user/user_display_name_version.rb +83 -0
- data/lib/etwin/user/user_display_name_versions.rb +83 -0
- data/lib/etwin/user/user_id.rb +57 -0
- data/lib/etwin/version.rb +6 -0
- data/sorbet/config +2 -0
- data/sorbet/rbi/gems/ast.rbi +48 -0
- data/sorbet/rbi/gems/debase.rbi +67 -0
- data/sorbet/rbi/gems/irb.rbi +352 -0
- data/sorbet/rbi/gems/parallel.rbi +83 -0
- data/sorbet/rbi/gems/parser.rbi +1405 -0
- data/sorbet/rbi/gems/rainbow.rbi +118 -0
- data/sorbet/rbi/gems/rake.rbi +644 -0
- data/sorbet/rbi/gems/regexp_parser.rbi +914 -0
- data/sorbet/rbi/gems/reline.rbi +556 -0
- data/sorbet/rbi/gems/rexml.rbi +605 -0
- data/sorbet/rbi/gems/rspec-core.rbi +1920 -0
- data/sorbet/rbi/gems/rspec-expectations.rbi +1148 -0
- data/sorbet/rbi/gems/rspec-mocks.rbi +1090 -0
- data/sorbet/rbi/gems/rspec-support.rbi +280 -0
- data/sorbet/rbi/gems/rspec.rbi +15 -0
- data/sorbet/rbi/gems/rubocop-ast.rbi +1338 -0
- data/sorbet/rbi/gems/rubocop.rbi +7491 -0
- data/sorbet/rbi/gems/ruby-debug-ide.rbi +608 -0
- data/sorbet/rbi/gems/ruby-progressbar.rbi +305 -0
- data/sorbet/rbi/gems/unicode-display_width.rbi +17 -0
- data/sorbet/rbi/hidden-definitions/errors.txt +4905 -0
- data/sorbet/rbi/hidden-definitions/hidden.rbi +9193 -0
- data/sorbet/rbi/sorbet-typed/lib/rainbow/all/rainbow.rbi +276 -0
- data/sorbet/rbi/todo.rbi +7 -0
- metadata +220 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Auth
|
6
|
+
# User authentication context
|
7
|
+
class UserAuthContext
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
final!
|
12
|
+
|
13
|
+
sig(:final) { returns(AuthScope) }
|
14
|
+
attr_reader :scope
|
15
|
+
|
16
|
+
sig(:final) { returns(Etwin::User::ShortUser) }
|
17
|
+
attr_reader :user
|
18
|
+
|
19
|
+
sig(:final) { returns(T::Boolean) }
|
20
|
+
attr_reader :is_administrator
|
21
|
+
|
22
|
+
sig(:final) { params(scope: AuthScope, user: Etwin::User::ShortUser, is_administrator: T::Boolean).void }
|
23
|
+
def initialize(scope, user, is_administrator)
|
24
|
+
@scope = T.let(scope, AuthScope)
|
25
|
+
@user = T.let(user, Etwin::User::ShortUser)
|
26
|
+
@is_administrator = T.let(is_administrator, T::Boolean)
|
27
|
+
freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
sig(:final) { params(other: BasicObject).returns(T::Boolean) }
|
31
|
+
def ==(other)
|
32
|
+
case other
|
33
|
+
when UserAuthContext
|
34
|
+
@scope == other.scope && @user == other.user && @is_administrator == other.is_administrator
|
35
|
+
else
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
sig(:final) { returns(Integer) }
|
41
|
+
def hash
|
42
|
+
[@scope, @user, @is_administrator].hash
|
43
|
+
end
|
44
|
+
|
45
|
+
# https://github.com/sorbet/sorbet/blob/master/rbi/stdlib/json.rbi#L194
|
46
|
+
sig(:final) { params(opts: T.untyped).returns(String) }
|
47
|
+
def to_json(opts = nil)
|
48
|
+
JSON.generate(as_json, opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
sig(:final) { returns(T::Hash[String, T.untyped]) }
|
52
|
+
def as_json
|
53
|
+
{
|
54
|
+
'scope' => @scope.serialize,
|
55
|
+
'user' => @user.as_json,
|
56
|
+
'is_administrator' => @is_administrator
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
sig(:final) { returns(String) }
|
61
|
+
def inspect
|
62
|
+
"UserAuthContext(scope=#{@scope.inspect},user=#{@user.inspect},is_administrator=#{@is_administrator.inspect})"
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
extend T::Sig
|
67
|
+
|
68
|
+
sig(:final) { params(json_str: String).returns(T.attached_class) }
|
69
|
+
def from_json(json_str)
|
70
|
+
deserialize JSON.parse(json_str)
|
71
|
+
end
|
72
|
+
|
73
|
+
sig(:final) { params(raw: T.untyped).returns(T.attached_class) }
|
74
|
+
def deserialize(raw)
|
75
|
+
scope = AuthScope.deserialize(raw['scope'])
|
76
|
+
user = Etwin::User::ShortUser.deserialize(raw['user'])
|
77
|
+
is_administrator = raw['is_administrator']
|
78
|
+
new(scope, user, is_administrator)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/etwin/client.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Client
|
6
|
+
# Eternal-Twin client authentication data
|
7
|
+
class Auth
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
final!
|
12
|
+
|
13
|
+
sig(:final) { returns(T.nilable(String)) }
|
14
|
+
attr_reader :authorization_header
|
15
|
+
|
16
|
+
sig(:final) { params(authorization_header: T.nilable(String)).void }
|
17
|
+
def initialize(authorization_header)
|
18
|
+
@authorization_header = T.let(authorization_header, T.nilable(String))
|
19
|
+
freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
sig(:final) { params(other: BasicObject).returns(T::Boolean) }
|
23
|
+
def ==(other)
|
24
|
+
case other
|
25
|
+
when Auth
|
26
|
+
@authorization_header == other.authorization_header
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
sig(:final) { returns(Integer) }
|
33
|
+
def hash
|
34
|
+
[@authorization_header].hash
|
35
|
+
end
|
36
|
+
|
37
|
+
sig(:final) { returns(String) }
|
38
|
+
def inspect
|
39
|
+
PP.singleline_pp(self, String.new)
|
40
|
+
end
|
41
|
+
|
42
|
+
sig(:final) { params(pp: T.untyped).returns(T.untyped) }
|
43
|
+
def pretty_print(pp)
|
44
|
+
pp.group(0, "#{self.class.name}(", ')') do
|
45
|
+
pp.nest 1 do
|
46
|
+
pp.breakable ''
|
47
|
+
pp.text 'authorization_header='
|
48
|
+
pp.pp @authorization_header
|
49
|
+
end
|
50
|
+
pp.breakable ''
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Guest = new(nil)
|
55
|
+
|
56
|
+
class << self
|
57
|
+
extend T::Sig
|
58
|
+
|
59
|
+
sig(:final) { params(key: String).returns(T.attached_class) }
|
60
|
+
def from_token(key)
|
61
|
+
new("Bearer #{key}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Client
|
6
|
+
# Etwin client interface
|
7
|
+
class EtwinClient
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
interface!
|
12
|
+
|
13
|
+
sig { abstract.params(auth: Auth, user_id: UserId).returns(User) }
|
14
|
+
def get_user(auth, user_id); end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Client
|
6
|
+
# HTTP Etwin client interface
|
7
|
+
class HttpEtwinClient
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
include EtwinClient
|
12
|
+
|
13
|
+
final!
|
14
|
+
|
15
|
+
sig(:final) { params(base_uri: URI::HTTP).void }
|
16
|
+
def initialize(base_uri)
|
17
|
+
@base_uri = T.let(base_uri.freeze, URI::HTTP)
|
18
|
+
freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
sig(:final) { params(auth: Auth, user_id: UserId).returns(User) }
|
22
|
+
def get_user(auth, user_id)
|
23
|
+
uri = resolve(['users', user_id.to_s])
|
24
|
+
res = Faraday.get uri
|
25
|
+
pp res
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
sig(:final) { params(segments: T::Array[String]).returns(URI::HTTP) }
|
31
|
+
def resolve(segments)
|
32
|
+
@base_uri.merge("api/v1/#{ segments * '/'}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/etwin/core.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Core
|
6
|
+
# Object type enum
|
7
|
+
class ObjectType < T::Enum
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
enums do
|
11
|
+
ClientForumActor = new('ClientForumActor')
|
12
|
+
ForumPost = new('ForumPost')
|
13
|
+
ForumPostRevision = new('ForumPostRevision')
|
14
|
+
ForumSection = new('ForumSection')
|
15
|
+
ForumThread = new('ForumThread')
|
16
|
+
HammerfestUser = new('HammerfestUser')
|
17
|
+
OauthClient = new('OauthClient')
|
18
|
+
RoleForumActor = new('RoleForumActor')
|
19
|
+
TwinoidUser = new('TwinoidUser')
|
20
|
+
User = new('User')
|
21
|
+
UserForumActor = new('UserForumActor')
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { returns(String) }
|
25
|
+
def to_s
|
26
|
+
T.cast(serialize, String)
|
27
|
+
end
|
28
|
+
|
29
|
+
sig { returns(String) }
|
30
|
+
def inspect
|
31
|
+
"ObjectType(#{self})"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
# Hammerfest module
|
6
|
+
module Hammerfest
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative './hammerfest/hammerfest_server'
|
11
|
+
require_relative './hammerfest/hammerfest_user_id'
|
12
|
+
require_relative './hammerfest/hammerfest_username'
|
13
|
+
require_relative './hammerfest/short_hammerfest_user'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Hammerfest
|
6
|
+
# A valid Hammerfest server
|
7
|
+
class HammerfestServer < T::Enum
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
enums do
|
11
|
+
HammerfestEs = new('hammerfest.es')
|
12
|
+
HammerfestFr = new('hammerfest.fr')
|
13
|
+
HfestNet = new('hfest.net')
|
14
|
+
end
|
15
|
+
|
16
|
+
sig { returns(String) }
|
17
|
+
def to_s
|
18
|
+
T.cast(serialize, String)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig { returns(String) }
|
22
|
+
def inspect
|
23
|
+
"HammerfestServer(#{self})"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Hammerfest
|
6
|
+
# A valid Hammerfest user id
|
7
|
+
class HammerfestUserId
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
final!
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
sig(:final) { returns(String) }
|
16
|
+
attr_reader :inner
|
17
|
+
|
18
|
+
public
|
19
|
+
|
20
|
+
sig(:final) { params(inner: String).void }
|
21
|
+
def initialize(inner)
|
22
|
+
@inner = T.let(inner.freeze, String)
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
sig(:final) { params(other: BasicObject).returns(T::Boolean) }
|
27
|
+
def ==(other)
|
28
|
+
case other
|
29
|
+
when HammerfestUserId
|
30
|
+
@inner == other.inner
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
sig(:final) { returns(Integer) }
|
37
|
+
def hash
|
38
|
+
@inner.hash
|
39
|
+
end
|
40
|
+
|
41
|
+
sig(:final) { returns(String) }
|
42
|
+
def to_s
|
43
|
+
@inner
|
44
|
+
end
|
45
|
+
|
46
|
+
sig(:final) { returns(String) }
|
47
|
+
def as_json
|
48
|
+
@inner
|
49
|
+
end
|
50
|
+
|
51
|
+
sig(:final) { returns(String) }
|
52
|
+
def inspect
|
53
|
+
"HammerfestUserId(#{@inner})"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Hammerfest
|
6
|
+
# A valid Hammerfest username
|
7
|
+
class HammerfestUsername
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
final!
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
sig(:final) { returns(String) }
|
16
|
+
attr_reader :inner
|
17
|
+
|
18
|
+
public
|
19
|
+
|
20
|
+
sig(:final) { params(inner: String).void }
|
21
|
+
def initialize(inner)
|
22
|
+
@inner = T.let(inner.freeze, String)
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
sig(:final) { params(other: BasicObject).returns(T::Boolean) }
|
27
|
+
def ==(other)
|
28
|
+
case other
|
29
|
+
when HammerfestUsername
|
30
|
+
@inner == other.inner
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
sig(:final) { returns(Integer) }
|
37
|
+
def hash
|
38
|
+
@inner.hash
|
39
|
+
end
|
40
|
+
|
41
|
+
sig(:final) { returns(String) }
|
42
|
+
def to_s
|
43
|
+
@inner
|
44
|
+
end
|
45
|
+
|
46
|
+
sig(:final) { returns(String) }
|
47
|
+
def as_json
|
48
|
+
@inner
|
49
|
+
end
|
50
|
+
|
51
|
+
sig(:final) { returns(String) }
|
52
|
+
def inspect
|
53
|
+
"HammerfestUsername(#{@inner})"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Etwin
|
5
|
+
module Hammerfest
|
6
|
+
# Hammerfest user reference with username
|
7
|
+
class ShortHammerfestUser
|
8
|
+
extend T::Helpers
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
final!
|
12
|
+
|
13
|
+
sig(:final) { returns(HammerfestServer) }
|
14
|
+
attr_reader :server
|
15
|
+
|
16
|
+
sig(:final) { returns(HammerfestUserId) }
|
17
|
+
attr_reader :id
|
18
|
+
|
19
|
+
sig(:final) { returns(HammerfestUsername) }
|
20
|
+
attr_reader :username
|
21
|
+
|
22
|
+
sig(:final) { params(server: HammerfestServer, id: HammerfestUserId, username: HammerfestUsername).void }
|
23
|
+
def initialize(server, id, username)
|
24
|
+
@server = T.let(server, HammerfestServer)
|
25
|
+
@id = T.let(id, HammerfestUserId)
|
26
|
+
@username = T.let(username, HammerfestUsername)
|
27
|
+
freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
sig(:final) { params(other: BasicObject).returns(T::Boolean) }
|
31
|
+
def ==(other)
|
32
|
+
case other
|
33
|
+
when ShortHammerfestUser
|
34
|
+
@server == other.server && @id == other.id && @username == other.username
|
35
|
+
else
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
sig(:final) { returns(Integer) }
|
41
|
+
def hash
|
42
|
+
[@server, @id, @username].hash
|
43
|
+
end
|
44
|
+
|
45
|
+
# https://github.com/sorbet/sorbet/blob/master/rbi/stdlib/json.rbi#L194
|
46
|
+
sig(:final) { params(opts: T.untyped).returns(String) }
|
47
|
+
def to_json(opts = nil)
|
48
|
+
JSON.generate(as_json, opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
sig(:final) { returns(T::Hash[String, T.untyped]) }
|
52
|
+
def as_json
|
53
|
+
{
|
54
|
+
'server' => @server.serialize,
|
55
|
+
'id' => @id.as_json,
|
56
|
+
'username' => @username.as_json
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
sig(:final) { returns(String) }
|
61
|
+
def inspect
|
62
|
+
PP.singleline_pp(self, String.new)
|
63
|
+
end
|
64
|
+
|
65
|
+
sig(:final) { params(pp: T.untyped).returns(T.untyped) }
|
66
|
+
def pretty_print(pp) # rubocop:disable Metrics/MethodLength
|
67
|
+
pp.group(0, "#{self.class.name}(", ')') do
|
68
|
+
pp.nest 1 do
|
69
|
+
pp.breakable ''
|
70
|
+
pp.text 'server='
|
71
|
+
pp.pp @server
|
72
|
+
pp.text ','
|
73
|
+
pp.breakable ''
|
74
|
+
pp.text 'id='
|
75
|
+
pp.pp @id
|
76
|
+
pp.text ','
|
77
|
+
pp.breakable ''
|
78
|
+
pp.text 'username='
|
79
|
+
pp.pp @username
|
80
|
+
end
|
81
|
+
pp.breakable ''
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class << self
|
86
|
+
extend T::Sig
|
87
|
+
|
88
|
+
sig(:final) { params(json_str: String).returns(T.attached_class) }
|
89
|
+
def from_json(json_str)
|
90
|
+
deserialize JSON.parse(json_str)
|
91
|
+
end
|
92
|
+
|
93
|
+
sig(:final) { params(raw: T.untyped).returns(T.attached_class) }
|
94
|
+
def deserialize(raw)
|
95
|
+
server = HammerfestServer.deserialize(raw['server'])
|
96
|
+
id = HammerfestUserId.new(raw['id'])
|
97
|
+
username = HammerfestUsername.new(raw['username'])
|
98
|
+
new(server, id, username)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|