Skip to content

Commit 789de59

Browse files
authored
Merge pull request #1 from KrugerMP/dev/initial-commit
Initial Commit. Will add more with bugs loaded
2 parents cec1a89 + 6bbbeda commit 789de59

18 files changed

+788
-0
lines changed

src/EasyPicture.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.4.33205.214
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyPicture", "EasyPicture\EasyPicture.csproj", "{6D7CED96-648D-443E-B70E-09D743DCAB98}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{6D7CED96-648D-443E-B70E-09D743DCAB98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{6D7CED96-648D-443E-B70E-09D743DCAB98}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{6D7CED96-648D-443E-B70E-09D743DCAB98}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{6D7CED96-648D-443E-B70E-09D743DCAB98}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {3F256548-071F-4C8B-8F0F-5EC389DBBC45}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"dotnet-ef": {
6+
"version": "7.0.1",
7+
"commands": [
8+
"dotnet-ef"
9+
]
10+
}
11+
}
12+
}

src/EasyPicture/EasyPicture.csproj

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<None Remove="Storage\EasyTracking.accdb" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
14+
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.12" />
15+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
16+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.1">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.1" />
21+
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
22+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
23+
<PackageReference Include="System.Data.Odbc" Version="7.0.0" />
24+
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
25+
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.0" />
26+
</ItemGroup>
27+
28+
<ItemGroup>
29+
<Content Include="Storage\EasyTracking.accdb">
30+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
31+
</Content>
32+
</ItemGroup>
33+
34+
</Project>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.ComponentModel.DataAnnotations.Schema;
2+
3+
namespace EasyPicture.Models
4+
{
5+
[Table("PictureLocations")]
6+
public class PictureLocations
7+
{
8+
public virtual int ID { get; set; }
9+
10+
public virtual string ImageLocation { get; set; }
11+
12+
public virtual string MD5 { get; set; }
13+
}
14+
}

src/EasyPicture/Models/Post.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Xml.Serialization;
2+
3+
[XmlRoot(ElementName = "post")]
4+
public class Post
5+
{
6+
7+
[XmlAttribute(AttributeName = "height")]
8+
public int Height { get; set; }
9+
10+
[XmlAttribute(AttributeName = "score")]
11+
public int Score { get; set; }
12+
13+
[XmlAttribute(AttributeName = "file_url")]
14+
public string FileUrl { get; set; }
15+
16+
17+
[XmlAttribute(AttributeName = "sample_url")]
18+
public string SampleUrl { get; set; }
19+
20+
[XmlAttribute(AttributeName = "sample_width")]
21+
public int SampleWidth { get; set; }
22+
23+
[XmlAttribute(AttributeName = "sample_height")]
24+
public int SampleHeight { get; set; }
25+
26+
[XmlAttribute(AttributeName = "preview_url")]
27+
public string PreviewUrl { get; set; }
28+
29+
[XmlAttribute(AttributeName = "rating")]
30+
public string Rating { get; set; }
31+
32+
[XmlAttribute(AttributeName = "tags")]
33+
public string Tags { get; set; }
34+
35+
[XmlAttribute(AttributeName = "id")]
36+
public int Id { get; set; }
37+
38+
[XmlAttribute(AttributeName = "width")]
39+
public int Width { get; set; }
40+
41+
[XmlAttribute(AttributeName = "change")]
42+
public int Change { get; set; }
43+
44+
[XmlAttribute(AttributeName = "md5")]
45+
public string Md5 { get; set; }
46+
47+
[XmlAttribute(AttributeName = "creator_id")]
48+
public int CreatorId { get; set; }
49+
50+
[XmlAttribute(AttributeName = "has_children")]
51+
public bool HasChildren { get; set; }
52+
53+
[XmlAttribute(AttributeName = "created_at")]
54+
public string CreatedAt { get; set; }
55+
56+
[XmlAttribute(AttributeName = "status")]
57+
public string Status { get; set; }
58+
59+
[XmlAttribute(AttributeName = "source")]
60+
public string Source { get; set; }
61+
62+
[XmlAttribute(AttributeName = "has_notes")]
63+
public bool HasNotes { get; set; }
64+
65+
[XmlAttribute(AttributeName = "has_comments")]
66+
public bool HasComments { get; set; }
67+
68+
[XmlAttribute(AttributeName = "preview_width")]
69+
public int PreviewWidth { get; set; }
70+
71+
[XmlAttribute(AttributeName = "preview_height")]
72+
public int PreviewHeight { get; set; }
73+
}

