{"id":13744617,"url":"https://github.com/MycroftAI/selene-backend","last_synced_at":"2025-05-09T03:32:44.527Z","repository":{"id":39490629,"uuid":"143091267","full_name":"MycroftAI/selene-backend","owner":"MycroftAI","description":"Microservices and web apps to support Mycroft devices","archived":false,"fork":false,"pushed_at":"2023-02-16T05:39:13.000Z","size":4070,"stargazers_count":143,"open_issues_count":47,"forks_count":52,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-08-04T05:04:38.445Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MycroftAI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-01T02:03:39.000Z","updated_at":"2024-06-02T11:46:52.000Z","dependencies_parsed_at":"2022-07-12T19:30:43.374Z","dependency_job_id":null,"html_url":"https://github.com/MycroftAI/selene-backend","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MycroftAI%2Fselene-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MycroftAI%2Fselene-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MycroftAI%2Fselene-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MycroftAI%2Fselene-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MycroftAI","download_url":"https://codeload.github.com/MycroftAI/selene-backend/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224811082,"owners_count":17373914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T05:01:12.785Z","updated_at":"2024-11-15T16:31:20.880Z","avatar_url":"https://github.com/MycroftAI.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"[![License](https://img.shields.io/badge/License-GNU_AGPL%203.0-blue.svg)](LICENSE)\n[![CLA](https://img.shields.io/badge/CLA%3F-Required-blue.svg)](https://mycroft.ai/cla)\n[![Team](https://img.shields.io/badge/Team-Mycroft_Backend-violetblue.svg)](https://github.com/MycroftAI/contributors/blob/master/team/Mycroft%20Backend.md)\n![Status](https://img.shields.io/badge/-Production_ready-green.svg)\n\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)\n[![Join chat](https://img.shields.io/badge/Mattermost-join_chat-brightgreen.svg)](https://chat.mycroft.ai)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n\n\nSelene -- Mycroft's Server Backend\n==========\n\nSelene provides the services used by [Mycroft Core](https://github.com/mycroftai/mycroft-core) to manage devices, skills\nand settings.  It consists of two repositories.  This one contains Python and SQL representing the database definition,\ndata access layer, APIs and scripts.  The second repository, [Selene UI](https://github.com/mycroftai/selene-ui),\ncontains Angular web applications that use the APIs defined in this repository.\n\nThere are four APIs defined in this repository, account management, single sign on, skill marketplace and device.\nThe first three support account.mycroft.ai (aka home.mycroft.ai), sso.mycroft.ai, and market.mycroft.ai, respectively.\nThe device API is how devices running Mycroft Core communicate with the server. Also included in this repository is\na package containing batch scripts for maintenance and the definition of the database schema.\n\nEach API is designed to run independently of the others. Code common to each of the APIs, such as the Data Access Layer,\ncan be found in the \"shared\" directory.  The shared code is an independent Python package required by each of the APIs.\nEach API has its own Pipfile so that it can be run in its own virtual environment.\n\n## Installation\nThe Python code utilizes features introduced in Python 3.7, such as data classes.\n[Pipenv](https://pipenv.readthedocs.io/en/latest/) is used for virtual environment and package management.\nIf you prefer to use pip and pyenv (or virtualenv), you can find the required libraries in the files named \"Pipfile\".\nThese instructions will use pipenv commands.\n\nIf the Selene applications will be servicing a large number of devices (enterprise usage, for example), it is\nrecommended that each of the applications run on their own server or virtual machine. This configuration makes it\neasier to scale and monitor each application independently.  However, all applications can be run on a single server.\nThis configuration could be more practical for a household running a handful of devices.\n\nThese instructions will assume a multi-server setup for several thousand devices. To run on a single server servicing a\nsmall number of devices, the recommended system requirements are 4 CPU, 8GB RAM and 100GB of disk.  There are a lot of\nmanual steps in this section that will eventually be replaced with an installation script.\n\nAll Selene applications are time zone agnostic.  It is recommended that the time zone on any server running Selene be UTC.\n\nIt is recommended to create an application specific user. In these instructions this user will be `mycroft`.\n\n### Postgres DB\n* Recommended server configuration: [Ubuntu 18.04 LTS (server install)](https://releases.ubuntu.com/bionic/), 2 CPU, 4GB RAM, 50GB disk.\n* Use the package management system to install Python 3.7, Python 3 pip and PostgreSQL 10\n```\nsudo apt-get install postgresql python3.7 python python3-pip\n```\n* Set Postgres to start on boot\n```\nsudo systemctl enable postgresql\n```\n* Clone the selene-backend and documentation repositories\n```\nsudo mkdir -p /opt/selene\nsudo chown -R mycroft:users /opt/selene\ncd /opt/selene\ngit clone https://github.com/MycroftAI/selene-backend.git\n```\n* Create the virtual environment for the database code\n```\nsudo python3.7 -m pip install pipenv\ncd /opt/selene/selene-backend/db\npipenv install\n```\n* Download files from geonames.org used to populate the geography schema tables\n```\nmkdir -p /opt/selene/data\ncd /opt/selene/data\nwget http://download.geonames.org/export/dump/countryInfo.txt\nwget http://download.geonames.org/export/dump/timeZones.txt\nwget http://download.geonames.org/export/dump/admin1CodesASCII.txt\nwget http://download.geonames.org/export/dump/cities500.zip\n```\n* Add environment variables containing these passwords for the bootstrap script\n```\nexport DB_PASSWORD=\u003cselene user password\u003e\nexport POSTGRES_PASSWORD=\u003cpostgres user password\u003e\n```\n* Generate secure passwords for the postgres user and selene user on the database\n```\nsudo -u postgres psql -c \"ALTER USER postgres PASSWORD '$POSTGRES_PASSWORD'\"\nsudo -u postgres psql -c \"CREATE ROLE selene WITH LOGIN ENCRYPTED PASSWORD '$DB_PASSWORD'\"\n```\n* Run the bootstrap script\n```\ncd /opt/selene/selene-backend/db/scripts\npipenv run python bootstrap_mycroft_db.py\n```\n  * Note: if you get an authentication error you can temporarily edit `/etc/postgresql/\u003cversion\u003e/main/pg_hba.conf` replacing the following lines:\n  ```\n  # \"local\" is for Unix domain socket connections only\n  local   all             all                                     trust\n  # IPv4 local connections:\n  host    all             all             127.0.0.1/32            trust\n  ```\n* By default, Postgres only listens on localhost.  This will not do for a multi-server setup.  Change the\n`listen_addresses` value in the `posgresql.conf` file to the private IP of the database server.  This file is owned by\nthe `postgres` user so use the following command to edit it (substituting vi for your favorite editor)\n```\nsudo -u postgres vi /etc/postgres/10/main/postgresql.conf\n```\n* By default, Postgres only allows connections from localhost.  This will not do for a multi-server setup either.  Add\nan entry to the `pg_hba.conf` file for each server that needs to access this database.  This file is also owned by\nthe `postgres` user so use the following command to edit it (substituting vi for your favorite editor)\n```\nsudo -u postgres vi /etc/postgres/10/main/pg_hba.conf\n```\n* Instructions on how to update the `pg_hba.conf` file can be found in\n[Postgres' documentation](https://www.postgresql.org/docs/10/auth-pg-hba-conf.html).  Below is an example for reference.\n```\n# IPv4 Selene connections\nhost    mycroft         selene          \u003cprivate IP address\u003e/32          md5\n```\n* Restart Postgres for the `postgres.conf` and `pg_hba.conf` changes to take effect.\n```\nsudo systemctl restart postgresql\n```\n\n### Redis DB\n\n* Recommended server configuration: Ubuntu 18.04 LTS, 1 CPU, 1GB RAM, 5GB disk.\nSo as to not reinvent the wheel, here are some easy-to-follow instructions for\n[installing Redis on Ubuntu 18.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04).\n* By default, Redis only listens on local host. For multi-server setups, one additional step is to change the \"bind\" variable in `/etc/redis/redis.conf` to be the private IP of the Redis host.\n\n### APIs\n\nThe majority of the setup for each API is the same.  This section defines the steps common to all APIs. Steps specific\nto each API will be defined in their respective sections.\n* Add an application user to the VM. Either give this user sudo privileges or execute the sudo commands below as a user\nwith sudo privileges.  These instructions will assume a user name of \"mycroft\"\n* Use the package management system to install Python 3.7, Python 3 pip and Python 3.7 Developer Tools\n```\nsudo apt install python3.7 python3-pip python3.7-dev\nsudo python3.7 -m pip install pipenv\n```\n* Setup the Backend Application Directory\n```\nsudo mkdir -p /opt/selene\nsudo chown -R mycroft:users /opt/selene\n```\n* Setup the Log Directory\n```\nsudo mkdir -p /var/log/mycroft\nsudo chown -R mycroft:users /var/log/mycroft\n```\n* Clone the Selene Backend Repository\n```\ncd /opt/selene\ngit clone https://github.com/MycroftAI/selene-backend.git\n```\n* If running in a test environment, be sure to checkout the \"test\" branch of the repository\n\n#### Single Sign On API\nRecommended server configuration: Ubuntu 18.04 LTS, 1 CPU, 1GB RAM, 5GB disk\n* Create the virtual environment and install the requirements for the application\n```\ncd /opt/selene/selene-backend/api/sso\npipenv install\n```\n\n#### Account API\n* Recommended server configuration: Ubuntu 18.04 LTS, 1 CPU, 1GB RAM, 5GB disk\n* Create the virtual environment and install the requirements for the application\n```\ncd /opt/selene/selene-backend/api/account\npipenv install\n```\n\n#### Marketplace API\n* Recommended server configuration: Ubuntu 18.04 LTS, 1 CPU, 1GB RAM, 10GB disk\n* Create the virtual environment and install the requirements for the application\n```\ncd /opt/selene/selene-backend/api/market\npipenv install\n```\n\n#### Device API\n* Recommended server configuration: Ubuntu 18.04 LTS, 2 CPU, 2GB RAM, 50GB disk\n* Create the virtual environment and install the requirements for the application\n```\ncd /opt/selene/selene-backend/api/public\npipenv install\n```\n\n#### Precise API\n* Recommended server configuration: Ubuntu 18.04 LTS, 1 CPU, 1GB RAM, 5GB disk\n* Create the virtual environment and install the requirements for the application\n```\ncd /opt/selene/selene-backend/api/precise\npipenv install\n```\n### Running the APIs\nEach API is configured to run on port 5000.  This is not a problem if each is running in its own VM but will be an\nissue if all APIs are running on the same server, or if port 5000 is already in use.  To address these scenarios,\nchange the port numbering in the uwsgi.ini file for each API.\n\n#### Single Sign On API\n* The SSO application uses three JWTs for authentication. First is an access key, which is required to authenticate a\nuser for API calls.  Second is a refresh key that automatically refreshes the access key when it expires.  Third is a\nreset key, which is used in a password reset scenario.  Generate a secret key for each JWT.\n* Any data that can identify a user is encrypted.  Generate a salt that will be used with the encryption algorithm.\n* Access to the Github API is required to support logging in with your Github account.  Details can be found\n[here](https://developer.github.com/v3/guides/basics-of-authentication/).\n* The password reset functionality sends an email to the user with a link to reset their password.  Selene uses\nSendGrid to send these emails so a SendGrid account and API key are required.\n* Define a systemd service to run the API.  The service defines environment variables that use the secret and API keys\ngenerated in previous steps.\n```\nsudo vim /etc/systemd/system/sso_api.service\n```\n```\n[Unit]\nDescription=Mycroft Single Sign On Api\nAfter=network.target\n\n[Service]\nUser=mycroft\nGroup=www-data\nRestart=always\nType=simple\nWorkingDirectory=/opt/selene/selene-backend/api/sso\nExecStart=/usr/local/bin/pipenv run uwsgi --ini uwsgi.ini\nEnvironment=DB_HOST=\u003cIP address or name of database host\u003e\nEnvironment=DB_NAME=mycroft\nEnvironment=DB_PASSWORD=\u003cselene database user password\u003e\nEnvironment=DB_PORT=5432\nEnvironment=DB_USER=selene\nEnvironment=GITHUB_CLIENT_ID=\u003cgithub client id\u003e\nEnvironment=GITHUB_CLIENT_SECRET=\u003cgithub client secret\u003e\nEnvironment=JWT_ACCESS_SECRET=\u003caccess secret\u003e\nEnvironment=JWT_REFRESH_SECRET=\u003crefresh secret\u003e\nEnvironment=JWT_RESET_SECRET=\u003creset secret\u003e\nEnvironment=SALT=\u003csalt value\u003e\nEnvironment=SELENE_ENVIRONMENT=\u003ctest/prod\u003e\nEnvironment=SENDGRID_API_KEY=\u003csendgrid API key\u003e\nEnvironment=SSO_BASE_URL=\u003cbase url for single sign on application\u003e\n\n[Install]\nWantedBy=multi-user.target\n```\n* Start the sso_api service and set it to start on boot\n```\nsudo systemctl start sso_api.service\nsudo systemctl enable sso_api.service\n```\n\n#### Account API\n* The account API uses the same authentication mechanism as the single sign on API.  The JWT_ACCESS_SECRET,\nJWT_REFRESH_SECRET and SALT environment variables must be the same values as those on the single sign on API.\n* This application uses the Redis database so the service needs to know where it resides.\n* Define a systemd service to run the API.  The service defines environment variables that use the secret and API keys\ngenerated in previous steps.\n```\nsudo vim /etc/systemd/system/account_api.service\n```\n```\n[Unit]\nDescription=Mycroft Account API\nAfter=network.target\n\n[Service]\nUser=mycroft\nGroup=www-data\nRestart=always\nType=simple\nWorkingDirectory=/opt/selene/selene-backend/api/account\nExecStart=/usr/local/bin/pipenv run uwsgi --ini uwsgi.ini\nEnvironment=DB_HOST=\u003cdb host IP address or name\u003e\nEnvironment=DB_NAME=mycroft\nEnvironment=DB_PASSWORD=\u003cselene user database password\u003e\nEnvironment=DB_PORT=5432\nEnvironment=DB_USER=selene\nEnvironment=JWT_ACCESS_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=JWT_REFRESH_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=OAUTH_BASE_URL=\u003curl for oauth service\u003e\nEnvironment=REDIS_HOST=\u003cIP address or name of redis host\u003e\nEnvironment=REDIS_PORT=6379\nEnvironment=SELENE_ENVIRONMENT=\u003ctest/prod\u003e\nEnvironment=SALT=\u003csame as value for single sign on\u003e\n\n[Install]\nWantedBy=multi-user.target\n```\n* Start the account_api service and set it to start on boot\n```\nsudo systemctl start account_api.service\nsudo systemctl enable account_api.service\n```\n\n#### Marketplace API\n* The marketplace API uses the same authentication mechanism as the single sign on API.  The JWT_ACCESS_SECRET,\nJWT_REFRESH_SECRET and SALT environment variables must be the same values as those on the single sign on API.\n* This application uses the Redis database so the service needs to know where it resides.\n* Define a systemd service to run the API.  The service defines environment variables that use the secret and API keys\ngenerated in previous steps.\n```\nsudo vim /etc/systemd/system/market_api.service\n```\n```\n[Unit]\nDescription=Mycroft Marketplace API\nAfter=network.target\n\n[Service]\nUser=mycroft\nGroup=www-data\nRestart=always\nType=simple\nWorkingDirectory=/opt/selene/selene-backend/api/market\nExecStart=/usr/local/bin/pipenv run uwsgi --ini uwsgi.ini\nEnvironment=DB_HOST=\u003cdb host IP address or name\u003e\nEnvironment=DB_NAME=mycroft\nEnvironment=DB_PASSWORD=\u003cselene user database password\u003e\nEnvironment=DB_PORT=5432\nEnvironment=DB_USER=selene\nEnvironment=JWT_ACCESS_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=JWT_REFRESH_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=OAUTH_BASE_URL=\u003curl for oauth service\u003e\nEnvironment=REDIS_HOST=\u003cIP address or name of redis host\u003e\nEnvironment=REDIS_PORT=6379\nEnvironment=SELENE_ENVIRONMENT=\u003ctest/prod\u003e\nEnvironment=SALT=\u003csame as value for single sign on\u003e\n\n[Install]\nWantedBy=multi-user.target\n```\n* Start the market_api service and set it to start on boot\n```\nsudo systemctl start market_api.service\nsudo systemctl enable market_api.service\n```\n* The marketplace API assumes that the skills it supplies to the web application are in the Postgres database. To get\nthem there, a script needs to be run to download them from Github.  The script requires the GITHUB_USER, GITHUB_PASSWORD,\nDB_HOST, DB_NAME, DB_USER and DB_PASSWORD environment variables to run.  Use the same values as those in the service\ndefinition files.\n```\ncd /opt/selene/selene-backend/batch\npipenv install\npipenv run python load_skill_display_data.py --core-version \u003cspecify core version, e.g. 19.02\u003e\n```\n\n#### Device API\n* The device API uses the same authentication mechanism as the single sign on API.  The JWT_ACCESS_SECRET,\nJWT_REFRESH_SECRET and SALT environment variables must be the same values as those on the single sign on API.\n* This application uses the Redis database so the service needs to know where it resides.\n* The weather skill requires a key to the Open Weather Map API\n* The speech to text engine requires a key to Google's STT API.\n* The Wolfram Alpha skill requires an API key to the Wolfram Alpha API\n* Define a systemd service to run the API.  The service defines environment variables that use the secret and API keys\ngenerated in previous steps.\n```\nsudo vim /etc/systemd/system/public_api.service\n```\n```\n[Unit]\nDescription=Mycroft Public API\nAfter=network.target\n\n[Service]\nUser=mycroft\nGroup=www-data\nRestart=always\nType=simple\nWorkingDirectory=/opt/selene/selene-backend/api/public\nExecStart=/usr/local/bin/pipenv run uwsgi --ini uwsgi.ini\nEnvironment=DB_HOST=\u003cdb host IP address or name\u003e\nEnvironment=DB_NAME=mycroft\nEnvironment=DB_PASSWORD=\u003cselene user database password\u003e\nEnvironment=DB_PORT=5432\nEnvironment=DB_USER=selene\nEnvironment=EMAIL_SERVICE_HOST=\u003cemail host\u003e\nEnvironment=EMAIL_SERVICE_PORT=\u003cemail port\u003e\nEnvironment=EMAIL_SERVICE_USER=\u003cemail user\u003e\nEnvironment=EMAIL_SERVICE_PASSWORD=\u003cemail password\u003e\nEnvironment=GOOGLE_STT_KEY=\u003cGoogle STT API key\u003e\nEnvironment=JWT_ACCESS_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=JWT_REFRESH_SECRET=\u003csame as value for single sign on\u003e\nEnvironment=OAUTH_BASE_URL=\u003curl for oauth service\u003e\nEnvironment=OWM_KEY=\u003cOpen Weather Map API Key\u003e\nEnvironment=OWM_URL=https://api.openweathermap.org/data/2.5\nEnvironment=REDIS_HOST=\u003cIP address or name of redis host\u003e\nEnvironment=REDIS_PORT=6379\nEnvironment=SELENE_ENVIRONMENT=\u003ctest/prod\u003e\nEnvironment=SALT=\u003csame as value for single sign on\u003e\nEnvironment=WOLFRAM_ALPHA_KEY=\u003cWolfram Alpha API Key\nEnvironment=WOLFRAM_ALPHA_URL=https://api.wolframalpha.com\n\n[Install]\nWantedBy=multi-user.target\n```\n* Start the public_api service and set it to start on boot\n```\nsudo systemctl start public_api.service\nsudo systemctl enable public_api.service\n```\n\n### Testing the endpoints\n\nBefore we continue, let's make sure that your endpoints are operational - for this we'll use the `public_api` endpoint as an example.\n\n1. As we do not yet have a http router configured, we must change the `uwsgi` configuration for the endpoint we want to test. This is contained in: `/opt/selene/selene-backend/api/public/uwsgi.ini`. Here we want to replace\n    ```\n    socket = :$PORT\n    ```\n    with\n    ```\n    http = :$PORT\n    ```\n    then restart the service:\n    ```\n    sudo systemctl restart public_api.service\n    ```\n\n2. Check the status of the systemd service:\n    ```\n    systemctl status public_api.service\n    ```\n    Should report the service as \"active (running)\"\n\n3. Send a GET request from a remote device:\n    ```\n    curl -v http://$IP_ADDRESS:$PORT/code?state=this-is-a-test\n    ```\n    You can also monitor this from the service logs by running:\n    ```\n    journalctl -u public_api.service -f\n    ```\n\n## Other Considerations\n### DNS\nThere are multiple ways to setup DNS.  This document will not dictate how to do so for Selene.  However, here is an\nexample, based on how DNS is setup at Mycroft AI...\n\nEach application runs on its own sub-domain.  Assuming a top level domain of \"mycroft.ai\" the subdomains are:\n* account.mycroft.ai\n* api.mycroft.ai\n* market.mycroft.ai\n* sso.mycroft.ai\n\nThe APIs that support the web applications are directories within the sub-domain (e.g. account.mycroft.ai/api).  Since\nthe device API is externally facing, it is versioned.  It's subdirectory must be \"v1\".\n\n### Reverse Proxy\nThere are multiple tools available for setting up a reverse proxy that will point your DNS entries to your APIs. As such, the decision on how to set this up will be left to the user.\n\n### SSL\nIt is recommended that Selene applications be run using HTTPS.  To do this an SSL certificate is necessary.\n\n[Let's Encrypt](https://letsencrypt.org) is a great way to easily set up SSL certificates for free.\n\n## What About the GUI???\nOnce the database and API setup is complete, the next step is to setup the GUI, The README file for the\n[Selene UI](https://github.com/mycroftai/selene-ui) repository contains the instructions for setting up the web\napplications.\n\n## Getting Involved\n\nThis is an open source project and we would love your help. We have prepared a [contributing](.github/CONTRIBUTING.md)\nguide to help you get started.\n\nIf this is your first PR or you're not sure where to get started,\nsay hi in [Mycroft Chat](https://chat.mycroft.ai/) and a team member would be happy to guide you.\nJoin the [Mycroft Forum](https://community.mycroft.ai/) for questions and answers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMycroftAI%2Fselene-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMycroftAI%2Fselene-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMycroftAI%2Fselene-backend/lists"}