mihari 5.6.1 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/README.md +1 -0
  4. data/config.ru +1 -1
  5. data/docs/analyzers/fofa.md +31 -0
  6. data/docs/analyzers/index.md +1 -0
  7. data/frontend/package-lock.json +183 -186
  8. data/frontend/package.json +10 -10
  9. data/frontend/src/components/alert/Form.vue +1 -14
  10. data/frontend/src/components/artifact/AS.vue +2 -8
  11. data/frontend/src/components/artifact/DnsRecords.vue +2 -8
  12. data/frontend/src/components/artifact/ReverseDnsNames.vue +2 -10
  13. data/frontend/src/components/artifact/WhoisRecord.vue +1 -1
  14. data/lib/mihari/{base.rb → actor.rb} +27 -3
  15. data/lib/mihari/analyzers/base.rb +16 -20
  16. data/lib/mihari/analyzers/binaryedge.rb +4 -1
  17. data/lib/mihari/analyzers/censys.rb +5 -3
  18. data/lib/mihari/analyzers/circl.rb +4 -1
  19. data/lib/mihari/analyzers/crtsh.rb +4 -1
  20. data/lib/mihari/analyzers/dnstwister.rb +4 -1
  21. data/lib/mihari/analyzers/feed.rb +3 -0
  22. data/lib/mihari/analyzers/fofa.rb +65 -0
  23. data/lib/mihari/analyzers/greynoise.rb +4 -1
  24. data/lib/mihari/analyzers/hunterhow.rb +7 -2
  25. data/lib/mihari/analyzers/onyphe.rb +4 -1
  26. data/lib/mihari/analyzers/otx.rb +4 -1
  27. data/lib/mihari/analyzers/passivetotal.rb +5 -2
  28. data/lib/mihari/analyzers/pulsedive.rb +4 -1
  29. data/lib/mihari/analyzers/securitytrails.rb +5 -2
  30. data/lib/mihari/analyzers/shodan.rb +4 -1
  31. data/lib/mihari/analyzers/urlscan.rb +5 -2
  32. data/lib/mihari/analyzers/virustotal.rb +9 -6
  33. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
  34. data/lib/mihari/analyzers/zoomeye.rb +8 -5
  35. data/lib/mihari/cli/alert.rb +3 -0
  36. data/lib/mihari/cli/base.rb +3 -0
  37. data/lib/mihari/cli/database.rb +3 -0
  38. data/lib/mihari/cli/main.rb +3 -0
  39. data/lib/mihari/cli/rule.rb +3 -0
  40. data/lib/mihari/clients/base.rb +3 -0
  41. data/lib/mihari/clients/binaryedge.rb +5 -2
  42. data/lib/mihari/clients/censys.rb +7 -4
  43. data/lib/mihari/clients/circl.rb +3 -0
  44. data/lib/mihari/clients/crtsh.rb +5 -2
  45. data/lib/mihari/clients/dnstwister.rb +3 -0
  46. data/lib/mihari/clients/fofa.rb +83 -0
  47. data/lib/mihari/clients/greynoise.rb +5 -2
  48. data/lib/mihari/clients/hunterhow.rb +5 -2
  49. data/lib/mihari/clients/misp.rb +3 -0
  50. data/lib/mihari/clients/onyphe.rb +5 -2
  51. data/lib/mihari/clients/otx.rb +3 -0
  52. data/lib/mihari/clients/passivetotal.rb +7 -4
  53. data/lib/mihari/clients/publsedive.rb +4 -1
  54. data/lib/mihari/clients/securitytrails.rb +6 -3
  55. data/lib/mihari/clients/shodan.rb +5 -2
  56. data/lib/mihari/clients/the_hive.rb +3 -0
  57. data/lib/mihari/clients/urlscan.rb +7 -4
  58. data/lib/mihari/clients/virustotal.rb +5 -2
  59. data/lib/mihari/clients/zoomeye.rb +3 -0
  60. data/lib/mihari/commands/alert.rb +5 -14
  61. data/lib/mihari/commands/database.rb +3 -0
  62. data/lib/mihari/commands/rule.rb +11 -11
  63. data/lib/mihari/commands/search.rb +9 -6
  64. data/lib/mihari/commands/version.rb +3 -0
  65. data/lib/mihari/commands/web.rb +4 -1
  66. data/lib/mihari/config.rb +139 -150
  67. data/lib/mihari/constants.rb +1 -1
  68. data/lib/mihari/database.rb +6 -0
  69. data/lib/mihari/emitters/base.rb +16 -25
  70. data/lib/mihari/emitters/database.rb +10 -9
  71. data/lib/mihari/emitters/misp.rb +20 -41
  72. data/lib/mihari/emitters/slack.rb +16 -13
  73. data/lib/mihari/emitters/the_hive.rb +18 -46
  74. data/lib/mihari/emitters/webhook.rb +34 -23
  75. data/lib/mihari/enrichers/base.rb +16 -15
  76. data/lib/mihari/enrichers/google_public_dns.rb +6 -5
  77. data/lib/mihari/enrichers/ipinfo.rb +10 -8
  78. data/lib/mihari/enrichers/shodan.rb +4 -6
  79. data/lib/mihari/enrichers/whois.rb +13 -10
  80. data/lib/mihari/errors.rb +6 -0
  81. data/lib/mihari/feed/parser.rb +3 -0
  82. data/lib/mihari/feed/reader.rb +3 -0
  83. data/lib/mihari/http.rb +6 -0
  84. data/lib/mihari/mixins/autonomous_system.rb +3 -0
  85. data/lib/mihari/mixins/configurable.rb +3 -0
  86. data/lib/mihari/mixins/error_notification.rb +3 -0
  87. data/lib/mihari/mixins/falsepositive.rb +3 -0
  88. data/lib/mihari/mixins/refang.rb +3 -0
  89. data/lib/mihari/mixins/retriable.rb +6 -2
  90. data/lib/mihari/models/alert.rb +78 -73
  91. data/lib/mihari/models/artifact.rb +186 -178
  92. data/lib/mihari/models/autonomous_system.rb +25 -20
  93. data/lib/mihari/models/cpe.rb +24 -19
  94. data/lib/mihari/models/dns.rb +27 -22
  95. data/lib/mihari/models/geolocation.rb +25 -20
  96. data/lib/mihari/models/port.rb +24 -19
  97. data/lib/mihari/models/reverse_dns.rb +24 -19
  98. data/lib/mihari/models/rule.rb +71 -66
  99. data/lib/mihari/models/tag.rb +8 -3
  100. data/lib/mihari/models/tagging.rb +8 -3
  101. data/lib/mihari/models/whois.rb +20 -17
  102. data/lib/mihari/rule.rb +357 -0
  103. data/lib/mihari/schemas/alert.rb +3 -0
  104. data/lib/mihari/schemas/analyzer.rb +105 -87
  105. data/lib/mihari/schemas/emitter.rb +12 -5
  106. data/lib/mihari/schemas/enricher.rb +11 -4
  107. data/lib/mihari/schemas/macros.rb +4 -0
  108. data/lib/mihari/schemas/mixins.rb +20 -0
  109. data/lib/mihari/schemas/rule.rb +6 -10
  110. data/lib/mihari/service.rb +16 -0
  111. data/lib/mihari/services/alert_builder.rb +8 -5
  112. data/lib/mihari/services/alert_proxy.rb +16 -7
  113. data/lib/mihari/services/alert_runner.rb +10 -14
  114. data/lib/mihari/services/rule_builder.rb +10 -7
  115. data/lib/mihari/services/rule_runner.rb +11 -13
  116. data/lib/mihari/structs/binaryedge.rb +14 -29
  117. data/lib/mihari/structs/censys.rb +54 -133
  118. data/lib/mihari/structs/config.rb +20 -31
  119. data/lib/mihari/structs/filters.rb +38 -0
  120. data/lib/mihari/structs/fofa.rb +44 -0
  121. data/lib/mihari/structs/google_public_dns.rb +10 -28
  122. data/lib/mihari/structs/greynoise.rb +38 -89
  123. data/lib/mihari/structs/hunterhow.rb +27 -25
  124. data/lib/mihari/structs/ipinfo.rb +14 -35
  125. data/lib/mihari/structs/onyphe.rb +36 -81
  126. data/lib/mihari/structs/shodan.rb +53 -118
  127. data/lib/mihari/structs/urlscan.rb +27 -66
  128. data/lib/mihari/structs/virustotal_intelligence.rb +23 -59
  129. data/lib/mihari/type_checker.rb +4 -0
  130. data/lib/mihari/types.rb +3 -0
  131. data/lib/mihari/version.rb +1 -1
  132. data/lib/mihari/web/api.rb +15 -10
  133. data/lib/mihari/web/app.rb +59 -54
  134. data/lib/mihari/web/endpoints/alerts.rb +94 -89
  135. data/lib/mihari/web/endpoints/artifacts.rb +115 -110
  136. data/lib/mihari/web/endpoints/configs.rb +18 -13
  137. data/lib/mihari/web/endpoints/ip_addresses.rb +21 -16
  138. data/lib/mihari/web/endpoints/rules.rb +202 -204
  139. data/lib/mihari/web/endpoints/tags.rb +41 -36
  140. data/lib/mihari/web/middleware/connection_adapter.rb +16 -9
  141. data/lib/mihari/web/middleware/error_notification_adapter.rb +17 -10
  142. data/lib/mihari/web/public/assets/{index-9cc489e6.js → index-821134e2.js} +54 -54
  143. data/lib/mihari/web/public/assets/mode-yaml-24faa242.js +8 -0
  144. data/lib/mihari/web/public/index.html +1 -1
  145. data/lib/mihari.rb +30 -13
  146. data/mihari.gemspec +9 -3
  147. data/mkdocs.yml +3 -2
  148. data/requirements.txt +1 -1
  149. metadata +44 -26
  150. data/lib/mihari/analyzers/rule.rb +0 -232
  151. data/lib/mihari/services/rule_proxy.rb +0 -182
  152. data/lib/mihari/templates/rule.yml.erb +0 -5
  153. data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