src/EasyPicture/Models/Posts.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Xml.Serialization;
2+
3+
[XmlRoot(ElementName = "posts")]
4+
public class Posts
5+
{
6+
7+
[XmlElement(ElementName = "post")]
8+
public List<Post> Post { get; set; }
9+
10+
[XmlAttribute(AttributeName = "count")]
11+
public int Count { get; set; }
12+
13+
[XmlAttribute(AttributeName = "offset")]
14+
public int Offset { get; set; }
15+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using EasyPicture.Models;
2+
using System.Data.Odbc;
3+
4+
namespace EasyPicture.Modules
5+
{
6+
public class AccessDataFactory : IAccessDataFactory
7+
{
8+
private readonly string _databaseConnectionString;
9+
private readonly ILogger<AccessDataFactory> _logger;
10+
11+
/// <summary>
12+
/// Base constructor
13+
/// </summary>
14+
/// <param name="configuration"></param>
15+
public AccessDataFactory(IConfiguration configuration, ILogger<AccessDataFactory> logger)
16+
{
17+
_databaseConnectionString = configuration["LocalAccess:DatabaseConnectionString"];
18+
_logger = logger;
19+
}
20+
21+
/// <summary>
22+
/// Validates if a database connection could be made and a table query was possible
23+
/// </summary>
24+
/// <returns></returns>
25+
public async Task<bool> HasDataBaseConnectionAsync()
26+
{
27+
string queryText = "SELECT TOP 1 * FROM PictureLocations";
28+
29+
return (await RunQueryAsync(queryText) != null);
30+
}
31+
32+
/// <summary>
33+
/// Inserts picture location data
34+
/// </summary>
35+
/// <param name="pictureLocations"></param>
36+
/// <returns></returns>
37+
public async Task InsertPictureDataAsync(PictureLocations pictureLocations)
38+
{
39+
string query = $"INSERT INTO PictureLocations(ImageLocation, MD5) VALUES ('{pictureLocations.ImageLocation}', '{pictureLocations.MD5}')";
40+
41+
_ = await RunQueryAsync(query);
42+
}
43+
44+
/// <summary>
45+
/// Check if the MD5 is not already downloaded
46+
/// </summary>
47+
/// <param name="md5"></param>
48+
/// <returns></returns>
49+
public async Task<PictureLocations> IsAlreadyDownloadedAsync(string md5)
50+
{
51+
string queryText = $"SELECT * FROM PictureLocations WHERE MD5 = '{md5}'";
52+
53+
return (await RunQueryAsync(queryText)).FirstOrDefault();
54+
}
55+
56+
/// <summary>
57+
/// Runs a query against the access database and return any selected result of type <see cref="PictureLocations"/>
58+
/// </summary>
59+
/// <param name="query"></param>
60+
/// <returns></returns>
61+
private async Task<List<PictureLocations>> RunQueryAsync(string query)
62+
{
63+
try
64+
{
65+
OdbcCommand command = new(query);
66+
List<PictureLocations> pictureLocations = new();
67+
68+
using OdbcConnection connection = new(_databaseConnectionString);
69+
command.Connection = connection;
70+
connection.Open();
71+
var reader = await command.ExecuteReaderAsync();
72+
73+
while (reader.Read())
74+
{
75+
pictureLocations.Add(new PictureLocations
76+
{
77+
ID = reader.GetInt32(reader.GetOrdinal("ID")),
78+
ImageLocation = reader.GetString(reader.GetOrdinal("ImageLocation")),
79+
MD5 = reader.GetString(reader.GetOrdinal("MD5"))
80+
});
81+
}
82+
83+
reader.Close();
84+
command.Dispose();
85+
connection.Close();
86+
connection.Dispose();
87+
88+
return pictureLocations;
89+
}
90+
catch (Exception ex)
91+
{
92+
_logger.LogError($"DbConnection Used:{_databaseConnectionString} with exception:{ex.Message}");
93+
return null;
94+
}
95+
}
96+
}
97+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
namespace EasyPicture.Modules
2+
{
3+
public class AuditHandler : IAuditHandler
4+
{
5+
/// <summary>
6+
/// The text file name and location
7+
/// </summary>
8+
public string TextFileName { get; private set; }
9+
10+
private readonly bool _audit = false;
11+
private readonly string _downloadPath;
12+
13+
private StreamWriter _streamWriter;
14+
15+
private readonly ILogger _logger;
16+
17+
/// <summary>
18+
/// Base constructor
19+
/// </summary>
20+
/// <param name="logger"></param>
21+
/// <param name="audit"></param>
22+
/// <param name="auditDirectory"></param>
23+
public AuditHandler(
24+
ILogger logger,
25+
string auditDirectory,
26+
bool audit = false)
27+
{
28+
_logger = logger;
29+
_downloadPath = auditDirectory;
30+
_audit = audit;
31+
}
32+
33+
/// <summary>
34+
/// Creates a file based on the name in downloads
35+
/// </summary>
36+
/// <param name="name"></param>
37+
/// <returns></returns>
38+
public async Task CreateFileAsync(string name, string firstLineAudit = "")
39+
{
40+
name = name.Replace("%20", "_");
41+
42+
string auditMessage = $"{DateTime.UtcNow}:{firstLineAudit}";
43+
44+
if (_audit)
45+
{
46+
TextFileName = _downloadPath + name + ".txt";
47+
48+
await File.WriteAllTextAsync(TextFileName, $"{DateTime.UtcNow}:Audit Started");
49+
50+
_streamWriter = new(TextFileName, append: true);
51+
_streamWriter.AutoFlush = true;
52+
53+
_logger.LogInformation($"{DateTime.UtcNow}:Audit Started");
54+
55+
if (!string.IsNullOrEmpty(firstLineAudit))
56+
{
57+
await _streamWriter.WriteLineAsync(auditMessage);
58+
}
59+
}
60+
_logger.LogInformation(auditMessage);
61+
}
62+
63+
/// <summary>
64+
/// Disposes the streamwriter
65+
/// </summary>
66+
/// <returns></returns>
67+
public async Task DropFileStreamAsync()
68+
{
69+
if (_streamWriter != null)
70+
{
71+
await _streamWriter.DisposeAsync();
72+
_streamWriter = null;
73+
}
74+
}
75+
76+
/// <summary>
77+
/// Audits the information message
78+
/// </summary>
79+
/// <param name="auditMessage"></param>
80+
/// <returns></returns>
81+
public async Task AuditInfoMessageAsync(string auditMessage)
82+
{
83+
string auditMessageConcat = $"{DateTime.UtcNow}:{auditMessage}";
84+
85+
if (_audit)
86+
{
87+
try
88+
{
89+
await _streamWriter.WriteLineAsync(auditMessageConcat);
90+
}
91+
catch (Exception)
92+
{
93+
_logger.LogWarning("Stream was already busy being written to");
94+
}
95+
}
96+
97+
_logger.LogInformation(auditMessageConcat);
98+
}
99+
100+
/// <summary>
101+
/// Audits the exception message
102+
/// </summary>
103+
/// <param name="ex"></param>
104+
/// <returns></returns>
105+
public async Task AuditExceptionMessageAsync(Exception ex)
106+
{
107+
if (_audit)
108+
{
109+
await AuditInfoMessageAsync($"{ex.Message}, {ex.InnerException}");
110+
}
111+
_logger.LogError(ex.Message);
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)