├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── SUPPORT.md ├── .gitignore ├── .pre-commit-config.yaml ├── AUTHORS ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Jenkinsfile ├── LICENSE ├── README.md ├── api ├── account │ ├── account_api │ │ ├── __init__.py │ │ ├── api.py │ │ └── endpoints │ │ │ ├── __init__.py │ │ │ ├── change_email_address.py │ │ │ ├── change_password.py │ │ │ ├── city.py │ │ │ ├── country.py │ │ │ ├── defaults.py │ │ │ ├── device.py │ │ │ ├── device_count.py │ │ │ ├── geography.py │ │ │ ├── membership.py │ │ │ ├── pairing_code.py │ │ │ ├── preferences.py │ │ │ ├── region.py │ │ │ ├── skill_oauth.py │ │ │ ├── skill_settings.py │ │ │ ├── skills.py │ │ │ ├── software_update.py │ │ │ ├── ssh_key_validator.py │ │ │ ├── timezone.py │ │ │ ├── verify_email_address.py │ │ │ ├── voice_endpoint.py │ │ │ └── wake_word_endpoint.py │ ├── poetry.lock │ ├── pyproject.toml │ ├── tests │ │ └── features │ │ │ ├── add_device.feature │ │ │ ├── agreements.feature │ │ │ ├── authentication.feature │ │ │ ├── environment.py │ │ │ ├── pantacor_update.feature │ │ │ ├── profile.feature │ │ │ ├── remove_account.feature │ │ │ └── steps │ │ │ ├── add_device.py │ │ │ ├── agreements.py │ │ │ ├── authentication.py │ │ │ ├── common.py │ │ │ ├── pantacor_update.py │ │ │ ├── profile.py │ │ │ └── remove_account.py │ └── uwsgi.ini ├── market │ ├── market_api │ │ ├── __init__.py │ │ ├── api.py │ │ └── endpoints │ │ │ ├── __init__.py │ │ │ ├── available_skills.py │ │ │ ├── skill_detail.py │ │ │ ├── skill_install.py │ │ │ └── skill_install_status.py │ ├── poetry.lock │ ├── pyproject.toml │ ├── swagger.yaml │ └── uwsgi.ini ├── precise │ ├── poetry.lock │ ├── precise_api │ │ ├── __init__.py │ │ ├── api.py │ │ └── endpoints │ │ │ ├── __init__.py │ │ │ ├── audio_file.py │ │ │ ├── designation.py │ │ │ └── tag.py │ ├── pyproject.toml │ └── uwsgi.ini ├── public │ ├── __init__.py │ ├── poetry.lock │ ├── public_api │ │ ├── __init__.py │ │ ├── api.py │ │ └── endpoints │ │ │ ├── __init__.py │ │ │ ├── audio_transcription.py │ │ │ ├── device.py │ │ │ ├── device_activate.py │ │ │ ├── device_code.py │ │ │ ├── device_email.py │ │ │ ├── device_location.py │ │ │ ├── device_metrics.py │ │ │ ├── device_oauth.py │ │ │ ├── device_pantacor.py │ │ │ ├── device_refresh_token.py │ │ │ ├── device_setting.py │ │ │ ├── device_skill.py │ │ │ ├── device_skill_manifest.py │ │ │ ├── device_skill_settings.py │ │ │ ├── device_subscription.py │ │ │ ├── geolocation.py │ │ │ ├── google_stt.py │ │ │ ├── oauth_callback.py │ │ │ ├── open_weather_map.py │ │ │ ├── premium_voice.py │ │ │ ├── stripe_webhook.py │ │ │ ├── wake_word_file.py │ │ │ ├── wolfram_alpha.py │ │ │ ├── wolfram_alpha_simple.py │ │ │ ├── wolfram_alpha_spoken.py │ │ │ └── wolfram_alpha_v2.py │ ├── pyproject.toml │ ├── tests │ │ └── features │ │ │ ├── device_email.feature │ │ │ ├── device_location.feature │ │ │ ├── device_metrics.feature │ │ │ ├── device_pairing.feature │ │ │ ├── device_refresh_token.feature │ │ │ ├── device_skill_manifest.feature │ │ │ ├── device_skill_settings.feature │ │ │ ├── device_subscription.feature │ │ │ ├── environment.py │ │ │ ├── get_device.feature │ │ │ ├── get_device_settings.feature │ │ │ ├── steps │ │ │ ├── common.py │ │ │ ├── device_email.py │ │ │ ├── device_location.py │ │ │ ├── device_metrics.py │ │ │ ├── device_pairing.py │ │ │ ├── device_refresh_token.py │ │ │ ├── device_skill_manifest.py │ │ │ ├── device_skill_settings.py │ │ │ ├── get_device.py │ │ │ ├── get_device_settings.py │ │ │ ├── get_device_subscription.py │ │ │ ├── resources │ │ │ │ ├── test_stt.flac │ │ │ │ └── wake_word_test.wav │ │ │ ├── transcribe_audio.py │ │ │ ├── wake_word_file.py │ │ │ └── wolfram_alpha.py │ │ │ ├── transcribe_audio.feature │ │ │ ├── wake_word_file_upload.feature │ │ │ └── wolfram_alpha.feature │ └── uwsgi.ini └── sso │ ├── Dockerfile │ ├── poetry.lock │ ├── pyproject.toml │ ├── sso_api │ ├── __init__.py │ ├── api.py │ └── endpoints │ │ ├── __init__.py │ │ ├── authenticate_internal.py │ │ ├── github_token.py │ │ ├── logout.py │ │ ├── password_change.py │ │ ├── password_reset.py │ │ ├── validate_federated.py │ │ └── validate_token.py │ ├── tests │ └── features │ │ ├── add_account.feature │ │ ├── agreements.feature │ │ ├── environment.py │ │ ├── federated_login.feature │ │ ├── internal_login.feature │ │ ├── logout.feature │ │ ├── password_change.feature │ │ └── steps │ │ ├── add_account.py │ │ ├── agreements.py │ │ ├── common.py │ │ ├── login.py │ │ ├── logout.py │ │ └── password_change.py │ └── uwsgi.ini ├── batch ├── job_scheduler │ ├── __init__.py │ └── jobs.py ├── poetry.lock ├── pyproject.toml └── script │ ├── __init__.py │ ├── daily_report.py │ ├── delete_wake_word_files.py │ ├── designate_wake_word_files.py │ ├── load_skill_display_data.py │ ├── move_wake_word_files.py │ ├── parse_core_metrics.py │ ├── partition_api_metrics.py │ ├── test_scheduler.py │ └── update_device_last_contact.py ├── db ├── mycroft │ ├── account_schema │ │ ├── create_schema.sql │ │ ├── data │ │ │ └── membership.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── account.sql │ │ │ ├── account_agreement.sql │ │ │ ├── account_membership.sql │ │ │ ├── agreement.sql │ │ │ └── membership.sql │ ├── create_extensions.sql │ ├── create_mycroft_db.sql │ ├── create_roles.sql │ ├── create_template_db.sql │ ├── device_schema │ │ ├── create_schema.sql │ │ ├── data │ │ │ └── text_to_speech.sql │ │ ├── get_device_defaults_for_city.sql │ │ ├── get_device_geographies_for_city.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── account_defaults.sql │ │ │ ├── account_preferences.sql │ │ │ ├── category.sql │ │ │ ├── device.sql │ │ │ ├── device_skill.sql │ │ │ ├── geography.sql │ │ │ ├── pantacor_config.sql │ │ │ ├── skill_setting.sql │ │ │ ├── text_to_speech.sql │ │ │ ├── wake_word.sql │ │ │ └── wake_word_settings.sql │ ├── drop_extensions.sql │ ├── drop_mycroft_db.sql │ ├── drop_roles.sql │ ├── drop_template_db.sql │ ├── geography_schema │ │ ├── create_schema.sql │ │ ├── delete_duplicate_cities.sql │ │ ├── get_duplicated_cities.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── city.sql │ │ │ ├── country.sql │ │ │ ├── region.sql │ │ │ └── timezone.sql │ ├── metric_schema │ │ ├── create_schema.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── account_activity.sql │ │ │ ├── api.sql │ │ │ ├── api_history.sql │ │ │ ├── core.sql │ │ │ ├── core_interaction.sql │ │ │ ├── job.sql │ │ │ ├── stt_engine.sql │ │ │ └── stt_transcription.sql │ ├── skill_schema │ │ ├── create_schema.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── display.sql │ │ │ ├── oauth_credential.sql │ │ │ ├── oauth_token.sql │ │ │ ├── settings_display.sql │ │ │ └── skill.sql │ ├── tagging_schema │ │ ├── create_schema.sql │ │ ├── grants.sql │ │ └── tables │ │ │ ├── file_location.sql │ │ │ ├── session.sql │ │ │ ├── tag.sql │ │ │ ├── tag_value.sql │ │ │ ├── tagger.sql │ │ │ ├── wake_word_file.sql │ │ │ ├── wake_word_file_designation.sql │ │ │ └── wake_word_file_tag.sql │ ├── types │ │ ├── agreement_enum.sql │ │ ├── cateogory_enum.sql │ │ ├── core_version_enum.sql │ │ ├── date_format_enum.sql │ │ ├── measurement_system_enum.sql │ │ ├── membership_type_enum.sql │ │ ├── payment_method_enum.sql │ │ ├── tagger_type_enum.sql │ │ ├── tagging_file_origin_enum.sql │ │ ├── tagging_file_status_enum.sql │ │ ├── time_format_enum.sql │ │ └── tts_engine_enum.sql │ ├── versions │ │ └── 2020.9.1.sql │ └── wake_word_schema │ │ ├── create_schema.sql │ │ ├── grants.sql │ │ └── tables │ │ ├── pocketsphinx_settings.sql │ │ └── wake_word.sql ├── poetry.lock ├── pyproject.toml └── scripts │ ├── __init__.py │ ├── bootstrap_mycroft_db.py │ ├── neo4j-postgres.py │ ├── queries.cypher │ └── remove_duplicate_cities.py └── shared ├── Dockerfile ├── MANIFEST.in ├── poetry.lock ├── pyproject.toml ├── selene ├── __init__.py ├── api │ ├── __init__.py │ ├── base_config.py │ ├── base_endpoint.py │ ├── blueprint.py │ ├── endpoints │ │ ├── __init__.py │ │ ├── account.py │ │ ├── agreements.py │ │ ├── password_change.py │ │ └── validate_email.py │ ├── etag.py │ ├── pantacor.py │ ├── public_endpoint.py │ └── response.py ├── batch │ ├── __init__.py │ └── base.py ├── data │ ├── __init__.py │ ├── account │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── account.py │ │ │ ├── agreement.py │ │ │ ├── membership.py │ │ │ └── skill.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── account.py │ │ │ ├── agreement.py │ │ │ ├── membership.py │ │ │ ├── skill.py │ │ │ └── sql │ │ │ ├── add_account.sql │ │ │ ├── add_account_agreement.sql │ │ │ ├── add_account_membership.sql │ │ │ ├── add_agreement.sql │ │ │ ├── add_membership.sql │ │ │ ├── change_email_address.sql │ │ │ ├── change_password.sql │ │ │ ├── daily_report.sql │ │ │ ├── delete_agreement.sql │ │ │ ├── delete_membership.sql │ │ │ ├── end_membership.sql │ │ │ ├── expire_account_agreement.sql │ │ │ ├── expire_agreement.sql │ │ │ ├── get_account.sql │ │ │ ├── get_account_by_device_id.sql │ │ │ ├── get_account_skills.sql │ │ │ ├── get_active_membership_by_account_id.sql │ │ │ ├── get_active_membership_by_payment_account_id.sql │ │ │ ├── get_agreement_content_id.sql │ │ │ ├── get_current_agreements.sql │ │ │ ├── get_membership_by_type.sql │ │ │ ├── get_membership_types.sql │ │ │ ├── remove_account.sql │ │ │ ├── update_last_activity_ts.sql │ │ │ └── update_username.sql │ ├── device │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── default.py │ │ │ ├── device.py │ │ │ ├── device_skill.py │ │ │ ├── geography.py │ │ │ ├── preference.py │ │ │ └── text_to_speech.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── default.py │ │ │ ├── device.py │ │ │ ├── device_skill.py │ │ │ ├── geography.py │ │ │ ├── preference.py │ │ │ ├── setting.py │ │ │ ├── sql │ │ │ ├── add_device.sql │ │ │ ├── add_geography.sql │ │ │ ├── add_manifest_skill.sql │ │ │ ├── add_text_to_speech.sql │ │ │ ├── delete_device_skill.sql │ │ │ ├── get_account_defaults.sql │ │ │ ├── get_account_device_count.sql │ │ │ ├── get_account_geographies.sql │ │ │ ├── get_account_preferences.sql │ │ │ ├── get_all_device_ids.sql │ │ │ ├── get_device_by_id.sql │ │ │ ├── get_device_settings_by_device_id.sql │ │ │ ├── get_device_skill_manifest.sql │ │ │ ├── get_devices_by_account_id.sql │ │ │ ├── get_location_by_device_id.sql │ │ │ ├── get_open_dataset_agreement_by_device_id.sql │ │ │ ├── get_settings_display_usage.sql │ │ │ ├── get_skill_manifest_for_account.sql │ │ │ ├── get_skill_settings_for_account.sql │ │ │ ├── get_skill_settings_for_device.sql │ │ │ ├── get_voices.sql │ │ │ ├── remove_device.sql │ │ │ ├── remove_manifest_skill.sql │ │ │ ├── remove_text_to_speech.sql │ │ │ ├── update_device_from_account.sql │ │ │ ├── update_device_from_core.sql │ │ │ ├── update_device_skill_settings.sql │ │ │ ├── update_last_contact_ts.sql │ │ │ ├── update_pantacor_config.sql │ │ │ ├── update_skill_manifest.sql │ │ │ ├── update_skill_settings.sql │ │ │ ├── upsert_defaults.sql │ │ │ ├── upsert_device_skill_settings.sql │ │ │ ├── upsert_pantacor_config.sql │ │ │ └── upsert_preferences.sql │ │ │ └── text_to_speech.py │ ├── geography │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── city.py │ │ │ ├── country.py │ │ │ ├── region.py │ │ │ └── timezone.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── city.py │ │ │ ├── country.py │ │ │ ├── region.py │ │ │ ├── sql │ │ │ ├── get_biggest_city_in_country.sql │ │ │ ├── get_biggest_city_in_region.sql │ │ │ ├── get_cities_by_region.sql │ │ │ ├── get_countries.sql │ │ │ ├── get_geographic_location_by_city.sql │ │ │ ├── get_regions_by_country.sql │ │ │ └── get_timezones_by_country.sql │ │ │ └── timezone.py │ ├── metric │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── account_activity.py │ │ │ ├── api.py │ │ │ ├── core.py │ │ │ ├── job.py │ │ │ └── stt.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── account_activity.py │ │ │ ├── api.py │ │ │ ├── core.py │ │ │ ├── job.py │ │ │ ├── sql │ │ │ ├── add_account_activity.sql │ │ │ ├── add_api_metric.sql │ │ │ ├── add_core_interaction.sql │ │ │ ├── add_core_metric.sql │ │ │ ├── add_job_metric.sql │ │ │ ├── add_tts_transcription_metric.sql │ │ │ ├── create_api_metric_partition.sql │ │ │ ├── create_api_metric_partition_index.sql │ │ │ ├── delete_account_activity_date.sql │ │ │ ├── delete_api_metrics_by_date.sql │ │ │ ├── delete_stt_transcription_by_date.sql │ │ │ ├── get_account_activity_by_date.sql │ │ │ ├── get_api_metrics_for_date.sql │ │ │ ├── get_core_metric_by_device.sql │ │ │ ├── get_core_timing_metrics_by_date.sql │ │ │ ├── get_tts_transcription_by_account.sql │ │ │ ├── increment_accounts_added.sql │ │ │ ├── increment_accounts_deleted.sql │ │ │ ├── increment_activity.sql │ │ │ ├── increment_members_added.sql │ │ │ ├── increment_members_expired.sql │ │ │ ├── increment_open_dataset_added.sql │ │ │ └── increment_open_dataset_deleted.sql │ │ │ └── stt.py │ ├── repository_base.py │ ├── skill │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── display.py │ │ │ ├── skill.py │ │ │ └── skill_setting.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── display.py │ │ │ ├── setting.py │ │ │ ├── settings_display.py │ │ │ ├── skill.py │ │ │ └── sql │ │ │ ├── add_device_skill.sql │ │ │ ├── add_settings_display.sql │ │ │ ├── add_skill.sql │ │ │ ├── delete_device_skill.sql │ │ │ ├── delete_settings_display.sql │ │ │ ├── get_display_data_for_skill.sql │ │ │ ├── get_display_data_for_skills.sql │ │ │ ├── get_settings_definition_by_gid.sql │ │ │ ├── get_settings_display_id.sql │ │ │ ├── get_settings_for_skill_family.sql │ │ │ ├── get_skill_by_global_id.sql │ │ │ ├── get_skill_setting_by_device.sql │ │ │ ├── get_skills_for_account.sql │ │ │ ├── remove_skill_by_gid.sql │ │ │ ├── update_device_skill_settings.sql │ │ │ └── upsert_skill_display_data.sql │ ├── tagging │ │ ├── __init__.py │ │ ├── entity │ │ │ ├── __init__.py │ │ │ ├── file_designation.py │ │ │ ├── file_location.py │ │ │ ├── file_tag.py │ │ │ ├── tag.py │ │ │ ├── tag_value.py │ │ │ ├── tagger.py │ │ │ └── wake_word_file.py │ │ └── repository │ │ │ ├── __init__.py │ │ │ ├── file_designation.py │ │ │ ├── file_location.py │ │ │ ├── file_tag.py │ │ │ ├── session.py │ │ │ ├── sql │ │ │ ├── add_file_location.sql │ │ │ ├── add_session.sql │ │ │ ├── add_tagger.sql │ │ │ ├── add_tagging_session.sql │ │ │ ├── add_wake_word_file.sql │ │ │ ├── add_wake_word_file_designation.sql │ │ │ ├── add_wake_word_file_tag.sql │ │ │ ├── change_account_file_status.sql │ │ │ ├── change_file_location.sql │ │ │ ├── change_file_status.sql │ │ │ ├── get_active_session.sql │ │ │ ├── get_designation_candidates.sql │ │ │ ├── get_designations_from_date.sql │ │ │ ├── get_file_location_id.sql │ │ │ ├── get_taggable_wake_word_file.sql │ │ │ ├── get_tagger_by_entity.sql │ │ │ ├── get_tags.sql │ │ │ ├── get_wake_word_files.sql │ │ │ ├── remove_file_location.sql │ │ │ ├── remove_wake_word_file.sql │ │ │ └── update_session_end_ts.sql │ │ │ ├── tag.py │ │ │ ├── tagger.py │ │ │ └── wake_word_file.py │ └── wake_word │ │ ├── __init__.py │ │ ├── entity │ │ ├── __init__.py │ │ ├── pocketsphinx_settings.py │ │ └── wake_word.py │ │ └── repository │ │ ├── __init__.py │ │ ├── sql │ │ ├── add_wake_word.sql │ │ ├── get_wake_word_id.sql │ │ ├── get_wake_words_for_web.sql │ │ └── remove_wake_word.sql │ │ └── wake_word.py ├── testing │ ├── __init__.py │ ├── account.py │ ├── account_activity.py │ ├── account_geography.py │ ├── account_preference.py │ ├── agreement.py │ ├── api.py │ ├── device.py │ ├── device_skill.py │ ├── membership.py │ ├── skill.py │ ├── tagging.py │ ├── test_db.py │ ├── text_to_speech.py │ └── wake_word.py └── util │ ├── __init__.py │ ├── auth.py │ ├── cache.py │ ├── db │ ├── __init__.py │ ├── connection.py │ ├── connection_pool.py │ ├── cursor.py │ └── transaction.py │ ├── email │ ├── __init__.py │ ├── email.py │ └── templates │ │ ├── account_not_found.html │ │ ├── base.html │ │ ├── email_change.html │ │ ├── email_verification.html │ │ ├── metrics.html │ │ ├── password_change.html │ │ └── reset_password.html │ ├── exceptions.py │ ├── github.py │ ├── log.py │ ├── payment │ ├── __init__.py │ └── stripe.py │ └── ssh │ ├── __init__.py │ ├── sftp.py │ └── ssh.py └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | # Matches multiple files with brace expansion notation 10 | # Set default charset 11 | [*.{py}] 12 | charset = utf-8 13 | 14 | # 4 space indentation 15 | [*.py] 16 | indent_style = space 17 | indent_size = 4 18 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | (Description of what the PR does, such as fixes # {issue number}) 3 | 4 | ## How to test 5 | (Description of how to validate or test this PR) 6 | 7 | ## Contributor license agreement signed? 8 | CLA [ ] (Whether you have signed a [CLA - Contributor Licensing Agreement](https://mycroft.ai/cla/) 9 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # How to get support with Mycroft software, hardware and products 2 | 3 | There are multiple ways to seek support with Mycroft software, hardware and products. 4 | 5 | ## Forum 6 | 7 | We maintain a [Forum](https://community.mycroft.ai) which is regularly monitored. 8 | Feel free to post questions, bugs, and requests for assistance in the relevant Forum Topic. 9 | 10 | ## Chat 11 | 12 | Mycroft staff are regularly available in our [Chat](https://chat.mycroft.ai) platform. 13 | There are specific rooms available for different projects and products. 14 | 15 | ## Contact 16 | 17 | You can contact us via [our online form](https://mycroft.ai/contact), or give a call. 18 | 19 | ## GitHub 20 | 21 | We welcome you raising Issues and Pull Requests on our public GitHub repositories. 22 | See the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information. 23 | 24 | ## Helping us to help you 25 | 26 | Our [documentation](https://mycroft.ai/documentation/troubleshooting/) contains troubleshooting information, and information on log files and other files that we may need to help us help you. 27 | 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | **/*.egg-info 8 | 9 | # dependencies 10 | **/node_modules 11 | 12 | # python notebooks 13 | *.ipynb 14 | 15 | # IDEs and editors 16 | **/.idea 17 | .project 18 | .classpath 19 | .c9/ 20 | *.launch 21 | .settings/ 22 | *.sublime-workspace 23 | __pycache__/ 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | 32 | # misc 33 | /.sass-cache 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | npm-debug.log 38 | yarn-error.log 39 | testem.log 40 | /typings 41 | 42 | # System Files 43 | .DS_Store 44 | Thumbs.db 45 | 46 | 47 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v2.3.0 4 | hooks: 5 | - id: check-yaml 6 | - id: end-of-file-fixer 7 | - id: trailing-whitespace 8 | - repo: https://github.com/psf/black 9 | rev: 22.3.0 10 | hooks: 11 | - id: black 12 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The Mycroft Server was initially developed by Mycroft AI Inc 2 | 3 | It lives on as an open source project with many contributors, a self-updating 4 | list is at: https://github.com/mycroftai/selene-backend/graphs/contributors -------------------------------------------------------------------------------- /api/account/account_api/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/account/account_api/endpoints/country.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from http import HTTPStatus 21 | 22 | from selene.api import SeleneEndpoint 23 | from selene.data.geography import CountryRepository 24 | 25 | 26 | class CountryEndpoint(SeleneEndpoint): 27 | def get(self): 28 | country_repository = CountryRepository(self.db) 29 | countries = country_repository.get_countries() 30 | 31 | return countries, HTTPStatus.OK 32 | -------------------------------------------------------------------------------- /api/account/account_api/endpoints/region.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from http import HTTPStatus 21 | 22 | from selene.api import SeleneEndpoint 23 | from selene.data.geography import RegionRepository 24 | 25 | 26 | class RegionEndpoint(SeleneEndpoint): 27 | def get(self): 28 | country_id = self.request.args["country"] 29 | region_repository = RegionRepository(self.db) 30 | regions = region_repository.get_regions_by_country(country_id) 31 | 32 | return regions, HTTPStatus.OK 33 | -------------------------------------------------------------------------------- /api/account/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "account" 3 | version = "0.1.0" 4 | description = "API to support account.mycroft.ai" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | # Version 1.0 of flask required because later versions do not allow lists to be passed as API repsonses. The Google 11 | # STT endpoint passes a list of transcriptions to the device. Changing this to return a dictionary would break the 12 | # API's V1 contract with Mycroft Core. 13 | # 14 | # To make flask 1.0 work, older versions of itsdangerous, jinja2, markupsafe and werkszeug are required. 15 | flask = "<1.1" 16 | itsdangerous = "<=2.0.1" 17 | jinja2 = "<=2.10.1" 18 | markupsafe = "<=2.0.1" 19 | schematics = "*" 20 | stripe = "*" 21 | selene = {path = "./../../shared", develop = true} 22 | uwsgi = "*" 23 | werkzeug = "<=2.0.3" 24 | 25 | [tool.poetry.dev-dependencies] 26 | allure-behave = "*" 27 | behave = "*" 28 | pyhamcrest = "*" 29 | pylint = "*" 30 | 31 | [build-system] 32 | requires = ["poetry-core>=1.0.0"] 33 | build-backend = "poetry.core.masonry.api" 34 | -------------------------------------------------------------------------------- /api/account/tests/features/add_device.feature: -------------------------------------------------------------------------------- 1 | Feature: Account API -- Pair a device 2 | Test the device add endpoint 3 | 4 | Scenario: Add a device 5 | Given an account 6 | And the account is authenticated 7 | And a device pairing code 8 | When an API request is sent to add a device 9 | Then the request will be successful 10 | And the device is added to the database 11 | And the pairing code is removed from cache 12 | And the pairing token is added to cache 13 | -------------------------------------------------------------------------------- /api/account/tests/features/agreements.feature: -------------------------------------------------------------------------------- 1 | Feature: Account API -- Get the active agreements 2 | We need to be able to retrieve an agreement and display it on the web app. 3 | 4 | Scenario: Multiple versions of an agreement exist 5 | When API request for Privacy Policy is made 6 | Then the request will be successful 7 | And Privacy Policy version 999 is returned 8 | 9 | 10 | Scenario: Retrieve Terms of Use 11 | When API request for Terms of Use is made 12 | Then the request will be successful 13 | And Terms of Use version 999 is returned 14 | -------------------------------------------------------------------------------- /api/account/tests/features/remove_account.feature: -------------------------------------------------------------------------------- 1 | Feature: Account API -- Delete an account 2 | Test the API call to delete an account and all its related data from the database. 3 | 4 | Scenario: Successful account deletion 5 | Given an account 6 | And the account is authenticated 7 | When a user requests to delete their account 8 | Then the request will be successful 9 | And the user's account is deleted 10 | And the deleted account will be reflected in the account activity metrics 11 | 12 | Scenario: Membership removed upon account deletion 13 | Given an account with a monthly membership 14 | When a user requests to delete their account 15 | Then the request will be successful 16 | And the membership is removed from stripe 17 | 18 | Scenario: Wake word files removed upon account deletion 19 | Given an account opted into the Open Dataset agreement 20 | And a wake word sample contributed by the user 21 | And the account is authenticated 22 | When a user requests to delete their account 23 | Then the request will be successful 24 | And the wake word contributions are flagged for deletion 25 | -------------------------------------------------------------------------------- /api/account/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | master = true 3 | module = account_api.api:acct 4 | processes = 4 5 | socket = :5000 6 | die-on-term = true 7 | lazy = true 8 | lazy-apps = true 9 | -------------------------------------------------------------------------------- /api/market/market_api/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/market/market_api/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .available_skills import AvailableSkillsEndpoint 21 | from .skill_detail import SkillDetailEndpoint 22 | from .skill_install import SkillInstallEndpoint 23 | from .skill_install_status import SkillInstallStatusEndpoint 24 | -------------------------------------------------------------------------------- /api/market/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "market" 3 | version = "0.1.0" 4 | description = "API for Mycroft Marketplace" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | flask = "*" 11 | requests = "*" 12 | pyjwt = "*" 13 | uwsgi = "*" 14 | markdown = "*" 15 | selene = {path = "./../../shared", develop = true} 16 | 17 | [tool.poetry.dev-dependencies] 18 | behave = "*" 19 | pyhamcrest = "*" 20 | allure-behave = "*" 21 | pylint = "*" 22 | 23 | [build-system] 24 | requires = ["poetry-core>=1.0.0"] 25 | build-backend = "poetry.core.masonry.api" 26 | -------------------------------------------------------------------------------- /api/market/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | master = true 3 | module = market_api.api:market 4 | processes = 4 5 | socket = :5000 6 | die-on-term = true 7 | lazy = true 8 | lazy-apps = true 9 | -------------------------------------------------------------------------------- /api/precise/precise_api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MycroftAI/selene-backend/e10ac91cde6bf6097ae7eafe3fcb6c1b1d292f70/api/precise/precise_api/__init__.py -------------------------------------------------------------------------------- /api/precise/precise_api/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API into the Precise API endpoint package.""" 20 | 21 | from .audio_file import AudioFileEndpoint 22 | from .designation import DesignationEndpoint 23 | from .tag import TagEndpoint 24 | -------------------------------------------------------------------------------- /api/precise/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "precise" 3 | version = "0.1.0" 4 | description = "API for Precise wake word tagger" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | flask = "*" 11 | selene = {path = "./../../shared", develop = true} 12 | uwsgi = "*" 13 | 14 | [tool.poetry.dev-dependencies] 15 | behave = "*" 16 | pyhamcrest = "*" 17 | pylint = "*" 18 | black = "*" 19 | 20 | [build-system] 21 | requires = ["poetry-core>=1.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | -------------------------------------------------------------------------------- /api/precise/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | master = true 3 | module = precise_api.api:precise 4 | processes = 4 5 | socket = :5000 6 | die-on-term = true 7 | lazy = true 8 | lazy-apps = true 9 | -------------------------------------------------------------------------------- /api/public/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/public/public_api/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/public/public_api/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/public/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "public" 3 | version = "0.1.0" 4 | description = "API for interactions between Selene and Mycroft devices" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | # Version 1.0 of flask required because later versions do not allow lists to be passed as API repsonses. The Google 11 | # STT endpoint passes a list of transcriptions to the device. Changing this to return a dictionary would break the 12 | # API's V1 contract with Mycroft Core. 13 | # 14 | # To make flask 1.0 work, older versions of itsdangerous, jinja2, markupsafe and werkszeug are required. 15 | flask = "<1.1" 16 | google-cloud-speech = "^2.15.1" 17 | itsdangerous = "<=2.0.1" 18 | jinja2 = "<=2.10.1" 19 | markupsafe = "<=2.0.1" 20 | requests = "*" 21 | selene = {path = "./../../shared", develop = true} 22 | SpeechRecognition = "*" 23 | stripe = "*" 24 | uwsgi = "*" 25 | werkzeug = "<=2.0.3" 26 | librosa = "^0.9.2" 27 | numpy = "<=1.22" 28 | 29 | 30 | [tool.poetry.dev-dependencies] 31 | allure-behave = "*" 32 | black = "*" 33 | pyhamcrest = "*" 34 | pylint = "*" 35 | behave = "^1.2.6" 36 | 37 | [build-system] 38 | requires = ["poetry-core>=1.0.0"] 39 | build-backend = "poetry.core.masonry.api" 40 | -------------------------------------------------------------------------------- /api/public/tests/features/device_email.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Send email to the account holder 2 | Some skills have the ability to send email upon request. One example of 3 | this is the support skill, which emails device diagnostics. 4 | 5 | Scenario: Email sent to account holder 6 | When a user interaction with a device causes an email to be sent 7 | Then the request will be successful 8 | And an email should be sent to the account that owns the device 9 | And the device's last contact time is updated 10 | 11 | Scenario: Email request sent by unauthorized device 12 | When an unpaired or unauthenticated device attempts to send an email 13 | Then the request will fail with an unauthorized error 14 | -------------------------------------------------------------------------------- /api/public/tests/features/device_location.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Request device location 2 | 3 | Scenario: Location is successfully retrieved from a device 4 | When a api call to get the location is done 5 | Then the location should be retrieved 6 | And the device's last contact time is updated 7 | 8 | Scenario: Try to get a location using an expired etag 9 | Given an expired etag from a location entity 10 | When try to get the location using the expired etag 11 | Then the location should be retrieved 12 | And an etag associated with the location should be created 13 | And the device's last contact time is updated 14 | 15 | Scenario: Try to get a location using a valid etag 16 | Given a valid etag from a location entity 17 | When try to get the location using a valid etag 18 | Then the location endpoint should return 304 19 | And the device's last contact time is updated 20 | -------------------------------------------------------------------------------- /api/public/tests/features/device_metrics.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Save device activity metrics 2 | 3 | Scenario: User opted into the open dataset uses their device 4 | Given a device registered to a user opted into the open dataset 5 | When someone issues a voice command to the device 6 | Then usage metrics are saved to the database 7 | And the device's last contact time is updated 8 | And the account's last activity time is updated 9 | And the account activity metrics will be updated 10 | 11 | Scenario: Metric endpoint fails for unauthorized device 12 | Given a non-existent device 13 | When someone issues a voice command to the device 14 | Then the request will fail with an unauthorized error 15 | And the device's last contact time is updated 16 | -------------------------------------------------------------------------------- /api/public/tests/features/device_pairing.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Pair a device 2 | Test the device pairing workflow 3 | 4 | Scenario: Pairing code generation 5 | When a device requests a pairing code 6 | Then the request will be successful 7 | And the pairing data is stored in Redis 8 | And the pairing data is sent to the device 9 | 10 | Scenario: Device activation 11 | Given the user completes the pairing process on the web application 12 | When the device requests to be activated 13 | Then the request will be successful 14 | And the activation data is sent to the device 15 | And the device attributes are stored in the database 16 | 17 | Scenario: Pantacor device configuration sync 18 | Given an authorized device 19 | When Pantacor has claimed the device 20 | And a device requests to sync with Pantacor 21 | Then the request will be successful 22 | And the Pantacor device configuration is stored in the database 23 | 24 | Scenario: Pantacor device not claimed 25 | Given an authorized device 26 | When Pantacor has not yet claimed the device 27 | And a device requests to sync with Pantacor 28 | Then the request will fail with a precondition required error 29 | -------------------------------------------------------------------------------- /api/public/tests/features/device_refresh_token.feature: -------------------------------------------------------------------------------- 1 | #Feature: Refresh device token 2 | # Test the endpoint used to refresh the device session login 3 | # 4 | # Scenario: A valid login session is returned after the refreshing token is performed 5 | # Given a device pairing code 6 | # When a device is added to an account using the pairing code 7 | # And device is activated 8 | # And the session token is refreshed 9 | # Then a valid new session entity should be returned 10 | # 11 | # Scenario: An error status code is returned after trying to refresh an invalid token 12 | # When try to refresh an invalid refresh token 13 | # Then 401 status code should be returned 14 | -------------------------------------------------------------------------------- /api/public/tests/features/device_subscription.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Request account subscription type 2 | Test the endpoint used to fetch the subscription type of a device 3 | 4 | Scenario: User has a free subscription 5 | When the subscription endpoint is called 6 | Then free type should be returned 7 | And the device's last contact time is updated 8 | 9 | Scenario: User has a monthly subscription 10 | When the subscription endpoint is called for a monthly account 11 | Then monthly type should be returned 12 | And the device's last contact time is updated 13 | 14 | Scenario: The endpoint is called to a nonexistent device 15 | When try to get the subscription for a nonexistent device 16 | Then 401 status code should be returned for the subscription endpoint 17 | And the device's last contact time is updated 18 | -------------------------------------------------------------------------------- /api/public/tests/features/get_device_settings.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Request device settings 2 | Test the endpoint used to fetch the settings from a device 3 | 4 | Scenario: Device's setting is returned 5 | When try to fetch device's setting 6 | Then a valid setting should be returned 7 | And the device's last contact time is updated 8 | 9 | Scenario: Try to get the settings from a not allowed device 10 | When the settings endpoint is a called to a not allowed device 11 | Then a 401 status code should be returned for the setting 12 | And the device's last contact time is updated 13 | 14 | Scenario: Try to get the device's settings using a valid etag 15 | Given a device's setting with a valid etag 16 | When try to fetch the device's settings using a valid etag 17 | Then 304 status code should be returned by the device's settings endpoint 18 | And the device's last contact time is updated 19 | 20 | Scenario: Try to get a device's settings using a expired etag 21 | Given a device's setting etag expired by the web ui at device level 22 | When try to fetch the device's settings using an expired etag 23 | Then 200 status code should be returned by the device's setting endpoint and a new etag 24 | And the device's last contact time is updated 25 | -------------------------------------------------------------------------------- /api/public/tests/features/steps/resources/test_stt.flac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MycroftAI/selene-backend/e10ac91cde6bf6097ae7eafe3fcb6c1b1d292f70/api/public/tests/features/steps/resources/test_stt.flac -------------------------------------------------------------------------------- /api/public/tests/features/steps/resources/wake_word_test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MycroftAI/selene-backend/e10ac91cde6bf6097ae7eafe3fcb6c1b1d292f70/api/public/tests/features/steps/resources/wake_word_test.wav -------------------------------------------------------------------------------- /api/public/tests/features/transcribe_audio.feature: -------------------------------------------------------------------------------- 1 | Feature: Transcribe audio data 2 | Test the integration with audio transcription service providers 3 | 4 | @stt 5 | Scenario: Transcribe audio using old Google endpoint 6 | When Utterance "what time is it" is transcribed using Google's STT API 7 | Then the request will be successful 8 | And Google's transcription will be correct 9 | And the device's last contact time is updated 10 | And the transcription metrics for will be added to the database 11 | 12 | @stt 13 | Scenario: Transcribe audio using new Google Cloud endpoint 14 | When Utterance "what time is it" is transcribed using Mycroft's transcription service 15 | Then the request will be successful 16 | And the transcription will be returned to the device 17 | And the device's last contact time is updated 18 | And the transcription metrics for will be added to the database 19 | -------------------------------------------------------------------------------- /api/public/tests/features/wake_word_file_upload.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Upload wake word samples 2 | Users that opted in to the Open Dataset Agreement will have files containing the audio that 3 | activated the wake word recognizer uploaded to Mycroft servers for classification and tracking. 4 | 5 | Scenario: Device sends wake word audio file 6 | When the device uploads a wake word file 7 | Then the request will be successful 8 | And the audio file is saved to a temporary directory 9 | And a reference to the sample is stored in the database 10 | 11 | Scenario: Device sends wake word file for an unknown wake word 12 | When the device uploads a wake word file for an unknown wake word 13 | Then the request will be successful 14 | And the audio file is saved to a temporary directory 15 | And a reference to the sample is stored in the database 16 | 17 | Scenario: Device sends wake word file with non-unique hash value 18 | When the hash value of the file being uploaded matches a previous upload 19 | And the device uploads a wake word file 20 | Then the request will be successful 21 | And the audio file is saved to a temporary directory 22 | And a reference to the sample is stored in the database 23 | -------------------------------------------------------------------------------- /api/public/tests/features/wolfram_alpha.feature: -------------------------------------------------------------------------------- 1 | Feature: Device API -- Integration with Wolfram Alpha API 2 | Mycroft Core uses Wolfram Alpha as a "fallback". When a user makes a request 3 | that cannot be satisfied by an installed skill, the fallback system is used to 4 | attempt to answer the query. The device API is used as a proxy to anonymize user 5 | requests. 6 | 7 | Scenario: Mycroft Core fallback system sends query to the Wolfram Alpha 8 | When a question is sent to the Wolfram Alpha full results endpoint 9 | Then the answer provided by Wolfram Alpha is returned 10 | And the device's last contact time is updated 11 | And the account's last activity time is updated 12 | And the account activity metrics will be updated 13 | 14 | Scenario: Question sent to the wolfram alpha simple endpoint 15 | When a question is sent to the wolfram alpha simple endpoint 16 | Then the answer provided by Wolfram Alpha is returned 17 | And the device's last contact time is updated 18 | 19 | Scenario: Question sent to the wolfram alpha spoken endpoint 20 | When a question is sent to the wolfram alpha spoken endpoint 21 | Then the answer provided by Wolfram Alpha is returned 22 | And the device's last contact time is updated 23 | -------------------------------------------------------------------------------- /api/public/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | master = true 3 | module = public_api.api:public 4 | processes = 10 5 | socket = :5000 6 | die-on-term = true 7 | lazy = true 8 | lazy-apps = true 9 | -------------------------------------------------------------------------------- /api/sso/Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker config for the Selene skill service 2 | 3 | # The selene-shared parent image contains all the common Docker configs for 4 | # all Selene apps and services see the "shared" directory in this repository. 5 | FROM docker.mycroft.ai/selene-shared:2018.4 6 | LABEL description="Run the API for the Mycroft login screen" 7 | 8 | # Use pipenv to install the package's dependencies in the container 9 | COPY Pipfile Pipfile 10 | COPY Pipfile.lock Pipfile.lock 11 | RUN pipenv install --system 12 | 13 | # Now that pipenv has installed all the packages required by selene-util 14 | # the Pipfile can be removed from the container. 15 | RUN rm Pipfile 16 | RUN rm Pipfile.lock 17 | 18 | # Load the skill service application to the image 19 | COPY sso_api /opt/selene/sso_api 20 | WORKDIR /opt/selene/ 21 | 22 | EXPOSE 7102 23 | 24 | # Use uwsgi to serve the API 25 | COPY uwsgi.ini uwsgi.ini 26 | ENTRYPOINT ["uwsgi", "--ini", "uwsgi.ini"] -------------------------------------------------------------------------------- /api/sso/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "sso" 3 | version = "0.1.0" 4 | description = "Single Sign on for all Selene applications" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | certifi = "*" 11 | flask = "*" 12 | selene = {path = "./../../shared", develop = true} 13 | uwsgi = "*" 14 | 15 | [tool.poetry.dev-dependencies] 16 | allure-behave = "*" 17 | behave = "*" 18 | black = "*" 19 | pyhamcrest = "*" 20 | pylint = "*" 21 | 22 | [build-system] 23 | requires = ["poetry-core>=1.0.0"] 24 | build-backend = "poetry.core.masonry.api" 25 | -------------------------------------------------------------------------------- /api/sso/sso_api/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /api/sso/sso_api/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API into the Single Sign On API endpoint package.""" 20 | 21 | from .authenticate_internal import AuthenticateInternalEndpoint 22 | from .github_token import GithubTokenEndpoint 23 | from .logout import LogoutEndpoint 24 | from .password_change import PasswordChangeEndpoint 25 | from .password_reset import PasswordResetEndpoint 26 | from .validate_federated import ValidateFederatedEndpoint 27 | from .validate_token import ValidateTokenEndpoint 28 | -------------------------------------------------------------------------------- /api/sso/sso_api/endpoints/github_token.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from http import HTTPStatus 21 | 22 | from selene.api import SeleneEndpoint 23 | from selene.util.auth import get_github_authentication_token 24 | 25 | 26 | class GithubTokenEndpoint(SeleneEndpoint): 27 | def get(self): 28 | token = get_github_authentication_token( 29 | self.request.args["code"], self.request.args["state"] 30 | ) 31 | 32 | return dict(token=token), HTTPStatus.OK 33 | -------------------------------------------------------------------------------- /api/sso/tests/features/agreements.feature: -------------------------------------------------------------------------------- 1 | Feature: Single Sign On API -- Get the active agreements 2 | We need to be able to retrieve an agreement and display it on the web app. 3 | 4 | Scenario: Retrieve Privacy Policy 5 | When API request for Privacy Policy is made 6 | Then the request will be successful 7 | And the current version of the Privacy Policy agreement is returned 8 | 9 | 10 | Scenario: Retrieve Terms of Use 11 | When API request for Terms of Use is made 12 | Then the request will be successful 13 | And the current version of the Terms of Use agreement is returned 14 | -------------------------------------------------------------------------------- /api/sso/tests/features/federated_login.feature: -------------------------------------------------------------------------------- 1 | Feature: Single Sign On API -- Federated login 2 | User signs into a selene web app after authenticating with a 3rd party. 3 | 4 | Scenario: User with existing account signs in via Facebook 5 | Given user "foo@mycroft.ai" authenticates through Facebook 6 | When single sign on validates the account 7 | Then the request will be successful 8 | And response contains authentication tokens 9 | 10 | Scenario: User without account signs in via Facebook 11 | Given user "bar@mycroft.ai" authenticates through Facebook 12 | When single sign on validates the account 13 | Then the request will fail with an unauthorized error 14 | And the response will contain a "no account found for provided email" error message 15 | 16 | Scenario: User with existing account signs in via Google 17 | Given user "foo@mycroft.ai" authenticates through Google 18 | When single sign on validates the account 19 | Then the request will be successful 20 | And response contains authentication tokens 21 | 22 | Scenario: User with existing account signs in via GitHub 23 | Given user "foo@mycroft.ai" authenticates through GitHub 24 | When single sign on validates the account 25 | Then the request will be successful 26 | And response contains authentication tokens 27 | -------------------------------------------------------------------------------- /api/sso/tests/features/internal_login.feature: -------------------------------------------------------------------------------- 1 | Feature: Single Sign On API -- Internal login 2 | User signs into a selene web app with an email address and password (rather 3 | than signing in with a third party authenticator, like Google). 4 | 5 | Scenario: User signs in with valid email/password combination 6 | Given user enters email address "foo@mycroft.ai" and password "foo" 7 | When user attempts to login 8 | Then the request will be successful 9 | And response contains authentication tokens 10 | 11 | Scenario: User signs in with invalid email/password combination 12 | Given user enters email address "foo@mycroft.ai" and password "bar" 13 | When user attempts to login 14 | Then the request will fail with an unauthorized error 15 | And the response will contain a "provided credentials not found" error message 16 | -------------------------------------------------------------------------------- /api/sso/tests/features/logout.feature: -------------------------------------------------------------------------------- 1 | Feature: Single Sign On API -- Logout 2 | Regardless of how a user logs in, logging out consists of expiring the 3 | tokens we use to identify logged-in users. 4 | 5 | Scenario: Logged in user requests logout 6 | Given an authenticated account 7 | When user attempts to logout 8 | Then the request will be successful 9 | And response contains expired token cookies 10 | -------------------------------------------------------------------------------- /api/sso/tests/features/password_change.feature: -------------------------------------------------------------------------------- 1 | Feature: Single Sign On API -- Password reset 2 | The only way a user can change their password in the single sign on application is 3 | through the password reset feature. The user clicks a link in an email sent when a 4 | password reset is requested. The link takes the user to a page where they reset 5 | their password and the change password endpoint is called. 6 | 7 | Scenario: User changes password via the password reset email 8 | Given a user who authenticates with a password 9 | When the user changes their password 10 | And user attempts to login 11 | Then the request will be successful 12 | -------------------------------------------------------------------------------- /api/sso/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | master = true 3 | module = sso_api.api:sso 4 | processes = 4 5 | socket = :5000 6 | die-on-term = true 7 | lazy = true 8 | lazy-apps = true 9 | -------------------------------------------------------------------------------- /batch/job_scheduler/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /batch/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "batch" 3 | version = "0.1.0" 4 | description = "Selene batch scripts and scheduler" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | selene = {path = "./../shared", develop = true} 11 | 12 | [tool.poetry.dev-dependencies] 13 | black = "*" 14 | pylint = "*" 15 | 16 | [build-system] 17 | requires = ["poetry-core>=1.0.0"] 18 | build-backend = "poetry.core.masonry.api" 19 | -------------------------------------------------------------------------------- /batch/script/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store user data 2 | -- took out the "e" in "user" because "user" is a Postgres keyword 3 | CREATE SCHEMA account; 4 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/data/membership.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.membership (type, rate, rate_period, stripe_plan) 3 | VALUES 4 | ('Monthly Membership', 1.99, 'month', 'monthly_premium'), 5 | ('Yearly Membership', 19.99, 'year', 'mycroft_ai_premium_annual_1999') 6 | ; 7 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA account TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA account TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/tables/account.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE account.account ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | email_address text NOT NULL 5 | UNIQUE, 6 | username text 7 | UNIQUE, 8 | password text, 9 | insert_ts TIMESTAMP NOT NULL 10 | DEFAULT CURRENT_TIMESTAMP, 11 | last_activity_ts TIMESTAMP 12 | ); 13 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/tables/account_agreement.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE account.account_agreement ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | account_id uuid NOT NULL REFERENCES account.account ON DELETE CASCADE, 4 | agreement_id uuid NOT NULL REFERENCES account.agreement, 5 | accept_date DATE NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (account_id, agreement_id, accept_date) 8 | ); 9 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/tables/account_membership.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE account.account_membership ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | account_id uuid NOT NULL 5 | REFERENCES account.account ON DELETE CASCADE, 6 | membership_id uuid NOT NULL 7 | REFERENCES account.membership, 8 | membership_ts_range tsrange NOT NULL, 9 | payment_method payment_method_enum NOT NULL, 10 | payment_account_id text NOT NULL, 11 | payment_id text NOT NULL, 12 | insert_ts TIMESTAMP NOT NULL 13 | DEFAULT CURRENT_TIMESTAMP, 14 | EXCLUDE USING gist (account_id WITH =, membership_ts_range with &&), 15 | UNIQUE (account_id, membership_id, membership_ts_range) 16 | ) 17 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/tables/agreement.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE account.agreement ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | agreement agreement_enum NOT NULL, 4 | version text NOT NULL, 5 | effective daterange NOT NULL, 6 | content_id oid, 7 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | EXCLUDE USING gist (agreement WITH =, effective WITH &&), 9 | UNIQUE (agreement, version) 10 | ); 11 | -------------------------------------------------------------------------------- /db/mycroft/account_schema/tables/membership.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE account.membership ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | type membership_type_enum NOT NULL 5 | UNIQUE, 6 | rate NUMERIC NOT NULL, 7 | rate_period text NOT NULL, 8 | stripe_plan text NOT NULL, 9 | insert_ts TIMESTAMP NOT NULL 10 | DEFAULT CURRENT_TIMESTAMP 11 | ); 12 | -------------------------------------------------------------------------------- /db/mycroft/create_extensions.sql: -------------------------------------------------------------------------------- 1 | CREATE EXTENSION pgcrypto; 2 | CREATE EXTENSION btree_gist; -------------------------------------------------------------------------------- /db/mycroft/create_mycroft_db.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE mycroft WITH TEMPLATE mycroft_template OWNER selene; 2 | -------------------------------------------------------------------------------- /db/mycroft/create_roles.sql: -------------------------------------------------------------------------------- 1 | -- create the roles that will be used by selene applications 2 | CREATE ROLE selene WITH SUPERUSER LOGIN ENCRYPTED PASSWORD 'adam'; 3 | -------------------------------------------------------------------------------- /db/mycroft/create_template_db.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE mycroft_template WITH OWNER = selene; 2 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store user data 2 | -- took out the "e" in "user" because "user" is a Postgres keyword 3 | CREATE SCHEMA device; 4 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/data/text_to_speech.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.text_to_speech (setting_name, display_name, engine) 3 | VALUES 4 | ('ap', 'British Male', 'mimic'), 5 | ('amy', 'American Female', 'mimic'), 6 | ('kusal', 'American Male', 'mimic'), 7 | ('google', 'Google Free Voice', 'google') 8 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/get_device_defaults_for_city.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | city_id 4 | FROM 5 | device.account_defaults 6 | WHERE 7 | city_id IN %(city_ids)s 8 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/get_device_geographies_for_city.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | city_id 4 | FROM 5 | device.geography 6 | WHERE 7 | city_id IN %(city_ids)s 8 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA device TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA device TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/account_defaults.sql: -------------------------------------------------------------------------------- 1 | -- Account level preferences that pertain to device function. 2 | CREATE TABLE device.account_defaults ( 3 | id uuid PRIMARY KEY 4 | DEFAULT gen_random_uuid(), 5 | account_id uuid NOT NULL 6 | UNIQUE 7 | REFERENCES account.account ON DELETE CASCADE, 8 | wake_word_id uuid 9 | REFERENCES wake_word.wake_word, 10 | text_to_speech_id uuid 11 | REFERENCES device.text_to_speech, 12 | country_id uuid 13 | REFERENCES geography.country, 14 | region_id uuid 15 | REFERENCES geography.region, 16 | city_id uuid 17 | REFERENCES geography.city, 18 | timezone_id uuid 19 | REFERENCES geography.timezone, 20 | insert_ts TIMESTAMP NOT NULL 21 | DEFAULT CURRENT_TIMESTAMP 22 | 23 | ); 24 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/account_preferences.sql: -------------------------------------------------------------------------------- 1 | -- Account level preferences that pertain to device function. 2 | CREATE TABLE device.account_preferences ( 3 | id uuid PRIMARY KEY 4 | DEFAULT gen_random_uuid(), 5 | account_id uuid NOT NULL 6 | UNIQUE 7 | REFERENCES account.account ON DELETE CASCADE, 8 | date_format date_format_enum NOT NULL 9 | DEFAULT 'MM/DD/YYYY', 10 | time_format time_format_enum NOT NULL 11 | DEFAULT '12 Hour', 12 | measurement_system measurement_system_enum NOT NULL 13 | DEFAULT 'Imperial', 14 | insert_ts TIMESTAMP NOT NULL 15 | DEFAULT CURRENT_TIMESTAMP 16 | ); 17 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/category.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.category ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | account_id uuid NOT NULL REFERENCES account.account ON DELETE CASCADE, 4 | category text, 5 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 6 | UNIQUE (account_id, category) 7 | ); 8 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/device.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.device ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | account_id uuid NOT NULL 5 | REFERENCES account.account ON DELETE CASCADE , 6 | name text NOT NULL, 7 | platform text NOT NULL 8 | DEFAULT 'unknown', 9 | enclosure_version text NOT NULL 10 | DEFAULT 'unknown', 11 | core_version text NOT NULL 12 | DEFAULT 'unknown', 13 | wake_word_id uuid NOT NULL 14 | REFERENCES wake_word.wake_word, 15 | text_to_speech_id uuid NOT NULL 16 | REFERENCES device.text_to_speech, 17 | category_id uuid 18 | REFERENCES device.category, 19 | geography_id uuid NOT NULL 20 | REFERENCES device.geography, 21 | placement text, 22 | last_contact_ts timestamp, 23 | insert_ts TIMESTAMP NOT NULL 24 | DEFAULT CURRENT_TIMESTAMP, 25 | UNIQUE (account_id, name) 26 | ); 27 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/device_skill.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.device_skill ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | device_id uuid NOT NULL 5 | REFERENCES device.device 6 | ON DELETE CASCADE, 7 | skill_id uuid NOT NULL 8 | REFERENCES skill.skill, 9 | install_method text NOT NULL 10 | DEFAULT 'msm', 11 | install_status text NOT NULL 12 | DEFAULT 'installed', 13 | install_failure_reason text, 14 | install_ts TIMESTAMP, 15 | update_ts TIMESTAMP, 16 | skill_settings_display_id uuid 17 | REFERENCES skill.settings_display, 18 | settings json, 19 | insert_ts TIMESTAMP NOT NULL 20 | DEFAULT CURRENT_TIMESTAMP, 21 | UNIQUE (device_id, skill_id) 22 | ); 23 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/geography.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.geography ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | account_id uuid NOT NULL 4 | REFERENCES account.account ON DELETE CASCADE, 5 | country_id uuid NOT NULL 6 | REFERENCES geography.country, 7 | region_id uuid NOT NULL 8 | REFERENCES geography.region, 9 | city_id uuid NOT NULL 10 | REFERENCES geography.city, 11 | timezone_id uuid NOT NULL 12 | REFERENCES geography.timezone, 13 | insert_ts TIMESTAMP NOT NULL 14 | DEFAULT CURRENT_TIMESTAMP, 15 | UNIQUE (account_id, country_id, region_id, city_id, timezone_id) 16 | ); 17 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/pantacor_config.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.pantacor_config ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | device_id uuid UNIQUE REFERENCES device.device ON DELETE CASCADE, 4 | pantacor_id text UNIQUE NOT NULL, 5 | ip_address inet NOT NULL, 6 | ssh_public_key text, 7 | auto_update bool NOT NULL, 8 | release_channel text NOT NULL, 9 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 10 | ); 11 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/skill_setting.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.skill_setting ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | device_skill_id uuid NOT NULL REFERENCES device.device_skill ON DELETE CASCADE, 4 | setting_id uuid NOT NULL REFERENCES skill.setting, 5 | value text NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (device_skill_id, setting_id) 8 | ); 9 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/text_to_speech.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.text_to_speech ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | setting_name text NOT NULL UNIQUE, 4 | display_name text NOT NULL, 5 | engine tts_engine_enum NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 7 | ); 8 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/wake_word.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE device.wake_word ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | setting_name text NOT NULL, 4 | display_name text NOT NULL, 5 | account_id uuid REFERENCES account.account ON DELETE CASCADE, 6 | engine text NOT NULL, 7 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | UNIQUE (account_id, setting_name) 9 | ); 10 | -------------------------------------------------------------------------------- /db/mycroft/device_schema/tables/wake_word_settings.sql: -------------------------------------------------------------------------------- 1 | -- Settings for wake words using the Pocketsphinx engine 2 | CREATE TABLE device.wake_word_settings ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | wake_word_id uuid UNIQUE REFERENCES device.wake_word ON DELETE CASCADE, 5 | sample_rate INTEGER, 6 | channels INTEGER, 7 | pronunciation text, 8 | threshold text, 9 | threshold_multiplier NUMERIC, 10 | dynamic_energy_ratio NUMERIC, 11 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /db/mycroft/drop_extensions.sql: -------------------------------------------------------------------------------- 1 | DROP EXTENSION IF EXISTS pgcrypto; 2 | DROP EXTENSION IF EXISTS btree_gist; -------------------------------------------------------------------------------- /db/mycroft/drop_mycroft_db.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE IF EXISTS mycroft; 2 | -------------------------------------------------------------------------------- /db/mycroft/drop_roles.sql: -------------------------------------------------------------------------------- 1 | DROP ROLE IF EXISTS selene; 2 | -------------------------------------------------------------------------------- /db/mycroft/drop_template_db.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE IF EXISTS mycroft_template; 2 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to geographical reference data 2 | CREATE SCHEMA geography; 3 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/delete_duplicate_cities.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | geography.city 3 | WHERE 4 | id IN %(city_ids)s 5 | and (population is null or population != %(max_population)s) 6 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/get_duplicated_cities.sql: -------------------------------------------------------------------------------- 1 | -- Query to get a list of duplicated cities for use in a process to remove them. 2 | WITH duplicated_cities AS ( 3 | SELECT 4 | c.name AS country_name, 5 | r.name AS region_name, 6 | y.name AS city_name, 7 | max(population) as max_population, 8 | array_agg(y.id::text) as city_ids 9 | FROM 10 | geography.city y 11 | INNER JOIN geography.region r on r.id = y.region_id 12 | INNER JOIN geography.country c on c.id = r.country_id 13 | GROUP BY 14 | 1, 2, 3 15 | ) 16 | SELECT 17 | * 18 | FROM 19 | duplicated_cities 20 | WHERE 21 | cardinality(city_ids) > 1 22 | ; 23 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA geography TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA geography TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/tables/city.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE geography.city ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | region_id uuid NOT NULL 5 | REFERENCES geography.region, 6 | timezone_id uuid NOT NULL 7 | REFERENCES geography.timezone, 8 | name text NOT NULL, 9 | latitude NUMERIC NOT NULL, 10 | longitude NUMERIC NOT NULL, 11 | insert_ts TIMESTAMP NOT NULL 12 | DEFAULT CURRENT_TIMESTAMP, 13 | population INTEGER 14 | ) 15 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/tables/country.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE geography.country ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | iso_code CHAR(2) NOT NULL 5 | UNIQUE, 6 | name text NOT NULL, 7 | insert_ts TIMESTAMP NOT NULL 8 | DEFAULT CURRENT_TIMESTAMP 9 | ) 10 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/tables/region.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE geography.region ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | country_id uuid NOT NULL 5 | REFERENCES geography.country, 6 | region_code VARCHAR(20) NOT NULL UNIQUE, 7 | name text NOT NULL, 8 | insert_ts TIMESTAMP NOT NULL 9 | DEFAULT CURRENT_TIMESTAMP 10 | ) 11 | -------------------------------------------------------------------------------- /db/mycroft/geography_schema/tables/timezone.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE geography.timezone ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | country_id uuid NOT NULL 5 | REFERENCES geography.country, 6 | name text NOT NULL UNIQUE, 7 | gmt_offset NUMERIC NOT NULL, 8 | dst_offset NUMERIC, 9 | insert_ts TIMESTAMP NOT NULL 10 | DEFAULT CURRENT_TIMESTAMP 11 | ) 12 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store system metrics data 2 | CREATE SCHEMA metric; 3 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA metric TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA metric TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/account_activity.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.account_activity ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | activity_dt date NOT NULL DEFAULT current_date, 4 | accounts INTEGER NOT NULL, 5 | accounts_added INTEGER NOT NULL DEFAULT 0, 6 | accounts_deleted INTEGER NOT NULL DEFAULT 0, 7 | accounts_active INTEGER NOT NULL DEFAULT 0, 8 | members INTEGER NOT NULL, 9 | members_added INTEGER NOT NULL DEFAULT 0, 10 | members_expired INTEGER NOT NULL DEFAULT 0, 11 | members_active INTEGER NOT NULL DEFAULT 0, 12 | open_dataset INTEGER NOT NULL, 13 | open_dataset_added INTEGER NOT NULL DEFAULT 0, 14 | open_dataset_deleted INTEGER NOT NULL DEFAULT 0, 15 | open_dataset_active INTEGER NOT NULL DEFAULT 0, 16 | insert_ts timestamp NOT NULL DEFAULT now() 17 | ); 18 | 19 | CREATE INDEX IF NOT EXISTS 20 | account_activity_dt_idx 21 | ON 22 | metric.account_activity (activity_dt) 23 | ; 24 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/api.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.api ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | http_method text NOT NULL, 5 | http_status CHAR(3) NOT NULL, 6 | duration NUMERIC NOT NULL, 7 | access_ts timestamp NOT NULL 8 | DEFAULT now(), 9 | api text NOT NULL, 10 | url text NOT NULL, 11 | account_id uuid, 12 | device_id uuid 13 | ); 14 | 15 | CREATE INDEX IF NOT EXISTS 16 | api_access_ts_idx 17 | ON 18 | metric.api (access_ts) 19 | ; 20 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/api_history.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.api_history ( 2 | id uuid NOT NULL, 3 | http_method text NOT NULL, 4 | http_status CHAR(3) NOT NULL, 5 | duration NUMERIC NOT NULL, 6 | access_ts timestamp NOT NULL, 7 | api text NOT NULL, 8 | url text NOT NULL, 9 | account_id uuid, 10 | device_id uuid 11 | ) 12 | PARTITION BY RANGE 13 | (access_ts) 14 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/core.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.core ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | device_id uuid NOT NULL 5 | REFERENCES device.device 6 | ON DELETE CASCADE, 7 | metric_type text NOT NULL, 8 | insert_ts TIMESTAMP NOT NULL 9 | DEFAULT now(), 10 | metric_value json NOT NULL, 11 | UNIQUE (device_id, insert_ts) 12 | ) 13 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/core_interaction.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.core_interaction ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | device_id uuid NOT NULL 5 | REFERENCES device.device, 6 | core_id text NOT NULL, 7 | start_ts TIMESTAMP NOT NULL, 8 | stt_engine text, 9 | stt_transcription text, 10 | stt_duration NUMERIC, 11 | intent_type text, 12 | intent_duration NUMERIC, 13 | fallback_handler_duration NUMERIC, 14 | skill_handler text, 15 | skill_duration NUMERIC, 16 | tts_engine text, 17 | tts_utterance text, 18 | tts_duration NUMERIC, 19 | speech_playback_duration NUMERIC, 20 | -- user_latency is the time between stt start and speech playback start 21 | user_latency NUMERIC, 22 | insert_ts TIMESTAMP NOT NULL 23 | DEFAULT current_timestamp, 24 | UNIQUE (device_id, core_id) 25 | ) 26 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/job.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.job ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | job_name text NOT NULL, 5 | batch_date date NOT NULL, 6 | start_ts TIMESTAMP NOT NULL, 7 | end_ts TIMESTAMP NOT NULL, 8 | command text NOT NULL, 9 | success BOOLEAN NOT NULL, 10 | UNIQUE (job_name, start_ts) 11 | ) 12 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/stt_engine.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE metric.stt_engine ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | activity_dt DATE NOT NULL DEFAULT current_date, 4 | engine TEXT NOT NULL, 5 | requests INTEGER NOT NULL DEFAULT 0, 6 | success_rate NUMERIC NOT NULL, 7 | transcription_speed NUMERIC NOT NULL, 8 | audio_duration NUMERIC NOT NULL DEFAULT 0, 9 | transcription_duration NUMERIC NOT NULL DEFAULT 0, 10 | insert_ts TIMESTAMP NOT NULL DEFAULT now() 11 | ); 12 | 13 | CREATE UNIQUE INDEX IF NOT EXISTS 14 | stt_transcription_engine_activity_idx 15 | ON 16 | metric.stt_engine (activity_dt, engine) 17 | ; 18 | -------------------------------------------------------------------------------- /db/mycroft/metric_schema/tables/stt_transcription.sql: -------------------------------------------------------------------------------- 1 | -- The metrics stored on this table provide the ability to reconcile STT transcription activity with a 2 | -- bill from a service provider. It can also be used to derive performance metrics by service provider. 3 | -- To keep our promise of privacy, this data will only be available at the account level for 24 hours, at 4 | -- which point it will be aggregated and wiped. 5 | CREATE TABLE metric.stt_transcription ( 6 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 7 | account_id uuid NOT NULL, 8 | engine TEXT NOT NULL, 9 | success BOOLEAN NOT NULL, 10 | audio_duration NUMERIC NOT NULL DEFAULT 0, 11 | transcription_duration NUMERIC NOT NULL DEFAULT 0, 12 | insert_ts TIMESTAMP NOT NULL DEFAULT now() 13 | ); 14 | 15 | CREATE UNIQUE INDEX IF NOT EXISTS 16 | stt_transcription_account_activity_idx 17 | ON 18 | metric.stt_transcription (account_id, insert_ts) 19 | ; 20 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store user data 2 | -- took out the "e" in "user" because "user" is a Postgres keyword 3 | CREATE SCHEMA skill; 4 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA skill TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA skill TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/tables/display.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE skill.display ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | skill_id uuid NOT NULL 5 | REFERENCES skill.skill, 6 | core_version core_version_enum NOT NULL, 7 | display_data json NOT NULL, 8 | insert_ts TIMESTAMP NOT NULL 9 | DEFAULT CURRENT_TIMESTAMP, 10 | UNIQUE (skill_id, core_version) 11 | ); 12 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/tables/oauth_credential.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE skill.oauth_credential ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | developer_id uuid NOT NULL REFERENCES account.account, 4 | application_name text NOT NULL, 5 | oauth_client_id text NOT NULL, 6 | oauth_client_secret text NOT NULL, 7 | oauth_scope text NOT NULL, 8 | token_uri text NOT NULL, 9 | auth_uri text NOT NULL, 10 | revoke_uri text NOT NULL, 11 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 12 | UNIQUE (developer_id, application_name) 13 | ) 14 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/tables/oauth_token.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE skill.oauth_token ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | oauth_credential_id uuid NOT NULL REFERENCES skill.oauth_credential, 4 | account_id uuid NOT NULL REFERENCES account.account, 5 | token json NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (oauth_credential_id, account_id) 8 | ) 9 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/tables/settings_display.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE skill.settings_display ( 2 | id uuid PRIMARY KEY 3 | DEFAULT gen_random_uuid(), 4 | skill_id uuid NOT NULL 5 | REFERENCES skill.skill ON DELETE CASCADE, 6 | settings_display jsonb NOT NULL, 7 | insert_ts TIMESTAMP NOT NULL 8 | DEFAULT CURRENT_TIMESTAMP, 9 | UNIQUE (skill_id, settings_display) 10 | ); 11 | -------------------------------------------------------------------------------- /db/mycroft/skill_schema/tables/skill.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE skill.skill ( 2 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 3 | skill_gid text NOT NULL UNIQUE, 4 | family_name text NOT NULL, 5 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 6 | ); 7 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store user data 2 | -- took out the "e" in "user" because "user" is a Postgres keyword 3 | CREATE SCHEMA tagging; 4 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA tagging TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA tagging TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/file_location.sql: -------------------------------------------------------------------------------- 1 | -- Servers and directories of files used for training machine learning models. 2 | CREATE TABLE tagging.file_location ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | server inet NOT NULL, 5 | directory text NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (server, directory) 8 | ); 9 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/session.sql: -------------------------------------------------------------------------------- 1 | -- A period of time a tagger spent tagging files. 2 | CREATE TABLE tagging.session ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | tagger_id text NOT NULL, 5 | session_ts_range tsrange NOT NULL, 6 | note text, 7 | insert_ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | EXCLUDE USING gist (tagger_id WITH =, session_ts_range with &&), 9 | UNIQUE (tagger_id, session_ts_range) 10 | ) 11 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/tag.sql: -------------------------------------------------------------------------------- 1 | -- Represents all the ways data can be classified (i.e. tagged). 2 | CREATE TABLE tagging.tag ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | name text NOT NULL UNIQUE, 5 | title text NOT NULL, 6 | instructions text NOT NULL, 7 | priority INTEGER NOT NULL, 8 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 9 | ); 10 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/tag_value.sql: -------------------------------------------------------------------------------- 1 | -- Represents all the ways data can be classified (i.e. tagged). 2 | CREATE TABLE tagging.tag_value ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | tag_id uuid NOT NULL REFERENCES tagging.tag, 5 | value text NOT NULL, 6 | display text NOT NULL, 7 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | UNIQUE (tag_id, value) 9 | ); 10 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/tagger.sql: -------------------------------------------------------------------------------- 1 | -- Entities that apply tags to files. 2 | CREATE TABLE tagging.tagger ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | entity_type tagger_type_enum NOT NULL, 5 | entity_id text NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (entity_type, entity_id) 8 | ); 9 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/wake_word_file.sql: -------------------------------------------------------------------------------- 1 | -- Files containing audio data used to train wake word machine learning models. 2 | CREATE TABLE tagging.wake_word_file ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | name text NOT NULL UNIQUE, 5 | wake_word_id uuid NOT NULL REFERENCES wake_word.wake_word, 6 | origin tagging_file_origin_enum NOT NULL, 7 | submission_date date NOT NULL DEFAULT CURRENT_DATE, 8 | file_location_id uuid NOT NULL REFERENCES tagging.file_location, 9 | account_id uuid, 10 | status tagging_file_status_enum NOT NULL DEFAULT 'uploaded'::tagging_file_status_enum, 11 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 12 | ); 13 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/wake_word_file_designation.sql: -------------------------------------------------------------------------------- 1 | -- The final agreed upon value of a tag for a file. 2 | CREATE TABLE tagging.wake_word_file_designation ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | wake_word_file_id uuid NOT NULL REFERENCES tagging.wake_word_file, 5 | tag_id uuid NOT NULL REFERENCES tagging.tag, 6 | tag_value_id uuid NOT NULL REFERENCES tagging.tag_value, 7 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | UNIQUE (wake_word_file_id, tag_id) 9 | ); 10 | -------------------------------------------------------------------------------- /db/mycroft/tagging_schema/tables/wake_word_file_tag.sql: -------------------------------------------------------------------------------- 1 | -- Represents all the ways data can be classified (i.e. tagged). 2 | CREATE TABLE tagging.wake_word_file_tag ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | wake_word_file_id uuid NOT NULL REFERENCES tagging.wake_word_file, 5 | session_id uuid NOT NULL REFERENCES tagging.session, 6 | tag_id uuid NOT NULL REFERENCES tagging.tag, 7 | tag_value_id uuid NOT NULL REFERENCES tagging.tag_value, 8 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 9 | UNIQUE (wake_word_file_id, session_id, tag_id) 10 | ); 11 | -------------------------------------------------------------------------------- /db/mycroft/types/agreement_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE agreement_enum AS ENUM ( 2 | 'Privacy Policy', 3 | 'Terms of Use', 4 | 'Open Dataset' 5 | ); 6 | -------------------------------------------------------------------------------- /db/mycroft/types/cateogory_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE category_enum AS ENUM ( 2 | 'Daily', 3 | 'Configuration', 4 | 'Entertainment', 5 | 'Information', 6 | 'IoT', 7 | 'Music and Audio', 8 | 'Media', 9 | 'Productivity', 10 | 'Transport' 11 | ); -------------------------------------------------------------------------------- /db/mycroft/types/core_version_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE core_version_enum AS ENUM ('18.08', '19.02', '19.08', '20.02', '20.08', '21.02', '21.08'); 2 | -------------------------------------------------------------------------------- /db/mycroft/types/date_format_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE date_format_enum AS ENUM ('DD/MM/YYYY', 'MM/DD/YYYY'); -------------------------------------------------------------------------------- /db/mycroft/types/measurement_system_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE measurement_system_enum AS ENUM ('Imperial', 'Metric'); -------------------------------------------------------------------------------- /db/mycroft/types/membership_type_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE membership_type_enum AS ENUM ('Monthly Membership', 'Yearly Membership'); 2 | -------------------------------------------------------------------------------- /db/mycroft/types/payment_method_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE payment_method_enum AS ENUM ('Stripe', 'PayPal'); 2 | -------------------------------------------------------------------------------- /db/mycroft/types/tagger_type_enum.sql: -------------------------------------------------------------------------------- 1 | -- How a tagging file is originated. Used as column type on the tagging.file table 2 | CREATE TYPE tagger_type_enum AS ENUM ('account', 'automated'); 3 | -------------------------------------------------------------------------------- /db/mycroft/types/tagging_file_origin_enum.sql: -------------------------------------------------------------------------------- 1 | -- How a tagging file is originated. Used as column type on the tagging.file table 2 | CREATE TYPE tagging_file_origin_enum AS ENUM ('mycroft', 'selene', 'manual'); 3 | -------------------------------------------------------------------------------- /db/mycroft/types/tagging_file_status_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE tagging_file_status_enum AS ENUM ( 2 | 'uploaded', 3 | 'stored', 4 | 'pending delete', 5 | 'deleted' 6 | ); 7 | -------------------------------------------------------------------------------- /db/mycroft/types/time_format_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE time_format_enum AS ENUM ('12 Hour', '24 Hour'); -------------------------------------------------------------------------------- /db/mycroft/types/tts_engine_enum.sql: -------------------------------------------------------------------------------- 1 | CREATE TYPE tts_engine_enum AS ENUM ('google', 'mimic'); -------------------------------------------------------------------------------- /db/mycroft/wake_word_schema/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- create the schema that will be used to store user data 2 | -- took out the "e" in "user" because "user" is a Postgres keyword 3 | CREATE SCHEMA wake_word; 4 | -------------------------------------------------------------------------------- /db/mycroft/wake_word_schema/grants.sql: -------------------------------------------------------------------------------- 1 | GRANT USAGE ON SCHEMA wake_word TO selene; 2 | GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA wake_word TO selene; 3 | -------------------------------------------------------------------------------- /db/mycroft/wake_word_schema/tables/pocketsphinx_settings.sql: -------------------------------------------------------------------------------- 1 | -- The Pocketsphinx wake word settings in use by each account. 2 | CREATE TABLE wake_word.pocketsphinx_settings ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | wake_word_id uuid REFERENCES wake_word.wake_word ON DELETE CASCADE, 5 | account_id uuid REFERENCES account.account ON DELETE CASCADE, 6 | sample_rate INTEGER, 7 | channels INTEGER, 8 | pronunciation text, 9 | threshold text, 10 | threshold_multiplier NUMERIC, 11 | dynamic_energy_ratio NUMERIC, 12 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 13 | UNIQUE (wake_word_id, account_id) 14 | ); 15 | -------------------------------------------------------------------------------- /db/mycroft/wake_word_schema/tables/wake_word.sql: -------------------------------------------------------------------------------- 1 | -- Domain table for all known wake words currently in use or previously used. 2 | CREATE TABLE wake_word.wake_word ( 3 | id uuid PRIMARY KEY DEFAULT gen_random_uuid(), 4 | name text NOT NULL, 5 | engine text NOT NULL, 6 | insert_ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | UNIQUE (name, engine) 8 | ); 9 | -------------------------------------------------------------------------------- /db/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "db" 3 | version = "0.1.0" 4 | description = "Database definition and related scripts" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | psycopg2-binary = "*" 11 | Markdown = "^3.4.1" 12 | 13 | [tool.poetry.dev-dependencies] 14 | ipython = "==5" 15 | pylint = "*" 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.0.0"] 19 | build-backend = "poetry.core.masonry.api" 20 | -------------------------------------------------------------------------------- /db/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | -------------------------------------------------------------------------------- /shared/Dockerfile: -------------------------------------------------------------------------------- 1 | # Parent dockerfile for all Selene services and APIs 2 | # 3 | # This Dockerfile contains the steps that are common to building all the 4 | # docker images for the Selene backend to Mycroft 5 | 6 | FROM python:3.9 7 | LABEL maintainer="Mycroft AI " 8 | 9 | # Install the software required for this image 10 | RUN pip install pipenv 11 | 12 | # Use pipenv to install the dependencies for selene-util 13 | COPY Pipfile Pipfile 14 | COPY Pipfile.lock Pipfile.lock 15 | RUN pipenv install --system 16 | 17 | # Now that pipenv has installed all the packages required by selene-util 18 | # the Pipfile can be removed from the container. This makes way for the 19 | # pepenv to use these files to install dependencies for the Selene services 20 | # or applications that will use this Docker config 21 | RUN rm Pipfile 22 | RUN rm Pipfile.lock 23 | 24 | # Copy the applicaction code to the image 25 | COPY selene_util /opt/selene/selene_util 26 | WORKDIR /opt/selene/ 27 | -------------------------------------------------------------------------------- /shared/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include selene/data/account/repository/sql/*.sql 2 | include selene/data/device/repository/sql/*.sql 3 | include selene/data/skill/repository/sql/*.sql -------------------------------------------------------------------------------- /shared/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "selene" 3 | version = "0.1.0" 4 | description = "Selene library code" 5 | authors = ["Chris Veilleux "] 6 | license = "GNU AGPL 3.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | facebook-sdk = "*" 11 | # Version 1.0 of flask required because later versions do not allow lists to be passed as API repsonses. The Google 12 | # STT endpoint passes a list of transcriptions to the device. Changing this to return a dictionary would break the 13 | # API's V1 contract with Mycroft Core. 14 | # 15 | # To make flask 1.0 work, older versions of itsdangerous, jinja2 and markupsafe are required. 16 | email-validator = "*" 17 | flask = "<1.1" 18 | itsdangerous = "<=2.0.1" 19 | jinja2 = "<=2.10.1" 20 | markupsafe = "<=2.0.1" 21 | paramiko = "*" 22 | passlib = "*" 23 | psycopg2-binary = "*" 24 | pygithub = "*" 25 | pyjwt = "*" 26 | redis = "*" 27 | schedule = "*" 28 | schematics = "*" 29 | sendgrid = "*" 30 | stripe = "*" 31 | werkzeug = "<=2.0.3" 32 | 33 | [tool.poetry.dev-dependencies] 34 | black = "*" 35 | pyhamcrest = "*" 36 | pylint = "*" 37 | 38 | [build-system] 39 | requires = ["poetry-core>=1.0.0"] 40 | build-backend = "poetry.core.masonry.api" 41 | -------------------------------------------------------------------------------- /shared/selene/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/api/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .base_config import get_base_config 21 | from .base_endpoint import APIError, SeleneEndpoint 22 | from .blueprint import selene_api 23 | from .etag import device_etag_key, device_setting_etag_key, ETagManager 24 | from .public_endpoint import PublicEndpoint, track_account_activity 25 | from .public_endpoint import generate_device_login 26 | from .response import SeleneResponse, snake_to_camel 27 | -------------------------------------------------------------------------------- /shared/selene/api/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API for the selene.api.endpoints package.""" 20 | 21 | from .account import AccountEndpoint 22 | from .agreements import AgreementsEndpoint 23 | from .password_change import PasswordChangeEndpoint 24 | from .validate_email import ValidateEmailEndpoint 25 | -------------------------------------------------------------------------------- /shared/selene/batch/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .base import SeleneScript 21 | -------------------------------------------------------------------------------- /shared/selene/data/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/account/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/account/entity/agreement.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from datetime import date 22 | 23 | TERMS_OF_USE = "Terms of Use" 24 | PRIVACY_POLICY = "Privacy Policy" 25 | OPEN_DATASET = "Open Dataset" 26 | 27 | 28 | @dataclass 29 | class Agreement(object): 30 | type: str 31 | version: str 32 | effective_date: date 33 | id: str = None 34 | content: str = None 35 | -------------------------------------------------------------------------------- /shared/selene/data/account/entity/membership.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from decimal import Decimal 22 | 23 | 24 | @dataclass 25 | class Membership(object): 26 | type: str 27 | rate: Decimal 28 | rate_period: str 29 | stripe_plan: str 30 | id: str = None 31 | -------------------------------------------------------------------------------- /shared/selene/data/account/entity/skill.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from typing import List 22 | 23 | 24 | @dataclass 25 | class AccountSkill(object): 26 | skill_id: str 27 | skill_name: str 28 | devices: List[str] 29 | display_name: str = None 30 | settings_version: str = None 31 | settings_display: dict = None 32 | settings: dict = None 33 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/add_account.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.account (email_address, password, username) 3 | VALUES 4 | (%(email_address)s, %(password)s, %(username)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/add_account_agreement.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.account_agreement (account_id, agreement_id, accept_date) 3 | VALUES 4 | ( 5 | %(account_id)s, 6 | ( 7 | SELECT 8 | id 9 | FROM 10 | account.agreement 11 | WHERE 12 | agreement = %(agreement_name)s 13 | AND effective @> CURRENT_DATE 14 | ), 15 | '[now,]' 16 | ) 17 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/add_account_membership.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.account_membership ( 3 | account_id, 4 | membership_id, 5 | membership_ts_range, 6 | payment_method, 7 | payment_account_id, 8 | payment_id 9 | ) 10 | VALUES 11 | ( 12 | %(account_id)s, 13 | ( 14 | SELECT 15 | id 16 | FROM 17 | account.membership 18 | WHERE 19 | type = %(membership_type)s 20 | ), 21 | '[now,]', 22 | %(payment_method)s, 23 | %(payment_account_id)s, 24 | %(payment_id)s 25 | ) 26 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/add_agreement.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.agreement (agreement, version, effective, content_id) 3 | VALUES 4 | (%(agreement_type)s, %(version)s, %(date_range)s, %(content_id)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/add_membership.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | account.membership (type, rate, rate_period) 3 | VALUES 4 | (%(membership_type)s, %(rate)s, %(rate_period)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/change_email_address.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.account 3 | SET 4 | email_address = %(email_address)s 5 | WHERE 6 | id = %(account_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/change_password.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.account 3 | SET 4 | password = %(password)s 5 | WHERE 6 | id = %(account_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/delete_agreement.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | account.agreement 3 | WHERE 4 | id = %(agreement_id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/delete_membership.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | account.membership 3 | WHERE 4 | id = %(membership_id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/end_membership.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.account_membership 3 | SET 4 | membership_ts_range = %(membership_ts_range)s 5 | WHERE 6 | id = %(id)s -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/expire_account_agreement.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | account.account_agreement 3 | WHERE 4 | account_id = %(account_id)s 5 | AND agreement_id in (SELECT id FROM account.agreement WHERE agreement = %(agreement_type)s) 6 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/expire_agreement.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.agreement 3 | SET 4 | effective = %(date_range)s 5 | WHERE 6 | agreement = %(agreement_type)s 7 | AND upper(effective) IS NULL 8 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_account_skills.sql: -------------------------------------------------------------------------------- 1 | -- get all combinations of skills and skill setting meta for an account 2 | WITH 3 | skills AS ( 4 | SELECT 5 | s.id AS skill_id, 6 | s.name AS skill_name, 7 | ds.skill_setting_meta_id, 8 | ds.settings::jsonb, 9 | array_agg(d.name) AS devices 10 | FROM 11 | skill.skill s 12 | INNER JOIN device.device_skill ds ON ds.skill_id = s.id 13 | INNER JOIN device.device d ON d.id = ds.device_id 14 | WHERE 15 | d.account_id = %(account_id)s 16 | GROUP BY 17 | s.id, 18 | s.name, 19 | ds.skill_setting_meta_id, 20 | ds.settings::jsonb 21 | ), 22 | skill_meta AS ( 23 | SELECT 24 | skill_id, 25 | display_name, 26 | max(branch) 27 | FROM 28 | skill.branch 29 | GROUP BY 30 | skill_id, 31 | display_name 32 | ) 33 | SELECT 34 | s.skill_id, 35 | s.skill_name, 36 | s.settings, 37 | s.devices, 38 | skm.display_name, 39 | sm.version AS settings_version, 40 | sm.settings_meta 41 | FROM 42 | skills s 43 | LEFT JOIN skill.setting_meta sm ON s.skill_setting_meta_id = sm.id 44 | LEFT JOIN skill_meta skm ON skm.skill_id = s.skill_id 45 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_active_membership_by_account_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | acc_mem.id, 3 | mem.type, 4 | LOWER(acc_mem.membership_ts_range)::date start_date, 5 | acc_mem.payment_method, 6 | payment_account_id, 7 | payment_id 8 | FROM 9 | account.account_membership acc_mem 10 | INNER JOIN 11 | account.membership mem ON acc_mem.membership_id = mem.id 12 | WHERE 13 | account_id = %(account_id)s AND UPPER(acc_mem.membership_ts_range) IS NULL 14 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_active_membership_by_payment_account_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | acc_mem.id, 3 | mem.type, 4 | LOWER(acc_mem.membership_ts_range)::date start_date, 5 | acc_mem.payment_method, 6 | payment_account_id, 7 | payment_id 8 | FROM 9 | account.account_membership acc_mem 10 | INNER JOIN 11 | account.membership mem ON acc_mem.membership_id = mem.id 12 | WHERE 13 | acc_mem.payment_account_id = %(payment_account_id)s AND UPPER(acc_mem.membership_ts_range) IS NULL 14 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_agreement_content_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | content_id 3 | FROM 4 | account.agreement 5 | WHERE 6 | id = %(agreement_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_current_agreements.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | agreement, 4 | version, 5 | content_id, 6 | lower(effective) as effective_date 7 | FROM 8 | account.agreement 9 | WHERE 10 | effective @> CURRENT_DATE 11 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_membership_by_type.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | type, 4 | rate, 5 | rate_period, 6 | stripe_plan 7 | FROM 8 | account.membership 9 | WHERE 10 | type = %(type)s -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/get_membership_types.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | type, 4 | rate, 5 | rate_period, 6 | stripe_plan 7 | FROM 8 | account.membership 9 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/remove_account.sql: -------------------------------------------------------------------------------- 1 | -- Perform a cascading delete on an account. All children of the account 2 | -- table should have ON DELETE CASCADE clauses. If this request fails, a missing 3 | -- ON DELETE CASCADE clause may be the culprit. 4 | DELETE FROM 5 | account.account 6 | WHERE 7 | id = %(id)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/update_last_activity_ts.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.account 3 | SET 4 | last_activity_ts = %(last_activity_ts)s 5 | WHERE 6 | id = %(account_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/account/repository/sql/update_username.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | account.account 3 | SET 4 | username = %(username)s 5 | WHERE 6 | id = %(account_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/device/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/device/entity/geography.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from decimal import Decimal 22 | 23 | 24 | @dataclass 25 | class Geography(object): 26 | country: str 27 | region: str 28 | city: str 29 | time_zone: str 30 | latitude: Decimal = None 31 | longitude: Decimal = None 32 | id: str = None 33 | -------------------------------------------------------------------------------- /shared/selene/data/device/entity/preference.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class AccountPreferences(object): 25 | date_format: str 26 | time_format: str 27 | measurement_system: str 28 | id: str = None 29 | -------------------------------------------------------------------------------- /shared/selene/data/device/entity/text_to_speech.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class TextToSpeech(object): 25 | setting_name: str 26 | display_name: str 27 | engine: str 28 | id: str = None 29 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .device import Device 21 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/add_device.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.device (account_id, name, placement, wake_word_id, text_to_speech_id, geography_id) 3 | VALUES 4 | ( 5 | %(account_id)s, 6 | %(name)s, 7 | %(placement)s, 8 | (SELECT id FROM wake_word.wake_word WHERE name = %(wake_word)s ORDER BY engine DESC LIMIT 1), 9 | (SELECT id FROM device.text_to_speech WHERE display_name = %(voice)s), 10 | %(geography_id)s 11 | ) 12 | RETURNING id 13 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/add_geography.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.geography (account_id, country_id, region_id, city_id, timezone_id) 3 | VALUES 4 | ( 5 | %(account_id)s, 6 | (SELECT id FROM geography.country WHERE name = %(country)s), 7 | ( 8 | SELECT 9 | r.id 10 | FROM 11 | geography.region r 12 | INNER JOIN geography.country c ON c.id = r.country_id 13 | WHERE 14 | r.name = %(region)s 15 | AND c.name = %(country)s 16 | ), 17 | ( 18 | SELECT 19 | c.id 20 | FROM 21 | geography.city c 22 | INNER JOIN geography.region r ON r.id = c.region_id 23 | 24 | WHERE 25 | c.name = %(city)s 26 | AND r.name = %(region)s 27 | ), 28 | (SELECT id FROM geography.timezone WHERE name = %(timezone)s) 29 | ) 30 | RETURNING 31 | id 32 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/add_manifest_skill.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.device_skill ( 3 | device_id, 4 | skill_id, 5 | install_method, 6 | install_status, 7 | install_failure_reason, 8 | install_ts, 9 | update_ts 10 | ) 11 | VALUES 12 | ( 13 | %(device_id)s, 14 | %(skill_id)s, 15 | %(install_method)s, 16 | %(install_status)s, 17 | %(install_failure_reason)s, 18 | %(install_ts)s, 19 | %(update_ts)s 20 | ) 21 | RETURNING 22 | id 23 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/add_text_to_speech.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.text_to_speech (setting_name, display_name, engine) 3 | VALUES 4 | (%(setting_name)s, %(display_name)s, %(engine)s) 5 | RETURNING id -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/delete_device_skill.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | device.device_skill 3 | WHERE 4 | device_id = %(device_id)s 5 | AND skill_id = %(skill_id)s 6 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_account_device_count.sql: -------------------------------------------------------------------------------- 1 | SELECT count(*) AS device_count FROM device.device WHERE account_id = %(account_id)s 2 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_account_geographies.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | g.id, 3 | cntry.name AS country, 4 | r.name as region, 5 | cty.name AS city, 6 | t.name as time_zone, 7 | latitude, 8 | longitude 9 | FROM 10 | device.geography g 11 | INNER JOIN geography.city cty ON g.city_id = cty.id 12 | INNER JOIN geography.country cntry ON g.country_id = cntry.id 13 | INNER JOIN geography.region r ON g.region_id = r.id 14 | INNER JOIN geography.timezone t ON g.timezone_id = t.id 15 | WHERE 16 | account_id = %(account_id)s 17 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_account_preferences.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | measurement_system, 4 | date_format, 5 | time_format 6 | FROM 7 | device.account_preferences 8 | WHERE 9 | account_id = %(account_id)s 10 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_all_device_ids.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id 3 | FROM 4 | device.device 5 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_device_settings_by_device_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | acc.id as uuid, 3 | acc.measurement_system as system_unit, 4 | acc.date_format as date_format, 5 | acc.time_format as time_format, 6 | json_build_object('setting_name', tts.setting_name, 'engine', tts.engine) as tts_settings, 7 | json_build_object( 8 | 'uuid', ps.id, 9 | 'sampleRate', ps.sample_rate, 10 | 'channels', ps.channels, 11 | 'wakeWord', ww.name, 12 | 'phonemes', ps.pronunciation, 13 | 'threshold', ps.threshold, 14 | 'multiplier', ps.threshold_multiplier, 15 | 'energyRatio', ps.dynamic_energy_ratio) as listener_setting 16 | FROM 17 | device.device dev 18 | INNER JOIN 19 | device.account_preferences acc ON dev.account_id = acc.account_id 20 | INNER JOIN 21 | device.text_to_speech tts ON dev.text_to_speech_id = tts.id 22 | INNER JOIN 23 | wake_word.wake_word ww ON dev.wake_word_id = ww.id 24 | LEFT JOIN 25 | wake_word.pocketsphinx_settings ps ON ww.id = ps.wake_word_id 26 | WHERE 27 | dev.id = %(device_id)s 28 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_device_skill_manifest.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | ds.id, 3 | ds.device_id, 4 | ds.install_failure_reason, 5 | ds.install_method, 6 | ds.install_status, 7 | ds.install_ts, 8 | ds.skill_id, 9 | ds.update_ts, 10 | s.skill_gid 11 | FROM 12 | device.device d 13 | INNER JOIN device.device_skill ds ON d.id = ds.device_id 14 | INNER JOIN skill.skill s ON ds.skill_id = s.id 15 | WHERE 16 | d.id = %(device_id)s 17 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_location_by_device_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | json_build_object( 3 | 'latitude', city.latitude, 4 | 'longitude', city.longitude 5 | ) as coordinate, 6 | json_build_object( 7 | 'name', timezone.name, 8 | 'code', timezone.name, 9 | 'offset', trunc(timezone.gmt_offset * 60 * 60 * 1000), 10 | 'dstOffset', trunc(timezone.dst_offset * 60 * 60 * 1000) 11 | ) as timezone, 12 | json_build_object( 13 | 'name', city.name, 14 | 'state', json_build_object( 15 | 'name', region.name, 16 | 'code', region.region_code, 17 | 'country', json_build_object( 18 | 'name', country.name, 19 | 'code', country.iso_code 20 | ) 21 | ) 22 | ) as city 23 | FROM 24 | device.device dev 25 | INNER JOIN 26 | device.geography geo ON dev.geography_id = geo.id 27 | INNER JOIN 28 | geography.country country ON geo.country_id = country.id 29 | INNER JOIN 30 | geography.region region ON geo.region_id = region.id 31 | INNER JOIN 32 | geography.city city ON geo.city_id = city.id 33 | INNER JOIN 34 | geography.timezone timezone ON geo.timezone_id = timezone.id 35 | WHERE 36 | dev.id = %(device_id)s -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_open_dataset_agreement_by_device_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | acc_agr.id 3 | FROM 4 | device.device dev 5 | INNER JOIN 6 | account.account acc ON dev.account_id = acc.id 7 | INNER JOIN 8 | account.account_agreement acc_agr ON acc.id = acc_agr.account_id 9 | INNER JOIN 10 | account.agreement agr ON acc_agr.agreement_id = agr.id 11 | WHERE 12 | dev.id = %(device_id)s AND agr.agreement = 'Open Dataset' -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_settings_display_usage.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | count(*) AS usage 3 | FROM 4 | device.device_skill 5 | WHERE 6 | skill_settings_display_id = %(settings_display_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_skill_manifest_for_account.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | ds.device_id, 3 | ds.install_failure_reason, 4 | ds.install_method, 5 | ds.install_status, 6 | ds.install_ts, 7 | ds.skill_id, 8 | ds.update_ts, 9 | s.skill_gid 10 | FROM 11 | device.device d 12 | INNER JOIN device.device_skill ds ON d.id = ds.device_id 13 | INNER JOIN skill.skill s ON ds.skill_id = s.id 14 | WHERE 15 | d.account_id = %(account_id)s 16 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_skill_settings_for_account.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | dds.skill_settings_display_id AS settings_display_id, 3 | dds.settings::jsonb AS settings_values, 4 | dds.install_method, 5 | dds.skill_id, 6 | array_agg(dds.device_id::text) AS device_ids 7 | FROM 8 | device.device dd 9 | INNER JOIN device.device_skill dds ON dd.id = dds.device_id 10 | WHERE 11 | dd.account_id = %(account_id)s 12 | AND dds.skill_id = %(skill_id)s 13 | GROUP BY 14 | dds.skill_settings_display_id, 15 | dds.settings::jsonb, 16 | dds.install_method, 17 | dds.skill_id 18 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_skill_settings_for_device.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | ds.skill_settings_display_id AS settings_display_id, 3 | ds.settings::jsonb AS settings_values, 4 | ds.skill_id, 5 | s.skill_gid 6 | FROM 7 | device.device_skill ds 8 | INNER JOIN skill.skill s ON ds.skill_id = s.id 9 | WHERE 10 | device_id = %(device_id)s 11 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/get_voices.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | setting_name, 4 | display_name, 5 | engine 6 | FROM 7 | device.text_to_speech 8 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/remove_device.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | device.device 3 | WHERE 4 | id = %(device_id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/remove_manifest_skill.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | device.device_skill 3 | WHERE 4 | device_id = %(device_id)s 5 | AND skill_id = (SELECT id FROM skill.skill WHERE skill_gid = %(skill_gid)s) 6 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/remove_text_to_speech.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | device.text_to_speech 3 | WHERE 4 | id = %(text_to_speech_id)s -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_device_from_account.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device 3 | SET 4 | name = %(name)s, 5 | placement = %(placement)s, 6 | geography_id = %(geography_id)s, 7 | wake_word_id = ( 8 | SELECT 9 | id 10 | FROM 11 | wake_word.wake_word 12 | WHERE 13 | name = %(wake_word)s 14 | ORDER BY 15 | engine DESC 16 | LIMIT 1 17 | ), 18 | text_to_speech_id = ( 19 | SELECT 20 | id 21 | FROM 22 | device.text_to_speech 23 | WHERE 24 | display_name = %(voice)s 25 | ) 26 | WHERE 27 | id = %(device_id)s 28 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_device_from_core.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device 3 | SET 4 | platform = %(platform)s, 5 | enclosure_version = %(enclosure_version)s, 6 | core_version = %(core_version)s 7 | WHERE 8 | id = %(device_id)s -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_device_skill_settings.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device_skill 3 | SET 4 | skill_settings_display_id = %(settings_display_id)s, 5 | settings = %(settings_values)s 6 | WHERE 7 | device_id = %(device_id)s 8 | AND skill_id = %(skill_id)s 9 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_last_contact_ts.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device 3 | SET 4 | last_contact_ts = %(last_contact_ts)s 5 | WHERE 6 | id = %(device_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_pantacor_config.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.pantacor_config 3 | SET 4 | ssh_public_key = %(ssh_public_key)s, 5 | auto_update = %(auto_update)s, 6 | release_channel = %(release_channel)s 7 | WHERE 8 | device_id = %(device_id)s 9 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_skill_manifest.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device_skill 3 | SET 4 | install_method = %(install_method)s, 5 | install_status = %(install_status)s, 6 | install_failure_reason = %(failure_message)s, 7 | install_ts = %(install_ts)s, 8 | update_ts = %(update_ts)s 9 | WHERE 10 | device_id = %(device_id)s 11 | AND skill_id = ( 12 | SELECT 13 | id 14 | FROM 15 | skill.skill 16 | WHERE 17 | skill_gid = %(skill_gid)s 18 | ) 19 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/update_skill_settings.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device_skill 3 | SET 4 | settings = %(settings)s 5 | WHERE 6 | device_id IN ( 7 | SELECT 8 | id 9 | FROM 10 | device.device 11 | WHERE 12 | account_id = %(account_id)s AND 13 | device_name IN %(device_names)s 14 | ) 15 | AND skill_id = (SELECT id from skill.skill WHERE name = %(skill_name)s) 16 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/upsert_device_skill_settings.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.device_skill ( 3 | device_id, 4 | skill_id, 5 | skill_settings_display_id, 6 | settings 7 | ) 8 | VALUES 9 | ( 10 | %(device_id)s, 11 | %(skill_id)s, 12 | %(settings_display_id)s, 13 | %(settings_values)s 14 | ) 15 | ON CONFLICT 16 | (device_id, skill_id) 17 | DO UPDATE SET 18 | skill_settings_display_id = %(settings_display_id)s, 19 | settings = %(settings_values)s 20 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/upsert_pantacor_config.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.pantacor_config (device_id, pantacor_id, ip_address, auto_update, release_channel) 3 | VALUES 4 | (%(device_id)s, %(pantacor_id)s, %(ip_address)s, %(auto_update)s, %(release_channel)s) 5 | ON CONFLICT 6 | (device_id) 7 | DO UPDATE SET 8 | ip_address = %(ip_address)s 9 | -------------------------------------------------------------------------------- /shared/selene/data/device/repository/sql/upsert_preferences.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.account_preferences( 3 | account_id, 4 | date_format, 5 | time_format, 6 | measurement_system 7 | ) 8 | VALUES 9 | ( 10 | %(account_id)s, 11 | %(date_format)s, 12 | %(time_format)s, 13 | %(measurement_system)s 14 | ) 15 | ON CONFLICT 16 | (account_id) 17 | DO UPDATE SET 18 | date_format = %(date_format)s, 19 | time_format = %(time_format)s, 20 | measurement_system = %(measurement_system)s 21 | RETURNING 22 | id 23 | -------------------------------------------------------------------------------- /shared/selene/data/geography/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .entity.city import City 21 | from .entity.country import Country 22 | from .entity.region import Region 23 | from .entity.timezone import Timezone 24 | from .repository.city import CityRepository 25 | from .repository.country import CountryRepository 26 | from .repository.region import RegionRepository 27 | from .repository.timezone import TimezoneRepository 28 | -------------------------------------------------------------------------------- /shared/selene/data/geography/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/geography/entity/city.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class City(object): 25 | id: str 26 | latitude: str 27 | longitude: str 28 | name: str 29 | timezone: str 30 | 31 | 32 | @dataclass 33 | class GeographicLocation(object): 34 | city: str 35 | country: str 36 | region: str 37 | latitude: str 38 | longitude: str 39 | timezone: str 40 | -------------------------------------------------------------------------------- /shared/selene/data/geography/entity/country.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class Country(object): 25 | id: str 26 | iso_code: str 27 | name: str 28 | -------------------------------------------------------------------------------- /shared/selene/data/geography/entity/region.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class Region(object): 25 | id: str 26 | region_code: str 27 | name: str 28 | -------------------------------------------------------------------------------- /shared/selene/data/geography/entity/timezone.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from decimal import Decimal 22 | 23 | 24 | @dataclass 25 | class Timezone(object): 26 | id: str 27 | dst_offset: Decimal 28 | gmt_offset: Decimal 29 | name: str 30 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/country.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from ..entity.country import Country 21 | from ...repository_base import RepositoryBase 22 | 23 | 24 | class CountryRepository(RepositoryBase): 25 | def __init__(self, db): 26 | super(CountryRepository, self).__init__(db, __file__) 27 | 28 | def get_countries(self): 29 | db_request = self._build_db_request(sql_file_name="get_countries.sql") 30 | db_result = self.cursor.select_all(db_request) 31 | 32 | return [Country(**row) for row in db_result] 33 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_biggest_city_in_country.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | cty.latitude, 3 | cty.longitude, 4 | cty.name AS city, 5 | cntry.name AS country, 6 | r.name AS region, 7 | t.name AS timezone 8 | FROM 9 | geography.city cty 10 | INNER JOIN geography.region r ON cty.region_id = r.id 11 | INNER JOIN geography.country cntry ON r.country_id = cntry.id 12 | INNER JOIN geography.timezone t ON cty.timezone_id = t.id 13 | WHERE 14 | lower(cntry.name) = %(country)s 15 | AND cty.population IS NOT NULL 16 | ORDER BY 17 | cty.population DESC 18 | LIMIT 19 | 1 20 | 21 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_biggest_city_in_region.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | cty.latitude, 3 | cty.longitude, 4 | cty.name AS city, 5 | cntry.name AS country, 6 | r.name AS region, 7 | t.name AS timezone 8 | FROM 9 | geography.city cty 10 | INNER JOIN geography.region r ON cty.region_id = r.id 11 | INNER JOIN geography.country cntry ON r.country_id = cntry.id 12 | INNER JOIN geography.timezone t ON cty.timezone_id = t.id 13 | WHERE 14 | lower(r.name) = %(region)s 15 | AND cty.population IS NOT NULL 16 | ORDER BY 17 | cty.population DESC 18 | LIMIT 19 | 1 20 | 21 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_cities_by_region.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | c.id, 3 | c.name, 4 | c.latitude, 5 | c.longitude, 6 | t.name as timezone 7 | FROM 8 | geography.city c 9 | INNER JOIN geography.timezone t ON c.timezone_id = t.id 10 | WHERE 11 | region_id = %(region_id)s 12 | ORDER BY 13 | c.name 14 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_countries.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | iso_code, 4 | name 5 | FROM 6 | geography.country 7 | ORDER BY 8 | name 9 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_geographic_location_by_city.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | cty.latitude, 3 | cty.longitude, 4 | cty.name AS city, 5 | cntry.name AS country, 6 | r.name AS region, 7 | t.name AS timezone 8 | FROM 9 | geography.city cty 10 | INNER JOIN geography.region r ON cty.region_id = r.id 11 | INNER JOIN geography.country cntry ON r.country_id = cntry.id 12 | INNER JOIN geography.timezone t ON cty.timezone_id = t.id 13 | WHERE 14 | lower(cty.name) IN %(possible_city_names)s 15 | ORDER BY 16 | cty.population DESC 17 | 18 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_regions_by_country.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | region_code, 4 | name 5 | FROM 6 | geography.region 7 | WHERE 8 | country_id = %(country_id)s 9 | ORDER BY 10 | name 11 | -------------------------------------------------------------------------------- /shared/selene/data/geography/repository/sql/get_timezones_by_country.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | name, 4 | gmt_offset, 5 | dst_offset 6 | FROM 7 | geography.timezone 8 | WHERE 9 | country_id = %(country_id)s 10 | ORDER BY 11 | name 12 | -------------------------------------------------------------------------------- /shared/selene/data/metric/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API for the selene.data.metric package.""" 20 | 21 | from .entity.api import ApiMetric 22 | from .entity.core import CoreMetric, CoreInteraction 23 | from .entity.job import JobMetric 24 | from .entity.stt import SttTranscriptionMetric 25 | from .repository.account_activity import AccountActivityRepository 26 | from .repository.api import ApiMetricsRepository 27 | from .repository.core import CoreMetricRepository 28 | from .repository.job import JobRepository 29 | from .repository.stt import TranscriptionMetricRepository 30 | -------------------------------------------------------------------------------- /shared/selene/data/metric/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/metric/entity/api.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from datetime import datetime 22 | from decimal import Decimal 23 | 24 | 25 | @dataclass 26 | class ApiMetric(object): 27 | url: str 28 | access_ts: datetime 29 | api: str 30 | duration: Decimal 31 | http_method: str 32 | http_status: int 33 | id: str = None 34 | account_id: str = None 35 | device_id: str = None 36 | -------------------------------------------------------------------------------- /shared/selene/data/metric/entity/job.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from datetime import date, datetime 22 | 23 | 24 | @dataclass 25 | class JobMetric(object): 26 | job_name: str 27 | batch_date: date 28 | start_ts: datetime 29 | end_ts: datetime 30 | command: str 31 | success: bool 32 | id: str = None 33 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_account_activity.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.account_activity ( 3 | accounts, 4 | members, 5 | open_dataset 6 | ) 7 | VALUES 8 | ( 9 | (SELECT count(*) FROM account.account), 10 | ( 11 | SELECT 12 | count(*) 13 | FROM 14 | account.account_membership 15 | WHERE 16 | membership_ts_range @> current_date::timestamp 17 | ), 18 | ( 19 | SELECT 20 | count(aa.*) 21 | FROM 22 | account.account_agreement aa 23 | INNER JOIN account.agreement a ON aa.agreement_id = a.id 24 | WHERE 25 | a.agreement = 'Open Dataset' 26 | ) 27 | ) 28 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_api_metric.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.api ( 3 | url, 4 | access_ts, 5 | api, 6 | account_id, 7 | device_id, 8 | duration, 9 | http_method, 10 | http_status 11 | ) 12 | VALUES 13 | ( 14 | %(url)s, 15 | %(access_ts)s, 16 | %(api)s, 17 | %(account_id)s, 18 | %(device_id)s, 19 | %(duration)s, 20 | %(http_method)s, 21 | %(http_status)s 22 | ) 23 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_core_interaction.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.core_interaction ( 3 | device_id, 4 | core_id, 5 | start_ts, 6 | stt_engine, 7 | stt_transcription, 8 | stt_duration, 9 | intent_type, 10 | intent_duration, 11 | fallback_handler_duration, 12 | skill_handler, 13 | skill_duration, 14 | tts_engine, 15 | tts_utterance, 16 | tts_duration, 17 | speech_playback_duration, 18 | user_latency 19 | ) 20 | VALUES 21 | ( 22 | %(device_id)s, 23 | %(core_id)s, 24 | %(start_ts)s, 25 | %(stt_engine)s, 26 | %(stt_transcription)s, 27 | %(stt_duration)s, 28 | %(intent_type)s, 29 | %(intent_duration)s, 30 | %(fallback_handler_duration)s, 31 | %(skill_handler)s, 32 | %(skill_duration)s, 33 | %(tts_engine)s, 34 | %(tts_utterance)s, 35 | %(tts_duration)s, 36 | %(speech_playback_duration)s, 37 | %(user_latency)s 38 | ) 39 | RETURNING 40 | id 41 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_core_metric.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.core (device_id, metric_type, metric_value) 3 | VALUES 4 | (%(device_id)s, %(metric_type)s, %(metric_value)s) 5 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_job_metric.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.job 3 | VALUES ( 4 | DEFAULT, 5 | %(job_name)s, 6 | %(batch_date)s, 7 | %(start_ts)s, 8 | %(end_ts)s, 9 | %(command)s, 10 | %(success)s 11 | ) 12 | RETURNING 13 | id 14 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/add_tts_transcription_metric.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | metric.stt_transcription 3 | VALUES ( 4 | DEFAULT, 5 | %(account_id)s, 6 | %(engine)s, 7 | %(success)s, 8 | %(audio_duration)s, 9 | %(transcription_duration)s 10 | ) 11 | RETURNING 12 | id 13 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/create_api_metric_partition.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS 2 | metric.api_history_{partition} 3 | PARTITION OF 4 | metric .api_history 5 | FOR VALUES FROM 6 | (%(start_ts)s) TO (%(end_ts)s) 7 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/create_api_metric_partition_index.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX IF NOT EXISTS 2 | api_history_{partition}_access_ts_idx 3 | ON 4 | metric.api_history_{partition} (access_ts) 5 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/delete_account_activity_date.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | metric.account_activity 3 | WHERE 4 | activity_dt = %(activity_date)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/delete_api_metrics_by_date.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | metric.api 3 | WHERE 4 | access_ts::date = %(delete_date)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/delete_stt_transcription_by_date.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | metric.stt_transcription 3 | WHERE 4 | insert_ts::date = %(transcription_date)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/get_account_activity_by_date.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | accounts, 3 | accounts_added, 4 | accounts_deleted, 5 | accounts_active, 6 | members, 7 | members_added, 8 | members_expired, 9 | members_active, 10 | open_dataset, 11 | open_dataset_added, 12 | open_dataset_deleted, 13 | open_dataset_active 14 | FROM 15 | metric.account_activity 16 | WHERE 17 | activity_dt = %(activity_date)s 18 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/get_api_metrics_for_date.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | * 3 | FROM 4 | metric.api 5 | WHERE 6 | access_ts::date = %(metrics_date)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/get_core_metric_by_device.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | device_id, 4 | metric_type, 5 | metric_value 6 | FROM 7 | metric.core 8 | WHERE 9 | device_id = %(device_id)s 10 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/get_core_timing_metrics_by_date.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | device_id, 3 | metric_type, 4 | metric_value 5 | FROM 6 | metric.core 7 | WHERE 8 | metric_type = 'timing' 9 | AND metric_value ->> 'id' NOT IN ('unknown', 'null') 10 | AND insert_ts::date = %(metric_date)s 11 | ORDER BY 12 | metric_value ->> 'id', 13 | metric_value ->> 'start_time' 14 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/get_tts_transcription_by_account.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | account_id, 3 | engine, 4 | success, 5 | audio_duration, 6 | transcription_duration 7 | FROM 8 | metric.stt_transcription 9 | WHERE 10 | account_id = %(account_id)s 11 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_accounts_added.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | accounts = accounts + 1, 5 | accounts_added = accounts_added + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_accounts_deleted.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | accounts = accounts - 1, 5 | accounts_deleted = accounts_deleted + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_activity.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | accounts_active = accounts_active + 1, 5 | members_active = members_active + %(member_increment)s, 6 | open_dataset_active = open_dataset_active + %(open_dataset_increment)s 7 | WHERE 8 | activity_dt = current_date 9 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_members_added.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | members = members + 1, 5 | members_added = members_added + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_members_expired.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | members = members - 1, 5 | members_expired = members_expired + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_open_dataset_added.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | open_dataset = open_dataset + 1, 5 | open_dataset_added = open_dataset_added + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/metric/repository/sql/increment_open_dataset_deleted.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | metric.account_activity 3 | SET 4 | open_dataset = open_dataset - 1, 5 | open_dataset_deleted = open_dataset_deleted + 1 6 | WHERE 7 | activity_dt = current_date 8 | -------------------------------------------------------------------------------- /shared/selene/data/skill/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .entity.display import SkillDisplay 21 | from .entity.skill import Skill 22 | from .entity.skill_setting import ( 23 | AccountSkillSetting, 24 | DeviceSkillSetting, 25 | SettingsDisplay, 26 | ) 27 | from .repository.display import SkillDisplayRepository 28 | from .repository.setting import SkillSettingRepository 29 | from .repository.settings_display import SettingsDisplayRepository 30 | from .repository.skill import extract_family_from_global_id, SkillRepository 31 | -------------------------------------------------------------------------------- /shared/selene/data/skill/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/skill/entity/display.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class SkillDisplay(object): 25 | skill_id: str 26 | core_version: str 27 | display_data: dict 28 | id: str = None 29 | -------------------------------------------------------------------------------- /shared/selene/data/skill/entity/skill.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from typing import List 22 | 23 | 24 | @dataclass 25 | class SkillVersion(object): 26 | version: str 27 | display_name: str 28 | 29 | 30 | @dataclass 31 | class Skill(object): 32 | skill_gid: str 33 | id: str = None 34 | 35 | 36 | @dataclass 37 | class SkillFamily(object): 38 | display_name: str 39 | family_name: str 40 | has_settings: bool 41 | market_id: str 42 | skill_ids: List[str] 43 | -------------------------------------------------------------------------------- /shared/selene/data/skill/entity/skill_setting.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | from typing import List 22 | 23 | 24 | @dataclass 25 | class AccountSkillSetting(object): 26 | settings_definition: dict 27 | settings_values: dict 28 | device_names: List[str] 29 | 30 | 31 | @dataclass 32 | class DeviceSkillSetting(object): 33 | settings_display: dict 34 | settings_values: dict 35 | skill_id: str 36 | 37 | 38 | @dataclass 39 | class SettingsDisplay(object): 40 | skill_id: str 41 | display_data: dict 42 | id: str = None 43 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/add_device_skill.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | device.device_skill (device_id, skill_id, skill_settings_display_id, settings) 3 | VALUES 4 | (%(device_id)s, %(skill_id)s, %(skill_settings_display_id)s, %(settings_value)s) 5 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/add_settings_display.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | skill.settings_display (skill_id, settings_display) 3 | VALUES 4 | (%(skill_id)s, %(display_data)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/add_skill.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | skill.skill (skill_gid, family_name) 3 | VALUES 4 | (%(skill_gid)s, %(family_name)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/delete_device_skill.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | device.device_skill 3 | WHERE 4 | id = ( 5 | SELECT 6 | ds.id 7 | FROM 8 | device.device_skill ds 9 | INNER JOIN 10 | skill.skill s ON ds.skill_id = s.id 11 | WHERE 12 | ds.device_id = %(device_id)s AND s.skill_gid = %(skill_gid)s 13 | ) -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/delete_settings_display.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | skill.settings_display 3 | WHERE 4 | id = %(settings_display_id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_display_data_for_skill.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | skill_id, 4 | core_version, 5 | display_data 6 | FROM 7 | skill.display 8 | WHERE 9 | id = %(skill_display_id)s 10 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_display_data_for_skills.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | skill_id, 4 | core_version, 5 | display_data 6 | FROM 7 | skill.display 8 | WHERE 9 | core_version = %(core_version)s 10 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_settings_definition_by_gid.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | sd.id, 3 | sd.skill_id, 4 | sd.settings_display as display_data 5 | FROM 6 | skill.settings_display sd 7 | INNER JOIN skill.skill s ON sd.skill_id = s.id 8 | WHERE 9 | s.skill_gid = %(global_id)s 10 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_settings_display_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id 3 | FROM 4 | skill.settings_display 5 | WHERE 6 | skill_id = %(skill_id)s 7 | AND settings_display = %(display_data)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_settings_for_skill_family.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | sd.settings_display::jsonb -> 'skillMetadata' AS settings_definition, 3 | ds.settings::jsonb AS settings_values, 4 | array_agg(d.name) AS device_names 5 | FROM 6 | device.device_skill ds 7 | INNER JOIN device.device d ON ds.device_id = d.id 8 | INNER JOIN skill.skill s ON ds.skill_id = s.id 9 | LEFT JOIN skill.settings_display sd ON ds.skill_settings_display_id = sd.id 10 | WHERE 11 | s.family_name = %(family_name)s 12 | AND d.account_id = %(account_id)s 13 | GROUP BY 14 | settings_definition, 15 | settings_values 16 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_skill_by_global_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id, 3 | skill_gid 4 | FROM 5 | skill.skill 6 | WHERE 7 | skill_gid = %(skill_global_id)s; 8 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_skill_setting_by_device.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | dds.skill_id, 3 | dds.settings AS settings_values, 4 | ssd.settings_display 5 | FROM 6 | device.device_skill dds 7 | INNER JOIN skill.skill ss ON dds.skill_id = ss.id 8 | INNER JOIN skill.settings_display ssd ON dds.skill_settings_display_id = ssd.id 9 | WHERE 10 | dds.device_id = %(device_id)s 11 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/get_skills_for_account.sql: -------------------------------------------------------------------------------- 1 | SELECT DISTINCT 2 | ss.family_name, 3 | sd.id AS market_id, 4 | ssd.settings_display -> 'skillMetadata' IS NOT NULL AS has_settings, 5 | ssd.settings_display -> 'display_name' AS display_name, 6 | array_agg(DISTINCT ss.id::text) AS skill_ids 7 | FROM 8 | skill.skill ss 9 | INNER JOIN device.device_skill dds ON dds.skill_id = ss.id 10 | INNER JOIN device.device dd ON dd.id = dds.device_id 11 | LEFT JOIN skill.display sd ON ss.id = sd.skill_id 12 | LEFT JOIN skill.settings_display ssd ON ssd.skill_id = ss.id 13 | WHERE 14 | ssd.id = dds.skill_settings_display_id 15 | AND dd.account_id = %(account_id)s 16 | GROUP BY 17 | 1, 2, 3, 4 18 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/remove_skill_by_gid.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | skill.skill 3 | WHERE 4 | skill_gid = %(skill_gid)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/update_device_skill_settings.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | device.device_skill 3 | SET 4 | settings = %(settings_values)s 5 | WHERE 6 | skill_id IN %(skill_id)s 7 | AND device_id IN ( 8 | SELECT 9 | id 10 | FROM 11 | device.device 12 | WHERE 13 | account_id = %(account_id)s 14 | AND name IN %(device_names)s 15 | ) 16 | -------------------------------------------------------------------------------- /shared/selene/data/skill/repository/sql/upsert_skill_display_data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | skill.display (skill_id, core_version, display_data) 3 | VALUES 4 | ( 5 | %(skill_id)s, 6 | %(core_version)s, 7 | %(display_data)s 8 | ) 9 | ON CONFLICT 10 | (skill_id, core_version) 11 | DO UPDATE SET 12 | display_data = %(display_data)s 13 | RETURNING 14 | id 15 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/file_designation.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing a designation applied to a wake word file.""" 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class FileDesignation: 25 | """Representation a designation applied to a wake word file.""" 26 | 27 | file_id: str 28 | tag_id: str 29 | tag_value_id: str 30 | id: str = None 31 | file_name: str = None 32 | file_directory: str = None 33 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/file_location.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing possible locations of machine learning training files.""" 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class TaggingFileLocation: 25 | """Data representation of a directory containing machine learning training files.""" 26 | 27 | server: str 28 | directory: str 29 | id: str = None 30 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/file_tag.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing a tag applied to a wake word file.""" 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class FileTag: 25 | """Representation a tag applied to a wake word file and its possible values.""" 26 | 27 | file_id: str 28 | session_id: str 29 | tag_id: str 30 | tag_value_id: str 31 | id: str = None 32 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/tag.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing a type of tag used to describe an audio file.""" 20 | from dataclasses import dataclass 21 | from typing import List 22 | 23 | from .tag_value import TagValue 24 | 25 | 26 | @dataclass 27 | class Tag: 28 | """Dataclass representation of a tag and its values.""" 29 | 30 | id: str 31 | name: str 32 | title: str 33 | instructions: str 34 | priority: str 35 | values: List[TagValue] 36 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/tag_value.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing a value of a tag.""" 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class TagValue: 25 | """Representation of a value of a tag.""" 26 | 27 | value: str 28 | display: str 29 | id: str = None 30 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/entity/tagger.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Data entities representing possible locations of machine learning training files.""" 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class Tagger: 25 | """Data representation of a tagging entity.""" 26 | 27 | entity_type: str 28 | entity_id: str 29 | id: str = None 30 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_file_location.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.file_location (server, directory) 3 | VALUES 4 | (%(server)s, %(directory)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_session.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.session (tagger_id, session_ts_range) 3 | VALUES 4 | (%(tagger_id)s, '[now,]'::tsrange) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_tagger.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.tagger (entity_type, entity_id) 3 | VALUES 4 | (%(entity_type)s, %(entity_id)s) 5 | RETURNING 6 | id 7 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_tagging_session.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.session (tagger_id) 3 | VALUES 4 | (%(tagger_id)s) 5 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_wake_word_file.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.wake_word_file ( 3 | wake_word_id, 4 | name, 5 | origin, 6 | submission_date, 7 | account_id, 8 | file_location_id 9 | ) 10 | VALUES 11 | ( 12 | %(wake_word_id)s, 13 | %(file_name)s, 14 | %(origin)s, 15 | %(submission_date)s, 16 | %(account_id)s, 17 | %(file_location_id)s 18 | ) 19 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_wake_word_file_designation.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.wake_word_file_designation (wake_word_file_id, tag_id, tag_value_id) 3 | VALUES 4 | (%(file_id)s, %(tag_id)s, %(tag_value_id)s) 5 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/add_wake_word_file_tag.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | tagging.wake_word_file_tag (wake_word_file_id, session_id, tag_id, tag_value_id) 3 | VALUES 4 | (%(file_id)s, %(session_id)s, %(tag_id)s, %(tag_value_id)s) 5 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/change_account_file_status.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | tagging.wake_word_file 3 | SET 4 | status = %(status)s 5 | WHERE 6 | account_id = %(account_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/change_file_location.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | tagging.wake_word_file 3 | SET 4 | file_location_id = %(file_location_id)s, 5 | status = 'stored'::tagging_file_status_enum 6 | WHERE 7 | id = %(wake_word_file_id)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/change_file_status.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | tagging.wake_word_file 3 | SET 4 | status = %(status)s 5 | WHERE 6 | name = %(file_name)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_active_session.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | s.id, 3 | max(ft.insert_ts) AS last_tag_ts 4 | FROM 5 | tagging.session s 6 | LEFT JOIN tagging.wake_word_file_tag ft ON s.id = ft.session_id 7 | WHERE 8 | tagger_id = ( 9 | SELECT 10 | id::text 11 | FROM 12 | tagging.tagger 13 | WHERE 14 | entity_type = 'account' 15 | AND entity_id = %(entity_id)s 16 | ) 17 | AND upper(session_ts_range) IS NULL 18 | GROUP BY 19 | 1 20 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_designation_candidates.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | ww.name AS wake_word, 3 | wwft.wake_word_file_id, 4 | wwft.session_id, 5 | wwft.tag_id, 6 | wwft.tag_value_id 7 | FROM 8 | tagging.wake_word_file wwf 9 | INNER JOIN wake_word.wake_word ww ON wwf.wake_word_id = ww.id 10 | INNER JOIN tagging.wake_word_file_tag wwft ON wwf.id = wwft.wake_word_file_id 11 | LEFT JOIN tagging.wake_word_file_designation wwfd ON wwf.id = wwfd.wake_word_file_id AND wwft.tag_id = wwfd.tag_id 12 | WHERE 13 | wwfd.id IS NULL 14 | ORDER BY 15 | ww.name, 16 | wwft.wake_word_file_id, 17 | wwft.tag_id, 18 | wwft.tag_value_id 19 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_designations_from_date.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | wwf.id AS file_id, 3 | wwf.name AS file_name, 4 | fl.directory AS file_directory, 5 | wwfd.tag_id, 6 | wwfd.tag_value_id 7 | FROM 8 | tagging.wake_word_file_designation wwfd 9 | INNER JOIN tagging.wake_word_file wwf ON wwf.id = wwfd.wake_word_file_id 10 | INNER JOIN tagging.file_location fl on fl.id = wwf.file_location_id 11 | WHERE 12 | wwfd.insert_ts::date >= %(start_date)s 13 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_file_location_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id 3 | FROM 4 | tagging.file_location 5 | WHERE 6 | server = %(server)s 7 | AND directory = %(directory)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_tagger_by_entity.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id 3 | FROM 4 | tagging.tagger 5 | WHERE 6 | entity_type = %(entity_type)s 7 | AND entity_id = %(entity_id)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_tags.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | t.id, 3 | t.name, 4 | t.title, 5 | t.instructions, 6 | t.priority, 7 | json_agg( 8 | json_build_object( 9 | 'value', tv.value, 10 | 'display', tv.display, 11 | 'id', tv.id 12 | ) 13 | ) AS values 14 | FROM 15 | tagging.tag t 16 | LEFT JOIN tagging.tag_value tv ON t.id = tv.tag_id 17 | GROUP BY 18 | t.id, 19 | t.name, 20 | t.title, 21 | t.instructions, 22 | t.priority 23 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/get_wake_word_files.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | json_build_object( 3 | 'name', ww.name, 4 | 'engine', ww.engine, 5 | 'id', ww.id 6 | ) AS wake_word, 7 | wwf.name, 8 | wwf.origin, 9 | wwf.submission_date, 10 | wwf.account_id, 11 | wwf.status, 12 | wwf.id, 13 | json_build_object( 14 | 'server', fl.server, 15 | 'directory', fl.directory, 16 | 'id', ww.id 17 | ) AS location 18 | FROM 19 | tagging.wake_word_file wwf 20 | INNER JOIN tagging.file_location fl ON fl.id = wwf.file_location_id 21 | INNER JOIN wake_word.wake_word ww on ww.id = wwf.wake_word_id 22 | WHERE 23 | {where_clause} 24 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/remove_file_location.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | tagging.file_location 3 | WHERE 4 | id = %(id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/remove_wake_word_file.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | tagging.wake_word_file 3 | WHERE 4 | id = %(id)s 5 | -------------------------------------------------------------------------------- /shared/selene/data/tagging/repository/sql/update_session_end_ts.sql: -------------------------------------------------------------------------------- 1 | UPDATE 2 | tagging.session 3 | SET 4 | session_ts_range = tsrange(lower(session_ts_range), %(end_ts)s) 5 | WHERE 6 | id = %(session_id)s 7 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .entity.wake_word import WakeWord 21 | from .entity.pocketsphinx_settings import PocketsphinxSettings 22 | from .repository.wake_word import WakeWordRepository 23 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/entity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MycroftAI/selene-backend/e10ac91cde6bf6097ae7eafe3fcb6c1b1d292f70/shared/selene/data/wake_word/entity/__init__.py -------------------------------------------------------------------------------- /shared/selene/data/wake_word/entity/pocketsphinx_settings.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class PocketsphinxSettings(object): 25 | id: str 26 | sample_rate: int 27 | channels: int 28 | pronunciation: str 29 | threshold: str 30 | threshold_multiplier: float 31 | dynamic_energy_ratio: float 32 | account_id: str = None 33 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/entity/wake_word.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from dataclasses import dataclass 21 | 22 | 23 | @dataclass 24 | class WakeWord(object): 25 | name: str 26 | engine: str 27 | id: str = None 28 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/repository/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MycroftAI/selene-backend/e10ac91cde6bf6097ae7eafe3fcb6c1b1d292f70/shared/selene/data/wake_word/repository/__init__.py -------------------------------------------------------------------------------- /shared/selene/data/wake_word/repository/sql/add_wake_word.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | wake_word.wake_word (name, engine) 3 | VALUES 4 | (%(name)s, %(engine)s) 5 | RETURNING id 6 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/repository/sql/get_wake_word_id.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | id 3 | FROM 4 | wake_word.wake_word 5 | WHERE 6 | name = %(name)s 7 | AND engine = %(engine)s 8 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/repository/sql/get_wake_words_for_web.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | ww.id, 3 | ww.name, 4 | ww.engine 5 | FROM 6 | wake_word.wake_word ww 7 | INNER JOIN wake_word.pocketsphinx_settings ps ON ww.id = ps.wake_word_id 8 | WHERE 9 | ps.account_id is NULL 10 | -------------------------------------------------------------------------------- /shared/selene/data/wake_word/repository/sql/remove_wake_word.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM 2 | wake_word.wake_word 3 | WHERE 4 | id = %(wake_word_id)s 5 | -------------------------------------------------------------------------------- /shared/selene/testing/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/testing/account_preference.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from selene.data.device import AccountPreferences, PreferenceRepository 21 | 22 | 23 | def add_account_preference(db, account_id): 24 | account_preferences = AccountPreferences( 25 | date_format="MM/DD/YYYY", time_format="12 Hour", measurement_system="Imperial" 26 | ) 27 | preference_repo = PreferenceRepository(db, account_id) 28 | preference_repo.upsert(account_preferences) 29 | -------------------------------------------------------------------------------- /shared/selene/util/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /shared/selene/util/db/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .connection import connect_to_db, DatabaseConnectionConfig 21 | from .connection_pool import ( 22 | allocate_db_connection_pool, 23 | get_db_connection, 24 | get_db_connection_from_pool, 25 | return_db_connection_to_pool, 26 | ) 27 | from .cursor import Cursor, DatabaseRequest, DatabaseBatchRequest, get_sql_from_file 28 | from .transaction import use_transaction 29 | -------------------------------------------------------------------------------- /shared/selene/util/email/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API into the selene.util.email package.""" 20 | 21 | from .email import EmailMessage, SeleneMailer, validate_email_address 22 | -------------------------------------------------------------------------------- /shared/selene/util/email/templates/base.html: -------------------------------------------------------------------------------- 1 |
2 | MYCROFT AI 7 |
16 |
17 |

