-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 11ac8d3
Showing
26 changed files
with
1,569 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
|
||
#ignore thumbnails created by windows | ||
Thumbs.db | ||
#Ignore files build by Visual Studio | ||
*.obj | ||
*.exe | ||
*.pdb | ||
*.user | ||
*.aps | ||
*.pch | ||
*.vspscc | ||
*_i.c | ||
*_p.c | ||
*.ncb | ||
*.suo | ||
*.tlb | ||
*.tlh | ||
*.bak | ||
*.cache | ||
*.ilk | ||
*.log | ||
[Bb]in | ||
[Dd]ebug*/ | ||
*.lib | ||
*.sbr | ||
obj/ | ||
[Rr]elease*/ | ||
_ReSharper*/ | ||
[Tt]est[Rr]esult* | ||
|
||
.idea/ | ||
.vs/ | ||
.DS_Store | ||
!StravaUpload.Lib/ | ||
|
||
|
||
#Ignore thumbnails created by Windows | ||
#Ignore files built by Visual Studio | ||
#Nuget packages folder | ||
packages/ | ||
local.appsettings.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2018 Marek Polak | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Strava upload | ||
|
||
Strava Upload is s simple library to synchronize (create, update) activities on **Strava** with other activities. Currently it provides synchronization with **Suunto Movescount** moves that | ||
are provided by [**MovescountBackup** library](https://github.com/marazt/movescount-backup). | ||
|
||
## Version | ||
|
||
- **Version 1.0.0** - 2018-03-15 | ||
|
||
### Getting Started/Installing | ||
|
||
```ps | ||
PM> Install-Package StravaUpload -Version 1.0.0 | ||
``` | ||
|
||
## Project Description | ||
|
||
The solution consists of the following projects: | ||
|
||
- **StravaUpload.Lib** is the main library containing `Uploader` class. | ||
|
||
- **StravaUpload.Console** is just a sample that downloads *Movescount* data, store them on local dist and sync them with *Strava*. | ||
|
||
- **StravaUpload.StravaUploadFunction** Azure function that periodically downloads data from *Movescount*, store them in *Azure Blob Storage* and sync them with *Strava*. | ||
|
||
- **StravaUpload.Lib.Spec** TODO. | ||
|
||
|
||
### Prerequisites | ||
|
||
- .NET Core 2.0. | ||
- For more details about *MovescountUpload* check the [project site](https://github.com/marazt/movescount-backup) | ||
|
||
### Configuration | ||
|
||
#### StravaUpload.Lib | ||
|
||
- **StravaAccessToken** - Name of the member whose data we want to get. | ||
|
||
#### StravaUpload.Console | ||
|
||
- **MovescountAppKey** - App key to be able to query Movescount API. | ||
- **MovescountUserKey** - User key to be able to query Movescount API. | ||
- **MovescountUserEmail** - User email to be able to query Movescount API. | ||
- **MovescountMemberName** - Name of the member whose data we want to get. | ||
- **CookieValue** - A cookie value that is needed to export GPX, TCX and other move files. | ||
This value can be get by the following steps: | ||
1. Open console in your browser to se network requests. | ||
1. Login into Movescount. | ||
1. Select a requeset to `http://www.movescount.com/api/members/private/messages`. | ||
1. Copy value of `Cookie` key in request header. It should start with `ASP.NET ...`. | ||
- **BackupDir** - Directory where moves should be stored. Required for `FileSystemStorage`. | ||
- **StorageConnectionString** - Connection string to Azure Blob Storage. Required for `CloudStorate`. | ||
- **ContainerName** - Container name on Azure Blob Storage. Required for `CloudStorate`. | ||
- **StravaAccessToken** - Strava access token wit write rights. | ||
|
||
#### StravaUpload.StravaUploadFunction | ||
|
||
- **MovescountAppKey** - App key to be able to query Movescount API. | ||
- **MovescountUserKey** - User key to be able to query Movescount API. | ||
- **MovescountUserEmail** - User email to be able to query Movescount API. | ||
- **MovescountMemberName** - Name of the member whose data we want to get. | ||
- **CookieValue** - A cookie value that is needed to export GPX, TCX and other move files. | ||
This value can be get by the following steps: | ||
1. Open console in your browser to se network requests. | ||
1. Login into Movescount. | ||
1. Select a requeset to `http://www.movescount.com/api/members/private/messages`. | ||
1. Copy value of `Cookie` key in request header. It should start with `ASP.NET ...`. | ||
- **BackupDir** - Directory where moves should be stored. Required for `FileSystemStorage`. | ||
- **StorageConnectionString** - Connection string to Azure Blob Storage. Required for `CloudStorate`. | ||
- **ContainerName** - Container name on Azure Blob Storage. Required for `CloudStorate`. | ||
- **StravaAccessToken** - Strava access token wit write rights. | ||
- **SendGridApiKey** - API key for *SendGrid* mail service to be able to send status messages. | ||
- **EmailFrom** - Email from. | ||
- **EmailTo** - Email to. | ||
|
||
### StravaUpload.Lib.Uploader.cs | ||
|
||
Uploader is the main class for activity synchronization. | ||
It downloads activities list from **Strava**, compare them with list of moves that should be added/updated. | ||
The first comparison is done by activity/move start/end datetime. If an acitvity is found in **Strava**, it is updated. If the activity is | ||
not found in **Strava**, *fit*, *gpx* or other activity data file is uploaded. | ||
It can happen that newly uploaded activity is already in **Strava**. This state is evaluated from the upload response. In this | ||
case, the activity is just updated. | ||
|
||
## Deployment | ||
|
||
You can use this libraly to be run manually (`StravaUpload.Console.Program.cs`) or you can create, e.g., a *Azure function* (`StravaUpload.StravaUploadFunction.Function.cs`) or *Lambda function on AWS*, that can run periodically. | ||
|
||
## Contributing | ||
|
||
Any contribution is welcomed. | ||
|
||
## Authors | ||
|
||
- **Marek Polak** - *Initial work* - [marazt](https://github.com/marazt) | ||
|
||
## License | ||
|
||
© 2018 Marek Polak. This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. | ||
|
||
## Acknowledgments | ||
|
||
- Enjoy it! | ||
- If you want, you can support this project too. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace StravaUpload.Console | ||
{ | ||
|
||
public class Configuration : MovescountBackup.Lib.IConfiguration, Lib.IConfiguration | ||
{ | ||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable | ||
private readonly IConfigurationRoot root; | ||
|
||
public Configuration() { } | ||
|
||
public Configuration(IConfigurationRoot root) | ||
{ | ||
this.root = root; | ||
|
||
this.MovescountAppKey = this.root["AppConfig:MovescountAppKey"]; | ||
this.MovescountUserEmail = this.root["AppConfig:MovescountUserEmail"]; | ||
this.MovescountUserKey = this.root["AppConfig:MovescountUserKey"]; | ||
this.MovescountMemberName = this.root["AppConfig:MovescountMemberName"]; | ||
this.BackupDir = this.root["AppConfig:BackupDir"]; | ||
this.CookieValue = this.root["AppConfig:CookieValue"]; | ||
this.StorageConnectionString = this.root["AppConfig:StorageConnectionString"]; | ||
this.ContainerName = this.root["AppConfig:ContainerName"]; | ||
this.StravaAccessToken = this.root["AppConfig:StravaAccessToken"]; | ||
} | ||
|
||
public string MovescountAppKey { get; set; } | ||
|
||
public string MovescountUserEmail { get; set; } | ||
|
||
public string MovescountUserKey { get; set; } | ||
|
||
public string MovescountMemberName { get; set; } | ||
|
||
public string BackupDir { get; set; } | ||
|
||
public string CookieValue { get; set; } | ||
|
||
public string StorageConnectionString { get; set; } | ||
|
||
public string ContainerName { get; set; } | ||
|
||
public string StravaAccessToken { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Diagnostics.CodeAnalysis; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace StravaUpload.Console | ||
{ | ||
[SuppressMessage("ReSharper", "UnusedMember.Global")] | ||
public class ConsoleLogger : ILogger | ||
{ | ||
public void Error(string message) | ||
{ | ||
System.Console.WriteLine($"Error: {message}"); | ||
} | ||
|
||
public void Information(string message) | ||
{ | ||
System.Console.WriteLine($"Information: {message}"); | ||
} | ||
|
||
public void Warning(string message) | ||
{ | ||
System.Console.WriteLine($"warning: {message}"); | ||
} | ||
|
||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) | ||
{ | ||
System.Console.WriteLine(state.ToString()); | ||
} | ||
|
||
public bool IsEnabled(LogLevel logLevel) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public IDisposable BeginScope<TState>(TState state) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
|
||
[SuppressMessage("ReSharper", "UnusedMember.Global")] | ||
public class ConsoleLogger<T> : ILogger<T> | ||
{ | ||
public void Error(string message) | ||
{ | ||
System.Console.WriteLine($"Error: {message}"); | ||
} | ||
|
||
public void Information(string message) | ||
{ | ||
System.Console.WriteLine($"Information: {message}"); | ||
} | ||
|
||
public void Warning(string message) | ||
{ | ||
System.Console.WriteLine($"warning: {message}"); | ||
} | ||
|
||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) | ||
{ | ||
System.Console.WriteLine(state.ToString()); | ||
} | ||
|
||
public bool IsEnabled(LogLevel logLevel) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public IDisposable BeginScope<TState>(TState state) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.Configuration; | ||
using MovescountBackup.Lib.Services; | ||
using Strava.Upload; | ||
using StravaUpload.Lib; | ||
|
||
namespace StravaUpload.Console | ||
{ | ||
static class Program | ||
{ | ||
// ReSharper disable once UnusedParameter.Local | ||
static async Task Main(string[] args) | ||
{ | ||
var configuration = SetupConfiguration(); | ||
var client = new Client(configuration, new ConsoleLogger<Client>()); | ||
var storage = new FileSystemStorage(); | ||
var downloader = new Downloader(configuration, client, storage, new ConsoleLogger<Downloader>()); | ||
var moves = await downloader.DownloadLastUserMoves(configuration.MovescountMemberName); | ||
|
||
var uploader = new Uploader(configuration.StravaAccessToken, new ConsoleLogger<Uploader>()); | ||
|
||
var fileFormat = DataFormat.Tcx; | ||
var movesData = moves.Select(move => (move, | ||
Path.Combine(configuration.BackupDir, move.MoveId.ToString(), Uploader.CreateGpsFileMapName(fileFormat)), | ||
fileFormat)).ToList(); | ||
|
||
try | ||
{ | ||
await uploader.AddOrUpdateMovescountMovesToStravaActivities(movesData); | ||
} | ||
catch (Exception ex) | ||
{ | ||
System.Console.WriteLine("Error while uploading activities"); | ||
System.Console.WriteLine(ex.Message); | ||
System.Console.WriteLine(ex.StackTrace); | ||
} | ||
} | ||
|
||
|
||
private static Configuration SetupConfiguration() | ||
{ | ||
var builder = new ConfigurationBuilder() | ||
.SetBasePath(Directory.GetCurrentDirectory()) | ||
.AddJsonFile("appsettings.json", false, true) | ||
.AddEnvironmentVariables(); | ||
var configuration = builder.Build(); | ||
return new Configuration(configuration); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp2.0</TargetFramework> | ||
<LangVersion>7.1</LangVersion> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<None Remove="appsettings.json" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Content Include="appsettings.json"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</Content> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\StravaUpload.Lib\StravaUpload.Lib.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"Logging": { | ||
"IncludeScopes": false, | ||
"LogLevel": { | ||
"Default": "Warning" | ||
} | ||
}, | ||
"AppConfig": { | ||
"MovescountAppKey": "TODO", | ||
"MovescountUserEmail": "TODO", | ||
"MovescountUserKey": "TODO", | ||
"MovescountMemberName": "TODO", | ||
"CookieValue": "TODO", | ||
"BackupDir": "TODO", | ||
"StravaAccessToken": "TODO", | ||
"StorageConnectionString": "TODO", | ||
"ContainerName": "TODO" | ||
} | ||
} |
Oops, something went wrong.