github_api 0.5.4 → 0.6.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.
Files changed (107) hide show
  1. data/README.md +3 -3
  2. data/features/cassettes/events/issue.yml +64 -32
  3. data/features/cassettes/events/network.yml +63 -32
  4. data/features/cassettes/events/org.yml +61 -31
  5. data/features/cassettes/events/performed.yml +63 -32
  6. data/features/cassettes/events/public.yml +61 -31
  7. data/features/cassettes/events/received.yml +63 -32
  8. data/features/cassettes/events/repo.yml +63 -32
  9. data/features/cassettes/gists/comments/all.yml +32 -1
  10. data/features/cassettes/gists/comments/first.yml +32 -1
  11. data/features/cassettes/gists/fork.yml +63 -31
  12. data/features/cassettes/gists/gist.yml +32 -1
  13. data/features/cassettes/gists/gists/public_all.yml +32 -1
  14. data/features/cassettes/gists/gists/starred.yml +60 -29
  15. data/features/cassettes/gists/gists/user_all.yml +87 -1
  16. data/features/cassettes/gists/star.yml +58 -27
  17. data/features/cassettes/gists/starred.yml +32 -1
  18. data/features/cassettes/gists/unstar.yml +54 -25
  19. data/features/cassettes/git_data/references/all.yml +32 -1
  20. data/features/cassettes/git_data/references/all_tags.yml +32 -1
  21. data/features/cassettes/git_data/references/one.yml +32 -1
  22. data/features/cassettes/issues/create.yml +46 -0
  23. data/features/cassettes/issues/edit.yml +44 -0
  24. data/features/cassettes/issues/get.yml +62 -0
  25. data/features/cassettes/issues/list/repo.yml +251 -0
  26. data/features/cassettes/issues/list/user.yml +44 -0
  27. data/features/cassettes/orgs/get.yml +60 -30
  28. data/features/cassettes/orgs/list/oauth_user.yml +60 -29
  29. data/features/cassettes/orgs/list/user.yml +87 -57
  30. data/features/cassettes/pagination/issues/list/first.yml +65 -33
  31. data/features/cassettes/pagination/issues/list/last.yml +66 -33
  32. data/features/cassettes/pagination/repos/commits/list.yml +32 -1
  33. data/features/cassettes/pagination/repos/commits/sha.yml +32 -1
  34. data/features/cassettes/pagination/repos/diff.yml +32 -1
  35. data/features/cassettes/pagination/repos/list.yml +32 -1
  36. data/features/cassettes/pagination/repos/per_page/first.yml +32 -1
  37. data/features/cassettes/pull_requests/get.yml +120 -0
  38. data/features/cassettes/pull_requests/list.yml +254 -0
  39. data/features/cassettes/repos/branches.yml +32 -1
  40. data/features/cassettes/repos/contents/archive.yml +95 -0
  41. data/features/cassettes/repos/contents/get.yml +226 -0
  42. data/features/cassettes/repos/contents/readme.yml +271 -0
  43. data/features/cassettes/repos/get.yml +61 -31
  44. data/features/cassettes/repos/languages.yml +61 -30
  45. data/features/cassettes/repos/list.yml +32 -1
  46. data/features/cassettes/repos/tags.yml +32 -1
  47. data/features/cassettes/search/email.yml +99 -0
  48. data/features/cassettes/search/issues.yml +180 -0
  49. data/features/cassettes/search/repos.yml +396 -0
  50. data/features/cassettes/search/users.yml +54 -0
  51. data/features/cassettes/users/emails/add.yml +61 -30
  52. data/features/cassettes/users/emails/all.yml +61 -30
  53. data/features/cassettes/users/get/oauth.yml +61 -0
  54. data/features/cassettes/users/get/user.yml +62 -0
  55. data/features/issues.feature +64 -0
  56. data/features/pull_requests.feature +27 -0
  57. data/features/repos/contents.feature +35 -0
  58. data/features/search.feature +48 -0
  59. data/features/users.feature +23 -0
  60. data/lib/github_api.rb +1 -0
  61. data/lib/github_api/api.rb +0 -15
  62. data/lib/github_api/client.rb +4 -0
  63. data/lib/github_api/constants.rb +4 -0
  64. data/lib/github_api/error.rb +1 -0
  65. data/lib/github_api/error/unknown_value.rb +18 -0
  66. data/lib/github_api/filter.rb +1 -0
  67. data/lib/github_api/gists.rb +2 -6
  68. data/lib/github_api/gists/comments.rb +2 -2
  69. data/lib/github_api/git_data/blobs.rb +1 -1
  70. data/lib/github_api/git_data/commits.rb +1 -1
  71. data/lib/github_api/git_data/references.rb +2 -2
  72. data/lib/github_api/git_data/tags.rb +1 -1
  73. data/lib/github_api/git_data/trees.rb +2 -3
  74. data/lib/github_api/issues.rb +6 -6
  75. data/lib/github_api/issues/comments.rb +2 -2
  76. data/lib/github_api/issues/labels.rb +2 -2
  77. data/lib/github_api/issues/milestones.rb +3 -3
  78. data/lib/github_api/orgs/teams.rb +4 -4
  79. data/lib/github_api/params_hash.rb +31 -0
  80. data/lib/github_api/pull_requests.rb +2 -2
  81. data/lib/github_api/pull_requests/comments.rb +2 -2
  82. data/lib/github_api/repos.rb +8 -10
  83. data/lib/github_api/repos/commits.rb +2 -2
  84. data/lib/github_api/repos/contents.rb +64 -0
  85. data/lib/github_api/repos/downloads.rb +1 -1
  86. data/lib/github_api/repos/hooks.rb +2 -2
  87. data/lib/github_api/repos/keys.rb +1 -1
  88. data/lib/github_api/result.rb +8 -0
  89. data/lib/github_api/search.rb +98 -0
  90. data/lib/github_api/users.rb +8 -6
  91. data/lib/github_api/users/emails.rb +2 -2
  92. data/lib/github_api/validations/format.rb +4 -3
  93. data/lib/github_api/validations/required.rb +5 -2
  94. data/lib/github_api/version.rb +2 -2
  95. data/spec/fixtures/repos/content.json +14 -0
  96. data/spec/fixtures/repos/readme.json +14 -0
  97. data/spec/fixtures/search/email.json +22 -0
  98. data/spec/fixtures/search/issues.json +23 -0
  99. data/spec/fixtures/search/repositories.json +29 -0
  100. data/spec/fixtures/search/users.json +24 -0
  101. data/spec/github/error/unknown_value_spec.rb +21 -0
  102. data/spec/github/repos/contents_spec.rb +65 -0
  103. data/spec/github/search_spec.rb +87 -0
  104. data/spec/github/users_spec.rb +7 -7
  105. data/spec/github/validations/format_spec.rb +6 -6
  106. data/spec/github/validations/required_spec.rb +3 -3
  107. metadata +69 -35
