auciel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4a4db1df8b90eb61efa04eb689e247d0ba58d7e2469e0b06b4ccd3dce458511e
4
+ data.tar.gz: e4ae843ec6cc04501c3c517ae8c25bcf2f715dde4b54d74ea370dfed45a73b11
5
+ SHA512:
6
+ metadata.gz: 45e2c98006106e4f76778456567dc8a68f7b000042e9afa6d1a5d3e79af7ddff46c5c4736c30dcb6a947c1e0091fb5c69eb6cae878766a23f45c7937342727ff
7
+ data.tar.gz: 0ac7d1a7ddf033ffa46cfb16d94a3b6ea4c979a074d0004ff32d564032bfd8ddcd244b8cd8360215e3183fc37ff972afcc41fecd2fd07b939b43d2da1323e661
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 jpegzilla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/lib/auciel.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tsurezure'
4
+ require_relative './endpoints/item'
5
+ require_relative './endpoints/search'
6
+ require_relative './endpoints/prices'
7
+ require_relative './endpoints/hot'
8
+ require_relative './endpoints/waitlist'
9
+
10
+ # main class for auciel
11
+ class Auciel
12
+ include ItemEndpoints
13
+ include SearchEndpoints
14
+ include PriceEndpoints
15
+ include HotEndpoints
16
+ include WaitlistEndpoints
17
+
18
+ def initialize(port = 8888)
19
+ @server = Tsurezure.new port
20
+ register_endpoints
21
+ end
22
+
23
+ def register_endpoints
24
+ # /item/:id
25
+ @server.register(*ItemEndpoints::GET_ITEM_BY_ID)
26
+
27
+ # /item/:cat/:sub
28
+ @server.register(*ItemEndpoints::GET_ITEM_BY_CATEGORY)
29
+
30
+ # /search
31
+ # requires a urlencoded string
32
+ @server.register(*SearchEndpoints::SEARCH_ITEM_BY_TEXT)
33
+
34
+ # /prices/:id
35
+ @server.register(*PriceEndpoints::GET_PRICE_LIST_BY_ID_AND_NAME)
36
+
37
+ # /hot
38
+ @server.register(*HotEndpoints::GET_HOT_ITEMS_LIST)
39
+
40
+ # /waitlist
41
+ @server.register(*WaitlistEndpoints::GET_WAITLIST_ITEMS)
42
+ end
43
+
44
+ def listen
45
+ @server.listen lambda { |opts|
46
+ puts "listening on port #{opts[:port]}!"
47
+ }
48
+ rescue Interrupt
49
+ puts '[auciel] shutting down.'
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Constants
4
+ COOKIE =
5
+ '__RequestVerificationToken=0q_pyZ8OMkALLxxv_pj6ty10hXKTDq3Sl_1NAbV5WYhUAbNvcurT6GwSUDmBRnaZVyEmd0lcTlR3I6X7_cXkAwH-nGQG_G2E6MQZPNcfNd41'
6
+ RVT = 'MGf54RSTVQkYrPo4Dvaf9IOuSilYwQIzWfdBI4PhFrV1l1o_e0BRmf78J6I7pVn_gcqj5DAv-G3MfFiWoUqFE3R62-Kxdcm4CgkRGd7oq7Y1'
7
+ ROOT_URL = 'https://na-trade.naeu.playblackdesert.com/Home'
8
+ WORLD_MARKET_LIST = '/GetWorldMarketList'
9
+ MARKET_SUB_LIST = '/GetWorldMarketSubList'
10
+ MARKET_SEARCH_LIST = '/GetWorldMarketSearchList'
11
+ MARKET_SELL_BUY_INFO = '/GetItemSellBuyInfo'
12
+ MARKET_HOT_LIST = '/GetWorldMarketHotList'
13
+ MARKET_WAIT_LIST = '/GetWorldMarketWaitList'
14
+ REQUEST_OPTS = {
15
+ method: 'post',
16
+ headers: {
17
+ 'Content-Type': 'application/x-www-form-urlencoded',
18
+ 'User-Agent':
19
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
20
+ Cookie: COOKIE
21
+ }
22
+ }.freeze
23
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require_relative './../constants/constants'
5
+ require_relative './../utils/response_formatter'
6
+
7
+ # get a list of currently popular items
8
+ module HotEndpoints
9
+ include Constants
10
+ include FormData
11
+ include ResponseFormatter
12
+
13
+ def self.send_post_request(uri)
14
+ HTTParty.post(
15
+ uri,
16
+ headers: Constants::REQUEST_OPTS[:headers]
17
+ )
18
+ end
19
+
20
+ def self.respond_if_available(res)
21
+ return res.body if res.body
22
+
23
+ {
24
+ error: 'invalid response from the black desert api.',
25
+ response: res
26
+ }.to_json
27
+ end
28
+
29
+ def self.hot_items
30
+ lambda do |_req|
31
+ uri = URI "#{Constants::ROOT_URL}#{Constants::MARKET_HOT_LIST}"
32
+ res = send_post_request uri
33
+
34
+ ResponseFormatter.format_hot_response(respond_if_available(res))
35
+ end
36
+ end
37
+
38
+ GET_HOT_ITEMS_LIST = {
39
+ method: 'get',
40
+ path: '/hot',
41
+ responder: hot_items,
42
+ opts: { content_type: 'application/json' }
43
+ }.values.freeze
44
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require_relative './../constants/constants'
5
+ require_relative './../utils/response_formatter'
6
+
7
+ # form data for various requests
8
+ module FormData
9
+ def self.item_by_id_data(id)
10
+ {
11
+ __requestVerificationToken: Constants::RVT,
12
+ mainKey: id,
13
+ usingCleint: 0
14
+ }
15
+ end
16
+
17
+ def self.item_by_cat_data(cat, sub)
18
+ {
19
+ __requestVerificationToken: Constants::RVT,
20
+ mainCategory: cat,
21
+ subCategory: sub
22
+ }
23
+ end
24
+ end
25
+
26
+ # get item by id and other item-related methods
27
+ module ItemEndpoints
28
+ include Constants
29
+ include FormData
30
+ include ResponseFormatter
31
+
32
+ def self.send_post_request(uri, data)
33
+ uri_params = URI.encode_www_form data
34
+
35
+ HTTParty.post(
36
+ uri,
37
+ body: uri_params,
38
+ headers: Constants::REQUEST_OPTS[:headers]
39
+ )
40
+ end
41
+
42
+ def self.respond_if_available(res)
43
+ return res.body if res.body
44
+
45
+ {
46
+ error: 'invalid response from the black desert api.',
47
+ response: res
48
+ }.to_json
49
+ end
50
+
51
+ def self.item_by_id
52
+ lambda do |req|
53
+ item_id = req[:vars]['id']
54
+ uri = URI "#{Constants::ROOT_URL}#{Constants::MARKET_SUB_LIST}"
55
+ form = FormData.item_by_id_data item_id
56
+ res = send_post_request uri, form
57
+
58
+ ResponseFormatter.format_item_response(respond_if_available(res))
59
+ end
60
+ end
61
+
62
+ def self.items_by_category
63
+ lambda do |req|
64
+ item_cat = req[:vars]['cat']
65
+ item_sub = req[:vars]['sub']
66
+ uri = URI "#{Constants::ROOT_URL}#{Constants::WORLD_MARKET_LIST}"
67
+ form = FormData.item_by_cat_data item_cat, item_sub
68
+ res = send_post_request uri, form
69
+
70
+ ResponseFormatter.format_cat_response(respond_if_available(res))
71
+ end
72
+ end
73
+
74
+ GET_ITEM_BY_ID = {
75
+ method: 'get',
76
+ path: '/item/:id',
77
+ responder: item_by_id,
78
+ opts: { content_type: 'application/json' }
79
+ }.values.freeze
80
+
81
+ GET_ITEM_BY_CATEGORY = {
82
+ method: 'get',
83
+ path: '/item/:cat/:sub',
84
+ responder: items_by_category,
85
+ opts: { content_type: 'application/json' }
86
+ }.values.freeze
87
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require_relative './../constants/constants'
5
+ require_relative './../utils/response_formatter'
6
+
7
+ # form data for various requests
8
+ module FormData
9
+ def self.price_list_data(id)
10
+ {
11
+ __requestVerificationToken: Constants::RVT,
12
+ mainKey: id,
13
+ subKey: 0,
14
+ keyType: 0,
15
+ isUp: true
16
+ }
17
+ end
18
+ end
19
+
20
+ # get price list by id and name, and other price-related endpoints
21
+ module PriceEndpoints
22
+ include Constants
23
+ include FormData
24
+ include ResponseFormatter
25
+
26
+ def self.send_post_request(uri, data)
27
+ uri_params = URI.encode_www_form data
28
+
29
+ HTTParty.post(
30
+ uri,
31
+ body: uri_params,
32
+ headers: Constants::REQUEST_OPTS[:headers]
33
+ )
34
+ end
35
+
36
+ def self.respond_if_available(res)
37
+ return res.body if res.body
38
+
39
+ {
40
+ error: 'invalid response from the black desert api.',
41
+ response: res
42
+ }.to_json
43
+ end
44
+
45
+ def self.price_list_by_id_and_name
46
+ lambda do |req|
47
+ item_id = req[:vars]['id']
48
+ uri = URI "#{Constants::ROOT_URL}#{Constants::MARKET_SELL_BUY_INFO}"
49
+ form = FormData.price_list_data item_id
50
+ res = send_post_request uri, form
51
+
52
+ ResponseFormatter.format_price_list_response(respond_if_available(res))
53
+ end
54
+ end
55
+
56
+ GET_PRICE_LIST_BY_ID_AND_NAME = {
57
+ method: 'get',
58
+ path: '/prices/:id',
59
+ responder: price_list_by_id_and_name,
60
+ opts: { content_type: 'application/json' }
61
+ }.values.freeze
62
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require_relative './../constants/constants'
5
+ require_relative './../utils/response_formatter'
6
+
7
+ # form data for various requests
8
+ module FormData
9
+ def self.search_item_by_text_data(search_text)
10
+ "__requestVerificationToken=#{Constants::RVT}&searchText=#{search_text}"
11
+ end
12
+ end
13
+
14
+ # search for item and other search-related methods
15
+ module SearchEndpoints
16
+ include Constants
17
+ include FormData
18
+ include ResponseFormatter
19
+
20
+ def self.send_post_request(uri, data)
21
+ uri_params = data
22
+ uri_params = URI.encode_www_form(data) if data.is_a? Hash
23
+
24
+ HTTParty.post(
25
+ uri,
26
+ body: uri_params,
27
+ headers: Constants::REQUEST_OPTS[:headers]
28
+ )
29
+ end
30
+
31
+ def self.respond_if_available(res)
32
+ return res.body if res.body
33
+
34
+ {
35
+ error: 'invalid response from the black desert api.',
36
+ response: res
37
+ }.to_json
38
+ end
39
+
40
+ def self.search_item_by_text
41
+ lambda do |req|
42
+ search_text = req[:params]['q']
43
+ uri = URI "#{Constants::ROOT_URL}#{Constants::MARKET_SEARCH_LIST}"
44
+ form = FormData.search_item_by_text_data search_text
45
+ res = send_post_request uri, form
46
+
47
+ ResponseFormatter.format_search_response(respond_if_available(res))
48
+ end
49
+ end
50
+
51
+ SEARCH_ITEM_BY_TEXT = {
52
+ method: 'get',
53
+ path: '/search',
54
+ responder: search_item_by_text,
55
+ opts: { content_type: 'application/json' }
56
+ }.values.freeze
57
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require_relative './../constants/constants'
5
+ require_relative './../utils/response_formatter'
6
+
7
+ # get a list of items in the registration queue
8
+ module WaitlistEndpoints
9
+ include Constants
10
+ include FormData
11
+ include ResponseFormatter
12
+
13
+ def self.send_post_request(uri)
14
+ HTTParty.post(
15
+ uri,
16
+ headers: Constants::REQUEST_OPTS[:headers]
17
+ )
18
+ end
19
+
20
+ def self.respond_if_available(res)
21
+ return res.body if res.body
22
+
23
+ {
24
+ error: 'invalid response from the black desert api.',
25
+ response: res
26
+ }.to_json
27
+ end
28
+
29
+ def self.waitlist_items
30
+ lambda do |_req|
31
+ uri = URI "#{Constants::ROOT_URL}#{Constants::MARKET_WAIT_LIST}"
32
+ res = send_post_request uri
33
+
34
+ ResponseFormatter.format_waitlist_response(respond_if_available(res))
35
+ end
36
+ end
37
+
38
+ GET_WAITLIST_ITEMS = {
39
+ method: 'get',
40
+ path: '/waitlist',
41
+ responder: waitlist_items,
42
+ opts: { content_type: 'application/json' }
43
+ }.values.freeze
44
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # contains all the errors the api can return.
4
+ module ApiErrors
5
+ UNEXPECTED_BLACK_DESERT_RESPONSE = {
6
+ error: 'the black desert api returned an unexpected value. please report this to jpegzilla.'
7
+ }.freeze.to_json
8
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require_relative './api_errors'
5
+
6
+ # rubocop:disable Lint/MissingCopEnableDirective, Metrics/MethodLength
7
+
8
+ # used to format responses from the black desert api
9
+ module ResponseFormatter
10
+ include ApiErrors
11
+
12
+ # returns an error message if the black desert api returns an error
13
+ def self.try_error(json)
14
+ return false if json['resultCode'].zero?
15
+
16
+ {
17
+ resultCode: json['resultCode'],
18
+ resultMsg: json['resultMsg']
19
+ }.to_json
20
+ end
21
+
22
+ # for /item/:id endpoint
23
+ def self.format_item_response(data)
24
+ json = JSON.parse(data)
25
+
26
+ return try_error json if try_error json
27
+
28
+ {
29
+ data: json['detailList'].map do |e|
30
+ {
31
+ **e,
32
+ id: e['mainKey']
33
+ }.except('mainKey')
34
+ end
35
+ }.to_json
36
+ rescue NoMethodError, JSON::ParserError
37
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
38
+ end
39
+
40
+ # for /item/:cat/:sub endpoint
41
+ def self.format_cat_response(data)
42
+ json = JSON.parse(data)
43
+
44
+ return try_error json if try_error json
45
+
46
+ {
47
+ data: json['marketList'].map { |e| { **e, id: e['mainKey'] } }
48
+ }.to_json
49
+ rescue NoMethodError, JSON::ParserError
50
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
51
+ end
52
+
53
+ # for /search endpoint
54
+ def self.format_search_response(data)
55
+ json = JSON.parse(data)
56
+
57
+ return try_error json if try_error json
58
+
59
+ {
60
+ data: json['list'].map { |e| { **e, id: e['mainKey'] } }
61
+ }.to_json
62
+ rescue NoMethodError, JSON::ParserError
63
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
64
+ end
65
+
66
+ # for /prices endpoint
67
+ def self.format_price_list_response(data)
68
+ json = JSON.parse(data)
69
+
70
+ return try_error json if try_error json
71
+
72
+ {
73
+ data: {
74
+ pricePoints: json['priceList'],
75
+ buySellCounts: json['marketConditionList'],
76
+ **json
77
+ }.except('marketConditionList', 'priceList', 'resultCode')
78
+ }.to_json
79
+ rescue NoMethodError, JSON::ParserError
80
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
81
+ end
82
+
83
+ # for /hot endpoint
84
+ def self.format_hot_response(data)
85
+ json = JSON.parse(data)
86
+
87
+ return try_error json if try_error json
88
+
89
+ {
90
+ data: json['hotList'].map do |e|
91
+ {
92
+ **e,
93
+ id: e['mainKey'],
94
+ fluctuationDirection: e['fluctuationType'] == 2 ? 'up' : 'down'
95
+ }
96
+ end
97
+ }.to_json
98
+ rescue NoMethodError, JSON::ParserError
99
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
100
+ end
101
+
102
+ # for /waitlist endpoint
103
+ def self.format_waitlist_response(data)
104
+ json = JSON.parse(data)
105
+
106
+ return try_error json if try_error json
107
+
108
+ {
109
+ data: json['_waitList'].map do |e|
110
+ {
111
+ **e,
112
+ id: e['mainKey'],
113
+ waitEndTime: DateTime.strptime(e['_waitEndTime'].to_s, '%Q'),
114
+ waitEndTimestampMs: e['_waitEndTime'],
115
+ pricePerOne: e['_pricePerOne']
116
+ }.except('_pricePerOne', '_waitEndTime')
117
+ end
118
+ }.to_json
119
+ rescue NoMethodError, JSON::ParserError
120
+ ApiErrors::UNEXPECTED_BLACK_DESERT_RESPONSE
121
+ end
122
+ end
data/readme.md ADDED
@@ -0,0 +1,319 @@
1
+ # auciel
2
+
3
+ auciel is a wrapper for the black desert central market api. its purpose is to enable developers to get data from the market more easily, without having to figure out the strict (and odd) request structures required for the raw central market api.
4
+
5
+ built with the [tsurezure](https://github.com/jpegzilla/tsurezure) [![gem version](https://badge.fury.io/rb/tsurezure.svg)](https://badge.fury.io/rb/tsurezure) framework.
6
+
7
+ ## usage
8
+
9
+ ### installing from rubygems
10
+
11
+ _no gem yet_
12
+
13
+ ### executable
14
+
15
+ _coming soon_
16
+
17
+ ### using source code
18
+
19
+ download this repo. then, in your ruby script:
20
+
21
+ ```ruby
22
+ require_relative 'path/to/lib/auciel'
23
+
24
+ # default port is 8888
25
+ server = Auciel.new 8888
26
+
27
+ # server will be ready for requests at localhost:8888
28
+ server.listen
29
+ ```
30
+
31
+ you can also just run `ruby main.rb` in the root directory and a server will start at `localhost:8888`.
32
+
33
+ ## endpoints
34
+
35
+ ### `/item/:id`
36
+
37
+ retrieves information about an item based on its id. equivalent to `GetWorldMarketSubList` in the raw api. example:
38
+
39
+ `GET https://localhost:8888/item/702`
40
+
41
+ ```js
42
+ {
43
+ "data": [
44
+ {
45
+ "pricePerOne": 10700,
46
+ "totalTradeCount": 14269193,
47
+ "keyType": 0,
48
+ "mainKey": 702,
49
+ "subKey": 0,
50
+ "count": 0,
51
+ "name": "Elixir of Will",
52
+ "grade": 1,
53
+ "mainCategory": 35,
54
+ "subCategory": 2,
55
+ "chooseKey": 0,
56
+ "isGodrAyed": false
57
+ }
58
+ ]
59
+ }
60
+
61
+ ```
62
+
63
+ ### `/item/:cat/:sub`
64
+
65
+ retrieves a list of items in a [category and subcategory](#item-categories). equivalent to `GetWorldMarketList` in the raw api. example:
66
+
67
+ `GET https://localhost:8888/item/35/1`
68
+ ```js
69
+ {
70
+ "data": [
71
+ {
72
+ "mainKey": 504,
73
+ "sumCount": 0,
74
+ "name": "Melee AP Enhancer",
75
+ "grade": 0,
76
+ "isGodrAyed": false,
77
+ "minPrice": 93500,
78
+ "id": 504
79
+ },
80
+ {
81
+ "mainKey": 505,
82
+ "sumCount": 0,
83
+ "name": "Ranged AP Enhancer",
84
+ "grade": 0,
85
+ "isGodrAyed": false,
86
+ "minPrice": 93500,
87
+ "id": 505
88
+ },
89
+
90
+ ...
91
+
92
+ ```
93
+
94
+ ### `/search?q=<search text>`
95
+
96
+ retrieves a list of items whose names match the provided **url encoded** search string. equivalent to `GetWorldMarketSearchList` in the raw api. example:
97
+
98
+ `GET http://localhost:8888/search?q=blood`
99
+ ```js
100
+ {
101
+ "data": [
102
+ {
103
+ "mainKey": 3040,
104
+ "sumCount": 1,
105
+ "totalSumCount": 77500000,
106
+ "name": "Muskan's Bloody Steel Helmet",
107
+ "grade": 2,
108
+ "isGodrAyed": false,
109
+ "id": 3040
110
+ },
111
+ {
112
+ "mainKey": 4453,
113
+ "sumCount": 2674,
114
+ "totalSumCount": 236000,
115
+ "name": "Blood Ruby",
116
+ "grade": 0,
117
+ "isGodrAyed": false,
118
+ "id": 4453
119
+ },
120
+ {
121
+ "mainKey": 5005,
122
+ "sumCount": 30309,
123
+ "totalSumCount": 19000,
124
+ "name": "Bloody Tree Knot",
125
+ "grade": 0,
126
+ "isGodrAyed": false,
127
+ "id": 5005
128
+ },
129
+
130
+ ...
131
+
132
+ ```
133
+
134
+ ### `/prices/:id`
135
+
136
+ retrieves a detailed price list for a specified item id. equivalent to `GetItemSellBuyInfo` in the raw api, and similar to `GetBiddingInfoList`. example:
137
+
138
+ `GET http://localhost:8888/prices/702`
139
+ ```js
140
+ {
141
+ "data": {
142
+ "pricePoints": [
143
+ 13500,
144
+ 13600,
145
+ 13700,
146
+ 13800,
147
+ 13900,
148
+ 14000,
149
+ 14100,
150
+ 14200,
151
+ 14300,
152
+ 14400,
153
+ 14500,
154
+ 14600
155
+ ],
156
+ "buySellCounts": [
157
+ {
158
+ "sellCount": 0,
159
+ "buyCount": 0,
160
+ "pricePerOne": 12500
161
+ },
162
+ {
163
+ "sellCount": 0,
164
+ "buyCount": 0,
165
+ "pricePerOne": 12600
166
+ },
167
+ {
168
+ "sellCount": 0,
169
+ "buyCount": 0,
170
+ "pricePerOne": 12700
171
+ },
172
+
173
+ ...
174
+
175
+ ```
176
+
177
+ ### `/hot`
178
+
179
+ retrieves a list of currently popular items. equivalent to `GetWorldMarketHotList` in the raw api. example:
180
+
181
+ `GET http://localhost:8888/hot`
182
+ ```js
183
+ {
184
+ "data": [
185
+ {
186
+ "subtype": 0,
187
+ "pricePerOne": 66000,
188
+ "totalTradeCount": 340891,
189
+ "fluctuationType": 2,
190
+ "fluctuationPrice": 12500,
191
+ "keyType": 0,
192
+ "mainKey": 641,
193
+ "subKey": 0,
194
+ "count": 0,
195
+ "name": "[Party] Elixir of Fury",
196
+ "grade": 1,
197
+ "mainCategory": 35,
198
+ "subCategory": 0,
199
+ "chooseKey": 0,
200
+ "isGodrAyed": false,
201
+ "id": 641,
202
+ "fluctuationDirection": "up"
203
+ },
204
+ {
205
+ "subtype": 0,
206
+ "pricePerOne": 47800,
207
+ "totalTradeCount": 1780501,
208
+ "fluctuationType": 1,
209
+ "fluctuationPrice": 12200,
210
+ "keyType": 0,
211
+ "mainKey": 683,
212
+ "subKey": 0,
213
+ "count": 8446,
214
+ "name": "Surging Energy Elixir",
215
+ "grade": 2,
216
+ "mainCategory": 35,
217
+ "subCategory": 0,
218
+ "chooseKey": 0,
219
+ "isGodrAyed": false,
220
+ "id": 683,
221
+ "fluctuationDirection": "down"
222
+ },
223
+
224
+ ...
225
+
226
+ ```
227
+
228
+ ### `/waitlist`
229
+
230
+ retrieves a list of currently waitlisted items. equivalent to `GetWorldMarketWaitList` in the raw api. example:
231
+
232
+ `GET http://localhost:8888/waitlist`
233
+ ```js
234
+ {
235
+ "data": [
236
+ {
237
+ "keyType": 0,
238
+ "mainKey": 11103,
239
+ "subKey": 0,
240
+ "count": 0,
241
+ "name": "Urugon's Shoes",
242
+ "grade": 3,
243
+ "mainCategory": 15,
244
+ "subCategory": 0,
245
+ "chooseKey": 20,
246
+ "isGodrAyed": false,
247
+ "id": 11103,
248
+ "waitEndTime": "2023-03-04T20:03:55+00:00",
249
+ "waitEndTimestampMs": 1677960235417,
250
+ "pricePerOne": 12400000000
251
+ },
252
+ {
253
+ "keyType": 0,
254
+ "mainKey": 12230,
255
+ "subKey": 0,
256
+ "count": 0,
257
+ "name": "Basilisk's Belt",
258
+ "grade": 3,
259
+ "mainCategory": 20,
260
+ "subCategory": 0,
261
+ "chooseKey": 5,
262
+ "isGodrAyed": false,
263
+ "id": 12230,
264
+ "waitEndTime": "2023-03-04T20:11:04+00:00",
265
+ "waitEndTimestampMs": 1677960664373,
266
+ "pricePerOne": 53000000000
267
+ },
268
+
269
+ ...
270
+
271
+ ```
272
+
273
+ ## item categories
274
+
275
+ here's a list of item types with their categories / subcategories for the `item/:cat/:sub` endpoint. for example, you could retrieve a list of foods at `item/35/4`.
276
+
277
+ item type | category | subcategories
278
+ ----------------------|----------|--------------
279
+ main weapon | 1 | 1-20
280
+ sub-weapon | 5 | 1-18
281
+ awakening | 10 | 1-24
282
+ armor | 15 | 1-6
283
+ accessories | 20 | 1-4
284
+ lightstone | 85 | 1-5
285
+ material | 25 | 1-8
286
+ enhancement / upgrade | 30 | 1-2
287
+ consumables | 35 | 1-8
288
+ life tools | 40 | 1-10
289
+ alchemy stone | 45 | 1-4
290
+ magic crystal | 50 | 1-4
291
+ pearl item | 55 | 1-8
292
+ dye | 60 | 1-8
293
+ mount | 65 | 1-13
294
+ ship | 70 | 1-9
295
+ wagon | 75 | 1-6
296
+ furniture | 80 | 1-9
297
+
298
+ ## item grades
299
+
300
+ here's a list of item grades with their corresponding `grade` numbers as returned from the api.
301
+
302
+ grade (border color) | number (`grade`)
303
+ ---------------------|-----------------
304
+ white | 0
305
+ green | 1
306
+ blue | 2
307
+ yellow | 3
308
+ orange | 4
309
+
310
+ ## other info
311
+
312
+ auciel is the name of the central market director at old wisdom tree.
313
+
314
+ ## stuff I don't know yet
315
+
316
+ - [ ] what is `chooseKey` on certain items?
317
+ - [ ] does `keyType` do anything?
318
+ - [ ] why does every item have an `isGodrAyed` property, even non-godr-ayeable items?
319
+ - [ ] can you get a list of every single item?
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auciel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - jpegzilla
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tsurezure
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.36
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.36
27
+ description: an api used to get data from the black desert online central market.
28
+ email: eris@jpegzilla.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - LICENSE
34
+ - lib/auciel.rb
35
+ - lib/constants/constants.rb
36
+ - lib/endpoints/hot.rb
37
+ - lib/endpoints/item.rb
38
+ - lib/endpoints/prices.rb
39
+ - lib/endpoints/search.rb
40
+ - lib/endpoints/waitlist.rb
41
+ - lib/utils/api_errors.rb
42
+ - lib/utils/response_formatter.rb
43
+ - readme.md
44
+ homepage: https://github.com/jpegzilla/auciel
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.4.7
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: this is a wrapper for black desert's marketplace api.
67
+ test_files: []