feature/backend #2

Merged
s468653 merged 2 commits from feature/backend into master 2022-01-25 00:43:25 +01:00
17 changed files with 441 additions and 1 deletions

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,104 @@
using BitSearch.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace BitSearch.API.Controllers
{
[ApiController]
[Route("[controller]")]
public class SearchController : ControllerBase
{
private readonly ILogger<SearchController> _logger;
private readonly IConfiguration Configuration;
private readonly IHttpClientFactory _httpClientFactory;
public SearchController(ILogger<SearchController> logger, IConfiguration configuration, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
Configuration = configuration;
}
[HttpGet("ranking")]
public async Task<IActionResult> GetRanking()
{
var cryptoHash = new Dictionary<string, string>()
{
{"Bitcoin", "#btc"},
{"Etherum", "#eth"},
{"Ripple", "xrp"},
{"Litecoin", "#ltc"},
{"Binance Coin", "#binance"}
};
var token = Configuration["Token"];
var twitterClient = _httpClientFactory.CreateClient();
twitterClient.BaseAddress = new Uri("https://api.twitter.com/2/tweets/counts/");
twitterClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
twitterClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var ranking = new List<CryptoRanking>();
foreach (KeyValuePair<string, string> crypto in cryptoHash)
{
var requestUri = QueryHelpers.AddQueryString("recent", "query", crypto.Value);
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
var response = await twitterClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var tweetsDto = JsonConvert.DeserializeObject<TweetCount>(await response.Content.ReadAsStringAsync());
ranking.Add(new CryptoRanking() { Name = crypto.Key, TweetAmount = tweetsDto.meta.total_tweet_count });
}
}
return Ok(ranking.OrderByDescending(r => r.TweetAmount));
}
[HttpGet("analise/{hash}")]
public async Task<IActionResult> GetAnalysis(string hash)
{
var queryString = new Dictionary<string, string>()
{
{"query", $"#{hash}"},
{"max_results", "100"},
{"tweet.fields", "lang,referenced_tweets"},
};
var token = Configuration["Token"];
var twitterClient = _httpClientFactory.CreateClient();
twitterClient.BaseAddress = new Uri("https://api.twitter.com/2/tweets/search/");
var requestUri = QueryHelpers.AddQueryString("recent", queryString);
var twiiterRequest = new HttpRequestMessage(HttpMethod.Get, requestUri);
twitterClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
twitterClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await twitterClient.SendAsync(twiiterRequest);
if (response.IsSuccessStatusCode)
{
var tweetsDto = JsonConvert.DeserializeObject<TweeterResponse>(await response.Content.ReadAsStringAsync());
tweetsDto.data = tweetsDto.data.Where(d => d.lang == "en");
var microServiceClient = _httpClientFactory.CreateClient();
var microServiceRequest = new HttpRequestMessage(HttpMethod.Get, "http://127.0.0.1:5000/analysis");
microServiceRequest.Content = JsonContent.Create(tweetsDto);
var microServiceResponse = await microServiceClient.SendAsync(microServiceRequest);
return Ok(await microServiceResponse.Content.ReadAsStringAsync());
//return Ok(tweetsDto);
}
return Ok(response);
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class BaseTweetsDto<T>
{
public IEnumerable<T> data { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class CryptoRanking
{
public string Name { get; set; }
public int TweetAmount { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class MetaData
{
public int total_tweet_count { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class ReferencedTweets
{
public string type { get; set; }
public string id { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class TweetCount
{
public MetaData meta { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class TweeterResponse : BaseTweetsDto<TweetsDto>
{
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API.Models
{
public class TweetsDto
{
public string id { get; set; }
public string text { get; set; }
public string lang { get; set; }
public IEnumerable<ReferencedTweets> referenced_tweets { get; set; }
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

View File

@ -0,0 +1,31 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:62241",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"BitSearch.API": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": "true",
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

View File

@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BitSearch.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "BitSearch.API", Version = "v1" });
});
services.AddHttpClient();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "BitSearch.API v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Token": "AAAAAAAAAAAAAAAAAAAAAJm8XwEAAAAAWyiq2ESxmQgVp5gCbvccbnLzfrE%3D1g4gSrKfNveU4E382aWh6JYkESNw09tsraYMFcdv6Wk87kQixh"
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.1.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,70 @@
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace BitSearch.Tests
{
public class Browser_ops
{
IWebDriver webDriver;
public void Init_Browser()
{
var options = new ChromeOptions();
options.AcceptInsecureCertificates = true;
webDriver = new ChromeDriver("C:\\Program Files (x86)\\Google\\Chrome\\Application", options);
webDriver.Manage().Window.Maximize();
}
public string Title
{
get { return webDriver.Title; }
}
public void Goto(string url)
{
webDriver.Url = url;
}
public void Close()
{
webDriver.Quit();
}
public IWebDriver getDriver
{
get { return webDriver; }
}
}
public class LoginTests
{
Browser_ops brow = new Browser_ops();
string test_url = "https://localhost:44371/Identity/Account/Login";
IWebDriver driver;
[SetUp]
public void Setup()
{
brow.Init_Browser();
driver = brow.getDriver;
}
[Test]
public void VerifyValidLogin()
{
brow.Goto(test_url);
System.Threading.Thread.Sleep(2000);
driver.FindElement(By.XPath("//*[@id='Input_Email']")).SendKeys("testowy@mail.com");
driver.FindElement(By.XPath("//*[@id='Input_Password']")).SendKeys("12#qwE");
driver.FindElement(By.XPath("//*[@id='login-submit']")).Click();
Assert.AreEqual(driver.Url, "https://localhost:44371/");
}
[Test]
public void VerifyInvalidLogin()
{
brow.Goto(test_url);
System.Threading.Thread.Sleep(2000);
driver.FindElement(By.XPath("//*[@id=\"Input_Email\"]")).SendKeys("wrong@mail.com");
driver.FindElement(By.XPath("//*[@id='Input_Password']")).SendKeys("invalid");
driver.FindElement(By.XPath("//*[@id='login-submit']")).Click();
Assert.AreEqual(driver.FindElement(By.XPath("//*[@id='account']/div[1]/ul/li")).Text, "Invalid login attempt.");
}
}
}

View File

@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31112.23
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BitSearch", "BitSearch\BitSearch.csproj", "{F5F997CE-0BBE-478A-B7A3-828B0EAB8B99}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitSearch", "BitSearch\BitSearch.csproj", "{F5F997CE-0BBE-478A-B7A3-828B0EAB8B99}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitSearch.Tests", "BitSearch.Tests\BitSearch.Tests.csproj", "{8B871554-1F3D-4828-9642-B191B499A80C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BitSearch.API", "BitSearch.API\BitSearch.API.csproj", "{08FC64E2-3128-4517-ADCA-D1BF8AF126F0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -15,6 +19,14 @@ Global
{F5F997CE-0BBE-478A-B7A3-828B0EAB8B99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5F997CE-0BBE-478A-B7A3-828B0EAB8B99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5F997CE-0BBE-478A-B7A3-828B0EAB8B99}.Release|Any CPU.Build.0 = Release|Any CPU
{8B871554-1F3D-4828-9642-B191B499A80C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B871554-1F3D-4828-9642-B191B499A80C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B871554-1F3D-4828-9642-B191B499A80C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B871554-1F3D-4828-9642-B191B499A80C}.Release|Any CPU.Build.0 = Release|Any CPU
{08FC64E2-3128-4517-ADCA-D1BF8AF126F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08FC64E2-3128-4517-ADCA-D1BF8AF126F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08FC64E2-3128-4517-ADCA-D1BF8AF126F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08FC64E2-3128-4517-ADCA-D1BF8AF126F0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE