iFun Engine API  1.0.0-b2601
Great Technology for Great Games
 All Classes Files Functions Variables Typedefs Macros
deploy_api_service.h
Go to the documentation of this file.
1 // Copyright (C) 2017 iFunFactory Inc. All Rights Reserved.
2 //
3 // This work is confidential and proprietary to iFunFactory Inc. and
4 // must not be used, disclosed, copied, or distributed without the prior
5 // consent of iFunFactory Inc.
6 
9 #ifndef INCLUDE_FUNAPI_MANAGEMENT_DEPLOY_API_SERVICE_H_
10 #define INCLUDE_FUNAPI_MANAGEMENT_DEPLOY_API_SERVICE_H_
11 
12 
13 #include <boost/function.hpp>
14 #include <boost/noncopyable.hpp>
15 #include <boost/regex.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include <boost/variant.hpp>
18 
20 #include <funapi/time/wall_clock.h>
21 #include <funapi/types.h>
22 
23 #include <string>
24 #include <vector>
25 
26 namespace fun {
27 
28 class Json;
29 
30 // HTTP response writers
31 struct ResponseWriter : private boost::noncopyable {
32  virtual ~ResponseWriter();
33 };
34 
35 
37  // Writes HTTP response with given status code
38  virtual void Write(const fun::http::StatusCode code) = 0;
39 };
40 
41 
42 template<typename T>
44  // Writes HTTP status code and result of type `T' to HTTP response
45  virtual void Write(const fun::http::StatusCode code, T *result) = 0;
46 };
47 
48 
53 
54 
55 class DeployApiService : public boost::noncopyable {
56  // Interface class for iFunDeploy APIs
57  // 아이펀 디플로이를 위한 인터페이스 클래스
58  // https://docs.ifun-deploy.com/
59  public:
60  struct PageInfo {
61  // NOTE: {0, 0} means that paging is disabled.
62  uint32_t page_no; // page number; starts from 1
63  uint32_t page_size; // number of entries for a single page
64 
65  PageInfo();
66  };
67 
68  struct DeployApiHandlerBase : private boost::noncopyable {
69  virtual ~DeployApiHandlerBase();
70 
71  // Should return searchable condition list for accounts
72  virtual void GetUserSearchConditions(
73  const Ptr<StringVectorResponseWriter> &writer) const;
74 
75  // Searches account for a given condition
76  virtual void SearchUsers(
77  const std::string &condition_name,
78  const std::string &condition_value,
79  const PageInfo &page_info,
80  const Ptr<JsonVectorResponseWriter> &writer) const;
81 
82  // Returns user data as JSON for user identified by "id".
83  // In case of failure, should pass appropritate HTTP status code.
84  virtual void GetUser(
85  const std::string &id,
86  const Ptr<JsonResponseWriter> &writer) const;
87 
88  // PUT /v1/cs-api/account/<id>/<field>/<value>
89  virtual void UpdateUser(
90  const std::string &id,
91  const std::string &field,
92  const std::string &value,
93  const Ptr<VoidResponseWriter> &writer) const;
94 
95  // Returns connection status for the account as string
96  virtual void IsLoggedIn(
97  const std::string &key,
98  const Ptr<BoolResponseWriter> &writer) const;
99 
100  // Forces user to be logged-out
101  virtual void ForceLogout(
102  const std::string &id,
103  const Ptr<VoidResponseWriter> &writer) const;
104 
105  // User ban
106  // {
107  virtual void GetUserBanned(
108  const std::string &key,
109  const Ptr<BoolResponseWriter> &writer) const;
110 
111  virtual void BanUser(
112  const std::string &key, const Ptr<VoidResponseWriter> &writer) const;
113 
114  virtual void UnbanUser(
115  const std::string &key, const Ptr<VoidResponseWriter> &writer) const;
116  // }
117 
118  // Characters API
119  // {
120  virtual void GetCharacters(
121  const std::string &user_id,
122  const Ptr<JsonVectorResponseWriter> &writer) const;
123 
124  virtual void GetCharacter(
125  const std::string &character_id,
126  const Ptr<JsonResponseWriter> &writer) const;
127 
128  virtual void UpdateCharacter(
129  const std::string &character_id,
130  const std::string &field,
131  const std::string &value,
132  const Ptr<VoidResponseWriter> &writer) const;
133 
134  // vector of (inventory type, vector of inventory id)
135  typedef std::vector<std::pair<std::string, std::vector<std::string> > >
136  InventoryInfo;
137  virtual void GetCharacterInventoryInfo(
138  const std::string &character_id,
139  const Ptr<ResponseWriterT<InventoryInfo> > &writer) const;
140 
141  // result should be JSON array, which holds item data
142  virtual void GetInventory(
143  const std::string &type,
144  const std::string &inventory_id,
145  const PageInfo &page_info,
146  const Ptr<JsonVectorResponseWriter> &writer) const;
147 
148  // iFunDeploy expects there are `expected_item_quantity` items for item_id.
149  // In this function, one should decrease the quantity of item
150  // by `quantity_to_reclaim`.
151  virtual void DeleteInventoryItem(
152  const std::string &inventory_type,
153  const std::string &inventory_id,
154  const std::string &item_id,
155  const int64_t expected_item_quantity,
156  const int64_t quantity_to_reclaim,
157  const Ptr<VoidResponseWriter> &writer) const;
158 
159  struct ReclaimInfo {
160  struct ReclaimedItem {
161  std::string item_id;
162  int64_t expected_item_quantity; // expected quantity of the item
163  int64_t quantity_to_reclaim; // # of items to be decreased
164  };
165 
166  std::string inventory_type;
167  std::string inventory_id;
168  std::vector<ReclaimedItem> reclaimed;
169  };
170 
171  virtual void DeleteMultipleInventoryItems(
172  const std::vector<ReclaimInfo> &reclaimed,
173  const Ptr<VoidResponseWriter> &writer) const;
174 
175  // send gift to specific users
176  virtual void GiveGift(
177  const std::string &target_type, // target type; (account or character)
178  const std::string &title, // title of the gift message
179  const std::string &content, // body of the gift message
180  const fun::WallClock::Value &expires, // expiration time for the gift
181  const std::vector<std::pair<std::string, uint64_t> > &items,
182  const std::vector<std::string> &users, // recipients
183  const Ptr<VoidResponseWriter> &writer) const;
184 
185  // send gift to all the users
186  virtual void GiveGiftToAll(
187  const std::string &target_type, // target type; (account or character)
188  const std::string &title, // title of the gift message
189  const std::string &content, // body of the gift message
190  const fun::WallClock::Value &expires, // expiration time for the gift
191  const std::vector<std::pair<std::string, uint64_t> > &items,
192  const Ptr<VoidResponseWriter> &writer) const;
193  // }
194  protected:
195  DeployApiHandlerBase(); // Never instantiate DeployApiHandlerBase
196  };
197 
198  // Restrict editable fields for user, character
199  static bool SetEditableFieldsForUser(
200  const std::vector<std::string> &field_list);
201  static bool SetEditableFieldsForCharacter(
202  const std::vector<std::string> &field_list);
203 
204  // Restrict items which could be sent to user as a gift.
205  // item_list should be vector of (item-id, item-name) pairs.
206  static bool SetGiftableItems(
207  const std::vector<std::pair<std::string, std::string> > &item_list);
208 
209  // Event API
210  // {
212  enum ValueType {
213  //int, float, string
214  VT_INT = 0, // int64_t
215  VT_FLOAT = 1, // double
216  VT_STRING = 2, // std::string
217  };
218 
219  std::string id; // identifier to distinguish rewards in single campaign
220  std::string name; // display name; can be empty string.
221  ValueType value_type;
222  };
223 
224  struct Campaign {
225  std::string name;
226  std::vector<CampaignRewardSchema> reward_schemas;
227  };
228 
229  // Arguments passed from iFun Deploy to campaign.
230  // 아이펀 디플로이에서 캠페인 콜백에게 전달하는 인자.
232  std::string name;
233  std::string description;
234 
235  // Arguments will be parsed as specified in CampaignRewardSchema.
236  // 각 인자는 CampaignRewardSchema 에 지정한 타입으로 파싱합니다.
237  // VT_INT: int64_t
238  // VT_DOUBLE: double
239  // VT_STRING: string
240  typedef boost::variant<int64_t, double, std::string> Value;
241 
242  // list of named pairs. (reward)
243  // 보상에 해당하는 이름, 값 쌍 목록.
244  std::vector<std::pair<std::string, Value> > values;
245 
246  fun::WallClock::Value begin_ts;
247  fun::WallClock::Value end_ts;
248 
249  bool is_recurring; // is recurring event (or not). 반복 이벤트인지 여부.
250 
251  // For recurring campaign (반복 이벤트)
253  // day of week for the campaign (0 = Sun, 1 = Mon, ...)
254  // 이벤트에 해당하는 요일 (0 = 일, 1 = 월, ...)
255  std::vector<boost::date_time::weekdays> days_of_the_week;
256 
257  int32_t begin_ts_of_day; // 0 .. 86400 (in timezone)
258  int32_t end_ts_of_day; // 0 .. 86400 (in timezone)
259 
260  std::string timezone; // timezone in tz database (eg. Asia/Seoul)
261  } recurring_schedule;
262  };
263 
264  typedef boost::function<bool (const Campaign & /*data*/,
265  const std::string & /*type*/, const std::string & /*id*/,
266  const CampaignArgument & /*arg*/)> BeginCampaignCallback;
267 
268  typedef boost::function<bool (const Campaign & /*campaign_type*/,
269  const std::string & /*type*/, const std::string & /*id*/)>
270  EndCampaignCallback;
271 
272  typedef boost::function<bool (const Campaign &campaign_type,
273  const std::string &type, const std::string &id)>
274  CancelCampaignCallback;
275 
276  static bool RegisterCampaignType(const std::string &campaign_id,
277  const Campaign &campaign);
278  // called when the campaign begins
279  static void RegisterBeginCampaignCallback(const BeginCampaignCallback &cb);
280 
281  // called when the campaign ends
282  static void RegisterEndCampaignCallback(const EndCampaignCallback &cb);
283 
284  // called when the campaign is canceled
285  static void RegisterCancelCampaignCallback(const CancelCampaignCallback &cb);
286  // }
287 
288  // You should pass handler as subclass of DeployApiHandlerBase.
289  // If you pass DeployApiHandlerBase as handler, it will terminate execution.
290  template <typename T>
291  static void RegisterDeployApiHandler(boost::shared_ptr<T> handler);
292 
294  struct ExtraData : boost::noncopyable {
295  static Ptr<ExtraData> Create();
296  virtual ~ExtraData();
297 
298  // Export as JSON, which can be passed as `extra_data` argument
299  // for RegisterCustomQueryHandler.
300  virtual fun::Json Export() const = 0;
301 
302  // Create dropdown list for parameter `name`.
303  // It would make iFunDeploy UI to use select box.
304  virtual bool SetDropdownList(
305  const std::string &name, const std::vector<std::string> &values) = 0;
306 
307  protected:
308  ExtraData();
309  };
310 
313  // Takes second JSON object as argument (which should be passed in HTTP
314  // request body), then write response to writer function.
315  // Handler may write non-200 status code to indicate the error.
316  // (If the json body is not set, iFuEngine will set the JSON body as
317  // {"error": "error string for http status code"}.)
318  // The first argument is used to indicate paging.
319  typedef boost::function<void (
320  const PageInfo & /*page_info*/,
321  const fun::Json & /*request*/,
322  Ptr<JsonResponseWriter> & /*response writer*/)> CustomApiHandler;
323 
324  // Register a handler for iFunDeploy custom query
325  static void RegisterCustomQueryHandler(
326  const std::string &name, // display name
327  const http::Method &method, // HTTP verb
328  const std::string &uri, // URI (MUST NOT include regex)
329  // JSON attributes which should be provided by JSON request body
330  const std::vector<std::string> &request_fields,
331  // JSON attributes which should be placed in JSON response
332  // (for successful response)
333  const std::vector<std::string> &response_fields,
334  const CustomApiHandler &handler,
335  // Optional data which can be used by iFunDeploy to provide
336  // addtional UI component or functionality.
337  const Ptr<ExtraData> &extra_data);
338 
339  static void RegisterCustomQueryHandler(
340  const std::string &name, // display name
341  const http::Method &method, // HTTP verb
342  const std::string &uri, // URI (MUST NOT include regex)
343  // JSON attributes which should be provided by JSON request body
344  const std::vector<std::string> &request_fields,
345  // JSON attributes which should be placed in JSON response
346  // (for successful response)
347  const std::vector<std::string> &response_fields,
348  const CustomApiHandler &handler,
349  // Optional data which can be used by iFunDeploy to provide
350  // addtional UI component or functionality.
351  // You may use alternative RegisterCustomQueryHandler
352  // with ExtraData API.
353  const fun::Json &extra_data=fun::Json());
355 
356  private:
357  static void _AddImplementedHandler(const std::string &account_handler_name);
358  static void _DoRegister(boost::shared_ptr<DeployApiHandlerBase> handler);
359 };
360 
361 
364 namespace detail {
365 
366 #define HAS_MEMBER_FUNCTION(NAME, ARGS) \
367 template <typename T> \
368 class Has ## NAME { \
369 private: \
370  typedef char Yes; \
371  typedef Yes No[2]; \
372 \
373  template <typename U, U> struct Same; \
374  template <typename C> static Yes& Test(Same< \
375  void (C::*)ARGS const, &C:: NAME>*); \
376  template <typename> static No& Test(...); \
377 \
378 public: \
379  static bool const value = sizeof(Test<T>(0)) == sizeof(Yes); \
380 }
381 
382 
383 #define CHECK_MEMBER_FUNCTION(NAME) \
384  if (detail::Has ## NAME<T>::value) { _AddImplementedHandler(#NAME); }
385 
386 
387 HAS_MEMBER_FUNCTION(GetUserSearchConditions,
388  (const Ptr<StringVectorResponseWriter>&));
389 HAS_MEMBER_FUNCTION(SearchUsers,
390  (const std::string&, const std::string&, const DeployApiService::PageInfo&,
391  const Ptr<JsonVectorResponseWriter>&));
392 HAS_MEMBER_FUNCTION(GetUser,
393  (const std::string&, const Ptr<JsonResponseWriter>&));
394 HAS_MEMBER_FUNCTION(UpdateUser,
395  (const std::string&, const std::string&, const std::string&,
396  const Ptr<VoidResponseWriter>&));
397 HAS_MEMBER_FUNCTION(IsLoggedIn,
398  (const std::string&, const Ptr<BoolResponseWriter>&));
399 HAS_MEMBER_FUNCTION(ForceLogout,
400  (const std::string&, const Ptr<VoidResponseWriter>&));
401 
402 HAS_MEMBER_FUNCTION(GetUserBanned,
403  (const std::string&, const Ptr<BoolResponseWriter>&));
404 HAS_MEMBER_FUNCTION(BanUser,
405  (const std::string&, const Ptr<VoidResponseWriter>&));
406 HAS_MEMBER_FUNCTION(UnbanUser,
407  (const std::string&, const Ptr<VoidResponseWriter>&));
408 
409 HAS_MEMBER_FUNCTION(GetCharacters,
410  (const std::string &, const Ptr<JsonVectorResponseWriter>&));
411 HAS_MEMBER_FUNCTION(GetCharacter,
412  (const std::string &, const Ptr<JsonResponseWriter>&));
413 HAS_MEMBER_FUNCTION(UpdateCharacter,
414  (const std::string&, const std::string&, const std::string&,
415  const Ptr<VoidResponseWriter> &));
416 HAS_MEMBER_FUNCTION(GiveGift,
417  (const std::string&, const std::string&, const std::string&,
418  const fun::WallClock::Value&,
419  const std::vector<std::pair<std::string, uint64_t> >&,
420  const std::vector<std::string>&,
421  const Ptr<VoidResponseWriter> &));
422 HAS_MEMBER_FUNCTION(GiveGiftToAll,
423  (const std::string&, const std::string&,
424  const fun::WallClock::Value&,
425  const std::vector<std::pair<std::string, uint64_t> >&,
426  const Ptr<VoidResponseWriter> &));
427 HAS_MEMBER_FUNCTION(GetCharacterInventoryInfo,
428  (const std::string &,
429  const Ptr<ResponseWriterT<
430  DeployApiService::DeployApiHandlerBase::InventoryInfo> >&));
431 HAS_MEMBER_FUNCTION(GetInventory,
432  (const std::string&, const std::string &,
434  const Ptr<JsonVectorResponseWriter>&));
435 HAS_MEMBER_FUNCTION(DeleteInventoryItem,
436  (const std::string&, const std::string&, const std::string &,
437  const int64_t, const int64_t, const Ptr<VoidResponseWriter> &));
438 HAS_MEMBER_FUNCTION(DeleteMultipleInventoryItems,
439  (const std::vector<DeployApiService::DeployApiHandlerBase::ReclaimInfo> &,
440  const Ptr<VoidResponseWriter> &));
441 
443 
444 } // namespace detail
445 
446 // NOTE: You MUST NOT call this specialized function.
447 template <>
448 void DeployApiService::RegisterDeployApiHandler<
449  DeployApiService::DeployApiHandlerBase>(
450  boost::shared_ptr<DeployApiService::DeployApiHandlerBase> handler);
451 
452 
453 template <typename T>
454 void DeployApiService::RegisterDeployApiHandler(boost::shared_ptr<T> handler) {
455  CHECK_MEMBER_FUNCTION(GetUserSearchConditions);
456  CHECK_MEMBER_FUNCTION(SearchUsers);
457 
458  CHECK_MEMBER_FUNCTION(GetUser);
459  CHECK_MEMBER_FUNCTION(UpdateUser);
460  CHECK_MEMBER_FUNCTION(IsLoggedIn);
461  CHECK_MEMBER_FUNCTION(ForceLogout);
462 
463  CHECK_MEMBER_FUNCTION(GetUserBanned);
464  CHECK_MEMBER_FUNCTION(BanUser);
465  CHECK_MEMBER_FUNCTION(UnbanUser);
466 
467  CHECK_MEMBER_FUNCTION(GetCharacters);
468  CHECK_MEMBER_FUNCTION(GetCharacter);
469  CHECK_MEMBER_FUNCTION(UpdateCharacter);
470  CHECK_MEMBER_FUNCTION(GiveGift);
471  if (not detail::HasGiveGift<T>::value) {
472  CHECK_MEMBER_FUNCTION(GiveGiftToAll);
473  }
474  CHECK_MEMBER_FUNCTION(GetCharacterInventoryInfo);
475  CHECK_MEMBER_FUNCTION(GetInventory);
476  CHECK_MEMBER_FUNCTION(DeleteInventoryItem);
477  CHECK_MEMBER_FUNCTION(DeleteMultipleInventoryItems);
478 
479  _DoRegister(static_cast<boost::shared_ptr<DeployApiHandlerBase> >(handler));
480 }
481 
482 } // namespace fun
483 
484 #endif // INCLUDE_FUNAPI_MANAGEMENT_DEPLOY_API_SERVICE_H_
Definition: deploy_api_service.h:43
Definition: deploy_api_service.h:55
Definition: deploy_api_service.h:224
boost::function< void(const PageInfo &, const fun::Json &, Ptr< JsonResponseWriter > &)> CustomApiHandler
Custom query handlers for iFunDeploy {.
Definition: deploy_api_service.h:322
Definition: deploy_api_service.h:68
Definition: deploy_api_service.h:211
Definition: json.h:27
Definition: deploy_api_service.h:231
Definition: deploy_api_service.h:60
Defines extra data for custom query.
Definition: deploy_api_service.h:294
Definition: deploy_api_service.h:31
Definition: deploy_api_service.h:36