@@ -50,7 +50,7 @@ module Github
50
50
  _normalize_params_keys(params)
51
51
  _filter_params_keys(VALID_REQUEST_PARAM_NAMES, params)
52
52
  # _merge_mime_type(:pull_request, params)
53
- _validate_params_values(VALID_REQUEST_PARAM_VALUES, params)
53
+ assert_valid_values(VALID_REQUEST_PARAM_VALUES, params)
54
54
 
55
55
  response = get_request("/repos/#{user}/#{repo}/pulls", params)
56
56
  return response unless block_given?
@@ -141,7 +141,7 @@ module Github
141
141
  _normalize_params_keys(params)
142
142
  _filter_params_keys(VALID_REQUEST_PARAM_NAMES, params)
143
143
  # _merge_mime_type(:pull_request, params)
144
- _validate_params_values(VALID_REQUEST_PARAM_VALUES, params)
144
+ assert_valid_values(VALID_REQUEST_PARAM_VALUES, params)
145
145
 
146
146
  patch_request("/repos/#{user}/#{repo}/pulls/#{request_id}", params)
147
147
  end
@@ -134,10 +134,10 @@ module Github
134
134
 
135
135
  # To let user know that the params supplied are wrong before request is made
136
136
  def _validate_reply_to(params)
137
- if params['in_reply_to'] && !_validate_inputs(%w[ body in_reply_to ], params)
137
+ if params['in_reply_to'] && !assert_required_keys(%w[ body in_reply_to ], params)
138
138
  raise ArgumentError, "Required params are: #{%w[ body in_reply_to].join(',')}"
