paint-brush
Twilio ve ASP.NET Core ile Trivia Quiz WhatsApp Botu Oluşturunile@zadok
2,818 okumalar
2,818 okumalar

Twilio ve ASP.NET Core ile Trivia Quiz WhatsApp Botu Oluşturun

ile Zadok J.15m2023/09/15
Read on Terminal Reader
Read this story w/o Javascript

Çok uzun; Okumak

Bu eğitim kılavuzunda Twilio for WhatsApp, ASP.NET Core ve The Trivia API'yi kullanarak nasıl bilgi yarışması oluşturulacağını öğreneceksiniz.
featured image - Twilio ve ASP.NET Core ile Trivia Quiz WhatsApp Botu Oluşturun
Zadok J. HackerNoon profile picture
0-item
1-item

Trivia oyunları, yeni gerçekleri öğrenebileceğiniz ve çeşitli konularda bilginizi genişletebileceğiniz ilgi çekici ve eğitici bir deneyim sunar. Günümüzde Trivia quiz mobil ve web uygulamaları bu tür bir aktivite için en sık başvurulan alanlardır. WhatsApp'ta bilgi yarışması oyunu oynamaya ne dersiniz?


Bu eğitim kılavuzunda, Twilio for WhatsApp, ASP.NET Core ve ASP.NET Core'u kullanarak bir bilgi yarışması uygulamasının nasıl oluşturulacağını öğreneceksiniz. Trivia API'si ( CC BY-NC 4.0 kapsamında lisanslanmıştır ). Bu eğitimin amacı, kullanıcıların WhatsApp kullanarak çoktan seçmeli soruları oynamasına ve yanıtlamasına olanak tanıyan bir trivia oyun uygulaması oluşturmaktır. Sen yararlanacaksın ASP.NET Core'daki oturumlar Kullanıcı ilerlemesini depolamak ve almak, puanı takip etmek ve oyun durumunu korumak için.


Bu soruları almak için geliştiricilerin çoktan seçmeli bilgi soruları sunarak sınav uygulamaları oluşturmasını kolaylaştıran bir REST API olan Trivia API'yi kullanacaksınız. Trivia API'si hakkında daha fazla bilgi edinmek için lütfen__ Trivia API belgelerini__ ziyaret edin.


Önkoşullar

Bu öğreticiyi tamamlamak için ihtiyacınız olacak:


Bu eğitimin kaynak kodunu GitHub'da bulabilirsiniz .


Yeni bir ASP.NET Core projesi ayarlama

Başlamak için tercih edilen bir çalışma dizininde kabuk terminalinizi kullanarak yeni bir web API projesi oluşturmak üzere aşağıdaki komutları çalıştırın:


 dotnet new webapi -n TwilioWhatsAppTriviaApp --no-openapi


Yukarıdaki kod parçasındaki ikinci komut, belirtilen adla ve OpenAPI (Swagger) desteği olmadan yeni bir web API projesi oluşturacaktır. Projede Swagger'ı kullanmak istiyorsanız yukarıdaki komutta --no-openapi komutunu atlamanız yeterlidir.


Bu komutu çalıştırarak proje dizinine geçin:


 cd TwilioWhatsAppTriviaApp


Yükle ASP.NET Core için Twilio Yardımcı kitaplığı NuGet paketi:


 dotnet add package Twilio.AspNet.Core


Bu kitaplık, bir ASP.NET Core uygulamasında Twilio web kancaları ve API'lerle çalışmayı kolaylaştırır.


Tercih ettiğiniz IDE'yi kullanarak projeyi açın. Denetleyiciler klasöründe, ortak şablon denetleyici dosyası WeatherForecastController.cs'yi kaldırın ve ayrıca proje dizinindeki WeatherForcast.cs dosyasını da kaldırın.


Şu ana kadar yaptığınız her şeyin iyi çalıştığından emin olmak için aşağıdaki komutları kullanarak projenizi oluşturun ve çalıştırın:


 dotnet build dotnet run


Projeyi başarıyla çalıştırdıktan sonra hata ayıklama konsolunda görünen localhost URL'lerinden herhangi birini not edin. Ngrok'u kullanarak herkesin erişebileceği bir yerel web sunucusu kurmak için bu URL'lerden herhangi birini kullanabilirsiniz.


