Giter Club home page Giter Club logo

core's Introduction

Strautomator Core

This is the core module of Strautomator, containing most of its business logic. This project doesn't run by itself, but is used by the Web and Functions.

Getting started

Some main points to know before you start:

  • Code is mostly TypeScript
  • Should run on Node 18+
  • Highly optimized for GCP (Google Cloud Platform)

Required 3rd party services

Mandatory credentials:

Optional credentials:

  • Garmin Connect API
  • GitHub API
  • LocationIQ API
  • musixmatch API
  • OpenAI API
  • PayPal API
  • Spotify API
  • Wahoo Cloud API
  • Weather providers: Open-Meteo, OpenWeatherMap, Tomorrow.io, Visual Crossing, WeatherAPI

Please note that most of the services listed above have a free / trial version, which should be enough for testing or a single user use case. For multiple power users, you might need to subscribe to paid plans.

Getting your GCP credentials

Once you have created a project in GCP, it's recommended to create a dedicated service account with full permissions to Firestore and Storage Buckets. You could also use an existing service account, as long as you make sure it has the aforementioned permissions.

You'll need to download a set of JSON credentials for that account:

  1. Open the credentials overview.
  2. On the Service Accounts list, click on the desired service account email.
  3. Go to the Keys tab, then click on Add Key > Create new key.
  4. Select JSON format and create.
  5. Save the file as ~/gcp-strautomator.json, on your home folder.

Settings

Strautomator is using the SetMeUp module to handle its settings, so for detailed info please check its docs. The settings are split as follows:

  • settings.json - settings shared by all environments, targeting production by default
  • settings.development.json - development settings, mostly when running on your dev machine
  • settings.production.json - production-only settings, except credentials and secrets (optional)
  • settings.secret.json - private credentials and secrets, excluded from the GIT repo
  • GCS settings - optional, will be downloaded from a Google Cloud Storage bucket on startup

Additionally, you can also define settings via environment variables, prefixed by SMU and separating levels with underscore. So for instance to define the app.title via an environment variable, you should set the value on $SMU_app_title. To define gcp.projectId, use $SMU_gcp_projectId. And so on.

If you want to download settings from Google Cloud Storage, you must define the gcp.downloadSettings.bucket (or via the $SMU_gcp_downloadSettings_bucket env variable). The default filename is settings.secret.json, but you can change that as well. The settings file downloaded from GCS will NOT persist on the disk.

Please note that settings specific to the web server, API and other web-specific features are defined on files directly on the Strautomator Web. Same procedure, same logic.

Database

By default Strautomator uses Google Cloud Firestore to store its data. But the database wrapper was made in such a way that it should be pretty easy to implement other document based data stores as well, such as MongoDB or DynamoDB.

The following collections are used:

  • app-state general application state
  • activities processed activities
  • announcements website announcements
  • athlete-records athlete sports records
  • calendars exported Strava calendars
  • faq help questions and answers
  • garmin cached Garmin data
  • gearwear GearWear configurations
  • komoot cached Komoot routes
  • lyrics cached Lyrics from musixmatch
  • maps cached geolocation data
  • notifications notifications to users
  • recipe-stats automation recipe stats
  • subscriptions PRO subscriptions
  • strava-cache cached responses from Strava
  • users registered user details
  • wahoo cached Wahoo data

Also note that these collections might have a suffix, depending on the settings. On development, the default suffix is -dev.

Some indexes are needed in Firestore. At the moment there's no automated creation, so you might see some warnings or errors on the logs asking to create an index before a specific query can be executed. Just follow the links provided directly on the console logs.

Storage

Strautomator will store some files on Google Cloud Storage buckets:

  • calendar cached calendar outputs, default name is bucket-calendar.strautomator.com
  • gdpr ZIP archives requested by users, default name is bucket-gdpr.strautomator.com

Buckets can have an optional TTL (days) policy, also defined on the settings as "ttlDays". If a bucket does not exist, it will be created during startup. If no "location" is set directly on the bucket settings, then the default is taken from the setting gcp.location.

By default, buckets in production are created as CNAME records. This can be disabled by setting the settings.storage.cname flag to false.

IAM policy

Please make sure that the service account being used has full permissions to read and write to your GCP project Storage buckets. Otherwise you'll have to create the buckets manually and assign the required permissions via the GCP Console.

Make

All the necessary commands to update, build and deploy the Strautomator Core are done using make. For instance, to update the Node.js dependencies and set a new package version:

