Skip to content

Commit

Permalink
Merge pull request #3 from AdityaP700/feature/mongodb-integration
Browse files Browse the repository at this point in the history
Feature/mongodb integration branch to be merged
  • Loading branch information
AdityaP700 authored Dec 13, 2024
2 parents f13070a + 5762bfb commit c8080fe
Show file tree
Hide file tree
Showing 24 changed files with 1,273 additions and 371 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@ pip-log.txt
# Misc
.DS_Store
Thumbs.db

# Application settings
appsettings.json
appsettings.Development.json
appsettings.Production.json
!appsettings.sample.json
184 changes: 184 additions & 0 deletions backend/Controllers/EmailController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SentimatrixAPI.Models;
using SentimatrixAPI.Services;

namespace SentimatrixAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class EmailController : ControllerBase
{
private readonly EmailService _emailService;
private readonly ILogger<EmailController> _logger;
private readonly IMongoCollection<EmailData> _emailCollection;

public EmailController(
EmailService emailService,
ILogger<EmailController> logger,
IMongoDatabase database)
{
_emailService = emailService ?? throw new ArgumentNullException(nameof(emailService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_emailCollection = database.GetCollection<EmailData>("email");
// Log a message indicating successful connection
_logger.LogInformation("Successfully connected to the Email database.");
}

[HttpGet("sentiment/{period}")]
public async Task<IActionResult> GetSentimentTrend(string period)
{
try
{
DateTime startDate = period.ToUpper() switch
{
"1D" => DateTime.UtcNow.AddDays(-1),
"5D" => DateTime.UtcNow.AddDays(-5),
"1W" => DateTime.UtcNow.AddDays(-7),
"1M" => DateTime.UtcNow.AddMonths(-1),
_ => throw new ArgumentException("Invalid time period")
};

var results = await _emailCollection
.Aggregate()
.Match(Builders<EmailData>.Filter.Gte(e => e.ReceivedDate, startDate))
.Group(e => e.ReceivedDate.Date,
g => new SentimentData
{
Period = g.Key.ToString("yyyy-MM-dd"),
AverageScore = g.Average(x => x.Score),
Count = g.Count()
})
.Sort(Builders<SentimentData>.Sort.Ascending(x => x.Period))
.ToListAsync();

return Ok(results);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving sentiment trend");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}

[HttpGet]
public async Task<ActionResult<IEnumerable<EmailData>>> GetAllEmails()
{
try
{
var emails = await _emailCollection.Find(new BsonDocument()).ToListAsync();
return Ok(emails);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving all emails");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}

[HttpGet("positive")]
public async Task<ActionResult<IEnumerable<EmailData>>> GetPositiveEmails(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10)
{
try
{
var emails = await _emailService.GetEmailsByScoreRangeAsync(70, 100);
var paginatedEmails = emails
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToList();

return Ok(new
{
Data = paginatedEmails,
Page = page,
PageSize = pageSize,
TotalCount = emails.Count()
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving positive emails");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}

[HttpGet("negative")]
public async Task<ActionResult<IEnumerable<EmailData>>> GetNegativeEmails(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10)
{
try
{
var emails = await _emailService.GetEmailsByScoreRangeAsync(0, 30);
var paginatedEmails = emails
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToList();

return Ok(new
{
Data = paginatedEmails,
Page = page,
PageSize = pageSize,
TotalCount = emails.Count()
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving negative emails");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}

[HttpGet("sender/{email}")]
public async Task<ActionResult<IEnumerable<EmailData>>> GetEmailsBySender(
string email,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10)
{
try
{
var emails = await _emailService.GetEmailsBySenderAsync(email);
var paginatedEmails = emails
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToList();

return Ok(new
{
Data = paginatedEmails,
Page = page,
PageSize = pageSize,
TotalCount = emails.Count()
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving emails by sender");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}

[HttpGet("stats")]
public async Task<ActionResult<DashboardStats>> GetDashboardStats()
{
try
{
var stats = await _emailService.GetDashboardStatsAsync();
return Ok(stats);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving dashboard stats");
return StatusCode(500, new { message = "Internal server error", details = ex.Message });
}
}
}
}
53 changes: 29 additions & 24 deletions backend/Controllers/EmailProcessController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ public class EmailProcessController : ControllerBase
private readonly ILogger<EmailProcessController> _logger;
private readonly GroqService _groqService;
private readonly IHubContext<TicketHub> _hubContext;
private readonly EmailService _emailService;
private const string SERIOUS_EMAILS_PATH = "serious_emails.json";
private const string POSITIVE_EMAILS_PATH = "positive_emails.json";

public EmailProcessController(
ILogger<EmailProcessController> logger,
GroqService groqService,
IHubContext<TicketHub> hubContext)
IHubContext<TicketHub> hubContext,
EmailService emailService)
{
_logger = logger;
_groqService = groqService;
_hubContext = hubContext;
_emailService = emailService;
}

/// <summary>
Expand Down Expand Up @@ -66,23 +69,35 @@ public async Task<IActionResult> ProcessEmail([FromForm] EmailData emailData)
int sentimentScore = await _groqService.AnalyzeSentiment(plainTextBody);
string response = _groqService.GenerateResponse(sentimentScore, plainTextBody);

var processedEmail = new ProcessedEmail
// Create email document for MongoDB
var email = new Email
{
Body = plainTextBody,
Score = sentimentScore,
Sender = emailData.SenderEmail ?? string.Empty,
Receiver = emailData.ReceiverEmail ?? string.Empty,
Type = sentimentScore <= 60 ? "positive" : "negative",
Time = DateTime.UtcNow
};

// Store in MongoDB
await _emailService.CreateAsync(email);

// Store in local JSON files for backward compatibility
await StoreEmail(new ProcessedEmail
{
Subject = emailData.Subject ?? string.Empty,
Body = plainTextBody,
SenderEmail = emailData.SenderEmail ?? string.Empty,
SentimentScore = sentimentScore,
Response = response,
ProcessedAt = DateTime.UtcNow
};

// Store email based on sentiment
await StoreEmail(processedEmail);
});

// If sentiment score is high (negative), notify all connected clients about the new serious ticket
// If sentiment score is high (negative), notify all connected clients
if (sentimentScore > 60)
{
await _hubContext.Clients.All.SendAsync("ReceiveSeriousTicket", processedEmail);
await _hubContext.Clients.All.SendAsync("ReceiveSeriousTicket", email);
}

return Ok(new EmailProcessResponse
Expand All @@ -91,9 +106,9 @@ public async Task<IActionResult> ProcessEmail([FromForm] EmailData emailData)
Message = response,
Data = new EmailResponseData
{
Subject = processedEmail.Subject,
Body = processedEmail.Body,
SenderEmail = processedEmail.SenderEmail,
Subject = emailData.Subject,
Body = plainTextBody,
SenderEmail = emailData.SenderEmail,
SentimentScore = sentimentScore,
Response = response
}
Expand All @@ -119,22 +134,12 @@ public async Task<IActionResult> ProcessEmail([FromForm] EmailData emailData)
/// <response code="200">Returns the list of serious tickets when successful</response>
/// <response code="500">If there's an error retrieving the tickets</response>
[HttpGet("serious-tickets")]
public IActionResult GetSeriousTickets()
public async Task<IActionResult> GetSeriousTickets()
{
try
{
string filePath = Path.Combine(Directory.GetCurrentDirectory(), "serious_emails.json");
if (!System.IO.File.Exists(filePath))
{
return Ok(new List<ProcessedEmail>());
}

string jsonContent = System.IO.File.ReadAllText(filePath);
var tickets = JsonConvert.DeserializeObject<List<ProcessedEmail>>(jsonContent) ?? new List<ProcessedEmail>();

// Sort by most recent first
tickets = tickets.OrderByDescending(t => t.ProcessedAt).ToList();

// Get negative emails from MongoDB
var tickets = await _emailService.GetNegativeEmailsAsync();
return Ok(tickets);
}
catch (Exception ex)
Expand Down
27 changes: 27 additions & 0 deletions backend/Controllers/YourController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// using Microsoft.AspNetCore.Mvc;

// using MongoDB.Driver;

// public class YourController : ControllerBase
// {
// private readonly MongoDbContext _mongoDbContext;

// public YourController(MongoDbContext mongoDbContext)
// {
// _mongoDbContext = mongoDbContext;
// }

// [HttpGet]
// public async Task<IActionResult> GetItems()
// {
// var items = await _mongoDbContext.GetCollection<Item>("items").Find(_ => true).ToListAsync();
// return Ok(items);
// }

// [HttpPost]
// public async Task<IActionResult> CreateItem(Item item)
// {
// await _mongoDbContext.GetCollection<Item>("items").InsertOneAsync(item);
// return CreatedAtAction(nameof(GetItems), item);
// }
// }
11 changes: 11 additions & 0 deletions backend/Data/MongoDBSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace SentimatrixAPI.Data
{
public class MongoDBSettings
{
public string ConnectionString { get; set; } = string.Empty;
public string DatabaseName { get; set; } = string.Empty;
public string EmailsCollectionName { get; set; } = string.Empty;
}
}
31 changes: 31 additions & 0 deletions backend/Data/MongoDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using MongoDB.Driver;
using MongoDB.Bson;

namespace MyApp
{
class Program
{
static void Main(string[] args)
{
const string connectionUri = "mongodb+srv://user001:[email protected]/?retryWrites=true&w=majority&appName=Cluster0";
var settings = MongoClientSettings.FromConnectionString(connectionUri);

// Set the ServerApi field of the settings object to set the version of the Stable API on the client
settings.ServerApi = new ServerApi(ServerApiVersion.V1);

// Create a new client and connect to the server
var client = new MongoClient(settings);

// Send a ping to confirm a successful connection
try
{
var result = client.GetDatabase("sentimatrix").RunCommand<BsonDocument>(new BsonDocument("ping", 1));
Console.WriteLine("Pinged your deployment. You successfully connected to MongoDB!");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
10 changes: 10 additions & 0 deletions backend/Models/DashboardStats.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SentimatrixAPI.Models
{
public class DashboardStats
{
public int TotalEmails { get; set; }
public int PositiveEmails { get; set; }
public int NegativeEmails { get; set; }
public double AverageSentimentScore { get; set; }
}
}
Loading

0 comments on commit c8080fe

Please sign in to comment.