yerel ana bilgisayar URL'leri


Oturumları Uygulama

Oturumlar, bir kullanıcının verilerini ASP.NET Core uygulamasında depolamanın çeşitli yollarından biridir. Varsayılan olarak HTTP protokolü durum bilgisiz olduğundan, yani veriler korunmadığından, kullanıcı verilerini istekler arasında tutmak istediğinizde bu çok önemlidir.

Aşağıdaki kodda gösterildiği gibi Program.cs dosyasını değiştirerek bellek içi oturum sağlayıcısını ekleyin:


 var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run();


AddDistributedMemoryCache() dağıtılmış bellek önbellek hizmetini kaydeder. Bu hizmet, birden fazla istek veya oturumda veri depolamak ve almak için kullanılabilecek bir bellek içi önbellek sağlar.


AddSession() , oturum hizmetlerini kaydederek uygulamanın oturum durumunu korumasını sağlar. options parametresi oturumla ilgili çeşitli seçenekleri yapılandırmanıza olanak tanır. IdleTimeout oturumun boşta sayılacağı eylemsizlik süresini ayarlamak için kullanılır. Bu durumda 40 saniyeye ayarlanır. Cookie.IsEssential , çerez reddinin etkinleştirildiği senaryolarda bile oturumun durumunun işlevsel kalmasını sağlar.


Oturum desteği, UseSession ara yazılımının uygulama hattına eklenmesiyle etkinleştirilir; yani uygulamanız, verileri depolamak ve almak için kullanılabilecek bir oturum nesnesine erişim kazanır.


Modelleri Oluşturun

Proje dizininizde Modeller adında yeni bir klasör oluşturun. Aşağıdaki kod örneklerinde gösterildiği gibi özelliklere sahip iki model sınıf dosyası ( TriviaApiResponse.cs ve Question.cs) ekleyin:


 using Newtonsoft.Json; namespace TwilioWhatsAppTriviaApp.Models; public class TriviaApiResponse { [JsonProperty("category")] public string Category { get; set; } [JsonProperty("correctAnswer")] public string CorrectAnswer { get; set; } [JsonProperty("incorrectAnswers")] public List<string> IncorrectAnswers { get; set; } [JsonProperty("question")] public string Question { get; set; } [JsonProperty("type")] public string? Type { get; set; } [JsonProperty("difficulty")] public string Difficulty { get; set; } }


 namespace TwilioWhatsAppTriviaApp.Models; public class Question { public string QuestionText { get; set; } public List<(string option, bool isCorrect)> Options { get; set; } }


TriviaApiResponse modeli, Trivia API yanıtının alanlarını temsil eden özellikleri içerir. JsonProperty özelliği, her özelliğin karşılık gelen JSON verileriyle doğru şekilde doldurulmasını sağlar.


Trivia sorularını basitleştirilmiş bir şekilde ele almak için Question sınıfı kurtarmaya geliyor. Bu sınıf, soru metni ve seçenekler listesi de dahil olmak üzere, önemsiz bir soru için gerekli bilgileri içerir. Her seçenek, seçenek metnini içeren bir tanımlama grubu ve bunun doğru seçenek olup olmadığını gösteren bir boole değeriyle temsil edilir.


Trivia Hizmet Sınıfını Ekle

