mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-22 07:15:25 +00:00
Quran API (#205)
* Add basic version of a Quran API * remove examples json swp * fix search translation * add examples json
This commit is contained in:
197
quran/handler/quran.go
Normal file
197
quran/handler/quran.go
Normal file
@@ -0,0 +1,197 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user