139
139
 
140
- elsif !_validate_inputs(VALID_REQUEST_COM_PARAM_NAMES - %w[ in_reply_to ], params)
140
+ elsif !assert_required_keys(VALID_REQUEST_COM_PARAM_NAMES - %w[ in_reply_to ], params)
141
141
  raise ArgumentError, "Required params are: #{VALID_REQUEST_COM_PARAM_NAMES.join(', ')}"
142
142
  end
143
143
  end
@@ -8,6 +8,7 @@ module Github
8
8
  autoload_all 'github_api/repos',
9
9
  :Collaborators => 'collaborators',
10
10
  :Commits => 'commits',
11
+ :Contents => 'contents',
11
12
  :Downloads => 'downloads',
12
13
  :Forks => 'forks',
13
14
  :Hooks => 'hooks',
@@ -51,6 +52,11 @@ module Github
51
52
  @commits ||= ApiFactory.new 'Repos::Commits'
52
53
  end
53
54
 
55
+ # Access to Repos::Contents API
56
+ def contents
57
+ @commits ||= ApiFactory.new 'Repos::Contents'
58
+ end
59
+
54
60
  # Access to Repos::Downloads API
55
61
  def downloads
56
62
  @downloads ||= ApiFactory.new 'Repos::Downloads'
@@ -136,12 +142,7 @@ module Github
136
142
  params = args.extract_options!
137
143
  _normalize_params_keys(params)
138
144
  _filter_params_keys(VALID_REPO_OPTIONS + %w[ org ], params)
139
-
140
- # if !_validate_inputs(%w[ name ], params)
141
- # raise ArgumentError, "Required params are: :name"
142
- # end
143
-
144
- _validate_inputs(%w[ name ], params)
145
+ assert_required_keys(%w[ name ], params)
145
146
 
146
147
  # Requires authenticated user
147
148
  if (org = params.delete("org"))
@@ -201,10 +202,7 @@ module Github
201
202
 
202
203
  _normalize_params_keys(params)
203
204
  _filter_params_keys(VALID_REPO_OPTIONS, params)
204
-
205
- unless _validate_inputs(%w[ name ], params)
206
- raise ArgumentError, "Required params are: #{%w[ :name ] }"
207
- end
205
+ assert_required_keys(%w[ name ], params)
208
206
 
209
207
  patch_request("/repos/#{user}/#{repo}", DEFAULT_REPO_OPTIONS.merge(params))
210
208
  end
@@ -54,7 +54,7 @@ module Github
54
54
  _normalize_params_keys(params)
55
55
  _filter_params_keys(REQUIRED_COMMENT_PARAMS, params)
56
56
 
57
- _validate_inputs(REQUIRED_COMMENT_PARAMS, params)
57
+ assert_required_keys(REQUIRED_COMMENT_PARAMS, params)
58
58
 
59
59
  post_request("/repos/#{user}/#{repo}/commits/#{sha}/comments", params)
60
60
  end
@@ -182,7 +182,7 @@ module Github
182
182
  _validate_presence_of comment_id
183
183
 
184
184
  _normalize_params_keys(params)
185
- _validate_inputs(%w[ body ], params)
185
+ assert_required_keys(%w[ body ], params)
186
186
 
187
187
  patch_request("/repos/#{user}/#{repo}/comments/#{comment_id}", params)
188
188
  end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ module Github
