Initial commit

This commit is contained in:
Chris Chen
2022-09-08 08:04:32 -07:00
commit 184db15773
4604 changed files with 503905 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "6.0.1",
"commands": [
"dotnet-ef"
]
}
}
}
+23
View File
@@ -0,0 +1,23 @@
===================04/06/2022 10:40=========================
{
"message": "Alice\t\t: http://localhost:4200/invitation/2XB12RB1RP13Y\r\nAnderson\t\t: http://localhost:4200/invitation/3BSLUS79C2GUX\r\nAndrew\t\t: http://localhost:4200/invitation/35VQACK1CYD8K\r\nAndy\t\t: http://localhost:4200/invitation/3E0E57AQAEUEJ\r\nBetty\t\t: http://localhost:4200/invitation/2X2G8LHAHHJ4B\r\nElaine\t\t: http://localhost:4200/invitation/36NQVXGY4JVRK\r\nElisa\t\t: http://localhost:4200/invitation/3D3R97E997E6J\r\nKlaire\t\t: http://localhost:4200/invitation/36FK8G13A3GMK\r\nLeya\t\t: http://localhost:4200/invitation/37H7CJM37TR4F\r\nLidia\t\t: http://localhost:4200/invitation/370N18EP897EU\r\nNick\t\t: http://localhost:4200/invitation/2T2UY7X6JKAVW\r\nVictoria\t\t: http://localhost:4200/invitation/2TL7VD9XHD82P\r\n孟懿\t\t: http://localhost:4200/invitation/31CJKVAVXNHWN\r\n蕾絲\t\t: http://localhost:4200/invitation/38BY2VDRGUM3T\r\n",
"to": "U97e9e579a41a5222e33bf68a3bf479a0"
}===================08/26/2022 19:11=========================
Message Type:Message
UserId:U4af4980629...
Reply Token:nHuyWiB7yP5Zw52FIkcQobQuGDXCTA
Message Type:Text
Message:@example Hello, world! (love)
===================08/26/2022 19:12=========================
Message Type:Message
UserId:U4af4980629...
Reply Token:nHuyWiB7yP5Zw52FIkcQobQuGDXCTA
Message Type:Text
Message:@example Hello, world! (love)
===================08/27/2022 18:03=========================
Message Type:Message
UserId:U4af4980629...
Reply Token:nHuyWiB7yP5Zw52FIkcQobQuGDXCTA
Message Type:Text
Message:@example Hello, world! (love)
+81
View File
@@ -0,0 +1,81 @@
{
"destination": "xxxxxxxxxx",
"events": [
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "message",
"mode": "active",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U4af4980629..."
},
"webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
"deliveryContext": {
"isRedelivery": false
},
"message": {
"id": "325708",
"type": "text",
"text": "@example Hello, world! (love)",
"emojis": [
{
"index": 23,
"length": 6,
"productId": "5ac1bfd5040ab15980c9b435",
"emojiId": "001"
}
],
"mention": {
"mentionees": [
{
"index": 0,
"length": 8,
"userId": "U850014438e..."
}
]
}
}
}
]
}{
"destination": "xxxxxxxxxx",
"events": [
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "message",
"mode": "active",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U4af4980629..."
},
"webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
"deliveryContext": {
"isRedelivery": false
},
"message": {
"id": "325708",
"type": "text",
"text": "@example Hello, world! (love)",
"emojis": [
{
"index": 23,
"length": 6,
"productId": "5ac1bfd5040ab15980c9b435",
"emojiId": "001"
}
],
"mention": {
"mentionees": [
{
"index": 0,
"length": 8,
"userId": "U850014438e..."
}
]
}
}
}
]
}"{\r\n \"destination\": \"xxxxxxxxxx\",\r\n \"events\": [\r\n {\r\n \"replyToken\": \"nHuyWiB7yP5Zw52FIkcQobQuGDXCTA\",\r\n \"type\": \"message\",\r\n \"mode\": \"active\",\r\n \"timestamp\": 1462629479859,\r\n \"source\": {\r\n \"type\": \"user\",\r\n \"userId\": \"U4af4980629...\"\r\n },\r\n \"webhookEventId\": \"01FZ74A0TDDPYRVKNK77XKC3ZR\",\r\n \"deliveryContext\": {\r\n \"isRedelivery\": false\r\n },\r\n \"message\": {\r\n \"id\": \"325708\",\r\n \"type\": \"text\",\r\n \"text\": \"@example Hello, world! (love)\",\r\n \"emojis\": [\r\n {\r\n \"index\": 23,\r\n \"length\": 6,\r\n \"productId\": \"5ac1bfd5040ab15980c9b435\",\r\n \"emojiId\": \"001\"\r\n }\r\n ],\r\n \"mention\": {\r\n \"mentionees\": [\r\n {\r\n \"index\": 0,\r\n \"length\": 8,\r\n \"userId\": \"U850014438e...\"\r\n }\r\n ]\r\n }\r\n }\r\n }\r\n ]\r\n}"
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