$ make update

Or to do a "dry run" and test the startup routine with the current settings:

$ make dry-run

Please have a look on the provided Makefile for all available commands.

Hosting on GCP

Strautomator is currently optimized to run on Google Cloud Platform. It makes use of Firestore, Cloud Storage, and various other Google APIs to get things working. There are no plans to port the code to make it work in other ecosystems, but as all the code is wrapped in its own specific set of modules, such tasks should be easily doable.

core's People

Contributors

cgraabaek avatar igoramadas avatar nieko-nera avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

core's Issues

Create GearWear based conditions on automation recipes

Depends on #3

Once the enable / disable toggle has been implemented on GearWear components, create a new automation action to enable / disable specific components. Example: when riding on a specific track, set the correct wheelset being used.

Dutch language

Could you please also include the Dutch language in Strautomator.

Thanks!

Feature request: mid-ride location and weather tags

Currently, only start and end location tags are supported, but 99% of my rides start and end at the same place - home, so I have no use for them.
It would be awesome to add location tags for a point half-way through the ride (cityMiddle/countryMiddle) - which is roughly the destination of the ride - to be able to e.g. append it to the ride name.
Currently, I have to do it manually for each ride.

Less important, but also weather tags for the mid-point location could arguably be more useful than beginning/end.

Thank you.

Does AI consider temperature being specified in Fahrenheit?

I do not have any hard proof, but is there any chance that ai engine that generates titles and verses assumes that temperature values are Fahrenheit?

Why do I think so? I noticed that it uses words that describe frosty or very cold weather when it is actually between 5 to 10°C (just didn't experience any warmer air recently). Which would make sense in Fahrenheit, as 10°F equals -12°C.

${maxPace} for indoor activities

For the past few weeks, ${maxPace} has been returning an empty value for treadmill runs (and probably treadmill walks, as well).

Was this an intended change? It had been working fine for months, and it still works correctly with outdoor walks/runs.

${avgPace} still works for indoor walks/runs, as do ${avgSpeed} and ${maxSpeed}.

Redirect loop during login

I'm getting a redirect loop when trying to use the "Connect with Strava" login button on strautomator.com. It would be nice to have some sort of contact form to contact you directly using the web site since this is not really a Github issue.

[Feature request] : mixing AND and OR

Hello.

I'd love to be able to create a complex condition like (Tuesday AND 20h) OR (Friday AND 19H) OR (Sunday AND 10H), or eventually even more complex, leading to one action.

Building an interface for this is not easy, but it could be JSON-editable only (and restricted to pro users).

Weather.Start & Weather.End Identical?

I went on a 10½-hour hike yesterday, and my automation, which shows both starting and ending weather for summary, temperature, humidity, wind speed, and direction produced the same values for start and end on every measurement. This was clearly not the case. In particular, I ended my activity at night, and as far as I can tell the ending weather icon should have shown a moon; however, it still showed a sun.

I was using the default weather provider, but then tried all the others, and they had the same issue.

Also, changing between weather providers and triggering a new manual sync did not change the weather at all between providers. Is there a limit to how often we can change weather providers and query for new weather data? I figured there might be some caching going on.

Lastly, if I trigger a manual sync with the same weather provider, I sometimes get wildly different weather outputs (for all values). Just now I triggered two successive syncs with the default weather provider and got very different results.

The activity ID is 9091862726.

Spotify track list added to description in reverse order

Just opened an account, added an automation to replace Perform, ran a manual sync of an activity and saw that the tracks were populated in reverse order of how I listened to them.

I don’t think order is guaranteed by the Spotify API, but it does seem to return in reverse listening order.

This will also impact first and last track.

For a short term fix, you could just push to the front of your tracks array (unshift()), but may want to manually order items to future proof it, especially if Spotify has changed this behavior recently.

I have the technical skill to do the quick fix, not the long term one, and happy to submit the 1 line PR if helpful.

const res = await this.makeRequest(tokens, `me/player/recently-played?after=${tsFrom}&limit=${settings.spotify.trackLimit}`)

Weather tags translation improvements

After playing around with Strautomator I did notice that the weather tags seem to be a little weird when I try to use it for me (in Dutch).
CleanShot 2023-06-27 at 17 29 11@2x

For example kph would for us be better translated to km/u

Also looking at the code it would be similar with the wind directions:

const directions = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"]

S (South) -> Z (Zuid)
E (East) -> O (Oost)

These are little details but it does bring the result to a higher level 😅

If I understood the translations/index.ts function correctly you wouldn't need to add the translations for each language as it would fall back to returning the id/key. The behaviour would remain the same for other users (until they have provided/requested translations).

Let me know what you think.

Automation triggered for incorrect total elapsed time conditions

I have 2 automations for workout sport type where total elapsed time is mainly used to determine which automation to be executed:

  • Daily workout: 00:20 h < total elapsed time < 01:00 h (between 20 minutes and 1 hour)
  • Cold shower: total elapsed time < 00:03 h (less than 3 minutes)

Daily workout automation was created a while back and worked fine by itself. After I created Cold shower automation, workouts that match Daily workout automation are now processed by the Cold shower automation.

Is there something that I have misconfigured, or there is something else causing the issue?

Debugging info

Strava activity IDs that were both processed today as Cold shower:

  • 6482483181 (should have been processed by Daily workout automation)
  • 6482483634 (processed correctly by Cold shower automation)
CleanShot 2022-01-06 at 19 44 56@2x

Thanks!

action to trigger "adjust elevation" for activities

my polar device's barometric altimeter is very inaccurate, resulting in completely wrong power estimates for activities and segments. would it be possible, to trigger the ... "adjust elevation" command of strava, in order to use strava basemap data?

perceivedExertion not being expanded in template

I have a calendar template like this:

${distance} @ ${speedAvg} (${perceivedExertion})
${elevationGain} (${climbingRatio})
${hrAvg}, ${wattsAvg}
Ride: ${gear}

But the resulting entries in ical look like this:

42.2mi @ 13mph (${perceivedExertion})
981ft (0.23)
145bpm, 149watts
Ride: Rove

Lithuanian language

Can You please add Lithuanian language for weather? I think OpenWeather supports it, and klimat.app supports Lithuanian :)