4
+ class Repos::Contents < API
5
+ # These API methods let you retrieve the contents of files within a repository as Base64 encoded content
6
+
7
+ # Get the README
8
+ #
9
+ # This method returns the preferred README for a repository.
10
+ #
11
+ # = Examples
12
+ # github = Github.new
13
+ # github.repos.contents.readme 'user-name', 'repo-name'
14
+ #
15
+ def readme(user_name, repo_name, params={})
16
+ _normalize_params_keys(params)
17
+
18
+ get_request("/repos/#{user_name}/#{repo_name}/readme", params)
19
+ end
20
+
21
+ # Get contents
22
+ #
23
+ # This method returns the contents of any file or directory in a repository.
24
+ #
25
+ # = Examples
26
+ # github = Github.new
27
+ # github.repos.contents.get 'user-name', 'repo-name', 'path'
28
+ #
29
+ def get(user_name, repo_name, path, params={})
30
+ _normalize_params_keys(params)
31
+
32
+ get_request("/repos/#{user_name}/#{repo_name}/contents/#{path}", params)
33
+ end
34
+ alias :find :get
35
+
36
+ # Get archive link
37
+ #
38
+ # This method will return a 302 to a URL to download a tarball or zipball
39
+ # archive for a repository. Please make sure your HTTP framework is configured
40
+ # to follow redirects or you will need to use the Location header to make
41
+ # a second GET request.
42
+ #
43
+ # Note: For private repositories, these links are temporary and expire quickly.
44
+ #
45
+ # = Parameters
46
+ # * <tt>:archive_format</tt> - Required string - either tarball or zipball
47
+ # * <tt>:ref</tt> - Optional string - valid Git reference, defaults to master
48
+ #
49
+ # = Examples
50
+ # github = Github.new
51
+ # github.repos.contents.archive 'user-name', 'repo-name',
52
+ # "archive_format" => "tarball",
53
+ # "ref" => "master"
54
+ #
55
+ def archive(user_name, repo_name, params={})
56
+ _normalize_params_keys(params)
57
+ archive_format = params.delete('archive_format') || 'zipball'
58
+ ref = params.delete('ref') || 'master'
59
+
60
+ get_request("/repos/#{user_name}/#{repo_name}/#{archive_format}/#{ref}", params)
61
+ end
62
+
63
+ end # Repos::Contents
64
+ end # Github
@@ -87,7 +87,7 @@ module Github
87
87
 
88
88
  _normalize_params_keys(params)
89
89
  _filter_params_keys(VALID_DOWNLOAD_PARAM_NAMES, params)
90
- _validate_inputs(REQUIRED_PARAMS, params)
90
+ assert_required_keys(REQUIRED_PARAMS, params)
91
91
 
92
92
  post_request("/repos/#{user}/#{repo}/downloads", params)
93
93
  end
@@ -92,7 +92,7 @@ module Github
92
92
 
93
93
  _normalize_params_keys(params)
94
94
  _filter_params_keys(VALID_HOOK_PARAM_NAMES, params, :recursive => false)
95
- _validate_inputs(REQUIRED_PARAMS, params)
95
+ assert_required_keys(REQUIRED_PARAMS, params)
96
96
 
97
97
  post_request("/repos/#{user}/#{repo}/hooks", params)
98
98
  end
@@ -125,7 +125,7 @@ module Github
125
125
 
126
126
  _normalize_params_keys(params)
127
127
  _filter_params_keys(VALID_HOOK_PARAM_NAMES, params, :recursive => false)
128
- _validate_inputs(REQUIRED_PARAMS, params)
128
+ assert_required_keys(REQUIRED_PARAMS, params)
129
129
 
130
130
  patch_request("/repos/#{user}/#{repo}/hooks/#{hook_id}", params)
131
131
  end
@@ -56,7 +56,7 @@ module Github
56
56
  _validate_user_repo_params(user, repo) unless user? && repo?
57
57
  _normalize_params_keys(params)
58
58
  _filter_params_keys(VALID_KEY_PARAM_NAMES, params)
59
- _validate_inputs(VALID_KEY_PARAM_NAMES, params)
59
+ assert_required_keys(VALID_KEY_PARAM_NAMES, params)
60
60
 
61
61
  post_request("/repos/#{user}/#{repo}/keys", params)
62
62
  end
@@ -15,6 +15,10 @@ module Github
15
15
  loaded? ? @env[:response_headers][RATELIMIT_REMAINING] : nil
16
16
  end
17
17
 
18
+ def cache_control
19
+ loaded? ? @env[:response_headers][CACHE_CONTROL] : nil
20
+ end
21
+
18
22
  def content_type
19
23
  loaded? ? @env[:response_headers][CONTENT_TYPE] : nil
20
24
  end
@@ -31,6 +35,10 @@ module Github
31
35
  loaded? ? @env[:response_headers][DATE] : nil
