From f7e3684d4564ccbdde270f77a9f598018bbda3a2 Mon Sep 17 00:00:00 2001 From: marioplus Date: Sat, 19 Apr 2025 13:29:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(YellowNote):=20add=20source=20=E5=B0=8F?= =?UTF-8?q?=E9=BB=84=E4=B9=A6=20(#8485)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(YellowNote): add source 小黄书 * fix(YellowNote): reverse chapter sorting order * feat(YellowNote): improve domain configuration and URL handling - Implement dual domain configuration (default + override) - Default settings refresh when code updates occur - Override settings maintain custom configurations - Enhance URL processing using HttpUrl - Fix encoding issues in query URLs - Improve URL parsing reliability * feat(YellowNote): adapter /amateurs.html --- .../assets/i18n/messages_en.properties | 80 +++++++++ .../assets/i18n/messages_es.properties | 82 +++++++++ .../assets/i18n/messages_ko.properties | 82 +++++++++ .../assets/i18n/messages_zh_hans.properties | 82 +++++++++ .../assets/i18n/messages_zh_hant.properties | 80 +++++++++ src/all/yellownote/build.gradle | 12 ++ .../res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3390 bytes .../res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1953 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4622 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 8217 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 11625 bytes .../extension/all/yellownote/JsonPExt.kt | 5 + .../all/yellownote/SimpleParsedHttpSource.kt | 42 +++++ .../extension/all/yellownote/YellowNote.kt | 157 ++++++++++++++++++ .../all/yellownote/YellowNoteFilters.kt | 139 ++++++++++++++++ .../all/yellownote/YellowNotePreferences.kt | 75 +++++++++ .../all/yellownote/YellowNoteSourceFactory.kt | 25 +++ 17 files changed, 861 insertions(+) create mode 100644 src/all/yellownote/assets/i18n/messages_en.properties create mode 100644 src/all/yellownote/assets/i18n/messages_es.properties create mode 100644 src/all/yellownote/assets/i18n/messages_ko.properties create mode 100644 src/all/yellownote/assets/i18n/messages_zh_hans.properties create mode 100644 src/all/yellownote/assets/i18n/messages_zh_hant.properties create mode 100644 src/all/yellownote/build.gradle create mode 100644 src/all/yellownote/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/all/yellownote/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/all/yellownote/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/all/yellownote/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/all/yellownote/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/JsonPExt.kt create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/SimpleParsedHttpSource.kt create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNote.kt create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteFilters.kt create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNotePreferences.kt create mode 100644 src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteSourceFactory.kt diff --git a/src/all/yellownote/assets/i18n/messages_en.properties b/src/all/yellownote/assets/i18n/messages_en.properties new file mode 100644 index 000000000..60a2ff325 --- /dev/null +++ b/src/all/yellownote/assets/i18n/messages_en.properties @@ -0,0 +1,80 @@ +filter.sort.title=Sort by +filter.sort.option.last-update=Last Update +filter.sort.option.popularity=Popularity +filter.sort.option.most-comments=Comment Count +filter.sort.option.latest-comments=Latest Comments +filter.header.ignored-when-search=These filters will be ignored when text search is active! +filter.category.title=Category +filter.category.option.theme.xiuren-featured=Theme: Xiuren Featured +filter.category.option.theme.large-scale=Theme: Large Scale +filter.category.option.theme.sex=Theme: Sex +filter.category.option.theme.exposure=Theme: Exposure +filter.category.option.theme.cosplay=Theme: Cosplay +filter.category.option.theme.sex-toy=Theme: Sex Toy +filter.category.option.theme.bondage=Theme: Bondage +filter.category.option.theme.shaved-pussy=Theme: Shaved Pussy +filter.category.option.theme.lesbian=Theme: Lesbian +filter.category.option.theme.with-original-photos=Theme: With Original Photos +filter.category.option.theme.with-video=Theme: With Video(s) +filter.category.option.theme.amateur=Theme: Amateur +filter.category.option.chinese-studios-pans=Chinese Studios: PANS +filter.category.option.chinese-studios-wind-sings=Chinese Studios: Wind sings +filter.category.option.chinese-studios-xing-se=Chinese Studios: Xing Se +filter.category.option.chinese-studios-huang-fu=Chinese Studios: Huang Fu +filter.category.option.chinese-studios-other-studios=Chinese Studios: Other Studios +filter.category.option.chinese-studios-metcn=Chinese Studios: MetCN +filter.category.option.chinese-studios-litu=Chinese Studios: Litu +filter.category.option.chinese-studios-midnight-project=Chinese Studios: Midnight Project +filter.category.option.chinese-studios-pandora=Chinese Studios: Pandora +filter.category.option.chinese-studios-missleg=Chinese Studios: MISSLEG +filter.category.option.chinese-studios-iss=Chinese Studios: ISS +filter.category.option.chinese-studios-aiss=Chinese Studios: AISS +filter.category.option.chinese-studios-au=Chinese Studios: AU +filter.category.option.chinese-studios-beijing-angel=Chinese Studios: Beijing Angel +filter.category.option.chinese-studios-wuji-works=Chinese Studios: Wuji Works +filter.category.option.chinese-studios-pomelo=Chinese Studios: Pomelo +filter.category.option.chinese-studios-sk-silk=Chinese Studios: SK Silk +filter.category.option.chinese-studios-ddy=Chinese Studios: DDY +filter.category.option.chinese-studios-dongguan-vgirls=Chinese Studios: Dongguan VGirls +filter.category.option.chinese-studios-youmei=Chinese Studios: YouMei +filter.category.option.other-photos-chinese-nude=Other Photos: Chinese Nude +filter.category.option.other-photos-korean-nude=Other Photos: Korean Nude +filter.category.option.other-photos-taiwan-nude=Other Photos: Taiwan Nude +filter.category.option.other-photos-other-regions=Other Photos: Other Regions +filter.category.option.xiuren-all=Xiuren: All +filter.category.option.xiuren-leaked=Xiuren: Leaked +filter.category.option.xiuren-huayang=Xiuren: HuaYang +filter.category.option.xiuren-mygirl=Xiuren: MyGirl +filter.category.option.xiuren-imiss=Xiuren: IMiss +filter.category.option.xiuren-miitao=Xiuren: MiiTao +filter.category.option.xiuren-feilin=Xiuren: FEILIN +filter.category.option.xiuren-youwu=Xiuren: YouWu +filter.category.option.xiuren-wings=Xiuren: WingS +filter.category.option.xiuren-ruisg=Xiuren: RUISG +filter.category.option.korean-studios-makemodel=Korean Studios: Makemodel +filter.category.option.korean-studios-pure-media=Korean Studios: Pure Media +filter.category.option.korean-studios-espacia-korea=Korean Studios: Espacia Korea +filter.category.option.korean-studios-loozy=Korean Studios: Loozy +filter.category.option.japanese-studios-graphis=Japanese Studios: Graphis +filter.category.option.japanese-studios-kuni-scan=Japanese Studios: KUNI Scan +filter.category.option.japanese-studios-weekly-post-digital-photo=Japanese Studios: Weekly Post-Digital Photo +filter.category.option.japanese-studios-morning-sexy=Japanese Studios: Morning SEXY +filter.category.option.japanese-studios-prestige=Japanese Studios: Prestige +filter.category.option.japanese-studios-x-city=Japanese Studios: X-City +filter.category.option.japanese-studios-friday=Japanese Studios: FRIDAY +filter.category.option.japanese-studios-super-pose-book=Japanese Studios: Super Pose Book +filter.category.option.japanese-studios-urabon=Japanese Studios: Urabon +filter.category.option.japanese-studios-escape=Japanese Studios: Escape +filter.category.option.japanese-studios-flash=Japanese Studios: Flash +filter.category.option.taiwan-studios-jvid=Taiwan Studios: JVID +filter.category.option.taiwan-studios-fantasy-factory=Taiwan Studios: Fantasy Factory +filter.category.option.taiwan-studios-tpimage=Taiwan Studios: TPimage +filter.category.option.others-ai-photos=Others: AI Photos + +config.domain.title=Domain Settings +config.domain.summary=If the current domain is blocked, you can change it manually here. It will take effect after restarting the app. +config.domain.dialog.title=Domain Settings +config.domain.dialog.message=Default domain: +config.domain.toast.changed-success=Domain changed successfully. It will take effect after restarting the app. +config.domain.toast.changed-failed=Invalid domain! + diff --git a/src/all/yellownote/assets/i18n/messages_es.properties b/src/all/yellownote/assets/i18n/messages_es.properties new file mode 100644 index 000000000..6ce66738a --- /dev/null +++ b/src/all/yellownote/assets/i18n/messages_es.properties @@ -0,0 +1,82 @@ +filter.sort.title=Ordenar por +filter.sort.option.last-update=Última actualización +filter.sort.option.popularity=Contenido más popular +filter.sort.option.most-comments=Más comentarios +filter.sort.option.latest-comments=Comentarios más recientes + +filter.header.ignored-when-search=¡Estos filtros se ignorarán cuando la búsqueda de texto esté activa! + +filter.category.title=Categoría del álbum +filter.category.option.theme.xiuren-featured=Xiuren Gran escala +filter.category.option.theme.large-scale=Gran Escala +filter.category.option.theme.sex=Sexo +filter.category.option.theme.exposure=Exposición +filter.category.option.theme.cosplay=Cosplay +filter.category.option.theme.sex-toy=Juguete Sexual +filter.category.option.theme.bondage=Esclavitud +filter.category.option.theme.shaved-pussy=Coño Afeitado +filter.category.option.theme.lesbian=Lesbiana +filter.category.option.theme.with-original-photos=Con foto original +filter.category.option.theme.with-video=Con Vídeo(s) +filter.category.option.theme.amateur=Aficionada +filter.category.option.chinese-studios-pans=Estudios chinos: PANS +filter.category.option.chinese-studios-wind-sings=Estudios chinos: El viento canta +filter.category.option.chinese-studios-xing-se=Estudios chinos: Xing Se +filter.category.option.chinese-studios-huang-fu=Estudios chinos: Huang Fu +filter.category.option.chinese-studios-other-studios=Estudios chinos: Otros estudios +filter.category.option.chinese-studios-metcn=Estudios chinos: MetCN +filter.category.option.chinese-studios-litu=Estudios chinos: Litu +filter.category.option.chinese-studios-midnight-project=Estudios chinos: Proyecto de medianoche +filter.category.option.chinese-studios-pandora=Estudios chinos: Pandora +filter.category.option.chinese-studios-missleg=Estudios chinos: MISSLEG +filter.category.option.chinese-studios-iss=Estudios chinos: ISS +filter.category.option.chinese-studios-aiss=Estudios chinos: AISS +filter.category.option.chinese-studios-au=Estudios chinos: AU +filter.category.option.chinese-studios-beijing-angel=Estudios chinos: Beijing Angel +filter.category.option.chinese-studios-wuji-works=Estudios chinos: Wuji Works +filter.category.option.chinese-studios-pomelo=Estudios chinos: Pomelo +filter.category.option.chinese-studios-sk-silk=Estudios chinos: SK Silk +filter.category.option.chinese-studios-ddy=Estudios chinos: DDY +filter.category.option.chinese-studios-dongguan-vgirls=Estudios chinos: Dongguan VGirls +filter.category.option.chinese-studios-youmei=Estudios chinos: YouMei +filter.category.option.other-photos-chinese-nude=Otras fotos: Desnuda China +filter.category.option.other-photos-korean-nude=Otras fotos: Desnudo Coreano +filter.category.option.other-photos-taiwan-nude=Otras fotos: Desnuda Taiwan +filter.category.option.other-photos-other-regions=Otras fotos: Otras Regiones +filter.category.option.xiuren-all=Xiuren: all +filter.category.option.xiuren-leaked=Xiuren: Filtrado +filter.category.option.xiuren-huayang=Xiuren: HuaYang +filter.category.option.xiuren-mygirl=Xiuren: MyGirl +filter.category.option.xiuren-imiss=Xiuren: IMiss +filter.category.option.xiuren-miitao=Xiuren: MiiTao +filter.category.option.xiuren-feilin=Xiuren: FEILIN +filter.category.option.xiuren-youwu=Xiuren: YouWu +filter.category.option.xiuren-wings=Xiuren: WingS +filter.category.option.xiuren-ruisg=Xiuren: RUISG +filter.category.option.korean-studios-makemodel=Estudios coreanos: Makemodel +filter.category.option.korean-studios-pure-media=Estudios coreanos: Pure Medios +filter.category.option.korean-studios-espacia-korea=Estudios coreanos: Espacia Korea +filter.category.option.korean-studios-loozy=Estudios coreanos: Loozy +filter.category.option.japanese-studios-graphis=Estudios japonesas: Graphis +filter.category.option.japanese-studios-kuni-scan=Estudios japonesas: KUNI Scan +filter.category.option.japanese-studios-weekly-post-digital-photo=Estudios japonesas: Foto Semanal Post-Digital +filter.category.option.japanese-studios-morning-sexy=Estudios japonesas: Matutinos Sexy +filter.category.option.japanese-studios-prestige=Estudios japonesas: Prestige +filter.category.option.japanese-studios-x-city=Estudios japonesas: X-City +filter.category.option.japanese-studios-friday=Estudios japonesas: FRIDAY +filter.category.option.japanese-studios-super-pose-book=Estudios japonesas: Super Pose Book +filter.category.option.japanese-studios-urabon=Estudios japonesas: Urabon +filter.category.option.japanese-studios-escape=Estudios japonesas: Escape +filter.category.option.japanese-studios-flash=Estudios japonesas: Flash +filter.category.option.taiwan-studios-jvid=Estudios de Taiwán: JVID +filter.category.option.taiwan-studios-fantasy-factory=Estudios de Taiwán: Fantasy Factory +filter.category.option.taiwan-studios-tpimage=Estudios de Taiwán: TPimage +filter.category.option.others-ai-photos=Otras: AI Photos + +config.domain.title=Configuración de dominio +config.domain.summary=Si el dominio actual está bloqueado, puedes cambiarlo manualmente aquí. Se aplicará después de reiniciar la aplicación. +config.domain.dialog.title=Configuración de dominio +config.domain.dialog.message=Dominio predeterminado: +config.domain.toast.changed-success=Dominio cambiado correctamente. Se aplicará tras reiniciar la aplicación. +config.domain.toast.changed-failed=¡Dominio no válido! + diff --git a/src/all/yellownote/assets/i18n/messages_ko.properties b/src/all/yellownote/assets/i18n/messages_ko.properties new file mode 100644 index 000000000..18641b970 --- /dev/null +++ b/src/all/yellownote/assets/i18n/messages_ko.properties @@ -0,0 +1,82 @@ +filter.sort.title=정렬 방식 +filter.sort.option.last-update=업데이트 날짜 +filter.sort.option.popularity=인기 콘텐츠 +filter.sort.option.most-comments=댓글 많은 순 +filter.sort.option.latest-comments=최신 댓글 순 + +filter.header.ignored-when-search=텍스트 검색이 활성화되면 이 필터는 무시됩니다! + +filter.category.title=앨범 분류 +filter.category.option.theme.xiuren-featured=Xiuren 대판 +filter.category.option.theme.large-scale=대판 +filter.category.option.theme.sex=섹스 +filter.category.option.theme.exposure=노출 +filter.category.option.theme.cosplay=Cosplay +filter.category.option.theme.sex-toy=섹스 토이 +filter.category.option.theme.bondage=속박 +filter.category.option.theme.shaved-pussy=면도한 음부 +filter.category.option.theme.lesbian=레즈비언 +filter.category.option.theme.with-original-photos=원본 있음 +filter.category.option.theme.with-video=동영상 포함 +filter.category.option.theme.amateur=아마추어 +filter.category.option.chinese-studios-pans=중국 스튜디오: PANS +filter.category.option.chinese-studios-wind-sings=중국 스튜디오: 바람이 노래한다 +filter.category.option.chinese-studios-xing-se=중국 스튜디오: 싱 세 +filter.category.option.chinese-studios-huang-fu=중국 스튜디오: 황 푸 +filter.category.option.chinese-studios-other-studios=중국 스튜디오: 다른 스튜디오 +filter.category.option.chinese-studios-metcn=중국 스튜디오: MetCN +filter.category.option.chinese-studios-litu=중국 스튜디오: Litu +filter.category.option.chinese-studios-midnight-project=중국 스튜디오: 미드나잇 프로젝트 +filter.category.option.chinese-studios-pandora=중국 스튜디오: Pandora +filter.category.option.chinese-studios-missleg=중국 스튜디오: MISSLEG +filter.category.option.chinese-studios-iss=중국 스튜디오: ISS +filter.category.option.chinese-studios-aiss=중국 스튜디오: AISS +filter.category.option.chinese-studios-au=중국 스튜디오: AU +filter.category.option.chinese-studios-beijing-angel=중국 스튜디오: Beijing Angel +filter.category.option.chinese-studios-wuji-works=중국 스튜디오: Wuji Works +filter.category.option.chinese-studios-pomelo=중국 스튜디오: 포멜로 +filter.category.option.chinese-studios-sk-silk=중국 스튜디오: SK Silk +filter.category.option.chinese-studios-ddy=중국 스튜디오: DDY +filter.category.option.chinese-studios-dongguan-vgirls=중국 스튜디오: Dongguan VGirls +filter.category.option.chinese-studios-youmei=중국 스튜디오: YouMei +filter.category.option.other-photos-chinese-nude=다른 사진들: 중국 누드 +filter.category.option.other-photos-korean-nude=다른 사진들: 한국 누드 +filter.category.option.other-photos-taiwan-nude=다른 사진들: 대만 누드 +filter.category.option.other-photos-other-regions=다른 사진들: 기타 지역 +filter.category.option.xiuren-all=Xiuren: All +filter.category.option.xiuren-leaked=Xiuren: 누출됨 +filter.category.option.xiuren-huayang=Xiuren: HuaYang +filter.category.option.xiuren-mygirl=Xiuren: MyGirl +filter.category.option.xiuren-imiss=Xiuren: IMiss +filter.category.option.xiuren-miitao=Xiuren: MiiTao +filter.category.option.xiuren-feilin=Xiuren: FEILIN +filter.category.option.xiuren-youwu=Xiuren: YouWu +filter.category.option.xiuren-wings=Xiuren: WingS +filter.category.option.xiuren-ruisg=Xiuren: RUISG +filter.category.option.korean-studios-makemodel=한국 스튜디오: Makemodel +filter.category.option.korean-studios-pure-media=한국 스튜디오: Pure Media +filter.category.option.korean-studios-espacia-korea=한국 스튜디오: Espacia Korea +filter.category.option.korean-studios-loozy=한국 스튜디오: Loozy +filter.category.option.japanese-studios-graphis=일본 스튜디오: Graphis +filter.category.option.japanese-studios-kuni-scan=일본 스튜디오: KUNI Scan +filter.category.option.japanese-studios-weekly-post-digital-photo=일본 스튜디오: 주간 포스트 디지털 사진 +filter.category.option.japanese-studios-morning-sexy=일본 스튜디오: 아침 연예 섹시 +filter.category.option.japanese-studios-prestige=일본 스튜디오: Prestige +filter.category.option.japanese-studios-x-city=일본 스튜디오: X-City +filter.category.option.japanese-studios-friday=일본 스튜디오: FRIDAY +filter.category.option.japanese-studios-super-pose-book=일본 스튜디오: Super Pose Book +filter.category.option.japanese-studios-urabon=일본 스튜디오: Urabon +filter.category.option.japanese-studios-escape=일본 스튜디오: Escape +filter.category.option.japanese-studios-flash=일본 스튜디오: Flash +filter.category.option.taiwan-studios-jvid=대만 스튜디오: JVID +filter.category.option.taiwan-studios-fantasy-factory=대만 스튜디오: Fantasy Factory +filter.category.option.taiwan-studios-tpimage=대만 스튜디오: TPimage +filter.category.option.others-ai-photos=기타: AI 사진 + +config.domain.title=도메인 설정 +config.domain.summary=현재 도메인이 차단된 경우, 여기에서 수동으로 변경할 수 있습니다. 앱을 재시작하면 적용됩니다. +config.domain.dialog.title=도메인 설정 +config.domain.dialog.message=기본 도메인: +config.domain.toast.changed-success=도메인이 변경되었습니다. 앱을 재시작하면 적용됩니다. +config.domain.toast.changed-failed=유효하지 않은 도메인입니다! + diff --git a/src/all/yellownote/assets/i18n/messages_zh_hans.properties b/src/all/yellownote/assets/i18n/messages_zh_hans.properties new file mode 100644 index 000000000..0aab0502e --- /dev/null +++ b/src/all/yellownote/assets/i18n/messages_zh_hans.properties @@ -0,0 +1,82 @@ +filter.sort.title=排序方式 +filter.sort.option.last-update=更新时间 +filter.sort.option.popularity=最热内容 +filter.sort.option.most-comments=最多评论 +filter.sort.option.latest-comments=最近评论 + +filter.header.ignored-when-search=以下过滤在文本搜索时会被忽略! + +filter.category.title=专辑分类 +filter.category.option.theme.xiuren-featured=主题: 秀人网特色 +filter.category.option.theme.large-scale=主题: 大尺度 +filter.category.option.theme.sex=主题: 性爱 +filter.category.option.theme.exposure=主题: 露出 +filter.category.option.theme.cosplay=主题: Cosplay +filter.category.option.theme.sex-toy=主题: 道具 +filter.category.option.theme.bondage=主题: 捆绑 +filter.category.option.theme.shaved-pussy=主题: 白虎 +filter.category.option.theme.lesbian=主题: 女同 +filter.category.option.theme.with-original-photos=主题: 有原图 +filter.category.option.theme.with-video=主题: 有视频 +filter.category.option.theme.amateur=主题: 业余自拍 +filter.category.option.chinese-studios-pans=中国工作室: PANS +filter.category.option.chinese-studios-wind-sings=中国工作室: 风吟鸟唱 +filter.category.option.chinese-studios-xing-se=中国工作室: 行色 +filter.category.option.chinese-studios-huang-fu=中国工作室: 黄甫 +filter.category.option.chinese-studios-other-studios=中国工作室: 其他中国工作室 +filter.category.option.chinese-studios-metcn=中国工作室: 相约中国 +filter.category.option.chinese-studios-litu=中国工作室: 丽图 +filter.category.option.chinese-studios-midnight-project=中国工作室: 深夜企划 +filter.category.option.chinese-studios-pandora=中国工作室: 潘多拉 +filter.category.option.chinese-studios-missleg=中国工作室: 蜜丝 +filter.category.option.chinese-studios-iss=中国工作室: ISS系列 +filter.category.option.chinese-studios-aiss=中国工作室: 爱丝 +filter.category.option.chinese-studios-au=中国工作室: AU +filter.category.option.chinese-studios-beijing-angel=中国工作室: 北京天使 +filter.category.option.chinese-studios-wuji-works=中国工作室: 无忌影社 +filter.category.option.chinese-studios-pomelo=中国工作室: 蜜柚摄影 +filter.category.option.chinese-studios-sk-silk=中国工作室: SK丝库 +filter.category.option.chinese-studios-ddy=中国工作室: DDY +filter.category.option.chinese-studios-dongguan-vgirls=中国工作室: 东莞V女郎 +filter.category.option.chinese-studios-youmei=中国工作室: 尤美 +filter.category.option.other-photos-chinese-nude=各国其他套图: 国模套图 +filter.category.option.other-photos-korean-nude=各国其他套图: 韩模套图 +filter.category.option.other-photos-taiwan-nude=各国其他套图: 台模套图 +filter.category.option.other-photos-other-regions=各国其他套图: 其他地区套图 +filter.category.option.xiuren-all=秀人网旗下: 全部秀人旗下 +filter.category.option.xiuren-leaked=秀人网旗下: 私购流出 +filter.category.option.xiuren-huayang=秀人网旗下: 花漾 +filter.category.option.xiuren-mygirl=秀人网旗下: 美媛馆 +filter.category.option.xiuren-imiss=秀人网旗下: 爱蜜社 +filter.category.option.xiuren-miitao=秀人网旗下: 蜜桃社 +filter.category.option.xiuren-feilin=秀人网旗下: FEILIN嗲囡囡 +filter.category.option.xiuren-youwu=秀人网旗下: 尤物馆 +filter.category.option.xiuren-wings=秀人网旗下: 影私荟 +filter.category.option.xiuren-ruisg=秀人网旗下: 瑞丝馆 +filter.category.option.korean-studios-makemodel=韩国工作室: Makemodel +filter.category.option.korean-studios-pure-media=韩国工作室: Pure Media +filter.category.option.korean-studios-espacia-korea=韩国工作室: Espacia Korea +filter.category.option.korean-studios-loozy=韩国工作室: Loozy +filter.category.option.japanese-studios-graphis=日本工作室: Graphis +filter.category.option.japanese-studios-kuni-scan=日本工作室: KUNI Scan +filter.category.option.japanese-studios-weekly-post-digital-photo=日本工作室: 周刊ポストデジタル写真集 +filter.category.option.japanese-studios-morning-sexy=日本工作室: アサ芸SEXY +filter.category.option.japanese-studios-prestige=日本工作室: Prestige +filter.category.option.japanese-studios-x-city=日本工作室: X-City +filter.category.option.japanese-studios-friday=日本工作室: FRIDAY +filter.category.option.japanese-studios-super-pose-book=日本工作室: Super Pose Book +filter.category.option.japanese-studios-urabon=日本工作室: Urabon +filter.category.option.japanese-studios-escape=日本工作室: Escape +filter.category.option.japanese-studios-flash=日本工作室: FLASHデジタル写真集 +filter.category.option.taiwan-studios-jvid=台湾工作室: JVID +filter.category.option.taiwan-studios-fantasy-factory=台湾工作室: Fantasy Factory +filter.category.option.taiwan-studios-tpimage=台湾工作室: TPimage +filter.category.option.others-ai-photos=其他套图: AI图区 + +config.domain.title=域名设置 +config.domain.summary=如果当前域名被封,可在此手动更换。重启应用后生效。 +config.domain.dialog.title=域名设置 +config.domain.dialog.message=默认域名: +config.domain.toast.changed-success=已更换域名,重启应用后生效。 +config.domain.toast.changed-failed=无效域名! + diff --git a/src/all/yellownote/assets/i18n/messages_zh_hant.properties b/src/all/yellownote/assets/i18n/messages_zh_hant.properties new file mode 100644 index 000000000..c58ebbc48 --- /dev/null +++ b/src/all/yellownote/assets/i18n/messages_zh_hant.properties @@ -0,0 +1,80 @@ +filter.sort.title=排序方式 +filter.sort.option.last-update=更新時間 +filter.sort.option.popularity=最熱門內容 +filter.sort.option.most-comments=最多評論 +filter.sort.option.latest-comments=最新評論 + +filter.category.title=專輯分類 +filter.category.option.theme.xiuren-featured=主題: 秀人網特色 +filter.category.option.theme.large-scale=主題: 大尺度 +filter.category.option.theme.sex=主題: 性愛 +filter.category.option.theme.exposure=主題: 露出 +filter.category.option.theme.cosplay=主題: Cosplay +filter.category.option.theme.sex-toy=主題: 道具 +filter.category.option.theme.bondage=主題: 捆綁 +filter.category.option.theme.shaved-pussy=主題: 白虎 +filter.category.option.theme.lesbian=主題: 女同 +filter.category.option.theme.with-original-photos=主題: 有原圖 +filter.category.option.theme.with-video=主題: 有影片 +filter.category.option.theme.amateur=主題: 業餘自拍 +filter.category.option.chinese-studios-pans=中國工作室: PANS +filter.category.option.chinese-studios-wind-sings=中國工作室: 風吟鳥唱 +filter.category.option.chinese-studios-xing-se=中國工作室: 行色 +filter.category.option.chinese-studios-huang-fu=中國工作室: 黃甫 +filter.category.option.chinese-studios-other-studios=中國工作室: 其他中國工作室 +filter.category.option.chinese-studios-metcn=中國工作室: 相約中國 +filter.category.option.chinese-studios-litu=中國工作室: 麗圖 +filter.category.option.chinese-studios-midnight-project=中國工作室: 深夜企劃 +filter.category.option.chinese-studios-pandora=中國工作室: 潘多菈 +filter.category.option.chinese-studios-missleg=中國工作室: 蜜絲 +filter.category.option.chinese-studios-iss=中國工作室: ISS係列 +filter.category.option.chinese-studios-aiss=中國工作室: 愛絲 +filter.category.option.chinese-studios-au=中國工作室: AU +filter.category.option.chinese-studios-beijing-angel=中國工作室: 北京天使 +filter.category.option.chinese-studios-wuji-works=中國工作室: 無忌影社 +filter.category.option.chinese-studios-pomelo=中國工作室: 蜜柚攝影 +filter.category.option.chinese-studios-sk-silk=中國工作室: SK絲庫 +filter.category.option.chinese-studios-ddy=中國工作室: DDY +filter.category.option.chinese-studios-dongguan-vgirls=中國工作室: 東莞V女郎 +filter.category.option.chinese-studios-youmei=中國工作室: 尤美 +filter.category.option.other-photos-chinese-nude=各國其他套圖: 國模套圖 +filter.category.option.other-photos-korean-nude=各國其他套圖: 韓模套圖 +filter.category.option.other-photos-taiwan-nude=各國其他套圖: 臺模套圖 +filter.category.option.other-photos-other-regions=各國其他套圖: 其他地區套圖 +filter.category.option.xiuren-all=秀人網旗下: 全部秀人旗下 +filter.category.option.xiuren-leaked=秀人網旗下: 私購流出 +filter.category.option.xiuren-huayang=秀人網旗下: 花漾 +filter.category.option.xiuren-mygirl=秀人網旗下: 美媛館 +filter.category.option.xiuren-imiss=秀人網旗下: 愛蜜社 +filter.category.option.xiuren-miitao=秀人網旗下: 蜜桃社 +filter.category.option.xiuren-feilin=秀人網旗下: FEILIN嗲囡囡 +filter.category.option.xiuren-youwu=秀人網旗下: 尤物館 +filter.category.option.xiuren-wings=秀人網旗下: 影私荟 +filter.category.option.xiuren-ruisg=秀人網旗下: 瑞絲館 +filter.category.option.korean-studios-makemodel=韓國工作室: Makemodel +filter.category.option.korean-studios-pure-media=韓國工作室: Pure Media +filter.category.option.korean-studios-espacia-korea=韓國工作室: Espacia Korea +filter.category.option.korean-studios-loozy=韓國工作室: Loozy +filter.category.option.japanese-studios-graphis=日本工作室: Graphis +filter.category.option.japanese-studios-kuni-scan=日本工作室: KUNI Scan +filter.category.option.japanese-studios-weekly-post-digital-photo=日本工作室: 週刊ポストデジタル寫真集 +filter.category.option.japanese-studios-morning-sexy=日本工作室: アサ芸SEXY +filter.category.option.japanese-studios-prestige=日本工作室: Prestige +filter.category.option.japanese-studios-x-city=日本工作室: X-City +filter.category.option.japanese-studios-friday=日本工作室: FRIDAY +filter.category.option.japanese-studios-super-pose-book=日本工作室: Super Pose Book +filter.category.option.japanese-studios-urabon=日本工作室: Urabon +filter.category.option.japanese-studios-escape=日本工作室: Escape +filter.category.option.japanese-studios-flash=日本工作室: FLASHデジタル寫真集 +filter.category.option.taiwan-studios-jvid=臺灣工作室: JVID +filter.category.option.taiwan-studios-fantasy-factory=臺灣工作室: Fantasy Factory +filter.category.option.taiwan-studios-tpimage=臺灣工作室: TPimage +filter.category.option.others-ai-photos=其他套圖: AI圖區 + +config.domain.title=網域設定 +config.domain.summary=若目前網域遭封鎖,可在此手動更換。重新啟動應用後生效。 +config.domain.dialog.title=網域設定 +config.domain.dialog.message=預設網域: +config.domain.toast.changed-success=網域已更換,重新啟動應用後生效。 +config.domain.toast.changed-failed=無效的網域! + diff --git a/src/all/yellownote/build.gradle b/src/all/yellownote/build.gradle new file mode 100644 index 000000000..a09ed699b --- /dev/null +++ b/src/all/yellownote/build.gradle @@ -0,0 +1,12 @@ +ext { + extName = 'YellowNote' + extClass = '.YellowNoteSourceFactory' + extVersionCode = 1 + isNsfw = true +} + +apply from: "$rootDir/common.gradle" + +dependencies { + implementation(project(':lib:i18n')) +} diff --git a/src/all/yellownote/res/mipmap-hdpi/ic_launcher.png b/src/all/yellownote/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..df0f96fe625c46ffd9822b2ae42233758292727f GIT binary patch literal 3390 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 Eg2^SpZU6uP literal 0 HcmV?d00001 diff --git a/src/all/yellownote/res/mipmap-xxhdpi/ic_launcher.png b/src/all/yellownote/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0bfcbda5fca1dcf7c9ffd98fc78c763ff770b2f6 GIT binary patch literal 8217 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 T+iPxSrvW`3W9>>!$B6#}c*A{1 literal 0 HcmV?d00001 diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/JsonPExt.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/JsonPExt.kt new file mode 100644 index 000000000..893fae055 --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/JsonPExt.kt @@ -0,0 +1,5 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import org.jsoup.nodes.Element + +fun Element.parentText(): String? = parent()?.text() diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/SimpleParsedHttpSource.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/SimpleParsedHttpSource.kt new file mode 100644 index 000000000..7017b8c4a --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/SimpleParsedHttpSource.kt @@ -0,0 +1,42 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element + +abstract class SimpleParsedHttpSource : ParsedHttpSource() { + + abstract fun simpleMangaSelector(): String + + abstract fun simpleMangaFromElement(element: Element): SManga + + abstract fun simpleNextPageSelector(): String? + + // region popular + override fun popularMangaSelector() = simpleMangaSelector() + override fun popularMangaNextPageSelector() = simpleNextPageSelector() + + override fun popularMangaFromElement(element: Element) = simpleMangaFromElement(element) + // endregion + + // region last + override fun latestUpdatesSelector() = simpleMangaSelector() + override fun latestUpdatesFromElement(element: Element) = simpleMangaFromElement(element) + + override fun latestUpdatesNextPageSelector() = simpleNextPageSelector() + // endregion + + // region search + override fun searchMangaSelector() = simpleMangaSelector() + override fun searchMangaFromElement(element: Element) = simpleMangaFromElement(element) + + override fun searchMangaNextPageSelector() = simpleNextPageSelector() + // endregion + + override fun chapterListSelector() = simpleMangaSelector() + override fun imageUrlParse(document: Document): String { + throw UnsupportedOperationException() + } + // endregion +} diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNote.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNote.kt new file mode 100644 index 000000000..3b6b906ae --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNote.kt @@ -0,0 +1,157 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.extension.all.yellownote.YellowNoteFilters.SortSelector +import eu.kanade.tachiyomi.extension.all.yellownote.YellowNotePreferences.baseUrl +import eu.kanade.tachiyomi.extension.all.yellownote.YellowNotePreferences.preferenceMigration +import eu.kanade.tachiyomi.lib.i18n.Intl +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.source.ConfigurableSource +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.model.UpdateStrategy +import eu.kanade.tachiyomi.util.asJsoup +import keiyoushi.utils.firstInstance +import keiyoushi.utils.getPreferences +import keiyoushi.utils.tryParse +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import java.text.SimpleDateFormat +import java.util.Locale + +class YellowNote( + override val lang: String, + private val subdomain: String? = null, +) : SimpleParsedHttpSource(), ConfigurableSource { + + override val baseUrl by lazy { preferences.baseUrl(subdomain) } + + override val name = "小黄书" + + override val supportsLatest = true + + override val client = network.cloudflareClient + + private val preferences = getPreferences { preferenceMigration() } + + override fun headersBuilder() = super.headersBuilder() + .add("Referer", "$baseUrl/") + + private val intl = Intl( + language = lang, + baseLanguage = YellowNoteSourceFactory.BASE_LANGUAGE, + availableLanguages = YellowNoteSourceFactory.SUPPORT_LANGUAGES, + classLoader = this::class.java.classLoader!!, + ) + + private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US) + + private val styleUrlRegex = """url\(['"]?([^'"]+)['"]?\)""".toRegex() + + override fun setupPreferenceScreen(screen: PreferenceScreen) { + YellowNotePreferences.buildPreferences(screen.context, intl) + .forEach(screen::addPreference) + } + + override fun simpleMangaSelector() = "div.article > div.list > div.item:not([class*=item exoclick_300x500])" + + override fun simpleMangaFromElement(element: Element): SManga { + if (element.hasClass("amateur")) { + return simpleMangaFromElementByAmateur(element) + } + + return SManga.create().apply { + val imgEl = element.selectFirst("img")!! + val titleAppend = element.selectFirst("div.tag > div")?.text()?.let { "($it)" }.orEmpty() + title = "${imgEl.attr("alt")}$titleAppend" + + thumbnail_url = imgEl.absUrl("src") + update_strategy = UpdateStrategy.ONLY_FETCH_ONCE + setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href")) + } + } + + // /amateurs + private fun simpleMangaFromElementByAmateur(element: Element) = SManga.create().apply { + val titleAppend = element.selectFirst("div.tag > div")?.text()?.let { "($it)" }.orEmpty() + title = "${element.selectFirst("div:nth-child(3)")!!.text()}$titleAppend" + + thumbnail_url = element.selectFirst(".img")?.attr("style") + ?.let { styleUrlRegex.find(it) } + ?.groupValues + ?.get(1) + + update_strategy = UpdateStrategy.ONLY_FETCH_ONCE + setUrlWithoutDomain(element.selectFirst("a[href]")!!.absUrl("href")) + } + + override fun simpleNextPageSelector() = "div.pager:first-of-type a[current] + a[href]" + + override fun popularMangaRequest(page: Int) = GET("$baseUrl/photos/sort-hot/$page.html", headers) + + override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/photos/$page.html", headers) + + override fun mangaDetailsParse(document: Document) = SManga.create().apply { + val tabEl = document.selectFirst("div#tab_1")!! + val titleAppend = tabEl.selectFirst("i.fa.fa-picture-o")?.parentText()?.let { "($it)" }.orEmpty() + title = "${tabEl.selectFirst("i.fa.fa-address-card-o")!!.parentText()!!}$titleAppend" + + author = tabEl.select("div.models > a").joinToString { it.text() } + genre = tabEl.select("div.contentTag").joinToString { it.text() } + status = SManga.COMPLETED + description = tabEl.selectFirst("i.fa.fa-calendar")?.text() + update_strategy = UpdateStrategy.ONLY_FETCH_ONCE + } + + override fun chapterFromElement(element: Element) = throw UnsupportedOperationException() + override fun chapterListParse(response: Response): List { + val doc = response.asJsoup() + val dateUploadStr = doc.selectFirst("i.fa.fa-calendar")?.text() + val dateUpload = dateFormat.tryParse(dateUploadStr) + val maxPage = doc.select("div.pager:first-of-type a:not([class])").last()?.text()?.toInt() ?: 1 + val basePageUrl = response.request.url.toString() + .removeSuffix(".html") + return (maxPage downTo 1).map { page -> + SChapter.create().apply { + chapter_number = 0F + setUrlWithoutDomain("$basePageUrl/$page.html") + name = "Page $page" + date_upload = dateUpload + } + } + } + + override fun pageListParse(document: Document): List { + return document.select("div.article.mask .photos img.cr_only") + .mapIndexed { i, imgEl -> Page(i, imageUrl = imgEl!!.absUrl("src")) } + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val categorySelector = filters.firstInstance() + val sortSelector = filters.firstInstance() + val uriPart = when { + query.isBlank() -> categorySelector.toUriPart() + else -> "photos/keyword-$query" + } + + val httpUrl = baseUrl.toHttpUrl().newBuilder() + .addPathSegments(uriPart) + .addPathSegment(sortSelector.toUriPart()) + .addPathSegments("$page.html") + .build() + return GET(httpUrl, headers) + } + + override fun getFilterList() = FilterList( + YellowNoteFilters.createSortSelector(intl), + Filter.Separator(), + Filter.Header(intl["filter.header.ignored-when-search"]), + YellowNoteFilters.createCategorySelector(intl), + ) +} diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteFilters.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteFilters.kt new file mode 100644 index 000000000..45710f175 --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteFilters.kt @@ -0,0 +1,139 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import eu.kanade.tachiyomi.lib.i18n.Intl +import eu.kanade.tachiyomi.source.model.Filter + +class YellowNoteFilters { + + data class SortOption(val name: String, val urlPart: String = "") { + override fun toString() = this.name + } + + class SortSelector(name: String, private val vals: Array) : + Filter.Select(name, vals) { + fun toUriPart() = vals[state].urlPart + } + + data class CategoryOption(val name: String, val uriPart: String) { + override fun toString() = this.name + } + + class CategorySelector(name: String, values: Array) : Filter.Select(name, values) { + fun toUriPart() = values[state].uriPart + } + + companion object { + fun createSortSelector(intl: Intl) = SortSelector( + intl["filter.sort.title"], + arrayOf( + SortOption(intl["filter.sort.option.last-update"]), + SortOption(intl["filter.sort.option.popularity"], "sort-hot"), + SortOption(intl["filter.sort.option.most-comments"], "sort-comment"), + SortOption(intl["filter.sort.option.latest-comments"], "sort-recent"), + ), + ) + + private fun themeCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.theme.xiuren-featured"], "photos/album-1"), + CategoryOption(intl["filter.category.option.theme.large-scale"], "photos/album-2"), + CategoryOption(intl["filter.category.option.theme.sex"], "photos/album-3"), + CategoryOption(intl["filter.category.option.theme.exposure"], "photos/album-4"), + CategoryOption(intl["filter.category.option.theme.cosplay"], "photos/album-5"), + CategoryOption(intl["filter.category.option.theme.sex-toy"], "photos/album-6"), + CategoryOption(intl["filter.category.option.theme.bondage"], "photos/album-7"), + CategoryOption(intl["filter.category.option.theme.shaved-pussy"], "photos/album-8"), + CategoryOption(intl["filter.category.option.theme.lesbian"], "photos/album-9"), + CategoryOption(intl["filter.category.option.theme.with-original-photos"], "photos/album-10"), + CategoryOption(intl["filter.category.option.theme.with-video"], "photos/album-11"), + CategoryOption(intl["filter.category.option.theme.amateur"], "amateurs"), + ) + + private fun chinaStudiosCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.chinese-studios-pans"], "photos/series-6310ce9b90056"), + CategoryOption(intl["filter.category.option.chinese-studios-wind-sings"], "photos/series-6666a7ac3ba9c"), + CategoryOption(intl["filter.category.option.chinese-studios-xing-se"], "photos/series-64f44d99ce673"), + CategoryOption(intl["filter.category.option.chinese-studios-huang-fu"], "photos/series-665f8bafab4bc"), + CategoryOption(intl["filter.category.option.chinese-studios-other-studios"], "photos/series-665f7d787d681"), + CategoryOption(intl["filter.category.option.chinese-studios-metcn"], "photos/series-5f1dcdeaee582"), + CategoryOption(intl["filter.category.option.chinese-studios-litu"], "photos/series-5f1d784995865"), + CategoryOption(intl["filter.category.option.chinese-studios-midnight-project"], "photos/series-638e5a60b1770"), + CategoryOption(intl["filter.category.option.chinese-studios-pandora"], "photos/series-5f23c44cd66bd"), + CategoryOption(intl["filter.category.option.chinese-studios-missleg"], "photos/series-5f2089564c6c2"), + CategoryOption(intl["filter.category.option.chinese-studios-iss"], "photos/series-646c69b675f3d"), + CategoryOption(intl["filter.category.option.chinese-studios-aiss"], "photos/series-5f15f389e993e"), + CategoryOption(intl["filter.category.option.chinese-studios-au"], "photos/series-5f60b98248a81"), + CategoryOption(intl["filter.category.option.chinese-studios-beijing-angel"], "photos/series-622c7f95220a4"), + CategoryOption(intl["filter.category.option.chinese-studios-wuji-works"], "photos/series-619a92aa1fa7a"), + CategoryOption(intl["filter.category.option.chinese-studios-pomelo"], "photos/series-676c3e9b90749"), + CategoryOption(intl["filter.category.option.chinese-studios-sk-silk"], "photos/series-5f382ba894af4"), + CategoryOption(intl["filter.category.option.chinese-studios-ddy"], "photos/series-5f15f727df393"), + CategoryOption(intl["filter.category.option.chinese-studios-dongguan-vgirls"], "photos/series-5f22ea422221c"), + CategoryOption(intl["filter.category.option.chinese-studios-youmei"], "photos/series-61b997728043b"), + ) + + private fun otherPhotosCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.other-photos-chinese-nude"], "photos/series-64be21c972ca4"), + CategoryOption(intl["filter.category.option.other-photos-korean-nude"], "photos/series-64be22b4a0fa0"), + CategoryOption(intl["filter.category.option.other-photos-taiwan-nude"], "photos/series-64be21ef4cc51"), + CategoryOption(intl["filter.category.option.other-photos-other-regions"], "photos/series-64be239ce73d4"), + ) + + private fun xiuRenCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.xiuren-all"], "photos/series-6660093348354"), + CategoryOption(intl["filter.category.option.xiuren-leaked"], "photos/series-66600a3a227ee"), + CategoryOption(intl["filter.category.option.xiuren-huayang"], "photos/series-5fc4ce40386af"), + CategoryOption(intl["filter.category.option.xiuren-mygirl"], "photos/series-5f1495dbda4de"), + CategoryOption(intl["filter.category.option.xiuren-imiss"], "photos/series-5f71afc92d8ab"), + CategoryOption(intl["filter.category.option.xiuren-miitao"], "photos/series-5f1dd5a7ebe9a"), + CategoryOption(intl["filter.category.option.xiuren-feilin"], "photos/series-5f14a3105d3e8"), + CategoryOption(intl["filter.category.option.xiuren-youwu"], "photos/series-60673bec9dd11"), + CategoryOption(intl["filter.category.option.xiuren-wings"], "photos/series-63d435352808c"), + CategoryOption(intl["filter.category.option.xiuren-ruisg"], "photos/series-61263de287e2f"), + ) + + private fun koreanStudiosCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.korean-studios-makemodel"], "photos/series-665f81885f103"), + CategoryOption(intl["filter.category.option.korean-studios-pure-media"], "photos/series-6224e755e21f4"), + CategoryOption(intl["filter.category.option.korean-studios-espacia-korea"], "photos/series-665a2385a2367"), + CategoryOption(intl["filter.category.option.korean-studios-loozy"], "photos/series-62888afad416b"), + ) + + private fun japaneseStudiosCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.japanese-studios-graphis"], "photos/series-6450b47c9db0b"), + CategoryOption(intl["filter.category.option.japanese-studios-kuni-scan"], "photos/series-66f9665804471"), + CategoryOption(intl["filter.category.option.japanese-studios-weekly-post-digital-photo"], "photos/series-66e68b9c96ab0"), + CategoryOption(intl["filter.category.option.japanese-studios-morning-sexy"], "photos/series-670d7142b3d88"), + CategoryOption(intl["filter.category.option.japanese-studios-prestige"], "photos/series-670791f5f2f0f"), + CategoryOption(intl["filter.category.option.japanese-studios-x-city"], "photos/series-66fb8cca706ae"), + CategoryOption(intl["filter.category.option.japanese-studios-friday"], "photos/series-66659e2d94489"), + CategoryOption(intl["filter.category.option.japanese-studios-super-pose-book"], "photos/series-62a0a15911f16"), + CategoryOption(intl["filter.category.option.japanese-studios-urabon"], "photos/series-6692ea004cc75"), + CategoryOption(intl["filter.category.option.japanese-studios-escape"], "photos/series-66603af933ec9"), + CategoryOption(intl["filter.category.option.japanese-studios-flash"], "photos/series-672a2029d6a32"), + ) + + private fun taiwanStudiosCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.taiwan-studios-jvid"], "photos/series-637b2029d2347"), + CategoryOption(intl["filter.category.option.taiwan-studios-fantasy-factory"], "photos/series-5f889afb37619"), + CategoryOption(intl["filter.category.option.taiwan-studios-tpimage"], "photos/series-5f7a0a80d3d66"), + ) + + private fun otherCategoryOptions(intl: Intl) = listOf( + CategoryOption(intl["filter.category.option.others-ai-photos"], "photos/series-6443d480eb757"), + ) + + fun createCategorySelector(intl: Intl) = CategorySelector( + intl["filter.category.title"], + listOf( + themeCategoryOptions(intl), + taiwanStudiosCategoryOptions(intl), + chinaStudiosCategoryOptions(intl), + otherCategoryOptions(intl), + koreanStudiosCategoryOptions(intl), + japaneseStudiosCategoryOptions(intl), + otherPhotosCategoryOptions(intl), + xiuRenCategoryOptions(intl), + ).flatten().toTypedArray(), + ) + } +} diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNotePreferences.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNotePreferences.kt new file mode 100644 index 000000000..14ae63886 --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNotePreferences.kt @@ -0,0 +1,75 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import android.content.Context +import android.content.SharedPreferences +import android.widget.Toast +import androidx.preference.EditTextPreference +import eu.kanade.tachiyomi.lib.i18n.Intl +import okhttp3.HttpUrl.Companion.toHttpUrl + +object YellowNotePreferences { + + private const val PS_KEY_ROOT = "XChina" + private const val PS_KEY_DOMAIN = "$PS_KEY_ROOT::DOMAIN" + private const val PS_KEY_DOMAIN_DEFAULT = "$PS_KEY_DOMAIN::DEFAULT" + private const val PS_KEY_DOMAIN_OVERRIDE = "$PS_KEY_DOMAIN::OVERRIDE" + + private const val DEFAULT_DOMAIN = "https://xchina.co" + + private fun SharedPreferences.getStringOrDefaultIfBlank(key: String, defValue: String): String { + val value = getString(key, defValue)!! + return value.ifBlank { defValue } + } + + internal fun SharedPreferences.preferenceMigration() { + // refresh when DEFAULT_DOMAIN update + val defaultDomain = getStringOrDefaultIfBlank(PS_KEY_DOMAIN_DEFAULT, DEFAULT_DOMAIN) + if (DEFAULT_DOMAIN != defaultDomain) { + edit() + .putString(PS_KEY_DOMAIN_DEFAULT, DEFAULT_DOMAIN) + .putString(PS_KEY_DOMAIN_OVERRIDE, DEFAULT_DOMAIN) + .apply() + } + } + + internal fun SharedPreferences.baseUrl(subdomain: String?): String { + val httpUrl = getStringOrDefaultIfBlank(PS_KEY_DOMAIN_OVERRIDE, DEFAULT_DOMAIN).toHttpUrl() + + val newHost = when { + httpUrl.host.split('.').size > 2 || subdomain == null -> httpUrl.host + else -> "$subdomain.${httpUrl.host}" + } + + return httpUrl.newBuilder() + .scheme("https") + .host(newHost) + .build() + .toString() + .removeSuffix("/") + } + + internal fun buildPreferences(context: Context, intl: Intl): List { + return listOf( + EditTextPreference(context).apply { + key = PS_KEY_DOMAIN_OVERRIDE + title = intl["config.domain.title"] + summary = intl["config.domain.summary"] + dialogTitle = intl["config.domain.dialog.title"] + dialogMessage = "${intl["config.domain.dialog.message"]}$DEFAULT_DOMAIN" + + setDefaultValue(DEFAULT_DOMAIN) + setOnPreferenceChangeListener { _, newValue -> + try { + (newValue as String).toHttpUrl() + } catch (e: IllegalArgumentException) { + Toast.makeText(context, intl["config.domain.toast.changed-failed"], Toast.LENGTH_LONG).show() + return@setOnPreferenceChangeListener false + } + + Toast.makeText(context, intl["config.domain.toast.changed-success"], Toast.LENGTH_LONG).show() + true + } + }, + ) + } +} diff --git a/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteSourceFactory.kt b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteSourceFactory.kt new file mode 100644 index 000000000..f458324ed --- /dev/null +++ b/src/all/yellownote/src/eu/kanade/tachiyomi/extension/all/yellownote/YellowNoteSourceFactory.kt @@ -0,0 +1,25 @@ +package eu.kanade.tachiyomi.extension.all.yellownote + +import eu.kanade.tachiyomi.source.SourceFactory + +class YellowNoteSourceFactory : SourceFactory { + + companion object { + const val BASE_LANGUAGE = "en" + val SUPPORT_LANGUAGES = setOf( + "en", + "es", + "ko", + "zh-Hans", + "zh-Hant", + ) + } + + override fun createSources() = listOf( + YellowNote("en", "en"), + YellowNote("es", "es"), + YellowNote("ko", "kr"), + YellowNote("zh-Hans"), + YellowNote("zh-Hant", "tw"), + ) +}