nexus_mods 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/nexus_mods/api/api_limits.rb +6 -1
- data/lib/nexus_mods/api/category.rb +6 -1
- data/lib/nexus_mods/api/game.rb +6 -1
- data/lib/nexus_mods/api/mod.rb +14 -1
- data/lib/nexus_mods/api/mod_file.rb +24 -1
- data/lib/nexus_mods/api/mod_updates.rb +27 -1
- data/lib/nexus_mods/api/resource.rb +20 -0
- data/lib/nexus_mods/api/user.rb +6 -1
- data/lib/nexus_mods/version.rb +1 -1
- data/lib/nexus_mods.rb +94 -2
- data/spec/nexus_mods_test/scenarios/nexus_mods/api/mod_file_spec.rb +232 -45
- data/spec/nexus_mods_test/scenarios/nexus_mods/api/mod_spec.rb +245 -57
- data/spec/nexus_mods_test/scenarios/nexus_mods/api/mod_updates_spec.rb +28 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f6c2d6e72c966955e6153a3381458fba4f56c36deac811d125edc962046b5a0
|
4
|
+
data.tar.gz: d0a2ec92da860dbb53b608e1de22762b3562bac1d4fe1333066f868612983747
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d159a8824c0c6b723ec7f3361f1df52162cebf3d4f91833e072ceeb94089fb84d102d46d597d0ee24e92c6983e56ddcd87a95a6a4ffbb282331a7f3aae94cc84
|
7
|
+
data.tar.gz: 9dda81c7f0f593190547ed55aeff36a3040610d13ee59f7c5ff6ffed7df1d95d806685d9cf77e090e3a2410a24a516a32617b9fc047d59cb30f149607022aaba
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# [v2.5.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.4.0...v2.5.0) (2023-04-12 19:15:44)
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
* [[Feature] Add links between resources](https://github.com/Muriel-Salvan/nexus_mods/commit/84c474b75f3ee1e4ac0c8bbda0d2ad25022f1f07)
|
6
|
+
|
7
|
+
# [v2.4.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.3.0...v2.4.0) (2023-04-12 17:23:29)
|
8
|
+
|
9
|
+
### Features
|
10
|
+
|
11
|
+
* [[Feature] Add options and methods for mod and mod_files to query for updates to check data freshness](https://github.com/Muriel-Salvan/nexus_mods/commit/72a933a6ac22faae601fbdc547cc9e0ffa8908fc)
|
12
|
+
|
1
13
|
# [v2.3.0](https://github.com/Muriel-Salvan/nexus_mods/compare/v2.2.0...v2.3.0) (2023-04-12 15:08:22)
|
2
14
|
|
3
15
|
### Features
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
4
6
|
|
5
7
|
# Object giving the NexusMods API limits
|
6
|
-
class ApiLimits
|
8
|
+
class ApiLimits < Resource
|
7
9
|
|
8
10
|
attr_reader(
|
9
11
|
*%i[
|
@@ -19,6 +21,7 @@ class NexusMods
|
|
19
21
|
# Constructor
|
20
22
|
#
|
21
23
|
# Parameters::
|
24
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
22
25
|
# * *daily_limit* (Integer): The daily limit
|
23
26
|
# * *daily_remaining* (Integer): The daily remaining
|
24
27
|
# * *daily_reset* (Integer): The daily reset time
|
@@ -26,6 +29,7 @@ class NexusMods
|
|
26
29
|
# * *hourly_remaining* (Integer): The hourly remaining
|
27
30
|
# * *hourly_reset* (Integer): The hourly reset time
|
28
31
|
def initialize(
|
32
|
+
nexus_mods:,
|
29
33
|
daily_limit:,
|
30
34
|
daily_remaining:,
|
31
35
|
daily_reset:,
|
@@ -33,6 +37,7 @@ class NexusMods
|
|
33
37
|
hourly_remaining:,
|
34
38
|
hourly_reset:
|
35
39
|
)
|
40
|
+
super(nexus_mods:)
|
36
41
|
@daily_limit = daily_limit
|
37
42
|
@daily_remaining = daily_remaining
|
38
43
|
@daily_reset = daily_reset
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
4
6
|
|
5
7
|
# Categories defined for a game in NexusMods
|
6
|
-
class Category
|
8
|
+
class Category < Resource
|
7
9
|
|
8
10
|
attr_reader(
|
9
11
|
*%i[
|
@@ -21,14 +23,17 @@ class NexusMods
|
|
21
23
|
# Constructor
|
22
24
|
#
|
23
25
|
# Parameters::
|
26
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
24
27
|
# *id* (Integer): The category id
|
25
28
|
# *name* (String): The category id
|
26
29
|
# *parent_category* (Category or nil): The parent category, or nil if none [default: nil]
|
27
30
|
def initialize(
|
31
|
+
nexus_mods:,
|
28
32
|
id:,
|
29
33
|
name:,
|
30
34
|
parent_category: nil
|
31
35
|
)
|
36
|
+
super(nexus_mods:)
|
32
37
|
@id = id
|
33
38
|
@name = name
|
34
39
|
@parent_category = parent_category
|
data/lib/nexus_mods/api/game.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
@@ -5,7 +7,7 @@ class NexusMods
|
|
5
7
|
# A NexusMods game.
|
6
8
|
# Attributes info can be taken from there:
|
7
9
|
# * https://github.com/Nexus-Mods/node-nexus-api/blob/master/docs/interfaces/_types_.igameinfo.md
|
8
|
-
class Game
|
10
|
+
class Game < Resource
|
9
11
|
|
10
12
|
attr_reader(
|
11
13
|
*%i[
|
@@ -29,6 +31,7 @@ class NexusMods
|
|
29
31
|
# Constructor
|
30
32
|
#
|
31
33
|
# Parameters::
|
34
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
32
35
|
# * *id* (Integer): The game's id
|
33
36
|
# * *name* (String): The game's name
|
34
37
|
# * *forum_url* (String): The game's forum's URL
|
@@ -44,6 +47,7 @@ class NexusMods
|
|
44
47
|
# * *mods_count* (Integer): The game's mods' count [default: 0]
|
45
48
|
# * *categories* (Array<Category>): The list of game's categories [default: []]
|
46
49
|
def initialize(
|
50
|
+
nexus_mods:,
|
47
51
|
id:,
|
48
52
|
name:,
|
49
53
|
forum_url:,
|
@@ -59,6 +63,7 @@ class NexusMods
|
|
59
63
|
mods_count: 0,
|
60
64
|
categories: []
|
61
65
|
)
|
66
|
+
super(nexus_mods:)
|
62
67
|
@id = id
|
63
68
|
@name = name
|
64
69
|
@forum_url = forum_url
|
data/lib/nexus_mods/api/mod.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
@@ -5,7 +7,7 @@ class NexusMods
|
|
5
7
|
# A NexusMods mod.
|
6
8
|
# Attributes info can be taken from there:
|
7
9
|
# * https://github.com/Nexus-Mods/node-nexus-api/blob/master/docs/interfaces/_types_.imodinfo.md
|
8
|
-
class Mod
|
10
|
+
class Mod < Resource
|
9
11
|
|
10
12
|
attr_reader(
|
11
13
|
*%i[
|
@@ -36,6 +38,7 @@ class NexusMods
|
|
36
38
|
# Constructor
|
37
39
|
#
|
38
40
|
# Parameters::
|
41
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
39
42
|
# * *uid* (Integer): The mod's uid
|
40
43
|
# * *mod_id* (Integer): The mod's id
|
41
44
|
# * *game_id* (Integer): The mod's game id
|
@@ -58,6 +61,7 @@ class NexusMods
|
|
58
61
|
# * *unique_downloads_count* (Integer): The mod's unique downloads' count [default: 0]
|
59
62
|
# * *endorsements_count* (Integer): The mod's endorsements' count [default: 0]
|
60
63
|
def initialize(
|
64
|
+
nexus_mods:,
|
61
65
|
uid:,
|
62
66
|
mod_id:,
|
63
67
|
game_id:,
|
@@ -80,6 +84,7 @@ class NexusMods
|
|
80
84
|
unique_downloads_count: 0,
|
81
85
|
endorsements_count: 0
|
82
86
|
)
|
87
|
+
super(nexus_mods:)
|
83
88
|
@uid = uid
|
84
89
|
@mod_id = mod_id
|
85
90
|
@game_id = game_id
|
@@ -134,6 +139,14 @@ class NexusMods
|
|
134
139
|
@endorsements_count == other.endorsements_count
|
135
140
|
end
|
136
141
|
|
142
|
+
# Get associated files information
|
143
|
+
#
|
144
|
+
# Result::
|
145
|
+
# * Array<ModFile>: The list of mod files information
|
146
|
+
def files
|
147
|
+
@nexus_mods.mod_files(game_domain_name: domain_name, mod_id:)
|
148
|
+
end
|
149
|
+
|
137
150
|
end
|
138
151
|
|
139
152
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
@@ -5,10 +7,12 @@ class NexusMods
|
|
5
7
|
# A NexusMods file.
|
6
8
|
# Attributes info can be taken from there:
|
7
9
|
# * https://github.com/Nexus-Mods/node-nexus-api/blob/master/docs/interfaces/_types_.ifileinfo.md
|
8
|
-
class ModFile
|
10
|
+
class ModFile < Resource
|
9
11
|
|
10
12
|
attr_reader(
|
11
13
|
*%i[
|
14
|
+
game_domain_name
|
15
|
+
mod_id
|
12
16
|
ids
|
13
17
|
uid
|
14
18
|
id
|
@@ -43,6 +47,9 @@ class NexusMods
|
|
43
47
|
# Constructor
|
44
48
|
#
|
45
49
|
# Parameters::
|
50
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
51
|
+
# * *game_domain_name* (String): The game this file belongs to
|
52
|
+
# * *mod_id* (Integer): The mod id this file belongs to
|
46
53
|
# * *ids* (Array<Integer>): The file's list of IDs
|
47
54
|
# * *uid* (Integer): The file's UID
|
48
55
|
# * *id* (Integer): The file's main ID
|
@@ -60,6 +67,9 @@ class NexusMods
|
|
60
67
|
# * *changelog_html* (String): The file's change log in HTML
|
61
68
|
# * *content_preview_url* (String): URL to a JSON that gives info on the file's content
|
62
69
|
def initialize(
|
70
|
+
nexus_mods:,
|
71
|
+
game_domain_name:,
|
72
|
+
mod_id:,
|
63
73
|
ids:,
|
64
74
|
uid:,
|
65
75
|
id:,
|
@@ -77,6 +87,9 @@ class NexusMods
|
|
77
87
|
changelog_html:,
|
78
88
|
content_preview_url:
|
79
89
|
)
|
90
|
+
super(nexus_mods:)
|
91
|
+
@game_domain_name = game_domain_name
|
92
|
+
@mod_id = mod_id
|
80
93
|
@ids = ids
|
81
94
|
@uid = uid
|
82
95
|
@id = id
|
@@ -105,6 +118,8 @@ class NexusMods
|
|
105
118
|
# * Boolean: Are objects equal?
|
106
119
|
def ==(other)
|
107
120
|
other.is_a?(ModFile) &&
|
121
|
+
@game_domain_name == other.game_domain_name &&
|
122
|
+
@mod_id == other.mod_id &&
|
108
123
|
@ids == other.ids &&
|
109
124
|
@uid == other.uid &&
|
110
125
|
@id == other.id &&
|
@@ -123,6 +138,14 @@ class NexusMods
|
|
123
138
|
@content_preview_url == other.content_preview_url
|
124
139
|
end
|
125
140
|
|
141
|
+
# Get associated mod information
|
142
|
+
#
|
143
|
+
# Result::
|
144
|
+
# * Mod: The corresponding mod
|
145
|
+
def mod
|
146
|
+
@nexus_mods.mod(game_domain_name:, mod_id:)
|
147
|
+
end
|
148
|
+
|
126
149
|
end
|
127
150
|
|
128
151
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
4
6
|
|
5
7
|
# A NexusMods mod updates.
|
6
|
-
class ModUpdates
|
8
|
+
class ModUpdates < Resource
|
7
9
|
|
8
10
|
attr_reader(
|
9
11
|
*%i[
|
12
|
+
game_domain_name
|
10
13
|
mod_id
|
11
14
|
latest_file_update
|
12
15
|
latest_mod_activity
|
@@ -16,14 +19,20 @@ class NexusMods
|
|
16
19
|
# Constructor
|
17
20
|
#
|
18
21
|
# Parameters::
|
22
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
23
|
+
# * *game_domain_name* (String): The game this file belongs to
|
19
24
|
# * *mod_id* (Integer): The mod's id
|
20
25
|
# * *latest_file_update* (Time): The mod's latest file update
|
21
26
|
# * *latest_mod_activity* (Time): The mod's latest activity
|
22
27
|
def initialize(
|
28
|
+
nexus_mods:,
|
29
|
+
game_domain_name:,
|
23
30
|
mod_id:,
|
24
31
|
latest_file_update:,
|
25
32
|
latest_mod_activity:
|
26
33
|
)
|
34
|
+
super(nexus_mods:)
|
35
|
+
@game_domain_name = game_domain_name
|
27
36
|
@mod_id = mod_id
|
28
37
|
@latest_file_update = latest_file_update
|
29
38
|
@latest_mod_activity = latest_mod_activity
|
@@ -37,11 +46,28 @@ class NexusMods
|
|
37
46
|
# * Boolean: Are objects equal?
|
38
47
|
def ==(other)
|
39
48
|
other.is_a?(ModUpdates) &&
|
49
|
+
@game_domain_name == game_domain_name &&
|
40
50
|
@mod_id == other.mod_id &&
|
41
51
|
@latest_file_update == other.latest_file_update &&
|
42
52
|
@latest_mod_activity == other.latest_mod_activity
|
43
53
|
end
|
44
54
|
|
55
|
+
# Get associated mod information
|
56
|
+
#
|
57
|
+
# Result::
|
58
|
+
# * Mod: The corresponding mod
|
59
|
+
def mod
|
60
|
+
@nexus_mods.mod(game_domain_name:, mod_id:)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get associated mod files information
|
64
|
+
#
|
65
|
+
# Result::
|
66
|
+
# * Array<ModFile>: The corresponding mod files
|
67
|
+
def mod_files
|
68
|
+
@nexus_mods.mod_files(game_domain_name:, mod_id:)
|
69
|
+
end
|
70
|
+
|
45
71
|
end
|
46
72
|
|
47
73
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class NexusMods
|
2
|
+
|
3
|
+
module Api
|
4
|
+
|
5
|
+
# Base class for any API resource
|
6
|
+
class Resource
|
7
|
+
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# Parameters::
|
11
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
12
|
+
def initialize(nexus_mods:)
|
13
|
+
@nexus_mods = nexus_mods
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/nexus_mods/api/user.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'nexus_mods/api/resource'
|
2
|
+
|
1
3
|
class NexusMods
|
2
4
|
|
3
5
|
module Api
|
4
6
|
|
5
7
|
# A user on NExusMods.
|
6
8
|
# Mainly used for uploaders information.
|
7
|
-
class User
|
9
|
+
class User < Resource
|
8
10
|
|
9
11
|
attr_reader(
|
10
12
|
*%i[
|
@@ -18,16 +20,19 @@ class NexusMods
|
|
18
20
|
# Constructor
|
19
21
|
#
|
20
22
|
# Parameters::
|
23
|
+
# * *nexus_mods* (NexusMods): The NexusMods API instance that the resource can use to query for other resources
|
21
24
|
# * *member_id* (Integer): The user's member id
|
22
25
|
# * *member_group_id* (Integer): The user's member group id
|
23
26
|
# * *name* (String): The user's name
|
24
27
|
# * *profile_url* (String): The user's profile URL
|
25
28
|
def initialize(
|
29
|
+
nexus_mods:,
|
26
30
|
member_id:,
|
27
31
|
member_group_id:,
|
28
32
|
name:,
|
29
33
|
profile_url:
|
30
34
|
)
|
35
|
+
super(nexus_mods:)
|
31
36
|
@member_id = member_id
|
32
37
|
@member_group_id = member_group_id
|
33
38
|
@name = name
|
data/lib/nexus_mods/version.rb
CHANGED
data/lib/nexus_mods.rb
CHANGED
@@ -88,6 +88,7 @@ class NexusMods
|
|
88
88
|
def api_limits
|
89
89
|
api_limits_headers = @api_client.http('users/validate').headers
|
90
90
|
Api::ApiLimits.new(
|
91
|
+
nexus_mods: self,
|
91
92
|
daily_limit: Integer(api_limits_headers['x-rl-daily-limit']),
|
92
93
|
daily_remaining: Integer(api_limits_headers['x-rl-daily-remaining']),
|
93
94
|
daily_reset: Time.parse(api_limits_headers['x-rl-daily-reset']).utc,
|
@@ -113,6 +114,7 @@ class NexusMods
|
|
113
114
|
category_id,
|
114
115
|
[
|
115
116
|
Api::Category.new(
|
117
|
+
nexus_mods: self,
|
116
118
|
id: category_id,
|
117
119
|
name: category_json['name']
|
118
120
|
),
|
@@ -125,6 +127,7 @@ class NexusMods
|
|
125
127
|
category.parent_category = categories[parent_category_id]&.first if parent_category_id
|
126
128
|
end
|
127
129
|
Api::Game.new(
|
130
|
+
nexus_mods: self,
|
128
131
|
id: game_json['id'],
|
129
132
|
name: game_json['name'],
|
130
133
|
forum_url: game_json['forum_url'],
|
@@ -166,11 +169,16 @@ class NexusMods
|
|
166
169
|
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
167
170
|
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
168
171
|
# * *clear_cache* (Boolean): Should we clear the API cache for this resource? [default: false]
|
172
|
+
# * *check_updates* (Boolean): Should we check updates?
|
173
|
+
# If yes then an extra call to updated_mods may be done to check for updates before retrieving the mod information.
|
174
|
+
# In case the mod was previously retrieved and may be in an old cache, then using this will optimize the calls to NexusMods API to the minimum.
|
169
175
|
# Result::
|
170
176
|
# * Mod: Mod information
|
171
|
-
def mod(game_domain_name: @game_domain_name, mod_id: @mod_id, clear_cache: false)
|
177
|
+
def mod(game_domain_name: @game_domain_name, mod_id: @mod_id, clear_cache: false, check_updates: false)
|
178
|
+
mod_cache_up_to_date?(game_domain_name:, mod_id:) if check_updates
|
172
179
|
mod_json = @api_client.api("games/#{game_domain_name}/mods/#{mod_id}", clear_cache:)
|
173
180
|
Api::Mod.new(
|
181
|
+
nexus_mods: self,
|
174
182
|
uid: mod_json['uid'],
|
175
183
|
mod_id: mod_json['mod_id'],
|
176
184
|
game_id: mod_json['game_id'],
|
@@ -185,6 +193,7 @@ class NexusMods
|
|
185
193
|
status: mod_json['status'],
|
186
194
|
available: mod_json['available'],
|
187
195
|
uploader: Api::User.new(
|
196
|
+
nexus_mods: self,
|
188
197
|
member_id: mod_json['user']['member_id'],
|
189
198
|
member_group_id: mod_json['user']['member_group_id'],
|
190
199
|
name: mod_json['user']['name'],
|
@@ -228,11 +237,18 @@ class NexusMods
|
|
228
237
|
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
229
238
|
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
230
239
|
# * *clear_cache* (Boolean): Should we clear the API cache for this resource? [default: false]
|
240
|
+
# * *check_updates* (Boolean): Should we check updates?
|
241
|
+
# If yes then an extra call to updated_mods may be done to check for updates before retrieving the mod information.
|
242
|
+
# In case the mod files were previously retrieved and may be in an old cache, then using this will optimize the calls to NexusMods API to the minimum.
|
231
243
|
# Result::
|
232
244
|
# * Array<ModFile>: List of mod's files
|
233
|
-
def mod_files(game_domain_name: @game_domain_name, mod_id: @mod_id, clear_cache: false)
|
245
|
+
def mod_files(game_domain_name: @game_domain_name, mod_id: @mod_id, clear_cache: false, check_updates: false)
|
246
|
+
mod_files_cache_up_to_date?(game_domain_name:, mod_id:) if check_updates
|
234
247
|
@api_client.api("games/#{game_domain_name}/mods/#{mod_id}/files", clear_cache:)['files'].map do |file_json|
|
235
248
|
Api::ModFile.new(
|
249
|
+
nexus_mods: self,
|
250
|
+
game_domain_name:,
|
251
|
+
mod_id:,
|
236
252
|
ids: file_json['id'],
|
237
253
|
uid: file_json['uid'],
|
238
254
|
id: file_json['file_id'],
|
@@ -290,6 +306,8 @@ class NexusMods
|
|
290
306
|
def updated_mods(game_domain_name: @game_domain_name, since: :one_day, clear_cache: false)
|
291
307
|
@api_client.api("games/#{game_domain_name}/mods/updated", parameters: period_to_url_params(since), clear_cache:).map do |updated_mod_json|
|
292
308
|
Api::ModUpdates.new(
|
309
|
+
nexus_mods: self,
|
310
|
+
game_domain_name:,
|
293
311
|
mod_id: updated_mod_json['mod_id'],
|
294
312
|
latest_file_update: Time.at(updated_mod_json['latest_file_update']).utc,
|
295
313
|
latest_mod_activity: Time.at(updated_mod_json['latest_mod_activity']).utc
|
@@ -327,6 +345,80 @@ class NexusMods
|
|
327
345
|
@api_client.set_api_cache_timestamp("games/#{game_domain_name}/mods/updated", parameters: period_to_url_params(since), cache_timestamp:)
|
328
346
|
end
|
329
347
|
|
348
|
+
# Does a given mod id have fresh information in our cache?
|
349
|
+
# This may fire queries to the updated mods API to get info from NexusMods about the latest updated mods.
|
350
|
+
# If we know the mod is up-to-date, then its mod information cache timestamp will be set to the time when we checked for updates if it was greater than the cache date.
|
351
|
+
#
|
352
|
+
# Here is the algorithm:
|
353
|
+
# If it is not in the cache, then it is not up-to-date.
|
354
|
+
# Otherwise, the API allows us to know if it has been updated up to 1 month in the past.
|
355
|
+
# Therefore if the current cache timestamp is older than 1 month, assume that it has to be updated.
|
356
|
+
# Otherwise query the API to know the latest updated mods since 1 month:
|
357
|
+
# * If the mod ID is not there, then it is up-to-date.
|
358
|
+
# * If the mod ID is there, then check if our cache timestamp is older than the last update timestamp from NexusMods.
|
359
|
+
#
|
360
|
+
# Parameters::
|
361
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
362
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
363
|
+
# Result::
|
364
|
+
# * Boolean: Is the mod cache up-to-date?
|
365
|
+
def mod_cache_up_to_date?(game_domain_name: @game_domain_name, mod_id: @mod_id)
|
366
|
+
existing_cache_timestamp = mod_cache_timestamp(game_domain_name:, mod_id:)
|
367
|
+
mod_up_to_date =
|
368
|
+
if existing_cache_timestamp.nil? || existing_cache_timestamp < Time.now - (30 * 24 * 60 * 60)
|
369
|
+
# It's not in the cache
|
370
|
+
# or it's older than 1 month
|
371
|
+
false
|
372
|
+
else
|
373
|
+
found_mod_updates = updated_mods(game_domain_name:, since: :one_month).find { |mod_updates| mod_updates.mod_id == mod_id }
|
374
|
+
# true if it has not been updated on NexusMods since 1 month
|
375
|
+
# or our cache timestamp is more recent
|
376
|
+
found_mod_updates.nil? || found_mod_updates.latest_mod_activity < existing_cache_timestamp
|
377
|
+
end
|
378
|
+
if mod_up_to_date
|
379
|
+
update_time = updated_mods_cache_timestamp(game_domain_name:, since: :one_month)
|
380
|
+
set_mod_cache_timestamp(cache_timestamp: update_time, game_domain_name:, mod_id:) if update_time > existing_cache_timestamp
|
381
|
+
end
|
382
|
+
mod_up_to_date
|
383
|
+
end
|
384
|
+
|
385
|
+
# Does a given mod id have fresh files information in our cache?
|
386
|
+
# This may fire queries to the updated mods API to get info from NexusMods about the latest updated mods.
|
387
|
+
# If we know the mod is up-to-date, then its mod information cache timestamp will be set to the time when we checked for updates if it was greater than the cache date.
|
388
|
+
#
|
389
|
+
# Here is the algorithm:
|
390
|
+
# If it is not in the cache, then it is not up-to-date.
|
391
|
+
# Otherwise, the API allows us to know if it has been updated up to 1 month in the past.
|
392
|
+
# Therefore if the current cache timestamp is older than 1 month, assume that it has to be updated.
|
393
|
+
# Otherwise query the API to know the latest updated mods since 1 month:
|
394
|
+
# * If the mod ID is not there, then it is up-to-date.
|
395
|
+
# * If the mod ID is there, then check if our cache timestamp is older than the last update timestamp from NexusMods.
|
396
|
+
#
|
397
|
+
# Parameters::
|
398
|
+
# * *game_domain_name* (String): Game domain name to query by default [default: @game_domain_name]
|
399
|
+
# * *mod_id* (Integer): The mod ID [default: @mod_id]
|
400
|
+
# Result::
|
401
|
+
# * Boolean: Is the mod cache up-to-date?
|
402
|
+
def mod_files_cache_up_to_date?(game_domain_name: @game_domain_name, mod_id: @mod_id)
|
403
|
+
existing_cache_timestamp = mod_files_cache_timestamp(game_domain_name:, mod_id:)
|
404
|
+
mod_up_to_date =
|
405
|
+
if existing_cache_timestamp.nil? || existing_cache_timestamp < Time.now - (30 * 24 * 60 * 60)
|
406
|
+
# It's not in the cache
|
407
|
+
# or it's older than 1 month
|
408
|
+
false
|
409
|
+
else
|
410
|
+
found_mod_updates = updated_mods(game_domain_name:, since: :one_month).find { |mod_updates| mod_updates.mod_id == mod_id }
|
411
|
+
# true if it has not been updated on NexusMods since 1 month
|
412
|
+
# or our cache timestamp is more recent
|
413
|
+
found_mod_updates.nil? || found_mod_updates.latest_file_update < existing_cache_timestamp
|
414
|
+
end
|
415
|
+
if mod_up_to_date
|
416
|
+
update_time = updated_mods_cache_timestamp(game_domain_name:, since: :one_month)
|
417
|
+
set_mod_files_cache_timestamp(cache_timestamp: update_time, game_domain_name:, mod_id:) if update_time > existing_cache_timestamp
|
418
|
+
end
|
419
|
+
mod_up_to_date
|
420
|
+
end
|
421
|
+
|
330
422
|
private
|
331
423
|
|
332
424
|
# Get the URL parameters from the required period
|
@@ -25,60 +25,55 @@ describe NexusMods::Api::ModFile do
|
|
25
25
|
expect_mod_file_to_be2487(sorted_mod_files[1])
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
expect_http_call_to(
|
30
|
-
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
31
|
-
json: { files: json_example_mod_files }
|
32
|
-
)
|
33
|
-
expect_mod_files_to_be_example(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014))
|
34
|
-
end
|
28
|
+
context 'when testing a mod with 2 files' do
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
30
|
+
before do
|
31
|
+
expect_http_call_to(
|
32
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
33
|
+
json: { 'files' => json_example_mod_files }
|
34
|
+
)
|
35
|
+
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
json: { files: json_example_mod_files }
|
48
|
-
)
|
49
|
-
expect_mod_files_to_be_example(nexus_mods(game_domain_name: 'skyrimspecialedition').mod_files(mod_id: 2014))
|
50
|
-
end
|
37
|
+
it 'returns a mod files list' do
|
38
|
+
expect_mod_files_to_be_example(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014))
|
39
|
+
end
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
json: { files: json_example_mod_files }
|
56
|
-
)
|
57
|
-
nexus_mods.game_domain_name = 'skyrimspecialedition'
|
58
|
-
expect_mod_files_to_be_example(nexus_mods.mod_files(mod_id: 2014))
|
59
|
-
end
|
41
|
+
it 'returns the default mod files list' do
|
42
|
+
expect_mod_files_to_be_example(nexus_mods(mod_id: 2014).mod_files(game_domain_name: 'skyrimspecialedition'))
|
43
|
+
end
|
60
44
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
45
|
+
it 'returns mod files list for the default game' do
|
46
|
+
expect_mod_files_to_be_example(nexus_mods(game_domain_name: 'skyrimspecialedition').mod_files(mod_id: 2014))
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns mod files list for the default game set using accessor' do
|
50
|
+
nexus_mods.game_domain_name = 'skyrimspecialedition'
|
51
|
+
expect_mod_files_to_be_example(nexus_mods.mod_files(mod_id: 2014))
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns mod files list for the default game and mod' do
|
55
|
+
expect_mod_files_to_be_example(nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014).mod_files)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns mod files list for the default game and mod using accessor' do
|
59
|
+
nexus_mods.mod_id = 2014
|
60
|
+
expect_mod_files_to_be_example(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition'))
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns the mod associated to the mod file' do
|
64
|
+
expect_http_call_to(
|
65
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
66
|
+
json: json_complete_mod
|
67
|
+
)
|
68
|
+
expect_mod_to_be_complete(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014).first.mod)
|
69
|
+
end
|
68
70
|
|
69
|
-
it 'returns mod files list for the default game and mod using accessor' do
|
70
|
-
expect_http_call_to(
|
71
|
-
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
72
|
-
json: { files: json_example_mod_files }
|
73
|
-
)
|
74
|
-
nexus_mods.mod_id = 2014
|
75
|
-
expect_mod_files_to_be_example(nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition'))
|
76
71
|
end
|
77
72
|
|
78
73
|
it 'compares objects for equality' do
|
79
74
|
expect_http_call_to(
|
80
75
|
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
81
|
-
json: { files
|
76
|
+
json: { 'files' => [json_mod_file2472] }
|
82
77
|
)
|
83
78
|
mod_file1 = nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014).mod_files.first
|
84
79
|
mod_file2 = nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014).mod_files.first
|
@@ -96,11 +91,12 @@ describe NexusMods::Api::ModFile do
|
|
96
91
|
archived: 7,
|
97
92
|
unknown: 100
|
98
93
|
}.each do |category, category_id|
|
94
|
+
|
99
95
|
it "accepts mod files having category #{category}" do
|
100
96
|
expect_http_call_to(
|
101
97
|
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
102
98
|
json: {
|
103
|
-
files
|
99
|
+
'files' => [
|
104
100
|
{
|
105
101
|
'id' => [
|
106
102
|
2472,
|
@@ -132,6 +128,197 @@ describe NexusMods::Api::ModFile do
|
|
132
128
|
expect(mod_file.category).to eq category
|
133
129
|
expect(mod_file.category_id).to eq category_id
|
134
130
|
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when checking cache data freshness' do
|
135
|
+
|
136
|
+
it 'returns that mod files never retrieved are not up-to-date' do
|
137
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when retrieving mod files previously' do
|
141
|
+
|
142
|
+
before do
|
143
|
+
expect_http_call_to(
|
144
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
145
|
+
json: { 'files' => [json_mod_file2472] }
|
146
|
+
)
|
147
|
+
nexus_mods.mod_files(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when retrieved 40 days ago' do
|
151
|
+
|
152
|
+
let(:forty_days_ago) { Time.now - (40 * 24 * 60 * 60) }
|
153
|
+
|
154
|
+
before do
|
155
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: forty_days_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns that mod files are not up-to-date' do
|
159
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
160
|
+
expect(nexus_mods.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq forty_days_ago
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'when retrieved 2 days ago' do
|
166
|
+
|
167
|
+
let(:two_days_ago) { Time.now - (2 * 24 * 60 * 60) }
|
168
|
+
|
169
|
+
before do
|
170
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: two_days_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'returns that mod files are up-to-date after checking updated mods and not finding it, and updates its cache timestamp to the update time' do
|
174
|
+
expect_http_call_to(
|
175
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
176
|
+
json: []
|
177
|
+
)
|
178
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
179
|
+
expect(nexus_mods.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq(
|
180
|
+
nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
181
|
+
)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'returns that mod files are up-to-date after checking updated mods and finding that cache is more recent, and updates its cache timestamp to the update time' do
|
185
|
+
expect_http_call_to(
|
186
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
187
|
+
json: [
|
188
|
+
{
|
189
|
+
'mod_id' => 2014,
|
190
|
+
# Mock that mod was updated 3 days ago
|
191
|
+
'latest_file_update' => Integer((Time.now - (3 * 24 * 60 * 60)).strftime('%s')),
|
192
|
+
'latest_mod_activity' => 1
|
193
|
+
}
|
194
|
+
]
|
195
|
+
)
|
196
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
197
|
+
expect(nexus_mods.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq(
|
198
|
+
nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'returns that mod files are not up-to-date after checking updated mods and finding that cache is less recent' do
|
203
|
+
expect_http_call_to(
|
204
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
205
|
+
json: [
|
206
|
+
{
|
207
|
+
'mod_id' => 2014,
|
208
|
+
# Mock that mod was updated yesterday
|
209
|
+
'latest_file_update' => Integer((Time.now - (24 * 60 * 60)).strftime('%s')),
|
210
|
+
'latest_mod_activity' => 1
|
211
|
+
}
|
212
|
+
]
|
213
|
+
)
|
214
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
215
|
+
expect(nexus_mods.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq two_days_ago
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'when retrieved 3 minutes ago with an updated mods query 4 minutes ago in the cache' do
|
221
|
+
|
222
|
+
let(:three_minutes_ago) { Time.now - (3 * 60) }
|
223
|
+
let(:four_minutes_ago) { Time.now - (4 * 60) }
|
224
|
+
|
225
|
+
before do
|
226
|
+
expect_http_call_to(
|
227
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
228
|
+
json: [
|
229
|
+
{
|
230
|
+
'mod_id' => 2014,
|
231
|
+
# Mock that mod was updated 3 days ago
|
232
|
+
'latest_file_update' => Integer((Time.now - (3 * 24 * 60 * 60)).strftime('%s')),
|
233
|
+
'latest_mod_activity' => 1
|
234
|
+
}
|
235
|
+
]
|
236
|
+
)
|
237
|
+
nexus_mods.updated_mods(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
238
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: three_minutes_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
239
|
+
nexus_mods.set_updated_mods_cache_timestamp(cache_timestamp: four_minutes_ago, game_domain_name: 'skyrimspecialedition', since: :one_month)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'returns that mod files are up-to-date but doesn\'t change its mod cache timestamp' do
|
243
|
+
expect(nexus_mods.mod_files_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
244
|
+
expect(nexus_mods.mod_files_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq three_minutes_ago
|
245
|
+
expect(nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)).to eq four_minutes_ago
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'when checking for updates' do
|
255
|
+
|
256
|
+
before do
|
257
|
+
nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'does not check for updates if mod files have not been retrieved before' do
|
261
|
+
expect_http_call_to(
|
262
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
263
|
+
json: { 'files' => [json_mod_file2472] }
|
264
|
+
)
|
265
|
+
expect_mod_file_to_be2472(nexus_mods.mod_files(check_updates: true).first)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'does not check for updates if mod files have been retrieved more than 1 month ago, and re-query the mod' do
|
269
|
+
expect_http_call_to(
|
270
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
271
|
+
json: { 'files' => [json_mod_file2472] },
|
272
|
+
times: 2
|
273
|
+
)
|
274
|
+
nexus_mods.mod_files
|
275
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: Time.now - (40 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
276
|
+
expect_mod_file_to_be2472(nexus_mods.mod_files(check_updates: true).first)
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'checks for updates when mod has been retrieved less than 1 month ago and does nothing if its date is less recent than the cache' do
|
280
|
+
expect_http_call_to(
|
281
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
282
|
+
json: { 'files' => [json_mod_file2472] }
|
283
|
+
)
|
284
|
+
expect_http_call_to(
|
285
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
286
|
+
json: [
|
287
|
+
{
|
288
|
+
'mod_id' => 2014,
|
289
|
+
# Mock that mod was updated 25 days ago
|
290
|
+
'latest_file_update' => Integer((Time.now - (25 * 24 * 60 * 60)).strftime('%s')),
|
291
|
+
'latest_mod_activity' => 1
|
292
|
+
}
|
293
|
+
]
|
294
|
+
)
|
295
|
+
nexus_mods.mod_files
|
296
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: Time.now - (20 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
297
|
+
expect_mod_file_to_be2472(nexus_mods.mod_files(check_updates: true).first)
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'checks for updates when mod has been retrieved less than 1 month ago and re-query the mod if its date is more recent than the cache' do
|
301
|
+
expect_http_call_to(
|
302
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
303
|
+
json: { 'files' => [json_mod_file2472] },
|
304
|
+
times: 2
|
305
|
+
)
|
306
|
+
expect_http_call_to(
|
307
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
308
|
+
json: [
|
309
|
+
{
|
310
|
+
'mod_id' => 2014,
|
311
|
+
# Mock that mod was updated 15 days ago
|
312
|
+
'latest_file_update' => Integer((Time.now - (15 * 24 * 60 * 60)).strftime('%s')),
|
313
|
+
'latest_mod_activity' => 1
|
314
|
+
}
|
315
|
+
]
|
316
|
+
)
|
317
|
+
nexus_mods.mod_files
|
318
|
+
nexus_mods.set_mod_files_cache_timestamp(cache_timestamp: Time.now - (20 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
319
|
+
expect_mod_file_to_be2472(nexus_mods.mod_files(check_updates: true).first)
|
320
|
+
end
|
321
|
+
|
135
322
|
end
|
136
323
|
|
137
324
|
end
|
@@ -6,73 +6,261 @@ describe NexusMods::Api::Mod do
|
|
6
6
|
expect_validate_user
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
expect_http_call_to(
|
11
|
-
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
12
|
-
json: json_complete_mod
|
13
|
-
)
|
14
|
-
expect_mod_to_be_complete(nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014))
|
15
|
-
end
|
9
|
+
context 'when accessing a partial mod' do
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
11
|
+
before do
|
12
|
+
expect_http_call_to(
|
13
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
14
|
+
json: json_partial_mod
|
15
|
+
)
|
16
|
+
end
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
json: json_complete_mod
|
29
|
-
)
|
30
|
-
expect_mod_to_be_complete(nexus_mods(mod_id: 2014).mod(game_domain_name: 'skyrimspecialedition'))
|
31
|
-
end
|
18
|
+
it 'returns the mod information' do
|
19
|
+
expect_mod_to_be_partial(nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014))
|
20
|
+
end
|
32
21
|
|
33
|
-
it 'returns mod information for the default game' do
|
34
|
-
expect_http_call_to(
|
35
|
-
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
36
|
-
json: json_complete_mod
|
37
|
-
)
|
38
|
-
expect_mod_to_be_complete(nexus_mods(game_domain_name: 'skyrimspecialedition').mod(mod_id: 2014))
|
39
22
|
end
|
40
23
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
24
|
+
context 'when accessing a complete mod' do
|
25
|
+
|
26
|
+
before do
|
27
|
+
expect_http_call_to(
|
28
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
29
|
+
json: json_complete_mod
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns the mod information' do
|
34
|
+
expect_mod_to_be_complete(nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014))
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns the default mod information' do
|
38
|
+
expect_mod_to_be_complete(nexus_mods(mod_id: 2014).mod(game_domain_name: 'skyrimspecialedition'))
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns mod information for the default game' do
|
42
|
+
expect_mod_to_be_complete(nexus_mods(game_domain_name: 'skyrimspecialedition').mod(mod_id: 2014))
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns mod information for the default game set using accessor' do
|
46
|
+
nexus_mods.game_domain_name = 'skyrimspecialedition'
|
47
|
+
expect_mod_to_be_complete(nexus_mods.mod(mod_id: 2014))
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns mod information for the default game and mod' do
|
51
|
+
expect_mod_to_be_complete(nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014).mod)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns mod information for the default game and mod set using accessor' do
|
55
|
+
nexus_mods.mod_id = 2014
|
56
|
+
expect_mod_to_be_complete(nexus_mods.mod(game_domain_name: 'skyrimspecialedition'))
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'compares objects for equality' do
|
60
|
+
mod1 = nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
61
|
+
mod2 = nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
62
|
+
expect(mod1.object_id).not_to eq mod2.object_id
|
63
|
+
expect(mod1).to eq mod2
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns the mod files associated to the mod' do
|
67
|
+
expect_http_call_to(
|
68
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
69
|
+
json: { 'files' => [json_mod_file2472] }
|
70
|
+
)
|
71
|
+
expect_mod_file_to_be2472(nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014).files.first)
|
72
|
+
end
|
49
73
|
|
50
|
-
it 'returns mod information for the default game and mod' do
|
51
|
-
expect_http_call_to(
|
52
|
-
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
53
|
-
json: json_complete_mod
|
54
|
-
)
|
55
|
-
expect_mod_to_be_complete(nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014).mod)
|
56
74
|
end
|
57
75
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
76
|
+
context 'when checking cache data freshness' do
|
77
|
+
|
78
|
+
it 'returns that a mod never retrieved is not up-to-date' do
|
79
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when retrieving a mod previously' do
|
83
|
+
|
84
|
+
before do
|
85
|
+
expect_http_call_to(
|
86
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
87
|
+
json: json_complete_mod
|
88
|
+
)
|
89
|
+
nexus_mods.mod(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when retrieved 40 days ago' do
|
93
|
+
|
94
|
+
let(:forty_days_ago) { Time.now - (40 * 24 * 60 * 60) }
|
95
|
+
|
96
|
+
before do
|
97
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: forty_days_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'returns that the mod is not up-to-date' do
|
101
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
102
|
+
expect(nexus_mods.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq forty_days_ago
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when retrieved 2 days ago' do
|
108
|
+
|
109
|
+
let(:two_days_ago) { Time.now - (2 * 24 * 60 * 60) }
|
110
|
+
|
111
|
+
before do
|
112
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: two_days_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns that the mod is up-to-date after checking updated mods and not finding it, and updates its cache timestamp to the update time' do
|
116
|
+
expect_http_call_to(
|
117
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
118
|
+
json: []
|
119
|
+
)
|
120
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
121
|
+
expect(nexus_mods.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq(
|
122
|
+
nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns that the mod is up-to-date after checking updated mods and finding that cache is more recent, and updates its cache timestamp to the update time' do
|
127
|
+
expect_http_call_to(
|
128
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
129
|
+
json: [
|
130
|
+
{
|
131
|
+
'mod_id' => 2014,
|
132
|
+
# Mock that mod was updated 3 days ago
|
133
|
+
'latest_file_update' => 1,
|
134
|
+
'latest_mod_activity' => Integer((Time.now - (3 * 24 * 60 * 60)).strftime('%s'))
|
135
|
+
}
|
136
|
+
]
|
137
|
+
)
|
138
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
139
|
+
expect(nexus_mods.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq(
|
140
|
+
nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'returns that the mod is not up-to-date after checking updated mods and finding that cache is less recent' do
|
145
|
+
expect_http_call_to(
|
146
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
147
|
+
json: [
|
148
|
+
{
|
149
|
+
'mod_id' => 2014,
|
150
|
+
# Mock that mod was updated yesterday
|
151
|
+
'latest_file_update' => 1,
|
152
|
+
'latest_mod_activity' => Integer((Time.now - (24 * 60 * 60)).strftime('%s'))
|
153
|
+
}
|
154
|
+
]
|
155
|
+
)
|
156
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be false
|
157
|
+
expect(nexus_mods.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq two_days_ago
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when retrieved 3 minutes ago with an updated mods query 4 minutes ago in the cache' do
|
163
|
+
|
164
|
+
let(:three_minutes_ago) { Time.now - (3 * 60) }
|
165
|
+
let(:four_minutes_ago) { Time.now - (4 * 60) }
|
166
|
+
|
167
|
+
before do
|
168
|
+
expect_http_call_to(
|
169
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
170
|
+
json: [
|
171
|
+
{
|
172
|
+
'mod_id' => 2014,
|
173
|
+
# Mock that mod was updated 3 days ago
|
174
|
+
'latest_file_update' => 1,
|
175
|
+
'latest_mod_activity' => Integer((Time.now - (3 * 24 * 60 * 60)).strftime('%s'))
|
176
|
+
}
|
177
|
+
]
|
178
|
+
)
|
179
|
+
nexus_mods.updated_mods(game_domain_name: 'skyrimspecialedition', since: :one_month)
|
180
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: three_minutes_ago, game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
181
|
+
nexus_mods.set_updated_mods_cache_timestamp(cache_timestamp: four_minutes_ago, game_domain_name: 'skyrimspecialedition', since: :one_month)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'returns that the mod is up-to-date but doesn\'t change its mod cache timestamp' do
|
185
|
+
expect(nexus_mods.mod_cache_up_to_date?(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to be true
|
186
|
+
expect(nexus_mods.mod_cache_timestamp(game_domain_name: 'skyrimspecialedition', mod_id: 2014)).to eq three_minutes_ago
|
187
|
+
expect(nexus_mods.updated_mods_cache_timestamp(game_domain_name: 'skyrimspecialedition', since: :one_month)).to eq four_minutes_ago
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
65
194
|
end
|
66
195
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
196
|
+
context 'when checking for updates' do
|
197
|
+
|
198
|
+
before do
|
199
|
+
nexus_mods(game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'does not check for updates if mod has not been retrieved before' do
|
203
|
+
expect_http_call_to(
|
204
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
205
|
+
json: json_complete_mod
|
206
|
+
)
|
207
|
+
expect_mod_to_be_complete(nexus_mods.mod(check_updates: true))
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'does not check for updates if mod has been retrieved more than 1 month ago, and re-query the mod' do
|
211
|
+
expect_http_call_to(
|
212
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
213
|
+
json: json_complete_mod,
|
214
|
+
times: 2
|
215
|
+
)
|
216
|
+
nexus_mods.mod
|
217
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: Time.now - (40 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
218
|
+
expect_mod_to_be_complete(nexus_mods.mod(check_updates: true))
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'checks for updates when mod has been retrieved less than 1 month ago and does nothing if its date is less recent than the cache' do
|
222
|
+
expect_http_call_to(
|
223
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
224
|
+
json: json_complete_mod
|
225
|
+
)
|
226
|
+
expect_http_call_to(
|
227
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
228
|
+
json: [
|
229
|
+
{
|
230
|
+
'mod_id' => 2014,
|
231
|
+
# Mock that mod was updated 25 days ago
|
232
|
+
'latest_file_update' => 1,
|
233
|
+
'latest_mod_activity' => Integer((Time.now - (25 * 24 * 60 * 60)).strftime('%s'))
|
234
|
+
}
|
235
|
+
]
|
236
|
+
)
|
237
|
+
nexus_mods.mod
|
238
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: Time.now - (20 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
239
|
+
expect_mod_to_be_complete(nexus_mods.mod(check_updates: true))
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'checks for updates when mod has been retrieved less than 1 month ago and re-query the mod if its date is more recent than the cache' do
|
243
|
+
expect_http_call_to(
|
244
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
245
|
+
json: json_complete_mod,
|
246
|
+
times: 2
|
247
|
+
)
|
248
|
+
expect_http_call_to(
|
249
|
+
path: '/v1/games/skyrimspecialedition/mods/updated.json?period=1m',
|
250
|
+
json: [
|
251
|
+
{
|
252
|
+
'mod_id' => 2014,
|
253
|
+
# Mock that mod was updated 15 days ago
|
254
|
+
'latest_file_update' => 1,
|
255
|
+
'latest_mod_activity' => Integer((Time.now - (15 * 24 * 60 * 60)).strftime('%s'))
|
256
|
+
}
|
257
|
+
]
|
258
|
+
)
|
259
|
+
nexus_mods.mod
|
260
|
+
nexus_mods.set_mod_cache_timestamp(cache_timestamp: Time.now - (20 * 24 * 60 * 60), game_domain_name: 'skyrimspecialedition', mod_id: 2014)
|
261
|
+
expect_mod_to_be_complete(nexus_mods.mod(check_updates: true))
|
262
|
+
end
|
263
|
+
|
76
264
|
end
|
77
265
|
|
78
266
|
end
|
@@ -78,6 +78,34 @@ describe NexusMods::Api::ModUpdates do
|
|
78
78
|
expect(mod_updates1).to eq mod_updates2
|
79
79
|
end
|
80
80
|
|
81
|
+
it 'returns the mod associated to the mod updates' do
|
82
|
+
expect_http_call_to(
|
83
|
+
path: "/v1/games/skyrimspecialedition/mods/updated.json?#{since_config[:expected_url_params]}",
|
84
|
+
json: [
|
85
|
+
json_mod_updates2014
|
86
|
+
]
|
87
|
+
)
|
88
|
+
expect_http_call_to(
|
89
|
+
path: '/v1/games/skyrimspecialedition/mods/2014.json',
|
90
|
+
json: json_complete_mod
|
91
|
+
)
|
92
|
+
expect_mod_to_be_complete(nexus_mods.updated_mods(game_domain_name: 'skyrimspecialedition', since: since_config[:since]).first.mod)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'returns the mod files associated to the mod updates' do
|
96
|
+
expect_http_call_to(
|
97
|
+
path: "/v1/games/skyrimspecialedition/mods/updated.json?#{since_config[:expected_url_params]}",
|
98
|
+
json: [
|
99
|
+
json_mod_updates2014
|
100
|
+
]
|
101
|
+
)
|
102
|
+
expect_http_call_to(
|
103
|
+
path: '/v1/games/skyrimspecialedition/mods/2014/files.json',
|
104
|
+
json: { 'files' => [json_mod_file2472] }
|
105
|
+
)
|
106
|
+
expect_mod_file_to_be2472(nexus_mods.updated_mods(game_domain_name: 'skyrimspecialedition', since: since_config[:since]).first.mod_files.first)
|
107
|
+
end
|
108
|
+
|
81
109
|
end
|
82
110
|
|
83
111
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexus_mods
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Muriel Salvan
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- lib/nexus_mods/api/mod.rb
|
139
139
|
- lib/nexus_mods/api/mod_file.rb
|
140
140
|
- lib/nexus_mods/api/mod_updates.rb
|
141
|
+
- lib/nexus_mods/api/resource.rb
|
141
142
|
- lib/nexus_mods/api/user.rb
|
142
143
|
- lib/nexus_mods/api_client.rb
|
143
144
|
- lib/nexus_mods/cacheable_api.rb
|