32
36
  end
33
37
 
38
+ def location
39
+ loaded? ? @env[:response_headers][LOCATION] : nil
40
+ end
41
+
34
42
  def server
35
43
  loaded? ? @env[:response_headers][SERVER] : nil
36
44
  end
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ module Github
4
+ class Search < API
5
+
6
+ # Creates new Search API
7
+ def initialize(options = {})
8
+ super(options)
9
+ end
10
+
11
+ # Search issues
12
+ #
13
+ # Find issues by state and keyword.
14
+ #
15
+ # = Parameters
16
+ # <tt>:state</tt> - open or closed.
17
+ # <tt>:keyword</tt> - search term
18
+ #
19
+ # = Examples
20
+ # github = Github.new
21
+ # github.search.issues owner: 'owner', repo: 'repo-name', state: 'open', keyword: 'api'
22
+ #
23
+ def issues(*args)
24
+ params = args.extract_options!
25
+ normalize params
26
+
27
+ required = ['owner', 'repo', 'state', 'keyword']
28
+ assert_required_keys required, params
29
+
30
+ options = required.inject({}) do |hash, key|
31
+ hash[key] = params.delete(key)
32
+ hash
33
+ end
34
+
35
+ get_request("/legacy/issues/search/#{options['owner']}/#{options['repo']}/#{options['state']}/#{options['keyword']}", params)
36
+ end
37
+
38
+ # Search repositories
39
+ #
40
+ # Find repositories by keyword.
41
+ #
42
+ # = Parameters
43
+ # <tt>:keyword</tt> - search term
44
+ #
45
+ # = Examples
46
+ # github = Github.new
47
+ # github.search.repos keyword: 'api'
48
+ #
49
+ def repos(*args)
50
+ params = args.extract_options!
51
+ normalize params
52
+ assert_required_keys %w[ keyword ], params
53
+
54
+ get_request("/legacy/repos/search/#{params.delete('keyword')}", params)
55
+ end
56
+ alias :repositories :repos
57
+
58
+ # Search users
59
+ #
60
+ # Find users by keyword.
61
+ #
62
+ # = Parameters
63
+ # <tt>:keyword</tt> - search term
64
+ #
65
+ # = Examples
66
+ # github = Github.new
67
+ # github.search.users keyword: 'wycats'
68
+ #
69
+ def users(*args)
70
+ params = args.extract_options!
71
+ normalize params
72
+ assert_required_keys %w[ keyword ], params
73
+
74
+ get_request("/legacy/user/search/#{params.delete('keyword')}", params)
75
+ end
76
+
77
+ # Search email
78
+ #
79
+ # This API call is added for compatibility reasons only. There’s no
80
+ # guarantee that full email searches will always be available.
81
+ #
82
+ # = Parameters
83
+ # <tt>:keyword</tt> - search term
84
+ #
85
+ # = Examples
86
+ # github = Github.new
87
+ # github.search.email email: 'wycats'
88
+ #
89
+ def email(*args)
90
+ params = args.extract_options!
91
+ normalize params
92
+ assert_required_keys %w[ email ], params
93
+
94
+ get_request("/legacy/user/email/#{params.delete('email')}", params)
95
+ end
96
+
97
+ end # Search
98
+ end # Github
@@ -44,17 +44,18 @@ module Github
44
44
  #
45
45
  # = Examples
46
46
  # github = Github.new
47
- # github.users.get 'user-name'
47
+ # github.users.get user: 'user-name'
48
48
  #
49
49
  # Get the authenticated user
50
50
  #
51
51
  # = Examples
52
- # @github = Github.new :oauth_token => '...'
53
- # @github.users.get
52
+ # github = Github.new oauth_token: '...'
53
+ # github.users.get
54
54
  #
55
- def get(user_name=nil, params={})
55
+ def get(*args)
56
+ params = args.extract_options!
56
57
  _normalize_params_keys(params)
57
- if user_name
58
+ if user_name = params.delete('user')
58
59
  get_request("/users/#{user_name}", params)
59
60
  else
60
61
  get_request("/user", params)
@@ -84,7 +85,8 @@ module Github
84
85
  # "hireable" => true,