@@ -3,38 +3,21 @@
3
3
  module Mihari
4
4
  module Structs
5
5
  class Config < Dry::Struct
6
+ # @!attribute [r] name
7
+ # @return [String]
6
8
  attribute :name, Types::String
7
- attribute :type, Types::String
8
- attribute :is_configured, Types::Bool
9
- attribute :values, Types.Array(Types::Hash).optional
10
9
 
11
- #
12
- # @return [String]
13
- #
14
- def name
15
- attributes[:name]
16
- end
17
-
18
- #
19
- # @return [String]
20
- #
21
- def type
22
- attributes[:type]
23
- end
10
+ # @!attribute [r] type
11
+ # @return [String]
12
+ attribute :type, Types::String
24
13
 
25
- #
26
- # @return [Boolean]
27
- #
28
- def is_configured
29
- attributes[:is_configured]
30
- end
14
+ # @!attribute [r] is_configured
15
+ # @return [Boolean]
16
+ attribute :is_configured, Types::Bool
31
17
 
32
- #
33
- # @return [Array<Hash>]
34
- #
35
- def values
36
- attributes[:values]
37
- end
18
+ # @!attribute [r] values
19
+ # @return [Array<Hash>, nil]
20
+ attribute :values, Types.Array(Types::Hash).optional
38
21
 