Proje dizininizde bir Hizmetler klasörü oluşturun ve TriviaService.cs adlı yeni bir sınıf dosyası ekleyin. Aşağıdaki kodda gösterildiği gibi içeriğini değiştirin:


 using Newtonsoft.Json; using TwilioWhatsAppTriviaApp.Models; namespace TwilioWhatsAppTriviaApp.Services; public class TriviaService { private const string TheTriviaApiUrl = @"https://the-trivia-api.com/api/questions?limit=3"; private HttpClient httpClient; public TriviaService(HttpClient httpClient) { this.httpClient = httpClient; } public async Task<IEnumerable<TriviaApiResponse>> GetTrivia() { var response = await httpClient.GetAsync(TheTriviaApiUrl); var triviaJson = await response.Content.ReadAsStringAsync(); var trivia = JsonConvert.DeserializeObject<IEnumerable<TriviaApiResponse>>(triviaJson); return trivia; } public List<Question> ConvertTriviaToQuestions(IEnumerable<TriviaApiResponse> questions) { List<Question> newQuestions = new(); foreach (var question in questions) { var options = new List<(string option, bool isCorrect)>() { (question.CorrectAnswer, true), (question.IncorrectAnswers[0], false), (question.IncorrectAnswers[1], false), (question.IncorrectAnswers[2], false) }; // Shuffle the options randomly Random random = new(); options = options.OrderBy(_ => random.Next()).ToList(); newQuestions.Add(new Question { QuestionText = question.Question, Options = options }); } return newQuestions; } }


TriviaService sınıfı iki yöntem içerir: GetTrivia ve ConvertTriviaToQuestions . GetTrivia yöntemi, HTTP GET isteğini Trivia API'sine, yalnızca 3 sorunun döndürülmesi gerektiğini belirten limit=3 sorgu parametresiyle gönderir. Limit parametresi olmadan API varsayılan olarak 10 soru döndürür.


ConvertTriviaToQuestions yöntemi, API'den gelen yanıtı organize bir şekilde dönüştürür. Yöntem ayrıca tüm soru seçeneklerini rastgele karıştırır, böylece tek bir seçenek tüm soruların yanıtı olmaz.


TriviaService ve HTTP istemcisini uygulamanızın Dependency Injection (DI) kapsayıcısına kaydetmek için Program.cs'yi aşağıdaki kodda gösterildiği gibi değiştirin:


 using TwilioWhatsAppTriviaApp.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(40); options.Cookie.IsEssential = true; }); builder.Services.AddHttpClient(); builder.Services.AddScoped<TriviaService>(); var app = builder.Build(); app.UseSession(); app.MapControllers(); app.Run();


Trivia Denetleyicisini Oluşturun

TriviaController.cs adlı bir dosyaya boş bir API denetleyici sınıfını Denetleyiciler klasörüne ekleyin ve içeriğini aşağıdaki kodda gösterildiği gibi değiştirin:


 using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Twilio.AspNet.Core; using Twilio.TwiML; using Twilio.TwiML.Messaging; using TwilioWhatsAppTriviaApp.Models; using TwilioWhatsAppTriviaApp.Services; namespace WhatsappTrivia.Controllers; [Route("[controller]")] [ApiController] public class TriviaController : TwilioController { private const string SessionKeyIsGameOn = "IsGameOn"; private const string SessionKeyScore = "Score"; private const string SessionKeyCurrentQuestionIndex = "CurrentQuestionIndex"; private const string SessionKeyTotalQuestions = "TotalQuestions"; private const string SessionKeyQuestions = "Questions"; private static readonly string[] StartCommands = { "START", "S" }; private static readonly string[] OptionValues = { "A", "B", "C", "D" }; private readonly TriviaService triviaService; public TriviaController(TriviaService triviaService) { this.triviaService = triviaService; } [HttpPost] public async Task<IActionResult> Index() { var response = new MessagingResponse(); var form = await Request.ReadFormAsync(); var body = form["Body"].ToString().ToUpper().Trim(); await HttpContext.Session.LoadAsync(); var isGameOn = Convert.ToBoolean(HttpContext.Session.GetString(SessionKeyIsGameOn)); int currentQuestionIndex = HttpContext.Session.GetInt32(SessionKeyCurrentQuestionIndex) ?? 0; int totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; if (StartCommands.Contains(body) && !isGameOn) { await StartGame(); HttpContext.Session.SetString(SessionKeyIsGameOn, "true"); response.Message(PresentQuestionWithOptions(currentQuestionIndex)); return TwiML(response); } if (OptionValues.Contains(body) && isGameOn) { var result = ProcessUserAnswer(body, currentQuestionIndex); response.Message(result); currentQuestionIndex++; if (currentQuestionIndex <= totalQuestions - 1) { HttpContext.Session.SetInt32(SessionKeyCurrentQuestionIndex, currentQuestionIndex); response.Append(new Message(PresentQuestionWithOptions(currentQuestionIndex))); } else { response.Append(new Message(EndTrivia())); } return TwiML(response); } response.Message(!isGameOn ? "*Hello! Send 'Start' or 'S' to play game*" : "*Invalid Input! Send a correct option 'A', 'B', 'C' or 'D'*"); return TwiML(response); } private async Task StartGame() { if (HttpContext.Session.GetString(SessionKeyQuestions) != null) { HttpContext.Session.Remove(SessionKeyQuestions); } var trivia = await this.triviaService.GetTrivia(); var questions = this.triviaService.ConvertTriviaToQuestions(trivia); AddNewQuestionsToSession(questions); HttpContext.Session.SetInt32(SessionKeyTotalQuestions, questions.Count); } private string ProcessUserAnswer(string userAnswer, int questionIndex) { bool optionIsCorrect = false; int score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var question = RetrieveQuestionFromSession(questionIndex); switch (userAnswer) { case "A": optionIsCorrect = question.Options[0].isCorrect; break; case "B": optionIsCorrect = question.Options[1].isCorrect; break; case "C": optionIsCorrect = question.Options[2].isCorrect; break; case "D": optionIsCorrect = question.Options[3].isCorrect; break; } if (optionIsCorrect) { score++; HttpContext.Session.SetInt32(SessionKeyScore, score); } return optionIsCorrect ? "_Correct ✅_" : $"_Incorrect ❌ Correct answer is {question.Options.Find(o => o.isCorrect).option.TrimEnd()}_"; } private string PresentQuestionWithOptions(int questionIndex) { var question = RetrieveQuestionFromSession(questionIndex); return $""" {questionIndex + 1}. {question.QuestionText} {OptionValues[0]}. {question.Options[0].option} {OptionValues[1]}. {question.Options[1].option} {OptionValues[2]}. {question.Options[2].option} {OptionValues[3]}. {question.Options[3].option} """; } private void AddNewQuestionsToSession(List<Question> questions) => HttpContext.Session.SetString(SessionKeyQuestions, JsonConvert.SerializeObject(questions)); private Question RetrieveQuestionFromSession(int questionIndex) { var questionsFromSession = HttpContext.Session.GetString(SessionKeyQuestions); return JsonConvert.DeserializeObject<List<Question>>(questionsFromSession)[questionIndex]; } private string EndTrivia() { var score = HttpContext.Session.GetInt32(SessionKeyScore) ?? 0; var totalQuestions = HttpContext.Session.GetInt32(SessionKeyTotalQuestions) ?? 0; var userResult = $""" Thanks for playing! 😊 You answered {score} out of {totalQuestions} questions correctly. To play again, send 'Start' or 'S' """; HttpContext.Session.Clear(); return userResult; } }


Bu denetleyici sınıfı, gelen iletilerin işlenmesinden, oturum durumunun yönetilmesinden ve yanıtların oluşturulmasından sorumludur. Twilio.AspNet.Core kitaplığı tarafından sağlanan ve TwiML yöntemine erişmenizi sağlayan TwilioController sınıfından miras alır. Yanıt vermek için bu yöntemi kullanabilirsiniz. Twilio İşaretleme Dili olan TwiML . TriviaController sınıfı, oturumla etkileşim kurmak için HttpContext.Session yöntemlerini kullanır.

Geçerli girişler, StartCommands ve OptionValues salt okunur dizilerindeki öğelerdir. Kullanıcının doğru bir giriş gönderdiğinden emin olmak için gelen mesajın gövdesi bu öğelerle karşılaştırılır, aksi takdirde kullanıcıya oyunun mevcut durumuna göre doğru girişi yapmasını isteyen bir mesaj gönderilir. “SessionKey” ön ekine sahip diğer alanlar, programdaki oturum anahtarlarına özel sabit dizileri tanımlamak için kullanılır.


Index yöntemi, WhatsApp'tan /Trivia yolu aracılığıyla gelen HTTP POST isteklerini işleyen ana eylem yöntemidir. Oturum verilerini HttpContext.Session.LoadAsync() kullanarak yükler ve HttpContext.Session.GetString() ve HttpContext.Session.GetInt32() yöntemlerini kullanarak oyun durumuna ilişkin verileri oturumdan alır.


Belirli dizelerin başında ve sonunda alt çizgi (_) ve yıldız işaretlerinin (*) kullanılması, oluşturulan WhatsApp mesajlarında sırasıyla italik ve kalın metin formatı elde etmek içindir.


TriviaController her yardımcı yöntem, sınıfın ana işlevselliğini destekleyen belirli bir görevi gerçekleştirir.

  • StartGame yöntemi trivia sorularını alarak, bunları oyuna uygun formata dönüştürerek ve oturumda saklayarak oyunu başlatır.
  • ProcessUserAnswer yöntemi kullanıcının bir soruya verdiği yanıtı işleyerek yanıtın doğru olup olmadığını belirler.
  • PresentQuestionWithOptions yöntemi, bir soruyu seçenekleriyle birlikte biçimlendirmekten ve sunmaktan sorumludur.
  • AddNewQuestionsToSession yöntemi oturumdaki soruların bir listesini saklar. Soruları JSON formatına dönüştürür ve JSON dizesini oturuma kaydeder.
  • RetrieveQuestionFromSession yöntemi, soru dizinini kullanarak oturumdan bir soruyu alır.
  • EndTrivia yöntemi trivia oyununu sonlandırmak için bir mesaj üretir. Bu yöntem aynı zamanda oyuna ilişkin oturum verilerini de kaldırır. Program.cs'deki oturum hizmetinin yapılandırmasına bağlı olarak, oturum 40 saniye boyunca boşta kaldığında bu işlem otomatik olarak gerçekleşir.


Uygulamayı Test Edin

Uygulamayı test etmek için WhatsApp için Twilio Sandbox'ı kurmanız, uygulama uç noktanızı herkese açık hale getirmeniz ve uç nokta URL'sini Sandbox yapılandırmasına bir web kancası olarak eklemeniz gerekir.

WhatsApp için Twilio Sandbox'ı kurun

Şuraya git: Twilio Konsolu Mesaj > Deneyin > WhatsApp Mesajı Gönder seçeneğine gidin.


Twilio Konsolu


WhatsApp sanal alanıyla başarılı bir bağlantı oluşturmak için cihazınızdan verilen Twilio numarasına bir WhatsApp mesajı göndererek sanal alana bağlanmak için sayfadaki talimatları izleyin. Benzer şekilde uygulamanızı kendi numaralarıyla test etmek isteyen diğer kişilerin de aynı prosedürü izlemesi gerekecektir.

Test için ngrok kullanarak web kancanızı gösterin

Şimdi, bir kabuk terminali açın ve ngrok'u başlatmak ve yerel ASP.NET Core uygulamanızı ortaya çıkarmak için <localhost-url> yerine başlangıçta kopyaladığınız localhost'un tam URL'sini koymak için aşağıdaki komutu çalıştırın:


 ngrok http <localhost-url>


ngrok, istekleri yerel ASP.NET uygulamanıza ileten genel bir URL oluşturacaktır. Ngrok terminal penceresinde Yönlendirme etiketli yönlendirme URL'sini arayın ve kopyalayın.


Yönlendirme URL'si


Twilio WhatsApp'ı Deneyin sayfasına geri dönün, Sandbox Ayarları'na tıklayın ve Uç noktadaki mesaj geldiğinde URL'yi ngrok artı /Trivia rotası tarafından oluşturulan yönlendirme URL'si ile değiştirin ve yöntemin POST olarak ayarlandığından emin olun. Daha sonra yeni korumalı alan yapılandırmasını kaydetmek için Kaydet'i tıklayın.


Twilio Korumalı Alanı


Proje Demosu

ASP.NET Core projenizi aşağıdaki komutu kullanarak çalıştırın:


 dotnet run


Şimdi, ilk görüşmede Twilio Sandbox numarasıyla bir mesaj göndererek uygulamanızı test edin.


Uygulamanızı WhatsApp'ta Test Etme


Çözüm

Twilio platformunun ve WhatsApp'ın gücünden yararlanarak, kullanıcıların keyif alabileceği sürükleyici bir bilgi oyunu deneyimi yarattınız. Ayrıca oturumlardaki verileri nasıl kaydedeceğinizi ve alacağınızı da öğrendiniz.


Bu projenin geliştirilebilmesinin birkaç yolu vardır. Zamanlayıcı ekleyerek, istisnaları ele alarak, kullanıcıların zorluk seçmesine izin vererek ve seçilen zorluğu Trivia API URL'si (örn. https://the-trivia-api.com/api/questions?difficulty=hard ). Ayrıca kullanıcıların WhatsApp aracılığıyla anket doldurmasına olanak tanıyan bir çözüm oluşturma olasılığını da keşfedebilirsiniz.