├── .github └── workflows │ └── dart.yml ├── .gitignore ├── .metadata ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ └── webview_page.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── lib ├── discord_api.dart └── src │ ├── discord_cdn_helper.dart │ ├── discord_client.dart │ ├── exceptions │ └── discord_api_exceptions.dart │ ├── extensions │ └── string_extensions.dart │ ├── models │ ├── discord_activity.dart │ ├── discord_activity_assets.dart │ ├── discord_activity_button.dart │ ├── discord_activity_flag.dart │ ├── discord_activity_party.dart │ ├── discord_activity_secrets.dart │ ├── discord_activity_timestamps.dart │ ├── discord_activity_type.dart │ ├── discord_allowed_mentions.dart │ ├── discord_api_scope.dart │ ├── discord_application.dart │ ├── discord_application_flag.dart │ ├── discord_attachment.dart │ ├── discord_audit_log.dart │ ├── discord_audit_log_change.dart │ ├── discord_audit_log_change_key.dart │ ├── discord_audit_log_entry.dart │ ├── discord_audit_log_event.dart │ ├── discord_authorization_information.dart │ ├── discord_ban.dart │ ├── discord_channel.dart │ ├── discord_channel_mention.dart │ ├── discord_channel_type.dart │ ├── discord_client_status.dart │ ├── discord_connection.dart │ ├── discord_connection_visibility_type.dart │ ├── discord_embed.dart │ ├── discord_embed_author.dart │ ├── discord_embed_field.dart │ ├── discord_embed_footer.dart │ ├── discord_embed_image.dart │ ├── discord_embed_provider.dart │ ├── discord_embed_thumbnail.dart │ ├── discord_embed_type.dart │ ├── discord_embed_video.dart │ ├── discord_emoji.dart │ ├── discord_errors.dart │ ├── discord_explicit_content_filter_level.dart │ ├── discord_followed_channel.dart │ ├── discord_guild.dart │ ├── discord_guild_feature.dart │ ├── discord_guild_member.dart │ ├── discord_guild_premium_tier.dart │ ├── discord_guild_preview.dart │ ├── discord_guild_scheduled_event.dart │ ├── discord_guild_scheduled_event_entity_metadata.dart │ ├── discord_guild_scheduled_event_entity_type.dart │ ├── discord_guild_scheduled_event_privacy_level.dart │ ├── discord_guild_scheduled_event_status.dart │ ├── discord_guild_scheduled_event_user.dart │ ├── discord_guild_template.dart │ ├── discord_guild_widget.dart │ ├── discord_guild_widget_settings.dart │ ├── discord_image_format.dart │ ├── discord_integration.dart │ ├── discord_integration_account.dart │ ├── discord_integration_application.dart │ ├── discord_integration_expiration_behavior.dart │ ├── discord_invite.dart │ ├── discord_invite_metadata.dart │ ├── discord_invite_stage_instance.dart │ ├── discord_invite_target_type.dart │ ├── discord_membership_state.dart │ ├── discord_mention_type.dart │ ├── discord_message.dart │ ├── discord_message_activity.dart │ ├── discord_message_activity_type.dart │ ├── discord_message_component.dart │ ├── discord_message_component_type.dart │ ├── discord_message_flag.dart │ ├── discord_message_interaction.dart │ ├── discord_message_interaction_type.dart │ ├── discord_message_notifications_level.dart │ ├── discord_message_reference.dart │ ├── discord_message_type.dart │ ├── discord_mfa_level.dart │ ├── discord_nsfw_level.dart │ ├── discord_optional_audit_entry_info.dart │ ├── discord_overwrite.dart │ ├── discord_overwrite_type.dart │ ├── discord_premium_type.dart │ ├── discord_presence_update.dart │ ├── discord_reaction.dart │ ├── discord_role.dart │ ├── discord_role_tags.dart │ ├── discord_snowflake.dart │ ├── discord_stage_instance.dart │ ├── discord_stage_privacy_level.dart │ ├── discord_status.dart │ ├── discord_sticker.dart │ ├── discord_sticker_format_type.dart │ ├── discord_sticker_item.dart │ ├── discord_sticker_pack.dart │ ├── discord_sticker_type.dart │ ├── discord_system_channel_flag.dart │ ├── discord_team.dart │ ├── discord_team_member.dart │ ├── discord_thread_member.dart │ ├── discord_thread_metadata.dart │ ├── discord_token.dart │ ├── discord_token_webhook.dart │ ├── discord_user.dart │ ├── discord_user_flag.dart │ ├── discord_verification_level.dart │ ├── discord_video_quality_mode.dart │ ├── discord_visibility_type.dart │ ├── discord_voice_region.dart │ ├── discord_voice_state.dart │ ├── discord_webhook.dart │ ├── discord_welcome_screen.dart │ └── discord_welcome_screen_channel.dart │ └── providers │ ├── discord_dio_provider.dart │ └── discord_http_client.dart ├── pubspec.yaml └── test └── discord_api_test.dart /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Dart 7 | 8 | on: 9 | push: 10 | branches: [ main, dev ] 11 | pull_request: 12 | branches: [ main, dev ] 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v2 19 | - uses: dart-lang/setup-dart@v1 20 | - name: Install dependencies 21 | run: dart pub get 22 | - name: Analyze project source 23 | run: dart analyze 24 | working-directory: ./lib 25 | - name: Run tests 26 | run: dart test --coverage="coverage" 27 | # - name: Generate Lcov 28 | # run: dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib 29 | # - name: Collect and report coverage 30 | # uses: coverallsapp/github-action@v1.1.2 31 | # with: 32 | # github-token: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | .fvm/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: db747aa1331bd95bc9b3874c842261ca2d302cd5 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /.pubignore: -------------------------------------------------------------------------------- 1 | # See https://dart.dev/tools/pub/publishing#what-files-are-published -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.1 2 | 3 | * Updated GitHub Links, as the repository was renamed from discord_api_flutter to discord_api. 4 | * Remove .pubignore file to include `/example` directory in the pub package 5 | * Gave the package a longer description in the `pubspec.yaml` file 6 | 7 | ## 0.1.0 8 | 9 | * **Initial Release** 10 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lint/analysis_options.yaml 2 | 3 | analyzer: 4 | exclude: 5 | - lib/**.g.dart 6 | - test/**.mocks.dart 7 | - lib/generated_plugin_registrant.dart 8 | strong-mode: 9 | implicit-casts: false 10 | errors: 11 | missing_required_param: error 12 | unrelated_type_equality_checks: error 13 | missing_return: warning 14 | close_sinks: warning 15 | cancel_subscriptions: warning 16 | parameter_assignments: warning 17 | prefer_final_in_for_each: warning 18 | prefer_mixin: warning 19 | unawaited_futures: warning 20 | unnecessary_await_in_return: warning 21 | unnecessary_null_aware_assignments: warning 22 | use_string_buffers: warning 23 | 24 | linter: 25 | rules: 26 | always_use_package_imports: false 27 | prefer_relative_imports: true 28 | use_string_buffers: true 29 | use_if_null_to_convert_nulls_to_bools: true 30 | parameter_assignments: true 31 | prefer_null_aware_method_calls: true 32 | use_is_even_rather_than_modulo: true 33 | prefer_final_in_for_each: true 34 | directives_ordering: true 35 | avoid_unused_constructor_parameters: true 36 | prefer_final_locals: true -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | /windows/* 34 | /web/* 35 | 36 | # Web related 37 | lib/generated_plugin_registrant.dart 38 | 39 | # Symbolication related 40 | app.*.symbols 41 | 42 | # Obfuscation related 43 | app.*.map.json 44 | 45 | # Android Studio will place build artifacts here 46 | /android/app/debug 47 | /android/app/profile 48 | /android/app/release 49 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: db747aa1331bd95bc9b3874c842261ca2d302cd5 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.example" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MeixDev/discord_api/3cb836325bccc9ec131945c93c7990daad6acec0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:discord_api/discord_api.dart'; 3 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; 4 | 5 | import 'webview_page.dart'; 6 | 7 | const clientId = 'CLIENT_ID'; 8 | const clientSecret = 'CLIENT_SECRET'; 9 | const redirectUri = 'http://localhost:8080/callback'; 10 | 11 | void main() { 12 | runApp(const MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | const MyApp({Key? key}) : super(key: key); 17 | 18 | // This widget is the root of your application. 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | title: 'Discord API Demo', 23 | theme: ThemeData( 24 | primarySwatch: Colors.blue, 25 | visualDensity: VisualDensity.adaptivePlatformDensity, 26 | ), 27 | home: const MyHomePage(title: 'Discord API Demo'), 28 | ); 29 | } 30 | } 31 | 32 | class MyHomePage extends StatefulWidget { 33 | const MyHomePage({Key? key, required this.title}) : super(key: key); 34 | 35 | final String title; 36 | 37 | @override 38 | State createState() => _MyHomePageState(); 39 | } 40 | 41 | class _MyHomePageState extends State { 42 | final _discordClient = DiscordClient( 43 | clientId: clientId, 44 | clientSecret: clientSecret, 45 | redirectUri: redirectUri, 46 | discordHttpClient: 47 | DiscordDioProvider(clientId: clientId, clientSecret: clientSecret), 48 | ); 49 | 50 | final _flutterWebviewPlugin = FlutterWebviewPlugin(); 51 | 52 | void _urlListener(String url) { 53 | if (url.startsWith(redirectUri)) { 54 | final code = Uri.parse(url).queryParameters['code']; 55 | if (code != null) { 56 | _discordClient.getAccessToken(code).then((token) { 57 | _flutterWebviewPlugin.close(); 58 | setState(() {}); 59 | }); 60 | } 61 | } 62 | } 63 | 64 | Future _openConnectionPage( 65 | {List scopes = const []}) { 66 | _flutterWebviewPlugin.onUrlChanged.listen(_urlListener); 67 | _flutterWebviewPlugin.onDestroy.listen((_) => Navigator.pop(context)); 68 | 69 | final url = _discordClient.authorizeUri(scopes); 70 | 71 | return Navigator.push( 72 | context, 73 | MaterialPageRoute( 74 | builder: (context) => WebViewPage(url.toString()), 75 | ), 76 | ).then((_) { 77 | if (_discordClient.discordHttpClient.discordToken != null) { 78 | debugPrint( 79 | "TOKEN: ${_discordClient.discordHttpClient.discordToken?.accessToken}"); 80 | return _discordClient.discordHttpClient.discordToken; 81 | } 82 | return null; 83 | }); 84 | } 85 | 86 | @override 87 | void initState() { 88 | super.initState(); 89 | WidgetsBinding.instance?.scheduleFrameCallback((timeStamp) { 90 | _openConnectionPage( 91 | scopes: [ 92 | DiscordApiScope.identify, 93 | DiscordApiScope.email, 94 | DiscordApiScope.guilds 95 | ], 96 | ).then((value) => setState(() {})); 97 | }); 98 | } 99 | 100 | void _displayDataAlert({ 101 | String? method, 102 | String? data, 103 | bool isImg = false, 104 | bool? isOnline, 105 | }) { 106 | showDialog( 107 | context: context, 108 | builder: (context) { 109 | return AlertDialog( 110 | title: Text(method ?? ''), 111 | content: Column( 112 | crossAxisAlignment: CrossAxisAlignment.start, 113 | mainAxisSize: MainAxisSize.min, 114 | children: [ 115 | if (isOnline != null) 116 | Text( 117 | isOnline ? 'Online' : 'Offline', 118 | style: TextStyle( 119 | color: isOnline ? Colors.green : Colors.red, 120 | fontWeight: FontWeight.bold, 121 | ), 122 | ), 123 | if (!isImg && data != null) Text(data), 124 | if (isImg && data != null) 125 | Image.network( 126 | data, 127 | loadingBuilder: (_, __, ___) => 128 | const CircularProgressIndicator(), 129 | ), 130 | ], 131 | ), 132 | ); 133 | }, 134 | ); 135 | } 136 | 137 | @override 138 | Widget build(BuildContext context) { 139 | return Scaffold( 140 | appBar: AppBar( 141 | title: Text(widget.title), 142 | ), 143 | body: ListView( 144 | children: [ 145 | // Text( 146 | // 'Welcome user: ${_discordClient.discordHttpClient.discordToken?.userId}', 147 | // ), 148 | Text( 149 | 'Your Discord access token is: ${_discordClient.discordHttpClient.discordToken?.accessToken}', 150 | ), 151 | ElevatedButton( 152 | onPressed: () async { 153 | final user = await _discordClient.getCurrentUser(); 154 | _displayDataAlert( 155 | method: 'getCurrentUser', 156 | data: user.toString(), 157 | ); 158 | }, 159 | child: const Text('Get Me'), 160 | ), 161 | ], 162 | ), 163 | ); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /example/lib/webview_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; 3 | 4 | class WebViewPage extends StatelessWidget { 5 | final String url; 6 | 7 | const WebViewPage(this.url, {Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return WebviewScaffold(appBar: AppBar(), url: url); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.4" 53 | dio: 54 | dependency: transitive 55 | description: 56 | name: dio 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "4.0.4" 60 | discord_api: 61 | dependency: "direct main" 62 | description: 63 | path: ".." 64 | relative: true 65 | source: path 66 | version: "0.1.0" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.0" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_lints: 80 | dependency: "direct dev" 81 | description: 82 | name: flutter_lints 83 | url: "https://pub.dartlang.org" 84 | source: hosted 85 | version: "1.0.4" 86 | flutter_test: 87 | dependency: "direct dev" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | flutter_webview_plugin: 92 | dependency: "direct dev" 93 | description: 94 | name: flutter_webview_plugin 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.4.0" 98 | http_parser: 99 | dependency: transitive 100 | description: 101 | name: http_parser 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "4.0.0" 105 | lints: 106 | dependency: transitive 107 | description: 108 | name: lints 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "1.0.1" 112 | matcher: 113 | dependency: transitive 114 | description: 115 | name: matcher 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "0.12.11" 119 | material_color_utilities: 120 | dependency: transitive 121 | description: 122 | name: material_color_utilities 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "0.1.3" 126 | meta: 127 | dependency: transitive 128 | description: 129 | name: meta 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "1.7.0" 133 | path: 134 | dependency: transitive 135 | description: 136 | name: path 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "1.8.1" 140 | sky_engine: 141 | dependency: transitive 142 | description: flutter 143 | source: sdk 144 | version: "0.0.99" 145 | source_span: 146 | dependency: transitive 147 | description: 148 | name: source_span 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.8.1" 152 | stack_trace: 153 | dependency: transitive 154 | description: 155 | name: stack_trace 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.10.0" 159 | stream_channel: 160 | dependency: transitive 161 | description: 162 | name: stream_channel 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.1.0" 166 | string_scanner: 167 | dependency: transitive 168 | description: 169 | name: string_scanner 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.1.0" 173 | term_glyph: 174 | dependency: transitive 175 | description: 176 | name: term_glyph 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.2.0" 180 | test_api: 181 | dependency: transitive 182 | description: 183 | name: test_api 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "0.4.9" 187 | typed_data: 188 | dependency: transitive 189 | description: 190 | name: typed_data 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.3.0" 194 | vector_math: 195 | dependency: transitive 196 | description: 197 | name: vector_math 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "2.1.1" 201 | sdks: 202 | dart: ">=2.16.1 <3.0.0" 203 | flutter: ">=2.0.0" 204 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.16.1 <3.0.0" 10 | 11 | dependencies: 12 | cupertino_icons: ^1.0.2 13 | flutter: 14 | sdk: flutter 15 | discord_api: 16 | path: ../ 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | flutter_webview_plugin: ^0.4.0 23 | flutter_lints: ^1.0.0 24 | 25 | flutter: 26 | 27 | uses-material-design: true -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/discord_api.dart: -------------------------------------------------------------------------------- 1 | library discord_api; 2 | 3 | export 'src/discord_cdn_helper.dart'; 4 | export 'src/discord_client.dart'; 5 | export 'src/exceptions/discord_api_exceptions.dart'; 6 | export 'src/extensions/string_extensions.dart'; 7 | export 'src/models/discord_activity.dart'; 8 | export 'src/models/discord_activity_assets.dart'; 9 | export 'src/models/discord_activity_button.dart'; 10 | export 'src/models/discord_activity_flag.dart'; 11 | export 'src/models/discord_activity_party.dart'; 12 | export 'src/models/discord_activity_secrets.dart'; 13 | export 'src/models/discord_activity_timestamps.dart'; 14 | export 'src/models/discord_activity_type.dart'; 15 | export 'src/models/discord_allowed_mentions.dart'; 16 | export 'src/models/discord_api_scope.dart'; 17 | export 'src/models/discord_application.dart'; 18 | export 'src/models/discord_application_flag.dart'; 19 | export 'src/models/discord_attachment.dart'; 20 | export 'src/models/discord_audit_log.dart'; 21 | export 'src/models/discord_audit_log_change.dart'; 22 | export 'src/models/discord_audit_log_change_key.dart'; 23 | export 'src/models/discord_audit_log_entry.dart'; 24 | export 'src/models/discord_authorization_information.dart'; 25 | export 'src/models/discord_ban.dart'; 26 | export 'src/models/discord_channel.dart'; 27 | export 'src/models/discord_channel_mention.dart'; 28 | export 'src/models/discord_channel_type.dart'; 29 | export 'src/models/discord_client_status.dart'; 30 | export 'src/models/discord_connection.dart'; 31 | export 'src/models/discord_connection_visibility_type.dart'; 32 | export 'src/models/discord_embed.dart'; 33 | export 'src/models/discord_embed_author.dart'; 34 | export 'src/models/discord_embed_field.dart'; 35 | export 'src/models/discord_embed_footer.dart'; 36 | export 'src/models/discord_embed_image.dart'; 37 | export 'src/models/discord_embed_provider.dart'; 38 | export 'src/models/discord_embed_thumbnail.dart'; 39 | export 'src/models/discord_embed_type.dart'; 40 | export 'src/models/discord_embed_video.dart'; 41 | export 'src/models/discord_emoji.dart'; 42 | export 'src/models/discord_errors.dart'; 43 | export 'src/models/discord_explicit_content_filter_level.dart'; 44 | export 'src/models/discord_followed_channel.dart'; 45 | export 'src/models/discord_guild.dart'; 46 | export 'src/models/discord_guild_feature.dart'; 47 | export 'src/models/discord_guild_member.dart'; 48 | export 'src/models/discord_guild_premium_tier.dart'; 49 | export 'src/models/discord_guild_preview.dart'; 50 | export 'src/models/discord_guild_scheduled_event.dart'; 51 | export 'src/models/discord_guild_scheduled_event_entity_metadata.dart'; 52 | export 'src/models/discord_guild_scheduled_event_entity_type.dart'; 53 | export 'src/models/discord_guild_scheduled_event_privacy_level.dart'; 54 | export 'src/models/discord_guild_scheduled_event_status.dart'; 55 | export 'src/models/discord_guild_scheduled_event_user.dart'; 56 | export 'src/models/discord_guild_template.dart'; 57 | export 'src/models/discord_guild_widget.dart'; 58 | export 'src/models/discord_guild_widget_settings.dart'; 59 | export 'src/models/discord_image_format.dart'; 60 | export 'src/models/discord_integration.dart'; 61 | export 'src/models/discord_integration_account.dart'; 62 | export 'src/models/discord_integration_application.dart'; 63 | export 'src/models/discord_integration_expiration_behavior.dart'; 64 | export 'src/models/discord_invite.dart'; 65 | export 'src/models/discord_invite_metadata.dart'; 66 | export 'src/models/discord_invite_stage_instance.dart'; 67 | export 'src/models/discord_invite_target_type.dart'; 68 | export 'src/models/discord_membership_state.dart'; 69 | export 'src/models/discord_mention_type.dart'; 70 | export 'src/models/discord_message.dart'; 71 | export 'src/models/discord_message_activity.dart'; 72 | export 'src/models/discord_message_activity_type.dart'; 73 | export 'src/models/discord_message_component.dart'; 74 | export 'src/models/discord_message_component_type.dart'; 75 | export 'src/models/discord_message_flag.dart'; 76 | export 'src/models/discord_message_interaction.dart'; 77 | export 'src/models/discord_message_interaction_type.dart'; 78 | export 'src/models/discord_message_notifications_level.dart'; 79 | export 'src/models/discord_message_reference.dart'; 80 | export 'src/models/discord_message_type.dart'; 81 | export 'src/models/discord_mfa_level.dart'; 82 | export 'src/models/discord_nsfw_level.dart'; 83 | export 'src/models/discord_optional_audit_entry_info.dart'; 84 | export 'src/models/discord_overwrite.dart'; 85 | export 'src/models/discord_overwrite_type.dart'; 86 | export 'src/models/discord_premium_type.dart'; 87 | export 'src/models/discord_presence_update.dart'; 88 | export 'src/models/discord_reaction.dart'; 89 | export 'src/models/discord_role.dart'; 90 | export 'src/models/discord_role_tags.dart'; 91 | export 'src/models/discord_snowflake.dart'; 92 | export 'src/models/discord_stage_instance.dart'; 93 | export 'src/models/discord_stage_privacy_level.dart'; 94 | export 'src/models/discord_status.dart'; 95 | export 'src/models/discord_sticker.dart'; 96 | export 'src/models/discord_sticker_format_type.dart'; 97 | export 'src/models/discord_sticker_item.dart'; 98 | export 'src/models/discord_sticker_pack.dart'; 99 | export 'src/models/discord_sticker_type.dart'; 100 | export 'src/models/discord_system_channel_flag.dart'; 101 | export 'src/models/discord_team.dart'; 102 | export 'src/models/discord_team_member.dart'; 103 | export 'src/models/discord_thread_member.dart'; 104 | export 'src/models/discord_thread_metadata.dart'; 105 | export 'src/models/discord_token.dart'; 106 | export 'src/models/discord_token_webhook.dart'; 107 | export 'src/models/discord_user.dart'; 108 | export 'src/models/discord_user_flag.dart'; 109 | export 'src/models/discord_verification_level.dart'; 110 | export 'src/models/discord_video_quality_mode.dart'; 111 | export 'src/models/discord_voice_region.dart'; 112 | export 'src/models/discord_voice_state.dart'; 113 | export 'src/models/discord_webhook.dart'; 114 | export 'src/models/discord_welcome_screen.dart'; 115 | export 'src/models/discord_welcome_screen_channel.dart'; 116 | export 'src/providers/discord_dio_provider.dart'; //! TEMPORARY 117 | export 'src/providers/discord_http_client.dart'; 118 | -------------------------------------------------------------------------------- /lib/src/exceptions/discord_api_exceptions.dart: -------------------------------------------------------------------------------- 1 | class DiscordApiException implements Exception { 2 | final String message; 3 | 4 | const DiscordApiException(this.message); 5 | 6 | @override 7 | String toString() => 'DiscordException: $message'; 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/extensions/string_extensions.dart: -------------------------------------------------------------------------------- 1 | extension StringExtension on String { 2 | String capitalize() { 3 | return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_assets.dart: -------------------------------------------------------------------------------- 1 | class DiscordActivityAssets { 2 | /// see [Activity Asset Image](https://discord.com/developers/docs/topics/gateway#activity-object-activity-asset-image) 3 | /// 4 | /// is not always returned, hence the nullable property 5 | final String? largeImage; 6 | 7 | /// text displayed when hovering over the large image of the activity 8 | /// 9 | /// is not always returned, hence the nullable property 10 | final String? largeText; 11 | 12 | /// see [Activity Asset Image](https://discord.com/developers/docs/topics/gateway#activity-object-activity-asset-image) 13 | /// 14 | /// is not always returned, hence the nullable property 15 | final String? smallImage; 16 | 17 | /// text displayed when hovering over the small image of the activity 18 | /// 19 | /// is not always returned, hence the nullable property 20 | final String? smallText; 21 | 22 | static const largeImageEntry = 'large_image'; 23 | static const largeTextEntry = 'large_text'; 24 | static const smallImageEntry = 'small_image'; 25 | static const smallTextEntry = 'small_text'; 26 | 27 | DiscordActivityAssets({ 28 | this.largeImage, 29 | this.largeText, 30 | this.smallImage, 31 | this.smallText, 32 | }); 33 | 34 | factory DiscordActivityAssets.fromJson(Map json) => 35 | DiscordActivityAssets( 36 | largeImage: json[largeImageEntry] as String?, 37 | largeText: json[largeTextEntry] as String?, 38 | smallImage: json[smallImageEntry] as String?, 39 | smallText: json[smallTextEntry] as String?, 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_button.dart: -------------------------------------------------------------------------------- 1 | class DiscordActivityButton { 2 | /// the text shown on the button (1-32 characters) 3 | final String label; 4 | 5 | /// the url opened when clicking the button (1-512 characters) 6 | final String url; 7 | 8 | static const labelEntry = 'label'; 9 | static const urlEntry = 'url'; 10 | 11 | DiscordActivityButton({ 12 | required this.label, 13 | required this.url, 14 | }); 15 | 16 | factory DiscordActivityButton.fromJson(Map json) => 17 | DiscordActivityButton( 18 | label: json[labelEntry] as String, 19 | url: json[urlEntry] as String, 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_flag.dart: -------------------------------------------------------------------------------- 1 | enum DiscordActivityFlag { 2 | /// 1 << 0 3 | instance, 4 | 5 | /// 1 << 1 6 | join, 7 | 8 | /// 1 << 2 9 | spectate, 10 | 11 | /// 1 << 3 12 | joinRequest, 13 | 14 | /// 1 << 4 15 | sync, 16 | 17 | /// 1 << 5 18 | play, 19 | 20 | /// 1 << 6 21 | partyPrivacyFriends, 22 | 23 | /// 1 << 7 24 | partyPrivacyVoiceChannel, 25 | 26 | /// 1 << 8 27 | embedded, 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_party.dart: -------------------------------------------------------------------------------- 1 | class DiscordActivityParty { 2 | /// the id of the party 3 | /// 4 | /// is not always returned, hence the nullable property 5 | final String? id; 6 | 7 | /// used to show the party's current and maximum size 8 | /// 9 | /// is an array of two integers (current_size, max_size) 10 | final List? size; 11 | 12 | static const idEntry = "id"; 13 | static const sizeEntry = "size"; 14 | 15 | DiscordActivityParty({ 16 | this.id, 17 | this.size, 18 | }); 19 | 20 | factory DiscordActivityParty.fromJson(Map json) => 21 | DiscordActivityParty( 22 | id: json[idEntry] as String?, 23 | size: List.from(json[sizeEntry] as List), 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_secrets.dart: -------------------------------------------------------------------------------- 1 | class DiscordActivitySecrets { 2 | /// the secret for joining a party 3 | /// 4 | /// is not always returned, hence the nullable property 5 | final String? join; 6 | 7 | /// the secret for spectating a game 8 | /// 9 | /// is not always returned, hence the nullable property 10 | final String? spectate; 11 | 12 | /// the secret for a specific instanced match 13 | /// 14 | /// is not always returned, hence the nullable property 15 | final String? match; 16 | 17 | static const joinEntry = 'join'; 18 | static const spectateEntry = 'spectate'; 19 | static const matchEntry = 'match'; 20 | 21 | DiscordActivitySecrets({ 22 | this.join, 23 | this.spectate, 24 | this.match, 25 | }); 26 | 27 | factory DiscordActivitySecrets.fromJson(Map json) => 28 | DiscordActivitySecrets( 29 | join: json[joinEntry] as String?, 30 | spectate: json[spectateEntry] as String?, 31 | match: json[matchEntry] as String?, 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_timestamps.dart: -------------------------------------------------------------------------------- 1 | class DiscordActivityTimestamps { 2 | /// unix time (in milliseconds) of when the activity started 3 | /// 4 | /// is not always returned, hence the nullable property 5 | final int? start; 6 | 7 | late final DateTime? _startAsDateTime; 8 | 9 | /// unix time (in milliseconds) of when the activity ends 10 | /// 11 | /// is not always returned, hence the nullable property 12 | final int? end; 13 | 14 | late final DateTime? _endAsDateTime; 15 | 16 | static const startEntry = 'start'; 17 | static const endEntry = 'end'; 18 | 19 | DiscordActivityTimestamps({ 20 | this.start, 21 | this.end, 22 | }); 23 | 24 | DateTime? get startAsDateTime { 25 | if (start == null) return null; 26 | return _startAsDateTime ??= DateTime.fromMillisecondsSinceEpoch(start!); 27 | } 28 | 29 | DateTime? get endAsDateTime { 30 | if (end == null) return null; 31 | return _endAsDateTime ??= DateTime.fromMillisecondsSinceEpoch(end!); 32 | } 33 | 34 | factory DiscordActivityTimestamps.fromJson(Map json) => 35 | DiscordActivityTimestamps( 36 | start: json['start'] as int?, 37 | end: json['end'] as int?, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_activity_type.dart: -------------------------------------------------------------------------------- 1 | /// Enum of Activity Types 2 | /// 3 | /// The streaming type currently only supports Twitch and YouTube. 4 | /// Only `https://twitch.tv/` and `https://www.youtube.com/` urls will work. 5 | enum DiscordActivityType { 6 | /// ID: 0 7 | /// Name: Game 8 | /// Format: Playing {name} 9 | /// Example: "Playing Rocket League" 10 | game, 11 | 12 | /// ID: 1 13 | /// Name: Streaming 14 | /// Format: Streaming {details} 15 | /// Example: "Streaming Rocket League" 16 | streaming, 17 | 18 | /// ID: 2 19 | /// Name: Listening 20 | /// Format: Listening to {name} 21 | /// Example: "Listening to Spotify" 22 | listening, 23 | 24 | /// ID: 3 25 | /// Name: Watching 26 | /// Format: Watching {name} 27 | /// Example: "Watching YouTube Together" 28 | watching, 29 | 30 | /// ID: 4 31 | /// Name: Custom 32 | /// Format: {emoji} {name} 33 | /// Example: ":smiley: I am cool" 34 | custom, 35 | 36 | /// ID: 5 37 | /// Name: Competing 38 | /// Format: Competing in {name} 39 | /// Example: "Competing in Arena World Champions" 40 | competing, 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/models/discord_allowed_mentions.dart: -------------------------------------------------------------------------------- 1 | import 'discord_mention_type.dart'; 2 | 3 | class DiscordAllowedMentions { 4 | /// an array of [allowed mention types](https://discord.com/developers/docs/resources/channel#allowed-mentions-object-allowed-mention-types) 5 | /// to parse from the content. 6 | final List parse; 7 | 8 | late final List? _parseAsEnum; 9 | 10 | /// array of role_ids to mention (Max size of 100) 11 | /// 12 | /// Should be converted to DiscordSnowflake if the need arise 13 | final List roles; 14 | 15 | /// array of user_ids to mention (Max size of 100) 16 | /// 17 | /// Should be converted to DiscordSnowflake if the need arise 18 | final List users; 19 | 20 | /// for replies, whether to mention the author of the message being 21 | /// replied to (default false) 22 | final bool repliedUser; 23 | 24 | static const parseEntry = 'parse'; 25 | static const rolesEntry = 'roles'; 26 | static const usersEntry = 'users'; 27 | static const repliedUserEntry = 'replied_user'; 28 | 29 | DiscordAllowedMentions({ 30 | required this.parse, 31 | required this.roles, 32 | required this.users, 33 | required this.repliedUser, 34 | }); 35 | 36 | DiscordMentionType _getFromString(String value) { 37 | switch (value) { 38 | case 'users': 39 | return DiscordMentionType.users; 40 | case 'roles': 41 | return DiscordMentionType.roles; 42 | case 'everyone': 43 | return DiscordMentionType.everyone; 44 | default: 45 | throw ArgumentError('Unknown mention type: $value'); 46 | } 47 | } 48 | 49 | List get parseAsEnum => 50 | _parseAsEnum ??= parse.map((e) => _getFromString(e)).toList(); 51 | 52 | factory DiscordAllowedMentions.fromJson(Map json) => 53 | DiscordAllowedMentions( 54 | parse: List.from(json[parseEntry] as List), 55 | roles: List.from(json[rolesEntry] as List), 56 | users: List.from(json[usersEntry] as List), 57 | repliedUser: json[repliedUserEntry] as bool, 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/models/discord_api_scope.dart: -------------------------------------------------------------------------------- 1 | enum DiscordApiScope { 2 | activitiesRead, 3 | activitiesWrite, 4 | applicationsBuildsRead, 5 | applicationsBuildsUpload, 6 | applicationsCommands, 7 | applicationsCommandsUpdate, 8 | applicationsEntitlements, 9 | applicationsStoreUpdate, 10 | bot, 11 | connections, 12 | email, 13 | gdmJoin, 14 | guilds, 15 | guildsJoin, 16 | guilsMembersRead, 17 | identify, 18 | messagesRead, 19 | rpc, 20 | rpcActivitiesWrite, 21 | rpcNotificationsRead, 22 | rpcVoiceRead, 23 | rpcVoiceWrite, 24 | webhookIncoming, 25 | } 26 | 27 | extension DiscordApiScopeModifier on DiscordApiScope { 28 | String get string { 29 | final RegExp regExp = RegExp('(?<=[a-z])[A-Z]'); 30 | return name 31 | .replaceAllMapped(regExp, (match) => '.${match.group(0)}') 32 | .toLowerCase(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/models/discord_application_flag.dart: -------------------------------------------------------------------------------- 1 | enum DiscordApplicationFlag { 2 | /// 1 << 12 3 | gatewayPresence, 4 | 5 | /// 1 << 13 6 | gatewayPresenceLimited, 7 | 8 | /// 1 << 14 9 | gatewayGuildMembers, 10 | 11 | /// 1 << 15 12 | gatewayGuildMembersLimited, 13 | 14 | /// 1 << 16 15 | verificationPendingGuildLimit, 16 | 17 | /// 1 << 17 18 | embedded, 19 | 20 | /// 1 << 18 21 | gatewayMessageContent, 22 | 23 | /// 1 << 19 24 | gatewayMessageContentLimited, 25 | } 26 | 27 | void _addFlagAsEnum( 28 | String r, 29 | int index, 30 | DiscordApplicationFlag flag, 31 | List f, 32 | ) { 33 | if (r.length >= index + 1 && r.substring(index, index + 1) == '1') { 34 | f.add(flag); 35 | } 36 | } 37 | 38 | List discordApplicationFlagsAsEnum(int? flags) { 39 | if (flags == null) { 40 | return []; 41 | } 42 | final flagsAsEnum = []; 43 | final radixString = 44 | String.fromCharCodes(flags.toRadixString(2).runes.toList().reversed); 45 | _addFlagAsEnum( 46 | radixString, 47 | 12, 48 | DiscordApplicationFlag.gatewayPresence, 49 | flagsAsEnum, 50 | ); 51 | _addFlagAsEnum( 52 | radixString, 53 | 13, 54 | DiscordApplicationFlag.gatewayPresenceLimited, 55 | flagsAsEnum, 56 | ); 57 | _addFlagAsEnum( 58 | radixString, 59 | 14, 60 | DiscordApplicationFlag.gatewayGuildMembers, 61 | flagsAsEnum, 62 | ); 63 | _addFlagAsEnum( 64 | radixString, 65 | 15, 66 | DiscordApplicationFlag.gatewayGuildMembersLimited, 67 | flagsAsEnum, 68 | ); 69 | _addFlagAsEnum( 70 | radixString, 71 | 16, 72 | DiscordApplicationFlag.verificationPendingGuildLimit, 73 | flagsAsEnum, 74 | ); 75 | _addFlagAsEnum( 76 | radixString, 77 | 17, 78 | DiscordApplicationFlag.embedded, 79 | flagsAsEnum, 80 | ); 81 | _addFlagAsEnum( 82 | radixString, 83 | 18, 84 | DiscordApplicationFlag.gatewayMessageContent, 85 | flagsAsEnum, 86 | ); 87 | _addFlagAsEnum( 88 | radixString, 89 | 19, 90 | DiscordApplicationFlag.gatewayMessageContentLimited, 91 | flagsAsEnum, 92 | ); 93 | return flagsAsEnum; 94 | } 95 | -------------------------------------------------------------------------------- /lib/src/models/discord_attachment.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordAttachment { 4 | /// attachment id 5 | final DiscordSnowflake id; 6 | 7 | /// name of file attached 8 | final String filename; 9 | 10 | /// description for the file 11 | final String? description; 12 | 13 | /// the attachment's [media type](https://en.wikipedia.org/wiki/Media_type) 14 | final String? contentType; 15 | 16 | /// size of file in bytes 17 | final int size; 18 | 19 | /// source url of file 20 | final String url; 21 | 22 | /// a proxied url of file 23 | final String proxyUrl; 24 | 25 | /// height of file (if image) 26 | final int? height; 27 | 28 | /// width of file (if image) 29 | final int? width; 30 | 31 | /// whether this attachment is ephemeral 32 | final bool? ephemeral; 33 | 34 | static const idEntry = 'id'; 35 | static const filenameEntry = 'filename'; 36 | static const descriptionEntry = 'description'; 37 | static const contentTypeEntry = 'content_type'; 38 | static const sizeEntry = 'size'; 39 | static const urlEntry = 'url'; 40 | static const proxyUrlEntry = 'proxy_url'; 41 | static const heightEntry = 'height'; 42 | static const widthEntry = 'width'; 43 | static const ephemeralEntry = 'ephemeral'; 44 | 45 | DiscordAttachment({ 46 | required this.id, 47 | required this.filename, 48 | this.description, 49 | this.contentType, 50 | required this.size, 51 | required this.url, 52 | required this.proxyUrl, 53 | this.height, 54 | this.width, 55 | this.ephemeral, 56 | }); 57 | 58 | factory DiscordAttachment.fromJson(Map json) => 59 | DiscordAttachment( 60 | id: DiscordSnowflake(json[idEntry] as String), 61 | filename: json[filenameEntry] as String, 62 | description: json[descriptionEntry] as String?, 63 | contentType: json[contentTypeEntry] as String?, 64 | size: json[sizeEntry] as int, 65 | url: json[urlEntry] as String, 66 | proxyUrl: json[proxyUrlEntry] as String, 67 | height: json[heightEntry] as int?, 68 | width: json[widthEntry] as int?, 69 | ephemeral: json[ephemeralEntry] as bool?, 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /lib/src/models/discord_audit_log.dart: -------------------------------------------------------------------------------- 1 | import 'discord_audit_log_entry.dart'; 2 | import 'discord_channel.dart'; 3 | import 'discord_guild_scheduled_event.dart'; 4 | import 'discord_integration.dart'; 5 | import 'discord_user.dart'; 6 | import 'discord_webhook.dart'; 7 | 8 | class DiscordAuditLog { 9 | /// list of audit log entries 10 | final List auditLogEntries; 11 | 12 | /// list of guild scheduled events found in the audit log 13 | final List guildScheduledEvents; 14 | 15 | /// list of partial integration objects 16 | final List integrations; 17 | 18 | /// list of threads found in the audit log 19 | /// 20 | /// * Threads referenced in THREAD_CREATE and THREAD_UPDATE 21 | /// events are included in the threads map, since archived 22 | /// threads might not be kept in memory by clients. 23 | final List threads; 24 | 25 | /// list of users found in the audit log 26 | final List users; 27 | 28 | /// list of webhooks found in the audit log 29 | final List webhooks; 30 | 31 | static const auditLogEntriesEntry = 'audit_log_entries'; 32 | static const guildScheduledEventsEntry = 'guild_scheduled_events'; 33 | static const integrationsEntry = 'integrations'; 34 | static const threadsEntry = 'threads'; 35 | static const usersEntry = 'users'; 36 | static const webhooksEntry = 'webhooks'; 37 | 38 | DiscordAuditLog({ 39 | required this.auditLogEntries, 40 | required this.guildScheduledEvents, 41 | required this.integrations, 42 | required this.threads, 43 | required this.users, 44 | required this.webhooks, 45 | }); 46 | 47 | factory DiscordAuditLog.fromJson(Map json) => 48 | DiscordAuditLog( 49 | auditLogEntries: List.from( 50 | (json[auditLogEntriesEntry] as List>) 51 | .map(DiscordAuditLogEntry.fromJson), 52 | ), 53 | guildScheduledEvents: List.from( 54 | (json[guildScheduledEventsEntry] as List>) 55 | .map(DiscordGuildScheduledEvent.fromJson), 56 | ), 57 | integrations: List.from( 58 | (json[integrationsEntry] as List>) 59 | .map(DiscordIntegration.fromJson), 60 | ), 61 | threads: List.from( 62 | (json[threadsEntry] as List>) 63 | .map(DiscordChannel.fromJson), 64 | ), 65 | users: List.from( 66 | (json[usersEntry] as List>) 67 | .map(DiscordUser.fromJson), 68 | ), 69 | webhooks: List.from( 70 | (json[webhooksEntry] as List>) 71 | .map(DiscordWebhook.fromJson), 72 | ), 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /lib/src/models/discord_audit_log_change.dart: -------------------------------------------------------------------------------- 1 | import 'discord_audit_log_change_key.dart'; 2 | import 'discord_overwrite.dart'; 3 | import 'discord_role.dart'; 4 | import 'discord_snowflake.dart'; 5 | 6 | class DiscordAuditLogChange { 7 | /// name of the audit log [change key](https://discord.com/developers/docs/resources/audit-log#audit-log-change-object-audit-log-change-key) 8 | final String key; 9 | 10 | late final DiscordAuditLogChangeKey? _keyAsEnum; 11 | late final Type? _changeType; 12 | 13 | late final _DiscordAuditLogChange change; 14 | 15 | static const keyEntry = 'key'; 16 | static const newValueEntry = 'new_value'; 17 | static const oldValueEntry = 'old_value'; 18 | 19 | DiscordAuditLogChange._(this.key, this.change); 20 | 21 | DiscordAuditLogChangeKey get keyAsEnum => 22 | _keyAsEnum ??= discordAuditLogChangeKeyFromValue(key); 23 | 24 | Type get changeType => _changeType ??= keyAsEnum.toType; 25 | 26 | factory DiscordAuditLogChange.fromJson(Map json) { 27 | final key = json[keyEntry] as String; 28 | final keyAsEnum = discordAuditLogChangeKeyFromValue(key); 29 | 30 | switch (keyAsEnum.toType) { 31 | case DiscordSnowflake: 32 | final changeSnowflake = _DiscordAuditLogChange( 33 | newValue: json[newValueEntry] != null 34 | ? DiscordSnowflake(json[newValueEntry] as String) 35 | : null, 36 | oldValue: json[oldValueEntry] != null 37 | ? DiscordSnowflake(json[oldValueEntry] as String) 38 | : null, 39 | ); 40 | return DiscordAuditLogChange._(key, changeSnowflake); 41 | case int: 42 | final changeInt = _DiscordAuditLogChange( 43 | newValue: json[newValueEntry] as int?, 44 | oldValue: json[oldValueEntry] as int?, 45 | ); 46 | return DiscordAuditLogChange._(key, changeInt); 47 | case String: 48 | final changeString = _DiscordAuditLogChange( 49 | newValue: json[newValueEntry] as String?, 50 | oldValue: json[oldValueEntry] as String?, 51 | ); 52 | return DiscordAuditLogChange._(key, changeString); 53 | case bool: 54 | final changeBool = _DiscordAuditLogChange( 55 | newValue: json[newValueEntry] as bool?, 56 | oldValue: json[oldValueEntry] as bool?, 57 | ); 58 | return DiscordAuditLogChange._(key, changeBool); 59 | case List: 60 | final changeRole = _DiscordAuditLogChange>( 61 | newValue: json[newValueEntry] != null 62 | ? List.from( 63 | (json[newValueEntry] as List).map( 64 | (e) => DiscordRole.fromJson(e as Map), 65 | ), 66 | ) 67 | : null, 68 | oldValue: json[oldValueEntry] != null 69 | ? List.from( 70 | (json[oldValueEntry] as List).map( 71 | (e) => DiscordRole.fromJson(e as Map), 72 | ), 73 | ) 74 | : null, 75 | ); 76 | return DiscordAuditLogChange._(key, changeRole); 77 | case List: 78 | final changePerm = _DiscordAuditLogChange>( 79 | newValue: json[newValueEntry] != null 80 | ? List.from( 81 | (json[newValueEntry] as List).map( 82 | (e) => DiscordOverwrite.fromJson(e as Map), 83 | ), 84 | ) 85 | : null, 86 | oldValue: json[oldValueEntry] != null 87 | ? List.from( 88 | (json[oldValueEntry] as List).map( 89 | (e) => DiscordOverwrite.fromJson(e as Map), 90 | ), 91 | ) 92 | : null, 93 | ); 94 | return DiscordAuditLogChange._(key, changePerm); 95 | case Object: 96 | final changeMixed = _DiscordAuditLogChange( 97 | newValue: json[newValueEntry]?.toString(), 98 | oldValue: json[oldValueEntry]?.toString(), 99 | ); 100 | return DiscordAuditLogChange._(key, changeMixed); 101 | } 102 | // default 103 | final changeInt = _DiscordAuditLogChange( 104 | newValue: json[newValueEntry] as int?, 105 | oldValue: json[oldValueEntry] as int?, 106 | ); 107 | return DiscordAuditLogChange._(key, changeInt); 108 | } 109 | } 110 | 111 | class _DiscordAuditLogChange { 112 | /// new value of the key 113 | final T? newValue; 114 | 115 | /// old value of the key 116 | final T? oldValue; 117 | 118 | _DiscordAuditLogChange({this.newValue, this.oldValue}); 119 | } 120 | -------------------------------------------------------------------------------- /lib/src/models/discord_audit_log_entry.dart: -------------------------------------------------------------------------------- 1 | import 'discord_audit_log_change.dart'; 2 | import 'discord_audit_log_event.dart'; 3 | import 'discord_optional_audit_entry_info.dart'; 4 | import 'discord_snowflake.dart'; 5 | 6 | class DiscordAuditLogEntry { 7 | /// id of the affected entity (webhook, user, role, etc.) 8 | /// 9 | /// is always returned, but can be null 10 | final String? targetId; 11 | 12 | /// changes made to the target_it 13 | /// 14 | /// is not always returned, hence the nullable property 15 | final List? changes; 16 | 17 | /// the user who made the changes 18 | /// 19 | /// is always returned, but can be null 20 | final DiscordSnowflake? userId; 21 | 22 | /// id of the entry 23 | final DiscordSnowflake id; 24 | 25 | /// type of action that occured 26 | final int actionType; 27 | 28 | late final DiscordAuditLogEvent? _actionTypeAsEnum; 29 | 30 | /// additional info for certain action types 31 | /// 32 | /// is not always returned, hence the nullable property 33 | final DiscordOptionalAuditEntryInfo? options; 34 | 35 | /// the reason for the change (0-512 characters) 36 | /// 37 | /// is not always returned, hence the nullable property 38 | final String? reason; 39 | 40 | static const targetIdEntry = "target_id"; 41 | static const changesEntry = "changes"; 42 | static const userIdEntry = "user_id"; 43 | static const idEntry = "id"; 44 | static const actionTypeEntry = "action_type"; 45 | static const optionsEntry = "options"; 46 | static const reasonEntry = "reason"; 47 | 48 | DiscordAuditLogEntry({ 49 | this.targetId, 50 | this.changes, 51 | this.userId, 52 | required this.id, 53 | required this.actionType, 54 | this.options, 55 | this.reason, 56 | }); 57 | 58 | DiscordAuditLogEvent get actionTypeAsEnum => 59 | _actionTypeAsEnum ??= discordAuditLogEventFromValue(actionType); 60 | 61 | factory DiscordAuditLogEntry.fromJson(Map json) => 62 | DiscordAuditLogEntry( 63 | targetId: json[targetIdEntry] as String?, 64 | changes: json[changesEntry] != null 65 | ? List.from( 66 | (json[changesEntry] as List).map( 67 | (x) => 68 | DiscordAuditLogChange.fromJson(x as Map), 69 | ), 70 | ) 71 | : null, 72 | userId: json[userIdEntry] != null 73 | ? DiscordSnowflake(json[userIdEntry] as String) 74 | : null, 75 | id: DiscordSnowflake(json[idEntry] as String), 76 | actionType: json[actionTypeEntry] as int, 77 | options: json[optionsEntry] != null 78 | ? DiscordOptionalAuditEntryInfo.fromJson( 79 | json[optionsEntry] as Map, 80 | ) 81 | : null, 82 | reason: json[reasonEntry] as String?, 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /lib/src/models/discord_authorization_information.dart: -------------------------------------------------------------------------------- 1 | import 'discord_api_scope.dart'; 2 | import 'discord_application.dart'; 3 | import 'discord_user.dart'; 4 | 5 | class DiscordAuthorizationInformation { 6 | final DiscordApplication application; 7 | final List scopes; 8 | late final List? _scopesAsEnum; 9 | final DateTime expiresAt; 10 | final DiscordUser? user; 11 | 12 | static const applicationEntry = 'application'; 13 | static const scopesEntry = 'scopes'; 14 | static const expiresEntry = 'expires'; 15 | static const userEntry = 'user'; 16 | 17 | DiscordAuthorizationInformation({ 18 | required this.application, 19 | required this.scopes, 20 | required this.expiresAt, 21 | this.user, 22 | }); 23 | 24 | List get scopesAsEnum => _scopesAsEnum ??= scopes.map((s) { 25 | final nameSegments = s.split('.'); 26 | for (int i = 1; i < nameSegments.length; i++) { 27 | nameSegments[i] = nameSegments[i].substring(0, 1).toUpperCase() + 28 | nameSegments[i].substring(1); 29 | } 30 | final dartName = nameSegments.join(); 31 | return DiscordApiScope.values 32 | .firstWhere((v) => v.toString() == 'DiscordApiScope.$dartName'); 33 | }).toList(); 34 | 35 | factory DiscordAuthorizationInformation.fromJson(Map json) => 36 | DiscordAuthorizationInformation( 37 | application: DiscordApplication.fromJson( 38 | json[applicationEntry] as Map, 39 | ), 40 | scopes: List.from(json[scopesEntry] as List), 41 | expiresAt: DateTime.parse(json[expiresEntry] as String), 42 | user: json[userEntry] != null 43 | ? DiscordUser.fromJson(json[userEntry] as Map) 44 | : null, 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/models/discord_ban.dart: -------------------------------------------------------------------------------- 1 | import 'discord_user.dart'; 2 | 3 | class DiscordBan { 4 | // the reason for the ban 5 | final String? reason; 6 | 7 | /// the banned user 8 | final DiscordUser user; 9 | 10 | static const reasonEntry = 'reason'; 11 | static const userEntry = 'user'; 12 | 13 | DiscordBan({ 14 | this.reason, 15 | required this.user, 16 | }); 17 | 18 | factory DiscordBan.fromJson(Map json) { 19 | return DiscordBan( 20 | reason: json[reasonEntry] as String?, 21 | user: DiscordUser.fromJson(json[userEntry] as Map), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/models/discord_channel_mention.dart: -------------------------------------------------------------------------------- 1 | import 'discord_channel_type.dart'; 2 | import 'discord_snowflake.dart'; 3 | 4 | class DiscordChannelMention { 5 | /// id of the channel 6 | final DiscordSnowflake id; 7 | 8 | /// id of the guild containing the channel 9 | final DiscordSnowflake guildId; 10 | 11 | /// the [type of channel](https://discord.com/developers/docs/resources/channel#channel-object-channel-types) 12 | final int type; 13 | 14 | late final DiscordChannelType? _typeAsEnum; 15 | 16 | /// the name of the channel 17 | final String name; 18 | 19 | static const idEntry = 'id'; 20 | static const guildIdEntry = 'guild_id'; 21 | static const typeEntry = 'type'; 22 | static const nameEntry = 'name'; 23 | 24 | DiscordChannelMention({ 25 | required this.id, 26 | required this.guildId, 27 | required this.type, 28 | required this.name, 29 | }); 30 | 31 | DiscordChannelType? get typeAsEnum => 32 | _typeAsEnum ??= DiscordChannelType.values[type]; 33 | 34 | factory DiscordChannelMention.fromJson(Map json) => 35 | DiscordChannelMention( 36 | id: DiscordSnowflake(json[idEntry] as String), 37 | guildId: DiscordSnowflake(json[guildIdEntry] as String), 38 | type: json[typeEntry] as int, 39 | name: json[nameEntry] as String, 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/models/discord_channel_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordChannelType { 2 | /// a text channel within a server 3 | guildText, 4 | 5 | /// a direct message between users 6 | dm, 7 | 8 | /// a voice channel within a server 9 | guildVoice, 10 | 11 | /// a direct message between multiple users 12 | groupDm, 13 | 14 | /// an [organizational category](https://support.discord.com/hc/en-us/articles/115001580171-Channel-Categories-101) 15 | /// that contains up to 50 channels 16 | guildCategory, 17 | 18 | /// a channel that [users can follow and crosspost into their own server](https://support.discord.com/hc/en-us/articles/360032008192) 19 | guildNews, 20 | 21 | /// a channel in which game developers can [sell their game on Discord]() 22 | guildStore, 23 | 24 | unused7, 25 | unused8, 26 | unused9, 27 | 28 | /// a temporary sub-channel within a GUILD_NEWS channel 29 | /// 30 | /// only available in API v9 31 | guildNewsThread, 32 | 33 | /// a temporary sub-channel within a GUILD_TEXT channel 34 | /// 35 | /// only available in API v9 36 | guildPublicThread, 37 | 38 | /// a temporary sub-channel within a GUILD_TEXT channel that is only viewable 39 | /// by those invited and those with the MANAGE_THREADS permission 40 | /// 41 | /// only available in API v9 42 | guildPrivateThread, 43 | 44 | /// a voice channel for [hosting events with an audience](https://support.discord.com/hc/en-us/articles/1500005513722) 45 | guildStageVoice, 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/models/discord_client_status.dart: -------------------------------------------------------------------------------- 1 | import 'discord_status.dart'; 2 | 3 | /// active sessions are indicated with an "online", "idle", or "dnd" 4 | /// string per platform. If a user is offline or invisible, the 5 | /// corresponding field is not present. 6 | class DiscordClientStatus { 7 | /// the user's status set for an active desktop 8 | /// (Windows, Linux, Mac) application session 9 | /// 10 | /// is not always returned, hence the nullable property 11 | final String? desktop; 12 | 13 | late final DiscordStatus? _desktopAsEnum; 14 | 15 | /// the user's status set for an active mobile 16 | /// (iOS, Android) application session 17 | /// 18 | /// is not always returned, hence the nullable property 19 | final String? mobile; 20 | 21 | late final DiscordStatus? _mobileAsEnum; 22 | 23 | /// the user's status set for an active web 24 | /// (browser, bot account) application session 25 | /// 26 | /// is not always returned, hence the nullable property 27 | final String? web; 28 | 29 | late final DiscordStatus? _webAsEnum; 30 | 31 | static const desktopEntry = "desktop"; 32 | static const mobileEntry = "mobile"; 33 | static const webEntry = "web"; 34 | 35 | DiscordClientStatus({ 36 | this.desktop, 37 | this.mobile, 38 | this.web, 39 | }); 40 | 41 | DiscordStatus? get desktopAsEnum { 42 | if (_desktopAsEnum == null) { 43 | if (desktop == null) { 44 | _desktopAsEnum ??= DiscordStatus.offline; 45 | } 46 | _desktopAsEnum ??= 47 | DiscordStatus.values.firstWhere((e) => e.name == desktop); 48 | } 49 | return _desktopAsEnum; 50 | } 51 | 52 | DiscordStatus? get mobileAsEnum { 53 | if (_mobileAsEnum == null) { 54 | if (mobile == null) { 55 | _mobileAsEnum ??= DiscordStatus.offline; 56 | } 57 | _mobileAsEnum ??= 58 | DiscordStatus.values.firstWhere((e) => e.name == mobile); 59 | } 60 | return _mobileAsEnum; 61 | } 62 | 63 | DiscordStatus? get webAsEnum { 64 | if (_webAsEnum == null) { 65 | if (web == null) { 66 | _webAsEnum ??= DiscordStatus.offline; 67 | } 68 | _webAsEnum ??= DiscordStatus.values.firstWhere((e) => e.name == web); 69 | } 70 | return _webAsEnum; 71 | } 72 | 73 | factory DiscordClientStatus.fromJson(Map json) => 74 | DiscordClientStatus( 75 | desktop: json[desktopEntry] as String?, 76 | mobile: json[mobileEntry] as String?, 77 | web: json[webEntry] as String?, 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /lib/src/models/discord_connection.dart: -------------------------------------------------------------------------------- 1 | import 'discord_integration.dart'; 2 | import 'discord_visibility_type.dart'; 3 | 4 | class DiscordConnection { 5 | /// id of the connection account 6 | final String id; 7 | 8 | /// the username of the connection account 9 | final String name; 10 | 11 | /// the service of the connection (twitch, youtube) 12 | final String type; 13 | 14 | /// whether the connection is revoked 15 | final bool? revoked; 16 | 17 | /// an array of partial [server integrations](https://discord.com/developers/docs/resources/guild#integration-object) 18 | final List? integrations; 19 | 20 | /// whether the connection is verified 21 | final bool verified; 22 | 23 | /// whether friend sync is enabled for this connection 24 | final bool friendSync; 25 | 26 | /// whether activities related to this connection will be shown in presence updates 27 | final bool showActivity; 28 | 29 | /// [visibility](https://discord.com/developers/docs/resources/user#connection-object-visibility-types) 30 | /// of this connection 31 | final int visibility; 32 | 33 | late final DiscordVisibilityType? _visibilityAsEnum; 34 | 35 | static const idEntry = 'id'; 36 | static const nameEntry = 'name'; 37 | static const typeEntry = 'type'; 38 | static const revokedEntry = 'revoked'; 39 | static const integrationsEntry = 'integrations'; 40 | static const verifiedEntry = 'verified'; 41 | static const friendSyncEntry = 'friend_sync'; 42 | static const showActivityEntry = 'show_activity'; 43 | static const visibilityEntry = 'visibility'; 44 | 45 | DiscordConnection({ 46 | required this.id, 47 | required this.name, 48 | required this.type, 49 | this.revoked, 50 | this.integrations, 51 | required this.verified, 52 | required this.friendSync, 53 | required this.showActivity, 54 | required this.visibility, 55 | }); 56 | 57 | DiscordVisibilityType get visibilityAsEnum => 58 | _visibilityAsEnum ??= DiscordVisibilityType.values[visibility]; 59 | 60 | factory DiscordConnection.fromJson(Map json) => 61 | DiscordConnection( 62 | id: json[idEntry] as String, 63 | name: json[nameEntry] as String, 64 | type: json[typeEntry] as String, 65 | revoked: json[revokedEntry] as bool?, 66 | integrations: json[integrationsEntry] != null 67 | ? List.from( 68 | (json[integrationsEntry] as List>) 69 | .map(DiscordIntegration.fromJson), 70 | ) 71 | : null, 72 | verified: json[verifiedEntry] as bool, 73 | friendSync: json[friendSyncEntry] as bool, 74 | showActivity: json[showActivityEntry] as bool, 75 | visibility: json[visibilityEntry] as int, 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /lib/src/models/discord_connection_visibility_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordConnectionVisibilityType { 2 | /// invisible to everyone except the user themselves 3 | none, 4 | 5 | /// visible to everyone 6 | everyone, 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed.dart: -------------------------------------------------------------------------------- 1 | import 'discord_embed_author.dart'; 2 | import 'discord_embed_field.dart'; 3 | import 'discord_embed_footer.dart'; 4 | import 'discord_embed_image.dart'; 5 | import 'discord_embed_provider.dart'; 6 | import 'discord_embed_thumbnail.dart'; 7 | import 'discord_embed_video.dart'; 8 | 9 | class DiscordEmbed { 10 | /// title of embed 11 | final String? title; 12 | 13 | /// [type of embed](https://discord.com/developers/docs/resources/channel#embed-object-embed-types) 14 | /// (always "rich" for webhook embeds) 15 | final String? type; 16 | 17 | /// description of embed 18 | final String? description; 19 | 20 | /// url of embed 21 | final String? url; 22 | 23 | /// timestamp of embed content 24 | final String? timestamp; 25 | 26 | late final DateTime? _timestampAsDateTime; 27 | 28 | /// color code of the embed 29 | final int? color; 30 | 31 | /// footer information 32 | final DiscordEmbedFooter? footer; 33 | 34 | /// image information 35 | final DiscordEmbedImage? image; 36 | 37 | /// thumbnail information 38 | final DiscordEmbedThumbnail? thumbnail; 39 | 40 | /// video information 41 | final DiscordEmbedVideo? video; 42 | 43 | /// provider information 44 | final DiscordEmbedProvider? provider; 45 | 46 | /// author information 47 | final DiscordEmbedAuthor? author; 48 | 49 | /// fields information 50 | final List? fields; 51 | 52 | static const titleEntry = 'title'; 53 | static const typeEntry = 'type'; 54 | static const descriptionEntry = 'description'; 55 | static const urlEntry = 'url'; 56 | static const timestampEntry = 'timestamp'; 57 | static const colorEntry = 'color'; 58 | static const footerEntry = 'footer'; 59 | static const imageEntry = 'image'; 60 | static const thumbnailEntry = 'thumbnail'; 61 | static const videoEntry = 'video'; 62 | static const providerEntry = 'provider'; 63 | static const authorEntry = 'author'; 64 | static const fieldsEntry = 'fields'; 65 | 66 | DiscordEmbed({ 67 | this.title, 68 | this.type, 69 | this.description, 70 | this.url, 71 | this.timestamp, 72 | this.color, 73 | this.footer, 74 | this.image, 75 | this.thumbnail, 76 | this.video, 77 | this.provider, 78 | this.author, 79 | this.fields, 80 | }); 81 | 82 | DateTime? get timestampAsDateTime { 83 | if (_timestampAsDateTime == null) { 84 | if (timestamp == null) { 85 | return null; 86 | } 87 | _timestampAsDateTime = DateTime.parse(timestamp!); 88 | } 89 | return _timestampAsDateTime; 90 | } 91 | 92 | factory DiscordEmbed.fromJson(Map json) => DiscordEmbed( 93 | title: json[titleEntry] as String?, 94 | type: json[typeEntry] as String?, 95 | description: json[descriptionEntry] as String?, 96 | url: json[urlEntry] as String?, 97 | timestamp: json[timestampEntry] as String?, 98 | color: json[colorEntry] as int?, 99 | footer: json[footerEntry] != null 100 | ? DiscordEmbedFooter.fromJson( 101 | json[footerEntry] as Map, 102 | ) 103 | : null, 104 | image: json[imageEntry] != null 105 | ? DiscordEmbedImage.fromJson( 106 | json[imageEntry] as Map, 107 | ) 108 | : null, 109 | thumbnail: json[thumbnailEntry] != null 110 | ? DiscordEmbedThumbnail.fromJson( 111 | json[thumbnailEntry] as Map, 112 | ) 113 | : null, 114 | video: json[videoEntry] != null 115 | ? DiscordEmbedVideo.fromJson( 116 | json[videoEntry] as Map, 117 | ) 118 | : null, 119 | provider: json[providerEntry] != null 120 | ? DiscordEmbedProvider.fromJson( 121 | json[providerEntry] as Map, 122 | ) 123 | : null, 124 | author: json[authorEntry] != null 125 | ? DiscordEmbedAuthor.fromJson( 126 | json[authorEntry] as Map, 127 | ) 128 | : null, 129 | fields: json[fieldsEntry] != null 130 | ? List.from( 131 | (json[fieldsEntry]! as List>) 132 | .map(DiscordEmbedField.fromJson), 133 | ) 134 | : null, 135 | ); 136 | } 137 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_author.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedAuthor { 2 | /// name of author 3 | final String name; 4 | 5 | /// url of author 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final String? url; 9 | 10 | /// url of author icon (only supports http(s) and attachments) 11 | /// 12 | /// is not always returned, hence the nullable property 13 | final String? iconUrl; 14 | 15 | /// a proxied url of author icon 16 | /// 17 | /// is not always returned, hence the nullable property 18 | final String? proxyIconUrl; 19 | 20 | static const nameEntry = 'name'; 21 | static const urlEntry = 'url'; 22 | static const iconUrlEntry = 'icon_url'; 23 | static const proxyIconUrlEntry = 'proxy_icon_url'; 24 | 25 | DiscordEmbedAuthor({ 26 | required this.name, 27 | this.url, 28 | this.iconUrl, 29 | this.proxyIconUrl, 30 | }); 31 | 32 | factory DiscordEmbedAuthor.fromJson(Map json) => 33 | DiscordEmbedAuthor( 34 | name: json[nameEntry] as String, 35 | url: json[urlEntry] as String?, 36 | iconUrl: json[iconUrlEntry] as String?, 37 | proxyIconUrl: json[proxyIconUrlEntry] as String?, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_field.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedField { 2 | /// name of the field 3 | final String name; 4 | 5 | /// value of the field 6 | final String value; 7 | 8 | /// whether or not this field should display inline 9 | /// 10 | /// is not always returned, hence the nullable property 11 | final bool? inline; 12 | 13 | static const nameEntry = 'name'; 14 | static const valueEntry = 'value'; 15 | static const inlineEntry = 'inline'; 16 | 17 | DiscordEmbedField({ 18 | required this.name, 19 | required this.value, 20 | this.inline, 21 | }); 22 | 23 | factory DiscordEmbedField.fromJson(Map json) => 24 | DiscordEmbedField( 25 | name: json[nameEntry] as String, 26 | value: json[valueEntry] as String, 27 | inline: json[inlineEntry] as bool?, 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_footer.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedFooter { 2 | /// footer text 3 | final String text; 4 | 5 | /// url of footer icon (only supports http(s) and attachments) 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final String? iconUrl; 9 | 10 | /// a proxied url of footer icon 11 | /// 12 | /// is not always returned, hence the nullable property 13 | final String? proxyIconUrl; 14 | 15 | static const textEntry = 'text'; 16 | static const iconUrlEntry = 'icon_url'; 17 | static const proxyIconUrlEntry = 'proxy_icon_url'; 18 | 19 | DiscordEmbedFooter({ 20 | required this.text, 21 | this.iconUrl, 22 | this.proxyIconUrl, 23 | }); 24 | 25 | factory DiscordEmbedFooter.fromJson(Map json) => 26 | DiscordEmbedFooter( 27 | text: json[textEntry] as String, 28 | iconUrl: json[iconUrlEntry] as String?, 29 | proxyIconUrl: json[proxyIconUrlEntry] as String?, 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_image.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedImage { 2 | /// source url of image (only supports http(s) and attachments) 3 | final String url; 4 | 5 | /// a proxied url of the image 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final String? proxyUrl; 9 | 10 | /// height of the image 11 | /// 12 | /// is not always returned, hence the nullable property 13 | final int? height; 14 | 15 | /// width of the image 16 | /// 17 | /// is not always returned, hence the nullable property 18 | final int? width; 19 | 20 | static const urlEntry = 'url'; 21 | static const proxyUrlEntry = 'proxy_url'; 22 | static const heightEntry = 'height'; 23 | static const widthEntry = 'width'; 24 | 25 | DiscordEmbedImage({ 26 | required this.url, 27 | this.proxyUrl, 28 | this.height, 29 | this.width, 30 | }); 31 | 32 | factory DiscordEmbedImage.fromJson(Map json) => 33 | DiscordEmbedImage( 34 | url: json[urlEntry] as String, 35 | proxyUrl: json[proxyUrlEntry] as String?, 36 | height: json[heightEntry] as int?, 37 | width: json[widthEntry] as int?, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_provider.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedProvider { 2 | /// name of provider 3 | /// 4 | /// is not always returned, hence the nullable property 5 | final String? name; 6 | 7 | /// url of provider 8 | /// 9 | /// is not always returned, hence the nullable property 10 | final String? url; 11 | 12 | static const nameEntry = 'name'; 13 | static const urlEntry = 'url'; 14 | 15 | DiscordEmbedProvider({ 16 | this.name, 17 | this.url, 18 | }); 19 | 20 | factory DiscordEmbedProvider.fromJson(Map json) => 21 | DiscordEmbedProvider( 22 | name: json[nameEntry] as String?, 23 | url: json[urlEntry] as String?, 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_thumbnail.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedThumbnail { 2 | /// source url of thumbnail (only supports http(s) and attachments) 3 | final String url; 4 | 5 | /// a proxied url of the thumbnail 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final String? proxyUrl; 9 | 10 | /// height of the thumbnail 11 | /// 12 | /// is not always returned, hence the nullable property 13 | final int? height; 14 | 15 | /// width of the thumbnail 16 | /// 17 | /// is not always returned, hence the nullable property 18 | final int? width; 19 | 20 | static const urlEntry = 'url'; 21 | static const proxyUrlEntry = 'proxy_url'; 22 | static const heightEntry = 'height'; 23 | static const widthEntry = 'width'; 24 | 25 | DiscordEmbedThumbnail({ 26 | required this.url, 27 | this.proxyUrl, 28 | this.height, 29 | this.width, 30 | }); 31 | 32 | factory DiscordEmbedThumbnail.fromJson(Map json) => 33 | DiscordEmbedThumbnail( 34 | url: json[urlEntry] as String, 35 | proxyUrl: json[proxyUrlEntry] as String?, 36 | height: json[heightEntry] as int?, 37 | width: json[widthEntry] as int?, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordEmbedType { 2 | /// generic embed rendered from embed attributes 3 | rich, 4 | 5 | /// image embed 6 | image, 7 | 8 | /// video embed 9 | video, 10 | 11 | /// animated gif image embed rendered as a video embed 12 | gifv, 13 | 14 | /// article embed 15 | article, 16 | 17 | /// link embed 18 | link, 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/discord_embed_video.dart: -------------------------------------------------------------------------------- 1 | class DiscordEmbedVideo { 2 | /// source url of video 3 | final String url; 4 | 5 | /// a proxied url of the video 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final String? proxyUrl; 9 | 10 | /// height of the video 11 | /// 12 | /// is not always returned, hence the nullable property 13 | final int? height; 14 | 15 | /// width of the video 16 | /// 17 | /// is not always returned, hence the nullable property 18 | final int? width; 19 | 20 | static const urlEntry = 'url'; 21 | static const proxyUrlEntry = 'proxy_url'; 22 | static const heightEntry = 'height'; 23 | static const widthEntry = 'width'; 24 | 25 | DiscordEmbedVideo({ 26 | required this.url, 27 | this.proxyUrl, 28 | this.height, 29 | this.width, 30 | }); 31 | 32 | factory DiscordEmbedVideo.fromJson(Map json) => 33 | DiscordEmbedVideo( 34 | url: json[urlEntry] as String, 35 | proxyUrl: json[proxyUrlEntry] as String?, 36 | height: json[heightEntry] as int?, 37 | width: json[widthEntry] as int?, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_emoji.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_user.dart'; 3 | 4 | class DiscordEmoji { 5 | /// [emoji id](https://discord.com/developers/docs/reference#image-formatting) 6 | final DiscordSnowflake? id; 7 | 8 | /// emoji name 9 | final String? name; 10 | 11 | /// roles allowed to use this emoji 12 | final List? roles; 13 | 14 | /// user that created this emoji 15 | final DiscordUser? user; 16 | 17 | /// whether this emoji must be wrapped in colons 18 | final bool? requireColons; 19 | 20 | /// whether this emoji is managed 21 | final bool? managed; 22 | 23 | /// whether this emoji is animated 24 | final bool? animated; 25 | 26 | /// whether this emoji can be used, may be false due to loss of Server Boosts 27 | final bool? available; 28 | 29 | static const idEntry = 'id'; 30 | static const nameEntry = 'name'; 31 | static const rolesEntry = 'roles'; 32 | static const userEntry = 'user'; 33 | static const requireColonsEntry = 'require_colons'; 34 | static const managedEntry = 'managed'; 35 | static const animatedEntry = 'animated'; 36 | static const availableEntry = 'available'; 37 | 38 | DiscordEmoji({ 39 | this.id, 40 | this.name, 41 | this.roles, 42 | this.user, 43 | this.requireColons, 44 | this.managed, 45 | this.animated, 46 | this.available, 47 | }); 48 | 49 | factory DiscordEmoji.fromJson(Map json) => DiscordEmoji( 50 | id: json[idEntry] != null 51 | ? DiscordSnowflake(json[idEntry] as String) 52 | : null, 53 | name: json[nameEntry] as String?, 54 | roles: json[rolesEntry] != null 55 | ? List.from(json[rolesEntry] as List) 56 | : null, 57 | user: json[userEntry] != null 58 | ? DiscordUser.fromJson(json[userEntry] as Map) 59 | : null, 60 | requireColons: json[requireColonsEntry] as bool?, 61 | managed: json[managedEntry] as bool?, 62 | animated: json[animatedEntry] as bool?, 63 | available: json[availableEntry] as bool?, 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/models/discord_errors.dart: -------------------------------------------------------------------------------- 1 | class DiscordErrors { 2 | /// The error code sent by Discord. 3 | final int code; 4 | 5 | /// The specification of the error. Differs from error type to error type. 6 | final Map errors; 7 | 8 | /// An human readable error message. 9 | final String message; 10 | 11 | DiscordErrors({ 12 | required this.code, 13 | required this.message, 14 | required this.errors, 15 | }); 16 | 17 | factory DiscordErrors.fromJson(Map json) => DiscordErrors( 18 | code: json['code'] as int, 19 | message: json['message'] as String, 20 | errors: json['errors'] as Map, 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/models/discord_explicit_content_filter_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordExplicitContentFilterLevel { 2 | /// media content will not be scanned 3 | disabled, 4 | 5 | /// media content sent by members without roles will be scanned 6 | membersWithoutRoles, 7 | 8 | /// media content sent by all members will be scanned 9 | allMembers, 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/models/discord_followed_channel.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordFollowedChannel { 4 | /// source channel id 5 | final DiscordSnowflake channelId; 6 | 7 | /// created target webhook id 8 | final DiscordSnowflake webhookId; 9 | 10 | static const channelIdEntry = 'channel_id'; 11 | static const webhookIdEntry = 'webhook_id'; 12 | 13 | DiscordFollowedChannel({ 14 | required this.channelId, 15 | required this.webhookId, 16 | }); 17 | 18 | factory DiscordFollowedChannel.fromJson(Map json) => 19 | DiscordFollowedChannel( 20 | channelId: DiscordSnowflake(json[channelIdEntry] as String), 21 | webhookId: DiscordSnowflake(json[webhookIdEntry] as String), 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_feature.dart: -------------------------------------------------------------------------------- 1 | enum DiscordGuildFeature { 2 | /// guild has access to set an animated guild icon 3 | animatedIcon, 4 | 5 | /// guild has access to set a guild banner image 6 | banner, 7 | 8 | /// guild has access to use commerce features (i.e. create store channels) 9 | commerce, 10 | 11 | /// guild can enable welcome screen, Membership Screening, stage channels 12 | /// and discovery, and receives community updates 13 | community, 14 | 15 | /// guild is able to be discovered in the directory 16 | discoverable, 17 | 18 | /// guild is able to be featured in the directory 19 | featurable, 20 | 21 | /// guild has access to set an invite splash background 22 | inviteSplash, 23 | 24 | /// guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) 25 | memberVerificationGateEnable, 26 | 27 | /// guild has enabled monetization 28 | monetizationEnabled, 29 | 30 | /// guild has increased custom stickers slots 31 | moreStickers, 32 | 33 | /// guild has access to create news channels 34 | news, 35 | 36 | /// guild is partnered 37 | partnered, 38 | 39 | /// guild can be previwed before joining via Membership Screening or the directory 40 | previewEnabled, 41 | 42 | /// guild has access to create private threads 43 | privateThreads, 44 | 45 | /// guild is able to set role icons 46 | roleIcons, 47 | 48 | /// guild has access to the seven day archive time for threads 49 | sevenDayThreadArchive, 50 | 51 | /// guild has access to the three day archive time for threads 52 | threeDayThreadArchive, 53 | 54 | /// guild has enabled ticketed events 55 | ticketedEventsEnabled, 56 | 57 | /// guild has access to set a vanity URL 58 | vanityUrl, 59 | 60 | /// guild is verified 61 | verified, 62 | 63 | /// guild has access to set 384kbps bitrate in voice (previously VIP voice servers) 64 | vipRegions, 65 | 66 | /// guild has enabled the welcome screen 67 | welcomeScreenEnabled, 68 | } 69 | 70 | List discordGuildFeaturesFromValues( 71 | List features, 72 | ) { 73 | final list = []; 74 | for (final feature in features) { 75 | switch (feature) { 76 | case "ANIMATED_ICON": 77 | list.add(DiscordGuildFeature.animatedIcon); 78 | break; 79 | case "BANNER": 80 | list.add(DiscordGuildFeature.banner); 81 | break; 82 | case "COMMERCE": 83 | list.add(DiscordGuildFeature.commerce); 84 | break; 85 | case "COMMUNITY": 86 | list.add(DiscordGuildFeature.community); 87 | break; 88 | case "DISCOVERABLE": 89 | list.add(DiscordGuildFeature.discoverable); 90 | break; 91 | case "FEATURABLE": 92 | list.add(DiscordGuildFeature.featurable); 93 | break; 94 | case "INVITE_SPLASH": 95 | list.add(DiscordGuildFeature.inviteSplash); 96 | break; 97 | case "MEMBER_VERIFICATION_GATE_ENABLED": 98 | list.add(DiscordGuildFeature.memberVerificationGateEnable); 99 | break; 100 | case "MONETIZATION_ENABLED": 101 | list.add(DiscordGuildFeature.monetizationEnabled); 102 | break; 103 | case "MORE_STICKERS": 104 | list.add(DiscordGuildFeature.moreStickers); 105 | break; 106 | case "NEWS": 107 | list.add(DiscordGuildFeature.news); 108 | break; 109 | case "PARTNERED": 110 | list.add(DiscordGuildFeature.partnered); 111 | break; 112 | case "PREVIEW_ENABLED": 113 | list.add(DiscordGuildFeature.previewEnabled); 114 | break; 115 | case "PRIVATE_THREADS": 116 | list.add(DiscordGuildFeature.privateThreads); 117 | break; 118 | case "ROLE_ICONS": 119 | list.add(DiscordGuildFeature.roleIcons); 120 | break; 121 | case "SEVEN_DAY_THREAD_ARCHIVE": 122 | list.add(DiscordGuildFeature.sevenDayThreadArchive); 123 | break; 124 | case "THREE_DAY_THREAD_ARCHIVE": 125 | list.add(DiscordGuildFeature.threeDayThreadArchive); 126 | break; 127 | case "TICKETED_EVENTS_ENABLED": 128 | list.add(DiscordGuildFeature.ticketedEventsEnabled); 129 | break; 130 | case "VANITY_URL": 131 | list.add(DiscordGuildFeature.vanityUrl); 132 | break; 133 | case "VERIFIED": 134 | list.add(DiscordGuildFeature.verified); 135 | break; 136 | case "VIP_REGIONS": 137 | list.add(DiscordGuildFeature.vipRegions); 138 | break; 139 | case "WELCOME_SCREEN_ENABLED": 140 | list.add(DiscordGuildFeature.welcomeScreenEnabled); 141 | break; 142 | } 143 | } 144 | return list; 145 | } 146 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_member.dart: -------------------------------------------------------------------------------- 1 | import 'discord_user.dart'; 2 | 3 | class DiscordGuildMember { 4 | /// the user this guild member represents 5 | /// 6 | /// is not always returned, hence the nullable property 7 | final DiscordUser? user; 8 | 9 | /// this user's guild nickname 10 | /// 11 | /// is not always returned, and can be null 12 | final String? nick; 13 | 14 | /// the member's [guild avatar hash](https://discord.com/developers/docs/reference#image-formatting) 15 | /// 16 | /// is not always returned, and can be null 17 | final String? avatar; 18 | 19 | /// array of [role](https://discord.com/developers/docs/topics/permissions#role-object) object ids 20 | final List roles; 21 | 22 | /// when the user joined the guild, 23 | /// as an ISO 8601 string 24 | final String joinedAt; 25 | 26 | late final DateTime? _joinedAtAsDateTime; 27 | 28 | /// when the user starter [boosting](https://support.discord.com/hc/en-us/articles/360028038352-Server-Boosting-) the guild 29 | /// 30 | /// is not always returned, and can be null 31 | final String? premiumSince; 32 | 33 | late final DateTime? _premiumSinceAsDateTime; 34 | 35 | /// whether the user is deafened in voice channels 36 | final bool deaf; 37 | 38 | /// whether the user is muted in voice channels 39 | final bool mute; 40 | 41 | /// whether the user has not yet passed the guild's [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) requirements 42 | /// 43 | /// is not always returned, hence the nullable property 44 | final bool? pending; 45 | 46 | /// total permissions of the member in the channel, including overwrites, 47 | /// returned when in the interaction object 48 | /// 49 | /// is not always returned, hence the nullable property 50 | final String? permissions; 51 | 52 | /// when the user's [timeout](https://support.discord.com/hc/en-us/articles/4413305239191-Time-Out-FAQ) 53 | /// will expire and the user will be able to communicate in the guild again, 54 | /// null or a time in the past if the user is not timed out 55 | /// 56 | /// is not always returned, and can be nullable 57 | final String? communicationDisabledUntil; 58 | 59 | late final DateTime? _communicationDisabledUntilAsDateTime; 60 | 61 | static const userEntry = 'user'; 62 | static const nickEntry = 'nick'; 63 | static const avatarEntry = 'avatar'; 64 | static const rolesEntry = 'roles'; 65 | static const joinedAtEntry = 'joined_at'; 66 | static const premiumSinceEntry = 'premium_since'; 67 | static const deafEntry = 'deaf'; 68 | static const muteEntry = 'mute'; 69 | static const pendingEntry = 'pending'; 70 | static const permissionsEntry = 'permissions'; 71 | static const communicationDisabledUntilEntry = 'communication_disabled_until'; 72 | 73 | DiscordGuildMember({ 74 | this.user, 75 | this.nick, 76 | this.avatar, 77 | required this.roles, 78 | required this.joinedAt, 79 | this.premiumSince, 80 | required this.deaf, 81 | required this.mute, 82 | this.pending, 83 | this.permissions, 84 | this.communicationDisabledUntil, 85 | }); 86 | 87 | DateTime get joinedAtAsDateTime { 88 | _joinedAtAsDateTime ??= DateTime.parse(joinedAt); 89 | return _joinedAtAsDateTime!; 90 | } 91 | 92 | DateTime? get premiumSinceAsDateTime { 93 | return _premiumSinceAsDateTime ??= 94 | premiumSince != null ? DateTime.parse(premiumSince!) : null; 95 | } 96 | 97 | DateTime? get communicationDisabledUntilAsDateTime { 98 | return _communicationDisabledUntilAsDateTime ??= 99 | communicationDisabledUntil != null 100 | ? DateTime.parse(communicationDisabledUntil!) 101 | : null; 102 | } 103 | 104 | factory DiscordGuildMember.fromJson(Map json) => 105 | DiscordGuildMember( 106 | user: json[userEntry] != null 107 | ? DiscordUser.fromJson(json[userEntry] as Map) 108 | : null, 109 | nick: json[nickEntry] as String?, 110 | avatar: json[avatarEntry] as String?, 111 | roles: List.from(json[rolesEntry] as List), 112 | joinedAt: json[joinedAtEntry] as String, 113 | premiumSince: json[premiumSinceEntry] as String?, 114 | deaf: json[deafEntry] as bool, 115 | mute: json[muteEntry] as bool, 116 | pending: json[pendingEntry] as bool?, 117 | permissions: json[permissionsEntry] as String?, 118 | communicationDisabledUntil: 119 | json[communicationDisabledUntilEntry] as String?, 120 | ); 121 | } 122 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_premium_tier.dart: -------------------------------------------------------------------------------- 1 | enum DiscordGuildPremiumTier { 2 | /// guild has not unlocked any Server Boost perks 3 | none, 4 | 5 | /// guild has unlocked the Server Boost level 1 perks 6 | tier1, 7 | 8 | /// guild has unlocked the Server Boost level 2 perks 9 | tier2, 10 | 11 | /// guild has unlocked the Server Boost level 3 perks 12 | tier3, 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_preview.dart: -------------------------------------------------------------------------------- 1 | import 'discord_emoji.dart'; 2 | import 'discord_guild_feature.dart'; 3 | import 'discord_snowflake.dart'; 4 | import 'discord_sticker.dart'; 5 | 6 | class DiscordGuildPreview { 7 | /// guild id 8 | final DiscordSnowflake id; 9 | 10 | /// guild name (2-100 characters) 11 | final String name; 12 | 13 | /// [icon hash](https://discord.com/developers/docs/reference#image-formatting) 14 | final String? icon; 15 | 16 | /// [splash hash](https://discord.com/developers/docs/reference#image-formatting) 17 | final String? splash; 18 | 19 | /// [discovery splash hash](https://discord.com/developers/docs/reference#image-formatting) 20 | final String? discoverySplash; 21 | 22 | /// custom guild emojis 23 | final List emojis; 24 | 25 | /// enabled guild features 26 | final List features; 27 | 28 | late final List? _featuresAsEnum; 29 | 30 | /// approximate number of members in this guild 31 | final int approximateMemberCount; 32 | 33 | /// approximate number of online members in this guild 34 | final int approximatePresenceCount; 35 | 36 | /// the description for the guild, if the guild is discoverable 37 | final String? description; 38 | 39 | /// custom guild stickers 40 | final List stickers; 41 | 42 | static const idEntry = 'id'; 43 | static const nameEntry = 'name'; 44 | static const iconEntry = 'icon'; 45 | static const splashEntry = 'splash'; 46 | static const discoverySplashEntry = 'discovery_splash'; 47 | static const emojisEntry = 'emojis'; 48 | static const featuresEntry = 'features'; 49 | static const approximateMemberCountEntry = 'approximate_member_count'; 50 | static const approximatePresenceCountEntry = 'approximate_presence_count'; 51 | static const descriptionEntry = 'description'; 52 | static const stickersEntry = 'stickers'; 53 | 54 | DiscordGuildPreview({ 55 | required this.id, 56 | required this.name, 57 | this.icon, 58 | this.splash, 59 | this.discoverySplash, 60 | required this.emojis, 61 | required this.features, 62 | required this.approximateMemberCount, 63 | required this.approximatePresenceCount, 64 | this.description, 65 | required this.stickers, 66 | }); 67 | 68 | List get featuresAsEnum => 69 | _featuresAsEnum ??= discordGuildFeaturesFromValues(features); 70 | 71 | factory DiscordGuildPreview.fromJson(Map json) => 72 | DiscordGuildPreview( 73 | id: DiscordSnowflake(json[idEntry] as String), 74 | name: json[nameEntry] as String, 75 | icon: json[iconEntry] as String?, 76 | splash: json[splashEntry] as String?, 77 | discoverySplash: json[discoverySplashEntry] as String?, 78 | emojis: List.from( 79 | (json[emojisEntry] as List>) 80 | .map(DiscordEmoji.fromJson), 81 | ), 82 | features: List.from(json[featuresEntry] as List), 83 | approximateMemberCount: json[approximateMemberCountEntry] as int, 84 | approximatePresenceCount: json[approximatePresenceCountEntry] as int, 85 | description: json[descriptionEntry] as String?, 86 | stickers: List.from( 87 | (json[stickersEntry] as List>) 88 | .map(DiscordSticker.fromJson), 89 | ), 90 | ); 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_scheduled_event_entity_metadata.dart: -------------------------------------------------------------------------------- 1 | class DiscordGuildScheduledEventEntityMetadata { 2 | /// location of the event (1-100 characters) 3 | /// 4 | /// [required](https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-entity-metadata) for events with 'entity_type': EXTERNAL 5 | /// 6 | /// is not always returned, hence the nullable property 7 | final String? location; 8 | 9 | static const locationEntry = 'location'; 10 | 11 | DiscordGuildScheduledEventEntityMetadata({ 12 | this.location, 13 | }); 14 | 15 | factory DiscordGuildScheduledEventEntityMetadata.fromJson( 16 | Map json, 17 | ) => 18 | DiscordGuildScheduledEventEntityMetadata( 19 | location: json[locationEntry] as String?, 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_scheduled_event_entity_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordGuildScheduledEventEntityType { 2 | unused, 3 | stageInstance, 4 | voice, 5 | external, 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_scheduled_event_privacy_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordGuildScheduledEventPrivacyLevel { 2 | unused, 3 | unused1, 4 | guildOnly, 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_scheduled_event_status.dart: -------------------------------------------------------------------------------- 1 | /// Once `status` is set to `COMPLETED` or `CANCELED`, 2 | /// the `status` can no longer be updated. 3 | /// 4 | /// **Valid Guild Scheduled Event Status Transitions** \ 5 | /// SCHEDULED --> ACTIVE \ 6 | /// ACTIVE --------> COMPLETED \ 7 | /// SCHEDULED --> CANCELED 8 | enum DiscordGuildScheduledEventStatus { 9 | unused, 10 | scheduled, 11 | active, 12 | completed, 13 | canceled, 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_scheduled_event_user.dart: -------------------------------------------------------------------------------- 1 | import 'discord_guild_member.dart'; 2 | import 'discord_snowflake.dart'; 3 | import 'discord_user.dart'; 4 | 5 | class DiscordGuildScheduledEventUser { 6 | /// the scheduled event id which the user subscribed to 7 | final DiscordSnowflake guildScheduledEventId; 8 | 9 | /// user which subscribed to an event 10 | final DiscordUser user; 11 | 12 | /// guild member data for this user for this guild 13 | /// which this event belongs to, if any 14 | /// 15 | /// is not always returned, hence the nullable property 16 | final DiscordGuildMember? member; 17 | 18 | static const guildScheduledEventIdEntry = 'guild_scheduled_event_id'; 19 | static const userEntry = 'user'; 20 | static const memberEntry = 'member'; 21 | 22 | DiscordGuildScheduledEventUser({ 23 | required this.guildScheduledEventId, 24 | required this.user, 25 | this.member, 26 | }); 27 | 28 | factory DiscordGuildScheduledEventUser.fromJson(Map json) => 29 | DiscordGuildScheduledEventUser( 30 | guildScheduledEventId: 31 | DiscordSnowflake(json[guildScheduledEventIdEntry] as String), 32 | user: DiscordUser.fromJson(json[userEntry] as Map), 33 | member: json[memberEntry] != null 34 | ? DiscordGuildMember.fromJson( 35 | json[memberEntry] as Map, 36 | ) 37 | : null, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_template.dart: -------------------------------------------------------------------------------- 1 | import 'discord_guild.dart'; 2 | import 'discord_snowflake.dart'; 3 | import 'discord_user.dart'; 4 | 5 | class DiscordGuildTemplate { 6 | /// the template code (unique ID) 7 | final String code; 8 | 9 | /// template name 10 | final String name; 11 | 12 | /// the description for the template 13 | final String? description; 14 | 15 | /// number of times this template has been used 16 | final int usageCount; 17 | 18 | /// the ID of the user who created this template 19 | final DiscordSnowflake creatorId; 20 | 21 | /// the user who created this template 22 | final DiscordUser creator; 23 | 24 | /// when this template was created 25 | /// 26 | /// as an ISO8601 string 27 | final String createdAt; 28 | 29 | late final DateTime? _createdAtAsDateTime; 30 | 31 | /// when this template was last synced to the source guild 32 | /// 33 | /// as an ISO8601 string 34 | final String updatedAt; 35 | 36 | late final DateTime? _updatedAtAsDateTime; 37 | 38 | /// the ID of the guild this template is based on 39 | final DiscordSnowflake sourceGuildId; 40 | 41 | /// the guild snapshot this template contains 42 | /// 43 | /// partial guild object 44 | final DiscordGuild serializedSourceGuild; 45 | 46 | /// whether the template has unsynced changes 47 | final bool? isDirty; 48 | 49 | static const codeEntry = 'code'; 50 | static const nameEntry = 'name'; 51 | static const descriptionEntry = 'description'; 52 | static const usageCountEntry = 'usage_count'; 53 | static const creatorIdEntry = 'creator_id'; 54 | static const creatorEntry = 'creator'; 55 | static const createdAtEntry = 'created_at'; 56 | static const updatedAtEntry = 'updated_at'; 57 | static const sourceGuildIdEntry = 'source_guild_id'; 58 | static const serializedSourceGuildEntry = 'serialized_source_guild'; 59 | static const isDirtyEntry = 'is_dirty'; 60 | 61 | DiscordGuildTemplate({ 62 | required this.code, 63 | required this.name, 64 | this.description, 65 | required this.usageCount, 66 | required this.creatorId, 67 | required this.creator, 68 | required this.createdAt, 69 | required this.updatedAt, 70 | required this.sourceGuildId, 71 | required this.serializedSourceGuild, 72 | this.isDirty, 73 | }); 74 | 75 | DateTime get createdAtAsDateTime => 76 | _createdAtAsDateTime ??= DateTime.parse(createdAt); 77 | 78 | DateTime get updatedAtAsDateTime => 79 | _updatedAtAsDateTime ??= DateTime.parse(updatedAt); 80 | 81 | factory DiscordGuildTemplate.fromJson(Map json) => 82 | DiscordGuildTemplate( 83 | code: json[codeEntry] as String, 84 | name: json[nameEntry] as String, 85 | description: json[descriptionEntry] as String?, 86 | usageCount: json[usageCountEntry] as int, 87 | creatorId: DiscordSnowflake(json[creatorIdEntry] as String), 88 | creator: 89 | DiscordUser.fromJson(json[creatorEntry] as Map), 90 | createdAt: json[createdAtEntry] as String, 91 | updatedAt: json[updatedAtEntry] as String, 92 | sourceGuildId: DiscordSnowflake(json[sourceGuildIdEntry] as String), 93 | serializedSourceGuild: DiscordGuild.fromJson( 94 | json[serializedSourceGuildEntry] as Map, 95 | ), 96 | isDirty: json[isDirtyEntry] as bool?, 97 | ); 98 | } 99 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_widget.dart: -------------------------------------------------------------------------------- 1 | import 'discord_channel.dart'; 2 | import 'discord_snowflake.dart'; 3 | import 'discord_user.dart'; 4 | 5 | class DiscordGuildWidget { 6 | /// guild id 7 | final DiscordSnowflake id; 8 | 9 | /// guild name (2-100 characters) 10 | final String name; 11 | 12 | /// instant invite for the guilds specified widget invite channel 13 | final String? instantInvite; 14 | 15 | /// voice and stage channels which are accessible by @everyone 16 | /// 17 | /// list of partial channel objects 18 | final List channels; 19 | 20 | /// special widget user objects that includes users presence (limit 100) 21 | /// 22 | /// list of partial user objects 23 | final List members; 24 | 25 | /// number of online members in this guild 26 | final int presenceCount; 27 | 28 | static const idEntry = 'id'; 29 | static const nameEntry = 'name'; 30 | static const instantInviteEntry = 'instant_invite'; 31 | static const channelsEntry = 'channels'; 32 | static const membersEntry = 'members'; 33 | static const presenceCountEntry = 'presence_count'; 34 | 35 | DiscordGuildWidget({ 36 | required this.id, 37 | required this.name, 38 | this.instantInvite, 39 | required this.channels, 40 | required this.members, 41 | required this.presenceCount, 42 | }); 43 | 44 | factory DiscordGuildWidget.fromJson(Map json) => 45 | DiscordGuildWidget( 46 | id: DiscordSnowflake(json[idEntry] as String), 47 | name: json[nameEntry] as String, 48 | instantInvite: json[instantInviteEntry] as String?, 49 | channels: List.from( 50 | (json[channelsEntry] as List>) 51 | .map(DiscordChannel.fromJson), 52 | ), 53 | members: List.from( 54 | (json[membersEntry] as List>) 55 | .map(DiscordUser.fromJson), 56 | ), 57 | presenceCount: json[presenceCountEntry] as int, 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/models/discord_guild_widget_settings.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordGuildWidgetSettings { 4 | /// whether the widget is enabled 5 | final bool enabled; 6 | 7 | /// the widget channel id 8 | final DiscordSnowflake? channelId; 9 | 10 | static const enabledEntry = 'enabled'; 11 | static const channelIdEntry = 'channel_id'; 12 | 13 | const DiscordGuildWidgetSettings({ 14 | required this.enabled, 15 | this.channelId, 16 | }); 17 | 18 | factory DiscordGuildWidgetSettings.fromJson(Map json) { 19 | return DiscordGuildWidgetSettings( 20 | enabled: json[enabledEntry] as bool, 21 | channelId: json[channelIdEntry] != null 22 | ? DiscordSnowflake(json[channelIdEntry] as String) 23 | : null, 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/models/discord_image_format.dart: -------------------------------------------------------------------------------- 1 | enum DiscordImageFormat { 2 | jpeg, 3 | png, 4 | webp, 5 | gif, 6 | lottie, 7 | } 8 | 9 | DiscordImageFormat discordImageFormatFromValue(String s) { 10 | return DiscordImageFormat.values 11 | .firstWhere((element) => element.fileExtension == s); 12 | } 13 | 14 | extension ToFileExtension on DiscordImageFormat { 15 | String get fileExtension { 16 | switch (this) { 17 | case DiscordImageFormat.jpeg: 18 | return 'jpg'; 19 | case DiscordImageFormat.png: 20 | return 'png'; 21 | case DiscordImageFormat.webp: 22 | return 'webp'; 23 | case DiscordImageFormat.gif: 24 | return 'gif'; 25 | case DiscordImageFormat.lottie: 26 | return 'json'; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/discord_integration_account.dart: -------------------------------------------------------------------------------- 1 | class DiscordIntegrationAccount { 2 | /// id of the account 3 | final String id; 4 | 5 | /// name of the account 6 | final String name; 7 | 8 | static const idEntry = 'id'; 9 | static const nameEntry = 'name'; 10 | 11 | DiscordIntegrationAccount({ 12 | required this.id, 13 | required this.name, 14 | }); 15 | 16 | factory DiscordIntegrationAccount.fromJson(Map json) { 17 | return DiscordIntegrationAccount( 18 | id: json[idEntry] as String, 19 | name: json[nameEntry] as String, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/models/discord_integration_application.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_user.dart'; 3 | 4 | class DiscordIntegrationApplication { 5 | /// the id of the app 6 | final DiscordSnowflake id; 7 | 8 | /// the name of the app 9 | final String name; 10 | 11 | /// the [icon hash](https://discord.com/developers/docs/reference#image-formatting) 12 | /// of the app 13 | /// 14 | /// is always returned, but can be null 15 | final String? icon; 16 | 17 | /// the description ofthe app 18 | final String description; 19 | 20 | /// the summary of the app 21 | final String summary; 22 | 23 | /// the bot associated with this application 24 | /// 25 | /// is not always returned, hence the nullable property 26 | final DiscordUser? bot; 27 | 28 | static const idEntry = 'id'; 29 | static const nameEntry = 'name'; 30 | static const iconEntry = 'icon'; 31 | static const descriptionEntry = 'description'; 32 | static const summaryEntry = 'summary'; 33 | static const botEntry = 'bot'; 34 | 35 | DiscordIntegrationApplication._({ 36 | required this.id, 37 | required this.name, 38 | this.icon, 39 | required this.description, 40 | required this.summary, 41 | this.bot, 42 | }); 43 | 44 | factory DiscordIntegrationApplication.fromJson(Map json) => 45 | DiscordIntegrationApplication._( 46 | id: DiscordSnowflake(json[idEntry] as String), 47 | name: json[nameEntry] as String, 48 | icon: json[iconEntry] as String?, 49 | description: json[descriptionEntry] as String, 50 | summary: json[summaryEntry] as String, 51 | bot: DiscordUser.fromJson(json[botEntry] as Map), 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/models/discord_integration_expiration_behavior.dart: -------------------------------------------------------------------------------- 1 | enum DiscordIntegrationExpirationBehavior { 2 | removeRole, 3 | kick, 4 | } 5 | -------------------------------------------------------------------------------- /lib/src/models/discord_invite.dart: -------------------------------------------------------------------------------- 1 | import 'discord_application.dart'; 2 | import 'discord_channel.dart'; 3 | import 'discord_guild.dart'; 4 | import 'discord_guild_scheduled_event.dart'; 5 | import 'discord_invite_stage_instance.dart'; 6 | import 'discord_invite_target_type.dart'; 7 | import 'discord_user.dart'; 8 | 9 | class DiscordInvite { 10 | /// the invite code (unique ID) 11 | final String code; 12 | 13 | /// the guild this invite is for 14 | /// 15 | /// partial guild object 16 | final DiscordGuild? guild; 17 | 18 | /// the channel this invite is for 19 | /// 20 | /// partial channel object 21 | final DiscordChannel? channel; 22 | 23 | /// the user who created this invite 24 | final DiscordUser? inviter; 25 | 26 | /// the [type of target](https://discord.com/developers/docs/resources/invite#invite-object-invite-target-types) 27 | /// for this voice channel invite 28 | final int? targetType; 29 | 30 | late final DiscordInviteTargetType? _targetTypeAsEnum; 31 | 32 | /// the user whose stream to display for this voice channel stream invite 33 | final DiscordUser? targetUser; 34 | 35 | /// the embedded application to open for this voice channel embedded application invite 36 | /// 37 | /// partial application object 38 | final DiscordApplication? targetApplication; 39 | 40 | /// approximate count of online members, returned from the 41 | /// `GET /invites/` endpoint when `with_counts` is set to `true` 42 | final int? approximatePresenceCount; 43 | 44 | /// approximate count of total members, returned from the 45 | /// `GET /invites/` endpoint when `with_counts` is set to `true` 46 | final int? approximateMemberCount; 47 | 48 | /// the expiration date of this invite, returned from the 49 | /// `GET /invites/` endpoint when `with_expiration` is set to `true` 50 | /// 51 | /// as an ISO 8601 date string 52 | final String? expiresAt; 53 | 54 | late final DateTime? _expiresAtAsDateTime; 55 | 56 | @Deprecated("") 57 | 58 | /// stage instance data if there is a [public Stage instance](https://discord.com/developers/docs/resources/stage-instance) 59 | /// in the Stage channel this invite is for 60 | final DiscordInviteStageInstance? stageInstance; 61 | 62 | /// guild scheduled event data, only included if `guild_scheduled_event_id` contains a valid guild scheduled event id 63 | final DiscordGuildScheduledEvent? guildScheduledEvent; 64 | 65 | static const codeEntry = 'code'; 66 | static const guildEntry = 'guild'; 67 | static const channelEntry = 'channel'; 68 | static const inviterEntry = 'inviter'; 69 | static const targetTypeEntry = 'target_type'; 70 | static const targetUserEntry = 'target_user'; 71 | static const targetApplicationEntry = 'target_application'; 72 | static const approximatePresenceCountEntry = 'approximate_presence_count'; 73 | static const approximateMemberCountEntry = 'approximate_member_count'; 74 | static const expiresAtEntry = 'expires_at'; 75 | static const stageInstanceEntry = 'stage_instance'; 76 | static const guildScheduledEventEntry = 'guild_scheduled_event'; 77 | 78 | DiscordInvite({ 79 | required this.code, 80 | this.guild, 81 | this.channel, 82 | this.inviter, 83 | this.targetType, 84 | this.targetUser, 85 | this.targetApplication, 86 | required this.approximatePresenceCount, 87 | required this.approximateMemberCount, 88 | this.expiresAt, 89 | @Deprecated("") this.stageInstance, 90 | this.guildScheduledEvent, 91 | }); 92 | 93 | DiscordInviteTargetType? get targetTypeAsEnum => _targetTypeAsEnum ??= 94 | targetType != null ? DiscordInviteTargetType.values[targetType!] : null; 95 | 96 | DateTime? get expiresAtAsDateTime => _expiresAtAsDateTime ??= 97 | expiresAt != null ? DateTime.parse(expiresAt!) : null; 98 | 99 | factory DiscordInvite.fromJson(Map json) => DiscordInvite( 100 | code: json[codeEntry] as String, 101 | guild: json[guildEntry] != null 102 | ? DiscordGuild.fromJson(json[guildEntry] as Map) 103 | : null, 104 | channel: json[channelEntry] != null 105 | ? DiscordChannel.fromJson( 106 | json[channelEntry] as Map, 107 | ) 108 | : null, 109 | inviter: json[inviterEntry] != null 110 | ? DiscordUser.fromJson(json[inviterEntry] as Map) 111 | : null, 112 | targetType: json[targetTypeEntry] as int?, 113 | targetUser: json[targetUserEntry] != null 114 | ? DiscordUser.fromJson( 115 | json[targetUserEntry] as Map, 116 | ) 117 | : null, 118 | targetApplication: json[targetApplicationEntry] != null 119 | ? DiscordApplication.fromJson( 120 | json[targetApplicationEntry] as Map, 121 | ) 122 | : null, 123 | approximatePresenceCount: json[approximatePresenceCountEntry] as int?, 124 | approximateMemberCount: json[approximateMemberCountEntry] as int?, 125 | expiresAt: json[expiresAtEntry] as String?, 126 | // ignore: deprecated_member_use_from_same_package 127 | stageInstance: json[stageInstanceEntry] != null 128 | ? DiscordInviteStageInstance.fromJson( 129 | json[stageInstanceEntry] as Map, 130 | ) 131 | : null, 132 | guildScheduledEvent: json[guildScheduledEventEntry] != null 133 | ? DiscordGuildScheduledEvent.fromJson( 134 | json[guildScheduledEventEntry] as Map, 135 | ) 136 | : null, 137 | ); 138 | } 139 | -------------------------------------------------------------------------------- /lib/src/models/discord_invite_metadata.dart: -------------------------------------------------------------------------------- 1 | class DiscordInviteMetadata { 2 | /// number of times the invite has been used 3 | final int uses; 4 | 5 | /// max number of times the invite can be used 6 | final int maxUses; 7 | 8 | /// duration (in seconds) after which the invite expires 9 | final int maxAge; 10 | 11 | /// whether this invite only grants temporary membership 12 | final bool temporary; 13 | 14 | /// when this invite was created 15 | /// 16 | /// as an ISO8601 string 17 | final String createdAt; 18 | 19 | late final DateTime? _createdAtAsDateTime; 20 | 21 | static const usesEntry = 'uses'; 22 | static const maxUsesEntry = 'max_uses'; 23 | static const maxAgeEntry = 'max_age'; 24 | static const temporaryEntry = 'temporary'; 25 | static const createdAtEntry = 'created_at'; 26 | 27 | DiscordInviteMetadata({ 28 | required this.uses, 29 | required this.maxUses, 30 | required this.maxAge, 31 | required this.temporary, 32 | required this.createdAt, 33 | }); 34 | 35 | DateTime get createdAtAsDateTime => 36 | _createdAtAsDateTime ??= DateTime.parse(createdAt); 37 | 38 | factory DiscordInviteMetadata.fromJson(Map json) => 39 | DiscordInviteMetadata( 40 | uses: json[usesEntry] as int, 41 | maxUses: json[maxUsesEntry] as int, 42 | maxAge: json[maxAgeEntry] as int, 43 | temporary: json[temporaryEntry] as bool, 44 | createdAt: json[createdAtEntry] as String, 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/models/discord_invite_stage_instance.dart: -------------------------------------------------------------------------------- 1 | import 'discord_guild_member.dart'; 2 | 3 | //@Deprecated("This is deprecated") 4 | class DiscordInviteStageInstance { 5 | /// the members speaking in the Stage 6 | final List members; 7 | 8 | /// the number of users in the Stage 9 | final int participantCount; 10 | 11 | /// the number of users speaking in the Stage 12 | final int speakerCount; 13 | 14 | /// the topic of the Stage instance (1-120 characters) 15 | final String topic; 16 | 17 | static const membersEntry = "members"; 18 | static const participantCountEntry = "participant_count"; 19 | static const speakerCountEntry = "speaker_count"; 20 | static const topicEntry = "topic"; 21 | 22 | DiscordInviteStageInstance({ 23 | required this.members, 24 | required this.participantCount, 25 | required this.speakerCount, 26 | required this.topic, 27 | }); 28 | 29 | factory DiscordInviteStageInstance.fromJson(Map json) => 30 | DiscordInviteStageInstance( 31 | members: List.from( 32 | (json[membersEntry] as List>) 33 | .map(DiscordGuildMember.fromJson), 34 | ), 35 | participantCount: json[participantCountEntry] as int, 36 | speakerCount: json[speakerCountEntry] as int, 37 | topic: json[topicEntry] as String, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_invite_target_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordInviteTargetType { 2 | unused, 3 | stream, 4 | embeddedApplication, 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/models/discord_membership_state.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMembershipState { 2 | none, 3 | invited, 4 | accepted, 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/models/discord_mention_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMentionType { 2 | /// controls role mentions 3 | roles, 4 | 5 | /// controls user mentions 6 | users, 7 | 8 | /// controls @everyone and @here mentions 9 | everyone, 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_activity.dart: -------------------------------------------------------------------------------- 1 | import 'discord_message_activity_type.dart'; 2 | 3 | class DiscordMessageActivity { 4 | /// [type of message activity](https://discord.com/developers/docs/resources/channel#message-object-message-activity-types) 5 | final int type; 6 | 7 | late final DiscordMessageActivityType? _typeAsEnum; 8 | 9 | /// party_id from a [Rich Presence event](https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields) 10 | final String? partyId; 11 | 12 | static const typeEntry = 'type'; 13 | static const partyIdEntry = 'party_id'; 14 | 15 | DiscordMessageActivity({ 16 | required this.type, 17 | this.partyId, 18 | }); 19 | 20 | DiscordMessageActivityType get typeAsEnum => 21 | _typeAsEnum ??= DiscordMessageActivityType.values[type]; 22 | 23 | factory DiscordMessageActivity.fromJson(Map json) => 24 | DiscordMessageActivity( 25 | type: json[typeEntry] as int, 26 | partyId: json[partyIdEntry] as String?, 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_activity_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMessageActivityType { 2 | unused, 3 | join, 4 | spectate, 5 | listen, 6 | unused4, 7 | joinRequest, 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_component_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMessageComponentType { 2 | unused, 3 | 4 | /// A container for other components 5 | actionRow, 6 | 7 | /// A button object 8 | button, 9 | 10 | /// A select menu for picking from choices 11 | selectMenu, 12 | 13 | /// A text input object 14 | textInput, 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_flag.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMessageFlag { 2 | /// 1 << 0 3 | /// 4 | /// this message has been published to subscribed channels 5 | /// (via Channel Following) 6 | crossposted, 7 | 8 | /// 1 << 1 9 | /// 10 | /// this message originated from a message in another channel 11 | /// (via Channel Following) 12 | isCrosspost, 13 | 14 | /// 1 << 2 15 | /// 16 | /// do not include any embeds when serializing this message 17 | suppressEmbeds, 18 | 19 | /// 1 << 3 20 | /// 21 | /// the source message for this crosspost has been deleted 22 | /// (via Channel Following) 23 | sourceMessageDeleted, 24 | 25 | /// 1 << 4 26 | /// 27 | /// this message came from the urgent message system 28 | urgent, 29 | 30 | /// 1 << 5 31 | /// 32 | /// this message has an associated thread, with the same id as the message 33 | hasThread, 34 | 35 | /// 1 << 6 36 | /// 37 | /// this message is only visible to the user who invoked the Interaction 38 | ephemeral, 39 | 40 | /// 1 << 7 41 | /// 42 | /// this message is an Interaction Response and the bot is "thinking" 43 | loading, 44 | 45 | /// 1 << 8 46 | /// 47 | /// this message failed to mention some roles and add their members 48 | /// to the thread 49 | failedToMentionSomeRolesInThread, 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_interaction.dart: -------------------------------------------------------------------------------- 1 | import 'discord_guild_member.dart'; 2 | import 'discord_message_interaction_type.dart'; 3 | import 'discord_snowflake.dart'; 4 | import 'discord_user.dart'; 5 | 6 | class DiscordMessageInteraction { 7 | /// id of the interaction 8 | final DiscordSnowflake id; 9 | 10 | /// the type of interaction 11 | final int type; 12 | 13 | late final DiscordMessageInteractionType? _typeAsEnum; 14 | 15 | /// the name of the [application command](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure) 16 | final String name; 17 | 18 | /// the user who invoked the interaction 19 | final DiscordUser user; 20 | 21 | /// the member who invoked the interaction in the guild 22 | final DiscordGuildMember? member; 23 | 24 | static const idEntry = 'id'; 25 | static const typeEntry = 'type'; 26 | static const nameEntry = 'name'; 27 | static const userEntry = 'user'; 28 | static const memberEntry = 'member'; 29 | 30 | DiscordMessageInteraction({ 31 | required this.id, 32 | required this.type, 33 | required this.name, 34 | required this.user, 35 | this.member, 36 | }); 37 | 38 | DiscordMessageInteractionType get typeAsEnum => 39 | _typeAsEnum ??= DiscordMessageInteractionType.values[type]; 40 | 41 | factory DiscordMessageInteraction.fromJson(Map json) => 42 | DiscordMessageInteraction( 43 | id: DiscordSnowflake(json[idEntry] as String), 44 | type: json[typeEntry] as int, 45 | name: json[nameEntry] as String, 46 | user: DiscordUser.fromJson(json[userEntry] as Map), 47 | member: json[memberEntry] != null 48 | ? DiscordGuildMember.fromJson( 49 | json[memberEntry] as Map, 50 | ) 51 | : null, 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_interaction_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMessageInteractionType { 2 | unused, 3 | ping, 4 | applicationCommand, 5 | messageComponent, 6 | applicationCommandAutocomplete, 7 | modalSubmit, 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_notifications_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMessageNotificationsLevel { 2 | /// members will receive notifications for all messages by default 3 | allMessages, 4 | 5 | /// members will receive notifications only for message that @mention them by default 6 | onlyMentions, 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_reference.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordMessageReference { 4 | /// id of the originating message 5 | /// 6 | /// is not always returned, hence the nullable property 7 | final DiscordSnowflake? messageId; 8 | 9 | /// id of the originating message's channel 10 | /// 11 | /// * is optional when creating a reply, but will always 12 | /// be present when receiving an event/response that includes this data model. 13 | /// 14 | /// is not always returned, hence the nullable property 15 | final DiscordSnowflake? channelId; 16 | 17 | /// id of the originating message's guild 18 | /// 19 | /// is not always returned, hence the nullable property 20 | final DiscordSnowflake? guildId; 21 | 22 | /// when sending, whether to error if the referenced message 23 | /// doesn't exist instead of sending as a normal (non-reply) 24 | /// message, default true 25 | /// 26 | /// is not always returned, hence the nullable property 27 | final bool? failIfNotExists; 28 | 29 | static const messageIdEntry = 'message_id'; 30 | static const channelIdEntry = 'channel_id'; 31 | static const guildIdEntry = 'guild_id'; 32 | static const failIfNotExistsEntry = 'fail_if_not_exists'; 33 | 34 | DiscordMessageReference({ 35 | this.messageId, 36 | this.channelId, 37 | this.guildId, 38 | this.failIfNotExists, 39 | }); 40 | 41 | factory DiscordMessageReference.fromJson(Map json) => 42 | DiscordMessageReference( 43 | messageId: json[messageIdEntry] != null 44 | ? DiscordSnowflake(json[messageIdEntry] as String) 45 | : null, 46 | channelId: json[channelIdEntry] != null 47 | ? DiscordSnowflake(json[channelIdEntry] as String) 48 | : null, 49 | guildId: json[guildIdEntry] != null 50 | ? DiscordSnowflake(json[guildIdEntry] as String) 51 | : null, 52 | failIfNotExists: json[failIfNotExistsEntry] as bool?, 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /lib/src/models/discord_message_type.dart: -------------------------------------------------------------------------------- 1 | /// Type 19 and 20 are only in API v8. In v6, they are still type 0. 2 | /// Type 21 is only in API v9. 3 | enum DiscordMessageType { 4 | default0, 5 | recipientAdd, 6 | recipientRemove, 7 | call, 8 | channelNameChange, 9 | channelIconChange, 10 | channelPinnedMessage, 11 | guildMemberJoin, 12 | userPremiumGuildSubscription, 13 | userPremiumGuildSubscriptionTier1, 14 | userPremiumGuildSubscriptionTier2, 15 | userPremiumGuildSubscriptionTier3, 16 | channelFollowAdd, 17 | guildDiscoveryDisqualified, 18 | guildDiscoveryRequalified, 19 | guildDiscoveryGracePeriodInitialWarning, 20 | guildDiscoveryGracePeriodFinalWarning, 21 | threadCreated, 22 | reply, 23 | chatInputCommand, 24 | threadStarterMessage, 25 | guildInviteReminder, 26 | contextMenuCommand, 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/models/discord_mfa_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordMfaLevel { 2 | /// guild has no MFA/2FA requirement for moderation actions 3 | none, 4 | 5 | /// guild has a 2FA requirement for moderation actions 6 | elevated, 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/discord_nsfw_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordNsfwLevel { 2 | default0, 3 | explicit, 4 | safe, 5 | ageRestricted, 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/models/discord_optional_audit_entry_info.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordOptionalAuditEntryInfo { 4 | /// channel in which the entities were targeted 5 | /// 6 | /// Available in : MEMBER_MOVE & MESSAGE_PIN & MESSAGE_UNPIN & MESSAGE_DELETE & STAGE_INSTANCE_CREATE & STAGE_INSTANCE_UPDATE & STAGE_INSTANCE_DELETE 7 | /// 8 | /// is not always returned, hence the nullable porperty 9 | final DiscordSnowflake? channelId; 10 | 11 | /// number of entities that were targeted 12 | /// 13 | /// Available in : MESSAGE_DELETE & MESSAGE_BULK_DELETE & MEMBER_DISCONNECT & MEMBER_MOVE 14 | /// 15 | /// is not always returned, hence the nullable porperty 16 | final String? count; 17 | 18 | /// number of days after which inactive members were kicked 19 | /// 20 | /// Available in : MEMBER_PRUNE 21 | /// 22 | /// is not always returned, hence the nullable porperty 23 | final String? deleteMemberDays; 24 | 25 | /// id of the overwritten entity 26 | /// 27 | /// Available in : CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE 28 | /// 29 | /// is not always returned, hence the nullable porperty 30 | final DiscordSnowflake? id; 31 | 32 | /// number of members removed by the prune 33 | /// 34 | /// Available in : MEMBER_PRUNE 35 | /// 36 | /// is not always returned, hence the nullable porperty 37 | final String? membersRemoved; 38 | 39 | /// id of the message that was targeted 40 | /// 41 | /// Available in : MESSAGE_PIN & MESSAGE_UNPIN 42 | /// 43 | /// is not always returned, hence the nullable porperty 44 | final DiscordSnowflake? messageId; 45 | 46 | /// name of the role if type is "0" (not present if type is "1") 47 | /// 48 | /// Available in : CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE 49 | /// 50 | /// is not always returned, hence the nullable porperty 51 | final String? roleName; 52 | 53 | /// type of overwrriten entity - "0" for "role" or "1" for "member" 54 | /// 55 | /// Available in : CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE 56 | /// 57 | /// is not always returned, hence the nullable porperty 58 | final String? type; 59 | 60 | static const channelIdEntry = "channel_id"; 61 | static const countEntry = "count"; 62 | static const deleteMemberDaysEntry = "delete_member_days"; 63 | static const idEntry = "id"; 64 | static const membersRemovedEntry = "members_removed"; 65 | static const messageIdEntry = "message_id"; 66 | static const roleNameEntry = "role_name"; 67 | static const typeEntry = "type"; 68 | 69 | DiscordOptionalAuditEntryInfo({ 70 | this.channelId, 71 | this.count, 72 | this.deleteMemberDays, 73 | this.id, 74 | this.membersRemoved, 75 | this.messageId, 76 | this.roleName, 77 | this.type, 78 | }); 79 | 80 | factory DiscordOptionalAuditEntryInfo.fromJson(Map json) => 81 | DiscordOptionalAuditEntryInfo( 82 | channelId: json[channelIdEntry] != null 83 | ? DiscordSnowflake(json[channelIdEntry] as String) 84 | : null, 85 | count: json[countEntry] as String?, 86 | deleteMemberDays: json[deleteMemberDaysEntry] as String?, 87 | id: json[idEntry] != null 88 | ? DiscordSnowflake(json[idEntry] as String) 89 | : null, 90 | membersRemoved: json[membersRemovedEntry] as String?, 91 | messageId: json[messageIdEntry] != null 92 | ? DiscordSnowflake(json[messageIdEntry] as String) 93 | : null, 94 | roleName: json[roleNameEntry] as String?, 95 | type: json[typeEntry] as String?, 96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /lib/src/models/discord_overwrite.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordOverwrite { 4 | /// role or user id 5 | final DiscordSnowflake id; 6 | 7 | /// 0 = role, 1 = member 8 | final int type; 9 | 10 | /// Permission bit set (see [permissions](https://discord.com/developers/docs/topics/permissions#permissions)) 11 | final String allow; 12 | 13 | /// Permission bit set (see [permissions](https://discord.com/developers/docs/topics/permissions#permissions)) 14 | final String deny; 15 | 16 | static const idEntry = 'id'; 17 | static const typeEntry = 'type'; 18 | static const allowEntry = 'allow'; 19 | static const denyEntry = 'deny'; 20 | 21 | DiscordOverwrite({ 22 | required this.id, 23 | required this.type, 24 | required this.allow, 25 | required this.deny, 26 | }); 27 | 28 | factory DiscordOverwrite.fromJson(Map json) => 29 | DiscordOverwrite( 30 | id: DiscordSnowflake(json[idEntry] as String), 31 | type: json[typeEntry] as int, 32 | allow: json[allowEntry] as String, 33 | deny: json[denyEntry] as String, 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/models/discord_overwrite_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordOverwriteType { 2 | role, 3 | member, 4 | } 5 | -------------------------------------------------------------------------------- /lib/src/models/discord_premium_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordPremiumType { 2 | none, 3 | nitroClassic, 4 | nitro, 5 | } 6 | -------------------------------------------------------------------------------- /lib/src/models/discord_presence_update.dart: -------------------------------------------------------------------------------- 1 | import 'discord_activity.dart'; 2 | import 'discord_client_status.dart'; 3 | import 'discord_snowflake.dart'; 4 | import 'discord_status.dart'; 5 | import 'discord_user.dart'; 6 | 7 | class DiscordPresenceUpdate { 8 | /// the user presence is being updated for 9 | final DiscordUser user; 10 | 11 | /// id of the guild 12 | final DiscordSnowflake guildId; 13 | 14 | /// the user's current status 15 | /// 16 | /// either "idle", "dnd", "online", or "offline" 17 | final String status; 18 | 19 | late final DiscordStatus? _statusAsEnum; 20 | 21 | /// user's current activities 22 | final List activites; 23 | 24 | /// user's platform-dependant status 25 | final DiscordClientStatus clientStatus; 26 | 27 | static const userEntry = 'user'; 28 | static const guildIdEntry = 'guild_id'; 29 | static const statusEntry = 'status'; 30 | static const activitiesEntry = 'activities'; 31 | static const clientStatusEntry = 'client_status'; 32 | 33 | DiscordPresenceUpdate({ 34 | required this.user, 35 | required this.guildId, 36 | required this.status, 37 | required this.activites, 38 | required this.clientStatus, 39 | }); 40 | 41 | DiscordStatus get statusAsEnum { 42 | _statusAsEnum ??= DiscordStatus.values.firstWhere((e) => e.name == status); 43 | return _statusAsEnum!; 44 | } 45 | 46 | factory DiscordPresenceUpdate.fromJson(Map json) => 47 | DiscordPresenceUpdate( 48 | user: DiscordUser.fromJson(json[userEntry] as Map), 49 | guildId: DiscordSnowflake(json[guildIdEntry] as String), 50 | status: json[statusEntry] as String, 51 | activites: List.from( 52 | (json[activitiesEntry] as List>) 53 | .map(DiscordActivity.fromJson), 54 | ), 55 | clientStatus: DiscordClientStatus.fromJson( 56 | json[clientStatusEntry] as Map, 57 | ), 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/models/discord_reaction.dart: -------------------------------------------------------------------------------- 1 | import 'discord_emoji.dart'; 2 | 3 | class DiscordReaction { 4 | /// times this emoji has been used to react 5 | final int count; 6 | 7 | /// whether the current user reacted using this emoji 8 | final bool me; 9 | 10 | /// emoji information 11 | final DiscordEmoji emoji; 12 | 13 | static const countEntry = 'count'; 14 | static const meEntry = 'me'; 15 | static const emojiEntry = 'emoji'; 16 | 17 | DiscordReaction({ 18 | required this.count, 19 | required this.me, 20 | required this.emoji, 21 | }); 22 | 23 | factory DiscordReaction.fromJson(Map json) => 24 | DiscordReaction( 25 | count: json[countEntry] as int, 26 | me: json[meEntry] as bool, 27 | emoji: DiscordEmoji.fromJson(json[emojiEntry] as Map), 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/discord_role.dart: -------------------------------------------------------------------------------- 1 | import 'discord_role_tags.dart'; 2 | import 'discord_snowflake.dart'; 3 | 4 | class DiscordRole { 5 | final DiscordSnowflake id; 6 | final String name; 7 | final int? color; 8 | final bool? hoist; 9 | final String? icon; 10 | final String? unicodeEmoji; 11 | final int? position; 12 | final String? permissions; 13 | final bool? managed; 14 | final bool? mentionable; 15 | final DiscordRoleTags? tags; 16 | 17 | static const idEntry = 'id'; 18 | static const nameEntry = 'name'; 19 | static const colorEntry = 'color'; 20 | static const hoistEntry = 'hoist'; 21 | static const iconEntry = 'icon'; 22 | static const unicodeEmojiEntry = 'unicode_emoji'; 23 | static const positionEntry = 'position'; 24 | static const permissionsEntry = 'permissions'; 25 | static const managedEntry = 'managed'; 26 | static const mentionableEntry = 'mentionable'; 27 | static const tagsEntry = 'tags'; 28 | 29 | DiscordRole({ 30 | required this.id, 31 | required this.name, 32 | this.color, 33 | this.hoist, 34 | this.icon, 35 | this.unicodeEmoji, 36 | this.position, 37 | this.permissions, 38 | this.managed, 39 | this.mentionable, 40 | this.tags, 41 | }); 42 | 43 | factory DiscordRole.fromJson(Map json) => DiscordRole( 44 | id: DiscordSnowflake(json[idEntry] as String), 45 | name: json[nameEntry] as String, 46 | color: json[colorEntry] as int?, 47 | hoist: json[hoistEntry] as bool?, 48 | icon: json[iconEntry] as String?, 49 | unicodeEmoji: json[unicodeEmojiEntry] as String?, 50 | position: json[positionEntry] as int?, 51 | permissions: json[permissionsEntry] as String?, 52 | managed: json[managedEntry] as bool?, 53 | mentionable: json[mentionableEntry] as bool?, 54 | tags: json[tagsEntry] != null 55 | ? DiscordRoleTags.fromJson(json[tagsEntry] as Map) 56 | : null, 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/models/discord_role_tags.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordRoleTags { 4 | final DiscordSnowflake? botId; 5 | final DiscordSnowflake? integrationId; 6 | 7 | /// Whether this is the guild's premium subscriber role. 8 | /// 9 | /// Is actually a field with a type of `null` in the API. 10 | /// In order to make it work here, we will check if the response 11 | /// got the key [premiumSubscriberEntry] and if it does, we consider 12 | /// it true. 13 | final bool premiumSubscriber; 14 | 15 | static const botIdEntry = 'bot_id'; 16 | static const integrationIdEntry = 'integration_id'; 17 | static const premiumSubscriberEntry = 'premium_subscriber'; 18 | 19 | DiscordRoleTags({ 20 | this.botId, 21 | this.integrationId, 22 | required this.premiumSubscriber, 23 | }); 24 | 25 | factory DiscordRoleTags.fromJson(Map json) { 26 | return DiscordRoleTags( 27 | botId: json[botIdEntry] != null 28 | ? DiscordSnowflake(json[botIdEntry] as String) 29 | : null, 30 | integrationId: json[integrationIdEntry] != null 31 | ? DiscordSnowflake(json[integrationIdEntry] as String) 32 | : null, 33 | premiumSubscriber: json.containsKey(premiumSubscriberEntry), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/models/discord_snowflake.dart: -------------------------------------------------------------------------------- 1 | class DiscordSnowflake { 2 | final int timestamp; 3 | late final DateTime? _timestampAsDateTime; 4 | 5 | final int workerId; 6 | final int processId; 7 | final int increment; 8 | 9 | final String snowflake; 10 | 11 | DiscordSnowflake(this.snowflake) 12 | : timestamp = (int.parse(snowflake) >> 22) + 1420070400000, 13 | workerId = (int.parse(snowflake) & 0x3E0000) >> 17, 14 | processId = (int.parse(snowflake) & 0x1F000) >> 12, 15 | increment = int.parse(snowflake) & 0xFFF; 16 | 17 | DateTime get timestampAsDateTime => 18 | _timestampAsDateTime ??= DateTime.fromMillisecondsSinceEpoch(timestamp); 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/models/discord_stage_instance.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_stage_privacy_level.dart'; 3 | 4 | class DiscordStageInstance { 5 | /// The id of this Stage instance 6 | final DiscordSnowflake id; 7 | 8 | /// The guild id of the associated Stage channel 9 | final DiscordSnowflake guildId; 10 | 11 | /// The id of the associated Stage channel 12 | final DiscordSnowflake channelId; 13 | 14 | /// The topic of the Stage instance (1-120 characters) 15 | final String topic; 16 | 17 | /// The [privacy level](https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level) 18 | /// of the Stage instance 19 | final int privacyLevel; 20 | 21 | late final DiscordStagePrivacyLevel? _privacyLevelAsEnum; 22 | 23 | /// Whether or not Stage Discovery is disabled (deprecated) 24 | @Deprecated('Use `privacyLevel` instead') 25 | final bool discoverableDisabled; 26 | 27 | static const idEntry = 'id'; 28 | static const guildIdEntry = 'guild_id'; 29 | static const channelIdEntry = 'channel_id'; 30 | static const topicEntry = 'topic'; 31 | static const privacyLevelEntry = 'privacy_level'; 32 | static const discoverableDisabledEntry = 'discoverable_disabled'; 33 | 34 | DiscordStageInstance({ 35 | required this.id, 36 | required this.guildId, 37 | required this.channelId, 38 | required this.topic, 39 | required this.privacyLevel, 40 | @Deprecated("Use `privacyLevel` instead") 41 | required this.discoverableDisabled, 42 | }); 43 | 44 | DiscordStagePrivacyLevel get privacyLevelAsEnum { 45 | _privacyLevelAsEnum ??= DiscordStagePrivacyLevel.values[privacyLevel]; 46 | return _privacyLevelAsEnum!; 47 | } 48 | 49 | factory DiscordStageInstance.fromJson(Map json) => 50 | DiscordStageInstance( 51 | id: DiscordSnowflake(json[idEntry] as String), 52 | guildId: DiscordSnowflake(json[guildIdEntry] as String), 53 | channelId: DiscordSnowflake(json[channelIdEntry] as String), 54 | topic: json[topicEntry] as String, 55 | privacyLevel: json[privacyLevelEntry] as int, 56 | // ignore: deprecated_member_use_from_same_package 57 | discoverableDisabled: json[discoverableDisabledEntry] as bool, 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/models/discord_stage_privacy_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordStagePrivacyLevel { 2 | unused, 3 | 4 | /// The stage instance is visible publicly. (deprecated) 5 | @Deprecated("Stages can't be publicly visible anymore") 6 | public, 7 | 8 | /// The stage instance is visible to only guild members. 9 | guildOnly, 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/models/discord_status.dart: -------------------------------------------------------------------------------- 1 | enum DiscordStatus { 2 | idle, 3 | dnd, 4 | online, 5 | offline, 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/models/discord_sticker.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_sticker_format_type.dart'; 3 | import 'discord_sticker_type.dart'; 4 | import 'discord_user.dart'; 5 | 6 | /// Represents a sticker that can be sent in messages. 7 | class DiscordSticker { 8 | /// [id of the sticker](https://discord.com/developers/docs/reference#image-formatting) 9 | final DiscordSnowflake id; 10 | 11 | /// for standard stickers, id of the pack the sticker is from 12 | /// 13 | /// is not always returned, hence the nullable property 14 | final DiscordSnowflake? packId; 15 | 16 | /// name of the sticker 17 | final String name; 18 | 19 | /// description of the sticker 20 | /// 21 | /// can be null 22 | final String? description; 23 | 24 | /// autocomplete/suggestion tags for the sticker (max 200 characters) 25 | /// 26 | /// * A comma separated list of keywords is the format used in this 27 | /// field by standard stickers, but this is just a convention. 28 | /// Incidentally the client will always use a name generated from 29 | /// an emoji as the value of this field when creating or modifying 30 | /// a guild sticker. 31 | final String tags; 32 | 33 | /// **Deprecated** previously the sticker asset hash, now an empty string 34 | final String asset; 35 | 36 | /// [type of sticker](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types) 37 | final int type; 38 | 39 | late final DiscordStickerType? _typeAsEnum; 40 | 41 | /// [type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) 42 | final int formatType; 43 | 44 | late final DiscordStickerFormatType? _formatTypeAsEnum; 45 | 46 | /// whether this guild sticker can be used, may be false due to loss of Server Boosts 47 | /// 48 | /// is not always returned, hence the nullable property 49 | final bool? available; 50 | 51 | /// id of the guild that owns this sticker 52 | /// 53 | /// is not always returned, hence the nullable property 54 | final DiscordSnowflake? guildId; 55 | 56 | /// the user that uploaded this guild sticker* 57 | /// 58 | /// is not always returned, hence the nullable property 59 | final DiscordUser? user; 60 | 61 | /// the standard sticker's sort order within its pack 62 | /// 63 | /// is not always returned, hence the nullable property 64 | final int? sortValue; 65 | 66 | static const idEntry = 'id'; 67 | static const packIdEntry = 'pack_id'; 68 | static const nameEntry = 'name'; 69 | static const descriptionEntry = 'description'; 70 | static const tagsEntry = 'tags'; 71 | static const assetEntry = 'asset'; 72 | static const typeEntry = 'type'; 73 | static const formatTypeEntry = 'format_type'; 74 | static const availableEntry = 'available'; 75 | static const guildIdEntry = 'guild_id'; 76 | static const userEntry = 'user'; 77 | static const sortValueEntry = 'sort_value'; 78 | 79 | DiscordSticker({ 80 | required this.id, 81 | this.packId, 82 | required this.name, 83 | this.description, 84 | required this.tags, 85 | required this.asset, 86 | required this.type, 87 | required this.formatType, 88 | this.available, 89 | this.guildId, 90 | this.user, 91 | this.sortValue, 92 | }); 93 | 94 | DiscordStickerType get typeAsEnum { 95 | _typeAsEnum ??= DiscordStickerType.values[type]; 96 | return _typeAsEnum!; 97 | } 98 | 99 | DiscordStickerFormatType get formatTypeAsEnum { 100 | _formatTypeAsEnum ??= DiscordStickerFormatType.values[formatType]; 101 | return _formatTypeAsEnum!; 102 | } 103 | 104 | factory DiscordSticker.fromJson(Map json) => DiscordSticker( 105 | id: DiscordSnowflake(json[idEntry] as String), 106 | packId: json[packIdEntry] != null 107 | ? DiscordSnowflake(json[packIdEntry] as String) 108 | : null, 109 | name: json[nameEntry] as String, 110 | description: json[descriptionEntry] as String?, 111 | tags: json[tagsEntry] as String, 112 | asset: json[assetEntry] as String, 113 | type: json[typeEntry] as int, 114 | formatType: json[formatTypeEntry] as int, 115 | available: 116 | json[availableEntry] != null ? json[availableEntry] as bool? : null, 117 | guildId: json[guildIdEntry] != null 118 | ? DiscordSnowflake(json[guildIdEntry] as String) 119 | : null, 120 | user: json[userEntry] != null 121 | ? DiscordUser.fromJson(json[userEntry] as Map) 122 | : null, 123 | sortValue: json[sortValueEntry] as int?, 124 | ); 125 | } 126 | -------------------------------------------------------------------------------- /lib/src/models/discord_sticker_format_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordStickerFormatType { 2 | unused, 3 | png, 4 | apng, 5 | lottie, 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/models/discord_sticker_item.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_sticker_format_type.dart'; 3 | 4 | /// The smallest amount of data required to render a sticker. 5 | /// A partial sticker object. 6 | class DiscordStickerItem { 7 | /// id of the sticker 8 | final DiscordSnowflake id; 9 | 10 | /// name of the sticker 11 | final String name; 12 | 13 | /// [type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) 14 | final int formatType; 15 | 16 | late final DiscordStickerFormatType? _formatTypeAsEnum; 17 | 18 | static const idEntry = 'id'; 19 | static const nameEntry = 'name'; 20 | static const formatTypeEntry = 'format_type'; 21 | 22 | DiscordStickerItem({ 23 | required this.id, 24 | required this.name, 25 | required this.formatType, 26 | }); 27 | 28 | DiscordStickerFormatType get formatTypeAsEnum { 29 | _formatTypeAsEnum ??= DiscordStickerFormatType.values[formatType]; 30 | return _formatTypeAsEnum!; 31 | } 32 | 33 | factory DiscordStickerItem.fromJson(Map json) => 34 | DiscordStickerItem( 35 | id: DiscordSnowflake(json[idEntry] as String), 36 | name: json[nameEntry] as String, 37 | formatType: json[formatTypeEntry] as int, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_sticker_pack.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_sticker.dart'; 3 | 4 | class DiscordStickerPack { 5 | /// id of the sticker pack 6 | final DiscordSnowflake id; 7 | 8 | /// the stickers in the pack 9 | final List stickers; 10 | 11 | /// name of the sticker pack 12 | final String name; 13 | 14 | /// id of the pack's SKU 15 | final DiscordSnowflake skuId; 16 | 17 | /// id of a sticker in the pack which is shown as the pack's icon 18 | /// 19 | /// is not always returned, hence the nullable property 20 | final DiscordSnowflake? coverStickerId; 21 | 22 | /// description of the sticker pack 23 | final String description; 24 | 25 | /// id of the sticker pack's [banner image](https://discord.com/developers/docs/reference#image-formatting) 26 | /// 27 | /// is not always returned, hence the nullable property 28 | final DiscordSnowflake? bannerAssetId; 29 | 30 | static const idEntry = 'id'; 31 | static const stickersEntry = 'stickers'; 32 | static const nameEntry = 'name'; 33 | static const skuIdEntry = 'sku_id'; 34 | static const coverStickerIdEntry = 'cover_sticker_id'; 35 | static const descriptionEntry = 'description'; 36 | static const bannerAssetIdEntry = 'banner_asset_id'; 37 | 38 | DiscordStickerPack({ 39 | required this.id, 40 | required this.stickers, 41 | required this.name, 42 | required this.skuId, 43 | this.coverStickerId, 44 | required this.description, 45 | this.bannerAssetId, 46 | }); 47 | 48 | factory DiscordStickerPack.fromJson(Map json) => 49 | DiscordStickerPack( 50 | id: DiscordSnowflake(json[idEntry] as String), 51 | stickers: List.from( 52 | (json[stickersEntry] as List>) 53 | .map(DiscordSticker.fromJson), 54 | ), 55 | name: json[nameEntry] as String, 56 | skuId: DiscordSnowflake(json[skuIdEntry] as String), 57 | coverStickerId: json[coverStickerIdEntry] != null 58 | ? DiscordSnowflake(json[coverStickerIdEntry] as String) 59 | : null, 60 | description: json[descriptionEntry] as String, 61 | bannerAssetId: json[bannerAssetIdEntry] != null 62 | ? DiscordSnowflake(json[bannerAssetIdEntry] as String) 63 | : null, 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/models/discord_sticker_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordStickerType { 2 | unused, 3 | 4 | /// an official sticker in a pack, part of Nitro or 5 | /// in a removed purchasable pack 6 | standard, 7 | 8 | /// a sticker upload to a Boosted guild for the guild's members 9 | guild, 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/models/discord_system_channel_flag.dart: -------------------------------------------------------------------------------- 1 | enum DiscordSystemChannelFlag { 2 | /// 1 << 0 3 | /// 4 | /// Suppress member join notifications 5 | suppressJoinNotifications, 6 | 7 | /// 1 << 1 8 | /// 9 | /// Suppress server boost notifications 10 | suppressPremiumSubscriptions, 11 | 12 | /// 1 << 2 13 | /// 14 | /// Suppress server setup tips 15 | suppressGuildReminderNotifications, 16 | 17 | /// 1 << 3 18 | /// 19 | /// Hide member join sticker reply buttons 20 | suppressJoinNotificationReplies, 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/models/discord_team.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | import 'discord_team_member.dart'; 3 | 4 | class DiscordTeam { 5 | final DiscordSnowflake id; 6 | 7 | final String? icon; 8 | final List? members; 9 | final String name; 10 | final DiscordSnowflake ownerUserId; 11 | 12 | static const idEntry = 'id'; 13 | static const iconEntry = 'icon'; 14 | static const membersEntry = 'members'; 15 | static const nameEntry = 'name'; 16 | static const ownerUserIdEntry = 'owner_user_id'; 17 | 18 | DiscordTeam({ 19 | required this.id, 20 | this.icon, 21 | this.members, 22 | required this.name, 23 | required this.ownerUserId, 24 | }); 25 | 26 | factory DiscordTeam.fromJson(Map json) => DiscordTeam( 27 | id: DiscordSnowflake(json[idEntry] as String), 28 | icon: json[iconEntry] as String?, 29 | members: (json[membersEntry] as Iterable?) 30 | ?.cast>() 31 | .map(DiscordTeamMember.fromJson) 32 | .toList(), 33 | name: json[nameEntry] as String, 34 | ownerUserId: DiscordSnowflake(json[ownerUserIdEntry] as String), 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/models/discord_team_member.dart: -------------------------------------------------------------------------------- 1 | import 'discord_membership_state.dart'; 2 | import 'discord_snowflake.dart'; 3 | import 'discord_user.dart'; 4 | 5 | class DiscordTeamMember { 6 | final int membershipState; 7 | late final DiscordMembershipState? _membershipStateAsEnum; 8 | final List permissions; // will always be ["*"] 9 | final DiscordSnowflake teamId; 10 | final DiscordUser 11 | user; // partial, only avatar, discriminator, id and username 12 | 13 | static const membershipStateEntry = "membership_state"; 14 | static const permissionsEntry = "permissions"; 15 | static const teamIdEntry = "team_id"; 16 | static const userEntry = "user"; 17 | 18 | DiscordTeamMember({ 19 | required this.membershipState, 20 | required this.permissions, 21 | required this.teamId, 22 | required this.user, 23 | }); 24 | 25 | DiscordMembershipState get membershipStateAsEnum => 26 | _membershipStateAsEnum ??= DiscordMembershipState.values[membershipState]; 27 | 28 | factory DiscordTeamMember.fromJson(Map json) => 29 | DiscordTeamMember( 30 | membershipState: json[membershipStateEntry] as int, 31 | permissions: List.from(json[permissionsEntry] as List), 32 | teamId: DiscordSnowflake(json[teamIdEntry] as String), 33 | user: DiscordUser.fromJson(json[userEntry] as Map), 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/models/discord_thread_member.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordThreadMember { 4 | /// the id of the thread 5 | final DiscordSnowflake? id; 6 | 7 | /// the id of the user 8 | final DiscordSnowflake? userId; 9 | 10 | /// the time the current user last joined the thread 11 | final String joinTimestamp; 12 | 13 | late final DateTime? _joinTimestampAsDateTime; 14 | 15 | /// any user-thread settings, currently only used for notifications 16 | final int flags; 17 | 18 | static const idEntry = 'id'; 19 | static const userIdEntry = 'user_id'; 20 | static const joinTimestampEntry = 'join_timestamp'; 21 | static const flagsEntry = 'flags'; 22 | 23 | DiscordThreadMember({ 24 | this.id, 25 | this.userId, 26 | required this.joinTimestamp, 27 | required this.flags, 28 | }); 29 | 30 | DateTime? get joinTimestampAsDateTime { 31 | return _joinTimestampAsDateTime ??= DateTime.parse(joinTimestamp); 32 | } 33 | 34 | factory DiscordThreadMember.fromJson(Map json) => 35 | DiscordThreadMember( 36 | id: json[idEntry] != null 37 | ? DiscordSnowflake(json[idEntry] as String) 38 | : null, 39 | userId: json[userIdEntry] != null 40 | ? DiscordSnowflake(json[userIdEntry] as String) 41 | : null, 42 | joinTimestamp: json[joinTimestampEntry] as String, 43 | flags: json[flagsEntry] as int, 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/models/discord_thread_metadata.dart: -------------------------------------------------------------------------------- 1 | class DiscordThreadMetadata { 2 | /// whether the thread is archived 3 | final bool archived; 4 | 5 | /// duration in minutes to automatically archive the thread 6 | /// after recent activity, can be set to: 60, 1440, 4320, 10080 7 | final int autoArchiveDuration; 8 | 9 | /// timestamp when the thread's archive status was last changed, 10 | /// used for calculating recent activity 11 | /// 12 | /// as an ISO 8601 string 13 | final String archiveTimestamp; 14 | 15 | late final DateTime? _archiveTimestampAsDateTime; 16 | 17 | /// whether the thread is locked; when a thread is locked, 18 | /// only users with MANAGE_THREADS can unarchive it 19 | final bool locked; 20 | 21 | /// whether non-moderators can add other non-moderators 22 | /// to a thread; only available on private threads 23 | /// 24 | /// is not always returned, hence the nullable property 25 | final bool? invitable; 26 | 27 | /// timestamp when the thread was created; only populated 28 | /// for threads created after 2022-01-09 29 | /// 30 | /// as an ISO 8601 string 31 | /// 32 | /// is not always returned, hence the nullable property 33 | final String? createTimestamp; 34 | 35 | late final DateTime? _createTimestampAsDateTime; 36 | 37 | static const archivedEntry = 'archived'; 38 | static const autoArchiveDurationEntry = 'auto_archive_duration'; 39 | static const archiveTimestampEntry = 'archive_timestamp'; 40 | static const lockedEntry = 'locked'; 41 | static const invitableEntry = 'invitable'; 42 | static const createTimestampEntry = 'create_timestamp'; 43 | 44 | DiscordThreadMetadata({ 45 | required this.archived, 46 | required this.autoArchiveDuration, 47 | required this.archiveTimestamp, 48 | required this.locked, 49 | this.invitable, 50 | this.createTimestamp, 51 | }); 52 | 53 | DateTime? get archiveTimestampAsDateTime { 54 | return _archiveTimestampAsDateTime ??= DateTime.parse(archiveTimestamp); 55 | } 56 | 57 | DateTime? get createTimestampAsDateTime { 58 | if (createTimestamp == null) return null; 59 | return _createTimestampAsDateTime ??= DateTime.parse(createTimestamp!); 60 | } 61 | 62 | factory DiscordThreadMetadata.fromJson(Map json) => 63 | DiscordThreadMetadata( 64 | archived: json[archivedEntry] as bool, 65 | autoArchiveDuration: json[autoArchiveDurationEntry] as int, 66 | archiveTimestamp: json[archiveTimestampEntry] as String, 67 | locked: json[lockedEntry] as bool, 68 | invitable: json[invitableEntry] as bool?, 69 | createTimestamp: json[createTimestampEntry] as String?, 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /lib/src/models/discord_token.dart: -------------------------------------------------------------------------------- 1 | import 'discord_token_webhook.dart'; 2 | 3 | class DiscordToken { 4 | final String accessToken; 5 | final String refreshToken; 6 | final String scope; 7 | final String tokenType; 8 | late final List? scopes; 9 | final int expiresIn; 10 | late final DateTime expiresAt; 11 | final DiscordTokenWebhook? webhook; 12 | 13 | static const accessTokenEntry = 'access_token'; 14 | static const tokenTypeEntry = 'token_type'; 15 | static const refreshTokenEntry = 'refresh_token'; 16 | static const scopeEntry = 'scope'; 17 | static const expiresInEntry = 'expires_in'; 18 | static const webhookEntry = 'webhook'; 19 | 20 | DiscordToken({ 21 | required this.accessToken, 22 | required this.refreshToken, 23 | required this.scope, 24 | required this.tokenType, 25 | required this.expiresIn, 26 | this.webhook, 27 | }) { 28 | scopes = scope.split(' '); 29 | // Removing 60 seconds as a sanity check. 30 | expiresAt = DateTime.now().add(Duration(seconds: expiresIn - 60)); 31 | } 32 | 33 | bool get isValid => expiresAt.isAfter(DateTime.now()); 34 | 35 | factory DiscordToken.fromJson(Map json) => DiscordToken( 36 | accessToken: json[accessTokenEntry] as String, 37 | refreshToken: json[refreshTokenEntry] as String, 38 | scope: json[scopeEntry] as String, 39 | tokenType: json[tokenTypeEntry] as String, 40 | expiresIn: json[expiresInEntry] as int, 41 | webhook: json[webhookEntry] != null 42 | ? DiscordTokenWebhook.fromJson( 43 | json[webhookEntry] as Map, 44 | ) 45 | : null, 46 | ); 47 | 48 | DiscordToken copyWith({ 49 | String? accessToken, 50 | String? refreshToken, 51 | String? scope, 52 | String? tokenType, 53 | int? expiresIn, 54 | DiscordTokenWebhook? webhook, 55 | }) => 56 | DiscordToken( 57 | accessToken: accessToken ?? this.accessToken, 58 | refreshToken: refreshToken ?? this.refreshToken, 59 | scope: scope ?? this.scope, 60 | tokenType: tokenType ?? this.tokenType, 61 | expiresIn: expiresIn ?? this.expiresIn, 62 | webhook: webhook ?? this.webhook, 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/models/discord_token_webhook.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordTokenWebhook { 4 | final DiscordSnowflake applicationId; 5 | final String name; 6 | final String url; 7 | final DiscordSnowflake channelId; 8 | final String token; 9 | final int type; 10 | final String? avatar; 11 | final DiscordSnowflake guildId; 12 | final DiscordSnowflake id; 13 | 14 | static const applicationIdEntry = 'application_id'; 15 | static const nameEntry = 'name'; 16 | static const urlEntry = 'url'; 17 | static const channelIdEntry = 'channel_id'; 18 | static const tokenEntry = 'token'; 19 | static const typeEntry = 'type'; 20 | static const avatarEntry = 'avatar'; 21 | static const guildIdEntry = 'guild_id'; 22 | static const idEntry = 'id'; 23 | 24 | DiscordTokenWebhook({ 25 | required this.applicationId, 26 | required this.name, 27 | required this.url, 28 | required this.channelId, 29 | required this.token, 30 | required this.type, 31 | required this.avatar, 32 | required this.guildId, 33 | required this.id, 34 | }); 35 | 36 | factory DiscordTokenWebhook.fromJson(Map json) => 37 | DiscordTokenWebhook( 38 | applicationId: DiscordSnowflake(json[applicationIdEntry] as String), 39 | name: json[nameEntry] as String, 40 | url: json[urlEntry] as String, 41 | channelId: DiscordSnowflake(json[channelIdEntry] as String), 42 | token: json[tokenEntry] as String, 43 | type: json[typeEntry] as int, 44 | avatar: json[avatarEntry] as String?, 45 | guildId: DiscordSnowflake(json[guildIdEntry] as String), 46 | id: DiscordSnowflake(json[idEntry] as String), 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/models/discord_user_flag.dart: -------------------------------------------------------------------------------- 1 | enum DiscordUserFlag { 2 | /// 0 3 | none, 4 | 5 | /// 1 << 0 6 | staff, 7 | 8 | /// 1 << 1 9 | partner, 10 | 11 | /// 1 << 2 12 | hypesquad, 13 | 14 | /// 1 << 3 15 | bugHunterLevel1, 16 | 17 | /// 1 << 6 18 | hypesquadOnlineHouse1, 19 | 20 | /// 1 << 7 21 | hypesquadOnlineHouse2, 22 | 23 | /// 1 << 8 24 | hypesquadOnlineHouse3, 25 | 26 | /// 1 << 9 27 | premiumEarlySupporter, 28 | 29 | /// 1 << 10 30 | teamPseudoUser, 31 | 32 | /// 1 << 14 33 | bugHunterLevel2, 34 | 35 | /// 1 << 16 36 | verifiedBot, 37 | 38 | /// 1 << 17 39 | verifiedDeveloper, 40 | 41 | /// 1 << 18 42 | certifiedModerator, 43 | 44 | /// 1 << 19 45 | botHttpInteractions, 46 | } 47 | 48 | void _addPublicFlagAsEnum( 49 | String r, 50 | int index, 51 | DiscordUserFlag flag, 52 | List f, 53 | ) { 54 | if (r.length >= index + 1 && r.substring(index, index + 1) == '1') { 55 | f.add(flag); 56 | } 57 | } 58 | 59 | List discordUserFlagsAsEnum(int? flags) { 60 | if (flags == null || flags == 0) { 61 | return [DiscordUserFlag.none]; 62 | } 63 | final f = []; 64 | final radixString = 65 | String.fromCharCodes(flags.toRadixString(2).runes.toList().reversed); 66 | _addPublicFlagAsEnum( 67 | radixString, 68 | 0, 69 | DiscordUserFlag.staff, 70 | f, 71 | ); 72 | _addPublicFlagAsEnum( 73 | radixString, 74 | 1, 75 | DiscordUserFlag.partner, 76 | f, 77 | ); 78 | _addPublicFlagAsEnum( 79 | radixString, 80 | 2, 81 | DiscordUserFlag.hypesquad, 82 | f, 83 | ); 84 | _addPublicFlagAsEnum( 85 | radixString, 86 | 3, 87 | DiscordUserFlag.bugHunterLevel1, 88 | f, 89 | ); 90 | _addPublicFlagAsEnum( 91 | radixString, 92 | 6, 93 | DiscordUserFlag.hypesquadOnlineHouse1, 94 | f, 95 | ); 96 | _addPublicFlagAsEnum( 97 | radixString, 98 | 7, 99 | DiscordUserFlag.hypesquadOnlineHouse2, 100 | f, 101 | ); 102 | _addPublicFlagAsEnum( 103 | radixString, 104 | 8, 105 | DiscordUserFlag.hypesquadOnlineHouse3, 106 | f, 107 | ); 108 | _addPublicFlagAsEnum( 109 | radixString, 110 | 9, 111 | DiscordUserFlag.premiumEarlySupporter, 112 | f, 113 | ); 114 | _addPublicFlagAsEnum( 115 | radixString, 116 | 10, 117 | DiscordUserFlag.teamPseudoUser, 118 | f, 119 | ); 120 | _addPublicFlagAsEnum( 121 | radixString, 122 | 14, 123 | DiscordUserFlag.bugHunterLevel2, 124 | f, 125 | ); 126 | _addPublicFlagAsEnum( 127 | radixString, 128 | 16, 129 | DiscordUserFlag.verifiedBot, 130 | f, 131 | ); 132 | _addPublicFlagAsEnum( 133 | radixString, 134 | 17, 135 | DiscordUserFlag.verifiedDeveloper, 136 | f, 137 | ); 138 | _addPublicFlagAsEnum( 139 | radixString, 140 | 18, 141 | DiscordUserFlag.certifiedModerator, 142 | f, 143 | ); 144 | _addPublicFlagAsEnum( 145 | radixString, 146 | 19, 147 | DiscordUserFlag.botHttpInteractions, 148 | f, 149 | ); 150 | return f; 151 | } 152 | -------------------------------------------------------------------------------- /lib/src/models/discord_verification_level.dart: -------------------------------------------------------------------------------- 1 | enum DiscordVerificationLevel { 2 | /// unrestricted 3 | none, 4 | 5 | /// must have verified email on account 6 | low, 7 | 8 | /// must be registered on Discord for longer than 5 minutes 9 | medium, 10 | 11 | /// must be a member of the server for longer than 10 minutes 12 | high, 13 | 14 | /// must have a verified phone number 15 | veryHigh, 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/models/discord_video_quality_mode.dart: -------------------------------------------------------------------------------- 1 | enum DiscordVideoQualityMode { 2 | unused, 3 | 4 | /// Discord chooses the quality for optimal performance 5 | auto, 6 | 7 | /// 720p 8 | full, 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/models/discord_visibility_type.dart: -------------------------------------------------------------------------------- 1 | enum DiscordVisibilityType { 2 | /// invisible to everyone except the user themselves 3 | none, 4 | 5 | /// visible to everyone 6 | everyone, 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/models/discord_voice_region.dart: -------------------------------------------------------------------------------- 1 | class DiscordVoiceRegion { 2 | /// unique ID for the region 3 | final String id; 4 | 5 | /// name of the region 6 | final String name; 7 | 8 | /// true for a single server that is closest to the current user's client 9 | final bool optimal; 10 | 11 | /// whether this is a deprecated voice region (avoid switching to these) 12 | final bool deprecated; 13 | 14 | /// whether this is a custom voice region (used for events/etc) 15 | final bool custom; 16 | 17 | static const idEntry = 'id'; 18 | static const nameEntry = 'name'; 19 | static const optimalEntry = 'optimal'; 20 | static const deprecatedEntry = 'deprecated'; 21 | static const customEntry = 'custom'; 22 | 23 | DiscordVoiceRegion({ 24 | required this.id, 25 | required this.name, 26 | required this.optimal, 27 | required this.deprecated, 28 | required this.custom, 29 | }); 30 | 31 | factory DiscordVoiceRegion.fromJson(Map json) => 32 | DiscordVoiceRegion( 33 | id: json[idEntry] as String, 34 | name: json[nameEntry] as String, 35 | optimal: json[optimalEntry] as bool, 36 | deprecated: json[deprecatedEntry] as bool, 37 | custom: json[customEntry] as bool, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/models/discord_voice_state.dart: -------------------------------------------------------------------------------- 1 | import 'discord_guild_member.dart'; 2 | import 'discord_snowflake.dart'; 3 | 4 | class DiscordVoiceState { 5 | /// the guild id this voice state is for 6 | /// 7 | /// is not always returned, hence the nullable property 8 | final DiscordSnowflake? guildId; 9 | 10 | /// the channel id this user is connected to 11 | /// 12 | /// is always returned, but can be null 13 | final DiscordSnowflake? channelId; 14 | 15 | /// the user id this voice state is for 16 | final DiscordSnowflake userId; 17 | 18 | /// the guild member this voice state is for 19 | /// 20 | /// is not always returned, hence the nullable property 21 | final DiscordGuildMember? member; 22 | 23 | /// the session id for this voice state 24 | final String sessionId; 25 | 26 | /// whether this user is deafened by the server 27 | final bool deaf; 28 | 29 | /// whether this user is muted by the server 30 | final bool muted; 31 | 32 | /// whether this user is locally deafened 33 | final bool selfDeaf; 34 | 35 | /// whether this user is locally muted 36 | final bool selfMuted; 37 | 38 | /// whether this user is streaming using "Go Live" 39 | /// 40 | /// is not always returned, hence the nullable property 41 | final bool? selfStream; 42 | 43 | /// whether this user's camera is enabled 44 | final bool selfVideo; 45 | 46 | /// whether this user is muted by the current user 47 | final bool suppress; 48 | 49 | /// the time at which the user request to speak, 50 | /// as an ISO 8601 timestamp 51 | /// 52 | /// is always returned, but can be null 53 | final String? requestToSpeakTimestamp; 54 | 55 | late final DateTime? _requestToSpeakTimestampAsDateTime; 56 | 57 | static const guildIdEntry = 'guild_id'; 58 | static const channelIdEntry = 'channel_id'; 59 | static const userIdEntry = 'user_id'; 60 | static const memberEntry = 'member'; 61 | static const sessionIdEntry = 'session_id'; 62 | static const deafEntry = 'deaf'; 63 | static const mutedEntry = 'muted'; 64 | static const selfDeafEntry = 'self_deaf'; 65 | static const selfMutedEntry = 'self_muted'; 66 | static const selfStreamEntry = 'self_stream'; 67 | static const selfVideoEntry = 'self_video'; 68 | static const suppressEntry = 'suppress'; 69 | static const requestToSpeakTimestampEntry = 'request_to_speak_timestamp'; 70 | 71 | DiscordVoiceState({ 72 | this.guildId, 73 | this.channelId, 74 | required this.userId, 75 | this.member, 76 | required this.sessionId, 77 | required this.deaf, 78 | required this.muted, 79 | required this.selfDeaf, 80 | required this.selfMuted, 81 | this.selfStream, 82 | required this.selfVideo, 83 | required this.suppress, 84 | this.requestToSpeakTimestamp, 85 | }); 86 | 87 | /// returns the [requestToSpeakTimestamp] as a DateTime 88 | DateTime? get requestToSpeakTimestampAsDateTime { 89 | if (requestToSpeakTimestamp == null) return null; 90 | return _requestToSpeakTimestampAsDateTime ??= 91 | DateTime.parse(requestToSpeakTimestamp!); 92 | } 93 | 94 | factory DiscordVoiceState.fromJson(Map json) => 95 | DiscordVoiceState( 96 | guildId: json[guildIdEntry] != null 97 | ? DiscordSnowflake(json[guildIdEntry] as String) 98 | : null, 99 | channelId: json[channelIdEntry] != null 100 | ? DiscordSnowflake(json[channelIdEntry] as String) 101 | : null, 102 | userId: DiscordSnowflake(json[userIdEntry] as String), 103 | member: json[memberEntry] != null 104 | ? DiscordGuildMember.fromJson( 105 | json[memberEntry] as Map, 106 | ) 107 | : null, 108 | sessionId: json[sessionIdEntry] as String, 109 | deaf: json[deafEntry] as bool, 110 | muted: json[mutedEntry] as bool, 111 | selfDeaf: json[selfDeafEntry] as bool, 112 | selfMuted: json[selfMutedEntry] as bool, 113 | selfStream: json[selfStreamEntry] as bool?, 114 | selfVideo: json[selfVideoEntry] as bool, 115 | suppress: json[suppressEntry] as bool, 116 | requestToSpeakTimestamp: json[requestToSpeakTimestampEntry] as String?, 117 | ); 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/models/discord_webhook.dart: -------------------------------------------------------------------------------- 1 | import 'discord_channel.dart'; 2 | import 'discord_guild.dart'; 3 | import 'discord_snowflake.dart'; 4 | import 'discord_user.dart'; 5 | 6 | class DiscordWebhook { 7 | /// the id of the webhook 8 | final DiscordSnowflake id; 9 | 10 | /// the [type](https://discord.com/developers/docs/resources/webhook#webhook-object-webhook-types) 11 | /// of the webhook 12 | final int type; 13 | 14 | /// the guild id this webhook is for, if any 15 | /// 16 | /// is not always returned, and can be null 17 | final DiscordSnowflake? guildId; 18 | 19 | /// the channel id this webhook is for, if any 20 | /// 21 | /// is always returned, but can be null 22 | final DiscordSnowflake? channelId; 23 | 24 | /// the user this webhook was created by (not returned when getting a webhook with its token) 25 | /// 26 | /// is not always returned, hence the nullable property 27 | final DiscordUser? user; 28 | 29 | /// the default name of the webhook 30 | /// 31 | /// is not always returned, hence the nullable property 32 | final String? name; 33 | 34 | /// the default user avatar [hash](https://discord.com/developers/docs/reference#image-formatting) 35 | /// of the webhook 36 | /// 37 | /// is not always returned, hence the nullable property 38 | final String? avatar; 39 | 40 | /// the secure token of the webhook (returned for Incoming Webhooks) 41 | /// 42 | /// is not always returned, hence the nullable property 43 | final String? token; 44 | 45 | /// the bot/OAuth2 application that created this webhook. 46 | /// 47 | /// is not always returned, and can be null 48 | final DiscordSnowflake? applicationId; 49 | 50 | /// the guild of the channel that this webhook is following (returned for Channel Follower Webhooks) 51 | /// 52 | /// returns only a partial object 53 | /// 54 | /// is not always returned, hence the nullable property 55 | final DiscordGuild? sourceGuild; 56 | 57 | /// the channel that this webhook is following (returned for Channel Follower Webhooks) 58 | /// 59 | /// returns only a partial object 60 | /// 61 | /// is not always returned, hence the nullable property 62 | final DiscordChannel? sourceChannel; 63 | 64 | /// the url used for executing the webhook (returned by the [webhooks](https://discord.com/developers/docs/topics/oauth2#webhooks) 65 | /// OAuth2 flow) 66 | /// 67 | /// is not always returned, hence the nullable property 68 | final String? url; 69 | 70 | static const idEntry = 'id'; 71 | static const typeEntry = 'type'; 72 | static const guildIdEntry = 'guild_id'; 73 | static const channelIdEntry = 'channel_id'; 74 | static const userEntry = 'user'; 75 | static const nameEntry = 'name'; 76 | static const avatarEntry = 'avatar'; 77 | static const tokenEntry = 'token'; 78 | static const applicationIdEntry = 'application_id'; 79 | static const sourceGuildEntry = 'source_guild'; 80 | static const sourceChannelEntry = 'source_channel'; 81 | static const urlEntry = 'url'; 82 | 83 | DiscordWebhook({ 84 | required this.id, 85 | required this.type, 86 | this.guildId, 87 | this.channelId, 88 | this.user, 89 | this.name, 90 | this.avatar, 91 | this.token, 92 | this.applicationId, 93 | this.sourceGuild, 94 | this.sourceChannel, 95 | this.url, 96 | }); 97 | 98 | factory DiscordWebhook.fromJson(Map json) => DiscordWebhook( 99 | id: DiscordSnowflake(json[idEntry] as String), 100 | type: json[typeEntry] as int, 101 | guildId: json[guildIdEntry] != null 102 | ? DiscordSnowflake(json[guildIdEntry] as String) 103 | : null, 104 | channelId: json[channelIdEntry] != null 105 | ? DiscordSnowflake(json[channelIdEntry] as String) 106 | : null, 107 | user: json[userEntry] != null 108 | ? DiscordUser.fromJson(json[userEntry] as Map) 109 | : null, 110 | name: json[nameEntry] as String?, 111 | avatar: json[avatarEntry] as String?, 112 | token: json[tokenEntry] as String?, 113 | applicationId: json[applicationIdEntry] != null 114 | ? DiscordSnowflake(json[applicationIdEntry] as String) 115 | : null, 116 | sourceGuild: json[sourceGuildEntry] != null 117 | ? DiscordGuild.fromJson( 118 | json[sourceGuildEntry] as Map, 119 | ) 120 | : null, 121 | sourceChannel: json[sourceChannelEntry] != null 122 | ? DiscordChannel.fromJson( 123 | json[sourceChannelEntry] as Map, 124 | ) 125 | : null, 126 | url: json[urlEntry] as String?, 127 | ); 128 | } 129 | -------------------------------------------------------------------------------- /lib/src/models/discord_welcome_screen.dart: -------------------------------------------------------------------------------- 1 | import 'discord_welcome_screen_channel.dart'; 2 | 3 | class DiscordWelcomeScreen { 4 | /// the server description shown in the welcome screen 5 | /// 6 | /// can be null 7 | final String? description; 8 | 9 | /// the channels shown in the welcome screen, up to 5 10 | final List welcomeChannels; 11 | 12 | static const descriptionEntry = 'description'; 13 | static const welcomeChannelsEntry = 'welcome_channels'; 14 | 15 | DiscordWelcomeScreen({ 16 | this.description, 17 | required this.welcomeChannels, 18 | }); 19 | 20 | factory DiscordWelcomeScreen.fromJson(Map json) => 21 | DiscordWelcomeScreen( 22 | description: json[descriptionEntry] as String?, 23 | welcomeChannels: List.from( 24 | (json[welcomeChannelsEntry] as List>) 25 | .map(DiscordWelcomeScreen.fromJson), 26 | ), 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/models/discord_welcome_screen_channel.dart: -------------------------------------------------------------------------------- 1 | import 'discord_snowflake.dart'; 2 | 3 | class DiscordWelcomeScreenChannel { 4 | /// the channel's id 5 | final DiscordSnowflake channelId; 6 | 7 | /// the description shown for the channel 8 | final String description; 9 | 10 | /// the [emoji id](https://discord.com/developers/docs/reference#image-formatting), 11 | /// if the emoji is custom 12 | /// 13 | /// can be null 14 | final DiscordSnowflake? emojiId; 15 | 16 | /// the emoji name if custom, the unicode character if standard, 17 | /// or `null` if no emoji is set 18 | final String? emojiName; 19 | 20 | static const channelIdEntry = 'channel_id'; 21 | static const descriptionEntry = 'description'; 22 | static const emojiIdEntry = 'emoji_id'; 23 | static const emojiNameEntry = 'emoji_name'; 24 | 25 | DiscordWelcomeScreenChannel({ 26 | required this.channelId, 27 | required this.description, 28 | this.emojiId, 29 | this.emojiName, 30 | }); 31 | 32 | factory DiscordWelcomeScreenChannel.fromJson(Map json) => 33 | DiscordWelcomeScreenChannel( 34 | channelId: DiscordSnowflake(json[channelIdEntry] as String), 35 | description: json[descriptionEntry] as String, 36 | emojiId: json[emojiIdEntry] != null 37 | ? DiscordSnowflake(json[emojiIdEntry] as String) 38 | : null, 39 | emojiName: json[emojiNameEntry] as String?, 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/providers/discord_http_client.dart: -------------------------------------------------------------------------------- 1 | import '../models/discord_token.dart'; 2 | 3 | abstract class DiscordHttpClient { 4 | DiscordToken? get discordToken; 5 | 6 | /// Method to initialize the token the first time after connection. 7 | /// 8 | /// [discordToken]: Token obtained with the first connection. 9 | void initializeToken(DiscordToken discordToken); 10 | 11 | /// Generic method for authenticated GET calls. 12 | Future getCall( 13 | Iterable pathSegments, { 14 | Map queryParameters = const {}, 15 | }); 16 | 17 | /// Generic method for authenticated POST calls. 18 | Future postCall( 19 | Iterable pathSegments, 20 | dynamic data, { 21 | Map queryParameters = const {}, 22 | }); 23 | 24 | /// Generic method for authenticated PATCH calls. 25 | Future patchCall( 26 | Iterable pathSegments, 27 | dynamic data, { 28 | Map queryParameters = const {}, 29 | }); 30 | 31 | /// Generic method for authenticated PUT calls. 32 | Future putCall( 33 | Iterable pathSegments, 34 | dynamic data, { 35 | Map queryParameters = const {}, 36 | }); 37 | 38 | /// Generic method for authenticated DELETE calls. 39 | Future deleteCall( 40 | Iterable pathSegments, { 41 | Map queryParameters = const {}, 42 | }); 43 | 44 | Future validateToken(); 45 | Future getAccessToken(String code, String redirectUri); 46 | Future refreshAccessToken(); 47 | Future revokeRefreshToken(); 48 | } 49 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: discord_api 2 | description: A pure dart package wrapping the discord API, including transformers for all its objects. 3 | version: 0.1.1 4 | homepage: https://github.com/MeixDev/discord_api 5 | repository: https://github.com/MeixDev/discord_api 6 | 7 | environment: 8 | sdk: '>=2.15.0 <3.0.0' 9 | 10 | dependencies: 11 | dio: ^4.0.4 12 | 13 | dev_dependencies: 14 | coverage: ^1.1.0 15 | http_mock_adapter: ^0.3.2 16 | lint: ^1.8.2 17 | test: ^1.20.1 -------------------------------------------------------------------------------- /test/discord_api_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:discord_api/src/discord_cdn_helper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | final cdn = DiscordCdnHelper.instance; 6 | 7 | group('DiscordCdnHelper tests', () { 8 | test("Get 131492741409538048's Avatar in size 64", () { 9 | final value = cdn.getUserAvatar( 10 | userId: "131492741409538048", 11 | userAvatarHash: "64d4f5dfcb00059794c20f656cb19c2b", 12 | size: 64, 13 | ); 14 | expect(value, isNotNull); 15 | expect( 16 | value, 17 | "https://cdn.discordapp.com/avatars/131492741409538048/64d4f5dfcb00059794c20f656cb19c2b.png?size=64", 18 | ); 19 | }); 20 | }); 21 | } 22 | --------------------------------------------------------------------------------