Add option to remove "accidental" stop/starts from activity

Love the work btw, thank you.

Strava annoyingly does not allow you to alter the following behaviour.
It gives you moving time for an activity if it is continuous, however, if you have a single stop/start during the activity then it gives you the overall time for the activity. I normally don't start/stop the timer during an activity... however, sometimes it gets caught on jacket or something... and occurs accidentally.

Strava then reports the overall moving time = activity time...

Can Strautomator have an option to clean stop/starts from an activity so strava calculates moving time correctly?

Condition on app name

Hi,

I tried setting up an automation based on the app uploading to Strava, but have no luck with it.

In strava I cannot see the name, but if I download a .tcx file I can see <Creator xsi:type="Device_t"><Name>BODY BIKE Smart+</Name></Creator>, but the condition does not work.

A I doing something wrong or does the condition not work?

Spotify integration not working

Hey, the Strava integration for listened tracks does not seem to be working.

I tried troubleshooting using a ride on Aug 19 (9680302450), which should have returned a lot of Taylor Swift.
IMG_0782

I’m not seeing any errors, and I unlinked Spotify and relinked, which didn’t fix it, so figured it might not be on my end.

Let me know if there’s any add’l information I can provide to help.

Thanks!

Mute Activity is possible with Strava API... :)

I just tried out the Strava API for the new mute functionality, and it seems to be possible. According to the swagger api, I managed to porperly update the mute flag for my activities using the v3 api.

the put /api/v3/activity/{id} works with the following body:

{
"hide_from_home": true
}

This will cause the expected behavior, even though it is not officially supported by the strava API in UpdateableActivity... ;)

Can you add this rule to the strautomator?

Weather summary has trailing space

My weather automation looks like this:

Set activity description: ${weather.icon} ${weather.summary}, ${weather.temperature} (feels like ${weather.feelsLike}), humidity ${weather.humidity}, wind ${weather.windSpeed} ${weather.windDirection} 

And I end up with descriptions like this:

☀ Cool, clear , 20°C (feels like 20°C), humidity 83%, wind 52 kph W

Note the Cool, clear ,: the comma comes after a space which shouldn't be there.

I think this comes from this line, not sure why there's a trailing space:

summary.summary = `${tempSummary}, ${translation(extraData.iconText, preferences)} `

Feature Request: Allow Date Fields to be formatted with options

Hello,

I would like to use the date in my titles but I don't think the current option suffices.

right now ${dateStart} delivers something like '04/04/2023 16:33h'

I think it would be best to have something like ${dateStart.format('DD-MMM-YYYY HH:mm:ss')} or similar, but with a free format spec.