39
22
  class << self
40
23
  #
@@ -61,8 +44,14 @@ module Mihari
61
44
  #
62
45
  def get_dummy(klass)
63
46
  type = get_type(klass)
64
- is_analyzer = type == "Analyzer"
65
- is_analyzer ? klass.new("dummy") : klass.new(artifacts: [], rule: nil)
47
+ case type
48
+ when "Analyzer"
49
+ klass.new("dummy")
50
+ when "Emitter"
51
+ klass.new(rule: nil)
52
+ else
53
+ klass.new
54
+ end
66
55
  end
67
56
 
68
57
  #
@@ -71,7 +60,7 @@ module Mihari
71
60
  # @return [Mihari::Structs::Config, nil] config
72
61
  #
73
62
  def from_class(klass)
74
- return nil if klass == Mihari::Analyzers::Rule
63
+ return nil if klass == Mihari::Rule
75
64
 
76
65
  type = get_type(klass)
77
66
  return nil if type.nil?
@@ -5,15 +5,34 @@ module Mihari
5
5
  module Filters
6
6
  module Alert
7
7
  class SearchFilter < Dry::Struct
8
+ # @!attribute [r] artifact_data
9
+ # @return [String, nil]
8
10
  attribute? :artifact_data, Types::String.optional
11
+
12
+ # @!attribute [r] rule_id
13
+ # @return [String, nil]
9
14
  attribute? :rule_id, Types::String.optional