Greetings,

18 | {% block email_body %} 19 | {% endblock email_body %} 20 |

Regards,

21 |

The Mycroft AI Team

22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /shared/selene/util/email/templates/email_change.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block email_body %} 3 |

4 | A change to the email address associated with your Mycroft account has been requested. If you did not make 5 | this request, please contact us immediately at support@mycroft.ai. Otherwise, check the inbox for the new email 6 | address for verification instructions. If you don't see the verification email in your inbox, please check your 7 | spam folder. 8 | 9 | Your account will not be updated until the new email address is verified. 10 |

11 | {% endblock email_body %} 12 | -------------------------------------------------------------------------------- /shared/selene/util/email/templates/email_verification.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block email_body %} 3 |

4 | A change to the email address associated with your Mycroft account has been requested. Before this change can 5 | be applied, the new email address must be verified. 6 |

7 |

To verify this email address, click the button below.

8 | 21 | VERIFY EMAIL ADDRESS 22 | 23 | {% endblock email_body %} 24 | -------------------------------------------------------------------------------- /shared/selene/util/email/templates/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block email_body %} 3 |

4 | The password for the Mycroft account associated with this email address has been changed. If you 5 | did not update your password, please contact us immediately at support@mycroft.ai. Otherwise, you can 6 | ignore this message. 7 |

