diff --git a/example/lib/main.dart b/example/lib/main.dart index 7308586..cf52c75 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -11,5 +11,4 @@ void main() async { var searchBoardGamesResult = await bgg.searchBoardGames('catan'); print(searchBoardGamesResult.length); - } diff --git a/lib/bgg_api.dart b/lib/bgg_api.dart index 570a422..d0d0031 100644 --- a/lib/bgg_api.dart +++ b/lib/bgg_api.dart @@ -4,6 +4,8 @@ export 'src/api/query_parameters.dart'; export 'src/api/search_parameters.dart'; export 'src/api/thing_parameters.dart'; export 'src/api/thing_type.dart'; +export 'src/model/generic_ref.dart'; +export 'src/model/poll.dart'; export 'src/model/board_game.dart' show BoardGame; export 'src/model/board_game_ref.dart' show BoardGameRef; export 'src/model/item_ref.dart' show ItemRef; diff --git a/lib/src/api/search_parameters.dart b/lib/src/api/search_parameters.dart index 445b397..80de239 100644 --- a/lib/src/api/search_parameters.dart +++ b/lib/src/api/search_parameters.dart @@ -13,7 +13,11 @@ class SearchParameters extends QueryParameters { /// Limit results to items that match the SEARCH_QUERY exactly final bool exact; - SearchParameters({required this.query, this.type = const [], this.exact = false}); + SearchParameters({ + required this.query, + this.type = const [], + this.exact = false, + }); @override Map toMap() { diff --git a/lib/src/api/thing_type.dart b/lib/src/api/thing_type.dart index c452588..ae01277 100644 --- a/lib/src/api/thing_type.dart +++ b/lib/src/api/thing_type.dart @@ -1,4 +1,11 @@ -enum ThingType { boardgame, boardgameexpansion, boardgameaccessory, videogame, rpgitem, rpgissue } +enum ThingType { + boardgame, + boardgameexpansion, + boardgameaccessory, + videogame, + rpgitem, + rpgissue +} extension ThingTypeName on ThingType { String name() { diff --git a/lib/src/client.dart b/lib/src/client.dart index 5a85bd6..f3be658 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -30,53 +30,113 @@ class Bgg { Bgg({BggHttp? http}) : _http = http ?? BggHttp(); /// Retrieve information about a particular board game by [gameId]. - Future getBoardGame(int gameId) async { - return _getFirstElement(['thing'], const BoardGameDecoder(), - ThingParameters(id: [gameId], type: [ThingType.boardgame, ThingType.boardgameexpansion])); - } + Future getBoardGame(int gameId) async => _getFirstElement( + ['thing'], + const BoardGameDecoder(), + ThingParameters( + id: [gameId], + type: [ThingType.boardgame, ThingType.boardgameexpansion], + ), + ); /// Retrieve information about a particular thing. - Future getThing(ThingParameters parameters) async { - return _getFirstElement(['thing'], const BoardGameDecoder(), parameters); - } + Future getThing(ThingParameters parameters) async => + _getFirstElement(['thing'], const BoardGameDecoder(), parameters); /// Retrieve information about things. - Future> getThings(ThingParameters parameters) async { - return _getAllElements(['thing'], const BoardGameDecoder(), parameters); - } + Future> getThings( + ThingParameters parameters, { + int limit = 30, + int offset = 0, + }) async => + _getAllElements( + ['thing'], + const BoardGameDecoder(), + parameters, + limit: limit, + offset: offset, + ); /// Retrieve information about things. - Future getForum(ForumParameters parameters) async { - return _getRoot(['forum'], const ForumDecoder(), parameters); - } + Future getForum(ForumParameters parameters) async => + _getRoot(['forum'], const ForumDecoder(), parameters); /// Retrieve information about things. - Future> getForumList(ForumListParameters parameters) async { - return _getAllElements(['forumlist'], const ForumDecoder(), parameters); - } + Future> getForumList( + ForumListParameters parameters, { + int limit = 30, + int offset = 0, + }) async => + _getAllElements( + ['forumlist'], + const ForumDecoder(), + parameters, + limit: limit, + offset: offset, + ); /// Retrieves a list of board games (only) matching [query]. - Future> searchBoardGames(String query) async { - return _getAllElements( - ['search'], const BoardGameRefDecoder(), SearchParameters(query: query, type: [ThingType.boardgame])); - } + Future> searchBoardGames( + String query, { + bool exact = false, + int limit = 30, + int offset = 0, + }) async => + _getAllElements( + ['search'], + const BoardGameRefDecoder(), + SearchParameters( + query: query, + type: [ThingType.boardgame], + exact: exact, + ), + limit: limit, + offset: offset, + ); /// Retrieves a list of all things matching [query]. - Future> getFamilyItems(FamilyParameters parameters) async { - return _getAllElements(['family'], const FamilyDecoder(), parameters); - } + Future> getFamilyItems( + FamilyParameters parameters, { + int limit = 30, + int offset = 0, + }) async => + _getAllElements( + ['family'], + const FamilyDecoder(), + parameters, + limit: limit, + offset: offset, + ); /// Retrieves a list of all things matching [query]. - Future> searchThings(SearchParameters parameters) async { - return _getAllElements(['search'], const ItemRefDecoder(), parameters); - } + Future> searchThings( + SearchParameters parameters, { + int limit = 30, + int offset = 0, + }) async => + _getAllElements( + ['search'], + const ItemRefDecoder(), + parameters, + limit: limit, + offset: offset, + ); - Future _getRoot(List path, XmlDecoder decoder, QueryParameters parameters) async { - final xml = (await _http.get(path, queryParameters: parameters.toMap())).rootElement; + Future _getRoot( + List path, + XmlDecoder decoder, + QueryParameters parameters, + ) async { + final xml = (await _http.get(path, queryParameters: parameters.toMap())) + .rootElement; return decoder.decode(xml); } - Future _getFirstElement(List path, XmlDecoder decoder, QueryParameters parameters) async { + Future _getFirstElement( + List path, + XmlDecoder decoder, + QueryParameters parameters, + ) async { final xml = (await _http.get(path, queryParameters: parameters.toMap())) .rootElement .children @@ -84,11 +144,17 @@ class Bgg { return xml != null ? decoder.decode(xml) : null; } - Future> _getAllElements(List path, XmlDecoder decoder, QueryParameters parameters) async { + Future> _getAllElements( + List path, + XmlDecoder decoder, + QueryParameters parameters, { + int limit = 30, + int offset = 0, + }) async { final xml = (await _http.get(path, queryParameters: parameters.toMap())) .rootElement .children .where((e) => e.nodeType == XmlNodeType.ELEMENT); - return xml.map((e) => decoder.decode(e)).toList(); + return xml.map((e) => decoder.decode(e)).skip(offset).take(limit).toList(); } } diff --git a/lib/src/http.dart b/lib/src/http.dart index a857d94..9781ef7 100644 --- a/lib/src/http.dart +++ b/lib/src/http.dart @@ -7,7 +7,8 @@ import 'package:xml/xml.dart'; /// /// Most users should directly use the high-level `Bgg` class. class BggHttp { - static final Uri _defaultBaseUri = Uri(scheme: 'https', host: 'www.boardgamegeek.com', path: 'xmlapi2'); + static final Uri _defaultBaseUri = + Uri(scheme: 'https', host: 'www.boardgamegeek.com', path: 'xmlapi2'); final Client _http; final Uri _baseUri; @@ -16,9 +17,11 @@ class BggHttp { : _http = http ?? Client(), _baseUri = baseUri ?? _defaultBaseUri; - Future get(Iterable pathSegments, {Map? queryParameters}) async { + Future get(Iterable pathSegments, + {Map? queryParameters}) async { var response = await _http.get(_baseUri.replace( - pathSegments: _baseUri.pathSegments.toList()..addAll(pathSegments), queryParameters: queryParameters)); + pathSegments: _baseUri.pathSegments.toList()..addAll(pathSegments), + queryParameters: queryParameters)); return XmlDocument.parse(response.body); } diff --git a/lib/src/model/board_game.dart b/lib/src/model/board_game.dart index ad15061..43fe1ce 100644 --- a/lib/src/model/board_game.dart +++ b/lib/src/model/board_game.dart @@ -1,3 +1,6 @@ +import 'package:bgg_api/src/model/generic_ref.dart'; +import 'package:bgg_api/src/model/poll.dart'; + import 'video.dart'; class BoardGame { @@ -15,6 +18,20 @@ class BoardGame { final Uri? image; final List