15
+
16
+ # @!attribute [r] tag_name
17
+ # @return [String, nil]
10
18
  attribute? :tag_name, Types::String.optional
19
+
20
+ # @!attribute [r] from_at
21
+ # @return [DateTime, nil]
11
22
  attribute? :from_at, Types::DateTime.optional
23
+
24
+ # @!attribute [r] to_at
25
+ # @return [DateTime, nil]
12
26
  attribute? :to_at, Types::DateTime.optional
13
27
  end
14
28
 
15
29
  class SearchFilterWithPagination < SearchFilter
30
+ # @!attribute [r] page
31
+ # @return [Integer, nil]
16
32
  attribute? :page, Types::Int.default(1)
33
+
34
+ # @!attribute [r] limit
35
+ # @return [Integer, nil]
17
36
  attribute? :limit, Types::Int.default(10)
18
37
 
19
38
  def without_pagination
@@ -30,15 +49,34 @@ module Mihari
30
49
 
31
50
  module Rule
32
51
  class SearchFilter < Dry::Struct
52
+ # @!attribute [r] description
53
+ # @return [String, nil]
33
54
  attribute? :description, Types::String.optional
55
+
56
+ # @!attribute [r] tag_name
57
+ # @return [String, nil]
34
58
  attribute? :tag_name, Types::String.optional
59
+
60
+ # @!attribute [r] title
61
+ # @return [String, nil]
35
62
  attribute? :title, Types::String.optional
63
+
64
+ # @!attribute [r] from_at
65
+ # @return [DateTime, nil]
36
66
  attribute? :from_at, Types::DateTime.optional
67
+
68
+ # @!attribute [r] to_at
69
+ # @return [DateTime, nil]
37
70
  attribute? :to_at, Types::DateTime.optional
38
71
  end
39
72
 
40
73
  class SearchFilterWithPagination < SearchFilter
74
+ # @!attribute [r] page
75
+ # @return [Integer, nil]
41
76
  attribute? :page, Types::Int.default(1)
77
+
78
+ # @!attribute [r] limit
79
+ # @return [Integer, nil]
42
80
  attribute? :limit, Types::Int.default(10)
43
81
 
44
82
  def without_pagination
