Commit bd52fed8 authored by Kirill's avatar Kirill

Итерация 1 завершена

parents 8add35b7 6430228d
...@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TourDataManager", "TourData ...@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TourDataManager", "TourData
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TourDataManagerConsoleApplication", "TourDataManagerConsoleApplication\TourDataManagerConsoleApplication.csproj", "{66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TourDataManagerConsoleApplication", "TourDataManagerConsoleApplication\TourDataManagerConsoleApplication.csproj", "{66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Clifton.Core.Pipes", "Clifton.Core.Pipes\Clifton.Core.Pipes.csproj", "{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -18,5 +20,9 @@ Global ...@@ -18,5 +20,9 @@ Global
{66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Release|Any CPU.Build.0 = Release|Any CPU {66F0D20A-DA45-45CB-8DDF-0F9900E03AE3}.Release|Any CPU.Build.0 = Release|Any CPU
{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B826097C-CC24-4CAC-8D31-8A65C4B76BE9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections> </configSections>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> </startup>
</configuration> </configuration>
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks;
using Ninject; using Ninject;
namespace TourDataManager { namespace TourDataManager {
...@@ -9,19 +10,22 @@ namespace TourDataManager { ...@@ -9,19 +10,22 @@ namespace TourDataManager {
[Inject] public HttpClient HttpClient{ get; set; } [Inject] public HttpClient HttpClient{ get; set; }
public async void Login(string email, string password, Action<bool, string> continuation = null){ public (bool, string) Login(string email, string password){
return LoginAsync(email, password).Result;
}
public async Task<(bool,string)> LoginAsync(string email, string password){
var x = await HttpClient.PostAsync(authUri, var x = await HttpClient.PostAsync(authUri,
new FormUrlEncodedContent(new[]{ new FormUrlEncodedContent(new[]{
new KeyValuePair<string, string>("email", email), new KeyValuePair<string, string>("email", email),
new KeyValuePair<string, string>("password", password) new KeyValuePair<string, string>("password", password)
})); }));
var content = await x.Content.ReadAsStringAsync(); var content = await x.Content.ReadAsStringAsync();
return (x.IsSuccessStatusCode, content);
continuation?.Invoke(x.IsSuccessStatusCode,content);
} }
public void Logout(){ public void Logout(){
throw new NotImplementedException();
} }
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
namespace TourDataManager {
public class BigantoErrorException : Exception {
public BigantoErrorList ErrorsList;
public BigantoErrorException(BigantoErrorList errors){
ErrorsList = errors;
}
}
public struct BigantoErrorList {
public List<BigantoError> Errors;
}
public struct BigantoError {
public int Code;
public string Message;
public override string ToString(){ return $"code={Code};message={Message}"; }
}
}
\ No newline at end of file
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using File = TourDataManager.Entities.File;
namespace TourDataManager {
public class ContentLoadingTask {
private ITourFilesListFetcher filesFetcher;
private long tourId;
public ContentLoadingTask(long tourId, ITourFilesListFetcher filesFetcher){
this.filesFetcher = filesFetcher;
this.tourId = tourId;
}
public void Run(IProgress<string> progress = null){
Debug.Log($"ContentLoadingTask.Run(){{ tourId = {tourId} }}");
var files = filesFetcher.FetchFilesAsync(tourId).Result;
var webClient = new WebClient();
var len = files.Length;
var count = 0;
foreach (var file in files){
//Debug.Log($"{++count} of {len} | {file.LocalUrl}");
progress?.Report($"{++count} of {len} | {file.LocalUrl}");
var dir = Path.GetDirectoryName(file.LocalUrl);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
webClient.DownloadFile(new Uri(file.Url),file.LocalUrl);
}
}
}
}
\ No newline at end of file
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common; using System.Data.Common;
using System.Data.Entity; using System.Data.Entity;
using System.Data.Entity.Core.Common; using System.Data.Entity.Core.Common;
using System.Data.Entity.Migrations;
using System.Data.SQLite; using System.Data.SQLite;
using System.Data.SQLite.EF6; using System.Data.SQLite.EF6;
using System.Linq;
using System.Threading.Tasks;
using SQLite.CodeFirst; using SQLite.CodeFirst;
using TourDataManager.Entities;
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace TourDataManager { namespace TourDataManager {
[Table("Foo")] // ReSharper disable once InconsistentNaming
public class Foo { public class SQLiteConfiguration : DbConfiguration{
public long Id{ get; set; } public SQLiteConfiguration(){
public string Data{ get; set; }
}
public class SQLiteConfiguration : DbConfiguration
{
public SQLiteConfiguration()
{
SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance); SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance); SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices))); SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
} }
} }
//[DbConfigurationType(typeof(Ef6CodeConfig))]
public class MyDbContext : DbContext{ public class MyDbContext : DbContext{
public MyDbContext(DbConnection connection, bool contextOwnsConnection) public MyDbContext(DbConnection connection, bool contextOwnsConnection)
...@@ -40,31 +37,67 @@ namespace TourDataManager { ...@@ -40,31 +37,67 @@ namespace TourDataManager {
protected override void OnModelCreating(DbModelBuilder modelBuilder){ protected override void OnModelCreating(DbModelBuilder modelBuilder){
//modelBuilder.Entity<Foo>(); // Эта штука отключает самостоятельную генерацию Id и позволяет мне самому устанавливать Id
modelBuilder.Entity<Estate>().Property(estate => estate.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<Tour>().Property(tour => tour.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
// Ещё, вероятно, помогло бы [DatabaseGenerated(DatabaseGeneratedOption.None)]
var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<MyDbContext>(modelBuilder); var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<MyDbContext>(modelBuilder);
Database.SetInitializer(sqliteConnectionInitializer); Database.SetInitializer(sqliteConnectionInitializer);
} }
public DbSet<Foo> Foo{ get; set; } public DbSet<Estate> Estates{ get; set; }
public DbSet<Tour> Tours{ get; set; }
public DbSet<File> Files{ get; set; }
} }
public class Db { public class Db : IDisposable {
private SQLiteConnection connection;
private MyDbContext context;
public Db(){ public Db(){
connection = new SQLiteConnection($"data source={TourDataManagerPlugin.GetPathInPersistent("sandbox.sqlite")}");
context = new MyDbContext(connection,true);
}
using (var sqLiteConnection = new System.Data.SQLite.SQLiteConnection("data source=mylovelybase.sqlite")){ public Estate[] GetEstates(){
using (var db = new MyDbContext(sqLiteConnection,true)){ return context.Estates.ToArray();
db.Foo.Add(new Foo{Id = new Random().Next(0,1000), Data = "Yolo"}); }
db.SaveChanges(); public Task<Estate[]> GetEstatesAsync(){
return context.Estates.ToArrayAsync();
}
public void InsertEstates(IEnumerable<Estate> estates){
foreach (var estate in estates){
context.Estates.AddOrUpdate(estate);
}
context.SaveChanges();
//db.Set<Foo>()
} }
public void InsertTours(IEnumerable<Tour> tours){
foreach (var tour in tours){
context.Tours.AddOrUpdate(tour);
} }
context.SaveChanges();
}
public void InsertFiles(IEnumerable<File> files){
Debug.Log("Inserting Files list to database");
var diff = files.Where(file => !context.Files.Any(file1 => file.Url == file1.Url));
context.Files.AddRange(diff);
context.SaveChanges();
}
public void Dispose(){
connection?.Dispose();
} }
} }
} }
\ No newline at end of file
...@@ -12,5 +12,11 @@ namespace TourDataManager { ...@@ -12,5 +12,11 @@ namespace TourDataManager {
Console.WriteLine(msg); Console.WriteLine(msg);
Console.ResetColor(); Console.ResetColor();
} }
public static char ReadKey(){
var ch = Console.ReadKey().KeyChar;
Console.WriteLine();
return ch;
}
} }
} }
\ No newline at end of file
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
namespace TourDataManager.Entities { namespace TourDataManager.Entities {
public class Estate { public class Estate {
/// Идентификатор объекта недвижимости /// Идентификатор объекта недвижимости
public long Id{ get; set; } [Key] public long Id{ get; set; }
public string Title{ get; set; } public string Title{ get; set; }
...@@ -16,5 +18,7 @@ namespace TourDataManager.Entities { ...@@ -16,5 +18,7 @@ namespace TourDataManager.Entities {
public string Preview{ get; set; } public string Preview{ get; set; }
public string Created{ get; set; } public string Created{ get; set; }
public override string ToString(){ return $"Estate : {Id} | {Title} | {TourCount} | {Preview} | {Created}"; }
} }
} }
\ No newline at end of file
using SQLite.CodeFirst;
namespace TourDataManager.Entities {
public class File {
public long Id{ get; set; }
[Unique] public string Url{ get; set; }
public int Size{ get; set; }
public string LocalUrl{ get; set; }
public override string ToString(){ return $"{Size} | {Url}"; }
}
}
\ No newline at end of file
...@@ -9,7 +9,6 @@ namespace TourDataManager.Entities { ...@@ -9,7 +9,6 @@ namespace TourDataManager.Entities {
public string Screen{ get; set; } public string Screen{ get; set; }
public int EstateId{ get; set; }
public string Created{ get; set; } public string Created{ get; set; }
...@@ -20,5 +19,9 @@ namespace TourDataManager.Entities { ...@@ -20,5 +19,9 @@ namespace TourDataManager.Entities {
/// Состояние тура /// Состояние тура
public int State{ get; set; } public int State{ get; set; }
public long EstateId{ get; set; }
public override string ToString(){ return $"Tour : {Id} | {Title} | {EstateId}"; }
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using Ninject; using Ninject;
using TourDataManager.Entities; using TourDataManager.Entities;
namespace TourDataManager { namespace TourDataManager {
public class GetEstatesUseCase { public class FetchEstatesUseCase {
[Inject]
public HttpClient httpClient{ get; set; }
[Inject] public HttpClient HttpClient{ get; set; }
[Inject] public Db Database{ get; set; }
public struct BigantoErrorList { public Task<Estate[]> FetchEstatesFromDbAsync(){
public List<BigantoError> Errors; return Database.GetEstatesAsync();
}
public struct BigantoError {
public int Code;
public string Message;
public override string ToString(){ return $"code={Code};message={Message}"; }
}
public class BigantoErrorException : Exception {
public BigantoErrorList ErrorsList;
public BigantoErrorException(BigantoErrorList errors){
ErrorsList = errors;
}
} }
/// <summary> /// <summary>
...@@ -39,9 +21,9 @@ namespace TourDataManager { ...@@ -39,9 +21,9 @@ namespace TourDataManager {
/// <exception cref="BigantoErrorException">Если вместо массива эстейтов с сервера получены ошибки</exception> /// <exception cref="BigantoErrorException">Если вместо массива эстейтов с сервера получены ошибки</exception>
/// <exception cref="JsonException">Если вместо массива эстейтов или ошибки пришло нечто иное</exception> /// <exception cref="JsonException">Если вместо массива эстейтов или ошибки пришло нечто иное</exception>
/// </summary> /// </summary>
public async Task<Estate[]> GetEstates(){ public async Task<Estate[]> FetchEstatesFromServerAsync(){
var response = await httpClient.GetAsync("https://biganto.com/api-novus/estates.getList?client=desktopplayer&client_version=3.0&v=2.0"); var response = await HttpClient.GetAsync("https://biganto.com/api-novus/estates.getList?client=desktopplayer&client_version=3.0&v=2.0");
// throw HttpRequestException // throw HttpRequestException
var content = await response.Content.ReadAsStringAsync(); var content = await response.Content.ReadAsStringAsync();
...@@ -57,7 +39,7 @@ namespace TourDataManager { ...@@ -57,7 +39,7 @@ namespace TourDataManager {
if (error == null) return estates; if (error == null) return estates;
error = null; error = null;
// Вместо массиво эстейтов в ответе может содержаться json ошибки // Вместо массива эстейтов в ответе может содержаться json ошибки
// Предпринимается попытка десериализовать ошибки и выкинуть BigantoErrorException // Предпринимается попытка десериализовать ошибки и выкинуть BigantoErrorException
var exceptionList = JsonConvert.DeserializeObject<BigantoErrorList>(content,errorHandlerSettings); var exceptionList = JsonConvert.DeserializeObject<BigantoErrorList>(content,errorHandlerSettings);
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Ninject;
using TourDataManager.Entities;
namespace TourDataManager {
public interface ITourFilesListFetcher {
Task<File[]> FetchFilesAsync(long tourId);
}
public class FetchTourContentUseCase : ITourFilesListFetcher{
[Inject] public HttpClient HttpClient{ get; set; }
[Inject] public Db Database{ get; set; }
public ContentLoadingTask FetchTourContentFromServerAsync(long tourId){
Debug.Log($"ContentLoadingTask queued for tour {tourId}");
var contentLoadingTask = new ContentLoadingTask(tourId, this);
// add to queue
return contentLoadingTask;
}
/// <summary>
/// Получить список файлов
/// </summary>
/// <param name="tourId"></param>
/// <returns></returns>
public async Task<File[]> FetchFilesAsync(long tourId){
Debug.Log("Fetching Files list");
var response = await HttpClient.GetAsync(
$"https://biganto.com/api-novus/tours.getFiles?client=desktopplayer&client_version=3.0&v=2.0&id={tourId}");
var content = await response.Content.ReadAsStringAsync();
var fukin_dict_wrap = JsonConvert.DeserializeObject<Dictionary<string,File[]>>(content);
var files = fukin_dict_wrap[tourId.ToString()];
var regex = new Regex(@"assets.+?(?=\?|$)");
// TODO Что если не сматчится?
foreach (var file in files){
// Id AutoIncrement
var val = regex.Match(file.Url).Value;
System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(val));
file.LocalUrl = TourDataManagerPlugin.GetPathInPersistent(val);
}
Database.InsertFiles(files);
return files;
}
}
}
\ No newline at end of file
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Ninject;
using TourDataManager.Entities;
namespace TourDataManager {
public class FetchTourPreviewsUseCase {
[Inject] public HttpClient HttpClient{ get; set; }
public async Task<Tour[]> FetchTourFromServerAsync(long estateId){
var response = await HttpClient.GetAsync(
$"https://biganto.com/api-novus/tours.getList?client=desktopplayer&client_version=3.0&v=2.0&estate_id={estateId}");
// throw HttpRequestException
var content = await response.Content.ReadAsStringAsync();
// TODO Это в буквальнос смысле копипаста с FetchEstatesUseCase.FetchEstatesFromServerAsync
ErrorContext error = null;
var errorHandlerSettings = new JsonSerializerSettings{
Error = (sender,args) => {
error = args.ErrorContext;
args.ErrorContext.Handled = true;
}
};
var tours = JsonConvert.DeserializeObject<Tour[]>(content,errorHandlerSettings);
if (error == null){
// Т.к из json нам не приходит estateId, а мы и так по контексту его знаем, то вбиваем так.
// Теперь и база будет знать.
foreach (var tour in tours){tour.EstateId = estateId;}
return tours;
}
error = null;
var exceptionList = JsonConvert.DeserializeObject<BigantoErrorList>(content,errorHandlerSettings);
if (error == null) throw new BigantoErrorException(exceptionList);
throw new JsonException("Something goes wrong",error.Error);
}
}
}
\ No newline at end of file
using System; using System;
using System.Threading.Tasks;
namespace TourDataManager { namespace TourDataManager {
public interface IAuthenticator { public interface IAuthenticator {
void Login(string email, string password, Action<bool,string> continuation = null); (bool,string) Login(string email, string password);
Task<(bool,string)> LoginAsync(string email, string password);
void Logout(); void Logout();
} }
} }
\ No newline at end of file
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Ninject;
using Ninject.Modules;
using TourDataManager.Entities;
namespace TourDataManager {
public class TourDataManager {
private string persistentPath;
private IKernel Container;
public TourDataManager(string persistentPath){
this.persistentPath = persistentPath;
Container = new StandardKernel(new MyModule(persistentPath));
}
public void Login(string email, string password){
Container.Get<IAuthenticator>().Login(email,password, (b, s) => {
var cookiestor = Container.Get<CookieStorage>();
Debug.Log($"Authorization : {s}");
Debug.Log($"Cookie count in storage : {cookiestor.Get().Count}");
cookiestor.Save();
});
}
public Task<Estate[]> GetEstates(){
return Container.Get<GetEstatesUseCase>().GetEstates();
}
}
public class MyModule : NinjectModule {
private readonly string persistentPath;
public MyModule(string persistentPath){
this.persistentPath = persistentPath;
}
public override void Load(){
var cookieStorage = new CookieStorage(persistentPath + "\\cookie.storage");
var httpClientHandler = new HttpClientHandler();
//CookieContainer сам запоминает полученные из ответа куки
httpClientHandler.CookieContainer = cookieStorage.Get();
var httpClient = new HttpClient(httpClientHandler);
Bind<CookieStorage>().ToConstant(cookieStorage).InSingletonScope();
Bind<HttpClientHandler>().ToConstant(httpClientHandler).InSingletonScope();
Bind<HttpClient>().ToConstant(httpClient).InSingletonScope();
Bind<IAuthenticator>().To<Authenticator>().InSingletonScope();
Bind<GetEstatesUseCase>().ToSelf().InSingletonScope();
}
}
}
\ No newline at end of file
...@@ -104,15 +104,20 @@ ...@@ -104,15 +104,20 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Authenticator.cs" /> <Compile Include="Authenticator.cs" />
<Compile Include="BigantoErrorException.cs" />
<Compile Include="ContentLoadingTask.cs" />
<Compile Include="CookieStorage.cs" /> <Compile Include="CookieStorage.cs" />
<Compile Include="Db.cs" /> <Compile Include="Db.cs" />
<Compile Include="Debug.cs" /> <Compile Include="Debug.cs" />
<Compile Include="Entities\Estate.cs" /> <Compile Include="Entities\Estate.cs" />
<Compile Include="Entities\File.cs" />
<Compile Include="Entities\Tour.cs" /> <Compile Include="Entities\Tour.cs" />
<Compile Include="GetEstatesUseCase.cs" /> <Compile Include="FetchEstatesUseCase.cs" />
<Compile Include="FetchTourContentUseCase.cs" />
<Compile Include="FetchTourPreviewsUseCase.cs" />
<Compile Include="IAuthenticator.cs" /> <Compile Include="IAuthenticator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TourDataManager.cs" /> <Compile Include="TourDataManagerPlugin.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
......
using System;
using System.Data.Entity;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Ninject;
using Ninject.Modules;
using TourDataManager.Entities;
namespace TourDataManager {
/// <summary>
/// Фасад для всего плагина
/// </summary>
public class TourDataManagerPlugin : IAuthenticator{
public static volatile string PersistentPath;
public static string GetPathInPersistent(string relative){
return Path.Combine(PersistentPath, relative);
}
private FetchEstatesUseCase estatesfetch{ get; set; }
private FetchTourPreviewsUseCase tourpreviewsfetch{ get; set; }
private Db database{ get; set; }
private IKernel Container;
public TourDataManagerPlugin(string persistentPath){
PersistentPath = persistentPath;
Container = new StandardKernel(new MyModule());
estatesfetch = Container.Get<FetchEstatesUseCase>();
tourpreviewsfetch = Container.Get<FetchTourPreviewsUseCase>();
database = Container.Get<Db>();
}
public async Task<(bool, string)> LoginAsync(string email, string password){
var result = await Container.Get<IAuthenticator>().LoginAsync(email, password);
if(result.Item1) SaveCookie();
return result;
}
private void SaveCookie(){
var cookiestor = Container.Get<CookieStorage>();
Debug.Log($"Cookie saved. Current count : {cookiestor.Get().Count}");
cookiestor.Save();
}
public void Logout(){ throw new NotImplementedException(); }
public async Task<Estate[]> FetchEstatesAsync(){
var estates = await estatesfetch.FetchEstatesFromServerAsync();
database.InsertEstates(estates);
return estates;
}
public async Task<Tour[]> FetchTourPreviewsAsync(long estateId){
var tours = await tourpreviewsfetch.FetchTourFromServerAsync(estateId);
database.InsertTours(tours);
return tours;
}
public ContentLoadingTask DownloadTourContent(long tourId){
return Container.Get<FetchTourContentUseCase>().FetchTourContentFromServerAsync(tourId);
}
public (bool, string) Login(string email, string password){
return LoginAsync(email, password).Result;
}
}
public class MyModule : NinjectModule {
public override void Load(){
var cookieStorage = new CookieStorage(TourDataManagerPlugin.GetPathInPersistent("cookie.storage"));
var httpClientHandler = new HttpClientHandler();
//CookieContainer сам запоминает полученные из ответа куки
httpClientHandler.CookieContainer = cookieStorage.Get();
var httpClient = new HttpClient(httpClientHandler);
Bind<CookieStorage>().ToConstant(cookieStorage).InSingletonScope();
Bind<HttpClientHandler>().ToConstant(httpClientHandler).InSingletonScope();
Bind<HttpClient>().ToConstant(httpClient).InSingletonScope();
Bind<IAuthenticator>().To<Authenticator>().InSingletonScope();
Bind<FetchEstatesUseCase>().ToSelf().InSingletonScope();
Bind<FetchTourPreviewsUseCase>().ToSelf().InSingletonScope();
Bind<FetchTourContentUseCase>().ToSelf().InSingletonScope();
Bind<Db>().ToSelf().InSingletonScope();
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="EntityFramework" version="6.2.0" targetFramework="net45" userInstalled="true" /> <package id="EntityFramework" version="6.2.0" targetFramework="net45" userInstalled="true" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net472" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net45" />
<package id="Ninject" version="3.3.4" targetFramework="net472" /> <package id="Ninject" version="3.3.4" targetFramework="net45" />
<package id="SQLite.CodeFirst" version="1.5.1.25" targetFramework="net472" /> <package id="SQLite.CodeFirst" version="1.5.1.25" targetFramework="net45" />
<package id="System.Data.SqlClient" version="4.5.1" targetFramework="net472" /> <package id="System.Data.SqlClient" version="4.5.1" targetFramework="net45" />
<package id="System.Data.SQLite" version="1.0.109.2" targetFramework="net472" /> <package id="System.Data.SQLite" version="1.0.109.2" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.109.2" targetFramework="net472" /> <package id="System.Data.SQLite.Core" version="1.0.109.2" targetFramework="net45" />
<package id="System.Data.SQLite.EF6" version="1.0.109.0" targetFramework="net472" /> <package id="System.Data.SQLite.EF6" version="1.0.109.0" targetFramework="net45" />
<package id="System.Data.SQLite.Linq" version="1.0.109.0" targetFramework="net472" /> <package id="System.Data.SQLite.Linq" version="1.0.109.0" targetFramework="net45" />
<package id="System.IO" version="4.3.0" targetFramework="net472" /> <package id="System.IO" version="4.3.0" targetFramework="net45" />
<package id="System.Net.Http" version="4.3.3" targetFramework="net472" /> <package id="System.Net.Http" version="4.3.3" targetFramework="net45" />
<package id="System.Runtime" version="4.3.0" targetFramework="net472" /> <package id="System.Runtime" version="4.3.0" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
using System; using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Ninject.Activation.Strategies;
using TourDataManager; using TourDataManager;
using TourDataManager.Entities;
namespace TourDataManagerConsoleApplication { namespace TourDataManagerConsoleApplication {
internal class Program { internal class Program {
...@@ -9,20 +14,94 @@ namespace TourDataManagerConsoleApplication { ...@@ -9,20 +14,94 @@ namespace TourDataManagerConsoleApplication {
const string defaultLogin = "demo@biganto.ru"; const string defaultLogin = "demo@biganto.ru";
const string defaultPassword = "demo"; const string defaultPassword = "demo";
public static TourDataManager.TourDataManagerPlugin TourDataManagerPlugin;
public static void Main(string[] args){ public static void Main(string[] args){
var tourDataManager = new TourDataManager.TourDataManager(PersistentPath); TourDataManagerPlugin = new TourDataManager.TourDataManagerPlugin(PersistentPath);
tourDataManager.Login(defaultLogin, defaultPassword);
//new Db(); MainWindow();
tourDataManager.GetEstates().ContinueWith(task => {
var est = task.Result; //tourDataManager.Login(defaultLogin, defaultPassword);
}); //AsyncMethod(tourDataManager);
Console.Read(); Console.Read();
} }
public static void MainWindow(){
Debug.Log("Commands : \n0 - Auth\n1 - Show estates list\n2 - exit");
var ch = Debug.ReadKey();
switch (ch){
case '0' :
Debug.Log("Login : ");
var login = Console.ReadLine();
Debug.Log("Password : ");
var pass = Console.ReadLine();
var result = TourDataManagerPlugin.Login(login,pass);
Debug.Log($"Auth result : {result.Item1} {result.Item2}");
MainWindow();
break;
case '1' :
var estates = TourDataManagerPlugin.FetchEstatesAsync().Result;
foreach (var estate in estates){
Debug.Log(estate);
}
EstateWindow();
break;
case '2' : Environment.Exit(0); break;
}
}
public static void EstateWindow(){
Debug.Log("Commands : \n0 - Fetch tours of estate\n1 - back\n2 - exit");
var ch = Debug.ReadKey();
switch (ch){
case '0' :
Debug.Log("Estate id : ");
var id = Console.ReadLine();
var tours = TourDataManagerPlugin.FetchTourPreviewsAsync(Int32.Parse(id)).Result;
foreach (var tour in tours){
Debug.Log(tour);
}
EstateWindow();
break;
case '1' : MainWindow(); break;
case '2' : Environment.Exit(0); break;
}
}
public static async void AsyncMethod(TourDataManager.TourDataManagerPlugin plugin){
try{
var estates = await plugin.FetchEstatesAsync();
Tour[] tours = null;
foreach (var estate in estates){
Debug.Log(estate);
tours = await plugin.FetchTourPreviewsAsync(estate.Id);
foreach (var tour in tours){
Debug.Log(tour);
}
}
System.Diagnostics.Debug.Assert(tours != null, nameof(tours) + " != null");
var contentLoadingTask = plugin.DownloadTourContent(tours[2].Id);
var x = Task.Factory
.StartNew(() => { contentLoadingTask.Run(); })
.ContinueWith(task => {
Debug.Log("Done");
});
} catch (Exception e){
Debug.Log(e);
}
}
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment