Skip to content

Commit

Permalink
sync code with SD
Browse files Browse the repository at this point in the history
  • Loading branch information
Dhiogo Acioli committed Apr 7, 2024
1 parent 5ad2cc5 commit 71760d8
Show file tree
Hide file tree
Showing 278 changed files with 10,219 additions and 4,400 deletions.
58 changes: 30 additions & 28 deletions MM.API/Core/ApiCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,49 @@ public static class ApiCore
return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
}

public static async Task<T?> GetNewsByFlixter<T>(this HttpClient http, CancellationToken cancellationToken) where T : class
{
using var request = new HttpRequestMessage(HttpMethod.Get, "https://flixster.p.rapidapi.com/news/list");
//public static async Task<T?> GetNewsByFlixter<T>(this HttpClient http, CancellationToken cancellationToken) where T : class
//{
// using var request = new HttpRequestMessage(HttpMethod.Get, "https://flixster.p.rapidapi.com/news/list");

request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "flixster.p.rapidapi.com");
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "flixster.p.rapidapi.com");

var response = await http.SendAsync(request, cancellationToken);
// var response = await http.SendAsync(request, cancellationToken);

if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);
// if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);

return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
}
// return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
//}

public static async Task<T?> GetTrailersByYoutubeSearch<T>(this HttpClient http, CancellationToken cancellationToken) where T : class
{
string id = "UCzcRQ3vRNr6fJ1A9rqFn7QA";
using var request = new HttpRequestMessage(HttpMethod.Get, $"https://youtube-search-and-download.p.rapidapi.com/channel?id={id}&sort=n");
//public static async Task<T?> GetTrailersByYoutubeSearch<T>(this HttpClient http, CancellationToken cancellationToken) where T : class
//{
// string id = "UCzcRQ3vRNr6fJ1A9rqFn7QA";
// using var request = new HttpRequestMessage(HttpMethod.Get, $"https://youtube-search-and-download.p.rapidapi.com/channel?id={id}&sort=n");

request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "youtube-search-and-download.p.rapidapi.com");
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "youtube-search-and-download.p.rapidapi.com");

var response = await http.SendAsync(request);
// var response = await http.SendAsync(request, cancellationToken);

if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);
// if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);

return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
}
// return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
//}

public static async Task<T?> GetReviewsByImdb8<T>(this HttpClient http, string tconst, CancellationToken cancellationToken) where T : class
{
using var request = new HttpRequestMessage(HttpMethod.Get, $"https://imdb8.p.rapidapi.com/title/get-metacritic?tconst={tconst}");
//public static async Task<T?> GetReviewsByImdb8<T>(this HttpClient http, string? tconst, CancellationToken cancellationToken) where T : class
//{
// if (string.IsNullOrEmpty(tconst)) return null;

request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "imdb8.p.rapidapi.com");
// using var request = new HttpRequestMessage(HttpMethod.Get, $"https://imdb8.p.rapidapi.com/title/v2/get-metacritic?tconst={tconst}");

var response = await http.SendAsync(request);
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Key", "36af8735e3msh39423dcd3a94067p1975bdjsn4536c4c2ed8a");
// request.Headers.TryAddWithoutValidation("X-RapidAPI-Host", "imdb8.p.rapidapi.com");

if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);
// var response = await http.SendAsync(request, cancellationToken);

return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
}
// if (!response.IsSuccessStatusCode) throw new NotificationException(response.ReasonPhrase);

// return await response.Content.ReadFromJsonAsync<T>(cancellationToken: cancellationToken);
//}
}
}
25 changes: 25 additions & 0 deletions MM.API/Core/ApiStartup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.Azure.Cosmos;