@@ -0,0 +1,44 @@
1
+ module Mihari
2
+ module Structs
3
+ module Fofa
4
+ class Response < Dry::Struct
5
+ # @!attribute [r] error
6
+ # @return [Boolean]
7
+ attribute :error, Types::Bool
8
+
9
+ # @!attribute [r] size
10
+ # @return [Integer, nil]
11
+ attribute? :size, Types::Int.optional
12
+
13
+ # @!attribute [r] page
14
+ # @return [Integer, nil]
15
+ attribute? :page, Types::Int.optional
16
+
17
+ # @!attribute [r] mode
18
+ # @return [String, nil]
19
+ attribute? :mode, Types::String.optional
20
+
21
+ # @!attribute [r] query
22
+ # @return [String, nil]
23
+ attribute? :query, Types::String.optional
24
+
25
+ # @!attribute [r] results
26
+ # @return [Array<String>, nil]
27
+ attribute? :results, Types.Array(Types.Array(Types::String)).optional
28
+
29
+ class << self
30
+ def from_dynamic!(d)
31
+ new(
32
+ error: d.fetch("error"),
33
+ size: d["size"],
34
+ page: d["page"],
35
+ mode: d["mode"],
36
+ query: d["query"],
37
+ results: d["results"]
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -12,30 +12,17 @@ module Mihari
12
12
  }.freeze
13
13
 
14
14
  class Answer < Dry::Struct
15
+ # @!attribute [r] name
16
+ # @return [String]
15
17
  attribute :name, Types::String
16
- attribute :data, Types::String
17
- attribute :resource_type, Types::String
18
18
 
19
- #
20
- # @return [String]
21
- #
22
- def name
23
- attributes[:name]
24
- end
25
-
26
- #
27
- # @return [String]
28
- #
29
- def data
30
- attributes[:data]
31
- end
19
+ # @!attribute [r] data
20
+ # @return [String]
21
+ attribute :data, Types::String
32
22
 
33
- #
34
- # @return [String]
35
- #
36
- def resource_type
37
- attributes[:resource_type]
38
- end
23
+ # @!attribute [r] resource_type
24
+ # @return [String]
25
+ attribute :resource_type, Types::String
39
26
 
40
27
  class << self
41
28
  #
@@ -56,15 +43,10 @@ module Mihari
56
43
  end
57
44
 
58
45
  class Response < Dry::Struct
46
+ # @!attribute [r] answers
47
+ # @return [Array<Answer>]
59
48
  attribute :answers, Types.Array(Answer)
60
49
 
61
- #
62
- # @return [Array<Answer>]
63
- #
64
- def answers
65
- attributes[:answers]
66
- end
67
-
68
50
  class << self
69
51
  #
70
52
  # @param [Hash] d
@@ -6,43 +6,30 @@ module Mihari
6
6
  class Metadata < Dry::Struct
7
7
  include Mixins::AutonomousSystem
8
8
 
9
+ # @!attribute [r] country
10
+ # @return [String]
9
11
  attribute :country, Types::String
10
- attribute :country_code, Types::String
11
- attribute :asn, Types::String
12
-
13
- #
14
- # @return [String]
15
- #
16
- def country
17
- attributes[:country]
18
- end
19
12
 
20
- #
21
- # @return [String]
22
- #
23
- def country_code
24
- attributes[:country_code]
25
- end
13
+ # @!attribute [r] country_code
14
+ # @return [String]
15
+ attribute :country_code, Types::String
26
16
 
27
- #
28
- # @return [String]
29
- #
30
- def asn
31
- attributes[:asn]
32
- end
17
+ # @!attribute [r] asn
18
+ # @return [String]
19
+ attribute :asn, Types::String
33
20
 
34
21
  #
35
22
  # @return [Mihari::AutonomousSystem]
36
23
  #
37
24
  def as
38
- Mihari::AutonomousSystem.new(asn: normalize_asn(asn))
25
+ Mihari::Models::AutonomousSystem.new(asn: normalize_asn(asn))
39
26
  end
40
27
 
41
28
  #
42
29
  # @return [Mihari::Geolocation]
43
30
  #
44
31
  def geolocation
