Changing to leaflet and adding support for manga id recovery.

This commit is contained in:
sergiotarxz 2021-10-30 04:02:10 +02:00
parent f4c9ed4f3a
commit 215563d862
6 changed files with 105 additions and 16 deletions

View File

@ -57,3 +57,5 @@ loop_search_class (const xmlNodePtr node, xmlNodePtr *nodes,
const char * class, size_t *len);
char *
copy_binary_data (const char *input, size_t size);
char *
match_1 (char *re_str, char *subject);

View File

@ -14,7 +14,8 @@ G_DECLARE_FINAL_TYPE (MgManga, mg_manga, MG, MANGA, GObject)
*/
char *mg_manga_get_image_url(MgManga *mg_manga);
char *mg_manga_get_title(MgManga *mg_manga);
char *mg_manga_get_id(MgManga *mg_manga);
MgManga *mg_manga_new (const char *const image_url, const char *const title);
MgManga *mg_manga_new (const char *const image_url, const char *const title, const char *const id);
G_END_DECLS

34
manga.c
View File

@ -94,6 +94,9 @@ print_debug_nodes (const xmlDocPtr html_document,
char *
get_attr (xmlNodePtr const node, const char *attr_name) {
char *return_value = NULL;
if (!node) {
return NULL;
}
for (xmlAttr *attr = node->properties; attr; attr=attr->next) {
if (!xmlStrcmp(attr->name, (const xmlChar *) attr_name)
&& attr->children && attr->children->content) {
@ -270,3 +273,34 @@ loop_search_class (const xmlNodePtr node, xmlNodePtr *nodes,
g_free (content);
return nodes;
}
char *
match_1 (char *re_str, char *subject) {
pcre2_code *re;
pcre2_match_data *match_data;
char *return_value;
int regex_compile_error;
int rc;
size_t len_match = 0;
return_value = NULL;
PCRE2_SIZE error_offset;
re = pcre2_compile ((PCRE2_SPTR8) re_str, strlen (re_str), 0,
&regex_compile_error, &error_offset, NULL);
match_data = pcre2_match_data_create_from_pattern (re, NULL);
if (!subject) {
goto cleanup_match;
}
rc = pcre2_match (re, (PCRE2_SPTR8) subject, strlen (subject),
0, 0, match_data, NULL);
if (rc < 0 ) {
goto cleanup_match;
}
pcre2_substring_get_bynumber (match_data, 1, (PCRE2_UCHAR8**)
&return_value, &len_match);
cleanup_match:
pcre2_match_data_free (match_data);
pcre2_code_free (re);
return return_value;
}

View File

@ -69,9 +69,14 @@ mg_backend_readmng_init (MgBackendReadmng *self) {
}
}
const char *
char *
mg_backend_readmng_get_base_url (MgBackendReadmng *self) {
return self->base_url;
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_STRING);
g_object_get_property (G_OBJECT (self),
"base_url",
&value);
return g_value_dup_string (&value);
}
void
@ -150,6 +155,7 @@ mg_backend_readmng_parse_main_page (MgBackendReadmng *self, const xmlDocPtr html
size_t li_len = 0;
li = mg_backend_readmng_retrieve_li_slides (self, slides, &li_len);
print_debug_nodes (html_document, li, li_len);
for (int i = 0; i<li_len; i++) {
xmlNodePtr current_li = li[i];
mg_backend_readmng_extract_manga_info_from_current_li (self,
@ -226,17 +232,38 @@ mg_backend_readmng_retrieve_title_from_li (MgBackendReadmng *self, xmlNodePtr li
return NULL;
}
static xmlNodePtr
mg_backend_readmng_find_a_link_chapter (MgBackendReadmng *self,
xmlNodePtr current_li) {
for (xmlNodePtr child = current_li->children; child; child = child->next) {
if (!strcmp((char *)child->name, "a")) {
return child;
}
}
return NULL;
}
static char *
mg_backend_get_id_manga_link (MgBackendReadmng *self, xmlNodePtr a) {
char *re_str = "readmng\\.com/([^/]+)";
return match_1 (re_str, get_attr (a, "href"));
}
static void
mg_backend_readmng_extract_manga_info_from_current_li (MgBackendReadmng *self,
GListStore *mangas, xmlNodePtr current_li) {
GListStore *mangas, xmlNodePtr current_li) {
xmlNodePtr thumbnail = mg_backend_readmng_retrieve_thumbnail_from_li (self, current_li);
xmlNodePtr title = mg_backend_readmng_retrieve_title_from_li (self, current_li);
xmlNodePtr a = mg_backend_readmng_find_a_link_chapter (self, current_li);
xmlNodePtr img;
char *id_manga = NULL;
if (thumbnail && title && (img = mg_backend_readmng_retrieve_img_from_thumbnail (self, thumbnail))) {
g_list_store_append (mangas, mg_manga_new (get_attr (img, "src"),
(char *)xmlNodeGetContent (title)));
if (thumbnail && title && (img = mg_backend_readmng_retrieve_img_from_thumbnail (self, thumbnail))
&& a && (id_manga = mg_backend_get_id_manga_link (self, a))) {
g_list_store_append (mangas,
mg_manga_new (get_attr (img, "src"), (char *)xmlNodeGetContent (title), id_manga));
}
}

View File

@ -7,6 +7,7 @@ struct _MgManga {
GObject parent_instance;
char *image_url;
char *title;
char *id;
};
G_DEFINE_TYPE (MgManga, mg_manga, G_TYPE_OBJECT)
@ -14,6 +15,7 @@ G_DEFINE_TYPE (MgManga, mg_manga, G_TYPE_OBJECT)
typedef enum {
MG_MANGA_IMAGE_URL = 1,
MG_MANGA_TITLE,
MG_MANGA_ID,
MG_MANGA_N_PROPERTIES
} MgMangaProperties;
@ -46,6 +48,11 @@ mg_manga_class_init (MgMangaClass *class) {
"Title of the manga.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
manga_properties[MG_MANGA_ID] = g_param_spec_string ("id",
"Id",
"Id of the manga",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_properties (object_class,
MG_MANGA_N_PROPERTIES,
@ -57,7 +64,17 @@ mg_manga_init (MgManga *self) {
}
char *
mg_manga_get_image_url(MgManga *self) {
mg_manga_get_id (MgManga *self) {
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_STRING);
g_object_get_property (G_OBJECT (self),
"id",
&value);
return g_value_dup_string (&value);
}
char *
mg_manga_get_image_url (MgManga *self) {
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_STRING);
g_object_get_property (G_OBJECT (self),
@ -67,7 +84,7 @@ mg_manga_get_image_url(MgManga *self) {
}
char *
mg_manga_get_title(MgManga *self) {
mg_manga_get_title (MgManga *self) {
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_STRING);
g_object_get_property (G_OBJECT (self),
@ -91,6 +108,10 @@ mg_manga_set_property (GObject *object,
g_free (self->title);
self->title = g_value_dup_string (value);
break;
case MG_MANGA_ID:
g_free (self->id);
self->id = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -110,6 +131,9 @@ mg_manga_get_property (GObject *object,
case MG_MANGA_TITLE:
g_value_set_string (value, self->title);
break;
case MG_MANGA_ID:
g_value_set_string (value, self->id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -117,12 +141,14 @@ mg_manga_get_property (GObject *object,
}
MgManga *
mg_manga_new (const char *const image_url, const char *const title) {
mg_manga_new (const char *const image_url, const char *const title, const char *id) {
MgManga *self = NULL;
self = (MG_MANGA) (g_object_new (MG_TYPE_MANGA, NULL));
self->image_url = alloc_string (strlen (image_url));
self->title = alloc_string (strlen (title));
self->id = alloc_string (strlen (id));
copy_substring (image_url, self->image_url, strlen(image_url) + 1, 0, strlen (image_url));
copy_substring (title, self->title, strlen(title) + 1, 0, strlen (title));
copy_substring (id, self->id, strlen(id) + 1, 0, strlen (id));
return self;
}

View File

@ -26,7 +26,7 @@ activate (AdwApplication *app,
MgBackendReadmng *readmng = mg_backend_readmng_new ();
GtkListView *list_view;
GtkWidget *scroll;
AdwViewStack *views_stack = ADW_VIEW_STACK (adw_view_stack_new ());
AdwLeaflet *views_leaflet = ADW_LEAFLET (adw_leaflet_new ());
create_headerbar (box);
@ -38,12 +38,11 @@ activate (AdwApplication *app,
gtk_widget_set_vexpand (scroll, 1);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroll), GTK_WIDGET (list_view));
adw_view_stack_add_named (views_stack, scroll, "manga-list");
adw_view_stack_set_visible_child_name (views_stack, "manga-list");
AdwViewStackPage *page = adw_view_stack_get_page (views_stack, scroll);
adw_view_stack_page_set_title (page, "Manga List");
adw_leaflet_append (views_leaflet, scroll);
adw_leaflet_set_can_unfold (views_leaflet, false);
// adw_leaflet_set_visible_child (views_leaflet, scroll);
gtk_box_append (box, GTK_WIDGET (views_stack));
gtk_box_append (box, GTK_WIDGET (views_leaflet));
gtk_widget_show (window);
}