+142
View File
@@ -0,0 +1,142 @@
using Church.Net.Entity;
using Church.Net.Entity.Interface;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
public class ApiControllerBase<T> : ControllerBase where T : IEntity
{
protected readonly ICrudLogic<T> logic;
public ApiControllerBase(ICrudLogic<T> logic)
{
this.logic = logic;
}
[HttpGet]
public virtual async Task<IEnumerable<T>> GetAll()
{
return await Task.Run(() => { return logic.GetAll(); });
}
[HttpGet]
public virtual async Task<T> GetById(string id)
{
return await Task.Run(() => {
return logic.GetById(id);
});
}
[HttpPost]
public virtual async Task<int> Update(T entity)
{
return await Task.Run(() => {
return logic.Update(entity);
});
}
[HttpPost]
public virtual async Task<string> CreateOrUpdate([FromBody] T entity)
{
return await Task.Run(() =>
{
logic.CreateOrUpdate(entity, out string id);
return id;
});
}
[HttpPost]
public virtual async Task<IEnumerable<T>> CreateOrUpdateAll([FromBody] IEnumerable<T> entitys)
{
return await Task.Run(() =>
{
foreach (var item in entitys)
{
logic.CreateOrUpdate(item, out string id);
}
return entitys;
});
}
[HttpDelete("{id}")]
public virtual async Task<T> Delete(string id)
{
return await Task.Run(() => {
var entity = logic.GetById(id);
if (entity != null)
{
logic.Delete(entity);
}
return entity;
});
}
}
public class CombinedKeyApiControllerBase<T> : ControllerBase where T : ICombinedKeyEntity
{
protected readonly ICombinedKeyCrudLogic<T> logic;
public CombinedKeyApiControllerBase(ICombinedKeyCrudLogic<T> logic)
{
this.logic = logic;
}
[HttpGet]
public virtual async Task<IEnumerable<T>> GetAll()
{
return await Task.Run(() => { return logic.GetAll(); });
}
[HttpGet]
public virtual async Task<T> GetById(string[] ids)
{
return await Task.Run(() => {
return logic.GetById(ids);
});
}
[HttpPost]
public virtual async Task<int> Update(T entity)
{
return await Task.Run(() => {
return logic.Update(entity);
});
}
[HttpPost]
public virtual async Task<int> CreateOrUpdate([FromBody] T entity)
{
return await Task.Run(() =>
{
return logic.CreateOrUpdate(entity);
});
}
[HttpPost]
public virtual async Task<IEnumerable<T>> CreateOrUpdateAll([FromBody] IEnumerable<T> entitys)
{
return await Task.Run(() =>
{
foreach (var item in entitys)
{
logic.CreateOrUpdate(item);
}
return entitys;
});
}
[HttpDelete]
public virtual async Task<T> Delete(string[] ids)
{
return await Task.Run(() => {
var entity = logic.GetById(ids);
if (entity != null)
{
logic.Delete(entity);
}
return entity;
});
}
}
}
+119
View File
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Primitives;
using QRCoder;
using WebAPI.Logics.Interface;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class BestController : ApiControllerBase<HappinessBEST>
{
private readonly ICrudLogic<HappinessBEST> logic;
private readonly ICrudLogic<HappinessGroup> groupLogic;
private readonly ICrudLogic<HappinessWeek> weekLogic;
public BestController(
ICrudLogic<HappinessBEST> logic,
ICrudLogic<HappinessGroup> groupLogic,
ICrudLogic<HappinessWeek> weekLogic
) : base(logic)
{
this.logic = logic;
this.groupLogic = groupLogic;
this.weekLogic = weekLogic;
}
// GET api/<BestController>/5
public override Task<IEnumerable<HappinessBEST>> GetAll()
{
return base.GetAll();
}
public override Task<HappinessBEST> GetById(string id)
{
return Task<HappinessBEST>.Run(() => {
var best = logic.GetById(id);
best.HappinessGroup = groupLogic.GetById(best.GroupId);
best.HappinessGroup.Weeks = weekLogic.GetAll(w => w.GroupId == best.GroupId).OrderBy(w=>w.SEQ).ToList();
return best;
});
}
[HttpGet()]
public async Task<IActionResult> GetInvitationQRcode(string id)
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode($"http://happiness.tours/invitation/{id}", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(3);
string qrCodeImagePath = ServerUtils.MapPath("App_Data/ScaneMeQrCode.png");
var backgroundBitmap = (Bitmap)Bitmap.FromFile(qrCodeImagePath);
//string qrCodeImagePath = Environment.GetEnvironmentVariable("AppData");
//HttpContext.Current.Server.MapPath("~/App_Data/");
//var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/ScaneMeQrCode.png");
//System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/yourXmlFile.xml");
int positionLeft = 0;
int positionTop = 0;
var best = logic.GetById(id);
if (best != null)
{
using (var memoryStream = new MemoryStream())
{
//fileStream.CopyTo(memoryStream);
Bitmap image = Superimpose(best.Name, backgroundBitmap, qrCodeImage, 10, 32);
image.Scalling(75).Save(memoryStream, ImageFormat.Png);
byte[] byteImage = memoryStream.ToArray();
return File(byteImage, "image/png");
}
}
return this.NotFound();
}
[NonAction]
public Bitmap Superimpose(string bestName, Bitmap largeBmp, Bitmap smallBmp, int? x = null, int? y = null)
{
Graphics g = Graphics.FromImage(largeBmp);
g.CompositingMode = CompositingMode.SourceOver;
smallBmp.MakeTransparent();
int margin = 5;
if (!x.HasValue)
{
x = largeBmp.Width - smallBmp.Width - margin;
}
if (!y.HasValue)
{
y = largeBmp.Height - smallBmp.Height - margin;
}
var scale = 0.8;
var scaleWidth = (int)(smallBmp.Width * scale);
var scaleHeight = (int)(smallBmp.Height * scale);
g.DrawImage(smallBmp, new Rectangle(x.Value, y.Value, scaleWidth, scaleHeight));
g.DrawString(bestName, new Font(new FontFamily("Arial"), 12), new SolidBrush(System.Drawing.Color.Black), 10, 0);
return largeBmp;
}
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using WebAPI.Logics;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class CellGroupRoutineEventAttendeesController : CombinedKeyApiControllerBase<CellGroupRoutineEventAttendee>
{
public CellGroupRoutineEventAttendeesController(ICombinedKeyCrudLogic<CellGroupRoutineEventAttendee> logic) : base(logic)
{
}
}
}
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using Church.Net.DAL.EFCoreDBF;
using WebAPI.Logics;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class CellGroupRoutineEventsController : ApiControllerBase<CellGroupRoutineEvent>
{
private readonly CellGroupLogic logic;
private readonly ICombinedKeyCrudLogic<CellGroupRoutineEventPrayer> prayerLogic;
private readonly ICombinedKeyCrudLogic<CellGroupRoutineEventAttendee> dinnerLogic;
public CellGroupRoutineEventsController(
CellGroupLogic logic,
ICrudLogic<CellGroupRoutineEvent> crudLogic,
ICombinedKeyCrudLogic<CellGroupRoutineEventPrayer> prayerLogic,
ICombinedKeyCrudLogic<CellGroupRoutineEventAttendee> dinnerLogic
) : base(crudLogic)
{
this.logic = logic;
this.prayerLogic = prayerLogic;
this.dinnerLogic = dinnerLogic;
}
// GET: api/CellGroupRoutineEvents
[HttpGet]
public CellGroupRoutineEvent GetComingEvent()
{
return logic.GetComingEvent();
}
[HttpGet]
public CellGroupRoutineEvent GetLastEvent()
{
return logic.GetLastEvent();
}
[HttpPost]
public int CreateOrUpdatePrayer(CellGroupRoutineEventPrayer p)
{
return prayerLogic.CreateOrUpdate(p);
}
[HttpPost]
public int CreateOrUpdateAttendees(CellGroupRoutineEventAttendee p)
{
return dinnerLogic.CreateOrUpdate(p);
}
}
[Route("[controller]/[action]")]
[ApiController]
public class CellGroupRoutineEventPrayerController : CombinedKeyApiControllerBase<CellGroupRoutineEventPrayer>
{
public CellGroupRoutineEventPrayerController(ICombinedKeyCrudLogic<CellGroupRoutineEventPrayer> logic) : base(logic)
{
}
}
}
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using WebAPI.Logics;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class HappinessGroupController : ApiControllerBase<HappinessGroup>
{
private readonly HappinessGroupLogic logic;
public HappinessGroupController(
ICrudLogic<HappinessGroup> crudLogic,
HappinessGroupLogic logic
):base(crudLogic)
{
this.logic = logic;
}
[HttpGet]
public override async Task<IEnumerable<HappinessGroup>> GetAll()
{
return await Task.Run(() => { return logic.GetAllGroups(); });
}
[HttpPost]
public virtual async Task<int> UpdateBestWeek(HappinessWeek entity)
{
return await Task.Run(() => {
return logic.UpdateWeekInfo(entity);
});
}
}
}
+119
View File
@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Primitives;
using QRCoder;
using LineMessaging;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Text;
using WebAPI.Services;
using Jint.Native;
using WebAPI.Services.Interfaces;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebAPI.Controllers
{
//[Route("[controller]")]
[ApiController]
[Route("[controller]/[action]")]
public class LineMessageController : ControllerBase
{
private readonly ChurchNetContext dbContext;
private readonly LineAutoBotService lineAutoBotService;
private readonly ILoggingService loggingService;
public LineMessageController(ChurchNetContext dbContext,
LineAutoBotService lineAutoBotService,
ILoggingService loggingService
)
{
this.dbContext = dbContext;
this.lineAutoBotService = lineAutoBotService;
this.loggingService = loggingService;
}
//private ChurchNetContext dbContext = new ChurchNetContext();
//// GET: api/<BestController>
//[HttpGet]
//public IEnumerable<string> Get()
//{
// return new string[] { "value2222", "value4" };
//}
//// GET api/<BestController>/5
//[HttpGet("{id}")]
//public HappinessBEST Get(string id)
//{
// var best = dbContext.HappinessBESTs.Include(b => b.HappinessGroup).ThenInclude(b => b.Weeks).FirstOrDefault(b => b.BestId == id);
// best.HappinessGroup.Weeks = best.HappinessGroup.Weeks.OrderBy(w => w.SEQ).ToList();
// return best;
//}
// POST api/<BestController>
[HttpPost]
public async Task PostFromLine([FromBody] object jsonData)
{
//string txtPath = ServerUtils.MapPath("App_Data/LinePostRawLog.txt");
//System.IO.File.AppendAllText(txtPath, JsonConvert.SerializeObject(jsonData.ToString(), Formatting.Indented));
try
{
LineWebhookContent content = JsonConvert.DeserializeObject<LineWebhookContent>(jsonData.ToString());
await lineAutoBotService.AutoReply(content);
}
catch (Exception ex)
{
this.loggingService.Error(ex);
}
//Cac4ac5a8d7fc52daa444d71dc7c360a9 方舟小組 GroupID
//Ca20e3b65aa58e676815eb13c3222591a 方舟小組同工 GroupID
//var test = new LineMessaging.();
//var test = new LineMessagingClient("WFAyMvMEZ86cfMJIAzE+yklUZGpeS/jFYTeL9a9O35QR83oNMmwaUJfyEe48Kegadz0BArDdBoySxs479U1pwTHtlyH+Sm4jqlz8BwukX/Hsa4D1fX03Qn4zFu7TwPFKWFXnZbWq89Yg0iNzjpfTNwdB04t89/1O/w1cDnyilFU=");
//test.PushMessage(value.To, new LineTextMessage() { Text = value.Message });
}
[HttpPut("{id}")]
public async void PushTextMessage(string id, [FromBody] LineMessage value)
{
var test = new LineMessagingClient();
await test.PushMessage(id, new LineTextMessage() { Text = value.Message });
}
[HttpGet]
public Task PushCommandMessage(string groupToken,string command)
{
return lineAutoBotService.PushCommandMessage(EnumHelper.GetEnumValueFromDescription<LineGroup>(groupToken), "#"+ command);
}
}
public class LineMessage{
public string To { get; set; }
public string Message { get; set; }
}
}
+24
View File
@@ -0,0 +1,24 @@
using Church.Net.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class LogController : ApiControllerBase<LogInfo>
{
public LogController(ICrudLogic<LogInfo> logic) : base(logic)
{
}
[HttpPost]
public void PurgeBefore([FromBody] DateTime date)
{
logic.Delete(l => l.Time <= date.ToUniversalTime());
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using Church.Net.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class MemberController : ApiControllerBase<FamilyMember>
{
public MemberController(ICrudLogic<FamilyMember> logic) : base(logic)
{
}
}
}
@@ -0,0 +1,19 @@
using Church.Net.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class NewVisitorController : ApiControllerBase<NewVisitor>
{
public NewVisitorController(ICrudLogic<NewVisitor> logic) : base(logic)
{
}
}
}
@@ -0,0 +1,243 @@
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet.Common;
using NuGet.ProjectModel;
using System;
using System.IO;
using System.Linq;
using System.Net;
using WebAPI.Logics.Interface;
using WebAPI.ViewModel;
using static QRCoder.PayloadGenerator;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebAPI.Controllers
{
[ApiController]
public class PasswordLoginController : ControllerBase
{
private readonly ChurchNetContext churchNetContext;
private readonly ICrudLogic<FamilyMember> crudLogic;
private readonly ICombinedKeyCrudLogic<PastoralDomainMembers> relationLogic;
private readonly ICrudLogic<PastoralDomain> domainLogic;
// POST api/<PasswordLoginController>
public PasswordLoginController(
ChurchNetContext churchNetContext,
ICrudLogic<FamilyMember> crudLogic,
ICombinedKeyCrudLogic<PastoralDomainMembers> relationLogic,
ICrudLogic<PastoralDomain> domainLogic
)
{
this.churchNetContext = churchNetContext;
this.crudLogic = crudLogic;
this.relationLogic = relationLogic;
this.domainLogic = domainLogic;
}
[HttpPost]
[Route("auth/login")]
public LoginTokenViewModel Login([FromBody] RegisterViewModel value)
{
FamilyMember member = null;
if (string.IsNullOrEmpty(value.OAuthType))
{
value.Email = value.Email.Trim().ToLower();
member = crudLogic.First(f => f.Password == value.Password && f.Email.ToLower() == value.Email.ToLower());
//member = this.churchNetContext.FamilyMembers
// .Where(f => f.Password == value.Password && f.Email.ToLower() == value.Email.ToLower()).FirstOrDefault();
}
return ToLoginTokenViewModel(member);
}
[HttpPost]
[Route("auth/sign-up")]
[Route("auth/oauth-login")]
public LoginTokenViewModel SignUp([FromBody] RegisterViewModel value)
{
FamilyMember member = null;
string loginToken = "";
if (!string.IsNullOrEmpty(value.OAuthType))
{
if (value.OAuthType == "google")
{
if (false == this.GetGoogleLoginInfo(ref value)) return null;
}
var userId = this.churchNetContext.FamilyMemberOAuths
.Where(f => f.OAuthType == value.OAuthType && f.OAuthAccessToken == value.AccessToken)
.Select(f => f.FamilyMemberId).FirstOrDefault();
if (string.IsNullOrEmpty(userId))
{
value.Email = value.Email.Trim().ToLower();
member = this.churchNetContext.FamilyMembers
.Where(m => m.Email.ToLower() == value.Email)
.FirstOrDefault();
if (member == null)
{
member = new FamilyMember()
{
Id = StringHelper.Get33BaseGuid(),
FirstName = value.FirstName,
LastName = value.LastName,
Email = value.Email,
AvatarImage = value.AvatarImage,
Password = StringHelper.Get33BaseGuid()
};
churchNetContext.Add(member);
}
else
{
member.AvatarImage = value.AvatarImage;
member.FirstName = value.FirstName;
member.LastName = value.LastName;
churchNetContext.Update(member);
}
churchNetContext.Add(new FamilyMemberOAuth()
{
FamilyMemberId = member.Id,
OAuthType = value.OAuthType,
OAuthAccessToken = value.AccessToken
});
churchNetContext.SaveChanges();
}
else
{
member = this.churchNetContext.FamilyMembers
.Where(f => f.Id == userId).FirstOrDefault();
}
}
else
{
value.Email = value.Email.Trim().ToLower();
if (!this.churchNetContext.FamilyMembers
.Any(f => f.Email == value.Email))
{
member = new FamilyMember()
{
Id = StringHelper.Get33BaseGuid(),
FirstName = value.FirstName,
LastName = value.LastName,
Email = value.Email,
AvatarImage = value.AvatarImage,
Password = value.Password
};
churchNetContext.Add(member);
churchNetContext.SaveChanges();
}
}
return ToLoginTokenViewModel(member);
}
[HttpPost]
[Route("auth/request-pass")]
public void RequestPassword([FromBody] RegisterViewModel value)
{
}
[HttpPost]
[Route("auth/reset-pass")]
public void ResetPassword([FromBody] RegisterViewModel value)
{
}
[HttpPost]
[Route("auth/loginwithtoken")]
public LoginTokenViewModel LoginWithToken([FromBody] LoginTokenViewModel value)
{
var memberId = TokenHelper.GetUserIdFromToken(value.Token);
if (!string.IsNullOrWhiteSpace(memberId))
{
var member = crudLogic.First(f => f.Id == memberId);
//var member = this.churchNetContext.FamilyMembers
// .Where(f => f.Id == memberId).FirstOrDefault();
return ToLoginTokenViewModel(member);
}
return null;
}
private LoginTokenViewModel ToLoginTokenViewModel(FamilyMember member)
{
if (member != null)
{
DateTime expiredTime = DateTime.Now.AddDays(30);
string token = TokenHelper.GenerateToken(member.Id, expiredTime);
var cellGroupId = churchNetContext.PastoralDomainMembers.Where(d => d.FamilyMemberId == member.Id).Select(d => d.PastoralDomainId).FirstOrDefault();
PastoralDomain cellGroup;
if (string.IsNullOrEmpty(cellGroupId))
{
cellGroup = churchNetContext.PastoralDomains.First();
relationLogic.Create(new PastoralDomainMembers(cellGroup.Id, member.Id));
}
else
{
cellGroup = churchNetContext.PastoralDomains.Where(g=>g.Id== cellGroupId).First();
}
return new LoginTokenViewModel()
{
MemberId = member.Id,
FirstName = member.FirstName,
LastName = member.LastName,
AvatarImage = member.AvatarImage,
Email = member.Email,
Token = token,
TokenExpireTime = expiredTime,
Role = member.Role,
CellGroup= cellGroup
};
}
return null;
}
private bool GetGoogleLoginInfo(ref RegisterViewModel model)
{
string uri = $"https://www.googleapis.com/oauth2/v2/userinfo?access_token={model.AccessToken}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
var obj = JsonConvert.DeserializeObject<JObject>(result);
if (obj.TryGetValue("email", out JToken value))
{
model.Email = ((string)value).ToLower().Trim();
model.FirstName = obj.GetValue<string>("given_name");
model.LastName = obj.GetValue<string>("family_name");
model.AvatarImage = obj.GetValue<string>("picture");
model.AccessToken = obj.GetValue<string>("id");
return true;
}
}
}
catch (Exception)
{
}
return false;
}
}
}
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Church.Net.DAL.EF;
using Church.Net.Entity;
using WebAPI.Logics;
using WebAPI.Logics.Interface;
namespace WebAPI.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class PastoralDomainController : ApiControllerBase<PastoralDomain>
{
public PastoralDomainController(ICrudLogic<PastoralDomain> logic) : base(logic)
{
}
}
[Route("[controller]/[action]")]
[ApiController]
public class DomainMemberShipController : CombinedKeyApiControllerBase<PastoralDomainMembers>
{
public DomainMemberShipController(ICombinedKeyCrudLogic<PastoralDomainMembers> logic) : base(logic)
{
}
[HttpPost]
public int AssignCellGroups(IEnumerable<PastoralDomainMembers> relations)
{
logic.Delete(r => relations.Any(rr => (r.FamilyMemberId == rr.FamilyMemberId)));
foreach (var relation in relations)
{
//logic.Delete(r => r.FamilyMemberId == relation.FamilyMemberId);
logic.Create(relation);
}
return 1;
}
}
}
+198
View File
@@ -0,0 +1,198 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Church.Net.Utility;
using LineMessaging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using WebAPI.Logics;
using WebAPI.Services;
using static System.Net.Mime.MediaTypeNames;
using WebAPI.Services.Interfaces;
namespace WebAPI.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class PingController : ControllerBase
{
private readonly IEnumerable<IAutoReplyCommand> autoReplyCommands;
public PingController(VideoDownloadLogic videoDownloadLogic,
IEnumerable<IAutoReplyCommand> autoReplyCommands)
{
VideoDownloadLogic = videoDownloadLogic;
this.autoReplyCommands = autoReplyCommands;
}
public VideoDownloadLogic VideoDownloadLogic { get; }
[HttpGet]
public List<Controller> GetEndpoints()
{
//using (var fileStream = new FileStream(ServerUtils.MapPath("Church/Test.mp4"), FileMode.Create))
//{
//}
//await Task.Run(() => {
//this.VideoDownloadLogic.Download(@"https://www.youtube.com/watch?v=nJBLeMrhu9w", @"\\ArkNAS\Church\Test.mp4");
//});
Console.WriteLine($"Self GetEndpoints: {DateTime.Now}");
string @namespace = this.GetType().Namespace;
Type ApiControllerType = typeof(ControllerBase);
IEnumerable<Type> controllers = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => t.Namespace == @namespace && ApiControllerType.IsAssignableFrom(t))
;
HashSet<string> baseMethods = new HashSet<string>(ApiControllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Select(mi => mi.Name));
List<Controller> _controllers = new List<Controller>();
foreach (var controller in controllers)
{
Controller _controller = new Controller { Name = controller.Name.Replace("Controller", "") };
foreach (var methodInfo in controller.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (baseMethods.Contains(methodInfo.Name)) continue;
try
{
bool isGet = methodInfo.GetCustomAttributes(typeof(HttpGetAttribute), false).Length > 0;
bool isPost = methodInfo.GetCustomAttributes(typeof(HttpPostAttribute), false).Length > 0;
bool isDelete = methodInfo.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Length > 0;
if(isGet|| isPost|| isDelete)
{
Endpoint _endpoint = new Endpoint
{
Name = methodInfo.Name,
Method = isGet ? "GET" : (isPost ? "POST" : (isDelete ? "DELETE" : "UNKNOWN")),
Inputs = methodInfo.GetParameters().Select(m=>new Input() { Name=m.Name}).ToArray(),
ReturnType = methodInfo.ReturnType,
//MethodInfo = methodInfo,
};
//_endpoint.HasDocString = HasDocString(_endpoint);
_controller.Endpoints.Add(_endpoint);
}
}
catch (Exception ex)
{
}
}
_controllers.Add(_controller);
}
return _controllers;
}
[HttpGet]
public async void TestMessage()
{
//\\ArkNAS\Church\WorshipVideo
//this.VideoDownloadLogic.Download(@"https://www.youtube.com/watch?v=K2bdSYim7uI", @"\\ArkNAS\home\Test.mp4");
var test = new LineMessagingClient();
string text = "$$$$Menu Item";
var textMessage = new LineTextMessage() { Text = text, Emojis = new List<Emoji>() };
textMessage.AddEmoji("$$", "5ac1bfd5040ab15980c9b435", "002");
var templateMessage = new LineTemplateMessage<ButtonTemplateObject>();
var addPrayerBtn = new UriAction()
{
Uri = "https://happiness.tours/CellGroup/prayer?openExternalBrowser=1",
Label = "Prayer"
};
templateMessage.AltText= "代禱事項";
templateMessage.Template.DefaultAction = addPrayerBtn;
templateMessage.Template.ThumbnailImageUrl = "https://dailyverses.net/images/tc/cuv/matthew-21-22-3.jpg";
templateMessage.Template.Title = "代禱事項";
templateMessage.Template.Text = "Chris" + Environment.NewLine + "Testwerewiorjowerjiowejiro, erjaiworjweiorjioawereaw";
templateMessage.Template.Actions = new List<ILineAction>();
templateMessage.Template.Actions.Add(addPrayerBtn);
await test.PushMessage(EnumHelper.EnumToDescriptionString(LineGroup.Chris), textMessage);
}
[HttpGet]
public async void TestAutoReply(string command)
{
//\\ArkNAS\Church\WorshipVideo
//this.VideoDownloadLogic.Download(@"https://www.youtube.com/watch?v=K2bdSYim7uI", @"\\ArkNAS\home\Test.mp4");
if (!String.IsNullOrWhiteSpace(command))
{
string text = command;
var group = LineGroup.Chris;
var autoReply = autoReplyCommands.Where(ar => ar.SupportGroups.Contains(group) && ar.Commands.Contains(text)).FirstOrDefault();
if (autoReply != null)
{
if (autoReply.LineMessage != null)
{
ReplyLineMessage(group.EnumToDescriptionString(), autoReply.LineMessage);
}
else
{
// ReplyTextMessage(replyToken, autoReply.ReplyMessage);
}
return;
}
};
}
public class Controller
{
public string Name { get; set; }
public List<Endpoint> Endpoints { get; set; } = new List<Endpoint>();
}
public class Endpoint
{
public string Name { get; set; }
public string Method { get; set; }
public Input[] Inputs { get; set; }
public Type ReturnType { get; set; }
public MethodInfo MethodInfo { get; set; }
public bool HasDocString { get; set; }
}
public partial class Input
{
public string Name { get; set; }
public long Position { get; set; }
}
private async void ReplyLineMessage(string replyToken, IEnumerable<ILineMessage> lineMessages)
{
var test = new LineMessagingClient();
var replyMessage = new LinePushMessage() { To = replyToken };
replyMessage.Messages = lineMessages;
await test.PushMessage(replyMessage);
}
}
}
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace WebAPI.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
+56
View File
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using WebAPI.Hubs;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebAPI.Controllers
{
[Route("[controller]")]
[ApiController]
public class WhoIsSpyController : ControllerBase
{
private readonly IHubContext<WhoIsSpyHub> hubContext;
public WhoIsSpyController(IHubContext<WhoIsSpyHub> hubContext)
{
this.hubContext = hubContext;
}
// GET: api/<WhoIsSpyController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<WhoIsSpyController>/5
[HttpGet("{id}")]
public string Get(string id)
{
return "value";
}
// POST api/<WhoIsSpyController>
[HttpPost]
public void Post([FromBody] string value)
{
hubContext.Clients.All.SendAsync("");
}
// PUT api/<WhoIsSpyController>/5
[HttpPut("{id}")]
public void Put(string id, [FromBody] string value)
{
}
// DELETE api/<WhoIsSpyController>/5
[HttpDelete("{id}")]
public void Delete(string id)
{
}
}
}
+25
View File
@@ -0,0 +1,25 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["WebAPI/WebAPI.csproj", "WebAPI/"]
COPY ["Church.Net.DAL.EFCoreDBF/Church.Net.DAL.EFCoreDBF.csproj", "Church.Net.DAL.EFCoreDBF/"]
COPY ["Church.Net.Entity2/Church.Net.Entity2.csproj", "Church.Net.Entity2/"]
COPY ["Church.Net.Utility/Church.Net.Utility.csproj", "Church.Net.Utility/"]
RUN dotnet restore "WebAPI/WebAPI.csproj"
COPY . .
WORKDIR "/src/WebAPI"
RUN dotnet build "WebAPI.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WebAPI.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebAPI.dll"]
+35
View File
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPI.Models.IceBreak;
namespace WebAPI
{
public class GameRoomLogic
{
public List<GameRoom> GameRooms { get; set; }
public bool UserJoinGameRoom(string id,string userName,string gameRoomId)
{
if (GameRooms.Any(g => g.Id == gameRoomId))
{
//Make sure user not exist in other room
UserLeave(id);
}
return false;
}
public void UserLeave(string id)
{
foreach (var room in GameRooms)
{
if (room.Players.Any(p => p.Id == id))
{
room.Players.Remove(room.Players.FirstOrDefault(p => p.Id == id));
break;
}
}
}
}
}
+42
View File
@@ -0,0 +1,42 @@
using System.Threading.Tasks;
using System.Threading;
using System.Web.Http.Filters;
using System;
using WebAPI.Services.Interfaces;
namespace WebAPI
{
public class HandleExceptionFilter : IExceptionFilter
{
private ILoggingService _loggingService;
public HandleExceptionFilter(ILoggingService loggingService)
{
_loggingService = loggingService;
}
public bool AllowMultiple => throw new NotImplementedException();
public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
return Task.Run(new Action(() =>
{
if (actionExecutedContext == null)
{
throw new ArgumentNullException("filterContext");
}
Exception exception = actionExecutedContext.Exception;
if (actionExecutedContext.Response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
// Log exception
//_loggingService.Error(exception);
int errorTrackNo = _loggingService.Error(exception, actionExecutedContext.Request.RequestUri.AbsoluteUri);
//actionExecutedContext.Exception = new HttpException($"Error Track No:{errorTrackNo}");
}
}));
}
}
}
+62
View File
@@ -0,0 +1,62 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace WebAPI.Hubs
{
public enum AvalonStage
{
JoinGame,
NewGame,
PickTeammate,
TeamVote,
TeamVoteResult,
QuestVote,
QuestVoteResult
}
public class AvalonHub : Hub
{
private readonly GameRoomLogic gameRoomLogic;
public AvalonHub(GameRoomLogic gameRoomLogic)
{
this.gameRoomLogic = gameRoomLogic;
}
public async Task JoinGame(string connectionId, string username)
{
await Clients.All.SendAsync("JoinGame", connectionId, username);
}
public async Task RefreshStage(AvalonStage stage)
{
await Clients.All.SendAsync("RefreshStage", stage);
}
public async Task Broadcast(string connectionId,string action, string jsonString)
{
//await Clients.AllExcept(connectionId).SendAsync("Broadcast", action, jsonString);
await Clients.Others.SendAsync("Broadcast", action, jsonString);
}
public override Task OnConnectedAsync()
{
var username = Context.GetHttpContext().Request.Query["username"];
var userId = Context.GetHttpContext().Request.Query["userId"];
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var userId = Context.GetHttpContext().Request.Query["userId"];
Clients.All.SendAsync("Broadcast", "LeaveGame", Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
}
}
+73
View File
@@ -0,0 +1,73 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPI.Models.IceBreak;
namespace WebAPI.Hubs
{
public class BaseHub : Hub
{
//private const string GAME_ROOM_KEY = "GameRooms";
//private const string GAME_ROOM_ID_KEY = "GameRoomId";
//private const string PLAYER_INFO_KEY = "GameRoomId";
//private readonly IMemoryCache memoryCache;
//public List<GameRoom> GameRooms
//{
// get
// {
// if (memoryCache.Get<List<GameRoom>>(GAME_ROOM_KEY) == null)
// {
// memoryCache.Set(GAME_ROOM_KEY, new List<GameRoom>());
// }
// return memoryCache.Get<List<GameRoom>>(GAME_ROOM_KEY);
// }
// set => memoryCache.Set(GAME_ROOM_KEY, value);
//}
//public string GameRoomId
//{
// get
// {
// if (memoryCache.Get<string>(GAME_ROOM_ID_KEY) == null)
// {
// memoryCache.Set(GAME_ROOM_ID_KEY, string.Empty);
// }
// return memoryCache.Get<string>(GAME_ROOM_ID_KEY);
// }
// set => memoryCache.Set(GAME_ROOM_ID_KEY, value);
//}
//public GamePlayer PlayerInfo
//{
// get
// {
// //this.Context.User
// var name = HttpContext.Session.GetString("12");
// if (HttpContext.Session.GetString("PlayerInfo") == null)
// {
// HttpContext.Session["PlayerInfo"] = new GamePlayer();
// }
// return (GamePlayer)HttpContext.Session["PlayerInfo"];
// }
// set => HttpContext.Session["PlayerInfo"] = value;
//}
//public BaseHub(IMemoryCache memoryCache)
//{
// this.memoryCache = memoryCache;
//}
}
}
+37
View File
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI.Hubs
{
public class WhoIsSpyHub:Hub
{
private readonly GameRoomLogic gameRoomLogic;
public WhoIsSpyHub(GameRoomLogic gameRoomLogic)
{
this.gameRoomLogic = gameRoomLogic;
}
public async Task JoinGame(string clientId,string username)
{
await Clients.All.SendAsync("JoinGame", clientId, username);
}
public override Task OnConnectedAsync()
{
var username = Context.GetHttpContext().Request.Query["username"];
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
var username = Context.GetHttpContext().Request.Query["username"];
return base.OnDisconnectedAsync(exception);
}
}
}
+61
View File
@@ -0,0 +1,61 @@
using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System;
using WebAPI.Logics.Core;
using WebAPI.Logics.Interface;
using System.Linq;
namespace WebAPI.Logics
{
public class CellGroupLogic
{
private readonly ICrudDAL<CellGroupRoutineEvent> eventCrudDAL;
private readonly ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL;
private readonly ICrudDAL<FamilyMember> memberCrudDAL;
public CellGroupLogic(
ICrudDAL<CellGroupRoutineEvent> eventCrudDAL,
ICombinedKeyCrudDAL<CellGroupRoutineEventAttendee> attendeeCrudDAL,
ICrudDAL<FamilyMember> memberCrudDAL
)
{
this.eventCrudDAL = eventCrudDAL;
this.attendeeCrudDAL = attendeeCrudDAL;
this.memberCrudDAL = memberCrudDAL;
}
public CellGroupRoutineEvent GetComingEvent()
{
var _event = eventCrudDAL.GetDbSet().Where(e => e.Time >= DateTime.UtcNow)
.Include(e => e.Attendees).Include(e => e.Prayers).FirstOrDefault();
if (_event == null)
{
_event = new CellGroupRoutineEvent()
{
Id = Format.Get33BaseGuid(),
Time = DateTimeHelper.GetNextWeekday(DateTime.Today, DayOfWeek.Friday).AddHours(19).AddMinutes(30),
Address = "1881 Forest Dr., Azusa, CA 91702",
Attendees = new List<CellGroupRoutineEventAttendee>()
};
eventCrudDAL.Create(_event);
}
return _event;
}
public CellGroupRoutineEvent GetLastEvent()
{
var _event = eventCrudDAL.GetDbSet().OrderByDescending(e=>e.Time)
.Include(e => e.Attendees).Include(e => e.Prayers).FirstOrDefault();
return _event;
}
public string GetMemberFirstNameById(string memberId)
{
return memberCrudDAL.GetById(memberId)?.FirstName;
}
}
}
@@ -0,0 +1,97 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Transactions;
using System;
using Church.Net.DAL.EF;
using System.Linq;
using Church.Net.Utility;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
using Church.Net.DAL.EFCoreDBF;
namespace WebAPI.Logics.Core
{
public class CombinedKeyLogicBase<T> : ICombinedKeyCrudLogic<T> where T : class, Church.Net.Entity.Interface.ICombinedKeyEntity, new()
{
private readonly LogicService logicService;
private readonly ICombinedKeyCrudDAL<T> crudDAL;
public CombinedKeyLogicBase(
LogicService logicService,
ICombinedKeyCrudDAL<T> crudDAL
)
{
this.logicService = logicService;
this.crudDAL = crudDAL;
}
public virtual bool CheckExist(T obj)
{
return this.crudDAL.CheckExist(obj);
}
public virtual int Create(T entity)
{
return this.crudDAL.Create(entity);
}
public virtual Task<int> CreateAsync(T entity)
{
return this.crudDAL.CreateAsync(entity);
}
public void CreateDone(T entity)
{
}
public int CreateOrUpdate(T entity)
{
var result= this.crudDAL.CreateOrUpdate(entity);
return result;
}
public int Delete(T obj)
{
return this.crudDAL.Delete(obj);
}
public int Delete(IEnumerable<string> combinedKeyIds)
{
return this.crudDAL.Delete(combinedKeyIds);
}
public int Delete(Func<T, bool> filter)
{
return this.crudDAL.Delete(filter);
}
public T First(Func<T, bool> filter = null)
{
return this.crudDAL.First(filter);
}
public IEnumerable<T> GetAll(Func<T, bool> filter = null)
{
return this.crudDAL.GetAll(filter);
}
public T GetById(IEnumerable<string> combinedKeyIds)
{
return this.crudDAL.GetById(combinedKeyIds);
}
public int Update(T entity)
{
return this.crudDAL.Update(entity);
}
public void UpdateDone(T entity)
{
}
public int UpdateRange(IEnumerable<T> entities)
{
return this.crudDAL.UpdateRange(entities);
}
}
}
+102
View File
@@ -0,0 +1,102 @@
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Transactions;
using System;
using Church.Net.DAL.EF;
using System.Linq;
using Church.Net.Utility;
using System.Threading.Tasks;
using WebAPI.Logics.Interface;
using Church.Net.DAL.EFCoreDBF;
namespace WebAPI.Logics.Core
{
public class LogicBase<T> : ICrudLogic<T> where T : class, Church.Net.Entity.Interface.IEntity, new()
{
private readonly LogicService logicService;
private readonly ICrudDAL<T> crudDAL;
public LogicBase(
LogicService logicService,
ICrudDAL<T> crudDAL
)
{
this.logicService = logicService;
this.crudDAL = crudDAL;
}
public virtual bool CheckExist(T obj)
{
return this.crudDAL.CheckExist(obj);
}
public virtual int Create(T entity)
{
return this.crudDAL.Create(entity);
}
public virtual Task<int> CreateAsync(T entity)
{
return this.crudDAL.CreateAsync(entity);
}
public void CreateDone(T entity)
{
}
public int CreateOrUpdate(T entity, out string id)
{
var result= this.crudDAL.CreateOrUpdate(entity, out string _id);
id = _id;
return result;
}
public string CreateReturnId(T entity)
{
return this.crudDAL.CreateReturnId(entity);
}
public int Delete(T obj)
{
return this.crudDAL.Delete(obj);
}
public int Delete(Func<T, bool> filter = null)
{
return this.crudDAL.Delete(filter);
}
public T First(Func<T, bool> filter = null)
{
return this.crudDAL.First(filter);
}
public IEnumerable<T> GetAll(Func<T, bool> filter = null)
{
return this.crudDAL.GetAll(filter);
}
public IEnumerable<T> GetAllById(IEnumerable<string> Ids)
{
return this.crudDAL.GetAllById(Ids);
}
public T GetById(string Id)
{
return this.crudDAL.GetById(Id);
}
public int Update(T entity)
{
return this.crudDAL.Update(entity);
}
public void UpdateDone(T entity)
{
}
public int UpdateRange(IEnumerable<T> entities)
{
return this.crudDAL.UpdateRange(entities);
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using Church.Net.DAL.EF;
namespace WebAPI.Logics.Core
{
public class LogicService
{
public LogicService(
ChurchNetContext dbContext
)
{
DbContext = dbContext;
}
public ChurchNetContext DbContext { get; }
}
}
+85
View File
@@ -0,0 +1,85 @@
using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity;
using Church.Net.Utility;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
namespace WebAPI.Logics
{
public class HappinessGroupLogic
{
private readonly ICrudDAL<HappinessGroup> groupCrudDAL;
private readonly ICrudDAL<HappinessWeek> weekCrudDAL;
string[] weekTitles = new string[] { "真幸福", "真相大白", "萬世巨星", "幸福連線", "當上帝來敲門", "十字架的勝利", "釋放與自由", "幸福的教會" };
public HappinessGroupLogic(
ICrudDAL<HappinessGroup> groupCrudDAL,
ICrudDAL<HappinessWeek> weekCrudDAL
)
{
this.groupCrudDAL = groupCrudDAL;
this.weekCrudDAL = weekCrudDAL;
}
public List<HappinessGroup> GetAllGroups()
{
var list = groupCrudDAL.GetDbSet().Include(g => g.BestList).Include(g => g.Weeks).ToList();
foreach (var group in list)
{
if (group.Weeks == null || group.Weeks.Count() == 0)
{
group.Weeks = new List<HappinessWeek>();
for (int i = 1; i <= 8; i++)
{
var week = GetHappinessWeek(group, i);
group.Weeks.Add(week);
weekCrudDAL.CreateOrUpdate(week, out string weekId);
}
}
group.Weeks = group.Weeks.OrderBy(w => w.SEQ).ToList();
}
return list;
}
public int UpdateWeekInfo(HappinessWeek value)
{
if (value.UpdateRestWeekDate)
{
var list = weekCrudDAL.GetAll(week => week.SEQ >= value.SEQ && week.GroupId == value.GroupId).OrderBy(w => w.SEQ).ToList();
var tempDate = new DateTime(value.Date.Year, value.Date.Month, value.Date.Day, value.Date.Hour, value.Date.Minute, value.Date.Second);
int count = 0;
foreach (var week in list)
{
week.Date = tempDate.AddDays(count * 7);
week.Address = value.Address;
week.CityAndZipCode = value.CityAndZipCode;
week.InvitationText = value.InvitationText;
count++;
}
return weekCrudDAL.UpdateRange(list);
}
return weekCrudDAL.CreateOrUpdate(value, out string id);
}
private HappinessWeek GetHappinessWeek(HappinessGroup group, int weekNo)
{
return new HappinessWeek()
{
GroupId = group.Id,
Address = group.Address,
CityAndZipCode = group.CityAndZipCode,
Date = group.BeginTime.AddDays(7 * (weekNo - 1)),
SEQ = weekNo
};
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using Church.Net.DAL.EF;
using Church.Net.Utility;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
namespace WebAPI.Logics.Interface
{
public interface ICrudLogic<T>
{
T First(Func<T, bool> filter = null);
T GetById(string Id);
IEnumerable<T> GetAll(Func<T, bool> filter = null);
IEnumerable<T> GetAllById(IEnumerable<string> Ids);
int Create(T entity);
Task<int> CreateAsync(T entity);
string CreateReturnId(T entity);
int CreateOrUpdate(T entity, out string id);
int Update(T entity);
void CreateDone(T entity);
void UpdateDone(T entity);
int UpdateRange(IEnumerable<T> entities);
int Delete(T obj);
int Delete(Func<T, bool> filter = null);
bool CheckExist(T obj);
}
public interface ICombinedKeyCrudLogic<T>
{
T First(Func<T, bool> filter = null);
T GetById(IEnumerable<string> combinedKeyIds);
IEnumerable<T> GetAll(Func<T, bool> filter = null);
int Create(T entity);
Task<int> CreateAsync(T entity);
int CreateOrUpdate(T entity);
int Update(T entity);
void CreateDone(T entity);
void UpdateDone(T entity);
int UpdateRange(IEnumerable<T> entities);
int Delete(T obj);
int Delete(IEnumerable<string> combinedKeyIds);
int Delete(Func<T, bool> filter);
bool CheckExist(T obj);
}
}
+62
View File
@@ -0,0 +1,62 @@
using DotNetTools.SharpGrabber;
using DotNetTools.SharpGrabber.Grabbed;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace WebAPI.Logics
{
public class VideoDownloadLogic
{
public async void Download(string youtubeUrl, string filePath)
{
var grabber = GrabberBuilder.New()
.UseDefaultServices()
.AddYouTube()
.Build();
var result = await grabber.GrabAsync(new Uri(youtubeUrl));
var info = result.Resource<GrabbedInfo>();
Console.WriteLine("Time Length: {0}", info.Length);
var videos = result.Resources<GrabbedMedia>();
foreach (var video in videos)
{
if ("mp4" == video.Format.Extension)
{
if (video.Resolution == "1080p")
{
await DownloadMedia(video, result, $"{filePath}/{video.Title}.mp4");
break;
}
}
}
}
public async void DownloadWorship(string youtubeUrl)
{
await Task.Run(() =>
{
Download(youtubeUrl, ServerUtils.MapPath("WorshipVideos"));//ServerUtils.MapPath("Church/Test.mp4")
});
}
private static async Task<string> DownloadMedia(GrabbedMedia media, IGrabResult grabResult, string path)
{
HttpClient Client = new HttpClient();
Client.Timeout = TimeSpan.FromMinutes(30);
Console.WriteLine("Downloading {0}...", media.Title ?? media.FormatTitle ?? media.Resolution);
using var response = await Client.GetAsync(media.ResourceUri);
response.EnsureSuccessStatusCode();
using var downloadStream = await response.Content.ReadAsStreamAsync();
using var resourceStream = await grabResult.WrapStreamAsync(downloadStream);
using var fileStream = new FileStream(path, FileMode.Create);
await resourceStream.CopyToAsync(fileStream);
return path;
}
}
}
+133
View File
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI.Models.IceBreak
{
public enum GameType
{
WereWolf,
WhoIsSpy
}
public class GameRoom
{
GameType Type { get; set; }
public string Id { get; set; }
private List<WhoIsSpyPlayer> _players;
public int TotalPlayer => Players.Count;
public List<WhoIsSpyPlayer> Players
{
get
{
if (_players == null)
{
_players = new List<WhoIsSpyPlayer>();
}
return _players;
}
set => _players = value;
}
}
public class GamePlayer
{
public string Id { get; set; }
[Required]
public string Name { get; set; }
public string TempGameRoomId { get; set; }
}
public enum WhoIsSpyProcess
{
WaitForPlayer,
Started,
Votting,
DisplayResult,
End,
Closed
}
public class WhoIsSpyGameRoom : GameRoom
{
public WhoIsSpyGameRoom()
{
PlayedAnswerId = new List<int>();
}
public int Question { get; set; }
[Required]
public int SpyAmount { get; set; }
[Required]
public int EmptyAmount { get; set; }
public int StartIndex { get; set; }
public WhoIsSpyAnswer Answer { get; set; }
public WhoIsSpyAnswer SpysAnswer { get; set; }
public WhoIsSpyProcess Status { get; set; }
public List<int> PlayedAnswerId { get; set; }
public int VoteAmount { get; set; }
}
public class WhoIsSpyPlayer
{
public string Id { get; set; }
public string RoomId { get; set; }
public int Seed { get; set; }
public string Name { get; set; }
public WhoIsSpyAnswer Answer { get; set; }
public bool IsSpy { get; set; }
public bool IsDead { get; set; }
public WhoIsSpyProcess GameStatus { get; set; }
public List<string> VoteTo { get; set; }
public int ReceviedVotes { get; set; }
public int VoteAmount { get; set; }
public List<WhoIsSpyVoteOption> VoteOption { get; set; }
}
public class WhoIsSpyVoteOption
{
public WhoIsSpyVoteOption(string id, string name)
{
Id = id;
Name = name;
}
public string Id { get; set; }
public string Name { get; set; }
}
public class WhoIsSpyAnswer
{
public WhoIsSpyAnswer()
{
}
public WhoIsSpyAnswer(string answerCht, string answerChs, string answerEn, string answerImage)
{
AnswerCht = answerCht;
AnswerChs = answerChs;
AnswerEn = answerEn;
AnswerImage = answerImage;
}
public string AnswerCht { get; set; }
public string AnswerChs { get; set; }
public string AnswerEn { get; set; }
public string AnswerImage { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace WebAPI
{
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>();
});
}
}
+39
View File
@@ -0,0 +1,39 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:12071",
"sslPort": 44374
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebAPI": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/weatherforecast",
"publishAllPorts": true,
"useSSL": true,
"httpPort": 49154,
"sslPort": 49155
}
}
}
+19
View File
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI
{
public class ServerUtils
{
public static string MapPath(string path)
{
return Path.Combine(
(string)AppDomain.CurrentDomain.GetData("ContentRootPath"),
path);
}
}
}
@@ -0,0 +1,241 @@
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using LineMessaging;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebAPI.Logics;
using WebAPI.Services.Interfaces;
namespace WebAPI.Services.AutoReplyCommands
{
public class ArArkCellGroupDinner : IAutoReplyCommand
{
public ArArkCellGroupDinner(ChurchNetContext context,
CellGroupLogic logic)
{
this._context = context;
this.logic = logic;
}
private static readonly string[] COMMANDS = { "晚餐", "dinner" };
private static readonly LineGroup[] GROUPS = {
LineGroup.Ark,
LineGroup.Chris,
};
private readonly ChurchNetContext _context;
private readonly CellGroupLogic logic;
public string Description => "顯示方舟小組聚會晚餐";
public IEnumerable<string> Commands => COMMANDS;
public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<string> ReplyMessage
{
get
{
StringBuilder sb = new StringBuilder();
StringBuilder comments = new StringBuilder();
sb.AppendLine("又到了令人期待的小組日~~~");
var _event = _context.CellGroupRoutineEvents.Where(e => e.Time >= DateTime.Today)
.Include(e => e.Attendees).FirstOrDefault();
if (_event == null)
{
_event = new CellGroupRoutineEvent()
{
Id = Format.Get33BaseGuid(),
Time = DateTimeHelper.GetNextWeekday(DateTime.Today, DayOfWeek.Friday).AddHours(19).AddMinutes(30),
Address = "1881 Forest Dr., Azusa, CA 91702",
Attendees = new List<CellGroupRoutineEventAttendee>()
};
_context.Add(_event);
_context.SaveChanges();
}
sb.AppendLine($"{_event.Time.ToString("MM/dd HH:mm tt")} 開飯~");
sb.AppendLine("======= 晚宴清單 =======");
foreach (var a in _event.Attendees)
{
sb.AppendLine($"{a.Name} - {string.Join(", ", a.PotluckItem.Split('|'))}");
if (!string.IsNullOrWhiteSpace(a.Comment))
{
comments.AppendLine($"{a.Name}:{a.Comment}");
}
}
if (comments.Length > 0)
{
sb.AppendLine("========= 備註 =========");
sb.Append(comments.ToString());
}
return new string[] { sb.ToString() };
}
}
public IEnumerable<ILineMessage> LineMessage
{
get
{
var random = new Random();
List<ILineMessage> list = new List<ILineMessage>();
var _event = logic.GetComingEvent();
string title = "小組晚宴,吃飯皇帝大";
string imageUrl = "https://happiness.tours/assets/images/dinner.jpg";
var flexMessage = new LineFlexMessage();
flexMessage.AltText = title;
#region Header
var headerContent = flexMessage.Contents.InitHeader();
headerContent.Add(
new LineFlexText(title)
{
Size = FlexObjectSize.lg,
Weight = FlexObjectTextWeidht.Bold,
Align = "center"
});
#endregion
#region Hero
flexMessage.Contents.InitHero()
.Add(
new LineFlexImage(imageUrl)
{
Size = FlexObjectSize.full,
AspectRatio = "1.38:1"
}
);
#endregion
#region Body
var bodyContent = flexMessage.Contents.InitBody();
TimeSpan ts = _event.Time - DateTime.Now;
Console.WriteLine("No. of Minutes (Difference) = {0}", ts.TotalMinutes);
bodyContent.Add(
new LineFlexText($"再過 {ts.TotalMinutes.ToString("N0")} 分鐘,就是萬眾期待的小組晚宴啦!!!")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Regular,
OffsetBottom = FlexObjectSize.xxl,
Wrap = true
});
bodyContent.Add(
new LineFlexText($"{_event.Time.ToString("MM/dd HH:mm tt")} 準時開飯唷!!")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Regular,
OffsetBottom = FlexObjectSize.xl,
Wrap = true
});
bodyContent.Add(
new LineFlexText("晚宴菜單")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Bold,
OffsetBottom = FlexObjectSize.md
});
//$"目前暫無禱告事項唷, 趕快來新增代禱事項吧!!"
List<LineFlexBox> comments = new List<LineFlexBox>();
foreach (var a in _event.Attendees)
{
var name = a.Name;// logic.GetMemberFirstNameById(a.MemberId);
var baseLineBox = new LineFlexBox()
{
Layout = FlexObjectBoxLayout.Baseline,
};
baseLineBox.Contents.Add(
new LineFlexText(name)
{
Size = FlexObjectSize.sm,
Color = "#aaaaaa",
Flex = 1
});
baseLineBox.Contents.Add(
new LineFlexText(
string.Join(", ", a.PotluckItem.Split('|')
.Where(s => !String.IsNullOrWhiteSpace(s))
)
)
{
Size = FlexObjectSize.sm,
Color = "#666666",
Flex = 5,
Wrap = true
});
if (!string.IsNullOrWhiteSpace(a.Comment))
{
var commentLineBox = new LineFlexBox()
{
Layout = FlexObjectBoxLayout.Baseline,
};
commentLineBox.Contents.Add(
new LineFlexText(name)
{
Size = FlexObjectSize.sm,
Color = "#aaaaaa",
Flex = 1
});
commentLineBox.Contents.Add(
new LineFlexText(a.Comment)
{
Size = FlexObjectSize.sm,
Color = "#666666",
Flex = 5
});
comments.Add(commentLineBox);
}
bodyContent.Add(baseLineBox);
}
if (comments.Count > 0)
{
bodyContent.Add(
new LineFlexText("備註")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Bold,
//Style = "Italic"
});
foreach (var item in comments)
{
bodyContent.Add(item);
}
}
bodyContent.Add(new LineFlexSeparator());
#endregion
#region Footer
flexMessage.Contents.InitFooter()
.Add(
new LineFlexButton()
{
Action = new UriAction()
{
Uri = "https://happiness.tours/CellGroup/dinner?openExternalBrowser=1",
Label = "我的菜單"
}
}
);
#endregion
list.Insert(0, flexMessage);
return list;
}
}
}
}
@@ -0,0 +1,33 @@
using LineMessaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPI.Services.Interfaces;
namespace WebAPI.Services.AutoReplyCommands
{
public class ArArkCellGroupInfo : IAutoReplyCommand
{
private static readonly string[] COMMANDS = { "方舟", "方舟小組", "ark" };
private static readonly string[] MESSAGES = {
"新生命靈糧堂 Arcadia 牧區 - 方舟小組\n" +
"聚會時間 & 流程 周五晚上\n" +
"07:30 PM ~ 08:30 PM - PotLuck 時光\n" +
"08:30 PM ~ 10:00 PM - 小組分享",
"1881 Forest Dr, Azusa, CA 91702"
};
private static readonly LineGroup[] GROUPS = {
LineGroup.Ark,
LineGroup.ArkCowoker,
LineGroup.Chris
};
public string Description => "顯示方舟小組聚會資訊";
public IEnumerable<string> Commands => COMMANDS;
public IEnumerable<string> ReplyMessage => MESSAGES;
public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<ILineMessage> LineMessage => null;
}
}
@@ -0,0 +1,297 @@
using Church.Net.DAL.EF;
using Church.Net.Entity;
using Church.Net.Utility;
using LineMessaging;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebAPI.Logics;
using WebAPI.Services.Interfaces;
namespace WebAPI.Services.AutoReplyCommands
{
public class ArArkCellGroupPrayer : IAutoReplyCommand
{
public ArArkCellGroupPrayer(
CellGroupLogic logic
)
{
this.logic = logic;
this.bibleReferrences = new List<BibleReferrence>();
bibleReferrences.Add(new BibleReferrence(
"腓立比書 4:6-7",
"應當一無掛慮,只要凡事藉著禱告、祈求和感謝,將你們所要的告訴神。神所賜出人意外的平安必在基督耶穌裡保守你們的心懷意念。"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 7:7-8",
"你們祈求,就給你們;尋找,就尋見;叩門,就給你們開門。因為凡祈求的,就得著;尋找的,就尋見;叩門的,就給他開門。"
));
bibleReferrences.Add(new BibleReferrence(
"耶利米書 29:12",
"你們要呼求我,禱告我,我就應允你們。"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 18:19-20",
"我又告訴你們,若是你們中間有兩個人在地上同心合意地求什麼事,我在天上的父必為他們成全。因為無論在哪裡,有兩三個人奉我的名聚會,那裡就有我在他們中間。"
));
bibleReferrences.Add(new BibleReferrence(
"路加福音 11:2-4",
"耶穌說:「你們禱告的時候,要說:『我們在天上的父(有古卷只作:父啊):願人都尊你的名為聖。願你的國降臨;願你的旨意行在地上,如同行在天上(有古卷無願你的旨意云云)。我們日用的飲食,天天賜給我們。赦免我們的罪,因為我們也赦免凡虧欠我們的人。不叫我們遇見試探;救我們脫離凶惡(有古卷無末句)。』」"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 21:22",
"主耶穌說:「你們禱告,無論求什麼,只要信,就必得著。」"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 6:5",
"你們禱告的時候,不可像那假冒為善的人,愛站在會堂裡和十字路口上禱告,故意叫人看見。我實在告訴你們,他們已經得了他們的賞賜。"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 6:6-7",
"你禱告的時候,要進你的內屋,關上門,禱告你在暗中的父;你父在暗中察看,必然報答你。你們禱告,不可像外邦人,用許多重複話,他們以為話多了必蒙垂聽。"
));
bibleReferrences.Add(new BibleReferrence(
"馬太福音 26:41",
"總要儆醒禱告,免得入了迷惑。你們心靈固然願意,肉體卻軟弱了。"
));
bibleReferrences.Add(new BibleReferrence(
"雅各書 5:16",
"所以你們要彼此認罪,互相代求,使你們可以得醫治。義人祈禱所發的力量是大有功效的。"
));
}
private static readonly string[] COMMANDS = { "禱告", "代禱", "letspray", "pray" };
private static readonly LineGroup[] GROUPS = {
LineGroup.Ark,
LineGroup.Chris,
LineGroup.ArkCowoker,
};
private readonly CellGroupLogic logic;
public string Description => "顯示代禱事項";
public IEnumerable<string> Commands => COMMANDS;
public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<string> ReplyMessage
{
get
{
StringBuilder sb = new StringBuilder();
StringBuilder comments = new StringBuilder();
sb.AppendLine("方舟小組-禱告中心");
var _event = logic.GetLastEvent();
if (_event == null || _event.Prayers.Count == 0)
{
sb.AppendLine($"目前暫無禱告事項唷!");
sb.AppendLine($"請使用方舟禱告系統,新增代禱項目唷!");
sb.AppendLine("https://happiness.tours/CellGroup/prayer?openExternalBrowser=1");
}
var random = new Random();
int index = random.Next(bibleReferrences.Count);
var bibleSentence = bibleReferrences[index];
sb.AppendLine("======= 代禱事項 =======");
foreach (var a in _event.Prayers)
{
var name = logic.GetMemberFirstNameById(a.MemberId);
sb.AppendLine($"{name} - {string.Join(", ", a.Prayer.Split('|'))}");
//sb.AppendLine($"{logic.GetMemberFirstNameById (a.MemberId)} - ");
//int count = 0;
//foreach (var prayer in a.Prayer.Split('|'))
//{
// count++;
// sb.AppendLine(prayer);
//}
if (!string.IsNullOrWhiteSpace(a.Comment))
{
comments.AppendLine($"{name}:{a.Comment}");
}
}
if (comments.Length > 0)
{
sb.AppendLine("========= 備註 =========");
sb.Append(comments.ToString());
}
sb.AppendLine("");
sb.AppendLine($"請使用方舟禱告系統,新增代禱項目唷!");
sb.AppendLine("https://happiness.tours/CellGroup/prayer?openExternalBrowser=1");
return new string[] { sb.ToString() };
}
}
public IEnumerable<ILineMessage> LineMessage
{
get
{
var random = new Random();
int index = random.Next(bibleReferrences.Count);
var bibleSentence = bibleReferrences[index];
List<ILineMessage> list = new List<ILineMessage>();
var _event = logic.GetLastEvent();
string title = "禱告中心 普壘森特";
string imageUrl = "https://dailyverses.net/images/tc/cuv/matthew-21-22-3.jpg";
var flexMessage = new LineFlexMessage();
flexMessage.AltText = title;
#region Header
var headerContent = flexMessage.Contents.InitHeader();
headerContent.Add(
new LineFlexText(title)
{
Size = FlexObjectSize.lg,
Weight = FlexObjectTextWeidht.Bold,
Align = "center"
});
#endregion
#region Hero
flexMessage.Contents.InitHero()
.Add(
new LineFlexImage(imageUrl)
{
Size = FlexObjectSize.full,
}
);
#endregion
#region Body
var bodyContent = flexMessage.Contents.InitBody();
bodyContent.Add(
new LineFlexText("代禱項目")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Bold,
OffsetBottom = FlexObjectSize.md
});
//$"目前暫無禱告事項唷, 趕快來新增代禱事項吧!!"
List<LineFlexBox> comments = new List<LineFlexBox>();
if (_event == null || _event.Prayers.Count == 0)
{
bodyContent.Add(
new LineFlexText("目前暫無禱告事項唷, 趕快來新增代禱事項吧!!")
{
Size = FlexObjectSize.md,
Color = "#666666",
});
}
else
{
foreach (var a in _event.Prayers)
{
var name = logic.GetMemberFirstNameById(a.MemberId);
var baseLineBox = new LineFlexBox()
{
Layout = FlexObjectBoxLayout.Baseline,
};
baseLineBox.Contents.Add(
new LineFlexText(name)
{
Size = FlexObjectSize.sm,
Color = "#aaaaaa",
Flex = 1
});
baseLineBox.Contents.Add(
new LineFlexText(
string.Join(", ", a.Prayer.Split('|')
.Where(s => !String.IsNullOrWhiteSpace(s))
)
)
{
Size = FlexObjectSize.sm,
Color = "#666666",
Flex = 5,
Wrap = true
});
if (!string.IsNullOrWhiteSpace(a.Comment))
{
var commentLineBox = new LineFlexBox()
{
Layout = FlexObjectBoxLayout.Baseline,
};
commentLineBox.Contents.Add(
new LineFlexText(name)
{
Size = FlexObjectSize.sm,
Color = "#aaaaaa",
Flex = 1
});
commentLineBox.Contents.Add(
new LineFlexText(a.Comment)
{
Size = FlexObjectSize.sm,
Color = "#666666",
Flex = 5
});
comments.Add(commentLineBox);
}
bodyContent.Add(baseLineBox);
}
if (comments.Count > 0)
{
bodyContent.Add(
new LineFlexText("備註")
{
Size = FlexObjectSize.md,
Weight = FlexObjectTextWeidht.Bold,
//Style = "Italic"
});
foreach (var item in comments)
{
bodyContent.Add(item);
}
}
}
bodyContent.Add(new LineFlexSeparator());
#endregion
#region Footer
flexMessage.Contents.InitFooter()
.Add(
new LineFlexButton()
{
Action = new UriAction()
{
Uri = "https://happiness.tours/CellGroup/prayer?openExternalBrowser=1",
Label = "我的代禱事項"
}
}
);
#endregion
list.Insert(0, flexMessage);
return list;
}
}
private List<BibleReferrence> bibleReferrences;
}
class BibleReferrence
{
public BibleReferrence(string from, string content)
{
From = from;
Content = content;
}
public string From { get; set; }
public string Content { get; set; }
}
}
@@ -0,0 +1,31 @@
using LineMessaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPI.Services.Interfaces;
namespace WebAPI.Services.AutoReplyCommands
{
public class ArChurchInfo : IAutoReplyCommand
{
private static readonly string[] COMMANDS = { "教會", "church" };
private static readonly string[] MESSAGES = {
"新生命靈糧堂 Arcadia 牧區\n聚會時間 周日 11:00 AM - 12:30PM\n聚會後有提供精緻午餐唷!",
"1881 S 1st Ave, Arcadia, CA 91006"
};
private static readonly LineGroup[] GROUPS = {
LineGroup.Ark,
LineGroup.ArkCowoker,
LineGroup.Chris
};
public string Description => "顯示教會主日聚會資訊";
public IEnumerable<string> Commands => COMMANDS;
public IEnumerable<string> ReplyMessage => MESSAGES;
public IEnumerable<LineGroup> SupportGroups => GROUPS;
public IEnumerable<ILineMessage> LineMessage => null;
}
}
+165
View File
@@ -0,0 +1,165 @@
using System.Collections.Generic;
using System.Linq;
using System;
using WebAPI.Services.Interfaces;
using System.Diagnostics;
using Church.Net.Entity;
using Church.Net.Entity.Interface;
using Church.Net.DAL.EFCoreDBF;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
namespace WebAPI.Services
{
public class DbLoggingService : ILoggingService
{
private readonly ICrudDAL<LogInfo> crudDAL;
public DbLoggingService(ICrudDAL<LogInfo> crudDAL)
{
this.crudDAL = crudDAL;
}
public int Error(Exception exception)
{
string msg = exception.Message.ToString();
string detailMsg = exception.InnerException != null ? exception.InnerException.Message : "";
LogInfo log = new LogInfo(LogLevel.Error)
{
Message = msg,
DetailMessage = detailMsg,
Source = exception.Source,
StackTrace = exception.StackTrace,
UserId = ""
};
return AppendLog(log);
}
public int Error(Exception exception, string from)
{
string msg = exception.Message.ToString();
string detailMsg = exception.InnerException != null ? exception.InnerException.Message : "";
LogInfo log = new LogInfo(LogLevel.Error)
{
Url = from,
Message = msg,
DetailMessage = detailMsg,
Source = exception.Source,
StackTrace = exception.StackTrace
};
return AppendLog(log);
}
public int Error(Exception exception, string from, string detailMsg)
{
string msg = exception.Message.ToString();
string exceptionDetailMsg = exception.InnerException != null ? exception.InnerException.Message : "";
if (false == string.IsNullOrEmpty(exceptionDetailMsg))
{
detailMsg += Environment.NewLine + "=========== Exception Detail ==========";
detailMsg += Environment.NewLine + exceptionDetailMsg;
}
LogInfo log = new LogInfo(LogLevel.Error)
{
Url = from,
Message = msg,
DetailMessage = detailMsg,
Source = exception.Source,
StackTrace = exception.StackTrace
};
return AppendLog(log);
}
public IEnumerable<LogInfo> GetAllErrors(DateTime? rangeStart = null, DateTime? rangeEnd = null)
{
IQueryable<LogInfo> query = crudDAL.GetDbSet().AsQueryable();
if (rangeStart != null)
{
query = query.Where(l => l.Time >= rangeStart);
}
if (rangeEnd != null)
{
query = query.Where(l => l.Time <= rangeEnd);
}
return query.OrderByDescending(l => l.Time).ToList();
}
private int AppendLog(LogInfo log)
{
try
{
crudDAL.Create(log);
return log.TrackNo;
}
catch (Exception ex)
{
WriteWindowsEventLog(ex);
WriteWindowsEventLog(log);
return -1;
}
}
private void WriteWindowsEventLog(LogInfo log)
{
//var fileLogService = new FileLoggingService();
//fileLogService.Error(new Exception(
// log.Source + Environment.NewLine + Environment.NewLine +
// log.Message + Environment.NewLine + Environment.NewLine +
// log.DetailMessage
// ));
EventLog.WriteEntry("BeyondAPI",
log.Source + Environment.NewLine + Environment.NewLine +
log.Message + Environment.NewLine + Environment.NewLine +
log.DetailMessage
, EventLogEntryType.Error);
}
private void WriteWindowsEventLog(Exception ex)
{
//var fileLogService = new FileLoggingService();
//fileLogService.Error(ex, "Can Not Append Error Log");
EventLog.WriteEntry("BeyondAPI", $"Can Not Append Error Log:{ex.Message}", EventLogEntryType.Error);
}
public void Log(string message, object detail)
{
LogInfo log = new LogInfo(LogLevel.Info)
{
Message = message,
DetailMessage = JsonConvert.SerializeObject(detail,Formatting.Indented) ,
//Source = exception.Source,
//StackTrace = exception.StackTrace
};
AppendLog(log);
}
public void Warning(string message, object detail)
{
LogInfo log = new LogInfo(LogLevel.Warning)
{
Message = message,
DetailMessage = JsonConvert.SerializeObject(detail, Formatting.Indented),
//Source = exception.Source,
//StackTrace = exception.StackTrace
};
AppendLog(log);
}
IEnumerable<LogInfo> ILoggingService.GetAllErrors(DateTime? rangeStart, DateTime? rangeEnd)
{
throw new NotImplementedException();
}
public IEnumerable<LogInfo> GetAllLogs(LogLevel logLevel, DateTime? rangeStart = null, DateTime? rangeEnd = null)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,17 @@
using LineMessaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI.Services.Interfaces
{
public interface IAutoReplyCommand
{
string Description { get; }
IEnumerable<string> Commands { get; }
IEnumerable<string> ReplyMessage { get; }
IEnumerable<LineGroup> SupportGroups { get; }
IEnumerable<ILineMessage> LineMessage { get; }
}
}
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System;
using Church.Net.Entity;
using Church.Net.Entity.Interface;
namespace WebAPI.Services.Interfaces
{
public interface ILoggingService
{
void Log(string message, object detail);
void Warning(string message, object detail);
int Error(Exception exception);
int Error(Exception exception, string from);
int Error(Exception exception, string from, string detailMsg);
IEnumerable<LogInfo> GetAllErrors(DateTime? rangeStart = null, DateTime? rangeEnd = null);
IEnumerable<LogInfo> GetAllLogs(LogLevel logLevel, DateTime? rangeStart = null, DateTime? rangeEnd = null);
}
}
+295
View File
@@ -0,0 +1,295 @@
using Church.Net.Utility;
using LineMessaging;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebAPI.Services.Interfaces;
using static System.Net.Mime.MediaTypeNames;
namespace WebAPI.Services
{
[Flags]
public enum LineGroup
{
[Description("Cac4ac5a8d7fc52daa444d71dc7c360a9")]
Ark = 1 << 0,
[Description("Ca20e3b65aa58e676815eb13c3222591a")]
ArkCowoker = 1 << 1,
[Description("U97e9e579a41a5222e33bf68a3bf479a0")]
Chris = ~(~0 << 20),
}
public class LineAutoBotService
{
private readonly IEnumerable<IAutoReplyCommand> autoReplyCommands;
private readonly ILoggingService loggingService;
public LineAutoBotService(
IEnumerable<IAutoReplyCommand> autoReplyCommands,
ILoggingService loggingService
)
{
this.autoReplyCommands = autoReplyCommands;
this.loggingService = loggingService;
}
public void SendTextMessage(string text, LineGroup target)
{
var test = new LineMessagingClient();
try
{
var wait = test.PushMessage(EnumHelper.EnumToDescriptionString(target), new LineTextMessage() { Text = text })
.GetAwaiter();
wait.GetResult();
}
catch (Exception ex)
{
this.loggingService.Error(ex);
}
}
public async Task<bool> ReplyTextMessage(string replyToken, IEnumerable<string> textMessages)
{
var test = new LineMessagingClient();
var replyMessage = new LineReplyMessage() { ReplyToken = replyToken };
var messages = new List<ILineMessage>();
foreach (var message in textMessages)
{
messages.Add(new LineTextMessage() { Text = message });
}
replyMessage.Messages = messages;
//test.ReplyMessage(replyMessage);
try
{
await test.ReplyMessage(replyMessage);
return true;
}
catch (Exception ex)
{
this.loggingService.Error(ex, "ReplyTextMessage:68", JsonConvert.SerializeObject(replyMessage, Formatting.Indented));
return false;
}
}
public async Task<bool> ReplyLineMessage(string replyToken, IEnumerable<ILineMessage> lineMessages)
{
var test = new LineMessagingClient();
var replyMessage = new LinePushMessage() { To = replyToken };
replyMessage.Messages = lineMessages;
try
{
//var wait= test.PushMessage(replyMessage).GetAwaiter();
//wait.GetResult();
await test.PushMessage(replyMessage);
return true;
}
catch (Exception ex)
{
this.loggingService.Error(ex, "ReplyLineMessage:84", JsonConvert.SerializeObject(replyMessage, Formatting.Indented));
return false;
}
}
public async Task<bool> AutoReply(LineWebhookContent content)
{
loggingService.Log("AutoReply", content);
try
{
foreach (var e in content.Events)
{
if (e.Message.Type == MessageType.Text)
{
List<string> textMessages = new List<string>();
string replyToken = e.ReplyToken;
string text = e.Message.Text;
string target = "";
switch (e.Source.Type)
{
case WebhookRequestSourceType.User:
target = e.Source.UserId;
break;
case WebhookRequestSourceType.Group:
target = e.Source.GroupId;
break;
case WebhookRequestSourceType.Room:
target = e.Source.RoomId;
break;
default:
break;
}
if (!String.IsNullOrWhiteSpace(replyToken) && text.IndexOf("#") == 0)
{
text = text.ToLower().Substring(1);
var group = EnumHelper.GetEnumValueFromDescription<LineGroup>(target);
var autoReply = autoReplyCommands.Where(ar => ar.SupportGroups.Contains(group) && ar.Commands.Contains(text)).FirstOrDefault();
if (autoReply != null)
{
if (autoReply.LineMessage != null)
{
await ReplyLineMessage(target, autoReply.LineMessage);
}
else
{
await ReplyTextMessage(replyToken, autoReply.ReplyMessage);
}
return true;
}
else if (text == "help" || text == "?")
{
StringBuilder commandText = new StringBuilder();
commandText.AppendLine("方舟資訊部 - 指令清單");
foreach (var ar in autoReplyCommands.Where(ar => ar.SupportGroups.Contains(group)))
{
commandText.AppendLine($"{string.Join(", ", ar.Commands.Select(s => $"#{s}"))} - {ar.Description}");
}
commandText.Append($"#help, #? - 顯示指令清單");
await ReplyTextMessage(replyToken, new string[] { commandText.ToString() });
}
}
}
this.LogLineMessage(e);
}
}
catch (Exception ex)
{
loggingService.Error(ex, "AutoReply:188", JsonConvert.SerializeObject(content, Formatting.Indented));
return false;
}
return true;
}
public async Task<bool> PushCommandMessage(LineGroup group, string command)
{
try
{
if (command.IndexOf("#") == 0)
{
command = command.ToLower().Substring(1);
var autoReply = autoReplyCommands.Where(ar => ar.SupportGroups.Contains(group) && ar.Commands.Contains(command)).FirstOrDefault();
if (autoReply != null)
{
if (autoReply.LineMessage != null)
{
await ReplyLineMessage(group.EnumToDescriptionString(), autoReply.LineMessage);
}
else
{
await ReplyTextMessage(group.EnumToDescriptionString(), autoReply.ReplyMessage);
}
return true;
}
else if (command == "help" || command == "?")
{
StringBuilder commandText = new StringBuilder();
commandText.AppendLine("方舟資訊部 - 指令清單");
foreach (var ar in autoReplyCommands.Where(ar => ar.SupportGroups.Contains(group)))
{
commandText.AppendLine($"{string.Join(", ", ar.Commands.Select(s => $"#{s}"))} - {ar.Description}");
}
commandText.Append($"#help, #? - 顯示指令清單");
await ReplyTextMessage(group.EnumToDescriptionString(), new string[] { commandText.ToString() });
}
}
}
catch (Exception ex)
{
loggingService.Error(ex, "AutoReply:188",command);
return false;
}
return true;
}
private void LogLineMessage(LineWebhookContent.Event e)
{
return;
try
{
//var lineHookRequest = new LineMessaging.LineWebhookRequest("d23edf453427256a759d218ec8b6779f", request);
//var content = await lineHookRequest.GetContent();
string txtPath = ServerUtils.MapPath("App_Data/LinePostLog.txt");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"==================={DateTime.Now.ToString("MM/dd/yyyy HH:mm")}=========================");
stringBuilder.AppendLine($"Message Type:{e.Type.ToString()}");
switch (e.Source.Type)
{
case WebhookRequestSourceType.User:
stringBuilder.AppendLine($"UserId:{e.Source.UserId}");
break;
case WebhookRequestSourceType.Group:
stringBuilder.AppendLine($"GroupId:{e.Source.GroupId}");
break;
case WebhookRequestSourceType.Room:
stringBuilder.AppendLine($"RoomId:{e.Source.RoomId}");
break;
default:
break;
}
stringBuilder.AppendLine($"Reply Token:{e.ReplyToken}");
stringBuilder.AppendLine($"Message Type:{e.Message.Type.ToString()}");
switch (e.Message.Type)
{
case MessageType.Text:
stringBuilder.AppendLine($"Message:{e.Message.Text}");
break;
case MessageType.Image:
case MessageType.Video:
case MessageType.Audio:
case MessageType.File:
case MessageType.Location:
case MessageType.Sticker:
case MessageType.Imagemap:
case MessageType.Template:
default:
stringBuilder.AppendLine($"Message:{JsonConvert.SerializeObject(e.Message, Formatting.Indented)}");
break;
}
System.IO.File.AppendAllText(txtPath, stringBuilder.ToString());
}
catch (Exception ex)
{
}
}
}
}
+184
View File
@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Church.Net.DAL.EF;
using Church.Net.DAL.EFCoreDBF;
using Church.Net.Entity;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using WebAPI.Hubs;
using WebAPI.Logics;
using WebAPI.Logics.Core;
using WebAPI.Logics.Interface;
using WebAPI.Services;
using WebAPI.Services.AutoReplyCommands;
using WebAPI.Services.Interfaces;
using static System.Net.Mime.MediaTypeNames;
namespace WebAPI
{
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().AddNewtonsoftJson(options =>
{
// Use the default property (Pascal) casing
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new CamelCaseNamingStrategy(),
};
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified;
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
services.AddSignalR();
services.AddSingleton<GameRoomLogic>();
//services.AddSingleton<ChurchNetContext>(new ChurchNetContext());
services.AddDbContext<ChurchNetContext>(options =>
options.UseNpgsql(
//Configuration.GetConnectionString()
"Host=192.168.86.131;Port=49154;Database=Church;Username=chris;Password=1124"
));
services.AddTransient<LineAutoBotService>();
services.AddTransient<IAutoReplyCommand, ArChurchInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupInfo>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupDinner>();
services.AddTransient<IAutoReplyCommand, ArArkCellGroupPrayer>();
services.AddSingleton<VideoDownloadLogic>();
services.AddScoped<LogicService>();
services.AddScoped<CellGroupLogic>();
services.AddScoped(typeof(ICrudLogic<>), typeof(LogicBase<>));
services.AddScoped(typeof(ICrudDAL<>), typeof(CrudDALCBase<>));
services.AddScoped(typeof(ICombinedKeyCrudLogic<>), typeof(CombinedKeyLogicBase<>));
services.AddScoped(typeof(ICombinedKeyCrudDAL<>), typeof(CombinedKeyCrudDALCBase<>));
services.AddScoped<HappinessGroupLogic>();
services.AddTransient<ILoggingService, DbLoggingService>();
//services.AddMvc(o=>o.Filters.Add(typeof(HandleExceptionFilter)));
//services.AddMvc(o => o.Filters.Add(new HandleExceptionFilter(services.BuildServiceProvider().GetService<ILoggingService>())));
//services.BuildServiceProvider().GetService<ILoggingService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ChurchNetContext dbContext)
{
//Reference:https://stackoverflow.com/questions/69961449/net6-and-datetime-problem-cannot-write-datetime-with-kind-utc-to-postgresql-ty
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
AppDomain.CurrentDomain.SetData("ContentRootPath", env.ContentRootPath);
AppDomain.CurrentDomain.SetData("WebRootPath", env.WebRootPath);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// global cors policy
app.UseCors(x => x
//.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials()
); // allow credentials
//app.UseCors(builder =>
//{
// builder.WithOrigins("http://localhost:4200")
// .AllowAnyHeader()
// .WithMethods("GET", "POST")
// .AllowCredentials();
//});
//app.UseHttpsRedirection();
//app.UsePathBase(new PathString("/api"));
app.UsePathBase(new PathString("/"));
app.UseRouting();
app.UseEndpoints(endpoints =>
{
//endpoints.MapControllerRoute(
// name: "default",
// pattern: "{controller}/{id?}");
endpoints.MapHub<AvalonHub>("/AvalonHub");
endpoints.MapHub<WhoIsSpyHub>("/WhoIsSpyHub");
endpoints.MapHub<BaseHub>("/BaseHub");
endpoints.MapControllers();
//endpoints.MapControllerRoute(
// name: "default",
// pattern: "{controller}/{action=Index}/{id?}");
});
//app.UseExceptionHandler(exceptionHandlerApp =>
//{
// exceptionHandlerApp.Run(async context =>
// {
// context.Response.StatusCode = StatusCodes.Status500InternalServerError;
// // using static System.Net.Mime.MediaTypeNames;
// context.Response.ContentType = Text.Plain;
// await context.Response.WriteAsync("An exception was thrown.");
// var exceptionHandlerPathFeature =
// context.Features.Get<IExceptionHandlerPathFeature>();
// if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
// {
// await context.Response.WriteAsync(" The file was not found.");
// }
// if (exceptionHandlerPathFeature?.Path == "/")
// {
// await context.Response.WriteAsync(" Page: Home.");
// }
// });
//});
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllers();
// endpoints.MapHub<WhoIsSpyHub>("/WhoIsSpyHub");
//});
if (env.IsDevelopment())
{
//dbContext.Database.EnsureCreated();
dbContext.Database.Migrate();
}
}
}
}
+39
View File
@@ -0,0 +1,39 @@
using Church.Net.Entity;
using System;
namespace WebAPI.ViewModel
{
public class RegisterViewModel
{
public string OAuthType { get; set; }
public string AccessToken { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string AvatarImage { get; set; }
}
public class OAuthRegisterViewModel
{
public string Type { get; set; }
public string Email { get; set; }
public string AccessToken { get; set; }
public string FullName { get; set; }
public string AvatarImage { get; set; }
}
public class LoginTokenViewModel
{
public string MemberId { get; set; }
public string Token { get; set; }
public DateTime TokenExpireTime { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string AvatarImage { get; set; }
public Role Role { get; set; }
public PastoralDomain CellGroup { get; set; }
}
}
+15
View File
@@ -0,0 +1,15 @@
using System;
namespace WebAPI
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
+52
View File
@@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<UserSecretsId>983731f5-925d-44ec-b4c8-a7c4ad857569</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<StartupObject></StartupObject>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Church.Net.DAL.EFCoreDBF\Church.Net.DAL.EFCoreDBF.csproj" />
<ProjectReference Include="..\Church.Net.Entity2\Church.Net.Entity.csproj" />
<ProjectReference Include="..\Church.Net.Utility\Church.Net.Utility.csproj" />
<ProjectReference Include="..\LineMessaging\LineMessaging.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Controllers\PasswordLogin\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="LineBotSDK" Version="2.8.35" />
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="QRCoder" Version="1.4.1" />
<PackageReference Include="SharpGrabber.YouTube" Version="1.4.0" />
</ItemGroup>
<ItemGroup>
<None Update="App_Data\ScaneMeQrCode.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+9
View File
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<httpProtocol>
<customHeaders>
<!--<add name="Access-Control-Allow-Origin" value="http://happiness.tours" />-->
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebAPI.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>