45
- Mihari::Geolocation.new(
32
+ Mihari::Models::Geolocation.new(
46
33
  country: country,
47
34
  country_code: country_code
48
35
  )
@@ -66,36 +53,23 @@ module Mihari
66
53
  end
67
54
 
68
55
  class Datum < Dry::Struct
56
+ # @!attribute [r] ip
57
+ # @return [String]
69
58
  attribute :ip, Types::String
70
- attribute :metadata, Metadata
71
- attribute :metadata_, Types::Hash
72
59
 
73
- #
74
- # @return [String]
75
- #
76
- def ip
77
- attributes[:ip]
78
- end
79
-
80
- #
81
- # @return [Metadata]
82
- #
83
- def metadata
84
- attributes[:metadata]
85
- end
60
+ # @!attribute [r] metadata
61
+ # @return [Metadata]
62
+ attribute :metadata, Metadata
86
63
 
87
- #
88
- # @return [Hash]
89
- #
90
- def metadata_
91
- attributes[:metadata_]
92
- end
64
+ # @!attribute [r] metadata_
65
+ # @return [Hash]
66
+ attribute :metadata_, Types::Hash
93
67
 
94
68
  #
95
- # @return [Mihari::Artifact]
69
+ # @return [Mihari::Models::Artifact]
96
70
  #
97
71
  def artifact
98
- Mihari::Artifact.new(
72
+ Mihari::Models::Artifact.new(
99
73
  data: ip,
100
74
  metadata: metadata_,
101
75
  autonomous_system: metadata.as,
@@ -121,57 +95,32 @@ module Mihari
121
95
  end
122
96
 
123
97
  class Response < Dry::Struct
98
+ # @!attribute [r] complete
99
+ # @return [Boolean]
124
100
  attribute :complete, Types::Bool
125
- attribute :count, Types::Int
126
- attribute :data, Types.Array(Datum)
127
- attribute :message, Types::String
128
- attribute :query, Types::String
129
- attribute :scroll, Types::String.optional
130
-
131
- #
132
- # @return [Boolean]
133
- #
134
- def complete
135
- attributes[:complete]
136
- end
137
101
 
138
- #
139
- # @return [Integer]
140
- #
141
- def count
142
- attributes[:count]
143
- end
102
+ # @!attribute [r] count
103
+ # @return [Integer]
104
+ attribute :count, Types::Int
144
105
 
145
- #
146
- # @return [Array<Datum>]
147
- #
148
- def data
149
- attributes[:data]
150
- end
106
+ # @!attribute [r] data
107
+ # @return [Array<Datnum>]
108
+ attribute :data, Types.Array(Datum)
151
109
 
152
- #
153
- # @return [String]
154
- #
155
- def message
156
- attributes[:message]
157
- end
110
+ # @!attribute [r] message
111
+ # @return [String]
112
+ attribute :message, Types::String
158
113
 
159
- #
160
- # @return [String]
161
- #
162
- def query
163
- attributes[:query]
164
- end
114
+ # @!attribute [r] query
115
+ # @return [String]
116
+ attribute :query, Types::String
165
117
 
166
- #
167
- # @return [String, nil]
168
- #
169
- def scroll
170
- attributes[:scroll]
171
- end
118
+ # @!attribute [r] scroll
119
+ # @return [String, nil]
120
+ attribute :scroll, Types::String.optional
172
121
 
173
122
  #
174
- # @return [Array<Mihari::Artifact>]
123
+ # @return [Array<Mihari::Models::Artifact>]
175
124
  #
176
125
  def artifacts
177
126
  data.map(&:artifact)
@@ -1,23 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mihari
2
4
  module Structs
3
5
  module HunterHow
4
6
  class ListItem < Dry::Struct
7
+ # @!attribute [r] domain
8
+ # @return [String]
5
9
  attribute :domain, Types::String
10
+
11
+ # @!attribute [r] ip
12
+ # @return [String]
6
13
  attribute :ip, Types::String
7
- attribute :port, Types::Integer
8
14
 
9
- #
10
- # @return [String]
11
- #
12
- def ip
13
- attributes[:ip]
14
- end
15
+ # @!attribute [r] port
16
+ # @return [Integer]
17
+ attribute :port, Types::Int
15
18
 
16
19
  #
17
- # @return [Mihari::Artifact]
20
+ # @return [Mihari::Models::Artifact]
18
21
  #
19
22
  def artifact
20
- Artifact.new(data: ip)
23
+ Models::Artifact.new(data: ip)
21
24
  end
22
25
 
23
26
  class << self
@@ -38,18 +41,16 @@ module Mihari
38
41
  end
39
42
 
40
43
  class DataClass < Dry::Struct
44
+ # @!attribute [r] list
45
+ # @return [Array<ListItem>]
41
46
  attribute :list, Types.Array(ListItem)
42
- attribute :total, Types::Integer
43
47
 
44
- #
45
- # @return [Array<ListItem>]
46
- #
47
- def list
48
- attributes[:list]
49
- end
48
+ # @!attribute [r] total
49
+ # @return [Integer]
50
+ attribute :total, Types::Int
50
51
 
51
52
  #
52
- # @return [Array<Mihari::Artifact>]
53
+ # @return [Array<Mihari::Models::Artifact>]
53
54
  #
54
55
  def artifacts
55
56
  list.map(&:artifact)
@@ -72,16 +73,17 @@ module Mihari
72
73
  end
73
74
 
74
75
  class Response < Dry::Struct
75
- attribute :code, Types::Integer
76
+ # @!attribute [r] code
77
+ # @return [Integer]
78
+ attribute :code, Types::Int
79
+
80
+ # @!attribute [r] data
81
+ # @return [DataClass]
76
82
  attribute :data, DataClass
77
- attribute :message, Types::String
78
83
 
79
- #
80
- # @return [DataClass]
81
- #
82
- def data
83
- attributes[:data]
84
- end
84
+ # @!attribute [r] message
85
+ # @return [String]
86
+ attribute :message, Types::String
85
87
 
86
88
  class << self
87
89
  #
@@ -4,46 +4,25 @@ module Mihari
4
4
  module Structs
5
5
  module IPInfo
6
6
  class Response < Dry::Struct
7
+ # @!attribute [r] ip
8
+ # @return [String]
7
9
  attribute :ip, Types::String
8
- attribute :hostname, Types::String.optional
9
- attribute :loc, Types::String.optional
10
- attribute :country_code, Types::String.optional
11
- attribute :asn, Types::Integer.optional
12
10
 
13
- #
14
- # @return [String]
15
- #
16
- def ip
17
- attributes[:ip]
18
- end
19
-
20
- #
21
- # @return [String, nil]
22
- #
23
- def hostname
24
- attributes[:hostname]
25
- end
11
+ # @!attribute [r] hostname
12
+ # @return [String, nil]
13
+ attribute :hostname, Types::String.optional
26
14
 
27
- #
28
- # @return [String, nil]
29
- #
30
- def loc
31
- attributes[:loc]
32
- end
15
+ # @!attribute [r] loc
16
+ # @return [String, nil]
17
+ attribute :loc, Types::String.optional
33
18
 
34
- #
35
- # @return [String, nil]
36
- #
37
- def country_code
38
- attributes[:country_code]
39
- end
19
+ # @!attribute [r] country_code
20
+ # @return [String, nil]
21
+ attribute :country_code, Types::String.optional
40
22
 
41
- #
42
- # @return [Integer, nil]
43
- #
44
- def asn
45
- attributes[:asn]
46
- end
23
+ # @!attribute [r] asn
24
+ # @return [Integer, nil]
25
+ attribute :asn, Types::Int.optional
47
26
 
48
27
  class << self
49
28
  include Mixins::AutonomousSystem