mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-12 03:05:14 +00:00
* Add basic version of a Quran API * remove examples json swp * fix search translation * add examples json
198 lines
5.0 KiB
Go
198 lines
5.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"github.com/micro/micro/v3/service/errors"
|
|
"github.com/micro/micro/v3/service/logger"
|
|
"github.com/micro/services/pkg/api"
|
|
"github.com/micro/services/quran/domain"
|
|
pb "github.com/micro/services/quran/proto"
|
|
)
|
|
|
|
const (
|
|
// the default api url
|
|
apiUrl = "https://api.quran.com/api/v4/"
|
|
// TODO: allow multiple translations
|
|
// the default translation id
|
|
translationId = "131,20"
|
|
// TODO: allow multiple interpretations
|
|
// the default tafsir id
|
|
tafsirId = "169"
|
|
// TODO: make configurable
|
|
arabicText = "text_imlaei"
|
|
)
|
|
|
|
type Quran struct{}
|
|
|
|
// Chapters returns a list of the chapters of the Quran
|
|
func (q *Quran) Chapters(ctx context.Context, req *pb.ChaptersRequest, rsp *pb.ChaptersResponse) error {
|
|
lang := "en"
|
|
if len(req.Language) > 0 {
|
|
lang = req.Language
|
|
}
|
|
|
|
var resp map[string][]*domain.Chapter
|
|
if err := api.Get(apiUrl+"chapters?language="+lang, &resp); err != nil {
|
|
logger.Errorf("Failed to retrieve chapters: %v", err)
|
|
return errors.InternalServerError("quran.chapters", "Failed to retrieve chapters")
|
|
}
|
|
|
|
for _, c := range resp["chapters"] {
|
|
rsp.Chapters = append(rsp.Chapters, &pb.Chapter{
|
|
Id: c.Id,
|
|
RevelationPlace: c.RevelationPlace,
|
|
RevelationOrder: c.RevelationOrder,
|
|
PrefixBismillah: c.BismillahPrefix,
|
|
Name: c.NameSimple,
|
|
ComplexName: c.NameComplex,
|
|
ArabicName: c.NameArabic,
|
|
TranslatedName: c.TranslatedName.Name,
|
|
Verses: c.VersesCount,
|
|
Pages: c.Pages,
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Retrieve the summary for a given chapter
|
|
func (q *Quran) Summary(ctx context.Context, req *pb.SummaryRequest, rsp *pb.SummaryResponse) error {
|
|
lang := "en"
|
|
if len(req.Language) > 0 {
|
|
lang = req.Language
|
|
}
|
|
if req.Chapter <= 0 {
|
|
return errors.BadRequest("quran.chapter-summary", "require chapter id")
|
|
}
|
|
|
|
var resp map[string]*domain.ChapterInfo
|
|
uri := fmt.Sprintf(apiUrl+"chapters/%d/info?language=%s", req.Chapter, lang)
|
|
|
|
if err := api.Get(uri, &resp); err != nil {
|
|
logger.Errorf("Failed to retrieve chapter info: %v", err)
|
|
return errors.InternalServerError("quran.chapter-summary", "Failed to retrieve chapter summary")
|
|
}
|
|
|
|
info := resp["chapter_info"]
|
|
rsp.Chapter = info.ChapterId
|
|
rsp.Summary = info.ShortText
|
|
rsp.Source = info.Source
|
|
rsp.Text = info.Text
|
|
|
|
return nil
|
|
}
|
|
|
|
// Return the verses by chapter
|
|
func (q *Quran) Verses(ctx context.Context, req *pb.VersesRequest, rsp *pb.VersesResponse) error {
|
|
lang := "en"
|
|
if len(req.Language) > 0 {
|
|
lang = req.Language
|
|
}
|
|
|
|
if req.Chapter <= 0 {
|
|
return errors.BadRequest("quran.verses", "require chapter id")
|
|
}
|
|
|
|
// TODO: enable configuring translations
|
|
// comma separated list of resource ids
|
|
// https://quran.api-docs.io/v4/resources/translations
|
|
translations := translationId
|
|
// TODO: enable configuring tafirs
|
|
// https://api.quran.com/api/v4/resources/tafsirs
|
|
tafsirs := tafsirId
|
|
|
|
uri := fmt.Sprintf(apiUrl+"verses/by_chapter/%d?language=%s", req.Chapter, lang)
|
|
|
|
// additional fields we require
|
|
// arabic text in imlaei script
|
|
uri += "&fields=" + arabicText
|
|
|
|
uri += "&words=true"
|
|
uri += "&word_fields=code_v2,text_imlaei"
|
|
|
|
if len(translations) > 0 && req.Translate {
|
|
uri += "&translations=" + translations
|
|
uri += "&translation_fields=resource_name"
|
|
}
|
|
|
|
if len(tafsirs) > 0 && req.Interpret {
|
|
uri += "&tafsirs=" + tafsirs
|
|
}
|
|
|
|
if req.Page > 0 {
|
|
uri += fmt.Sprintf("&page=%d", req.Page)
|
|
}
|
|
|
|
if req.Limit > 0 {
|
|
uri += fmt.Sprintf("&per_page=%d", req.Limit)
|
|
}
|
|
|
|
var resp *domain.VersesByChapter
|
|
|
|
if err := api.Get(uri, &resp); err != nil {
|
|
logger.Errorf("Failed to retrieve verses: %v", err)
|
|
return errors.InternalServerError("quran.verses", "Failed to retrieve verses")
|
|
}
|
|
|
|
rsp.Chapter = req.Chapter
|
|
rsp.Page = resp.Pagination.CurrentPage
|
|
rsp.TotalPages = resp.Pagination.TotalPages
|
|
|
|
for _, verse := range resp.Verses {
|
|
v := domain.VerseToProto(verse)
|
|
// strip words if not asked for
|
|
if req.Words != true {
|
|
v.Words = nil
|
|
}
|
|
rsp.Verses = append(rsp.Verses, v)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Return the search results for a given query
|
|
func (q *Quran) Search(ctx context.Context, req *pb.SearchRequest, rsp *pb.SearchResponse) error {
|
|
if len(req.Query) == 0 {
|
|
return errors.BadRequest("quran.search", "missing search query")
|
|
}
|
|
|
|
lang := "en"
|
|
if len(req.Language) > 0 {
|
|
lang = req.Language
|
|
}
|
|
|
|
if req.Limit <= 0 {
|
|
req.Limit = 20
|
|
}
|
|
|
|
qq := url.Values{}
|
|
qq.Set("q", req.Query)
|
|
qq.Set("size", fmt.Sprintf("%d", req.Limit))
|
|
qq.Set("page", fmt.Sprintf("%d", req.Page))
|
|
qq.Set("language", lang)
|
|
|
|
uri := fmt.Sprintf(apiUrl+"search?%s", qq.Encode())
|
|
|
|
var resp map[string]*domain.SearchResults
|
|
|
|
if err := api.Get(uri, &resp); err != nil {
|
|
logger.Errorf("Failed to retrieve search results: %v", err)
|
|
return errors.InternalServerError("quran.search", "Failed to retrieve search results")
|
|
}
|
|
|
|
rsp.Query = req.Query
|
|
rsp.Page = resp["search"].CurrentPage
|
|
rsp.TotalPages = resp["search"].TotalPages
|
|
rsp.TotalResults = resp["search"].TotalResults
|
|
|
|
for _, result := range resp["search"].Results {
|
|
r := domain.ResultToProto(result)
|
|
rsp.Results = append(rsp.Results, r)
|
|
}
|
|
|
|
return nil
|
|
}
|