I believe every language should have a default function for this.

we would be free to use any date or time piece in the automation.

Please add more geolocation radius options

Hi,

I have found that a radius of 60m is not working for me, maybe because I have privacy settings for Strava to restrict 250m of start and endpoint on certain locations. I find the 650m radius too big though. Would it be possible to add a 300m option? Strava has a 200m option, so 100m more should be enough to cover most of activities if gps precision is good enough...

Allow disabling / enabling specific GearWear components

Make it possible to disable (and re-enable) individual components. By doing so it will be possible to track different wheelsets, tires etc for the same bike as long as the user does change the active components beforehand.

Wrong Cadence on Running Activities

Strautomator reports half the cadence for running activities. You can see on activity ID 9066037696 that Strava correctly reports the value recorded by my Apple Watch (182 SPM), whereas Strautomator printed out 91.2.

(I’ve manually adjusted the value to 182.4 in my description, but it was 91.2 coming out of Strautomator.)

From looking at the code under recipes/lists.ts, I see that cadenceAvg is interpreted as RPM. It would make sense that in cycling, the RPM would be equal to half the SPM.

Thank you for the great utility!

Note: Other foot-based activities can report the cadence to Strava, not just running. This includes walking, hiking, snowshoeing, trail running, and possibly others (like cross-country skiing).

AI activity name cutoff

Not sure what went wrong but it seems that the generated name was to long and that some of it was cut off.
It seems to be cutoff on Strautomator side I am guessing, in Strava UI I could manually edit the activity and add more characters.

CleanShot 2024-05-27 at 19 59 25@2x
It is in Dutch 😅

Strava gear update/refresh

I've added a new bike on Strava and it hasn't been synced with Strautomator.

I think Strava API doesn't send events when gear is changed, so we'd have to manually sync. Can you add that feature?

Activity fortunes are sometimes cut off with ChatGPT

First off - the integration with ChatGPT is great. The names generated seem far better and more appropriate now. I did however notice when testing some previous activities to see what name was generated that sometimes they appear to be cut off. An example:

Oh, just a casual 113.7km in under 5 hours with a measly

This happened to me a few times with activities I tested. It appears somewhere in the process there might be a character limit that is being enforced.

Account settings not saved

Hi,

first of all, thanks for that awesome app!

I am facing an issue where i try to set "Wind speed unit", "language" and "FTP auto update" on the account page.
I can change the settings and see the outgoing requests to the server. However, if I reload the page (e.g.: Strg + F5), the mentioned settings are resetted to it's original values.

Browser: latest Chrome

Request example:

POST https://strautomator.com/api/users/15751672/preferences

{
    "ftpAutoUpdate": false,
    "linksOn": 0,
    "delayedProcessing": false,
    "gearwearDelayDays": 2,
    "activityHashtag": false,
    "noSuffixes": false,
    "privacyMode": false,
    "weatherProvider": null,
    "weatherUnit": "c",
    "windSpeedUnit": "m/s", <-- changed value from "kph" to "m/s"
    "language": "en",
    "aiProvider": "openai",
    "aiPrompt": "",
    "dateResetCounter": false
}

BR,
Thomas

Feature request: Mark ride as NOT commute

This is perhaps me not figuring out Strava's defaults but every time I ride my e-bike around town, Strava marks it as a commute. I never commute on this bike so if there's a setting in Strava to remove it I would do that but in absence of that it'd be great if Strautomator had the ability to remove the commute tag.

Allow modification of "Who can view"

I like to keep most of my activities shared with only followers. However, if the activities have no ties to my home address I'd like to make them public to be included in Strava statistics/records. I can't see an option to modify an activity's visibility/privacy as shown
image

Feature Request: Enhanced Private Notes Functionality

I want to propose an enhancement to the current private notes functionality on Strautomator.

Current Issue:
The existing functionality only allows setting private notes, which erases all previous information contained in the note.

Feature Idea:
Since we already have the logic to append and prepend text to activity descriptions, implementing similar functionality for private notes could be a natural and beneficial extension.

Bug: Automation keeps getting disabled

I have an automation to mark my Peloton rides as virtual rides, assign the correct bike, and change it to a virtual ride. It seems every time I come back to the site (daily, after I do my workouts) the automation has disabled itself.

JSON of automation is

