completing part walker, adding month string getters
This commit is contained in:
parent
dd9e3aab42
commit
ac8ea2723a
@ -3,9 +3,11 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Mixonomer.Fire\Mixonomer.Fire.csproj" />
|
<ProjectReference Include="..\Mixonomer.Fire\Mixonomer.Fire.csproj" />
|
||||||
|
<ProjectReference Include="..\Mixonomer.Playlist\Mixonomer.Playlist.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -3,19 +3,21 @@ using System.Linq;
|
|||||||
using Mixonomer.Fire;
|
using Mixonomer.Fire;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Mixonomer.Fire.Extensions;
|
using Mixonomer.Fire.Extensions;
|
||||||
|
using Mixonomer.Playlist;
|
||||||
|
|
||||||
namespace Mixonomer.CLI
|
namespace Mixonomer.CLI;
|
||||||
|
|
||||||
|
class Program
|
||||||
{
|
{
|
||||||
class Program
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
static async Task Main(string[] args)
|
var repo = new UserRepo(projectId: System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT"));
|
||||||
{
|
|
||||||
var repo = new UserRepo(projectId: "mixonomer-test");
|
|
||||||
|
|
||||||
var userContext = await repo.GetUserContext("andy");
|
var userContext = await repo.GetUserContext("andy");
|
||||||
|
|
||||||
Console.WriteLine(userContext.User);
|
Console.WriteLine(userContext.User);
|
||||||
}
|
|
||||||
|
var walker = new PartTreeWalker(repo);
|
||||||
|
var partPlaylists = await walker.GetPlaylistParts("andy", "RAP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,60 +4,69 @@ using System.Threading.Tasks;
|
|||||||
using Google.Cloud.Firestore;
|
using Google.Cloud.Firestore;
|
||||||
using Mixonomer.Fire.Model;
|
using Mixonomer.Fire.Model;
|
||||||
|
|
||||||
namespace Mixonomer.Fire.Extensions
|
namespace Mixonomer.Fire.Extensions;
|
||||||
|
|
||||||
|
public static class UserRepoExtensions
|
||||||
{
|
{
|
||||||
public static class UserRepoExtensions
|
public static async IAsyncEnumerable<User> GetUsers(this UserRepo repo)
|
||||||
{
|
{
|
||||||
public static async Task<IAsyncEnumerable<DocumentSnapshot>> GetPlaylistDocs(this UserRepo repo, string username)
|
var users = repo.GetUserDocs();
|
||||||
|
|
||||||
|
await foreach (var user in users)
|
||||||
{
|
{
|
||||||
var user = await repo.GetUser(username).ConfigureAwait(false);
|
yield return user.ConvertTo<User>();
|
||||||
|
|
||||||
return await repo.GetPlaylistDocs(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async IAsyncEnumerable<Playlist> GetPlaylists(this UserRepo repo, User user)
|
|
||||||
{
|
|
||||||
var playlists = await repo.GetPlaylistDocs(user).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await foreach (var playlist in playlists)
|
|
||||||
{
|
|
||||||
yield return playlist.ConvertTo<Playlist>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<IAsyncEnumerable<DocumentSnapshot>> GetTagDocs(this UserRepo repo, string username)
|
|
||||||
{
|
|
||||||
var user = await repo.GetUser(username).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return await repo.GetTagDocs(user).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async IAsyncEnumerable<Tag> GetTags(this UserRepo repo, User user)
|
|
||||||
{
|
|
||||||
var tags = await repo.GetTagDocs(user).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await foreach (var tag in tags)
|
|
||||||
{
|
|
||||||
yield return tag.ConvertTo<Tag>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<UserContext> GetUserContext(this UserRepo repo, string username)
|
|
||||||
{
|
|
||||||
var user = new UserContext
|
|
||||||
{
|
|
||||||
User = await repo.GetUser(username).ConfigureAwait(false)
|
|
||||||
};
|
|
||||||
|
|
||||||
var playlists = repo.GetPlaylists(user.User).ToListAsync();
|
|
||||||
var tags = repo.GetTags(user.User).ToListAsync();
|
|
||||||
|
|
||||||
await Task.WhenAll(playlists.AsTask(), tags.AsTask()).ConfigureAwait(false);
|
|
||||||
|
|
||||||
user.Playlists = playlists.Result;
|
|
||||||
user.Tags = tags.Result;
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<IAsyncEnumerable<DocumentSnapshot>> GetPlaylistDocs(this UserRepo repo, string username)
|
||||||
|
{
|
||||||
|
var user = await repo.GetUser(username).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return repo.GetPlaylistDocs(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async IAsyncEnumerable<Playlist> GetPlaylists(this UserRepo repo, User user)
|
||||||
|
{
|
||||||
|
var playlists = repo.GetPlaylistDocs(user);
|
||||||
|
|
||||||
|
await foreach (var playlist in playlists)
|
||||||
|
{
|
||||||
|
yield return playlist.ConvertTo<Playlist>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IAsyncEnumerable<DocumentSnapshot>> GetTagDocs(this UserRepo repo, string username)
|
||||||
|
{
|
||||||
|
var user = await repo.GetUser(username).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return repo.GetTagDocs(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async IAsyncEnumerable<Tag> GetTags(this UserRepo repo, User user)
|
||||||
|
{
|
||||||
|
var tags = repo.GetTagDocs(user);
|
||||||
|
|
||||||
|
await foreach (var tag in tags)
|
||||||
|
{
|
||||||
|
yield return tag.ConvertTo<Tag>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<UserContext> GetUserContext(this UserRepo repo, string username)
|
||||||
|
{
|
||||||
|
var user = new UserContext
|
||||||
|
{
|
||||||
|
User = await repo.GetUser(username).ConfigureAwait(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
var playlists = repo.GetPlaylists(user.User).ToListAsync();
|
||||||
|
var tags = repo.GetTags(user.User).ToListAsync();
|
||||||
|
|
||||||
|
await Task.WhenAll(playlists.AsTask(), tags.AsTask()).ConfigureAwait(false);
|
||||||
|
|
||||||
|
user.Playlists = playlists.Result;
|
||||||
|
user.Tags = tags.Result;
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,9 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
namespace Mixonomer.Fire
|
namespace Mixonomer.Fire;
|
||||||
|
|
||||||
|
public interface IRepository
|
||||||
{
|
{
|
||||||
public interface IRepository
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,84 +2,83 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Google.Cloud.Firestore;
|
using Google.Cloud.Firestore;
|
||||||
|
|
||||||
namespace Mixonomer.Fire
|
namespace Mixonomer.Fire;
|
||||||
|
|
||||||
|
[FirestoreData]
|
||||||
|
public class Playlist
|
||||||
{
|
{
|
||||||
[FirestoreData]
|
[FirestoreProperty]
|
||||||
public class Playlist
|
public string uri { get; set; }
|
||||||
{
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string name { get; set; }
|
||||||
public string uri { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string type { get; set; }
|
||||||
public string name { get; set; }
|
|
||||||
[FirestoreProperty]
|
|
||||||
public string type { get; set; }
|
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool include_recommendations { get; set; }
|
public bool include_recommendations { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int recommendation_sample { get; set; }
|
public int recommendation_sample { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool include_library_tracks { get; set; }
|
public bool include_library_tracks { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<string> parts { get; set; }
|
public IEnumerable<string> parts { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<DocumentReference> playlist_references { get; set; }
|
public IEnumerable<DocumentReference> playlist_references { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool shuffle { get; set; }
|
public bool shuffle { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string sort { get; set; }
|
public string sort { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string description_overwrite { get; set; }
|
public string description_overwrite { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string description_suffix { get; set; }
|
public string description_suffix { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public DateTime last_updated { get; set; }
|
public DateTime last_updated { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int lastfm_stat_count { get; set; }
|
public int lastfm_stat_count { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int lastfm_stat_album_count { get; set; }
|
public int lastfm_stat_album_count { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int lastfm_stat_artist_count { get; set; }
|
public int lastfm_stat_artist_count { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public double lastfm_stat_percent { get; set; }
|
public double lastfm_stat_percent { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public double lastfm_stat_album_percent { get; set; }
|
public double lastfm_stat_album_percent { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public double lastfm_stat_artist_percent { get; set; }
|
public double lastfm_stat_artist_percent { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public DateTime lastfm_stat_last_refresh { get; set; }
|
public DateTime lastfm_stat_last_refresh { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool add_last_month { get; set; }
|
public bool add_last_month { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool add_this_month { get; set; }
|
public bool add_this_month { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int day_boundary { get; set; }
|
public int day_boundary { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool include_spotify_owned { get; set; }
|
public bool include_spotify_owned { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string chart_range { get; set; }
|
public string chart_range { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int chart_limit { get; set; }
|
public int chart_limit { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentId]
|
[FirestoreDocumentId]
|
||||||
public DocumentReference Reference { get; set; }
|
public DocumentReference Reference { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentCreateTimestamp]
|
[FirestoreDocumentCreateTimestamp]
|
||||||
public Timestamp CreateTime { get; set; }
|
public Timestamp CreateTime { get; set; }
|
||||||
[FirestoreDocumentUpdateTimestamp]
|
[FirestoreDocumentUpdateTimestamp]
|
||||||
public Timestamp UpdateTime { get; set; }
|
public Timestamp UpdateTime { get; set; }
|
||||||
[FirestoreDocumentReadTimestamp]
|
[FirestoreDocumentReadTimestamp]
|
||||||
public Timestamp ReadTime { get; set; }
|
public Timestamp ReadTime { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,74 +2,73 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Google.Cloud.Firestore;
|
using Google.Cloud.Firestore;
|
||||||
|
|
||||||
namespace Mixonomer.Fire
|
namespace Mixonomer.Fire;
|
||||||
|
|
||||||
|
[FirestoreData]
|
||||||
|
public class Tag
|
||||||
{
|
{
|
||||||
[FirestoreData]
|
[FirestoreProperty]
|
||||||
public class Tag
|
public string name { get; set; }
|
||||||
{
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string tag_id { get; set; }
|
||||||
public string name { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string username { get; set; }
|
||||||
public string tag_id { get; set; }
|
|
||||||
[FirestoreProperty]
|
|
||||||
public string username { get; set; }
|
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public DateTime last_updated { get; set; }
|
public DateTime last_updated { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int count { get; set; }
|
public int count { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public double proportion { get; set; }
|
public double proportion { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool time_objects { get; set; }
|
public bool time_objects { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string total_time { get; set; }
|
public string total_time { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int total_time_ms { get; set; }
|
public int total_time_ms { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int total_user_scrobbles { get; set; }
|
public int total_user_scrobbles { get; set; }
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<TagItem> tracks { get; set; }
|
public IEnumerable<TagItem> tracks { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<TagItem> albums { get; set; }
|
public IEnumerable<TagItem> albums { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<TagItem> artists { get; set; }
|
public IEnumerable<TagItem> artists { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentId]
|
[FirestoreDocumentId]
|
||||||
public DocumentReference Reference { get; set; }
|
public DocumentReference Reference { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentCreateTimestamp]
|
[FirestoreDocumentCreateTimestamp]
|
||||||
public Timestamp CreateTime { get; set; }
|
public Timestamp CreateTime { get; set; }
|
||||||
[FirestoreDocumentUpdateTimestamp]
|
[FirestoreDocumentUpdateTimestamp]
|
||||||
public Timestamp UpdateTime { get; set; }
|
public Timestamp UpdateTime { get; set; }
|
||||||
[FirestoreDocumentReadTimestamp]
|
[FirestoreDocumentReadTimestamp]
|
||||||
public Timestamp ReadTime { get; set; }
|
public Timestamp ReadTime { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[FirestoreData]
|
[FirestoreData]
|
||||||
public class TagItem
|
public class TagItem
|
||||||
{
|
{
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string name { get; set; }
|
public string name { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public string time { get; set; }
|
public string time { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int time_ms { get; set; }
|
public int time_ms { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public int count { get; set; }
|
public int count { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentId]
|
[FirestoreDocumentId]
|
||||||
public DocumentReference Reference { get; set; }
|
public DocumentReference Reference { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentCreateTimestamp]
|
[FirestoreDocumentCreateTimestamp]
|
||||||
public Timestamp CreateTime { get; set; }
|
public Timestamp CreateTime { get; set; }
|
||||||
[FirestoreDocumentUpdateTimestamp]
|
[FirestoreDocumentUpdateTimestamp]
|
||||||
public Timestamp UpdateTime { get; set; }
|
public Timestamp UpdateTime { get; set; }
|
||||||
[FirestoreDocumentReadTimestamp]
|
[FirestoreDocumentReadTimestamp]
|
||||||
public Timestamp ReadTime { get; set; }
|
public Timestamp ReadTime { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,60 +2,58 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Google.Cloud.Firestore;
|
using Google.Cloud.Firestore;
|
||||||
|
|
||||||
namespace Mixonomer.Fire
|
namespace Mixonomer.Fire;
|
||||||
|
|
||||||
|
[FirestoreData]
|
||||||
|
public class User
|
||||||
{
|
{
|
||||||
[FirestoreData]
|
[FirestoreProperty]
|
||||||
public class User
|
public string access_token { get; set; }
|
||||||
{
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string email { get; set; }
|
||||||
public string access_token { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public DateTime last_login { get; set; }
|
||||||
public string email { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public DateTime last_refreshed { get; set; }
|
||||||
public DateTime last_login { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public DateTime last_keygen { get; set; }
|
||||||
public DateTime last_refreshed { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string lastfm_username { get; set; }
|
||||||
public DateTime last_keygen { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public bool locked { get; set; }
|
||||||
public string lastfm_username { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string password { get; set; }
|
||||||
public bool locked { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string refresh_token { get; set; }
|
||||||
public string password { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public bool spotify_linked { get; set; }
|
||||||
public string refresh_token { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public int token_expiry { get; set; }
|
||||||
public bool spotify_linked { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string type { get; set; }
|
||||||
public int token_expiry { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public string username { get; set; }
|
||||||
public string type { get; set; }
|
[FirestoreProperty]
|
||||||
[FirestoreProperty]
|
public bool validated { get; set; }
|
||||||
public string username { get; set; }
|
|
||||||
[FirestoreProperty]
|
|
||||||
public bool validated { get; set; }
|
|
||||||
|
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public IEnumerable<string> apns_tokens { get; set; }
|
public IEnumerable<string> apns_tokens { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool notify { get; set; }
|
public bool notify { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool notify_admins { get; set; }
|
public bool notify_admins { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool notify_playlist_updates { get; set; }
|
public bool notify_playlist_updates { get; set; }
|
||||||
[FirestoreProperty]
|
[FirestoreProperty]
|
||||||
public bool notify_tag_updates { get; set; }
|
public bool notify_tag_updates { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentId]
|
[FirestoreDocumentId]
|
||||||
public DocumentReference Reference { get; set; }
|
public DocumentReference Reference { get; set; }
|
||||||
|
|
||||||
[FirestoreDocumentCreateTimestamp]
|
[FirestoreDocumentCreateTimestamp]
|
||||||
public Timestamp CreateTime { get; set; }
|
public Timestamp CreateTime { get; set; }
|
||||||
[FirestoreDocumentUpdateTimestamp]
|
[FirestoreDocumentUpdateTimestamp]
|
||||||
public Timestamp UpdateTime { get; set; }
|
public Timestamp UpdateTime { get; set; }
|
||||||
[FirestoreDocumentReadTimestamp]
|
[FirestoreDocumentReadTimestamp]
|
||||||
public Timestamp ReadTime { get; set; }
|
public Timestamp ReadTime { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Mixonomer.Fire.Model
|
namespace Mixonomer.Fire.Model;
|
||||||
|
|
||||||
|
public class UserContext
|
||||||
{
|
{
|
||||||
public class UserContext
|
public User User { get; set; }
|
||||||
{
|
public IEnumerable<Playlist> Playlists { get; set; }
|
||||||
public User User { get; set; }
|
public IEnumerable<Tag> Tags { get; set; }
|
||||||
public IEnumerable<Playlist> Playlists { get; set; }
|
|
||||||
public IEnumerable<Tag> Tags { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,47 +4,45 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Google.Cloud.Firestore;
|
using Google.Cloud.Firestore;
|
||||||
|
|
||||||
namespace Mixonomer.Fire
|
namespace Mixonomer.Fire;
|
||||||
|
|
||||||
|
public class UserRepo
|
||||||
{
|
{
|
||||||
public class UserRepo
|
private static readonly string USER_COLLECTION = "spotify_users";
|
||||||
|
|
||||||
|
private readonly FirestoreDb db;
|
||||||
|
private readonly CollectionReference userCollection;
|
||||||
|
|
||||||
|
public UserRepo(FirestoreDb db = null, string projectId = null)
|
||||||
{
|
{
|
||||||
private static readonly string USER_COLLECTION = "spotify_users";
|
this.db = db ?? FirestoreDb.Create(projectId);
|
||||||
|
userCollection = this.db.Collection(USER_COLLECTION);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly FirestoreDb db;
|
public IAsyncEnumerable<DocumentSnapshot> GetUserDocs()
|
||||||
private readonly CollectionReference userCollection;
|
{
|
||||||
|
return userCollection.StreamAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public UserRepo(FirestoreDb db = null, string projectId = null)
|
public async Task<User> GetUser(string username)
|
||||||
{
|
{
|
||||||
this.db = db ?? FirestoreDb.Create(projectId);
|
var query = userCollection.WhereEqualTo("username", username.ToLower());
|
||||||
userCollection = this.db.Collection(USER_COLLECTION);
|
var querySnapshot = await query.GetSnapshotAsync().ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
public IAsyncEnumerable<DocumentSnapshot> GetUsers()
|
return querySnapshot.SingleOrDefault()?.ConvertTo<User>();
|
||||||
{
|
}
|
||||||
return userCollection.StreamAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<User> GetUser(string username)
|
public IAsyncEnumerable<DocumentSnapshot> GetPlaylistDocs(User user)
|
||||||
{
|
{
|
||||||
var query = userCollection.WhereEqualTo("username", username.ToLower());
|
var playlistCollection = db.Collection($"{USER_COLLECTION}/{user.Reference.Id}/playlists");
|
||||||
var querySnapshot = await query.GetSnapshotAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
return querySnapshot.SingleOrDefault()?.ConvertTo<User>();
|
return playlistCollection.StreamAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IAsyncEnumerable<DocumentSnapshot>> GetPlaylistDocs(User user)
|
public IAsyncEnumerable<DocumentSnapshot> GetTagDocs(User user)
|
||||||
{
|
{
|
||||||
var playlistCollection = db.Collection($"{USER_COLLECTION}/{user.Reference.Id}/playlists");
|
var playlistCollection = db.Collection($"{USER_COLLECTION}/{user.Reference.Id}/tags");
|
||||||
|
|
||||||
return Task.FromResult(playlistCollection.StreamAsync());
|
return playlistCollection.StreamAsync();
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IAsyncEnumerable<DocumentSnapshot>> GetTagDocs(User user)
|
|
||||||
{
|
|
||||||
var playlistCollection = db.Collection($"{USER_COLLECTION}/{user.Reference.Id}/tags");
|
|
||||||
|
|
||||||
return Task.FromResult(playlistCollection.StreamAsync());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,16 +3,19 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Cloud.Functions.Hosting" Version="2.1.0" />
|
<PackageReference Include="Google.Cloud.Functions.Hosting" Version="2.1.0" />
|
||||||
<PackageReference Include="Google.Events.Protobuf" Version="1.3.0" />
|
<PackageReference Include="Google.Events.Protobuf" Version="1.3.0" />
|
||||||
<None Include="appsettings*.json" CopyToOutputDirectory="PreserveNewest" />
|
<None Include="appsettings*.json" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
<PackageReference Include="SpotifyAPI.Web" Version="7.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Mixonomer.Fire\Mixonomer.Fire.csproj" />
|
<ProjectReference Include="..\Mixonomer.Fire\Mixonomer.Fire.csproj" />
|
||||||
|
<ProjectReference Include="..\Mixonomer.Playlist\Mixonomer.Playlist.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -8,28 +8,26 @@ using Google.Events.Protobuf.Cloud.PubSub.V1;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Mixonomer.Fire;
|
using Mixonomer.Fire;
|
||||||
|
|
||||||
namespace Mixonomer.Func
|
namespace Mixonomer.Func;
|
||||||
|
|
||||||
|
public class RunUserPlaylist : ICloudEventFunction<MessagePublishedData>
|
||||||
{
|
{
|
||||||
public class RunUserPlaylist : ICloudEventFunction<MessagePublishedData>
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public RunUserPlaylist(ILogger<RunUserPlaylist> logger)
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
_logger = logger;
|
||||||
|
}
|
||||||
public RunUserPlaylist(ILogger<RunUserPlaylist> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
|
public async Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Received message in C# {data.Message}, {cloudEvent.GetPopulatedAttributes()}");
|
_logger.LogInformation($"Received message in C# {data.Message}, {cloudEvent.GetPopulatedAttributes()}");
|
||||||
|
|
||||||
var userRepo = new UserRepo(projectId: System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT"));
|
var userRepo = new UserRepo(projectId: System.Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT"));
|
||||||
|
|
||||||
var user = await userRepo.GetUser(data.Message.Attributes["username"]);
|
var user = await userRepo.GetUser(data.Message.Attributes["username"]);
|
||||||
|
|
||||||
_logger.LogInformation($"{user.username} was last refreshed at {user.last_refreshed}");
|
_logger.LogInformation($"{user.username} was last refreshed at {user.last_refreshed}");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mixonomer.Tests", "Mixonome
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mixonomer.CLI", "Mixonomer.CLI\Mixonomer.CLI.csproj", "{7469F571-DBF2-4D60-85FE-4041C445A490}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mixonomer.CLI", "Mixonomer.CLI\Mixonomer.CLI.csproj", "{7469F571-DBF2-4D60-85FE-4041C445A490}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mixonomer.Playlist", "Mixonomer.Playlist\Mixonomer.Playlist.csproj", "{274560D0-2EBB-4C6D-BA45-2270DB92F12C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -33,6 +35,10 @@ Global
|
|||||||
{7469F571-DBF2-4D60-85FE-4041C445A490}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7469F571-DBF2-4D60-85FE-4041C445A490}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7469F571-DBF2-4D60-85FE-4041C445A490}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7469F571-DBF2-4D60-85FE-4041C445A490}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7469F571-DBF2-4D60-85FE-4041C445A490}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7469F571-DBF2-4D60-85FE-4041C445A490}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{274560D0-2EBB-4C6D-BA45-2270DB92F12C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{274560D0-2EBB-4C6D-BA45-2270DB92F12C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{274560D0-2EBB-4C6D-BA45-2270DB92F12C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{274560D0-2EBB-4C6D-BA45-2270DB92F12C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
14
Mixonomer.Playlist/Mixonomer.Playlist.csproj
Normal file
14
Mixonomer.Playlist/Mixonomer.Playlist.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Mixonomer.Fire\Mixonomer.Fire.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
13
Mixonomer.Playlist/Months.cs
Normal file
13
Mixonomer.Playlist/Months.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace Mixonomer.Playlist;
|
||||||
|
|
||||||
|
public static class Months
|
||||||
|
{
|
||||||
|
public static string ThisMonth() => DateTime.Now.ToString("MMMM yy").ToLowerInvariant();
|
||||||
|
|
||||||
|
public static string LastMonth()
|
||||||
|
{
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var lastMonth = now.AddDays(-now.Day - 1);
|
||||||
|
return lastMonth.ToString("MMMM yy").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
61
Mixonomer.Playlist/PartTreeWalker.cs
Normal file
61
Mixonomer.Playlist/PartTreeWalker.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using Google.Cloud.Firestore;
|
||||||
|
using Mixonomer.Fire;
|
||||||
|
using Mixonomer.Fire.Extensions;
|
||||||
|
|
||||||
|
namespace Mixonomer.Playlist;
|
||||||
|
|
||||||
|
public class PartTreeWalker
|
||||||
|
{
|
||||||
|
private readonly UserRepo _userRepo;
|
||||||
|
|
||||||
|
private readonly HashSet<string> _processedPlaylists = new();
|
||||||
|
public HashSet<string>? SpotifyPlaylistNames { get; private set; }
|
||||||
|
|
||||||
|
public PartTreeWalker(UserRepo userRepo)
|
||||||
|
{
|
||||||
|
_userRepo = userRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetPlaylistParts(string username, string playlistName)
|
||||||
|
{
|
||||||
|
var user = await _userRepo.GetUser(username);
|
||||||
|
|
||||||
|
return await GetPlaylistParts(user, playlistName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetPlaylistParts(User user, string playlistName)
|
||||||
|
{
|
||||||
|
var playlist = await _userRepo.GetPlaylists(user).Where(x => x.name == playlistName).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (playlist is not null)
|
||||||
|
{
|
||||||
|
SpotifyPlaylistNames = new HashSet<string>(playlist.parts);
|
||||||
|
|
||||||
|
foreach (var part in playlist.playlist_references)
|
||||||
|
{
|
||||||
|
await ProcessPlaylist(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SpotifyPlaylistNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessPlaylist(DocumentReference documentReference)
|
||||||
|
{
|
||||||
|
if (!_processedPlaylists.Contains(documentReference.Id))
|
||||||
|
{
|
||||||
|
var playlist = (await documentReference.GetSnapshotAsync()).ConvertTo<Fire.Playlist>();
|
||||||
|
|
||||||
|
_processedPlaylists.Add(documentReference.Id);
|
||||||
|
foreach (var p in playlist.parts)
|
||||||
|
{
|
||||||
|
SpotifyPlaylistNames?.Add(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var p in playlist.playlist_references)
|
||||||
|
{
|
||||||
|
await ProcessPlaylist(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@
|
|||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
<LangVersion>default</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,17 +2,15 @@
|
|||||||
using Mixonomer.Fire;
|
using Mixonomer.Fire;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Mixonomer.Tests
|
namespace Mixonomer.Tests;
|
||||||
{
|
|
||||||
public class UnitTest1
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public async void Test1()
|
|
||||||
{
|
|
||||||
// var repo = new UserRepo();
|
|
||||||
|
|
||||||
// var user = await repo.GetUser("andy");
|
public class UnitTest1
|
||||||
}
|
{
|
||||||
|
[Fact]
|
||||||
|
public async void Test1()
|
||||||
|
{
|
||||||
|
// var repo = new UserRepo();
|
||||||
|
|
||||||
|
// var user = await repo.GetUser("andy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user