Closed Kagami closed 6 years ago
Там вообще самописный движок. Заебeтесь интегрироваться с ним .
Проблема в том, що там контент генерируется внутренними скриптами. Они грузят json, и с него уже строят страницу. При загрузке страницы же куклоскрипт видит дырку от бублика вместо контента. Ладно, фиг с ним, це я победил с помощью костыля, откладывая исполнение куклы. Мало того, структура постов и тредов очень корявая, некоторые контейнеры вообще бкз классов и id, и структура эта различная на странице и в треде. Черт ногу сломит, в общем. Ну да ладно.
Теперь возникла проблема - svg на странице не отображаются. Никак. В чем причина - не нашел, да и нема у меня на это времени, в последнее время оченно занят. Ежели вы разберетесь с отображением SVG, тогда можно будет двигаться далее.
Пикрелейтед:
Дифф для поддержки 0chan.hk:
@@ -13132,10 +13132,34 @@ function getImageBoard(checkDomains, checkEngines) {
return false;
}
}
ibDomains['0chan.eu'] = _0chanEu;
+ class _0chanHk extends BaseBoard {
+ constructor(prot, dm) {
+ super(prot, dm);
+ this.nul = true;
+
+ this.cReply = 'block post';
+ this.qDForm = '#content > div > .threads-scroll-spy + div, .threads > div:first-of-type';
+ this.qOPost = '.post-op';
+ this.qPostRef = '.post-header';
+ this.qPostMsg = '.post-body-message';
+ this.qRPost = '.block.post:not(.post-op)';
+ }
+ get qThread() {
+ return 'div[style="margin-top: 20px; margin-bottom: 40px;"] > div, .thread > div';
+ }
+ getPNum(post) {
+ return +$q('a[name]', post).name;
+ }
+ getTNum(op) {
+ return +$q('a[name]', op).name;
+ }
+ }
+ ibDomains['0chan.hk'] = _0chanHk;
+
class _2chan extends BaseBoard {
constructor(prot, dm) {
super(prot, dm);
this.qDForm = 'form:not([enctype])';
@@ -15742,13 +15766,19 @@ function* runMain(checkDomains, cfgPromise) {
}
if(!aib) {
aib = getImageBoard(checkDomains, true);
}
let formEl = $q(aib.qDForm + ', form[de-form]');
+ console.log('Trying to run');
if(!formEl) {
+ if(aib.nul && !$id('app').hasChildNodes()) {
+ console.log('Delform not found');
+ setTimeout(async(runMain.bind(null, checkDomains, cfgPromise)), 2e3)
+ }
return;
}
+ console.log('Delform loading success!');
Logger.log('Imageboard check');
if(!locStorage) {
if(!checkStorage()) {
return;
}
Подозреваю, что дело в
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
Тег <html>
на нульчане не имеет атрибута xmlns
.
У меня всё нормально в последнем хромиуме на линуксе отсюда https://download-chromium.appspot.com/
cc @klkvsk
Firefox 52.0.2 SVG не оторбажаются, хотя стили применяются.
Только форме настроек надо z-index добавить, а то её посты перекрывают и на табы не получается кликать. Ну или какой-нибудь другой фикс.
Там пилить еще много чего. Я запилил только базовую поддержку, половина функционала не работает. Давайте сначала разберемся с SVG в Firefox'e.
На 8ch.net аналогичный доктайп и без неймспейсов, но работает. Возможно с каким-нибудь стилем сайта конфликтует.
Нашёл причину проблемы. Это использование тега <base>
+ SVG URIs.
Проблема достаточно известная, много где описана:
Сильно пока не вникал, в качестве временного хака можно добавить document.querySelector("base").remove()
перед addSVGIcons()
.
@Kagami, спасибо! Будем посмотреть.
Подобный костыль уже есть для 2chan: https://github.com/SthephanShinkufag/Dollchan-Extension-Tools/blob/17c512992fd042d44bce6990ca58e544e89ce555/src/Dollchan_Extension_Tools.es6.user.js#L13181
Только надо будет проверить, будет ли 0chan работать без этого тега.
Я слегка потыкал, вроде работает и без base
. Хотя можно и получше способ попробовать поискать.
Тут ещё дело в том, что новонульч SPA и можно переходить между разделами/тредами без перезагрузки страницы. А куклоскрипт не отслеживает вызовы pushState.
новонульч SPA и можно переходить между разделами/тредами без перезагрузки страницы. А куклоскрипт не отслеживает вызовы pushState.
А вот это, кстати, проблема. Перехожу в тред, и кукле шиш - контент поменялся на лету. Бида.
Можно отслеживать при помощи MutationObserver
- в нём нет оверхеда если правильно инициализировать (следить за как можно меньшим количеством элементов). Только в некроопере работать не будет. Делформа у нас уже создаётся отдельным объектом и активно используется для загрузки страниц.
Тогда придется как-то убивать все объекты в памяти, касаемые контента, постов и прочего.
Они разве уже не убиваются? Я имею в виду, в кукле есть встроенное обновление тредов без перезагрузки и там используется тот же самый механизм, что и при начальной загрузке скрипта.
Ну ті переходишь с одного треда в другой. Или даже в другую доску. По сути, нужно заново инициализировать скрипт, убивая все, что использовалось ранее.
А, ну тогда только нужно провести аудит функций которые работают только внутри тредов. Плюс проверить все глобальные переменные. А так скрипт уже должен нормально работать на одностраничных приложениях.
Как вариант можно удалять событие onclick на ссылках на другие треды/разделы, чтобы переход по ним вызывал перезагрузку страницы. Тогда будет проще добиться корректной работы.
удалять событие onclick на ссылках на другие треды/разделы, чтобы переход по ним вызывал перезагрузку страницы
Спасибо, пригорело.
Давайте пока хотя бы так: window.app.$bus.on('refreshContentDone', () => { ваша инициализация })
@klkvsk спок, братишка, ваш single page application никуда не денется, я уже все это подебил с помощью MutationObserver. Тут другие баги вылязят, однако. Много еще чего допиливать.
Блджад. Номера оп-постов не совпадают с нумерацией тредов. А в кукле на это многое завязано. Спеллы, скрытие, и т.д. и т.п. Теперь точно полскрипта переписывать :(
Да, весьма странное решение. Может пофиксить каким-нибудь костылём, например считать номер треда равным ОП-посту, а где-нибудь в глубине, там, где XHR-запросы делаются или что ещё, добавить спешл-кейс для нульчана? Ну или выкатить хотя бы базовый функционал, чтобы хоть какая-то поддержка была, а остальное уже потом инкрементально доделывать.
там, где XHR-запросы делаются или что ещё, добавить спешл-кейс для нульчана
Так и сделаю, пожалуй.
выкатить хотя бы базовый функционал
Разберусь с инфинитискроллом и выкачу. Нужно научить куклу перехватывать встроенную подгрузку тредов. Либо порезать ее и запилить инфинитискролл на основе кукольного.
Мда, ожидаемо. При попытке получить тред аяксом, получаем:
<!DOCTYPE html><html>
<head>
<meta charset=utf-8><base href=/ ><meta name=description content="">
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
<link rel=icon href=/static/favicon.ico><link href=/static/css/app.9a1165aabdb5f1f6622bbd92281ad0fc.css rel=stylesheet>
</head>
<body>
<div id=app></div>
<script type=text/javascript src=/static/js/manifest.48fefcd5fe424fc95355.js></script>
<script type=text/javascript src=/static/js/vendor.d72f88216d1eec66f70b.js></script>
<script type=text/javascript src=/static/js/app.014c6fc9b807acbe3ebf.js></script>
</body>
</html>
Контейнер, который должен содержать тред — пуст. Надо пользовать API:
https://0chan.hk/api/thread?thread=2390&after=32496&session=rg8lrxtkz1eswczofxppw8rmnlpg220x
Только вот где брать ключ сессии, хер его знает. Печально.
sessionId лежит либо в localStorage, либо получается из заголовка X-Session
GET-запроса на /api/session
. Т.к. код нульчана сам его получает, то идентификатор всегда должен присутствовать в localStorage.
Ну это на тот случай, если понадобится. Документацию на API пока не завезли, приходится реверс-инжирить и читать минифицированные исходники.
Есть новости? Можно как-нибудь помочь?
Признаю, что поддержка этой борды невозможна, натыкаюсь на подводные камни на каждом шагу. А еще лень и некогда. И допиливать еще ОЧЕНЬ много. Мне стыдно выкладывать то, что сейчас есть.
Жаль. Может добавить под галку «экспериментальная поддержка 0chan (много багов)» всё, что есть? Глядишь, люди потом пришлют пулл-реквесты с исправлениями. По крайней мере проще улучшить, чем пилить с нуля.
Еще может чутка поковыряю. С формой ответа просто беда. По сути, формы то никакой нет, все делается и отправляется внутренними скриптами движка. А там черт ногу сломит, нужно много времени провести на реверс-инжиниринг.
Публичного API у них нет? Вот пусть сделают, а потом уже и будем пилить скрипт.
Есть API, просто (пока) не документированное. Я могу отреверсить, только скажите, какие действия нужны в первую очередь. Отправка сообщения и создание треда?
А смысл? Они его в любой момент поменять могут. Пусть стабилизируется сначала, а потом уже можно и думать что и как.
@SthephanShinkufag а можешь выкладывать патчи частями, не связанные с самим 0chan? Там например поддержку построения ОП-постов на основе JSON и прочее.
Да ладно, хер с апи - я даже банально не могу форму к треду привязать - с нулевой страницы идет попытка создания треда вместо ответа на пост. Форма в треде и на доске ничем не отличается, кроме принудительной ссылки (кстати, затея с принудительной ссылкой в тексте мне жутко не нравится, тупо ефг сделал). Все на внутренних скриптах, чо там и где - хер его знает.
Возможно, в там два разных апи на создаение треда и ответа на пост, да.
А смысл? Они его в любой момент поменять могут.
Ну так на любой борде может появиться breaking change. Не думаю, что оно будет очень часто меняться. А на редкие изменения просто реагировать после багрепорта.
Ок, я тогда поковыряю API и отпишусь.
Один товарищ покопался и скинул такое описание (форматирование моё):
идёт POST-запрос на https://0chan.hk/api/thread/reply?parent=НОМЕР_СООБЩЕНИЯ_НА_КОТОРОЕ_ИДЁТ_ОТВЕТ&session=СЕССИЯ содержимое такое:
{"board": null, "thread": null, "parent": null, "message": "ТЕКСТ_СООБЩЕНИЯ",
"images": [], "captcha": null}
дальше идёт запрос https://0chan.hk/api/thread?thread=НОМЕР_ТРЕДА&after=НОМЕР_СООБЩЕНИЯ_ПОСЛЕ_КОТОРОГО_ПОДГРУЗИТЬ_СООБЩЕНИЯ&session=СЕССИЯ
POST-запрос на https://0chan.hk/api/thread/create?board=ИМЯ_БОРДЫ_ОН_ЖЕ_ТЕКСТОВЫЙ_ИДЕНТИФИКАТОР&session=СЕССИЯ содержимое:
{"board": null, "thread": null, "parent": null, "message": "СООБЩЕНИЕ",
"images": [], "captcha": null}
это если без картинки
сначала делается multipart/form-data POST-запрос на https://0chan.hk/api/attachment/upload?session=СЕССИЯ с содержимым:
------BoundaryТУТКАКАЯТОХУЙНЯСЛУЧАЙНАЯ
Content-Disposition: form-data; name="file"; filename="mi8WwGt.jpg"
Content-Type: image/jpeg
<байты картинки>
------BoundaryТУТКАКАЯТОХУЙНЯСЛУЧАЙНАЯ
приходит ответ такого рода:
{
"attachment": {
"embed": null,
"id": "39747",
"images": {
"original": {
"height": "400",
"id": "159438",
"name": "170415ejsqqmwzyffd.jpg",
"path": "17/04/15/170415ejsqqmwzyffd.jpg",
"server": "s01",
"size_kb": 41.99,
"url": "//s01.0chan.hk/17/04/15/170415ejsqqmwzyffd.jpg?hash=XXX&exp=1492300800",
"width": "600"
},
"thumb_100px": {
"height": "67",
"id": "159439",
"name": "170415ejsqqmwzyffd-100.jpg",
"path": "17/04/15/170415ejsqqmwzyffd-100.jpg",
"server": "s01",
"size_kb": 2.54,
"url": "//s01.0chan.hk/17/04/15/170415ejsqqmwzyffd-100.jpg?hash=XXX&exp=1492300800",
"width": "100"
},
"thumb_200px": {
"height": "134",
"id": "159440",
"name": "170415ejsqqmwzyffd-200.jpg",
"path": "17/04/15/170415ejsqqmwzyffd-200.jpg",
"server": "s01",
"size_kb": 7.65,
"url": "//s01.0chan.hk/17/04/15/170415ejsqqmwzyffd-200.jpg?hash=XXX&exp=1492300800",
"width": "200"
},
"thumb_400px": {
"height": "267",
"id": "159441",
"name": "170415ejsqqmwzyffd-400.jpg",
"path": "17/04/15/170415ejsqqmwzyffd-400.jpg",
"server": "s01",
"size_kb": 22.45,
"url": "//s01.0chan.hk/17/04/15/170415ejsqqmwzyffd-400.jpg?hash=XXX&exp=1492300800",
"width": "400"
}
},
"isNsfw": false,
"token": "t6yas3b2pd662jng"
},
"ok": true
}
дальше делается запрос создания как без каринки, только в содержимом уже:
{"board": null, "thread": null, "parent": null, "message": "СООБЩЕНИЕ",
"images": ["t6yas3b2pd662jng"], "captcha":null}
видно что в images
лежит token
который пришёл в ответе.
когда запрос обработается приходит ответ с тредом
кстати когда пост создаёшь тоже приходит пост
когда делаем POST-запрос на создание, тогда в ответ приходит такой жсон
{"error": 403, "message": "captcha required", "details": {"require": "captcha"}}
дальше надо сделать GET-запрос https://0chan.hk/api/captcha?session=сессия придёт жсон ответ:
{"captcha":"какой-то-текстовый-ид", "image": "data:image/png;base64,xxx"}
как видно base64 картинка с капчей делаем GET-запрос https://0chan.hk/api/captcha?captcha=этоттектовыйид&answer=ответнакапчувurlencodeкажетсякорочспроцентиками&session=сессия приходит жсон ответ если на капчу ответ неправильный:
{"captcha": "новыйиддлякапчи", "ok": false}
а когда правильный:
{"captcha": "новыйидкапчи", "ok": true}
после чего делаем повторный постзапрос https://0chan.hk/api/thread/create?board=имяборды&session=сессия&captcha=новыйидкапчи cо стандартым содержимым жсона для создания треда
@SthephanShinkufag класс, большое спасибо. Этот баг закрываем или оставить?
Пусть здесь будет general discuss по нульчану. Можете аще пейсать сюда замеченных вами баги (кроме инфинитискролла и формы ответа, конечно). Будем допиливать потихоньку.
Дублируется плеер ютуба. Пример: https://0chan.hk/test/1311
Не работает нулевая. То есть https://0chan.hk/b - работает, https://0chan.hk/ пишет в консоль
VM2599:3774 Generator throw: TypeError: Cannot read property 'querySelectorAll' of null
at $Q (eval at E_c (:3:114), <anonymous>:3499:14)
at Function.gen (eval at E_c (:3:114), <anonymous>:15406:18)
at Function.init (eval at E_c (:3:114), <anonymous>:15444:11)
at DelForm.addStuff (eval at E_c (:3:114), <anonymous>:20069:12)
at runMain$ (eval at E_c (:3:114), <anonymous>:21068:21)
at tryCatch (eval at E_c (:3:114), <anonymous>:2411:40)
at Generator.invoke [as _invoke] (eval at E_c (:3:114), <anonymous>:2617:22)
at Generator.prototype.(anonymous function) [as next] (eval at E_c (:3:114), <anonymous>:2436:21)
at continuer (eval at E_c (:3:114), <anonymous>:3772:30)
at onFulfilled (eval at E_c (:3:114), <anonymous>:3786:12)
at eval (eval at E_c (:3:114), <anonymous>:3791:11)
at eval (eval at E_c (:3:114), <anonymous>:18193:24)
at r (https://0chan.hk/static/js/vendor.290177527e891c936288.js:45:47985)
continuer @ VM2599:3774
onFulfilled @ VM2599:3786
(anonymous) @ VM2599:3791
(anonymous) @ VM2599:18193
r @ vendor.290177527e891c936288.js:45
VM2599:3499 Uncaught (in promise) TypeError: Cannot read property 'querySelectorAll' of null
at $Q (eval at E_c (:3:114), <anonymous>:3499:14)
at Function.gen (eval at E_c (:3:114), <anonymous>:15406:18)
at Function.init (eval at E_c (:3:114), <anonymous>:15444:11)
at DelForm.addStuff (eval at E_c (:3:114), <anonymous>:20069:12)
at runMain$ (eval at E_c (:3:114), <anonymous>:21068:21)
at tryCatch (eval at E_c (:3:114), <anonymous>:2411:40)
at Generator.invoke [as _invoke] (eval at E_c (:3:114), <anonymous>:2617:22)
at Generator.prototype.(anonymous function) [as next] (eval at E_c (:3:114), <anonymous>:2436:21)
at continuer (eval at E_c (:3:114), <anonymous>:3772:30)
at onFulfilled (eval at E_c (:3:114), <anonymous>:3786:12)
at eval (eval at E_c (:3:114), <anonymous>:3791:11)
at eval (eval at E_c (:3:114), <anonymous>:18193:24)
at r (https://0chan.hk/static/js/vendor.290177527e891c936288.js:45:47985)
$Q @ VM2599:3499
gen @ VM2599:15406
init @ VM2599:15444
addStuff @ VM2599:20069
runMain$ @ VM2599:21068
tryCatch @ VM2599:2411
invoke @ VM2599:2617
prototype.(anonymous function) @ VM2599:2436
continuer @ VM2599:3772
onFulfilled @ VM2599:3786
(anonymous) @ VM2599:3791
(anonymous) @ VM2599:18193
r @ vendor.290177527e891c936288.js:45
А у меня работает. Браузер, тип установки скрипта?
Я так понял, это какая-то опера с Violentmonkey? Версия оперы?
@SthephanShinkufag нет, это chrome версия 58.0.3029.81, tampermonkey 4.2.7, кукла v17.2.13.0.9dbef43 теперь уже v17.2.13.0.b1b0328.
Алсо:
**ВНЕЗАПНО**
вместо ВНЕЗАПНО
2.1. Время выводит в unix формате в виде 1492636080.
Короче весь пост выдается без изменений в "сыром" виде.Оно как то рандомно работает. Сначала раз 10 нормально грузит нулевую, но при подзагрузке не выдает треды, то потом вообще борду не грузит с ошибкой в логе.
Время и разметка исправлены. Чтобы починить нажатие по F5 на доске, надо научить скрипт строить доску с тредами из jsona.
Плавающая форма ответа уезжает куда-то за пределы страницы и не имеет кнопок закрытия и прикрепления обратно. Можно "вытащить" руками.
Пощу, чтобы не потерять: 0chan API
Поддержка 0chan.hk
прекращена, весь код убран.
0chan.hk
лежит и неизвестно что с ним будет.
Слишком много чего надо было допиливать, работал только базовый функционал, да и то через одно место. Можно сказать, толком ничего не работало. Проще выпилить всё вообще.
https://0chan.hk/ Новый, подозреваю что нестандартный движок.