8 | {% endblock email_body %} 9 | -------------------------------------------------------------------------------- /shared/selene/util/email/templates/reset_password.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block email_body %} 3 |

4 | A password reset was requested for the Mycroft account associated with this email address. If you did 5 | not make this request, you can ignore this message. 6 |

7 |

To reset your password, click the button below.

8 | 21 | RESET PASSWORD 22 | 23 | {% endblock email_body %} 24 | -------------------------------------------------------------------------------- /shared/selene/util/exceptions.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | """Define custom exceptions used in Selene APIs and scripts""" 21 | 22 | 23 | class NotModifiedException(Exception): 24 | """Raise this exception when a request contains an etag found in cache. 25 | 26 | The Flask blueprint will catch this exception and return a HTTP 304 code. 27 | """ 28 | 29 | pass 30 | -------------------------------------------------------------------------------- /shared/selene/util/payment/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2019 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | 20 | from .stripe import ( 21 | cancel_stripe_subscription, 22 | create_stripe_account, 23 | create_stripe_subscription, 24 | ) 25 | -------------------------------------------------------------------------------- /shared/selene/util/ssh/__init__.py: -------------------------------------------------------------------------------- 1 | # Mycroft Server - Backend 2 | # Copyright (C) 2020 Mycroft AI Inc 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | # 5 | # This file is part of the Mycroft Server. 6 | # 7 | # The Mycroft Server is free software: you can redistribute it and/or 8 | # modify it under the terms of the GNU Affero General Public License as 9 | # published by the Free Software Foundation, either version 3 of the 10 | # License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU Affero General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU Affero General Public License 18 | # along with this program. If not, see . 19 | """Public API into the ssh package.""" 20 | from .sftp import get_remote_file 21 | from .ssh import SshClientConfig, validate_rsa_public_key 22 | --------------------------------------------------------------------------------