-
-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
581: 578 consider to add geo service r=myConsciousness a=myConsciousness # 1. Description <!-- Provide a description of what this PR is doing. If you're modifying existing behavior, describe the existing behavior, how this PR is changing it, and what motivated the change. If this is a breaking change, specify explicitly which APIs have been changed. --> ## 1.1. Checklist <!-- Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`). This will ensure a smooth and quick review process. --> - [x] The title of my PR starts with a [Conventional Commit] prefix (`fix:`, `feat:`, `docs:` etc). - [x] I have read the [Contributor Guide] and followed the process outlined for submitting PRs. - [x] I have updated/added tests for ALL new/updated/fixed functionality. - [x] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. - [x] I have updated/added relevant examples in `examples`. ## 1.2. Breaking Change <!-- Does your PR require users to manually update their apps to accommodate your change? If the PR is a breaking change this should be indicated with suffix "!" (for example, `feat!:`, `fix!:`). See [Conventional Commit] for details. --> - [ ] Yes, this is a breaking change. - [x] No, this is _not_ a breaking change. ## 1.3. Related Issues <!-- Provide a list of issues related to this PR from the [issue database]. Indicate which of these issues are resolved or fixed by this PR, i.e. Fixes #xxxx* !--> <!-- Links --> [issue database]: https://github.com/twitter-dart/twitter-api-v2/issues [contributor guide]: https://github.com/twitter-dart/twitter-api-v2/blob/main/CONTRIBUTING.md [style guide]: https://github.com/twitter-dart/twitter-api-v2/blob/main/STYLEGUIDE.md [conventional commit]: https://conventionalcommits.org Co-authored-by: myConsciousness <[email protected]>
- Loading branch information
Showing
50 changed files
with
2,174 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
"DDTHH", | ||
"Decahose", | ||
"Elon", | ||
"geocode", | ||
"hashtagged", | ||
"hmac", | ||
"Kato", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2022 Kato Shinya. All rights reserved. | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided the conditions. | ||
|
||
// Package imports: | ||
import 'package:twitter_api_core/twitter_api_core.dart'; | ||
|
||
enum GeoGranularity implements Serializable { | ||
neighborhood, | ||
city, | ||
admin, | ||
country; | ||
|
||
@override | ||
String get value => name; | ||
|
||
const GeoGranularity(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
// Copyright 2022 Kato Shinya. All rights reserved. | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided the conditions. | ||
|
||
// Package imports: | ||
import 'dart:convert'; | ||
|
||
import 'package:twitter_api_core/twitter_api_core.dart' as core; | ||
|
||
// Project imports: | ||
import '../../../twitter_api_v2.dart'; | ||
import '../base_service.dart'; | ||
|
||
/// This class provides methods to easily access endpoints based on Geo. | ||
abstract class GeoService { | ||
/// Returns the new instance of [GeoService]. | ||
factory GeoService({required core.ClientContext context}) => | ||
_GeoService(context: context); | ||
|
||
/// Returns place data associated with a specific place ID. | ||
/// | ||
/// ## Parameters | ||
/// | ||
/// - [placeId]: An ID indicating a specific place. | ||
/// | ||
/// ## Endpoint Url | ||
/// | ||
/// - https://api.twitter.com/1.1/geo/id/:placeId.json | ||
/// | ||
/// ## Authentication Methods | ||
/// | ||
/// - OAuth 1.0a | ||
/// | ||
/// ## Rate Limits | ||
/// | ||
/// - **User rate limit (OAuth 1.0a)**: | ||
/// 75 requests per 15-minute window per each authenticated user | ||
Future<TwitterResponse<PlaceData, void>> lookupById({ | ||
required String placeId, | ||
}); | ||
|
||
/// Search for places that can be attached to a Tweet. | ||
/// | ||
/// Given a latitude and a longitude pair, an IP address, or a name, | ||
/// this request will return a list of all the valid places that | ||
/// can be used as the `placeId` when updating a status. | ||
/// | ||
/// Conceptually, a query can be made from the user's location, | ||
/// retrieve a list of places, have the user validate the location they | ||
/// are at, and then send the ID of this location. | ||
/// | ||
/// This is the recommended method to use find places that can be | ||
/// attached to tweet. | ||
/// | ||
/// Unlike `GET /1.1/geo/reverse_geocode` which provides raw data access, | ||
/// this endpoint can potentially re-order places with regards to the user | ||
/// who is authenticated. This approach is also preferred for interactive | ||
/// place matching with the user. | ||
/// | ||
/// Some parameters in this method are only required based on the | ||
/// existence of other parameters. For instance, [latitude] is required if | ||
/// [longitude] is provided, and vice-versa. Authentication is recommended, | ||
/// but not required with this method. | ||
/// | ||
/// ## Parameters | ||
/// | ||
/// - [query]: Free-form text to match against while executing | ||
/// a geo-based query, best suited for finding nearby locations | ||
/// by name. Remember to URL encode the query. | ||
/// | ||
/// - [granularity]: This is the minimal granularity of place types to | ||
/// return and must be one of: [GeoGranularity.neighborhood], | ||
/// [GeoGranularity.city], [GeoGranularity.admin] or | ||
/// [GeoGranularity.country]. If no granularity is provided | ||
/// for the request [GeoGranularity.neighborhood] is assumed. | ||
/// Setting this to [GeoGranularity.city], for example, | ||
/// will find places which have a type of | ||
/// [GeoGranularity.city], [GeoGranularity.admin] or | ||
/// [GeoGranularity.country]. | ||
/// | ||
/// - [maxResults]: A hint as to the number of results to return. | ||
/// This does not guarantee that the number of results | ||
/// returned will equal max_results, but instead informs how | ||
/// many "nearby" results to return. Ideally, only pass in | ||
/// the number of places you intend to display to the user | ||
/// here. | ||
/// | ||
/// - [latitude]: The `latitude` to search around. | ||
/// This parameter will be ignored unless it is | ||
/// inside the `range -90.0 to +90.0` (North is positive) | ||
/// inclusive. It will also be ignored if there isn't a | ||
/// corresponding long parameter. | ||
/// | ||
/// - [longitude]: The `longitude` to search around. | ||
/// The valid ranges for longitude are `-180.0 to +180.0` | ||
/// (East is positive) inclusive. This parameter will be | ||
/// ignored if outside that range, if it is not a number, | ||
/// if geo_enabled is turned off, or if there not a | ||
/// corresponding lat parameter. | ||
/// | ||
/// - [ipAddress]: An IP address. | ||
/// Used when attempting to fix geo location based off of | ||
/// the user's IP address. | ||
/// | ||
/// ## Endpoint Url | ||
/// | ||
/// - https://api.twitter.com/1.1/geo/search.json | ||
/// | ||
/// ## Authentication Methods | ||
/// | ||
/// - OAuth 1.0a | ||
/// | ||
/// ## Rate Limits | ||
/// | ||
/// - **User rate limit (OAuth 1.0a)**: | ||
/// 75 requests per 15-minute window per each authenticated user | ||
/// | ||
/// ## Reference | ||
/// | ||
/// - https://developer.twitter.com/en/docs/twitter-api/v1/geo/places-near-location/api-reference/get-geo-search | ||
Future<TwitterResponse<List<PlaceData>, void>> searchLocations({ | ||
String? query, | ||
GeoGranularity? granularity, | ||
int? maxResults, | ||
double? latitude, | ||
double? longitude, | ||
String? ipAddress, | ||
}); | ||
} | ||
|
||
class _GeoService extends BaseService implements GeoService { | ||
/// Returns the new instance of [_GeoService]. | ||
_GeoService({required super.context}); | ||
|
||
@override | ||
Future<TwitterResponse<PlaceData, void>> lookupById({ | ||
required String placeId, | ||
}) async { | ||
final response = await super.get( | ||
core.UserContext.oauth1Only, | ||
'/1.1/geo/id/$placeId.json', | ||
); | ||
|
||
final place = _checkResponse(response); | ||
|
||
return TwitterResponse( | ||
rateLimit: RateLimit.fromJson( | ||
rateLimitConverter.convert(response.headers), | ||
), | ||
data: PlaceData.fromJson(_toV2Format([place]).first), | ||
); | ||
} | ||
|
||
@override | ||
Future<TwitterResponse<List<PlaceData>, void>> searchLocations({ | ||
String? query, | ||
GeoGranularity? granularity, | ||
int? maxResults, | ||
double? latitude, | ||
double? longitude, | ||
String? ipAddress, | ||
}) async { | ||
final response = await super.get( | ||
core.UserContext.oauth1Only, | ||
'/1.1/geo/search.json', | ||
queryParameters: { | ||
'query': query, | ||
'granularity': granularity, | ||
'max_results': maxResults, | ||
'lat': latitude, | ||
'long': longitude, | ||
'ip': ipAddress, | ||
}, | ||
); | ||
|
||
final places = _checkResponse(response)['result']['places']; | ||
|
||
return TwitterResponse( | ||
rateLimit: RateLimit.fromJson( | ||
rateLimitConverter.convert(response.headers), | ||
), | ||
data: _toV2Format(places) | ||
.map<PlaceData>((json) => PlaceData.fromJson(json)) | ||
.toList(), | ||
); | ||
} | ||
|
||
dynamic _checkResponse(final core.Response response) { | ||
final json = jsonDecode(response.body); | ||
|
||
if (json is Map<String, dynamic>) { | ||
if (json.containsKey('errors')) { | ||
throw DataNotFoundException( | ||
'No data exists in response.', | ||
response, | ||
); | ||
} | ||
} | ||
|
||
return json; | ||
} | ||
|
||
List<dynamic> _toV2Format( | ||
final List<dynamic> places, | ||
) { | ||
final json = <dynamic>[]; | ||
for (final place in places) { | ||
final $place = Map<String, dynamic>.from(place); | ||
|
||
final containedWithinIdentifiers = <String>[]; | ||
for (final containedWithinPlace in place['contained_within']) { | ||
containedWithinIdentifiers.add(containedWithinPlace['id']); | ||
} | ||
|
||
$place['contained_within'] = containedWithinIdentifiers; | ||
|
||
json.add($place); | ||
} | ||
|
||
return json; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.