Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sources/ru.desu/res/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"info": {
"id": "ru.desu",
"name": "Desu",
"version": 7,
"version": 8,
"url": "https://desu.uno",
"contentRating": 2,
"languages": [
Expand Down
12 changes: 9 additions & 3 deletions sources/ru.desu/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ pub fn apply_headers(request: Request) -> Request {
)
}

/// The `/api/...` endpoints return JSON; pin `Accept` so a content-negotiating
/// backend never answers these requests with an HTML page.
pub fn apply_api_headers(request: Request) -> Request {
apply_headers(request).header("Accept", "application/json")
}

fn format_errors(errors: Option<Vec<DesuError>>) -> String {
errors
.map(|errs| {
Expand All @@ -43,7 +49,7 @@ fn format_errors(errors: Option<Vec<DesuError>>) -> String {

pub fn fetch_by_id(id: &str) -> Result<DesuItem> {
let url = format!("{}/{}", get_base_api_url(), id);
let response = apply_headers(Request::get(url)?).json_owned::<DesuMangaResponse>()?;
let response = apply_api_headers(Request::get(url)?).json_owned::<DesuMangaResponse>()?;

if let Some(res) = response.manga {
Ok(res)
Expand All @@ -58,7 +64,7 @@ pub fn fetch_by_id(id: &str) -> Result<DesuItem> {

pub fn fetch_chapters(id: &str) -> Result<Vec<DesuChapter>> {
let url = format!("{}/{}/chapters", get_base_api_url(), id);
let response = apply_headers(Request::get(url)?).json_owned::<DesuChaptersResponse>()?;
let response = apply_api_headers(Request::get(url)?).json_owned::<DesuChaptersResponse>()?;

if let Some(chapters) = response.chapters {
Ok(chapters
Expand All @@ -81,7 +87,7 @@ pub fn fetch_chapter_pages(manga_id: &str, chapter_id: &str) -> Result<Vec<Strin
manga_id,
chapter_id
);
let response = apply_headers(Request::get(url)?).json_owned::<DesuChapterResponse>()?;
let response = apply_api_headers(Request::get(url)?).json_owned::<DesuChapterResponse>()?;

if let Some(chapter) = response.chapter {
Ok(chapter
Expand Down
6 changes: 3 additions & 3 deletions sources/ru.desu/src/ranobe.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::auth::{AuthedRequest, require_login};
use crate::helpers::{apply_headers, get_base_url};
use crate::helpers::{apply_api_headers, apply_headers, get_base_url};
use crate::keys::{ranobe_key, ranobe_slug};
use crate::models::{DesuChapter, DesuChaptersResponse};
use crate::settings::{eng_title, path_on_site, ranobe_cover_preview, rewrite_media_url};
Expand Down Expand Up @@ -229,7 +229,7 @@ fn chapter_id_from_api_view_url(

fn fetch_ranobe_chapter_records(book_id: &str) -> Result<Vec<DesuChapter>> {
let url = format!("{}/api/ranobe/{book_id}/chapters", get_base_url());
let response = apply_headers(Request::get(url)?).send()?;
let response = apply_api_headers(Request::get(url)?).send()?;
if response.status_code() >= 400 {
bail!(
"HTTP {} while fetching Ranobe chapter list",
Expand Down Expand Up @@ -570,7 +570,7 @@ pub fn fetch_ranobe_chapter_pages(slug: &str, chapter: &Chapter) -> Result<Vec<P
let base = get_base_url();
let title_url = format!("{base}/ranobe/{slug}/");
let referer = chapter.url.as_deref().unwrap_or(title_url.as_str());
let response = apply_headers(Request::get(url)?)
let response = apply_api_headers(Request::get(url)?)
.header("Referer", referer)
.send()?;
if response.status_code() == 401 {
Expand Down
2 changes: 1 addition & 1 deletion sources/zh.copymanga/res/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "zh.copymanga",
"name": "拷貝漫畫",
"altNames": ["拷贝漫画"],
"version": 23,
"version": 24,
"urls": [
"https://www.copy5000.com",
"https://www.copy4000.com",
Expand Down
1 change: 1 addition & 0 deletions sources/zh.copymanga/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub fn login(username: &str, password: &str) -> Result<()> {
"application/x-www-form-urlencoded;charset=UTF-8",
)
.header("X-Requested-With", "XMLHttpRequest")
.header("Accept", "application/json")
.body(body)
.send()?;

Expand Down
11 changes: 9 additions & 2 deletions sources/zh.copymanga/src/favorites.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,15 @@ fn to_manga(comic: CollectComic) -> Manga {
fn fetch_collect_page(page: i32) -> Result<MangaPageResult> {
let url = collect_page_url(&base_url()?, page);

let mut response = Request::get(&url)?.authed()?.send()?;
let mut response = Request::get(&url)?
.authed()?
.header("Accept", "application/json")
.send()?;
if response.status_code() == 401 && try_relogin() {
response = Request::get(&url)?.authed()?.send()?;
response = Request::get(&url)?
.authed()?
.header("Accept", "application/json")
.send()?;
}
if response.status_code() == 401 {
bail!("登入已失效,請重新在設定中登入");
Expand Down Expand Up @@ -429,6 +435,7 @@ fn set_collect_once(url: &str, body: &str) -> CollectWriteAttempt {
"application/x-www-form-urlencoded;charset=UTF-8",
)
.header("X-Requested-With", "XMLHttpRequest")
.header("Accept", "application/json")
.header("Cookie", &format!("token={token}"))
.header("Authorization", &format!("Token {token}"))
.body(body)
Expand Down
8 changes: 7 additions & 1 deletion sources/zh.copymanga/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,17 @@ impl Url<'_> {

pub fn request(&self) -> Result<Request> {
let url = self.to_string()?;
let request = Request::get(url)?.header(
let mut request = Request::get(url)?.header(
"User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) \
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0.1 Safari/605.1.15",
);
// The API endpoints content-negotiate (Django REST framework): without an
// explicit `Accept` header, hosts that inject a browser header suite get
// the browsable-API HTML page instead of the JSON envelope.
if self.is_search() || self.is_chapter_list() {
request.set_header("Accept", "application/json");
}
Ok(request)
}

Expand Down
2 changes: 1 addition & 1 deletion sources/zh.relamanhua/res/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"info": {
"id": "zh.relamanhua",
"name": "熱辣漫畫",
"version": 2,
"version": 3,
"urls": [
"https://www.manga2026.com",
"https://www.manga2025.com",
Expand Down
7 changes: 7 additions & 0 deletions sources/zh.relamanhua/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ impl Url<'_> {
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15",
);

// The API endpoints content-negotiate (Django REST framework): without an
// explicit `Accept` header, hosts that inject a browser header suite get
// the browsable-API HTML page instead of the JSON envelope.
Comment on lines +39 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments like this are verbose and should be rephrased to be more understandable.

if self.is_search() || self.is_chapter_list() {
request.set_header("Accept", "application/json");
}

if self.is_chapter_list() {
request.set_header("dnts", "1");
}
Expand Down
Loading