Compare commits
14 Commits
564429be01
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
58975ce589 | ||
![]() |
337fbba488 | ||
![]() |
8a8239908f | ||
![]() |
d93c3dce8a | ||
![]() |
ba3bffd9eb | ||
![]() |
4e31d34164 | ||
![]() |
8b4e21f29a | ||
![]() |
4748413951 | ||
![]() |
1ca1b4f1eb | ||
![]() |
2f66807bc1 | ||
![]() |
869d1f2ef1 | ||
![]() |
c889ce9e03 | ||
![]() |
6a2de3d7c2 | ||
![]() |
49304f93a2 |
30
.dockerignore
Normal file
30
.dockerignore
Normal file
@@ -0,0 +1,30 @@
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
!**/.gitignore
|
||||
!.git/HEAD
|
||||
!.git/config
|
||||
!.git/packed-refs
|
||||
!.git/refs/heads/**
|
@@ -7,14 +7,13 @@ package aia;
|
||||
|
||||
service aiAssistance {
|
||||
rpc SendQuestion (aiaRequest) returns (aiaReply);
|
||||
rpc imageAnalize (aiaRequest) returns (aiaReply);
|
||||
}
|
||||
|
||||
message aiaRequest {
|
||||
string question = 1;
|
||||
string prompts = 2;
|
||||
string model = 3;
|
||||
string apitoken = 4;
|
||||
string url = 5;
|
||||
}
|
||||
|
||||
message aiaReply {
|
||||
|
@@ -23,6 +23,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HushianWebApp", "Presentati
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIAss", "Presentation\AIAss\AIAss.csproj", "{AF6AE286-63CF-4A8A-A0B4-DBDA047FC9AE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
command.txt = command.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@@ -39,7 +39,7 @@ namespace Hushian.Infrastructure.Ai_Ass
|
||||
(new aiaRequest()
|
||||
{ Prompts = Request.ToString(),
|
||||
Question = Request.question,
|
||||
Model=model,Apitoken=_aiSettings.apitoken,Url=_aiSettings.url });
|
||||
Model=model});
|
||||
|
||||
if (response!=null)
|
||||
{
|
||||
|
@@ -24,16 +24,16 @@ namespace AIAss.Protos {
|
||||
static AiaReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"CglhaWEucHJvdG8SA2FpYSJdCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg",
|
||||
"ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkSEAoIYXBpdG9r",
|
||||
"ZW4YBCABKAkSCwoDdXJsGAUgASgJIhsKCGFpYVJlcGx5Eg8KB21lc3NhZ2UY",
|
||||
"ASABKAkyPgoMYWlBc3Npc3RhbmNlEi4KDFNlbmRRdWVzdGlvbhIPLmFpYS5h",
|
||||
"aWFSZXF1ZXN0Gg0uYWlhLmFpYVJlcGx5Qg+qAgxBSUFzcy5Qcm90b3NiBnBy",
|
||||
"b3RvMw=="));
|
||||
"CglhaWEucHJvdG8SA2FpYSI+CgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg",
|
||||
"ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkiGwoIYWlhUmVw",
|
||||
"bHkSDwoHbWVzc2FnZRgBIAEoCTJuCgxhaUFzc2lzdGFuY2USLgoMU2VuZFF1",
|
||||
"ZXN0aW9uEg8uYWlhLmFpYVJlcXVlc3QaDS5haWEuYWlhUmVwbHkSLgoMaW1h",
|
||||
"Z2VBbmFsaXplEg8uYWlhLmFpYVJlcXVlc3QaDS5haWEuYWlhUmVwbHlCD6oC",
|
||||
"DEFJQXNzLlByb3Rvc2IGcHJvdG8z"));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model", "Apitoken", "Url" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaReply), global::AIAss.Protos.aiaReply.Parser, new[]{ "Message" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
@@ -79,8 +79,6 @@ namespace AIAss.Protos {
|
||||
question_ = other.question_;
|
||||
prompts_ = other.prompts_;
|
||||
model_ = other.model_;
|
||||
apitoken_ = other.apitoken_;
|
||||
url_ = other.url_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -126,30 +124,6 @@ namespace AIAss.Protos {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "apitoken" field.</summary>
|
||||
public const int ApitokenFieldNumber = 4;
|
||||
private string apitoken_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Apitoken {
|
||||
get { return apitoken_; }
|
||||
set {
|
||||
apitoken_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "url" field.</summary>
|
||||
public const int UrlFieldNumber = 5;
|
||||
private string url_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Url {
|
||||
get { return url_; }
|
||||
set {
|
||||
url_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
@@ -168,8 +142,6 @@ namespace AIAss.Protos {
|
||||
if (Question != other.Question) return false;
|
||||
if (Prompts != other.Prompts) return false;
|
||||
if (Model != other.Model) return false;
|
||||
if (Apitoken != other.Apitoken) return false;
|
||||
if (Url != other.Url) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -180,8 +152,6 @@ namespace AIAss.Protos {
|
||||
if (Question.Length != 0) hash ^= Question.GetHashCode();
|
||||
if (Prompts.Length != 0) hash ^= Prompts.GetHashCode();
|
||||
if (Model.Length != 0) hash ^= Model.GetHashCode();
|
||||
if (Apitoken.Length != 0) hash ^= Apitoken.GetHashCode();
|
||||
if (Url.Length != 0) hash ^= Url.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
@@ -212,14 +182,6 @@ namespace AIAss.Protos {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteString(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteString(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
@@ -242,14 +204,6 @@ namespace AIAss.Protos {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteString(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteString(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
@@ -269,12 +223,6 @@ namespace AIAss.Protos {
|
||||
if (Model.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
@@ -296,12 +244,6 @@ namespace AIAss.Protos {
|
||||
if (other.Model.Length != 0) {
|
||||
Model = other.Model;
|
||||
}
|
||||
if (other.Apitoken.Length != 0) {
|
||||
Apitoken = other.Apitoken;
|
||||
}
|
||||
if (other.Url.Length != 0) {
|
||||
Url = other.Url;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -329,14 +271,6 @@ namespace AIAss.Protos {
|
||||
Model = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
Apitoken = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
Url = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -364,14 +298,6 @@ namespace AIAss.Protos {
|
||||
Model = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
Apitoken = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
Url = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -58,6 +58,14 @@ namespace AIAss.Protos {
|
||||
__Marshaller_aia_aiaRequest,
|
||||
__Marshaller_aia_aiaReply);
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Method<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply> __Method_imageAnalize = new grpc::Method<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"imageAnalize",
|
||||
__Marshaller_aia_aiaRequest,
|
||||
__Marshaller_aia_aiaReply);
|
||||
|
||||
/// <summary>Service descriptor</summary>
|
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
|
||||
{
|
||||
@@ -74,6 +82,12 @@ namespace AIAss.Protos {
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::System.Threading.Tasks.Task<global::AIAss.Protos.aiaReply> imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Client for aiAssistance</summary>
|
||||
@@ -123,6 +137,26 @@ namespace AIAss.Protos {
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_SendQuestion, null, options, request);
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::AIAss.Protos.aiaReply imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return imageAnalize(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::AIAss.Protos.aiaReply imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_imageAnalize, null, options, request);
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::AIAss.Protos.aiaReply> imageAnalizeAsync(global::AIAss.Protos.aiaRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return imageAnalizeAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::AIAss.Protos.aiaReply> imageAnalizeAsync(global::AIAss.Protos.aiaRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_imageAnalize, null, options, request);
|
||||
}
|
||||
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
protected override aiAssistanceClient NewInstance(ClientBaseConfiguration configuration)
|
||||
@@ -137,7 +171,8 @@ namespace AIAss.Protos {
|
||||
public static grpc::ServerServiceDefinition BindService(aiAssistanceBase serviceImpl)
|
||||
{
|
||||
return grpc::ServerServiceDefinition.CreateBuilder()
|
||||
.AddMethod(__Method_SendQuestion, serviceImpl.SendQuestion).Build();
|
||||
.AddMethod(__Method_SendQuestion, serviceImpl.SendQuestion)
|
||||
.AddMethod(__Method_imageAnalize, serviceImpl.imageAnalize).Build();
|
||||
}
|
||||
|
||||
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
|
||||
@@ -148,6 +183,7 @@ namespace AIAss.Protos {
|
||||
public static void BindService(grpc::ServiceBinderBase serviceBinder, aiAssistanceBase serviceImpl)
|
||||
{
|
||||
serviceBinder.AddMethod(__Method_SendQuestion, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(serviceImpl.SendQuestion));
|
||||
serviceBinder.AddMethod(__Method_imageAnalize, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(serviceImpl.imageAnalize));
|
||||
}
|
||||
|
||||
}
|
||||
|
374
Presentation/AIAss/.dockerignore
Normal file
374
Presentation/AIAss/.dockerignore
Normal file
@@ -0,0 +1,374 @@
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these files will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment the next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
CConversionReport*.XML
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.user
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
10
Presentation/AIAss/Docker Command.txt
Normal file
10
Presentation/AIAss/Docker Command.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
docker build -t ai_assistance .
|
||||
|
||||
docker run --name openai_assistance -d -p 5042:5010 ai_assistance
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------
|
||||
in local => docker build -t mmrbnjd/ai_assistance:latest .
|
||||
in local => docker push mmrbnjd/ai_assistance:latest
|
||||
in server => docker pull mmrbnjd/ai_assistance:latest
|
||||
in server => docker run -d -p 5042:5010 --restart always mmrbnjd/ai_assistance:latest
|
40
Presentation/AIAss/Dockerfile
Normal file
40
Presentation/AIAss/Dockerfile
Normal file
@@ -0,0 +1,40 @@
|
||||
# Use the official .NET 9.0 runtime image as the base image
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 5010
|
||||
|
||||
# Use the official .NET 9.0 SDK image for building
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Copy the project file and restore dependencies
|
||||
COPY ["AIAss.csproj", "./"]
|
||||
RUN dotnet restore "AIAss.csproj"
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY . .
|
||||
WORKDIR "/src/."
|
||||
|
||||
# Build the application
|
||||
RUN dotnet build "AIAss.csproj" -c Release -o /app/build
|
||||
|
||||
# Publish the application
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "AIAss.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
# Final stage/image
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
|
||||
# Set environment variables
|
||||
ENV ASPNETCORE_URLS=http://+:5010;
|
||||
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
# Create a non-root user for security
|
||||
RUN adduser --disabled-password --gecos "" appuser && chown -R appuser /app
|
||||
USER appuser
|
||||
|
||||
# Set the entry point
|
||||
ENTRYPOINT ["dotnet", "AIAss.dll"]
|
||||
|
110
Presentation/AIAss/README-Docker.md
Normal file
110
Presentation/AIAss/README-Docker.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# AIAss Docker Setup
|
||||
|
||||
This document explains how to run the AIAss gRPC service using Docker.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Desktop installed and running
|
||||
- Docker Compose (usually comes with Docker Desktop)
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker Compose (Recommended)
|
||||
|
||||
1. Navigate to the AIAss project directory:
|
||||
```bash
|
||||
cd Presentation/AIAss
|
||||
```
|
||||
|
||||
2. Build and run the service:
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
3. The service will be available at:
|
||||
- HTTP: http://localhost:5000
|
||||
- HTTPS: https://localhost:5001
|
||||
|
||||
### Using Docker directly
|
||||
|
||||
1. Build the Docker image:
|
||||
```bash
|
||||
docker build -t aiass .
|
||||
```
|
||||
|
||||
2. Run the container:
|
||||
```bash
|
||||
docker run -p 5000:80 -p 5001:443 aiass
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `ASPNETCORE_ENVIRONMENT`: Set to `Development` or `Production`
|
||||
- `ASPNETCORE_URLS`: Configure the URLs the service listens on
|
||||
|
||||
### Ports
|
||||
|
||||
- Port 80: HTTP endpoint
|
||||
- Port 443: HTTPS endpoint
|
||||
|
||||
## Development
|
||||
|
||||
### Hot Reload
|
||||
|
||||
For development with hot reload, you can mount the source code:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- .:/src
|
||||
- /src/bin
|
||||
- /src/obj
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
To debug the containerized application, you can:
|
||||
|
||||
1. Attach a debugger to the running container
|
||||
2. Use remote debugging tools
|
||||
3. Check logs: `docker-compose logs aiass`
|
||||
|
||||
## Production
|
||||
|
||||
For production deployment:
|
||||
|
||||
1. Set `ASPNETCORE_ENVIRONMENT=Production`
|
||||
2. Use proper SSL certificates
|
||||
3. Configure health checks
|
||||
4. Set up monitoring and logging
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Port already in use**: Change the port mappings in docker-compose.yml
|
||||
2. **Build failures**: Ensure all dependencies are properly restored
|
||||
3. **Permission issues**: Check file ownership and Docker user settings
|
||||
|
||||
### Logs
|
||||
|
||||
View container logs:
|
||||
```bash
|
||||
docker-compose logs -f aiass
|
||||
```
|
||||
|
||||
### Cleanup
|
||||
|
||||
Remove containers and images:
|
||||
```bash
|
||||
docker-compose down
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
## Security Notes
|
||||
|
||||
- The container runs as a non-root user (`appuser`)
|
||||
- Only necessary ports are exposed
|
||||
- Environment variables can be overridden for different deployment scenarios
|
||||
|
@@ -4,19 +4,29 @@ using AIAss.Protos;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AIAss.Services;
|
||||
|
||||
public class aiAssistanceService: aiAssistance.aiAssistanceBase
|
||||
public class aiAssistanceService : aiAssistance.aiAssistanceBase
|
||||
{
|
||||
private readonly string Apitoken;
|
||||
private readonly string url;
|
||||
public aiAssistanceService(IConfiguration configuration)
|
||||
{
|
||||
url = configuration["aiSettings:url"];
|
||||
Apitoken = configuration["aiSettings:apitoken"];
|
||||
|
||||
}
|
||||
|
||||
public async override Task<aiaReply> SendQuestion(aiaRequest request, ServerCallContext context)
|
||||
{
|
||||
using var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Authorization =
|
||||
new AuthenticationHeaderValue("Bearer", request.Apitoken);
|
||||
new AuthenticationHeaderValue("Bearer", Apitoken);
|
||||
var content = new
|
||||
{
|
||||
model= request.Model,
|
||||
model = request.Model,
|
||||
messages = new[]
|
||||
{
|
||||
new { role = "system", content = "شما یک دستیار پاسخگو به سوالات هستید." },
|
||||
@@ -24,7 +34,7 @@ namespace AIAss.Services;
|
||||
new { role = "system", content = "به سوالات غیره متن بالا پاسخ نده و بگو در این زمینه اطلاعی ندارم" }
|
||||
}
|
||||
};
|
||||
var response = await client.PostAsync(request.Url,
|
||||
var response = await client.PostAsync(url,
|
||||
new StringContent(JsonSerializer.Serialize(content), Encoding.UTF8, "application/json"));
|
||||
string reponse = "";
|
||||
if (response.IsSuccessStatusCode)
|
||||
@@ -35,7 +45,66 @@ namespace AIAss.Services;
|
||||
}
|
||||
else
|
||||
{
|
||||
reponse="خطا در ارتباط سرور ai";
|
||||
reponse = "خطا در ارتباط سرور ai";
|
||||
}
|
||||
|
||||
return new aiaReply
|
||||
{
|
||||
Message = $" {reponse}"
|
||||
};
|
||||
}
|
||||
public async override Task<aiaReply> imageAnalize(aiaRequest request, ServerCallContext context)
|
||||
{
|
||||
|
||||
|
||||
using var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Authorization =
|
||||
new AuthenticationHeaderValue("Bearer", Apitoken);
|
||||
var content = new
|
||||
{
|
||||
model = request.Model,
|
||||
messages = new object[]
|
||||
{
|
||||
new {
|
||||
role = "system",
|
||||
content = "شما دستیار برای توصیف آزمایشات هستید."
|
||||
},
|
||||
new {
|
||||
role = "user",
|
||||
content = new object[]
|
||||
{
|
||||
new { type = "text", text = "این تصویر اگر آزمایش انسان است توصیف کن در غیر اینصورت پاسخ نده" },
|
||||
new {
|
||||
type = "image_url",
|
||||
image_url = new {
|
||||
url = $"data:image/jpeg;base64,{request.Question}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var response = await client.PostAsync(url,
|
||||
new StringContent(JsonSerializer.Serialize(content), Encoding.UTF8, "application/json"));
|
||||
string reponse = "";
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
reponse = doc.RootElement.GetProperty("choices")[0].GetProperty("message").GetProperty("content").GetString();
|
||||
context.Status = new Status(StatusCode.OK,"is Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
reponse = "خطا در ارتباط سرور ai";
|
||||
if (response.StatusCode==System.Net.HttpStatusCode.TooManyRequests)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Cancelled, "ترافیک بالای شبکه در زمان دیگری تلاش کنید"));
|
||||
|
||||
}
|
||||
else
|
||||
throw new RpcException(new Status(StatusCode.Cancelled, "خطا در ارتباط سرور"));
|
||||
}
|
||||
|
||||
return new aiaReply
|
||||
|
@@ -10,5 +10,11 @@
|
||||
"EndpointDefaults": {
|
||||
"Protocols": "Http2"
|
||||
}
|
||||
},
|
||||
"aiSettings": {
|
||||
"url": "https://api.openai.com/v1/chat/completions",
|
||||
"apitokenold": "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",
|
||||
"apitoken": "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"
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -24,16 +24,16 @@ namespace AIAss.Protos {
|
||||
static AiaReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"CglhaWEucHJvdG8SA2FpYSJdCgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg",
|
||||
"ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkSEAoIYXBpdG9r",
|
||||
"ZW4YBCABKAkSCwoDdXJsGAUgASgJIhsKCGFpYVJlcGx5Eg8KB21lc3NhZ2UY",
|
||||
"ASABKAkyPgoMYWlBc3Npc3RhbmNlEi4KDFNlbmRRdWVzdGlvbhIPLmFpYS5h",
|
||||
"aWFSZXF1ZXN0Gg0uYWlhLmFpYVJlcGx5Qg+qAgxBSUFzcy5Qcm90b3NiBnBy",
|
||||
"b3RvMw=="));
|
||||
"CglhaWEucHJvdG8SA2FpYSI+CgphaWFSZXF1ZXN0EhAKCHF1ZXN0aW9uGAEg",
|
||||
"ASgJEg8KB3Byb21wdHMYAiABKAkSDQoFbW9kZWwYAyABKAkiGwoIYWlhUmVw",
|
||||
"bHkSDwoHbWVzc2FnZRgBIAEoCTJuCgxhaUFzc2lzdGFuY2USLgoMU2VuZFF1",
|
||||
"ZXN0aW9uEg8uYWlhLmFpYVJlcXVlc3QaDS5haWEuYWlhUmVwbHkSLgoMaW1h",
|
||||
"Z2VBbmFsaXplEg8uYWlhLmFpYVJlcXVlc3QaDS5haWEuYWlhUmVwbHlCD6oC",
|
||||
"DEFJQXNzLlByb3Rvc2IGcHJvdG8z"));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model", "Apitoken", "Url" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaRequest), global::AIAss.Protos.aiaRequest.Parser, new[]{ "Question", "Prompts", "Model" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AIAss.Protos.aiaReply), global::AIAss.Protos.aiaReply.Parser, new[]{ "Message" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
@@ -79,8 +79,6 @@ namespace AIAss.Protos {
|
||||
question_ = other.question_;
|
||||
prompts_ = other.prompts_;
|
||||
model_ = other.model_;
|
||||
apitoken_ = other.apitoken_;
|
||||
url_ = other.url_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -126,30 +124,6 @@ namespace AIAss.Protos {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "apitoken" field.</summary>
|
||||
public const int ApitokenFieldNumber = 4;
|
||||
private string apitoken_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Apitoken {
|
||||
get { return apitoken_; }
|
||||
set {
|
||||
apitoken_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "url" field.</summary>
|
||||
public const int UrlFieldNumber = 5;
|
||||
private string url_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Url {
|
||||
get { return url_; }
|
||||
set {
|
||||
url_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
@@ -168,8 +142,6 @@ namespace AIAss.Protos {
|
||||
if (Question != other.Question) return false;
|
||||
if (Prompts != other.Prompts) return false;
|
||||
if (Model != other.Model) return false;
|
||||
if (Apitoken != other.Apitoken) return false;
|
||||
if (Url != other.Url) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -180,8 +152,6 @@ namespace AIAss.Protos {
|
||||
if (Question.Length != 0) hash ^= Question.GetHashCode();
|
||||
if (Prompts.Length != 0) hash ^= Prompts.GetHashCode();
|
||||
if (Model.Length != 0) hash ^= Model.GetHashCode();
|
||||
if (Apitoken.Length != 0) hash ^= Apitoken.GetHashCode();
|
||||
if (Url.Length != 0) hash ^= Url.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
@@ -212,14 +182,6 @@ namespace AIAss.Protos {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteString(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteString(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
@@ -242,14 +204,6 @@ namespace AIAss.Protos {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteString(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteString(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
@@ -269,12 +223,6 @@ namespace AIAss.Protos {
|
||||
if (Model.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Model);
|
||||
}
|
||||
if (Apitoken.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Apitoken);
|
||||
}
|
||||
if (Url.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Url);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
@@ -296,12 +244,6 @@ namespace AIAss.Protos {
|
||||
if (other.Model.Length != 0) {
|
||||
Model = other.Model;
|
||||
}
|
||||
if (other.Apitoken.Length != 0) {
|
||||
Apitoken = other.Apitoken;
|
||||
}
|
||||
if (other.Url.Length != 0) {
|
||||
Url = other.Url;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -329,14 +271,6 @@ namespace AIAss.Protos {
|
||||
Model = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
Apitoken = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
Url = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -364,14 +298,6 @@ namespace AIAss.Protos {
|
||||
Model = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
Apitoken = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
Url = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -58,6 +58,14 @@ namespace AIAss.Protos {
|
||||
__Marshaller_aia_aiaRequest,
|
||||
__Marshaller_aia_aiaReply);
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
static readonly grpc::Method<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply> __Method_imageAnalize = new grpc::Method<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(
|
||||
grpc::MethodType.Unary,
|
||||
__ServiceName,
|
||||
"imageAnalize",
|
||||
__Marshaller_aia_aiaRequest,
|
||||
__Marshaller_aia_aiaReply);
|
||||
|
||||
/// <summary>Service descriptor</summary>
|
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
|
||||
{
|
||||
@@ -74,6 +82,12 @@ namespace AIAss.Protos {
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::System.Threading.Tasks.Task<global::AIAss.Protos.aiaReply> imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::ServerCallContext context)
|
||||
{
|
||||
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Client for aiAssistance</summary>
|
||||
@@ -123,6 +137,26 @@ namespace AIAss.Protos {
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_SendQuestion, null, options, request);
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::AIAss.Protos.aiaReply imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return imageAnalize(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual global::AIAss.Protos.aiaReply imageAnalize(global::AIAss.Protos.aiaRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.BlockingUnaryCall(__Method_imageAnalize, null, options, request);
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::AIAss.Protos.aiaReply> imageAnalizeAsync(global::AIAss.Protos.aiaRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
|
||||
{
|
||||
return imageAnalizeAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
|
||||
}
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
public virtual grpc::AsyncUnaryCall<global::AIAss.Protos.aiaReply> imageAnalizeAsync(global::AIAss.Protos.aiaRequest request, grpc::CallOptions options)
|
||||
{
|
||||
return CallInvoker.AsyncUnaryCall(__Method_imageAnalize, null, options, request);
|
||||
}
|
||||
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)]
|
||||
protected override aiAssistanceClient NewInstance(ClientBaseConfiguration configuration)
|
||||
@@ -137,7 +171,8 @@ namespace AIAss.Protos {
|
||||
public static grpc::ServerServiceDefinition BindService(aiAssistanceBase serviceImpl)
|
||||
{
|
||||
return grpc::ServerServiceDefinition.CreateBuilder()
|
||||
.AddMethod(__Method_SendQuestion, serviceImpl.SendQuestion).Build();
|
||||
.AddMethod(__Method_SendQuestion, serviceImpl.SendQuestion)
|
||||
.AddMethod(__Method_imageAnalize, serviceImpl.imageAnalize).Build();
|
||||
}
|
||||
|
||||
/// <summary>Register service method with a service binder with or without implementation. Useful when customizing the service binding logic.
|
||||
@@ -148,6 +183,7 @@ namespace AIAss.Protos {
|
||||
public static void BindService(grpc::ServiceBinderBase serviceBinder, aiAssistanceBase serviceImpl)
|
||||
{
|
||||
serviceBinder.AddMethod(__Method_SendQuestion, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(serviceImpl.SendQuestion));
|
||||
serviceBinder.AddMethod(__Method_imageAnalize, serviceImpl == null ? null : new grpc::UnaryServerMethod<global::AIAss.Protos.aiaRequest, global::AIAss.Protos.aiaReply>(serviceImpl.imageAnalize));
|
||||
}
|
||||
|
||||
}
|
||||
|
10
Presentation/Hushian.WebApi/DockerCommand.txt
Normal file
10
Presentation/Hushian.WebApi/DockerCommand.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
E:\_hushian> docker build -f Presentation\Hushian.WebApi\Dockerfile -t hushianapi .
|
||||
|
||||
docker run --name hushian_api -d -p 2201:8080 hushianapi
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------
|
||||
in local => docker build -f Presentation\Hushian.WebApi\Dockerfile -t mmrbnjd/hushianapi:latest .
|
||||
in local => docker push mmrbnjd/hushianapi:latest
|
||||
in server => docker pull mmrbnjd/hushianapi:latest
|
||||
in server => docker run -d -p 2201:8080 --restart always mmrbnjd/hushianapi:latest
|
35
Presentation/Hushian.WebApi/Dockerfile
Normal file
35
Presentation/Hushian.WebApi/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
# This stage is used when running from VS in fast mode (Default for Debug configuration)
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
|
||||
USER $APP_UID
|
||||
WORKDIR /app
|
||||
EXPOSE 8080
|
||||
EXPOSE 8081
|
||||
|
||||
|
||||
# This stage is used to build the service project
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
WORKDIR /src
|
||||
COPY ["Presentation/Hushian.WebApi/Hushian.WebApi.csproj", "Presentation/Hushian.WebApi/"]
|
||||
COPY ["Common/Common.csproj", "Common/"]
|
||||
COPY ["Hushian.Application/Hushian.Application.csproj", "Hushian.Application/"]
|
||||
COPY ["Hushian.Domain/Hushian.Domain.csproj", "Hushian.Domain/"]
|
||||
COPY ["Infrastructure/Infrastructure/Hushian.Infrastructure.csproj", "Infrastructure/Infrastructure/"]
|
||||
COPY ["Infrastructure/Persistence/Hushian.Persistence.csproj", "Infrastructure/Persistence/"]
|
||||
RUN dotnet restore "./Presentation/Hushian.WebApi/Hushian.WebApi.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Presentation/Hushian.WebApi"
|
||||
RUN dotnet build "./Hushian.WebApi.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||
|
||||
# This stage is used to publish the service project to be copied to the final stage
|
||||
FROM build AS publish
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
RUN dotnet publish "./Hushian.WebApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||
|
||||
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "Hushian.WebApi.dll"]
|
@@ -4,6 +4,9 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>a648da2d-f055-444d-91e3-3d53de7d1f5a</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<DockerfileContext>..\..</DockerfileContext>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -16,6 +19,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -1,23 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
{
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5089",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5089"
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7046;http://localhost:5089",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "https://localhost:7046;http://localhost:5089"
|
||||
},
|
||||
"Container (Dockerfile)": {
|
||||
"commandName": "Docker",
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_HTTPS_PORTS": "8081",
|
||||
"ASPNETCORE_HTTP_PORTS": "8080"
|
||||
},
|
||||
"publishAllPorts": true,
|
||||
"useSSL": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json"
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"MainConnectionString": "Data Source=195.88.208.142;Initial Catalog=Hushian;User ID=sa;Password=M439610m@;TrustServerCertificate=True"
|
||||
"MainConnectionString": "Data Source=156.255.1.229;Initial Catalog=Hushian;User ID=sa;Password=SAPassw0rd;TrustServerCertificate=True"
|
||||
},
|
||||
"EmailSettings": {
|
||||
"ApiKey": "SendGrid_Key_Here",
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
},
|
||||
"aigrpcserver": {
|
||||
"target": "localhost:5010"
|
||||
"target": "156.255.1.229:5042"
|
||||
|
||||
|
||||
},
|
||||
|
@@ -1,5 +1,4 @@
|
||||
|
||||
@using Common.Dtos.Verification
|
||||
@using Common.Dtos.Verification
|
||||
@using Common.Enums
|
||||
@using HushianWebApp.Service
|
||||
@inject VerificationService verificationService;
|
||||
@@ -10,27 +9,9 @@
|
||||
</div>
|
||||
@if (type == VerificationCodeType.ForgetPassword)
|
||||
{
|
||||
<div style="justify-content: space-between;margin-top:5px;;margin-bottom:15px">
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code1" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input1" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code2" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input2" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code3" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input3" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code4" @oninput="OnLastInput"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input4" />
|
||||
</div>
|
||||
<div style="justify-content: space-between;margin-top:5px;margin-bottom:15px">
|
||||
<input class="cus-input" maxlength='4' @bind-value="code" @bind-value:event="oninput" />
|
||||
</div>
|
||||
|
||||
<div style="justify-content: space-between">
|
||||
<TextInput @bind-value=Value type="password" name="Value" style="text-align:center;margin-top: 10px;;margin-left: 10px" placeholder="کلمه عبور جدید" required="required" />
|
||||
@@ -43,27 +24,7 @@
|
||||
else
|
||||
{
|
||||
<div style="justify-content: space-between;margin-top:5px">
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code1" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input1" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code2" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input2" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code3" @oninput="MoveNext"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input3" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code4" @oninput="OnLastInput"
|
||||
style="width: 40px; height: 40px; text-align: center; border: 2px solid #ccc; border-radius: 5px; font-size: 20px;"
|
||||
@ref="input4" />
|
||||
|
||||
<input class="cus-input" maxlength='4' @bind-value="code" @bind-value:event="oninput" />
|
||||
|
||||
</div>
|
||||
}
|
||||
@@ -82,7 +43,18 @@ else
|
||||
public string sendValue { get; set; }
|
||||
[Parameter]
|
||||
public int? ID { get; set; }
|
||||
public string? code { get; set; }
|
||||
private string? _code = string.Empty;
|
||||
public string? code
|
||||
{
|
||||
get { return _code; }
|
||||
set
|
||||
{
|
||||
_code = value;
|
||||
if (value.Length == 4)
|
||||
onClick().ConfigureAwait(true);
|
||||
|
||||
}
|
||||
}
|
||||
[Parameter] public string? Title { get; set; }
|
||||
[Inject] protected ToastService ToastService { get; set; } = default!;
|
||||
[Parameter] public EventCallback<VerificationCodeType> OnMultipleOfThree { get; set; }
|
||||
@@ -92,7 +64,7 @@ else
|
||||
string resendmsg = "ارسال مجدد";
|
||||
bool Disabledresendmsg = false;
|
||||
//-----------------
|
||||
private string code1, code2, code3, code4;
|
||||
//private string code1, code2, code3, code4;
|
||||
|
||||
private ElementReference input1, input2, input3, input4;
|
||||
}
|
||||
@@ -144,14 +116,16 @@ else
|
||||
else
|
||||
{
|
||||
if (Value != ReValue)
|
||||
{ ToastService.Notify(new(ToastType.Warning, $"کلمه عبور جدید و تکرار متفاوت هستند"));
|
||||
return;}
|
||||
{
|
||||
ToastService.Notify(new(ToastType.Warning, $"کلمه عبور جدید و تکرار متفاوت هستند"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
loading = true;
|
||||
loading = true;
|
||||
if (await verificationService.ConfirmedCode(new ConfirmedCodeDto()
|
||||
{ code = code, codeType = type, Id = ID.Value, value = Value }))
|
||||
{
|
||||
@@ -161,35 +135,54 @@ else
|
||||
}
|
||||
loading = false;
|
||||
}
|
||||
private async Task MoveNext(ChangeEventArgs e)
|
||||
{
|
||||
if (e.Value?.ToString()?.Length == 1)
|
||||
{
|
||||
if (input1.Context == null) return;
|
||||
// private async Task MoveNext(ChangeEventArgs e)
|
||||
// {
|
||||
// if (e.Value?.ToString()?.Length == 1)
|
||||
// {
|
||||
// if (input1.Context == null) return;
|
||||
|
||||
if (string.IsNullOrEmpty(code1))
|
||||
await input2.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code2))
|
||||
await input3.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code3))
|
||||
await input4.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code4))
|
||||
{
|
||||
code = $"{code1}{code2}{code3}{code4}";
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task OnLastInput(ChangeEventArgs e)
|
||||
{
|
||||
code4 = e.Value?.ToString();
|
||||
// if (string.IsNullOrEmpty(code1))
|
||||
// await input2.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code2))
|
||||
// await input3.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code3))
|
||||
// await input4.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code4))
|
||||
// {
|
||||
// code = $"{code1}{code2}{code3}{code4}";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// private async Task OnLastInput(ChangeEventArgs e)
|
||||
// {
|
||||
// ///code4 = e.Value?.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(code4) && code4.Length == 1)
|
||||
{
|
||||
code = $"{code1}{code2}{code3}{code4}";
|
||||
if(type==VerificationCodeType.PhoneNumberConfirmed)
|
||||
await onClick();
|
||||
}
|
||||
}
|
||||
// if (!string.IsNullOrEmpty(code) && code.Length == 4)
|
||||
// {
|
||||
// // code = $"{code1}{code2}{code3}{code4}";
|
||||
// if (type == VerificationCodeType.PhoneNumberConfirmed)
|
||||
// await onClick();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
<style>
|
||||
.cus-input {
|
||||
direction: ltr;
|
||||
display: block;
|
||||
margin: 2em auto;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: 6ch;
|
||||
background: repeating-linear-gradient(90deg, dimgrey 0, dimgrey 1ch, transparent 0, transparent 1.5ch) 0 100%/ 5.5ch 2px no-repeat;
|
||||
font: 5ch droid sans mono, consolas, monospace;
|
||||
letter-spacing: 0.5ch;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
color: dodgerblue;
|
||||
}
|
||||
|
||||
</style>
|
12
Presentation/HushianWebApp/DockerCommand.txt
Normal file
12
Presentation/HushianWebApp/DockerCommand.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
E:\_hushian> docker build -f Presentation\HushianWebApp\Dockerfile -t hushianapp .
|
||||
|
||||
|
||||
docker run --name hushian_app -d -p 5165:5165 sha256:cd08e4a869cb44e17fafdcf551e7eaa3f26c0c3d1420df78f695359bde08f0fb
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------
|
||||
in local => docker build -f Presentation\HushianWebApp\Dockerfile -t mmrbnjd/hushianapp:latest .
|
||||
in local => docker push mmrbnjd/hushianapp:latest
|
||||
in server => docker pull mmrbnjd/hushianapp:latest
|
||||
in server => docker run -d -p 2101:5165 --restart always mmrbnjd/hushianapp:latest
|
74
Presentation/HushianWebApp/Dockerfile
Normal file
74
Presentation/HushianWebApp/Dockerfile
Normal file
@@ -0,0 +1,74 @@
|
||||
# مرحله ۱: Build پروژه Blazor WASM با .NET 9
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
# نصب وابستگیها برای emscripten (python3 + سایر ابزارها)
|
||||
RUN apt-get update && apt-get install -y python3 make cmake clang zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# کپی کردن فایلهای پروژه
|
||||
COPY ["Presentation/HushianWebApp/HushianWebApp.csproj", "Presentation/HushianWebApp/"]
|
||||
COPY ["Common/Common.csproj", "Common/"]
|
||||
COPY . .
|
||||
RUN dotnet workload clean
|
||||
|
||||
# نصب wasm-tools برای Blazor
|
||||
RUN dotnet workload install wasm-tools
|
||||
|
||||
# انتشار (Publish) خروجی در حالت Release
|
||||
RUN dotnet publish "Presentation/HushianWebApp/HushianWebApp.csproj" -c Release -o /app \
|
||||
-p:TreatWarningsAsErrors=false \
|
||||
-p:RunAOTCompilation=false \
|
||||
-p:PublishTrimmed=false
|
||||
|
||||
# مرحله ۲: سرو کردن با Nginx
|
||||
FROM nginx:alpine AS final
|
||||
WORKDIR /usr/share/nginx/html
|
||||
|
||||
# حذف محتوای پیشفرض nginx
|
||||
RUN rm -rf ./*
|
||||
|
||||
# کپی خروجی Blazor WASM
|
||||
COPY --from=build /app/wwwroot ./
|
||||
|
||||
# فقط بلوک server داخل default.conf
|
||||
RUN printf 'server {\n\
|
||||
listen 5165;\n\
|
||||
server_name localhost;\n\
|
||||
\n\
|
||||
root /usr/share/nginx/html;\n\
|
||||
index index.html;\n\
|
||||
\n\
|
||||
location / {\n\
|
||||
try_files $uri $uri/ /index.html;\n\
|
||||
}\n\
|
||||
\n\
|
||||
location /_framework/ {\n\
|
||||
expires 1y;\n\
|
||||
add_header Cache-Control "public, immutable";\n\
|
||||
}\n\
|
||||
\n\
|
||||
location /_content/ {\n\
|
||||
expires 1y;\n\
|
||||
add_header Cache-Control "public, immutable";\n\
|
||||
}\n\
|
||||
\n\
|
||||
location /Before/ {\n\
|
||||
expires 7d;\n\
|
||||
add_header Cache-Control "public";\n\
|
||||
}\n\
|
||||
\n\
|
||||
location ~ \\.dll$ { add_header Content-Type application/octet-stream; }\n\
|
||||
location ~ \\.wasm$ { add_header Content-Type application/wasm; }\n\
|
||||
location ~ \\.pdb$ { add_header Content-Type application/octet-stream; }\n\
|
||||
location ~ \\.dat$ { add_header Content-Type application/octet-stream; }\n\
|
||||
\n\
|
||||
gzip on;\n\
|
||||
gzip_types text/plain application/xml text/css application/javascript application/json application/wasm;\n\
|
||||
gzip_min_length 256;\n\
|
||||
\n\
|
||||
error_page 404 /index.html;\n\
|
||||
}' > /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 5165
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
File diff suppressed because one or more lines are too long
@@ -18,8 +18,6 @@
|
||||
Href="/"
|
||||
IconName="IconName.BootstrapFill"
|
||||
Title="هوشــیان"
|
||||
BadgeText="v1.3.1"
|
||||
ImageSrc="/before/assets/images/logofilehushian.png"
|
||||
DataProvider="SidebarDataProvider"
|
||||
Width="200"
|
||||
WidthUnit="Unit.Px" />
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -45,38 +45,17 @@
|
||||
|
||||
<div class="d-flex justify-content-center">
|
||||
|
||||
<div class="verification-inputs" style="display: flex; gap: 8px; direction: ltr;">
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code1" @oninput="MoveNext"
|
||||
style="width: 45px; height: 45px; text-align: center; border: 2px solid #ccc; border-radius: 8px; font-size: 18px; font-weight: bold;"
|
||||
@ref="input1" autoFocus />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code2" @oninput="MoveNext"
|
||||
style="width: 45px; height: 45px; text-align: center; border: 2px solid #ccc; border-radius: 8px; font-size: 18px; font-weight: bold;"
|
||||
@ref="input2" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code3" @oninput="MoveNext"
|
||||
style="width: 45px; height: 45px; text-align: center; border: 2px solid #ccc; border-radius: 8px; font-size: 18px; font-weight: bold;"
|
||||
@ref="input3" />
|
||||
|
||||
<input maxlength="1" type="text" inputmode="numeric" pattern="[0-9]*"
|
||||
@bind="code4" @oninput="OnLastInput"
|
||||
style="width: 45px; height: 45px; text-align: center; border: 2px solid #ccc; border-radius: 8px; font-size: 18px; font-weight: bold;"
|
||||
@ref="input4" />
|
||||
|
||||
</div>
|
||||
<input class="cus-input" maxlength='4' @bind-value="Code" @bind-value:event="oninput"/>
|
||||
|
||||
</div>
|
||||
<Button Color="ButtonColor.Link"
|
||||
Disabled="@isButtonDisabled"
|
||||
@onclick="async () =>
|
||||
Disabled="@isButtonDisabled"
|
||||
@onclick="async () =>
|
||||
{
|
||||
await verificationService.ReSendCode(ID);
|
||||
await verifiTimer();
|
||||
}"
|
||||
Style="padding: 6px 16px; font-size: 14px; background-color: #f8f9fa; transition: all 0.3s ease; display: inline-flex; align-items: center; gap: 8px; margin-top: 10px;margin-bottom: -10px;">
|
||||
Style="padding: 6px 16px; font-size: 14px; background-color: #f8f9fa; transition: all 0.3s ease; display: inline-flex; align-items: center; gap: 8px; margin-top: 10px;margin-bottom: -10px;">
|
||||
|
||||
<span>ارسال مجدد</span>
|
||||
|
||||
@@ -98,9 +77,16 @@
|
||||
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
|
||||
public string Username { get; set; }
|
||||
public int ID { get; set; } = 0;
|
||||
public string Code { get; set; } = string.Empty;
|
||||
private string _code = string.Empty;
|
||||
public string Code { get { return _code; } set
|
||||
{
|
||||
_code=value;
|
||||
if (value.Length == 4)
|
||||
ver().ConfigureAwait(true);
|
||||
|
||||
} }
|
||||
//-----------------
|
||||
private string code1, code2, code3, code4;
|
||||
// private string code1, code2, code3, code4;
|
||||
private ElementReference input1, input2, input3, input4;
|
||||
string validateStyleUser = "";
|
||||
private bool isButtonDisabled = true;
|
||||
@@ -161,35 +147,35 @@
|
||||
await OnMultipleOfThree.InvokeAsync();
|
||||
visible = false;
|
||||
}
|
||||
private async Task MoveNext(ChangeEventArgs e)
|
||||
{
|
||||
if (e.Value?.ToString()?.Length == 1)
|
||||
{
|
||||
if (input1.Context == null) return;
|
||||
// private async Task MoveNext(ChangeEventArgs e)
|
||||
// {
|
||||
// if (e.Value?.ToString()?.Length == 1)
|
||||
// {
|
||||
// if (input1.Context == null) return;
|
||||
|
||||
if (string.IsNullOrEmpty(code1))
|
||||
await input2.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code2))
|
||||
await input3.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code3))
|
||||
await input4.FocusAsync();
|
||||
else if (string.IsNullOrEmpty(code4))
|
||||
{
|
||||
Code = $"{code1}{code2}{code3}{code4}";
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task OnLastInput(ChangeEventArgs e)
|
||||
{
|
||||
code4 = e.Value?.ToString();
|
||||
// if (string.IsNullOrEmpty(code1))
|
||||
// await input2.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code2))
|
||||
// await input3.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code3))
|
||||
// await input4.FocusAsync();
|
||||
// else if (string.IsNullOrEmpty(code4))
|
||||
// {
|
||||
// Code = $"{code1}{code2}{code3}{code4}";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// private async Task OnLastInput(ChangeEventArgs e)
|
||||
// {
|
||||
// code4 = e.Value?.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(code4) && code4.Length == 1)
|
||||
{
|
||||
Code = $"{code1}{code2}{code3}{code4}";
|
||||
// if (!string.IsNullOrEmpty(code4) && code4.Length == 1)
|
||||
// {
|
||||
// Code = $"{code1}{code2}{code3}{code4}";
|
||||
|
||||
await ver();
|
||||
}
|
||||
}
|
||||
// await ver();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
<script>
|
||||
function formatPhoneNumber(input) {
|
||||
@@ -281,4 +267,22 @@
|
||||
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.cus-input {
|
||||
direction:ltr;
|
||||
display: block;
|
||||
margin: 2em auto;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: 6ch;
|
||||
background: repeating-linear-gradient(90deg, dimgrey 0, dimgrey 1ch, transparent 0, transparent 1.5ch) 0 100%/ 5.5ch 2px no-repeat;
|
||||
font: 5ch droid sans mono, consolas, monospace;
|
||||
letter-spacing: 0.5ch;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
color: dodgerblue;
|
||||
}
|
||||
|
||||
</style>
|
@@ -7,8 +7,8 @@ using HushianWebApp.Service;
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost:5089/api/") });
|
||||
string BaseAddress = builder.Configuration.GetSection("BaseAddress").Value;
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(BaseAddress) });
|
||||
builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();
|
||||
builder.Services.AddScoped<BaseController>();
|
||||
builder.Services.AddScoped<AuthService>();
|
||||
|
21
Presentation/HushianWebApp/default.conf
Normal file
21
Presentation/HushianWebApp/default.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
server {
|
||||
listen 5089;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg)$ {
|
||||
expires 6M;
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
|
||||
}
|
||||
}
|
12
Presentation/HushianWebApp/nginx.conf
Normal file
12
Presentation/HushianWebApp/nginx.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
worker_processes 1;
|
||||
|
||||
events { worker_connections 1024; }
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
}
|
10
Presentation/HushianWebApp/wwwroot/appsettings.json
Normal file
10
Presentation/HushianWebApp/wwwroot/appsettings.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"BaseAddress": "https://service.hushian.ir/api/",
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
@@ -34,7 +34,15 @@
|
||||
<span class="dismiss">🗙</span>
|
||||
</div>
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
<script>navigator.serviceWorker.register('service-worker.js');</script>
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/service-worker.js')
|
||||
.then(reg => console.log('Service Worker registered', reg))
|
||||
.catch(err => console.error('Service Worker registration failed:', err));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
||||
<!-- Add chart.js reference if chart components are used in your application. -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.0.1/chart.umd.js" integrity="sha512-gQhCDsnnnUfaRzD8k1L5llCCV6O9HN09zClIzzeJ8OJ9MpGmIlCxm+pdCkqTwqJ4JcjbojFr79rl2F1mzcoLMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "HushianWebApp",
|
||||
"short_name": "HushianWebApp",
|
||||
"name": "هوشیان",
|
||||
"short_name": "هوشیان",
|
||||
"id": "./",
|
||||
"start_url": "./",
|
||||
"display": "standalone",
|
||||
|
1
command.txt
Normal file
1
command.txt
Normal file
@@ -0,0 +1 @@
|
||||
docker compose up -d --build
|
53
docker-compose.yml
Normal file
53
docker-compose.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
aiass:
|
||||
build:
|
||||
context: ./Presentation/AIAss
|
||||
dockerfile: Dockerfile
|
||||
image: aiass:latest
|
||||
container_name: aiass
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Production
|
||||
- ASPNETCORE_URLS=http://+:5010
|
||||
ports:
|
||||
- "5011:5010"
|
||||
networks:
|
||||
- hushainnet
|
||||
- aiassnet
|
||||
|
||||
webapi:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Presentation/Hushian.WebApi/Dockerfile
|
||||
image: hushian.webapi:latest
|
||||
container_name: hushian-webapi
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Production
|
||||
ports:
|
||||
- "1011:8080"
|
||||
- "1012:8081"
|
||||
networks:
|
||||
- hushainnet
|
||||
|
||||
webapp:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Presentation/HushianWebApp/Dockerfile
|
||||
image: hushian.webapp:latest
|
||||
container_name: hushian-webapp
|
||||
ports:
|
||||
- "80:5165"
|
||||
depends_on:
|
||||
- webapi
|
||||
networks:
|
||||
- hushainnet
|
||||
|
||||
networks:
|
||||
hushainnet:
|
||||
name: hushainnet
|
||||
aiassnet:
|
||||
name: aiassnet
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user