namespace MM.API.Core
{
public static class ApiStartup
{
private static readonly HttpClient _httpClient = new();

private static CosmosClient _cosmosClient = default!;

public static HttpClient HttpClient => _httpClient;
public static CosmosClient CosmosClient => _cosmosClient;

public static void Startup(string conn)
{
_cosmosClient = new(conn, new CosmosClientOptions()
{
SerializerOptions = new CosmosSerializationOptions()
{
PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
}
});
}
}
}
10 changes: 0 additions & 10 deletions MM.API/Core/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,4 @@ public static class TmdbOptions
public const string LargePosterPath = "https://www.themoviedb.org/t/p/w154/";
public const string OriginalPosterPath = "https://www.themoviedb.org/t/p/original/";
}

/// <summary>
/// this API is free, so it's not a big problem to expose this data
/// </summary>
public static class ImdbOptions
{
public const string Section = "IMDB";
public const string BaseUri = "https://imdb-api.com/en/API/";
public const string ApiKey = "k_0fc2gbsu";
}
}
40 changes: 16 additions & 24 deletions MM.API/Core/CosmosLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@

namespace MM.API.Core
{
public class CosmosLogger : ILogger
public sealed class CosmosLoggerProvider(CosmosLogRepository repo) : ILoggerProvider
{
private readonly string _name;
private readonly CosmosLogRepository _repo;
private readonly CosmosLogRepository _repo = repo;
private readonly ConcurrentDictionary<string, CosmosLogger> _loggers = new();

public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, name => new CosmosLogger(name, _repo));

public void Dispose() => _loggers.Clear();
}

public class CosmosLogger(string name, CosmosLogRepository repo) : ILogger
{
private readonly string _name = name;
private readonly CosmosLogRepository _repo = repo;

public CosmosLogger(string name, CosmosLogRepository repo)
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
_name = name;
_repo = repo;
return default;
}

public IDisposable BeginScope<TState>(TState state) => default!;

public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
Expand All @@ -39,19 +46,4 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
});
}
}

public sealed class CosmosLoggerProvider : ILoggerProvider
{
private readonly CosmosLogRepository _repo;
private readonly ConcurrentDictionary<string, CosmosLogger> _loggers = new();

public CosmosLoggerProvider(CosmosLogRepository repo)
{
_repo = repo;
}

public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, name => new CosmosLogger(name, _repo));

public void Dispose() => _loggers.Clear();
}
}
62 changes: 0 additions & 62 deletions MM.API/Core/ExceptionHandlingMiddleware.cs

This file was deleted.

13 changes: 8 additions & 5 deletions MM.API/Core/IsolatedFunctionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using MM.Shared.Core.Models;
using System.Collections.Specialized;
using System.Text.Json;
using System.Web;
Expand Down Expand Up @@ -42,6 +41,7 @@ public static class IsolatedFunctionHelper

public static async Task<T> GetPublicBody<T>(this HttpRequestData req, CancellationToken cancellationToken) where T : class, new()
{
req.Body.Position = 0; //in case of a previous read
var model = await JsonSerializer.DeserializeAsync<T>(req.Body, cancellationToken: cancellationToken);
//TODO: call Update
model ??= new T();
Expand Down Expand Up @@ -88,10 +88,13 @@ private static string BuildState(this HttpRequestData req)
{
if (ex is CosmosException cex)
{
//var result = JsonSerializer.Deserialize<CosmosExceptionStructure>(cex.ResponseBody);
var result = JsonSerializer.Deserialize<CosmosExceptionStructure>("{" + cex.ResponseBody.Replace("Errors", "\"Errors\"") + "}", options: null);
//TODO: review this

return result?.Errors.FirstOrDefault();
//var result = JsonSerializer.Deserialize<CosmosExceptionStructure>("{" + cex.ResponseBody.Replace("Errors", "\"Errors\"") + "}", options: null);

//return result?.Message?.Errors.FirstOrDefault();

return cex.Message;
}
else
{
Expand All @@ -102,7 +105,7 @@ private static string BuildState(this HttpRequestData req)

public class CosmosExceptionStructure
{
public string[] Errors { get; set; } = Array.Empty<string>();
public string[] Errors { get; set; } = [];
}

public struct Method
Expand Down
26 changes: 26 additions & 0 deletions MM.API/Core/Middleware/ExceptionHandlingMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Middleware;
using Microsoft.Extensions.Logging;
using System.Net;

namespace MM.API.Core.Middleware
{
internal sealed class ExceptionHandlingMiddleware(ILogger<ExceptionHandlingMiddleware> logger) : IFunctionsWorkerMiddleware
{
private readonly ILogger<ExceptionHandlingMiddleware> _logger = logger ?? throw new ArgumentNullException(nameof(logger));

public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
try
{
await next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing invocation");

await context.SetHttpResponseStatusCode(HttpStatusCode.InternalServerError, "Invocation failed!");
}
}
}
}
41 changes: 41 additions & 0 deletions MM.API/Core/Middleware/FunctionContextExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using System.Net;

namespace MM.API.Core.Middleware
{
public static class FunctionContextExtensions
{
public static async Task SetHttpResponseStatusCode(this FunctionContext context, HttpStatusCode statusCode, string? status)
{
var req = await context.GetHttpRequestDataAsync();

var newHttpResponse = req.CreateResponse(statusCode);

// You need to explicitly pass the status code in WriteAsJsonAsync method.
// https://github.com/Azure/azure-functions-dotnet-worker/issues/776
await newHttpResponse.WriteAsJsonAsync(new { Status = status }, newHttpResponse.StatusCode);

var invocationResult = context.GetInvocationResult();

var httpOutputBindingFromMultipleOutputBindings = GetHttpOutputBindingFromMultipleOutputBinding(context);
if (httpOutputBindingFromMultipleOutputBindings is not null)
{
httpOutputBindingFromMultipleOutputBindings.Value = newHttpResponse;
}
else
{
invocationResult.Value = newHttpResponse;
}
}

private static OutputBindingData<HttpResponseData>? GetHttpOutputBindingFromMultipleOutputBinding(FunctionContext context)
{
// The output binding entry name will be "$return" only when the function return type is HttpResponseData
var httpOutputBinding = context.GetOutputBindings<HttpResponseData>()
.FirstOrDefault(b => b.BindingType == "http" && b.Name != "$return");

return httpOutputBinding;
}
}
}
39 changes: 39 additions & 0 deletions MM.API/Core/PaddleHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.Azure.Functions.Worker.Http;
using System.Security.Cryptography;
using System.Text;

namespace MM.API.Core
{
public static class PaddleHelper
{
public static async Task<bool> ValidPaddleSignature(this HttpRequestData req, string? paddleSignature, CancellationToken cancellationToken)
{
var paddleHeader = req.Headers.GetValues("Paddle-Signature").First();
var ts = paddleHeader.Split(";")[0];
var h1 = paddleHeader.Split(";")[1];
var tsValue = ts.Split("=")[1];
var h1Value = h1.Split("=")[1];
var rawbody = await new StreamReader(req.Body).ReadToEndAsync(cancellationToken);
var payload = tsValue + ":" + rawbody;

var encoding = new UTF8Encoding();
var keyByte = encoding.GetBytes(paddleSignature ?? throw new ArgumentNullException(nameof(paddleSignature)));
var hmacsha256 = new HMACSHA256(keyByte);
var messageBytes = encoding.GetBytes(payload);
var hashmessage = hmacsha256.ComputeHash(messageBytes);
var hash = ByteToString(hashmessage);

return h1Value.Equals(hash, StringComparison.CurrentCultureIgnoreCase);
}

public static string ByteToString(byte[] buff)
{
var sbinary = new StringBuilder();
for (int i = 0; i < buff.Length; i++)
{
sbinary.Append(buff[i].ToString("X2")); // hex format
}
return (sbinary.ToString());
}
}
}
Loading

0 comments on commit 71760d8

Please sign in to comment.