{
    "conditions": [
        {
            "property": "trainer",
            "value": true,
            "operator": "=",
            "friendlyValue": "Yes"
        },
        {
            "property": "sportType",
            "value": "Ride,GravelRide,MountainBikeRide,EBikeRide,EMountainBikeRide,VirtualRide",
            "operator": "=",
            "friendlyValue": "Ride or Gravel Ride or Mountain Bike Ride or E Bike Ride or E Mountain Bike Ride or Virtual Ride"
        }
    ],
    "actions": [
        {
            "type": "sportType",
            "value": "VirtualRide",
            "friendlyValue": "Virtual Ride"
        },
        {
            "type": "gear",
            "value": "b13183031",
            "friendlyValue": "Peloton Bike+ (bike)"
        },
        {
            "type": "workoutType",
            "value": 12,
            "friendlyValue": "Ride: Workout"
        }
    ]
}

The ID of my automation is r64f8aa4f. Am I doing something wrong here or is it a bug?

Ride/Run Type

could You add an automatic Ride/Run Type and Bike/Shoes changing action

I have to set End time -1 hr for the automation to trigger correctly

Thank you for the great tool with great value at great price.

I have the following automation defined:

{
    "conditions": [
        {
            "property": "weekday",
            "value": "1,2,3,4,5",
            "operator": "=",
            "friendlyValue": "Monday or Tuesday or Wednesday or Thursday or Friday"
        },
        {
            "property": "dateEnd",
            "value": 30600,
            "operator": ">",
            "friendlyValue": "08:30"
        },
        {
            "property": "dateEnd",
            "value": 63000,
            "operator": "<",
            "friendlyValue": "17:30"
        }
    ],
    "actions": [
        {
            "type": "prependName",
            "value": "Active break "
        }
    ]
}

What I actually wanted is to have the automation triggered on activity end time between 9:30 and 18:30. Had to subtract 1 hr in conditions for the trigger to work within expected time range. Not sure if it is a bug or a user is expected to define the time as if they were in UTC TZ.

P.S. Great UX. Defining automations is intuitively clear. I realized the benefits just after setting two automations. Was able to discard another single job Strava App. --- Yours sincerely happy subscriber.

The only UX thing I'd suggest is that Logical operators section followed the Conditions sections immediately if not come first. There must be a reason it follows Actions for, but lmk if you want me to submit a proposal as an issue here.

Strava 0 Watt Challenge

Hello,

Recently I've been wondering to implement a a feature to track what is the longest you rode with your bike without doing any effort (hence, 0W challenge). I wanted to implement as a challenge that is tracked throughout your activities and updates whenever you had a new personal best, that's why I came across your project.

The concept is simple: if you have data from either power meter or cadence sensor, it would track the individual distance segments that you covered without doing any effort, and it would take the max segment for the ride. It would then be a select-able metric for your strava automation.

My questions are:

  • Do you think this is doable using the strava api?
  • Would you be willing to review such feature?
  • Could you point me out, in the current implementation where this could be done?

I'm of course willing to implement this feature.

Wind speed values seem very off (unnecessary conversion?)

I'm using ${weather.start.windSpeed} on automation and I've tried both m/s and km/h and the values seem very high (no idea about the provider that I'm using, it's a free account) about x3 the real value (maybe the values obtained are assumed to be on m/s and there is an unnecessary conversion?).

E.g. right now it said I run with a wind of 103km/h 👯

I've checked both OpenWeatherMap and OpenMeteo and the value on their API is right.

Additional tags for activity names (and descriptions)

I'd like to improve on the default Strava activity naming but there are some tags that I don't see in the UI. Specifically, I'd like to be able to add:

  1. The activity type (e.g. Run or Ride)
  2. The city or general location name. Similar to Garmin's default names based on the activity location (e.g. Chicago Run).

Improvement OpenAI generated name: translation support

It would be very nice if the OpenAI prompt also included translation language.
You are also passing the UserData object so the information should already be available.
I did a small test in the free prompt and it seemed to work.
CleanShot 2023-06-26 at 21 55 06@2x
Also tried language codes:
CleanShot 2023-06-26 at 21 56 50@2x

Automation failure when using OR operator

Hi there! I'm a big fan that Strautomator exists - thanks for making it! I've been trying to use it for a couple things - (1) auto set a bike if I'm using the trainer and (2) auto name workouts that are input as 'workout' or 'pilates'.

I'm consistently having the automation fail when using the OR operator for condition (2). If I disable the OR and only query one of the two conditions, it works.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.