Skip to content

Commit

Permalink
Merge #115
Browse files Browse the repository at this point in the history
115: feat: Added `Lists Follows` endpoints (#27) 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: Kato Shinya <kato.shinya.dev@gmail.com>
  • Loading branch information
bors[bot] and myConsciousness committed May 12, 2022
2 parents bb40a05 + ccc5213 commit 3970e5f
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 11 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"PKCE",
"unfollow",
"unfollowed",
"unfollowing",
"unhide",
"Unhides",
"unliked",
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
- DELETE /2/lists/:id
- PUT /2/lists/:id
- POST /2/lists
- Added **Lists Follows** endpoints. ([#27](https://github.com/twitter-dart/twitter-api-v2/issues/27))
- DELETE /2/users/:id/followed_lists/:list_id
- GET /2/lists/:id/followers
- GET /2/users/:id/followed_lists
- POST /2/users/:id/followed_lists

## v1.7.0

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ void main() async {
1. [DELETE /2/lists/:id](https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id)
2. [PUT /2/lists/:id](https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id)
3. [POST /2/lists](https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists)
5. **Follows**
1. [DELETE /2/users/:id/followed_lists/:list_id](https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed-lists-list_id)
2. [GET /2/lists/:id/followers](https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers)
3. [GET /2/users/:id/followed_lists](https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists)
4. [POST /2/users/:id/followed_lists](https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed-lists)

5. **Compliance**
1. **Batch Compliance**
Expand Down
214 changes: 204 additions & 10 deletions lib/src/service/lists/lists_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import '../base_service.dart';
import '../tweets/tweet_data.dart';
import '../tweets/tweet_meta.dart';
import '../twitter_response.dart';
import '../users/user_data.dart';
import '../users/user_meta.dart';
import 'list_data.dart';
import 'list_meta.dart';

Expand Down Expand Up @@ -276,11 +278,8 @@ abstract class ListsService {
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id
Future<bool> updateListAsPublic({
required String listId,
String? name,
String? description,
});
Future<bool> updateListAsPublic(
{required String listId, String? name, String? description});

/// Enables the authenticated user to update the meta data of a specified List
/// that they own as a private scope.
Expand All @@ -305,11 +304,131 @@ abstract class ListsService {
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id
Future<bool> updateListAsPrivate({
required String listId,
String? name,
String? description,
});
Future<bool> updateListAsPrivate(
{required String listId, String? name, String? description});

/// Enables the authenticated user to follow a List.
///
/// ## Parameters
///
/// - [userId]: The user ID who you are following a List on behalf of.
/// It must match your own user ID or that of an authenticating
/// user, meaning that you must pass the Access Tokens associated
/// with the user ID when authenticating your request.
///
/// - [listId]: The ID of the List that you would like the user id to follow.
///
/// ## Endpoint Url
///
/// - https://api.twitter.com/2/users/:id/followed_lists
///
/// ## Rate Limits
///
/// - **User rate limit (OAuth 2.0 user Access Token)**:
/// 50 requests per 15-minute window per each authenticated user
///
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed-lists
Future<bool> createFollow({required String userId, required String listId});

/// Enables the authenticated user to unfollow a List.
///
/// ## Parameters
///
/// - [userId]: The user ID who you are unfollowing a List on behalf of.
/// It must match your own user ID or that of an authenticating
/// user, meaning that you must pass the Access Tokens associated
/// with the user ID when authenticating your request.
///
/// - [listId]: The ID of the List that you would like the user id to
/// unfollow.
///
/// ## Endpoint Url
///
/// - https://api.twitter.com/2/users/:id/followed_lists/:list_id
///
/// ## Rate Limits
///
/// - **User rate limit (OAuth 2.0 user Access Token)**:
/// 50 requests per 15-minute window per each authenticated user
///
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed-lists-list_id
Future<bool> destroyFollow({required String userId, required String listId});

/// Returns a list of users who are followers of the specified List.
///
/// ## Parameters
///
/// - [listId]: The ID of the List whose followers you would like to retrieve.
///
/// - [maxResults]: The maximum number of results to be returned per page.
/// This can be a number between 1 and 100. By default,
/// each page will return 100 results.
///
/// - [paginationToken]: Used to request the next page of results if all
/// results weren't returned with the latest request,
/// or to go back to the previous page of results.
/// To return the next page, pass the next_token returned
/// in your previous response. To go back one page, pass
/// the previous_token returned in your previous
/// response.
///
/// ## Endpoint Url
///
/// - https://api.twitter.com/2/lists/:id/followers
///
/// ## Rate Limits
///
/// - **App rate limit (OAuth 2.0 App Access Token)**:
/// 180 requests per 15-minute window shared among all users of your app
///
/// - **User rate limit (OAuth 2.0 user Access Token)**:
/// 180 requests per 15-minute window per each authenticated user
///
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-lists-id-followers
Future<TwitterResponse<List<UserData>, UserMeta>> lookupFollowers(
{required String listId, int? maxResults, String? paginationToken});

/// Returns all Lists a specified user follows.
///
/// ## Parameters
///
/// - [userId]: The user ID whose followed Lists you would like to retrieve.
///
/// - [maxResults]: The maximum number of results to be returned per page.
/// This can be a number between 1 and 100. By default,
/// each page will return 100 results.
///
/// - [paginationToken]: Used to request the next page of results if all
/// results weren't returned with the latest request,
/// or to go back to the previous page of results.
/// To return the next page, pass the next_token returned
/// in your previous response. To go back one page, pass
/// the previous_token returned in your previous
/// response.
///
/// ## Endpoint Url
///
/// - https://api.twitter.com/2/users/:id/followed_lists
///
/// ## Rate Limits
///
/// - **App rate limit (OAuth 2.0 App Access Token)**:
/// 15 requests per 15-minute window shared among all users of your app
///
/// - **User rate limit (OAuth 2.0 user Access Token)**:
/// 15 requests per 15-minute window per each authenticated user
///
/// ## Reference
///
/// - https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists
Future<TwitterResponse<List<ListData>, ListMeta>> lookupFollowedLists(
{required String userId, int? maxResults, String? paginationToken});
}

class _ListsService extends BaseService implements ListsService {
Expand Down Expand Up @@ -458,6 +577,81 @@ class _ListsService extends BaseService implements ListsService {
private: true,
);

@override
Future<bool> createFollow({
required String userId,
required String listId,
}) async {
final response = await super.post(
UserContext.oauth2OrOAuth1,
'/2/users/$userId/followed_lists',
body: {
'list_id': listId,
},
);

return response['data']['following'];
}

@override
Future<bool> destroyFollow({
required String userId,
required String listId,
}) async {
final response = await super.delete(
UserContext.oauth2OrOAuth1,
'/2/users/$userId/followed_lists/$listId',
);

return !response['data']['following'];
}

@override
Future<TwitterResponse<List<UserData>, UserMeta>> lookupFollowers({
required String listId,
int? maxResults,
String? paginationToken,
}) async {
final response = await super.get(
UserContext.oauth2OrOAuth1,
'/2/lists/$listId/followers',
queryParameters: {
'max_results': maxResults,
'pagination_token': paginationToken,
},
);

return TwitterResponse(
data: response['data']
.map<UserData>((user) => UserData.fromJson(user))
.toList(),
meta: UserMeta.fromJson(response['meta']),
);
}

@override
Future<TwitterResponse<List<ListData>, ListMeta>> lookupFollowedLists({
required String userId,
int? maxResults,
String? paginationToken,
}) async {
final response = await super.get(
UserContext.oauth2OrOAuth1,
'/2/users/$userId/followed_lists',
queryParameters: {
'max_results': maxResults,
'pagination_token': paginationToken,
},
);

return TwitterResponse(
data: response['data']
.map<ListData>((list) => ListData.fromJson(list))
.toList(),
meta: ListMeta.fromJson(response['meta']),
);
}

Future<TwitterResponse<ListData, void>> _createList({
required String name,
String? description,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies:
freezed_annotation: ^2.0.3

dev_dependencies:
lints: ^2.0.0
lints: ^1.0.1
test: ^1.21.1
build_runner: ^2.1.10
json_serializable: ^6.2.0
Expand Down
5 changes: 5 additions & 0 deletions test/src/service/lists/data/create_follow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"data": {
"following": true
}
}
5 changes: 5 additions & 0 deletions test/src/service/lists/data/destroy_follow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"data": {
"following": false
}
}
11 changes: 11 additions & 0 deletions test/src/service/lists/data/lookup_followed_lists.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"data": [
{
"id": "1630685563471",
"name": "Test List"
}
],
"meta": {
"result_count": 1
}
}
33 changes: 33 additions & 0 deletions test/src/service/lists/data/lookup_followers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"data": [
{
"id": "1324848235714736129",
"name": "Alan Lee",
"username": "alanbenlee"
},
{
"id": "1328359963937259520",
"name": "Wilson Chong",
"username": "xo_chong"
},
{
"id": "1451609880113070085",
"name": "Sumira Nazir",
"username": "SumiraNazir"
},
{
"id": "1420055293082415107",
"name": "Bo艡ek 艩indelka(he/him)",
"username": "JustBorek"
},
{
"id": "1409136449803325441",
"name": "閲戜簳鎲插徃",
"username": "w22ZccksRpafZAx"
}
],
"meta": {
"result_count": 5,
"next_token": "1714209892546977900"
}
}
Loading

0 comments on commit 3970e5f

Please sign in to comment.