dorar_hadith 0.1.0 copy "dorar_hadith: ^0.1.0" to clipboard
dorar_hadith: ^0.1.0 copied to clipboard

A comprehensive Dart library for accessing Dorar.net hadith database. Search hadiths, get explanations (sharh), browse scholars, books, and narrators. Includes offline reference data for 688 books, 20 [...]

بسم الله الرحمن الرحيم #

Change Language: 🇺🇸 EN #


درر الحديث - Dorar Hadith #

مكتبة بلغة Dart تهدف إلى تسهيل التعامل والحصول على الأحاديث ومتعلقاتها من خلال موقع الدرر السنية.

مستوحاة وكثير من اجزاءها مبني على مستودع dorar-hadith-api من الأخ: أحمد الطبراني. تعمل المكتبة على كل برمجيات Dart دون الحاجة إلى Flutter.

pub package License: MIT

مزايا المكتبة #

  • البحث عن الأحاديث بسرعة مع إمكانية الفلترة بحسب الراوي، الكتاب، الصحة، الراوي والمزيد.
  • الحصول على بيانات تفصيلة للحديث.
  • إمكانية البحث والحصول على الشرح للأحاديث.
  • البحث عن الأحاديث المشابه او البديل الصحيح.
  • البحث في الكتب، والرواة والمحديثين المتوفرين لفلترة النتائج بدون اتصال بالإنترنت.

إمكانيات البحث #

  • البحث بنص (متن) الحديث.
  • فلترة بصحة الحديث.
  • فلترة بالمحدثين.
  • فلترة بالرواة.
  • فلترة بالكتب.
  • فلترة بنوع الحديث (قدسي، أثر، إلخ).
  • بيانات لترقيم الصفحات.

التثبيت #

قم بتشغيل الأمر التالي :

dart pub add dorar_hadith

أو بإستخدام Flutter :

flutter pub add dorar_hadith

بداية سريعة #

import 'package:dorar_hadith/dorar_hadith.dart';

void main() async {
  // Create the client
  final client = DorarClient();

  try {
    // Search for hadiths about prayer
    final results = await client.searchHadith(
      HadithSearchParams(value: 'الصلاة', page: 1),
    );

    print('Found ${results.data.length} hadiths');

    // Print first hadith
    if (results.data.isNotEmpty) {
      final hadith = results.data.first;
      print('Hadith: ${hadith.hadith}');
      print('Narrator: ${hadith.rawi}');
      print('Scholar: ${hadith.mohdith}');
      print('Grade: ${hadith.grade}');
    }
  } on DorarException catch (e) {
    print('Error: ${getExceptionMessage(e)}');
  } finally {
    // Clean up resources (important: closes database connections)
    await client.dispose();
  }
}

لرؤية مثال كامل يتطرق لكل مزايا المكتبة انظر هنا: example/example.dart

طريقة الإستخدام #

ملاحظة مهمة #

أغلب العمليات في DorarClient والخدمات الباقية تعيد النتائج داخل Object بإسم ApiResponse وهذا لتسهيل عملية ترقيم الصفحات. يحتوي ApiResponse على عضوين:

  • الناتج: data
  • بيانات الترقيم: SearchMetadata وذلك لتسهيل عملية طلب بيانات جديدة عند الحاجة كالذهاب للصفحة التالية.

بحث سريع في الأحاديث #

البحث عن طريق client.searchHadith سريع لكن معلومات الحديث تكون ناقصة وبدون معرفات (hadithId, bookId, etc).

  • عدد النتائج لا يتجاوز 15 حديث، كما يمكن استخدام الفلاتر بلا إشكال.
  • نتائج البحث تحتوي على المعلومات التالية:
  • متن(نص) الحديث: Hadith.hadith
  • الراوي: Hadith.rawi
  • المحدث: Hadith.mohdith
  • الكتاب المأخوذ منه الحديث:Hadith.book
  • رقم الحديث او الصفحة في الكتاب أعلاه: Hadith.numberOrPage
  • درجة صحة الحديث: Hadith.grade
final results = await client.searchHadith(
  HadithSearchParams(value: 'الإيمان'),
);

for (var hadith in results.data) {
  print('${hadith.hadith}');
  print('Grade: ${hadith.grade}');
}

البحث المفصل مع الفلترة #

ملاحظة: بسبب طريقة عمل موقع الدرر السنية، حكم الحديث في البحث المفصل يظهر في explainGrade، ليس في grade.


final params = HadithSearchParams(
  value: 'الصيام',
  page: 1,
  degrees: [HadithDegree.authenticHadith], // الأحاديث الصحيحة فقط
  mohdith: [MohdithReference.bukhari],
  searchMethod: SearchMethod.anyWord,
  zone: SearchZone.qudsi,
);

final results = await client.searchHadithDetailed(params);

البحث عن حديث بالمعرف (ID) #

final hadith = await client.getHadithById('12345');
print('Hadith: ${hadith.hadith}');
print('Book: ${hadith.book}');
print('Grade: ${hadith.grade}');

الأحاديث المشابهة، الأصول، البديل الصحيح #

ملاحظة: يوجد داخل فئة Hadith خصائص للتأكد من توفر هذه الخيارات لهذا الحديث وهي كالتالي:

  • للتأكد من وجود صحيح بديل hasAlternateHadithSahih
  • للتأكد من وجود أحاديث مشابهة hasSimilarHadith
  • للتأكد من وجود الأصول hasUsulHadith
// الحصول على حديث مشابه
final similar = await client.hadith.getSimilar('12345');

// الحصول على البديل الصحيح
final alternate = await client.hadith.getAlternate('12345');

// الحصول على الأصول
final usul = await client.hadith.getUsul('12345');
print('Main hadith: ${usul.hadith.hadith}');
print('Sources: ${usul.count}');

البحث عن الشرح #

ملاحظة: عند البحث بإستخدام client.searchHadithDetailed وفي حال وجود حديث له شرح ستجد معرف الشرح داخل خصائص الحديث في عضو بإسم sharhMetadata، وتوجد خصائص للتأكد من وجود الشرح لهذا الحديث، في حال وجود الشرح ستجد المعرف قم بتمرير المعرف كما في المثال التالي:

// الحصول على الشرح بالمعرف
final sharh = await client.sharh.getById('789');

// البحث بنص الشرح
final sharhByText = await client.sharh.getByText('إنما الأعمال بالنيات');

بيانات المرجعية (لا تحتاج إلى اتصال بالشبكة) #

هذه البيانات تستخدم في عملية الفلترة، كالبحث عن محدث معين او كتاب معين او راوي معين ثم تمريره في عملية البحث عن الحديث. وجعلت هذه العملية على الجهاز لكثرة البيانات ولجعل الوصول لها سهلًا.

ملاحظة: القيم المرجعية تحتوي فقط على معرف المرجع id واسم المرجع مثال: صحيح البخاري، حتى تحصل على تفاصيل هذا المرجع يجب ان تقوم بطلبها راجع: [[#الحصول على تفاصيل المحدث او الكتاب]] .

البحث في المحدثين

// البحث بالإسم
final bukhari = await client.mohdithRef.searchMohdith('البخاري');

// البحث بالمعرف
final scholar = await client.mohdithRef.getMohdithById('256');

// عرض الجميع مع الترقيم
final allScholars = await client.mohdithRef.getAllMohdith(limit: 50);

// الحصول على اكثر من قيمة من اكثر من معرف
final scholars = await client.mohdithRef.getMohdithByIds(['256', '179']);

// اختصار للبحث في المحدثين بدون الدخول في mohdithRef
final results = await client.searchMohdith('أحمد');

البحث في الكتب

// البحث بالإسم
final sahihBooks = await client.bookRef.searchBook('صحيح');

// البحث بالمعرف
final book = await client.bookRef.getBookById('6216');

// عرض الجميع مع الترقيم
final allBooks = await client.bookRef.getAllBooks(limit: 100, offset: 0);

// اختصار للبحث في الكتب بدون الدخول في bookRef
final results = await client.searchBooks('سنن');

البحث في الرواة

// البحث بالإسم 
final narrators = await client.rawiRef.searchRawi('أبو هريرة', limit: 10);

// البحث بالمعرف
final abuHurayrah = await client.rawiRef.getRawiById(4396);

// عرض الجميع مع الترقيم
final page1 = await client.rawiRef.getAllRawi(limit: 50, offset: 0);

// عدد النتائج
final total = await client.rawiRef.countRawi();
final searchCount = await client.rawiRef.countRawi(query: 'عبد الله');

// اختصار للبحث في الرواة بدون الدخول في rawiRef
final results = await client.searchRawi('عمر');

// مهم: التخلص من الوسيط بعد الإنتهاء لتفادي بعض الإنذارات والأخطاء
await client.dispose();

قيم ثابتة

حتى يسهل الفلترة بالكتب والرواة والمحدثين معروفين دون الحاجة على البحث عنهم كل مرة قمت بوضع ما اشتهر من هذه القيم كقيم جاهزة دون الحاجة للبحث، في الكتب مثلًا ستجد صحيح البخاري وصحيح مسلم وغيرهم. في حال رغبة بإضافة قيم اخرى ثابتة يرجع فتح Issue على Github

// مثال على قيم المحدثين الثابتة
MohdithReference.bukhari  
MohdithReference.muslim     
MohdithReference.abuDawud   
// ... 17 المجموع

// مثال على قيم الكتب الثابتة
BookReference.sahihBukhari  
BookReference.sahihMuslim     
// ... 20 المجموع

// مثال على قيم الرواة الثابتة
RawiReference.abuHurayrah     
RawiReference.aisha          
// ... 21 المجموع

// استخدام القيم هذه في الفلترة
final params = HadithSearchParams(
  value: 'الصلاة',
  page: 1,
  mohdith: [MohdithReference.Bukhari],
  books: [BookReference.sahihBukhari],
);
final results = await client.hadith.searchViaSite(params);

الحصول على تفاصيل المحدث او الكتاب #

// الحصول على تفاصيل الكتاب من API
final book = await client.book.getById('123');
print('Book: ${book.name}');
print('Author: ${book.author}');

// الحصول على تفاصيل المحدث من API
final scholar = await client.mohdith.getById('456');
print('Name: ${scholar.name}');
print('Bio: ${scholar.info}');

الخيارات المتاحة #

في هذا القسم سنتعرف على جميع الكائنات (Models) والخيارات المتاحة في المكتبة بشكل تفصيلي.

كائن الحديث (Hadith Model) #

الكائن الرئيسي الذي يمثل الحديث مع جميع معلوماته وبياناته المرتبطة به.

class Hadith {
  // المعلومات الأساسية للحديث
  final String hadith;              // نص (متن) الحديث
  final String? hadithId;           // المعرف الفريد للحديث
  
  // معلومات الإسناد
  final String rawi;                // اسم الراوي
  final String mohdith;             // اسم المحدث (العالم)
  final String? mohdithId;          // معرف المحدث
  
  // معلومات المصدر
  final String book;                // اسم الكتاب المصدر
  final String? bookId;             // معرف الكتاب
  final String numberOrPage;        // رقم الصفحة أو رقم الحديث في الكتاب
  
  // معلومات الصحة والتخريج
  final String grade;               // درجة صحة الحديث (صحيح، ضعيف، إلخ)
  final String? explainGrade;       // شرح تفصيلي لدرجة الحديث
  final String? takhrij;            // معلومات التخريج (المصادر الأخرى)
  
  // العلاقات والروابط
  final bool hasSimilarHadith;           // هل يوجد أحاديث مشابهة؟
  final bool hasAlternateHadithSahih;    // هل يوجد بديل صحيح؟
  final bool hasUsulHadith;              // هل يوجد أصول للحديث؟
  
  // روابط موقع الدرر السنية
  final String? similarHadithDorar;        // رابط الأحاديث المشابهة
  final String? alternateHadithSahihDorar; // رابط البديل الصحيح
  final String? usulHadithDorar;           // رابط أصول الحديث
  
  // معلومات الشرح
  final bool hasSharhMetadata;      // هل يوجد شرح متاح؟
  final SharhMetadata? sharhMetadata; // بيانات الشرح (إن وجد)
}

ملاحظات مهمة:

  • استخدم hasSimilarHadith للتأكد من وجود أحاديث مشابهة قبل طلبها عبر client.hadith.getSimilar()
  • استخدم hasAlternateHadithSahih للتأكد من وجود بديل صحيح قبل طلبه عبر client.hadith.getAlternate()
  • استخدم hasUsulHadith للتأكد من وجود أصول قبل طلبها عبر client.hadith.getUsul()
  • استخدم hasSharhMetadata للتأكد من وجود شرح، وإذا كان موجودًا ستجد sharhMetadata.id

كائن الشرح (Sharh Model) #

يمثل الحديث مع شرحه التفصيلي.

class Sharh {
  // معلومات الحديث الأساسية
  final String hadith;              // نص الحديث
  final String rawi;                // الراوي
  final String mohdith;             // المحدث
  final String book;                // الكتاب المصدر
  final String numberOrPage;        // رقم الصفحة/الحديث
  final String grade;               // درجة الحديث
  final String? takhrij;            // التخريج
  
  // معلومات الشرح
  final bool hasSharhMetadata;      // هل يوجد شرح؟
  final SharhMetadata? sharhMetadata; // بيانات الشرح
  
  // خاصية مساعدة للحصول على نص الشرح مباشرة
  String? get sharhText => sharhMetadata?.sharh;
}

استخدام:

final sharh = await client.sharh.getById('789');
if (sharh.hasSharhMetadata && sharh.sharhText != null) {
  print('الشرح: ${sharh.sharhText}');
}

معلومات الشرح (SharhMetadata) #

يحتوي على التفاصيل الخاصة بالشرح.

class SharhMetadata {
  final String id;                  // معرف الشرح
  final bool isContainSharh;        // هل يحتوي على نص الشرح؟
  final String? sharh;              // نص الشرح (إن وجد)
}

أصول الحديث (UsulHadith Model) #

يمثل الحديث مع جميع مصادره وأصوله.

class UsulHadith {
  final Hadith hadith;              // الحديث الأساسي
  final List<UsulSource> sources;   // قائمة جميع المصادر
  final int count;                  // عدد المصادر
}

// مصدر واحد من أصول الحديث
class UsulSource {
  final String source;              // اسم المصدر والصفحة
  final String chain;               // سلسلة الإسناد
  final String hadithText;          // نص الحديث في هذا المصدر
}

مثال للاستخدام:

final usulResponse = await client.hadith.getUsul('12345');
final usul = usulResponse.data;

print('عدد المصادر: ${usul.count}');
for (var source in usul.sources) {
  print('المصدر: ${source.source}');
  print('الإسناد: ${source.chain}');
}

معلومات الكتاب (BookInfo) #

يحتوي على التفاصيل الكاملة للكتاب (يُستخدم عبر API).

class BookInfo {
  final String name;                // اسم الكتاب
  final String bookId;              // المعرف الفريد
  final String author;              // المؤلف
  final String reviewer;            // المحقق
  final String publisher;           // الناشر
  final String edition;             // رقم الطبعة
  final String editionYear;         // سنة الطبعة
}

الحصول على معلومات كتاب:

final book = await client.book.getById('6216');
print('${book.name} - ${book.author}');
print('الناشر: ${book.publisher}');

معلومات المحدث (MohdithInfo) #

يحتوي على التفاصيل الكاملة للمحدث (يُستخدم عبر API).

class MohdithInfo {
  final String name;                // اسم المحدث
  final String mohdithId;           // المعرف الفريد
  final String info;                // السيرة الذاتية والمعلومات التفصيلية
}

الحصول على معلومات محدث:

final mohdith = await client.mohdith.getById('256');
print('الاسم: ${mohdith.name}');
print('نبذة: ${mohdith.info}');

القيم المرجعية (Reference Items) #

القيم المرجعية هي بيانات خفيفة تُستخدم للبحث والفلترة بدون الحاجة للإنترنت. جميعها تمتد من ReferenceItem.

الكتب المرجعية (BookItem)

class BookItem extends ReferenceItem {
  final String id;                  // معرف الكتاب
  final String name;                // اسم الكتاب
  final String? author;             // اسم المؤلف (إن وُجد)
  final String? mohdithId;          // معرف المحدث المؤلف
  final String? category;           // التصنيف (إن وُجد)
}

استخدام:

// البحث في الكتب (بدون إنترنت)
final books = await client.bookRef.searchBook('صحيح', limit: 10);
for (var book in books) {
  print('${book.name} - ${book.author}');
  
  // للحصول على تفاصيل كاملة (يحتاج إنترنت)
  final fullInfo = await client.book.getById(book.id);
}

المحدثين المرجعيين (MohdithItem)

class MohdithItem extends ReferenceItem {
  final String id;                  // معرف المحدث
  final String name;                // اسم المحدث
  final int? deathYear;             // سنة الوفاة بالهجري (إن وُجدت)
  final String? era;                // الحقبة الزمنية (إن وُجدت)
}

استخدام:

// البحث في المحدثين (بدون إنترنت)
final scholars = await client.mohdithRef.searchMohdith('البخاري', limit: 5);
for (var scholar in scholars) {
  print('${scholar.name}');
  if (scholar.deathYear != null) {
    print('توفي سنة: ${scholar.deathYear}هـ');
  }
}

الرواة المرجعيين (RawiItem)

class RawiItem extends ReferenceItem {
  final String id;                  // معرف الراوي
  final String name;                // اسم الراوي
}

استخدام:

// البحث في الرواة (بدون إنترنت)
final narrators = await client.rawiRef.searchRawi('أبو هريرة', limit: 3);
for (var narrator in narrators) {
  print(narrator.name);
}

// عد النتائج
final total = await client.rawiRef.countRawi();
final searchCount = await client.rawiRef.countRawi(query: 'عبد الله');

بيانات الاستجابة (ApiResponse) #

جميع عمليات البحث والاسترجاع تُرجع النتائج داخل ApiResponse لتسهيل ترقيم الصفحات وإدارة البيانات.

class ApiResponse<T> {
  final T data;                     // البيانات الفعلية (حديث، قائمة أحاديث، إلخ)
  final SearchMetadata metadata;    // معلومات إضافية عن النتيجة
}

أمثلة للاستخدام:

// البحث يُرجع ApiResponse<List<Hadith>>
final response = await client.searchHadith(
  HadithSearchParams(value: 'الصلاة', page: 1),
);

print('عدد النتائج: ${response.data.length}');
print('الصفحة الحالية: ${response.metadata.page}');
print('من الكاش: ${response.metadata.isCached}');

// أصول الحديث تُرجع ApiResponse<UsulHadith>
final usulResponse = await client.hadith.getUsul('12345');
print('عدد المصادر: ${usulResponse.data.count}');

بيانات البحث الوصفية (SearchMetadata) #

يحتوي على معلومات إضافية عن نتيجة البحث.

class SearchMetadata {
  final int length;                      // عدد النتائج المُرجعة
  final int? page;                       // رقم الصفحة الحالية
  final bool? removeHtml;                // هل تم إزالة وسوم HTML؟
  final bool? specialist;                // هل تشمل الأحاديث المتخصصة؟
  final int? numberOfNonSpecialist;      // عدد الأحاديث غير المتخصصة
  final int? numberOfSpecialist;         // عدد الأحاديث المتخصصة
  final bool isCached;                   // هل النتيجة من الكاش؟
  final int? usulSourcesCount;           // عدد المصادر (لطلبات أصول الحديث)
  
  // دالة لإنشاء نسخة معدلة
  SearchMetadata copyWith({...});
}

استخدام:

final response = await client.searchHadith(params);
final meta = response.metadata;

if (meta.isCached) {
  print('النتيجة من الكاش - سريعة!');
}

print('الصفحة ${meta.page} من أصل ???');
print('النتائج: ${meta.length}');

معايير البحث (HadithSearchParams) #

يحتوي على جميع معايير وفلاتر البحث عن الأحاديث.

class HadithSearchParams {
  // إلزامي
  final String value;                    // نص البحث (كلمات الحديث)
  
  // اختياري - خيارات البحث
  final int page;                        // رقم الصفحة (افتراضي: 1)
  final bool removeHtml;                 // إزالة وسوم HTML (افتراضي: true)
  final bool specialist;                 // تضمين الأحاديث المتخصصة (افتراضي: false)
  final String? exclude;                 // كلمات أو عبارات للاستبعاد
  
  // اختياري - الفلاتر
  final SearchMethod? searchMethod;      // طريقة البحث (جميع/أي/مطابق)
  final SearchZone? zone;                // نوع الحديث (مرفوع/قدسي/آثار/شرح)
  final List<HadithDegree>? degrees;     // فلترة بدرجة الصحة
  final List<MohdithReference>? mohdith; // فلترة بالمحدثين
  final List<BookReference>? books;      // فلترة بالكتب
  final List<RawiReference>? rawi;       // فلترة بالرواة
  
  // دالة لإنشاء نسخة معدلة
  HadithSearchParams copyWith({...});
}

أمثلة الاستخدام:

// بحث بسيط (الحد الأدنى)
final simple = HadithSearchParams(value: 'الصلاة', page: 1);

// بحث مع فلاتر محددة
final filtered = HadithSearchParams(
  value: 'الإيمان',
  page: 1,
  degrees: [HadithDegree.authenticHadith],      // صحيح فقط
  mohdith: [MohdithReference.bukhari],          // البخاري فقط
  books: [BookReference.sahihBukhari],          // صحيح البخاري فقط
  searchMethod: SearchMethod.allWords,          // جميع الكلمات
  zone: SearchZone.qudsi,                       // أحاديث قدسية
);

// بحث متقدم مع استبعاد كلمات
final advanced = HadithSearchParams(
  value: 'الجنة النار',
  page: 1,
  exclude: 'الدنيا',                           // استبعاد كلمة "الدنيا"
  degrees: [
    HadithDegree.authenticHadith,
    HadithDegree.authenticChain,
  ],
  mohdith: [
    MohdithReference.bukhari,
    MohdithReference.muslim,
  ],
  searchMethod: SearchMethod.anyWord,           // أي كلمة
  removeHtml: true,                             // إزالة HTML
);

// تعديل معايير موجودة
final modified = simple.copyWith(
  page: 2,                                      // الانتقال للصفحة الثانية
  degrees: [HadithDegree.authenticHadith],     // إضافة فلتر
);

final results = await client.searchHadithDetailed(advanced);

درجات صحة الحديث (HadithDegree) #

قيم ثابتة لدرجات صحة الأحاديث حسب أحكام المحدثين.

enum HadithDegree {
  all,                   // جميع الدرجات (بدون فلتر)
  authenticHadith,       // أحاديث حكم المحدثون عليها بالصحة
  authenticChain,        // أحاديث حكم المحدثون على أسانيدها بالصحة
  weakHadith,            // أحاديث حكم المحدثون عليها بالضعف
  weakChain,             // أحاديث حكم المحدثون على أسانيدها بالضعف
  
  // كل قيمة لها:
  final String id;       // المعرف للاستخدام في API
  final String label;    // الوصف العربي
}

استخدام:

// فلترة بالأحاديث الصحيحة فقط
final params = HadithSearchParams(
  value: 'الصدقة',
  page: 1,
  degrees: [HadithDegree.authenticHadith],
);

// الأحاديث الصحيحة (الحديث أو السند)
final params2 = HadithSearchParams(
  value: 'الصدقة',
  page: 1,
  degrees: [
    HadithDegree.authenticHadith,
    HadithDegree.authenticChain,
  ],
);

// استخدام الدالات المساعدة
print(HadithDegree.authenticHadith.toString()); // يطبع الوصف العربي
print(HadithDegree.authenticHadith.toQueryParam()); // يطبع المعرف للـAPI

طرق البحث (SearchMethod) #

تحدد كيفية البحث في نص الحديث.

enum SearchMethod {
  allWords,                     // جميع الكلمات (AND)
  anyWord,                      // أي كلمة (OR)
  exactMatch,                   // بحث مطابق (عبارة كاملة)
  
  // كل قيمة لها:
  final String id;              // المعرف للاستخدام في API
  final String label;           // الوصف العربي
}

استخدام:

// البحث عن جميع الكلمات (AND)
final allWords = HadithSearchParams(
  value: 'الصلاة الزكاة',
  page: 1,
  searchMethod: SearchMethod.allWords, // أحاديث تحتوي "الصلاة" و"الزكاة" معًا
);

// البحث عن أي كلمة (OR)
final anyWord = HadithSearchParams(
  value: 'الصلاة الزكاة',
  page: 1,
  searchMethod: SearchMethod.anyWord,  // أحاديث تحتوي "الصلاة" أو "الزكاة"
);

// البحث المطابق (العبارة كاملة)
final exact = HadithSearchParams(
  value: 'إنما الأعمال بالنيات',
  page: 1,
  searchMethod: SearchMethod.exactMatch, // العبارة كاملة تمامًا
);

// استخدام الدالات المساعدة
print(SearchMethod.allWords.toString()); // "جميع الكلمات"
print(SearchMethod.allWords.toQueryParam()); // "w"

مناطق البحث (SearchZone) #

تحدد تصنيف نوع الحديث للفلترة.

enum SearchZone {
  all,                          // جميع الأحاديث (بدون فلتر)
  marfoo,                       // الأحاديث المرفوعة (المنسوبة للنبي ﷺ)
  qudsi,                        // الأحاديث القدسية (من الله تعالى)
  sahabaAthar,                  // آثار الصحابة
  sharh,                        // شروح الأحاديث
  
  // كل قيمة لها:
  final String id;              // المعرف للاستخدام في API
  final String label;           // الوصف العربي
}

استخدام:

// البحث في الأحاديث القدسية فقط
final qudsi = HadithSearchParams(
  value: 'الجنة',
  page: 1,
  zone: SearchZone.qudsi,
);

// البحث في الأحاديث المرفوعة
final marfoo = HadithSearchParams(
  value: 'الصلاة',
  page: 1,
  zone: SearchZone.marfoo,
);

// البحث في آثار الصحابة
final athar = HadithSearchParams(
  value: 'عمر بن الخطاب',
  page: 1,
  zone: SearchZone.sahabaAthar,
);

// استخدام الدالات المساعدة
print(SearchZone.qudsi.toString()); // "الأحاديث القدسية"
print(SearchZone.qudsi.toQueryParam()); // "1"

إعدادات العميل (Client Options) #

يمكنك تخصيص DorarClient عند إنشائه.

final client = DorarClient(
  timeout: Duration(seconds: 15),       // مهلة الطلبات (افتراضي: 15 ثواني)
  enableCache: true,                    // تفعيل الكاش (افتراضي: true)
  cacheTtl: Duration(hours: 24),       // مدة بقاء الكاش (افتراضي: 24 ساعة)
);

إدارة الكاش #

// الحصول على إحصائيات الكاش
final stats = client.getCacheStats();
print('إجمالي العناصر: ${stats.totalEntries}');
print('العناصر الصالحة: ${stats.validEntries}');
print('معدل الإصابة: ${(stats.hitRate * 100).toStringAsFixed(1)}%');

// مسح كل الكاش
client.clearCache();

// مسح كاش خدمة معينة
client.hadith.clearCache();
client.sharh.clearCache();
client.book.clearCache();

التخلص من الموارد #

مهم جدًا: يجب دائمًا استدعاء dispose() عند الانتهاء من استخدام DorarClient لإغلاق اتصالات قاعدة البيانات وتجنب التحذيرات.

void main() async {
  final client = DorarClient();
  
  try {
    // استخدام المكتبة
    final results = await client.searchHadith(
      HadithSearchParams(value: 'الصلاة', page: 1),
    );
  } finally {
    // التخلص من الموارد (إلزامي)
    await client.dispose();
  }
}

معالجة الأخطاء (Error Handling) #

المكتبة تستخدم sealed class لتمثيل الأخطاء، مما يجعل التعامل معها أكثر أمانًا ودقة باستخدام Pattern Matching.

أنواع الأخطاء (DorarException)

جميع الأخطاء في المكتبة ترث من DorarException وهو sealed class يحتوي على الأنواع التالية:

// 1. خطأ الشبكة - مشكلة في الاتصال بالإنترنت
DorarNetworkException {
  final String message;
  final String? details;
}

// 2. انتهاء المهلة - الطلب استغرق وقتًا طويلاً
DorarTimeoutException {
  final String message;
  final Duration timeout;
  final String? details;
}

// 3. غير موجود - المورد المطلوب غير متوفر
DorarNotFoundException {
  final String message;
  final String resource;
  final String? details;
}

// 4. خطأ في التحقق - المدخلات غير صحيحة
DorarValidationException {
  final String message;
  final String? field;        // اسم الحقل الذي به خطأ
  final String? rule;         // القاعدة المخالفة
  final String? details;
}

// 5. خطأ السيرفر - مشكلة في خادم الدرر السنية
DorarServerException {
  final String message;
  final int statusCode;       // رمز حالة HTTP
  final String? details;
}

// 6. خطأ في المعالجة - مشكلة في تحليل الاستجابة
DorarParseException {
  final String message;
  final String? expectedType; // النوع المتوقع
  final String? details;
}

// 7. تجاوز الحد - عدد طلبات كثير جدًا
DorarRateLimitException {
  final String message;
  final int? limit;           // الحد الأقصى للطلبات
  final DateTime? resetAt;    // وقت إعادة التفعيل
  final String? details;
}

معالجة شاملة باستخدام Switch Expression

أفضل طريقة للتعامل مع الأخطاء هي استخدام Pattern Matching مع switch، حيث يضمن المترجم (Compiler) تغطية جميع الحالات:

try {
  final results = await client.searchHadith(
    HadithSearchParams(value: 'الصلاة', page: 1),
  );
} on DorarException catch (e) {
  // Pattern Matching - المترجم يضمن تغطية كل الحالات!
  final message = switch (e) {
    DorarNetworkException() => 
      '🌐 خطأ في الشبكة: ${e.message}\n'
      'تحقق من اتصالك بالإنترنت',
      
    DorarTimeoutException() => 
      '⏱️ انتهت المهلة بعد ${e.timeout.inSeconds} ثانية\n'
      'حاول مرة أخرى',
      
    DorarNotFoundException() => 
      '🔍 غير موجود: ${e.resource}\n'
      'تأكد من صحة المعرف',
      
    DorarValidationException() => 
      '✋ خطأ في المدخلات: ${e.message}\n'
      '${e.field != null ? "الحقل: ${e.field}" : ""}',
      
    DorarServerException() => 
      '🖥️ خطأ في السيرفر (${e.statusCode}): ${e.message}',
      
    DorarParseException() => 
      '📄 خطأ في معالجة البيانات: ${e.message}',
      
    DorarRateLimitException() => 
      '🚫 تجاوزت الحد المسموح من الطلبات\n'
      '${e.resetAt != null ? "حاول مرة أخرى بعد: ${e.resetAt}" : ""}',
  };
  
  print(message);
}

دالة مساعدة لرسائل الأخطاء

المكتبة توفر دالة جاهزة لتحويل الأخطاء لرسائل مفهومة:

import 'package:dorar_hadith/dorar_hadith.dart';

try {
  final results = await client.searchHadith(params);
} on DorarException catch (e) {
  // استخدام الدالة المساعدة
  print(getExceptionMessage(e));
}

الخدمات المتاحة (Available Services) #

DorarClient يوفر الوصول إلى عدة خدمات متخصصة، كل خدمة مسؤولة عن جزء معين من الوظائف.

خدمة الأحاديث (Hadith Service) #

الخدمة الأساسية للبحث عن الأحاديث والحصول على تفاصيلها.

final client = DorarClient();

// 1. البحث السريع (عبر API - ~15 نتيجة)
final quickResults = await client.searchHadith(
  HadithSearchParams(value: 'الصلاة', page: 1),
);

// 2. البحث المفصل (عبر الموقع - ~30 نتيجة)
final detailedResults = await client.searchHadithDetailed(
  HadithSearchParams(value: 'الصلاة', page: 1),
);

// 3. الحصول على حديث بالمعرف
final hadith = await client.getHadithById('12345');

// أو استخدام الخدمة مباشرة
final sameResults = await client.hadith.searchViaApi(params);
final sameDetailed = await client.hadith.searchViaSite(params);
final sameHadith = await client.hadith.getById('12345');

// 4. الأحاديث المشابهة
if (hadith.hasSimilarHadith && hadith.hadithId != null) {
  final similar = await client.hadith.getSimilar(hadith.hadithId!);
  print('وجدنا ${similar.length} حديث مشابه');
}

// 5. البديل الصحيح
if (hadith.hasAlternateHadithSahih && hadith.hadithId != null) {
  final alternate = await client.hadith.getAlternate(hadith.hadithId!);
  if (alternate != null) {
    print('البديل الصحيح: ${alternate.hadith}');
  }
}

// 6. أصول الحديث
if (hadith.hasUsulHadith && hadith.hadithId != null) {
  final usulResponse = await client.hadith.getUsul(hadith.hadithId!);
  final usul = usulResponse.data;
  print('عدد المصادر: ${usul.count}');
  for (var source in usul.sources) {
    print('- ${source.source}: ${source.chain}');
  }
}

// 7. مسح الكاش
client.hadith.clearCache();

خدمة الشروح (Sharh Service) #

للبحث عن شروح الأحاديث والحصول عليها.

// 1. البحث في الشروح بنص الحديث
final sharh = await client.sharh.getByText('إنما الأعمال بالنيات');

// يمكن أيضًا البحث في الأحاديث المتخصصة
final specialistSharh = await client.sharh.getByText(
  'نص الحديث',
  specialist: true,
);

// 2. الحصول على شرح بالمعرف
// (المعرف يأتي من hadith.sharhMetadata.id)
final hadith = await client.getHadithById('12345');
if (hadith.hasSharhMetadata && hadith.sharhMetadata != null) {
  final sharhId = hadith.sharhMetadata!.id;
  final sharh = await client.sharh.getById(sharhId);
  
  if (sharh.sharhText != null) {
    print('الشرح: ${sharh.sharhText}');
  }
}

// 3. مسح الكاش
client.sharh.clearCache();

خدمة الكتب التفصيلية (Book Service) #

للحصول على معلومات تفصيلية عن الكتب (يحتاج إنترنت).

// الحصول على معلومات كتاب بالمعرف
final book = await client.book.getById('6216'); // صحيح البخاري

print('الكتاب: ${book.name}');
print('المؤلف: ${book.author}');
print('المحقق: ${book.reviewer}');
print('الناشر: ${book.publisher}');
print('الطبعة: ${book.edition}');
print('سنة النشر: ${book.editionYear}');

// مسح الكاش
client.book.clearCache();

خدمة المحدثين التفصيليين (Mohdith Service) #

للحصول على معلومات تفصيلية عن المحدثين (يحتاج إنترنت).

// الحصول على معلومات محدث بالمعرف
final mohdith = await client.mohdith.getById('256'); // الإمام البخاري

print('الاسم: ${mohdith.name}');
print('السيرة: ${mohdith.info}');

// مسح الكاش
client.mohdith.clearCache();

خدمة الكتب المرجعية (Book Reference Service) #

للبحث في الكتب المتوفرة (بدون إنترنت).

// 1. البحث بالاسم
final books = await client.bookRef.searchBook('صحيح', limit: 10);

// أو اختصار
final sameBooks = await client.searchBooks('صحيح');

for (var book in books) {
  print('${book.name} - ${book.author}');
}

// 2. الحصول على كتاب بالمعرف
final bukhari = await client.bookRef.getBookById('6216');
print(bukhari.name); // صحيح البخاري

// 3. الحصول على عدة كتب دفعة واحدة
final multipleBooks = await client.bookRef.getBooksByIds([
  '6216', // صحيح البخاري
  '3662', // صحيح مسلم
]);

// 4. عرض جميع الكتب مع الترقيم
final allBooks = await client.bookRef.getAllBookss(
  limit: 50,
  offset: 0,
);

// 5. عد النتائج
final totalBooks = await client.bookRef.countBooks();
final sahihBooks = await client.bookRef.countBooks(query: 'صحيح');
print('إجمالي الكتب: $totalBooks');
print('كتب "صحيح": $sahihBooks');

خدمة المحدثين المرجعيين (Mohdith Reference Service) #

للبحث في المحدثين المتوفرين (بدون إنترنت).

// 1. البحث بالاسم
final scholars = await client.mohdithRef.searchMohdith('البخاري', limit: 5);

// أو اختصار
final sameScholars = await client.searchMohdith('البخاري');

for (var scholar in scholars) {
  print('${scholar.name}');
  if (scholar.deathYear != null) {
    print('سنة الوفاة: ${scholar.deathYear}هـ');
  }
}

// 2. الحصول على محدث بالمعرف
final bukhari = await client.mohdithRef.getMohdithById('256');
print(bukhari.name); // البخاري

// 3. الحصول على عدة محدثين دفعة واحدة
final multipleScholars = await client.mohdithRef.getMohdithByIds([
  '256',  // البخاري
  '261',  // مسلم
]);

// 4. عرض جميع المحدثين مع الترقيم
final allScholars = await client.mohdithRef.getAllMohdith(
  limit: 50,
  offset: 0,
);

// 5. عد النتائج
final totalScholars = await client.mohdithRef.countMohdith();
final classicalScholars = await client.mohdithRef.countMohdith(
  query: 'أحمد',
);
print('إجمالي المحدثين: $totalScholars');

خدمة الرواة المرجعيين (Rawi Reference Service) #

للبحث في الرواة المتوفرين (بدون إنترنت).

// 1. البحث بالاسم
final narrators = await client.rawiRef.searchRawi('أبو هريرة', limit: 10);

// أو اختصار
final sameNarrators = await client.searchRawi('أبو هريرة');

for (var narrator in narrators) {
  print(narrator.name);
}

// 2. الحصول على راوي بالمعرف
final abuHurayrah = await client.rawiRef.getRawiById(4396);
print(abuHurayrah.name); // أبو هريرة عبد الرحمن بن صخر الدوسي

// 3. الحصول على عدة رواة دفعة واحدة
final multipleNarrators = await client.rawiRef.getRawiByIds([
  4396,   // أبو هريرة
  5593,   // عائشة
]);

// 4. عرض جميع الرواة مع الترقيم
final allNarrators = await client.rawiRef.getAllRawi(
  limit: 100,
  offset: 0,
);

// 5. عد النتائج
final totalNarrators = await client.rawiRef.countRawi();
final abdullahNarrators = await client.rawiRef.countRawi(query: 'عبد الله');
print('إجمالي الرواة: $totalNarrators');
print('رواة "عبد الله": $abdullahNarrators');

القيم الثابتة للفلترة #

المكتبة توفر قيم ثابتة جاهزة لأشهر المحدثين والكتب والرواة لتسهيل عملية الفلترة.

المحدثون الثابتون (MohdithReference)

// القيم الثابتة المتاحة (20 محدث)
MohdithReference.all             // الجميع (بدون فلتر) - ID: 0
MohdithReference.malik           // الإمام مالك - ID: 179
MohdithReference.shafii          // الإمام الشافعي - ID: 204
MohdithReference.ahmad           // الإمام أحمد - ID: 241
MohdithReference.bukhari         // البخاري - ID: 256
MohdithReference.muslim          // مسلم - ID: 261
MohdithReference.ibnMajah        // ابن ماجه - ID: 273
MohdithReference.abuDawud        // أبو داود - ID: 275
MohdithReference.tirmidhi        // الترمذي - ID: 279
MohdithReference.nasai           // النسائي - ID: 303
MohdithReference.sufyanThawri    // سفيان الثوري - ID: 161
MohdithReference.ibnMubarak      // عبدالله بن المبارك - ID: 181
MohdithReference.sufyanIbnUyaynah // سفيان بن عيينة - ID: 198
MohdithReference.ishaqIbnRahawayh // إسحاق بن راهويه - ID: 238
MohdithReference.darimi          // الدارمي - ID: 250
MohdithReference.ibnKhuzaymah    // ابن خزيمة - ID: 311
MohdithReference.ibnHibban       // ابن حبان - ID: 354
MohdithReference.hakim           // الحاكم - ID: 405
MohdithReference.bayhaqi         // البيهقي - ID: 458
MohdithReference.tabarani        // الطبراني - ID: 360

// كل قيمة لها معرف واسم
final bukhari = MohdithReference.bukhari;
print(bukhari.id);    // "256"
print(bukhari.name);  // "البخاري"

// الاستخدام في الفلترة
final params = HadithSearchParams(
  value: 'الصلاة',
  page: 1,
  mohdith: [MohdithReference.bukhari],
);

// الحصول على المعرف كرقم للاستخدام في الفلترة
final bukhariId = int.parse(MohdithReference.bukhari.id);

الكتب الثابتة (BookReference)

// القيم الثابتة المتاحة (21 كتاب)
BookReference.all                 // الجميع (بدون فلتر)
BookReference.sahihBukhari        // صحيح البخاري (6216)
BookReference.sahihMuslim         // صحيح مسلم (3088)
BookReference.arbainNawawi        // الأربعون النووية (13457)
BookReference.sahihMusnad         // الصحيح المسند (96)
BookReference.sunanAbuDawud       // سنن أبي داود (4549)
BookReference.jamiTirmidhi        // سنن الترمذي (3662)
BookReference.sunanNasai          // سنن النسائي (5766)
BookReference.sunanIbnMajah       // سنن ابن ماجه (5299)
BookReference.musnadAhmad         // مسند أحمد (14)
BookReference.muwattaMalik        // موطأ مالك (6453)
BookReference.musnadDarimi        // سنن الدارمي (6277)
BookReference.sahihIbnKhuzaymah   // صحيح ابن خزيمة (3024)
BookReference.sahihIbnHibban      // صحيح ابن حبان (5876)
BookReference.mustadrakHakim      // المستدرك على الصحيحين (2800)
BookReference.sunanBayhaqiKubra   // السنن الكبرى للبيهقي (7989)
BookReference.sunanDaraqutni      // سنن الدارقطني (3233)
BookReference.musannafIbnAbiShaybah // مصنف ابن أبي شيبة (6598)
BookReference.musannafAbdRazzaq   // مصنف عبد الرزاق (7613)
BookReference.riyadSalihin        // رياض الصالحين (10106)
BookReference.bulughMaram         // بلوغ المرام (9927)

// كل قيمة لها معرف واسم
final bukhari = BookReference.sahihBukhari;
print(bukhari.id);    // "6216"
print(bukhari.name);  // "صحيح البخاري"

// الاستخدام في الفلترة
final params = HadithSearchParams(
  value: 'الزكاة',
  page: 1,
  books: [
    BookReference.sahihBukhari,
    BookReference.sahihMuslim,
  ],
);

// الحصول على المعرف كرقم للاستخدام في الفلترة
final bukhariId = int.parse(BookReference.sahihBukhari.id);

الرواة الثابتون (RawiReference)

ملاحظة: يوجد حوالي 14,000 راوي في قاعدة البيانات، لذلك تم توفير بعض الصحابة فقط كقيم ثابتة.

// القيم الثابتة المتاحة (20 صحابي)
RawiReference.all                // الجميع (بدون فلتر)
RawiReference.abuHurayrah        // أبو هريرة (1416)
RawiReference.aisha              // عائشة أم المؤمنين (6617)
RawiReference.ibnAbbas           // ابن عباس (2664)
RawiReference.ibnUmar            // عبدالله بن عمر (7687)
RawiReference.anasBinMalik       // أنس بن مالك (2177)
RawiReference.jabirIbnAbdullah  // جابر بن عبدالله (3971)
RawiReference.abuSaidKhudri      // أبو سعيد الخدري (779)
RawiReference.ibnMasud           // عبدالله بن مسعود (7918)
RawiReference.abuMusaAshari      // أبو موسى الأشعري (1342)
RawiReference.umarIbnKhattab     // عمر بن الخطاب (8918)
RawiReference.aliIbnAbiTalib     // علي بن أبي طالب (8637)
RawiReference.abuBakr            // أبو بكر الصديق (455)
RawiReference.uthmanIbnAffan     // عثمان بن عفان (8310)
RawiReference.salmanFarisi       // سلمان الفارسي (5947)
RawiReference.muadhIbnJabal      // معاذ بن جبل (10349)
RawiReference.abuDharr           // أبو ذر الغفاري (667)
RawiReference.bilal              // بلال بن رباح (3808)
RawiReference.zaydIbnThabit      // زيد بن ثابت (5545)
RawiReference.ubayyIbnKab        // أبي بن كعب (1695)
RawiReference.abuAyyub           // أبو أيوب الأنصاري (129)

// كل قيمة لها معرف واسم
final abuHurayrah = RawiReference.abuHurayrah;
print(abuHurayrah.id);    // "1416"
print(abuHurayrah.name);  // "أبو هريرة"

// الاستخدام في الفلترة
final params = HadithSearchParams(
  value: 'الجنة',
  page: 1,
  rawi: [RawiReference.abuHurayrah],
);

// الحصول على المعرف كرقم للاستخدام في الفلترة
final abuHurayrahId = int.parse(RawiReference.abuHurayrah.id);

// للبحث عن رواة آخرين، استخدم خدمة البحث
final narrators = await client.rawiRef.searchRawi('عبد الله', limit: 10);

يوجد لدي تحذير بعنوان "Unclosed database"؟ #

يجب دائمًا استدعاء client.dispose():

final client = DorarClient();
try {
  // استخدام المكتبة
} finally {
  await client.dispose(); // إلزامي
}

المساهمة #

المساهمة بأي شكل من الأشكال مرحب به.

License #

MIT License - see LICENSE file.

Architecture #

DorarClient (Facade)
    ├── HadithService
    ├── SharhService  
    ├── BookService
    ├── MohdithService
    ├── MohdithRefService 
    ├── BookRefService 
    └── RawiRefService 
         └── HTTP Client + Cache
              └── HTML Parsers

سائلًا الله تعالى أن يكتب اجري واجركم

2
likes
0
points
26
downloads

Publisher

verified publishermoathdev.me

Weekly Downloads

A comprehensive Dart library for accessing Dorar.net hadith database. Search hadiths, get explanations (sharh), browse scholars, books, and narrators. Includes offline reference data for 688 books, 200 scholars, and 11,436 narrators.

Repository (GitHub)
View/report issues

Topics

#hadith #islamic #dorar #arabic #religion

License

unknown (license)

Dependencies

drift, equatable, html, http, path, sqlite3

More

Packages that depend on dorar_hadith