├── .github └── workflows │ └── dart.yml ├── .gitignore ├── .media └── example.png ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example └── main.dart ├── lib ├── api │ ├── abstract_twitter_client.dart │ ├── common │ │ └── data │ │ │ ├── edit_control.dart │ │ │ ├── edit_control.g.dart │ │ │ ├── entities.dart │ │ │ ├── entities.g.dart │ │ │ ├── hashtag.dart │ │ │ ├── hashtag.g.dart │ │ │ ├── option.dart │ │ │ ├── option.g.dart │ │ │ ├── poll.dart │ │ │ ├── poll.g.dart │ │ │ ├── symbol.dart │ │ │ ├── symbol.g.dart │ │ │ ├── url.dart │ │ │ ├── url.g.dart │ │ │ ├── user_mention.dart │ │ │ └── user_mention.g.dart │ ├── direct_messages │ │ └── direct_messages_service.dart │ ├── geo │ │ └── data │ │ │ ├── bounding_box.dart │ │ │ ├── bounding_box.g.dart │ │ │ ├── coordinates.dart │ │ │ ├── coordinates.g.dart │ │ │ ├── place.dart │ │ │ └── place.g.dart │ ├── lists │ │ ├── data │ │ │ ├── paginated_twitter_lists.dart │ │ │ ├── paginated_twitter_lists.g.dart │ │ │ ├── twitter_list.dart │ │ │ └── twitter_list.g.dart │ │ └── lists_service.dart │ ├── media │ │ ├── data │ │ │ ├── additional_media_info.dart │ │ │ ├── additional_media_info.g.dart │ │ │ ├── media.dart │ │ │ ├── media.g.dart │ │ │ ├── media_upload.dart │ │ │ ├── media_upload.g.dart │ │ │ ├── size.dart │ │ │ ├── size.g.dart │ │ │ ├── sizes.dart │ │ │ ├── sizes.g.dart │ │ │ ├── video_info.dart │ │ │ └── video_info.g.dart │ │ └── media_service.dart │ ├── trends │ │ ├── data │ │ │ ├── trend.dart │ │ │ ├── trend.g.dart │ │ │ ├── trend_location.dart │ │ │ ├── trend_location.g.dart │ │ │ ├── trends.dart │ │ │ └── trends.g.dart │ │ └── trends_service.dart │ ├── tweets │ │ ├── data │ │ │ ├── current_user_retweet.dart │ │ │ ├── current_user_retweet.g.dart │ │ │ ├── quoted_status_permalink.dart │ │ │ ├── quoted_status_permalink.g.dart │ │ │ ├── tweet.dart │ │ │ ├── tweet.g.dart │ │ │ ├── tweet_search.dart │ │ │ └── tweet_search.g.dart │ │ ├── timeline_service.dart │ │ ├── tweet_search_service.dart │ │ └── tweet_service.dart │ ├── twitter_client.dart │ └── users │ │ ├── data │ │ ├── banner.dart │ │ ├── banner.g.dart │ │ ├── derived.dart │ │ ├── derived.g.dart │ │ ├── friendship.dart │ │ ├── friendship.g.dart │ │ ├── location.dart │ │ ├── location.g.dart │ │ ├── paginated_ids.dart │ │ ├── paginated_ids.g.dart │ │ ├── paginated_users.dart │ │ ├── paginated_users.g.dart │ │ ├── relationship.dart │ │ ├── relationship.g.dart │ │ ├── relationship_entity.dart │ │ ├── relationship_entity.g.dart │ │ ├── user.dart │ │ ├── user.g.dart │ │ ├── user_entities.dart │ │ └── user_entities.g.dart │ │ └── user_service.dart ├── src │ ├── annotations.dart │ ├── twitter_api_base.dart │ └── utils │ │ ├── _isolates_io.dart │ │ ├── _isolates_web.dart │ │ ├── date_utils.dart │ │ ├── isolates.dart │ │ ├── map_utils.dart │ │ └── transforms.dart └── twitter_api.dart ├── pubspec.yaml └── test └── api ├── lists ├── data │ └── list.json └── lists_service_test.dart ├── mocks ├── mock_twitter_client.dart └── mock_twitter_client.mocks.dart ├── trends ├── data │ ├── trends_available_response.json │ ├── trends_closest_response.json │ └── trends_place_response.json └── trends_service_test.dart └── tweets ├── data ├── favorites_create.json ├── favorites_destroy.json ├── favorites_list.json ├── statuses_destroy.json ├── statuses_retweet.json ├── statuses_retweets.json ├── statuses_retweets_of_me.json ├── statuses_show.json ├── statuses_unretweet.json └── statuses_update.json └── tweet_service_test.dart /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | container: 15 | image: google/dart:latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Install dependencies 20 | run: pub get 21 | - name: Run tests 22 | run: pub run test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs 8 | build/ 9 | 10 | # Directory created by dartdoc 11 | doc/api/ 12 | 13 | # intellij 14 | .idea/ 15 | -------------------------------------------------------------------------------- /.media/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertodoering/twitter_api/c944ab2fceed820ff84b7ebb04d52c5fb48eaca5/.media/example.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.6.0 2 | - Updated dependencies 3 | 4 | # 0.5.8 5 | - Implemented `UserService.profileBanner` request 6 | 7 | # 0.5.7+1 8 | 9 | - Fixed `InitialInfo` and `EditedInfo` models were missing the `explicitToJson: true` flag (Thanks @ryzizub!) 10 | 11 | # 0.5.7 12 | 13 | - Added `extEditControl` field in `Tweet`s and `includeExtEditControl` param in requests (Thanks @ryzizub!) 14 | 15 | # 0.5.6+1 16 | 17 | - Removed unnecessary annotation (Thanks @myConsciousness!) 18 | 19 | # 0.5.6 20 | 21 | - Fixed `MediaData.indices` was not parsed correctly (Thanks @matiasosuna!) 22 | 23 | # 0.5.5+1 24 | 25 | - Updated formatting 26 | 27 | # 0.5.5 28 | 29 | - Fixed unable to parse dates when the dart environment locale was set to some non-en_US locales (Thanks @jonjomckay!) 30 | 31 | # 0.5.4 32 | 33 | - Fixed `ListService.membersCreate` request (Thanks @nikolajjsj!) 34 | - Fixed `count` param was not included in `TweetService.retweets` (Thanks @dre8597!) 35 | 36 | # 0.5.3 37 | 38 | - Added `ListsService` with implementations for all `lists/*` endpoints 39 | 40 | # 0.5.2 41 | 42 | - Fixed twitter client non-2xx response not returned correctly 43 | 44 | # 0.5.1 45 | 46 | - Fixed twitter client forcing header argument to be non null 47 | 48 | # 0.5.0 49 | 50 | - Added support for web 51 | 52 | # 0.4.0 53 | 54 | - Migrated to null safety 55 | 56 | # 0.3.5 57 | 58 | - Added `TrendsService` with implementations for all `trends/*` endpoints 59 | - Raised `oauth` dependency to include a bugfix where authentication failed when 60 | some special characters where included in the request 61 | Thanks @nikolajjsj! 62 | 63 | # 0.3.4 64 | 65 | - Fixed user timeline `userId` & `screenName` request parameter 66 | 67 | # 0.3.3 68 | 69 | - Added user entities to the `User` object 70 | 71 | # 0.3.2 72 | 73 | - Implemented the `friendships/lookup` request 74 | - Added the `status` object for a `User` 75 | - Added more exports to the `twitter_api.dart` library 76 | 77 | # 0.3.1 78 | 79 | - Fixed `DateTime` in response models not set to UTC 80 | 81 | # 0.3.0 82 | 83 | - Fixed using the `Size` object instead of `Sizes` in the tweet media object 84 | - Added `VideoInfo` and `AdditionalMediaInfo` to the tweet media object 85 | 86 | # 0.2.1 87 | 88 | - Fixed parsing a `PaginatedUsers` response 89 | 90 | # 0.2.0 91 | 92 | - Added the user service 93 | 94 | # 0.1.1 95 | 96 | - Added support to change the twitter client default timeout 97 | - Added support to change the twitter client api keys & token after instantiation 98 | 99 | # 0.1.0+1 100 | 101 | - Updated readme 102 | 103 | # 0.1.0 104 | 105 | - Initial release 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Roberto Doering 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Dart wrapper for the Twitter API v1.1 2 | 3 | [![pub](https://img.shields.io/pub/v/dart_twitter_api)](https://pub.dev/packages/dart_twitter_api) 4 | ![test](https://github.com/robertodoering/twitter_api/workflows/test/badge.svg?branch=master) 5 | 6 | This dart package provides a well documented wrapper for the [Twitter v1.1 7 | API](https://developer.twitter.com/en/docs/twitter-api/v1). 8 | 9 | To access the v2 endpoints, check out [twitter-api-v2](https://github.com/twitter-dart/twitter-api-v2). 10 | 11 | ## Why use this package? 12 | 13 | To make the usage as convenient and comfortable as possible, this package provides 14 | interfaces for the various endpoints of the Twitter API. Documentation for each 15 | request is available as dart docs and each request's parameters can be changed as 16 | named parameters. 17 | 18 | The various data structures returned by Twitter are parsed into data models in 19 | an isolate. 20 | 21 | ## Example usage 22 | 23 | ![example](.media/example.png) 24 | 25 | ## Twitter API key 26 | 27 | Get your Twitter API key 28 | [here](https://developer.twitter.com/en/apply-for-access). 29 | 30 | ## Features 31 | 32 | ### Implemented endpoints 33 | 34 | The implemented API endpoints are available as methods in the corresponding 35 | service. The request parameters can be set through named parameters and the 36 | response will be parsed into a data object for maximum convenience. 37 | 38 | Find a list of implemented endpoints [here](https://github.com/robertodoering/twitter_api/wiki/Implemented-API-endpoints). 39 | 40 | --- 41 | 42 | If an API endpoint is not yet implemented, a request can be made to that 43 | endpoint by manually using the `TwitterClient` from the `TwitterApi` object. 44 | 45 | See [Making a custom request to the Twitter 46 | API](https://github.com/robertodoering/twitter_api/wiki/Making-a-custom-request-to-the-Twitter-API) 47 | for an example. 48 | 49 | ### Error handling 50 | 51 | Requests made by the client can throw the following errors: 52 | 53 | * `TimeoutException` when a request hasn't returned a response for some time 54 | (defaults to 10s, can be changed in the `TwitterClient`). 55 | 56 | * `Response` when the received response does not have a 2xx status code. Most 57 | responses include additional error information that can be parsed manually 58 | from the response's body. Check out the Twitter Developer documentation of 59 | the endpoint for possible error responses (Hyperlinked in the dart doc for 60 | each endpoint). 61 | 62 | * Other unexpected errors in unlikely events (for example when parsing the 63 | response). 64 | 65 | --- 66 | 67 | For an example of uploading media files to Twitter, see [Attaching media to a 68 | Tweet](https://github.com/robertodoering/twitter_api/wiki/Attaching-media-to-a-Tweet). 69 | 70 | ## Development 71 | 72 | ### Contribution 73 | 74 | I appreciate any contributions to this package. Any not yet implemented endpoints can 75 | be added similarly to the other implementations. Feel free to reach out to me to ask any questions. 76 | 77 | Please make sure `dartanalyzer` doesn't report any problems before opening a pull request. 78 | 79 | ### Miscellaneous 80 | 81 | - To generate json_serializable models 82 | - `dart run build_runner build --delete-conflicting-outputs` 83 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Defines a default set of lint rules enforced for 2 | # projects at Google. For details and rationale, 3 | # see https://github.com/dart-lang/pedantic#enabled-lints. 4 | include: package:pedantic/analysis_options.yaml 5 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_twitter_api/twitter_api.dart'; 2 | 3 | final twitterApi = TwitterApi( 4 | client: TwitterClient( 5 | consumerKey: 'your_consumer_key', 6 | consumerSecret: 'your_consumer_secret', 7 | token: 'your_token', 8 | secret: 'your_secret', 9 | ), 10 | ); 11 | 12 | Future main() async { 13 | try { 14 | // Get the last 200 tweets from your home timeline 15 | final homeTimeline = await twitterApi.timelineService.homeTimeline( 16 | count: 200, 17 | ); 18 | 19 | // Print the text of each Tweet 20 | homeTimeline.forEach((tweet) => print(tweet.fullText)); 21 | 22 | // Update your status (tweet) 23 | await twitterApi.tweetService.update( 24 | status: 'Hello world!', 25 | ); 26 | } catch (error) { 27 | // Requests made by the client can throw the following errors: 28 | // 29 | // * `TimeoutException` when a request hasn't returned a response for some 30 | // time (defaults to 10s, can be changed in the TwitterClient). 31 | // 32 | // * `Response` when the received response does not have a 2xx status code. 33 | // Most responses include additional error information that can be parsed 34 | // manually from the response's body. 35 | // 36 | // * Other unexpected errors in unlikely events (for example when parsing 37 | // the response). 38 | print('error while requesting home timeline: $error'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/api/abstract_twitter_client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:dart_twitter_api/twitter_api.dart'; 4 | import 'package:http/http.dart'; 5 | 6 | /// An abstraction to make http calls to the Twitter API used by the 7 | /// services. 8 | /// 9 | /// Implemented by [TwitterClient]. 10 | abstract class AbstractTwitterClient { 11 | const AbstractTwitterClient(); 12 | 13 | Future get( 14 | Uri uri, { 15 | Map? headers, 16 | Duration? timeout, 17 | }); 18 | 19 | Future post( 20 | Uri uri, { 21 | Map? headers, 22 | dynamic body, 23 | Encoding? encoding, 24 | Duration? timeout, 25 | }); 26 | 27 | Future multipartRequest( 28 | Uri uri, { 29 | List? files, 30 | Map? headers, 31 | Duration? timeout, 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /lib/api/common/data/edit_control.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'edit_control.g.dart'; 4 | 5 | @JsonSerializable( 6 | explicitToJson: true, 7 | fieldRename: FieldRename.snake, 8 | ) 9 | class EditControlData { 10 | EditControlData(); 11 | 12 | factory EditControlData.fromJson(Map json) => 13 | _$EditControlDataFromJson(json); 14 | 15 | InitialInfo? initial; 16 | 17 | EditedInfo? edit; 18 | 19 | Map toJson() => _$EditControlDataToJson(this); 20 | } 21 | 22 | @JsonSerializable( 23 | explicitToJson: true, 24 | fieldRename: FieldRename.snake, 25 | ) 26 | class InitialInfo { 27 | InitialInfo(); 28 | 29 | factory InitialInfo.fromJson(Map json) => 30 | _$InitialInfoFromJson(json); 31 | 32 | List? editTweetIds; 33 | 34 | String? editableUntilMsecs; 35 | 36 | String? editsRemaining; 37 | 38 | bool? isEditEligible; 39 | 40 | Map toJson() => _$InitialInfoToJson(this); 41 | } 42 | 43 | @JsonSerializable( 44 | explicitToJson: true, 45 | fieldRename: FieldRename.snake, 46 | ) 47 | class EditedInfo { 48 | EditedInfo(); 49 | 50 | factory EditedInfo.fromJson(Map json) => 51 | _$EditedInfoFromJson(json); 52 | 53 | InitialInfo? editControlInitial; 54 | 55 | String? initialTweetId; 56 | 57 | Map toJson() => _$EditedInfoToJson(this); 58 | } 59 | -------------------------------------------------------------------------------- /lib/api/common/data/edit_control.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'edit_control.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | EditControlData _$EditControlDataFromJson(Map json) { 10 | return EditControlData() 11 | ..initial = json['initial'] == null 12 | ? null 13 | : InitialInfo.fromJson(json['initial'] as Map) 14 | ..edit = json['edit'] == null 15 | ? null 16 | : EditedInfo.fromJson(json['edit'] as Map); 17 | } 18 | 19 | Map _$EditControlDataToJson(EditControlData instance) => 20 | { 21 | 'initial': instance.initial?.toJson(), 22 | 'edit': instance.edit?.toJson(), 23 | }; 24 | 25 | InitialInfo _$InitialInfoFromJson(Map json) { 26 | return InitialInfo() 27 | ..editTweetIds = (json['edit_tweet_ids'] as List?) 28 | ?.map((e) => e as String) 29 | .toList() 30 | ..editableUntilMsecs = json['editable_until_msecs'] as String? 31 | ..editsRemaining = json['edits_remaining'] as String? 32 | ..isEditEligible = json['is_edit_eligible'] as bool?; 33 | } 34 | 35 | Map _$InitialInfoToJson(InitialInfo instance) => 36 | { 37 | 'edit_tweet_ids': instance.editTweetIds, 38 | 'editable_until_msecs': instance.editableUntilMsecs, 39 | 'edits_remaining': instance.editsRemaining, 40 | 'is_edit_eligible': instance.isEditEligible, 41 | }; 42 | 43 | EditedInfo _$EditedInfoFromJson(Map json) { 44 | return EditedInfo() 45 | ..editControlInitial = json['edit_control_initial'] == null 46 | ? null 47 | : InitialInfo.fromJson( 48 | json['edit_control_initial'] as Map) 49 | ..initialTweetId = json['initial_tweet_id'] as String?; 50 | } 51 | 52 | Map _$EditedInfoToJson(EditedInfo instance) => 53 | { 54 | 'edit_control_initial': instance.editControlInitial?.toJson(), 55 | 'initial_tweet_id': instance.initialTweetId, 56 | }; 57 | -------------------------------------------------------------------------------- /lib/api/common/data/entities.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_twitter_api/api/common/data/hashtag.dart'; 2 | import 'package:dart_twitter_api/api/common/data/poll.dart'; 3 | import 'package:dart_twitter_api/api/common/data/symbol.dart'; 4 | import 'package:dart_twitter_api/api/common/data/url.dart'; 5 | import 'package:dart_twitter_api/api/common/data/user_mention.dart'; 6 | import 'package:dart_twitter_api/api/media/data/media.dart'; 7 | import 'package:json_annotation/json_annotation.dart'; 8 | 9 | part 'entities.g.dart'; 10 | 11 | @JsonSerializable( 12 | explicitToJson: true, 13 | fieldRename: FieldRename.snake, 14 | ) 15 | class Entities { 16 | Entities(); 17 | 18 | factory Entities.fromJson(Map json) => 19 | _$EntitiesFromJson(json); 20 | 21 | /// Represents hashtags which have been parsed out of the Tweet text. 22 | List? hashtags; 23 | 24 | /// Represents media elements uploaded with the Tweet. 25 | List? media; 26 | 27 | /// Represents URLs included in the text of a Tweet. 28 | List? urls; 29 | 30 | /// Represents URLs included in the text of a Tweet. 31 | List? userMentions; 32 | 33 | /// Represents symbols, i.e. $cashtags, included in the text of the Tweet. 34 | List? symbols; 35 | 36 | /// Represents Twitter Polls included in the Tweet. 37 | List? polls; 38 | 39 | Map toJson() => _$EntitiesToJson(this); 40 | } 41 | -------------------------------------------------------------------------------- /lib/api/common/data/entities.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'entities.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Entities _$EntitiesFromJson(Map json) { 10 | return Entities() 11 | ..hashtags = (json['hashtags'] as List?) 12 | ?.map((e) => Hashtag.fromJson(e as Map)) 13 | .toList() 14 | ..media = (json['media'] as List?) 15 | ?.map((e) => Media.fromJson(e as Map)) 16 | .toList() 17 | ..urls = (json['urls'] as List?) 18 | ?.map((e) => Url.fromJson(e as Map)) 19 | .toList() 20 | ..userMentions = (json['user_mentions'] as List?) 21 | ?.map((e) => UserMention.fromJson(e as Map)) 22 | .toList() 23 | ..symbols = (json['symbols'] as List?) 24 | ?.map((e) => Symbol.fromJson(e as Map)) 25 | .toList() 26 | ..polls = (json['polls'] as List?) 27 | ?.map((e) => Poll.fromJson(e as Map)) 28 | .toList(); 29 | } 30 | 31 | Map _$EntitiesToJson(Entities instance) => { 32 | 'hashtags': instance.hashtags?.map((e) => e.toJson()).toList(), 33 | 'media': instance.media?.map((e) => e.toJson()).toList(), 34 | 'urls': instance.urls?.map((e) => e.toJson()).toList(), 35 | 'user_mentions': instance.userMentions?.map((e) => e.toJson()).toList(), 36 | 'symbols': instance.symbols?.map((e) => e.toJson()).toList(), 37 | 'polls': instance.polls?.map((e) => e.toJson()).toList(), 38 | }; 39 | -------------------------------------------------------------------------------- /lib/api/common/data/hashtag.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'hashtag.g.dart'; 4 | 5 | @JsonSerializable( 6 | explicitToJson: true, 7 | fieldRename: FieldRename.snake, 8 | ) 9 | class Hashtag { 10 | Hashtag(); 11 | 12 | factory Hashtag.fromJson(Map json) => 13 | _$HashtagFromJson(json); 14 | 15 | /// An array of integers indicating the offsets within the Tweet text where 16 | /// the hashtag begins and ends. The first integer represents the location of 17 | /// the # character in the Tweet text string. The second integer represents 18 | /// the location of the first character after the hashtag. Therefore the 19 | /// difference between the two numbers will be the length of the hashtag name 20 | /// plus one (for the `#` character). 21 | List? indices; 22 | 23 | /// Name of the hashtag, minus the leading `#` character. 24 | String? text; 25 | 26 | Map toJson() => _$HashtagToJson(this); 27 | } 28 | -------------------------------------------------------------------------------- /lib/api/common/data/hashtag.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'hashtag.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Hashtag _$HashtagFromJson(Map json) { 10 | return Hashtag() 11 | ..indices = 12 | (json['indices'] as List?)?.map((e) => e as int).toList() 13 | ..text = json['text'] as String?; 14 | } 15 | 16 | Map _$HashtagToJson(Hashtag instance) => { 17 | 'indices': instance.indices, 18 | 'text': instance.text, 19 | }; 20 | -------------------------------------------------------------------------------- /lib/api/common/data/option.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'option.g.dart'; 4 | 5 | @JsonSerializable( 6 | explicitToJson: true, 7 | fieldRename: FieldRename.snake, 8 | ) 9 | class Option { 10 | Option(); 11 | 12 | factory Option.fromJson(Map json) => _$OptionFromJson(json); 13 | 14 | /// The poll position for this option. 15 | int? position; 16 | 17 | /// The text of this poll option. 18 | String? text; 19 | 20 | Map toJson() => _$OptionToJson(this); 21 | } 22 | -------------------------------------------------------------------------------- /lib/api/common/data/option.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'option.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Option _$OptionFromJson(Map json) { 10 | return Option() 11 | ..position = json['position'] as int? 12 | ..text = json['text'] as String?; 13 | } 14 | 15 | Map _$OptionToJson(Option instance) => { 16 | 'position': instance.position, 17 | 'text': instance.text, 18 | }; 19 | -------------------------------------------------------------------------------- /lib/api/common/data/poll.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_twitter_api/api/common/data/option.dart'; 2 | import 'package:dart_twitter_api/src/utils/date_utils.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | part 'poll.g.dart'; 6 | 7 | @JsonSerializable( 8 | explicitToJson: true, 9 | fieldRename: FieldRename.snake, 10 | ) 11 | class Poll { 12 | Poll(); 13 | 14 | factory Poll.fromJson(Map json) => _$PollFromJson(json); 15 | 16 | /// An array of options, each having a poll position, and the text for that 17 | /// position. 18 | List