85
86
  # "bio" => "There once..."
86
87
  #
87
- def update(params={})
88
+ def update(*args)
89
+ params = args.extract_options!
88
90
  _normalize_params_keys(params)
89
91
  _filter_params_keys(VALID_USER_PARAMS_NAMES, params)
90
92
  patch_request("/user", params)
@@ -29,7 +29,7 @@ module Github
29
29
  # github.users.emails.add "octocat@github.com", "support@github.com"
30
30
  #
31
31
  def add(*args)
32
- params = _extract_parameters(args)
32
+ params = args.extract_options!
33
33
  _normalize_params_keys(params)
34
34
  params['data'] = args if args
35
35
  post_request("/user/emails", params)
@@ -46,7 +46,7 @@ module Github
46
46
  # github.users.emails.delete "octocat@github.com", "support@github.com"
47
47
  #
48
48
  def delete(*args)
49
- params = _extract_parameters(args)
49
+ params = args.extract_options!
50
50
  _normalize_params_keys(params)
51
51
  params['data'] = args if args
52
52
  delete_request("/user/emails", params)
@@ -7,13 +7,14 @@ module Github
7
7
  # Ensures that value for a given key is of the correct form whether
8
8
  # matching regular expression or set of predefined values.
9
9
  #
10
- def _validate_params_values(permitted, params)
10
+ def assert_valid_values(permitted, params)
11
11
  params.each do |k, v|
12
12
  next unless permitted.keys.include?(k)
13
13
  if permitted[k].is_a?(Array) && !permitted[k].include?(params[k])
14
- raise ArgumentError, "Wrong value for #{k}, allowed: #{permitted[k].join(', ')}"
14
+ raise Github::Error::UnknownValue.new(k,v, permitted[k].join(', '))
15
+
15
16
  elsif permitted[k].is_a?(Regexp) && !(permitted[k] =~ params[k])
16
- raise ArgumentError, "String does not match the parameter value."
17
+ raise Github::Error::UnknownValue.new(k,v, permitted[k])
17
18
  end
18
19
  end
19
20
  end
@@ -4,9 +4,12 @@ module Github
4
4
  module Validations
5
5
  module Required
6
6
 
7
- # Ensures that esential input parameters are present before request is made.
7
+ # Validate all keys present in a provided hash against required set,
8
+ # on mismatch raise Github::Error::RequiredParams
9
+ # Note that keys need to be in the same format i.e. symbols or strings,
10
+ # otherwise the comparison will fail.
8
11
  #
9
- def _validate_inputs(required, provided)
12
+ def assert_required_keys(required, provided)
10
13
  result = required.all? do |key|
11
14
  provided.has_deep_key? key
12
15
  end
@@ -3,8 +3,8 @@
3
3
  module Github
4
4
  module VERSION
5
5
  MAJOR = 0
6
- MINOR = 5
7
- PATCH = 4
6
+ MINOR = 6
7
+ PATCH = 0
8
8
  BUILD = nil
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.');
@@ -0,0 +1,14 @@
1
+ {
2
+ "type": "file",
3
+ "encoding": "base64",
4
+ "_links": {
5
+ "git": "https://api.github.com/repos/pengwynn/octokit/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
6
+ "self": "https://api.github.com/repos/pengwynn/octokit/contents/README.md",
7
+ "html": "https://github.com/pengwynn/octokit/blob/master/README.md"
8
+ },
9
+ "size": 5362,
10
+ "name": "README.md",
11
+ "path": "README.md",
12
+ "content": "encoded content ...",
13
+ "sha": "3d21ec53a331a6f037a91c368710b99387d012c1"
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "type": "file",
3
+ "encoding": "base64",
4
+ "_links": {
5
+ "git": "https://api.github.com/repos/pengwynn/octokit/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1",
6
+ "self": "https://api.github.com/repos/pengwynn/octokit/contents/README.md",
7
+ "html": "https://github.com/pengwynn/octokit/blob/master/README.md"
8
+ },
9
+ "size": 5362,
10
+ "name": "README.md",
11
+ "path": "README.md",
12
+ "content": "encoded content ...",
13
+ "sha": "3d21ec53a331a6f037a91c368710b99387d012c1"
14
+ }