...
This commit is contained in:
parent
2a25b49baa
commit
1272c91430
@ -115,8 +115,8 @@ dependencies {
|
||||
// implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
||||
// https://mvnrepository.com/artifact/org.mozilla.geckoview/geckoview
|
||||
implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
|
||||
|
||||
|
||||
implementation("com.vladsch.flexmark:flexmark-all:0.64.0")
|
||||
// implementation 'com.vladsch.flexmark:flexmark-all:0.64.8'
|
||||
// implementation("org.opencv:opencv-android:4.11.0")
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
version: '3'
|
||||
services:
|
||||
couchdb:
|
||||
image: couchdb:latest
|
||||
container_name: couchdb
|
||||
restart: always
|
||||
ports:
|
||||
- "5984:5984" # 외부접근: 5984포트
|
||||
environment:
|
||||
- COUCHDB_USER=obsidian
|
||||
- COUCHDB_PASSWORD=HiVi88131921
|
||||
volumes:
|
||||
- ./data:/opt/couchdb/data
|
||||
@ -74,13 +74,7 @@ port.onMessage.addListener(response => {
|
||||
}
|
||||
break;
|
||||
case "saveContent":{
|
||||
sendMessage(
|
||||
{
|
||||
type: "SHOWVIEWER",
|
||||
contents : document.documentElement.outerHTML
|
||||
}
|
||||
);
|
||||
|
||||
scrollToLazyImg()
|
||||
}
|
||||
default:
|
||||
port.postMessage(`Received: ${JSON.stringify(response)}`);
|
||||
@ -121,11 +115,6 @@ if(document.querySelector("#html_encoder_div")) {
|
||||
}
|
||||
);
|
||||
}
|
||||
// else {
|
||||
// sendMessage({type:"MSG",msg:"connected has Nothings"});
|
||||
// loadComplete()
|
||||
// }
|
||||
|
||||
|
||||
function getList(children) {
|
||||
// port.postMessage("Start of getList!" + children);
|
||||
@ -213,7 +202,7 @@ function scrollByPercent(current , max) {
|
||||
const moveAmount = pageHeight / max;
|
||||
window.scrollTo({ top: moveAmount * current, behavior: "smooth" });
|
||||
}
|
||||
document.querySelector(".header__inner")
|
||||
|
||||
function scrollByPercentUpDown(isToDown , max) {
|
||||
const pageHeight = Math.max(
|
||||
document.body.scrollHeight,
|
||||
@ -227,364 +216,68 @@ function scrollByPercentUpDown(isToDown , max) {
|
||||
const moveAmount = Math.max(pageHeight / max,150);
|
||||
window.scrollTo({ top: currentScroll + (moveAmount * isToDown) , behavior: "smooth" });
|
||||
}
|
||||
|
||||
function loadComplete() {
|
||||
// try {port.postMessage(JSON.stringify({type: "NotRegistered"}));}catch (e) {}
|
||||
}
|
||||
function sendMessage(msg) {
|
||||
port.postMessage(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function toast(msg) {
|
||||
port.postMessage(JSON.stringify({type:"MSG",msg:msg}));
|
||||
}
|
||||
var time1 = null
|
||||
|
||||
var mainContentsEl = null
|
||||
if (port) {
|
||||
sendMessage({type: "MSG", msg:"connect prot"});
|
||||
sendMessage({type: "MSG", msg: "connect prot"});
|
||||
time1 = setTimeout(autoScrollAndSave(false), 2000)
|
||||
}
|
||||
|
||||
function scrollToLazyImg() {
|
||||
(function(autoScrollAndSave){
|
||||
// 한 번에 이동할 픽셀
|
||||
const step = 200;
|
||||
// 반복 간격(ms) (느릴수록 로딩에 더 여유 생김)
|
||||
const delay = 600;
|
||||
// 스크롤 현재 위치 추적
|
||||
let currentY = window.scrollY;
|
||||
let maxY = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight
|
||||
);
|
||||
|
||||
|
||||
time1 = setTimeout(
|
||||
|
||||
|
||||
function(){
|
||||
if (location.hostname.search("clien") > -1 && document.querySelectorAll('[class^="view_top"]')) {
|
||||
document.querySelectorAll('[class^="view_top"]').forEach(e => e.remove())
|
||||
}
|
||||
|
||||
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[id^="id_mbv"]')) {
|
||||
document.querySelectorAll('[id^="id_mbv"]').forEach(e => e.remove())
|
||||
}
|
||||
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[class^="basic-banner"]')) {
|
||||
document.querySelectorAll('[class^="basic-banner"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelector(".top_google_ad_space")) {
|
||||
document.querySelector(".top_google_ad_space").remove()
|
||||
}
|
||||
if (document.querySelectorAll(".adv-group")) {
|
||||
document.querySelectorAll(".adv-group").forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div-gpt-ad"]')) {
|
||||
document.querySelectorAll('[id^="div-gpt-ad"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.location.href.search("reddit") > -1) {
|
||||
if (document.querySelector('#xpromo-bottom-sheet')) {
|
||||
document.querySelector('#xpromo-bottom-sheet').remove()
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div_adnmore_area"]')) {
|
||||
document.querySelectorAll('[id^="div_adnmore_area"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div_adnmore_area"]')) {
|
||||
document.querySelectorAll('[id^="div_adnmore_area"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[class^="adv-groupno"]')) {
|
||||
document.querySelectorAll('[class^="adv-groupno"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[class^="code-block"]')) {
|
||||
document.querySelectorAll('[class^="code-block"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('.ad-template')) {
|
||||
document.querySelectorAll('.ad-template').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
if (document.querySelectorAll('[class^="popupBanner_w popupOpen"]')) {
|
||||
document.querySelectorAll('[class^="popupBanner_w popupOpen"]').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('iframe')) {
|
||||
document.querySelectorAll('iframe').forEach(function (e) {
|
||||
if (e.getAttribute("src") != null && (e.getAttribute("src").search("ads") > -1 || e.getAttribute("src").search("coupang") > -1)) {
|
||||
e.remove()
|
||||
function scrollStep() {
|
||||
// 페이지 최대값(일정 margin 여유)
|
||||
maxY = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.documentElement.scrollHeight
|
||||
);
|
||||
if (currentY + step < maxY - window.innerHeight) {
|
||||
currentY += step;
|
||||
window.scrollTo({ top: currentY, behavior: 'smooth' });
|
||||
setTimeout(scrollStep, delay);
|
||||
} else {
|
||||
// 끝까지 도달하면 마지막으로 최하단 이동
|
||||
window.scrollTo({ top: maxY, behavior: 'smooth' });
|
||||
setTimeout(function() {
|
||||
// == 여기에 저장 등 후처리 콜백 코드 호출 ==
|
||||
if (typeof autoScrollAndSave === 'function') {
|
||||
autoScrollAndSave(true);
|
||||
} else {
|
||||
// 직접 메시지 보내거나, 원하는 최종 동작 실행
|
||||
// 예: window.postMessage('saveToObsidian', '*');
|
||||
}
|
||||
})
|
||||
}, 800);
|
||||
}
|
||||
if (location.href.search("x.com") > -1) {
|
||||
var mainClass = document.querySelector('section').className
|
||||
|
||||
document.querySelector('section').querySelectorAll('div[class="'+ mainClass +'"]').forEach(function (e) {
|
||||
if (e.hasAttribute("data-testid") && e.querySelector('video')) {
|
||||
e.querySelectorAll('[poster]').forEach(function (e) {
|
||||
|
||||
})
|
||||
console.log(e.innerHTML)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[data-banner^="coupang-"]')) {
|
||||
document.querySelectorAll('[data-banner^="coupang-"]').forEach(e => e.remove())
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[id^="mobonDivBanner"]')) {
|
||||
document.querySelectorAll('[id^="mobonDivBanner"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[id^="pnlTopAd"]')) {
|
||||
document.querySelectorAll('[id^="pnlTopAd"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="ad-tag"]')) {
|
||||
document.querySelectorAll('[class^="ad-tag"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="science-banner-area"]')) {
|
||||
document.querySelectorAll('[class^="science-banner-area"]').forEach(e=> e.remove())
|
||||
}
|
||||
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
||||
document.querySelectorAll('a').forEach(function (e) {
|
||||
if (e.getAttribute('href') != null && e.getAttribute('href').startsWith("/adver-")) {
|
||||
e.remove()
|
||||
}
|
||||
}
|
||||
)
|
||||
if(document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').forEach(function (e) {
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e){
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
var description = e.querySelector('.flex-none w-16 text-center').textContent + e.querySelector('.badge badge-third w-auto px-1 flex-none mr-2 float-left').textContent
|
||||
var md = e.querySelector(".flex-none w-14 text-center hidden md:block").textContent
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let now = new Date();
|
||||
let hh = String(now.getHours()).padStart(2, '0'); // 시 (2자리)
|
||||
let mm = String(now.getMinutes()).padStart(2, '0'); // 분 (2자리)
|
||||
let ss = String(now.getSeconds()).padStart(2, '0'); // 초 (2자리)
|
||||
|
||||
let time = `${hh}:${mm}:${ss}`;
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title" : title,
|
||||
"description" : description,
|
||||
"originPage" : link,
|
||||
"pubDate" : dateObj.getTime(),
|
||||
"category" : "TORRENT"
|
||||
});
|
||||
})
|
||||
if(datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage : location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||
var thumbnail = ""
|
||||
e.querySelectorAll("img").forEach(function (e){
|
||||
if(e.getAttribute("class") === "border"){
|
||||
thumbnail = e.getAttribute('src')
|
||||
}
|
||||
})
|
||||
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e){
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if(e.getAttribute("class") === "item-link"){
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
var description = ""
|
||||
var time = ""
|
||||
var md = ""
|
||||
if(e.querySelector('[class^="pb-2 w-100 text-gray-500"]')){
|
||||
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||
md = description.split(" ")[1].trim();
|
||||
time = description.split(" ")[2].trim();
|
||||
description = description.split(" ")[0].trim();
|
||||
}
|
||||
console.log(link)
|
||||
console.log(thumbnail)
|
||||
console.log(title)
|
||||
console.log(description)
|
||||
console.log(md)
|
||||
console.log(time)
|
||||
|
||||
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title" : title,
|
||||
"description" : description,
|
||||
"originPage" : link,
|
||||
"thumbnail" : thumbnail,
|
||||
"pubDate" : dateObj.getTime(),
|
||||
"category" : "TORRENT"
|
||||
});
|
||||
})
|
||||
if(datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage : location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').forEach(function (e) {
|
||||
var date = 0
|
||||
try {
|
||||
const dateString = e.querySelector('[class^="mb-2"]').querySelector("a").textContent.trim();
|
||||
|
||||
const [day, month, year] = dateString.split("/").map(Number);
|
||||
date = new Date(year, month - 1, day).getTime();
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
var actor = ""
|
||||
try {
|
||||
actor = e.querySelector('[class^="mb-1"]').getAttribute("alt").trim()
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
var desc = ""
|
||||
try {
|
||||
e.querySelectorAll('[class^="badge badge-"]').forEach(function (e) {
|
||||
try {
|
||||
if (Number(e.textContent) > 0) {
|
||||
|
||||
}else {
|
||||
if (desc.length > 0) {
|
||||
desc += ","
|
||||
}
|
||||
desc += e.textContent.trim()
|
||||
}
|
||||
}catch (e) {}
|
||||
}
|
||||
)
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
var thumb = ""
|
||||
try {
|
||||
thumb = e.querySelector("td").querySelector("a").getAttribute('data-link')
|
||||
try {
|
||||
var sets = e.querySelector("td").querySelector("img").getAttribute('srcset')
|
||||
if(sets.search(",") > -1) {
|
||||
var srcSet = sets.split(",")
|
||||
var newT = srcSet[srcSet.length - 1]
|
||||
if (newT != null && newT.length > 5) {
|
||||
thumb = newT
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}catch (e) {}
|
||||
var magnet = ""
|
||||
try {
|
||||
e.querySelectorAll("td").forEach(function (e) {
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if(e.getAttribute("href").startsWith("magnet")) {
|
||||
magnet = e.getAttribute("href").replaceAll("&", "&");
|
||||
}
|
||||
})
|
||||
})
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
var title = "";
|
||||
try {
|
||||
e.querySelector(".name").querySelector("a").querySelectorAll("span").forEach(function (e) {
|
||||
if (e.hasAttribute("class") == false) {
|
||||
title = e.textContent.trim();
|
||||
}
|
||||
})
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
var originPage = ""
|
||||
try {
|
||||
originPage = location.protocol + "//" + location.hostname + e.querySelector(".name").querySelector("a").getAttribute("href");
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
var screenshots = ""
|
||||
try {
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if(e.getAttribute("href").search("screenshots") > -1) {
|
||||
screenshots = e.getAttribute("href");
|
||||
}
|
||||
})
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
if (thumb.length > 0 || screenshots.length > 0) {}
|
||||
datas.push({
|
||||
"title" : title,
|
||||
"description" : desc,
|
||||
"originPage" : originPage,
|
||||
"magnet_link" : magnet,
|
||||
"thumbnail" : thumb,
|
||||
"pubDate" : date,
|
||||
"screenshotsUrl" : screenshots,
|
||||
"chosung" : "",
|
||||
"category" : "PRIVATE"
|
||||
});
|
||||
})
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage : location.href
|
||||
}
|
||||
);
|
||||
|
||||
gotoNext()
|
||||
}
|
||||
},1500)
|
||||
|
||||
}
|
||||
|
||||
// 시작(로드 이벤트 이후 실행 권장)
|
||||
scrollStep();
|
||||
})(autoScrollAndSave);
|
||||
}
|
||||
|
||||
var targetUrl = ""
|
||||
var time2 = null
|
||||
var time1 = null
|
||||
function gotoNext() {
|
||||
clearTimeout(time1)
|
||||
try{
|
||||
@ -614,4 +307,484 @@ function gotoNext() {
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function isNewerThanOneDay(dateStr) {
|
||||
if (!dateStr) return false;
|
||||
const date = new Date(dateStr);
|
||||
if (isNaN(date)) return false;
|
||||
|
||||
const now = new Date();
|
||||
const oneDayMs = 24 * 60 * 60 * 1000;
|
||||
return (now - date) < oneDayMs;
|
||||
}
|
||||
function autoScrollAndSave(senContents) {
|
||||
if (location.hostname.search("theqoo.net") > -1 && document.querySelectorAll('[class^="m-list m-element"]')) {
|
||||
document.querySelectorAll('[class^="m-list m-element"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="button_area"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="board_content_google_ad"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="clearfix list-header"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="clearfix list-footer"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="main-footer"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('ins[class^="adsbygoogle"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[id="grid-content"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("dcinside.com") > -1 && document.querySelectorAll('[class^="container"]')) {
|
||||
document.querySelectorAll('[id^="view_btn_area"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="trend-rank"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="view-btm-con"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="md-tit-box"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="gall-detail-lst"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="outside-search-box"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="footer ftlong"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[class="container"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("fmkorea.com") > -1 && document.querySelectorAll('[class^="bd bd_mobile"]')) {
|
||||
document.querySelectorAll('[class^="fmad_wrapper fmad_naver_power_link"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="ad ad_wrapper"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="bd_lst_wrp"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="m_top_hotdeal"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[class="bd bd_mobile"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("acrofan.com") > -1 && document.querySelectorAll('[id^="wide"]')) {
|
||||
document.querySelectorAll('[class^="header"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="footer"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[id^="tabmenu"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[class="wide"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("yna.co.kr") > -1 && document.querySelectorAll('[class^="wrapper"]')) {
|
||||
document.querySelectorAll('[class^="aside-box426 sticky"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('aside[class^="aside-box"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="section02"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="content03 wide"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[id="footer"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[id="container"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("clien") > -1 && document.querySelectorAll('[class^="content_view"]')) {
|
||||
document.querySelectorAll('[class^="view_top"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[id^="naverAd"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="content_view_list"]').forEach(e => e.remove())
|
||||
document.querySelectorAll('[class^="footer_wrap"]').forEach(e => e.remove())
|
||||
mainContentsEl = document.querySelector('div[id="content_view"]')
|
||||
}
|
||||
|
||||
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[id^="id_mbv"]')) {
|
||||
document.querySelectorAll('[id^="id_mbv"]').forEach(e => e.remove())
|
||||
}
|
||||
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[class^="basic-banner"]')) {
|
||||
document.querySelectorAll('[class^="basic-banner"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelector(".top_google_ad_space")) {
|
||||
document.querySelector(".top_google_ad_space").remove()
|
||||
}
|
||||
if (document.querySelectorAll(".adv-group")) {
|
||||
document.querySelectorAll(".adv-group").forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div-gpt-ad"]')) {
|
||||
document.querySelectorAll('[id^="div-gpt-ad"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.location.href.search("reddit") > -1) {
|
||||
if (document.querySelector('#xpromo-bottom-sheet')) {
|
||||
document.querySelector('#xpromo-bottom-sheet').remove()
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div_adnmore_area"]')) {
|
||||
document.querySelectorAll('[id^="div_adnmore_area"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[id^="div_adnmore_area"]')) {
|
||||
document.querySelectorAll('[id^="div_adnmore_area"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[class^="adv-groupno"]')) {
|
||||
document.querySelectorAll('[class^="adv-groupno"]').forEach(e =>
|
||||
e.remove()
|
||||
)
|
||||
}
|
||||
if (document.querySelectorAll('[class^="code-block"]')) {
|
||||
document.querySelectorAll('[class^="code-block"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('.ad-template')) {
|
||||
document.querySelectorAll('.ad-template').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
if (location.href.search("arca.live") > -1 && document.querySelectorAll('[class^="vrow hybrid"]')) {
|
||||
const tempArray = [];
|
||||
document.querySelectorAll('[class^="vrow hybrid"]').forEach(function (aracaLi) {
|
||||
if (aracaLi.innerHTML.search("title ") > -1) {
|
||||
// title.hybrid-title 클래스가 붙은 첫 번째 요소 텍스트 추출
|
||||
let titleEl = aracaLi.querySelector('.title.hybrid-title');
|
||||
let title = titleEl ? titleEl.textContent.trim() : '';
|
||||
|
||||
// badge 클래스 텍스트와 user-info 클래스 텍스트 합치기
|
||||
let descBadge = aracaLi.querySelector('.badge');
|
||||
let descUserInfo = aracaLi.querySelector('.user-info');
|
||||
let desc = (descBadge ? descBadge.textContent.trim() : '')
|
||||
if (desc.length > 0) {
|
||||
desc = desc + ","
|
||||
}
|
||||
desc = desc + (descUserInfo ? descUserInfo.textContent.trim() : '');
|
||||
if (descUserInfo) {
|
||||
desc = desc + ","
|
||||
}
|
||||
|
||||
// time 태그 datetime 속성 값
|
||||
let timeEl = aracaLi.querySelector('time');
|
||||
|
||||
let dateTime = timeEl ? timeEl.getAttribute('datetime') : '';
|
||||
// console.log("dateTime >>> "+ dateTime)
|
||||
// const dateObj = new Date(dateTime);
|
||||
// console.log(dateObj.getFullYear()); // 2025
|
||||
// console.log(dateObj.getMonth() + 1); // 7 (월은 0부터 시작하므로 +1)
|
||||
// console.log(dateObj.getDate()); // 30
|
||||
// console.log(dateObj.getHours()); // 13 (현지 시간 기준)
|
||||
// console.log(dateObj.getMinutes()); // 45
|
||||
// console.log(dateObj.getSeconds());
|
||||
// console.log(dateObj);
|
||||
// img 태그 src 값
|
||||
let imgEl = aracaLi.querySelector('img');
|
||||
let thumbnail = imgEl ? imgEl.getAttribute('src') : '';
|
||||
|
||||
// 링크 만들기
|
||||
let link = 'https://arca.live';
|
||||
if (titleEl && titleEl.getAttribute('href')) {
|
||||
link += titleEl.getAttribute('href');
|
||||
} else {
|
||||
let aEl = aracaLi.querySelector('a');
|
||||
if (aEl && aEl.getAttribute('href')) {
|
||||
link += aEl.getAttribute('href');
|
||||
}
|
||||
}
|
||||
|
||||
if (title.length > 0 && link.length > 20) {
|
||||
// thumbnail 절대경로 처리 (프로토콜이 없는 경우 https: 붙이기)
|
||||
if (thumbnail.startsWith('//')) {
|
||||
thumbnail = 'https:' + thumbnail;
|
||||
}
|
||||
|
||||
// 날짜가 하루 이내인지 확인하는 함수 사용
|
||||
|
||||
tempArray.push({
|
||||
title: title.replace(/\s+/g, ' ').trim(),
|
||||
description: desc.replace(/\s+/g, ' ').trim() + "ARCA",
|
||||
pubDate: new Date(dateTime).getTime(),
|
||||
originPage: link,
|
||||
"category": "ARCA",
|
||||
thumbnail: thumbnail
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
if (tempArray.length > 0) {
|
||||
console.log(tempArray);
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: tempArray,
|
||||
currentPage: location.href
|
||||
}
|
||||
);
|
||||
location.href = "about:blank;"
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[class^="popupBanner_w popupOpen"]')) {
|
||||
document.querySelectorAll('[class^="popupBanner_w popupOpen"]').forEach(function (e) {
|
||||
e.remove()
|
||||
})
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('iframe')) {
|
||||
document.querySelectorAll('iframe').forEach(function (e) {
|
||||
if (e.getAttribute("src") != null && (e.getAttribute("src").search("ads") > -1 || e.getAttribute("src").search("coupang") > -1)) {
|
||||
e.remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
if (location.href.search("x.com") > -1) {
|
||||
var mainClass = document.querySelector('section').className
|
||||
|
||||
document.querySelector('section').querySelectorAll('div[class="' + mainClass + '"]').forEach(function (e) {
|
||||
if (e.hasAttribute("data-testid") && e.querySelector('video')) {
|
||||
e.querySelectorAll('[poster]').forEach(function (e) {
|
||||
|
||||
})
|
||||
console.log(e.innerHTML)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[data-banner^="coupang-"]')) {
|
||||
document.querySelectorAll('[data-banner^="coupang-"]').forEach(e => e.remove())
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[id^="mobonDivBanner"]')) {
|
||||
document.querySelectorAll('[id^="mobonDivBanner"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[id^="pnlTopAd"]')) {
|
||||
document.querySelectorAll('[id^="pnlTopAd"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="ad-tag"]')) {
|
||||
document.querySelectorAll('[class^="ad-tag"]').forEach(e => e.remove())
|
||||
}
|
||||
if (document.querySelectorAll('[class^="science-banner-area"]')) {
|
||||
document.querySelectorAll('[class^="science-banner-area"]').forEach(e => e.remove())
|
||||
}
|
||||
if (location.href.search("torrentzota") > -1 && document.querySelectorAll('a')) {
|
||||
document.querySelectorAll('a').forEach(function (e) {
|
||||
if (e.getAttribute('href') != null && e.getAttribute('href').startsWith("/adver-")) {
|
||||
e.remove()
|
||||
}
|
||||
}
|
||||
)
|
||||
if (document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="py-4 flex flex-row border-b topic-item"]').forEach(function (e) {
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if (e.getAttribute("class") === "item-link") {
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if (e.getAttribute("class") === "item-link") {
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
var description = e.querySelector('.flex-none w-16 text-center').textContent + e.querySelector('.badge badge-third w-auto px-1 flex-none mr-2 float-left').textContent
|
||||
var md = e.querySelector(".flex-none w-14 text-center hidden md:block").textContent
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let now = new Date();
|
||||
let hh = String(now.getHours()).padStart(2, '0'); // 시 (2자리)
|
||||
let mm = String(now.getMinutes()).padStart(2, '0'); // 분 (2자리)
|
||||
let ss = String(now.getSeconds()).padStart(2, '0'); // 초 (2자리)
|
||||
|
||||
let time = `${hh}:${mm}:${ss}`;
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title": title,
|
||||
"description": description,
|
||||
"originPage": link,
|
||||
"pubDate": dateObj.getTime(),
|
||||
"category": "TORRENT"
|
||||
});
|
||||
})
|
||||
if (datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage: location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (document.querySelectorAll('[class^="w-full flex"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="w-full flex"]').forEach(function (e) {
|
||||
var thumbnail = ""
|
||||
e.querySelectorAll("img").forEach(function (e) {
|
||||
if (e.getAttribute("class") === "border") {
|
||||
thumbnail = e.getAttribute('src')
|
||||
}
|
||||
})
|
||||
|
||||
var title = ""
|
||||
var link = ""
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if (e.getAttribute("class") === "item-link") {
|
||||
title = e.getAttribute('title')
|
||||
}
|
||||
if (e.getAttribute("class") === "item-link") {
|
||||
link = e.getAttribute('href')
|
||||
if (link.length > 0) {
|
||||
link = location.protocol + '//' + location.hostname + link
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
var description = ""
|
||||
var time = ""
|
||||
var md = ""
|
||||
if (e.querySelector('[class^="pb-2 w-100 text-gray-500"]')) {
|
||||
description = e.querySelector('[class^="pb-2 w-100 text-gray-500"]').textContent.replace(/\s+/g, ' ').trim();
|
||||
md = description.split(" ")[1].trim();
|
||||
time = description.split(" ")[2].trim();
|
||||
description = description.split(" ")[0].trim();
|
||||
}
|
||||
console.log(link)
|
||||
console.log(thumbnail)
|
||||
console.log(title)
|
||||
console.log(description)
|
||||
console.log(md)
|
||||
console.log(time)
|
||||
|
||||
|
||||
let todayYear = new Date().getFullYear();
|
||||
let combinedStr = todayYear + "-" + md + " " + time;
|
||||
let dateObj = new Date(combinedStr);
|
||||
|
||||
datas.push({
|
||||
"title": title,
|
||||
"description": description,
|
||||
"originPage": link,
|
||||
"thumbnail": thumbnail,
|
||||
"pubDate": dateObj.getTime(),
|
||||
"category": "TORRENT"
|
||||
});
|
||||
})
|
||||
if (datas.length > 0) {
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage: location.href
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').length > 1) {
|
||||
var datas = []
|
||||
document.querySelectorAll('[class^="col-md-4 mb-4 video-item"]').forEach(function (e) {
|
||||
var date = 0
|
||||
try {
|
||||
const dateString = e.querySelector('[class^="mb-2"]').querySelector("a").textContent.trim();
|
||||
|
||||
const [day, month, year] = dateString.split("/").map(Number);
|
||||
date = new Date(year, month - 1, day).getTime();
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
var actor = ""
|
||||
try {
|
||||
actor = e.querySelector('[class^="mb-1"]').getAttribute("alt").trim()
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
var desc = ""
|
||||
try {
|
||||
e.querySelectorAll('[class^="badge badge-"]').forEach(function (e) {
|
||||
try {
|
||||
if (Number(e.textContent) > 0) {
|
||||
|
||||
} else {
|
||||
if (desc.length > 0) {
|
||||
desc += ","
|
||||
}
|
||||
desc += e.textContent.trim()
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
var thumb = ""
|
||||
try {
|
||||
thumb = e.querySelector("td").querySelector("a").getAttribute('data-link')
|
||||
try {
|
||||
var sets = e.querySelector("td").querySelector("img").getAttribute('srcset')
|
||||
if (sets.search(",") > -1) {
|
||||
var srcSet = sets.split(",")
|
||||
var newT = srcSet[srcSet.length - 1]
|
||||
if (newT != null && newT.length > 5) {
|
||||
thumb = newT
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
var magnet = ""
|
||||
try {
|
||||
e.querySelectorAll("td").forEach(function (e) {
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if (e.getAttribute("href").startsWith("magnet")) {
|
||||
magnet = e.getAttribute("href").replaceAll("&", "&");
|
||||
}
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
var title = "";
|
||||
try {
|
||||
e.querySelector(".name").querySelector("a").querySelectorAll("span").forEach(function (e) {
|
||||
if (e.hasAttribute("class") == false) {
|
||||
title = e.textContent.trim();
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
var originPage = ""
|
||||
try {
|
||||
originPage = location.protocol + "//" + location.hostname + e.querySelector(".name").querySelector("a").getAttribute("href");
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
var screenshots = ""
|
||||
try {
|
||||
e.querySelectorAll("a").forEach(function (e) {
|
||||
if (e.getAttribute("href").search("screenshots") > -1) {
|
||||
screenshots = e.getAttribute("href");
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
if (thumb.length > 0 || screenshots.length > 0) {
|
||||
}
|
||||
datas.push({
|
||||
"title": title,
|
||||
"description": desc,
|
||||
"originPage": originPage,
|
||||
"magnet_link": magnet,
|
||||
"thumbnail": thumb,
|
||||
"pubDate": date,
|
||||
"screenshotsUrl": screenshots,
|
||||
"chosung": "",
|
||||
"category": "PRIVATE"
|
||||
});
|
||||
})
|
||||
sendMessage(
|
||||
{
|
||||
type: "PRIVATES",
|
||||
privates: datas,
|
||||
currentPage: location.href
|
||||
}
|
||||
);
|
||||
|
||||
gotoNext()
|
||||
}
|
||||
window.scrollTo({ top: 10, behavior: 'smooth' });
|
||||
if (senContents) {
|
||||
sendMessage({type: "MainContentsEl", contents: mainContentsEl.outerHTML, currentPage: location.href});
|
||||
}
|
||||
}
|
||||
@ -1,168 +1,168 @@
|
||||
//package android.print;
|
||||
//
|
||||
//import android.app.Activity;
|
||||
//import android.content.Context;
|
||||
//import android.os.Bundle;
|
||||
//import android.os.CancellationSignal;
|
||||
//import android.os.ParcelFileDescriptor;
|
||||
//import android.webkit.WebView;
|
||||
//import android.webkit.WebViewClient;
|
||||
//
|
||||
//import java.io.File;
|
||||
//import java.io.FileInputStream;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//
|
||||
//public class PDFPrint {
|
||||
//
|
||||
// public static void generatePDFFromHTML(final Context context, final File file, final String htmlString, final OnPDFPrintListener onPDFPrintListener) {
|
||||
// final WebView mWebView = new WebView(context);
|
||||
// mWebView.setWebViewClient(new WebViewClient() {
|
||||
// @Override
|
||||
// public void onPageFinished(WebView view, String url) {
|
||||
// PrintAttributes printAttributes = new PrintAttributes.Builder()
|
||||
// .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
|
||||
// .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
|
||||
// .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
|
||||
// .build();
|
||||
//
|
||||
// final PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter(file.getName());
|
||||
// documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
|
||||
// @Override
|
||||
// public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
|
||||
// documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteCancelled() {
|
||||
// super.onWriteCancelled();
|
||||
// onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteFailed(CharSequence error) {
|
||||
// super.onWriteFailed(error);
|
||||
// onPDFPrintListener.onError(new Exception(error.toString()));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteFinished(PageRange[] pages) {
|
||||
// super.onWriteFinished(pages);
|
||||
// onPDFPrintListener.onSuccess(file);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }, null);
|
||||
// }
|
||||
// });
|
||||
// mWebView.loadData(htmlString.replaceAll("#", "%23"), "text/HTML", "UTF-8");
|
||||
// }
|
||||
//
|
||||
// public static void generatePDFFromWebView(final File file, final WebView webView, final OnPDFPrintListener onPDFPrintListener) {
|
||||
// PrintAttributes printAttributes = new PrintAttributes.Builder()
|
||||
// .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
|
||||
// .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
|
||||
// .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
|
||||
// .build();
|
||||
//
|
||||
// final PrintDocumentAdapter documentAdapter = webView.createPrintDocumentAdapter(file.getName());
|
||||
// documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
|
||||
// @Override
|
||||
// public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
|
||||
// documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteCancelled() {
|
||||
// super.onWriteCancelled();
|
||||
// onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteFailed(CharSequence error) {
|
||||
// super.onWriteFailed(error);
|
||||
// try {
|
||||
// if (error != null && error.toString().length() > 0) {
|
||||
// onPDFPrintListener.onError(new Exception(error.toString()));
|
||||
// } else {
|
||||
// onPDFPrintListener.onError(new Exception("Empty Page"));
|
||||
// }
|
||||
// }catch (Exception e) {e.printStackTrace();}
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onWriteFinished(PageRange[] pages) {
|
||||
// super.onWriteFinished(pages);
|
||||
// onPDFPrintListener.onSuccess(file);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }, null);
|
||||
// }
|
||||
//
|
||||
// private static ParcelFileDescriptor getOutputFile(File file) {
|
||||
// try {
|
||||
// if (!file.exists()) {
|
||||
// file.createNewFile();
|
||||
// }
|
||||
// return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public static PrintJob printPDF(final Activity activity, final File pdfFileToPrint, final PrintAttributes printAttributes) {
|
||||
// PrintManager printManager = (PrintManager) activity.getSystemService(Context.PRINT_SERVICE);
|
||||
// String jobName = Long.valueOf(System.currentTimeMillis()).toString();
|
||||
// return printManager.print(jobName, new PrintDocumentAdapter() {
|
||||
// @Override
|
||||
// public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
|
||||
// InputStream input = null;
|
||||
// OutputStream output = null;
|
||||
//
|
||||
// try {
|
||||
//
|
||||
// input = new FileInputStream(pdfFileToPrint);
|
||||
// output = new FileOutputStream(destination.getFileDescriptor());
|
||||
//
|
||||
// byte[] buf = new byte[1024];
|
||||
// int bytesRead;
|
||||
//
|
||||
// while ((bytesRead = input.read(buf)) > 0) {
|
||||
// output.write(buf, 0, bytesRead);
|
||||
// }
|
||||
//
|
||||
// callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// } finally {
|
||||
// try {
|
||||
// input.close();
|
||||
// output.close();
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
|
||||
// if (cancellationSignal.isCanceled()) {
|
||||
// callback.onLayoutCancelled();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(pdfFileToPrint.getName()).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
|
||||
// callback.onLayoutFinished(pdi, true);
|
||||
// }
|
||||
// }, printAttributes);
|
||||
// }
|
||||
//
|
||||
// public interface OnPDFPrintListener {
|
||||
// void onSuccess(File file);
|
||||
//
|
||||
// void onError(Exception exception);
|
||||
// }
|
||||
//}
|
||||
package android.print;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class PDFPrint {
|
||||
|
||||
public static void generatePDFFromHTML(final Context context, final File file, final String htmlString, final OnPDFPrintListener onPDFPrintListener) {
|
||||
final WebView mWebView = new WebView(context);
|
||||
mWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
PrintAttributes printAttributes = new PrintAttributes.Builder()
|
||||
.setMediaSize(PrintAttributes.MediaSize.ISO_A4)
|
||||
.setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
|
||||
.setMinMargins(PrintAttributes.Margins.NO_MARGINS)
|
||||
.build();
|
||||
|
||||
final PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter(file.getName());
|
||||
documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
|
||||
@Override
|
||||
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
|
||||
documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
|
||||
|
||||
@Override
|
||||
public void onWriteCancelled() {
|
||||
super.onWriteCancelled();
|
||||
onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWriteFailed(CharSequence error) {
|
||||
super.onWriteFailed(error);
|
||||
onPDFPrintListener.onError(new Exception(error.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWriteFinished(PageRange[] pages) {
|
||||
super.onWriteFinished(pages);
|
||||
onPDFPrintListener.onSuccess(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
});
|
||||
mWebView.loadData(htmlString.replaceAll("#", "%23"), "text/HTML", "UTF-8");
|
||||
}
|
||||
|
||||
public static void generatePDFFromWebView(final File file, final WebView webView, final OnPDFPrintListener onPDFPrintListener) {
|
||||
PrintAttributes printAttributes = new PrintAttributes.Builder()
|
||||
.setMediaSize(PrintAttributes.MediaSize.ISO_A4)
|
||||
.setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
|
||||
.setMinMargins(PrintAttributes.Margins.NO_MARGINS)
|
||||
.build();
|
||||
|
||||
final PrintDocumentAdapter documentAdapter = webView.createPrintDocumentAdapter(file.getName());
|
||||
documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
|
||||
@Override
|
||||
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
|
||||
documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
|
||||
|
||||
@Override
|
||||
public void onWriteCancelled() {
|
||||
super.onWriteCancelled();
|
||||
onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWriteFailed(CharSequence error) {
|
||||
super.onWriteFailed(error);
|
||||
try {
|
||||
if (error != null && error.toString().length() > 0) {
|
||||
onPDFPrintListener.onError(new Exception(error.toString()));
|
||||
} else {
|
||||
onPDFPrintListener.onError(new Exception("Empty Page"));
|
||||
}
|
||||
}catch (Exception e) {e.printStackTrace();}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWriteFinished(PageRange[] pages) {
|
||||
super.onWriteFinished(pages);
|
||||
onPDFPrintListener.onSuccess(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
private static ParcelFileDescriptor getOutputFile(File file) {
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PrintJob printPDF(final Activity activity, final File pdfFileToPrint, final PrintAttributes printAttributes) {
|
||||
PrintManager printManager = (PrintManager) activity.getSystemService(Context.PRINT_SERVICE);
|
||||
String jobName = Long.valueOf(System.currentTimeMillis()).toString();
|
||||
return printManager.print(jobName, new PrintDocumentAdapter() {
|
||||
@Override
|
||||
public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try {
|
||||
|
||||
input = new FileInputStream(pdfFileToPrint);
|
||||
output = new FileOutputStream(destination.getFileDescriptor());
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = input.read(buf)) > 0) {
|
||||
output.write(buf, 0, bytesRead);
|
||||
}
|
||||
|
||||
callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
input.close();
|
||||
output.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
|
||||
if (cancellationSignal.isCanceled()) {
|
||||
callback.onLayoutCancelled();
|
||||
return;
|
||||
}
|
||||
|
||||
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(pdfFileToPrint.getName()).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
|
||||
callback.onLayoutFinished(pdi, true);
|
||||
}
|
||||
}, printAttributes);
|
||||
}
|
||||
|
||||
public interface OnPDFPrintListener {
|
||||
void onSuccess(File file);
|
||||
|
||||
void onError(Exception exception);
|
||||
}
|
||||
}
|
||||
@ -569,8 +569,11 @@ internal class LauncherActivity : CommonActivity() {
|
||||
private fun initGeckoRuntime() {
|
||||
if (sRuntime == null) {
|
||||
try {
|
||||
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder().extensionsProcessEnabled(true)
|
||||
.extensionsWebAPIEnabled(true).experimentDelegate(experimentDelegate)
|
||||
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
|
||||
.extensionsProcessEnabled(true)
|
||||
.extensionsWebAPIEnabled(true)
|
||||
.experimentDelegate(experimentDelegate)
|
||||
.debugLogging(false)
|
||||
.remoteDebuggingEnabled(true).build())
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
@ -717,6 +720,7 @@ internal class LauncherActivity : CommonActivity() {
|
||||
}
|
||||
val callBackHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -73,9 +73,9 @@ class BluetoothManager : Service() {
|
||||
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||
registerReceiver(bluetoothreceiver, filter)
|
||||
refreshFeeds()
|
||||
// GeckoWeb(applicationContext).apply {
|
||||
// loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=")
|
||||
// }
|
||||
GeckoWeb(applicationContext).apply {
|
||||
loadUrl("https://arca.live/b/live")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
import com.vladsch.flexmark.html2md.converter.*
|
||||
import com.vladsch.flexmark.util.data.DataHolder
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class CustomVideoNodeRenderer(options: DataHolder?) : HtmlNodeRenderer {
|
||||
|
||||
override fun getHtmlNodeRendererHandlers(): Set<HtmlNodeRendererHandler<*>> {
|
||||
return setOf(
|
||||
HtmlNodeRendererHandler(
|
||||
"video", // 처리할 태그명!
|
||||
Element::class.java
|
||||
) { node, context, markdown ->
|
||||
// node: org.jsoup.nodes.Element 타입, 즉 <video ...> 태그
|
||||
val sources = node.getElementsByTag("source")
|
||||
val src = if (sources.isNotEmpty()) {
|
||||
sources.first()?.attr("src")
|
||||
} else {
|
||||
node.attr("src")
|
||||
}
|
||||
// 대표 src가 있으면 단일 <video src=... controls></video>
|
||||
if (src?.isNotBlank() == true) {
|
||||
markdown.append("<video src=\"$src\" controls></video>\n")
|
||||
} else {
|
||||
// 혹시 src 속성이 없거나 source 태그가 없으면 원본 전체 남김
|
||||
markdown.append(node.outerHtml() + "\n")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package bums.lunatic.launcher.home
|
||||
|
||||
import CustomVideoNodeRenderer
|
||||
import android.app.DownloadManager
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
@ -8,9 +9,6 @@ import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.util.AttributeSet
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
@ -26,36 +24,36 @@ import android.view.KeyEvent.KEYCODE_DPAD_DOWN
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_UP
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CheckBox
|
||||
import android.widget.EditText
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
|
||||
import bums.lunatic.launcher.R
|
||||
import bums.lunatic.launcher.tokiz.data.HistoryManager
|
||||
import bums.lunatic.launcher.tokiz.data.model.History
|
||||
import bums.lunatic.launcher.tokiz.data.model.PortMessage
|
||||
import bums.lunatic.launcher.tokiz.view.BWebview
|
||||
import bums.lunatic.launcher.tokiz.view.JxEvent
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import bums.lunatic.launcher.utils.afterDay
|
||||
import bums.lunatic.launcher.workers.WorkersDb
|
||||
import bums.lunatic.launcher.workers.WorkersDb.getRealm
|
||||
import com.google.gson.Gson
|
||||
import io.realm.kotlin.UpdatePolicy
|
||||
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.mozilla.gecko.util.ThreadUtils
|
||||
import org.mozilla.geckoview.BuildConfig
|
||||
import org.mozilla.geckoview.ExperimentDelegate
|
||||
import org.mozilla.geckoview.GeckoResult
|
||||
import org.mozilla.geckoview.GeckoRuntime
|
||||
import org.mozilla.geckoview.GeckoRuntimeSettings
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.GeckoView
|
||||
import org.mozilla.geckoview.MediaSession
|
||||
import org.mozilla.geckoview.WebExtension
|
||||
import org.mozilla.geckoview.WebExtension.MessageDelegate
|
||||
@ -63,7 +61,10 @@ import org.mozilla.geckoview.WebExtension.PortDelegate
|
||||
import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate
|
||||
import org.mozilla.geckoview.WebRequestError
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
class GeckoWeb : BWebview {
|
||||
constructor(context: Context?) : super(context) {
|
||||
@ -84,6 +85,7 @@ class GeckoWeb : BWebview {
|
||||
val extId = "messaging@booktoki468.com"
|
||||
|
||||
private fun buildWeb() {
|
||||
|
||||
getRuntime()?.let {
|
||||
val session: GeckoSession = GeckoSession()
|
||||
session.open(it)
|
||||
@ -275,30 +277,108 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
|
||||
fun showImageDownloadDialog(context: Context, imageUrl: Uri) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle("이미지 다운로드")
|
||||
.setMessage("이미지를 저장하시겠습니까?")
|
||||
.setPositiveButton("저장") { _, _ ->
|
||||
downloadImage(context, imageUrl)
|
||||
}
|
||||
.setNegativeButton("취소", null)
|
||||
.show()
|
||||
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: Uri) {
|
||||
fun savePdfStreamToFile(pdfStream: InputStream?, outputFile: File) {
|
||||
pdfStream?.let {
|
||||
FileOutputStream(outputFile).use { output ->
|
||||
val buffer = ByteArray(8 * 1024)
|
||||
var bytesRead: Int
|
||||
while (pdfStream.read(buffer).also { bytesRead = it } != -1) {
|
||||
output.write(buffer, 0, bytesRead)
|
||||
}
|
||||
output.flush()
|
||||
}
|
||||
pdfStream.close()
|
||||
}
|
||||
}
|
||||
|
||||
// 실제 사용 예시
|
||||
|
||||
fun scrapWebToMd(context: Context, url: Uri?, markdownText: String) {
|
||||
// 경로 선언 (예: /storage/emulated/0/fff_gg/pdfs)
|
||||
val dir = File("/storage/emulated/0/bums_ob/BUM'S PACED /scraped/md")
|
||||
///BUM'S PACED/pdfs
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs()
|
||||
} else {
|
||||
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
|
||||
}
|
||||
val outputFile = File(dir, "${url?.host ?: "UnKnown"}_scraped_${SimpleDateFormat("yyyyMMdd-HHmm").format(Date())}.md")
|
||||
outputFile.writeText(markdownText, Charsets.UTF_8)
|
||||
// 저장 성공 알림 등 후속 처리
|
||||
println("PDF 저장 완료: ${outputFile.absolutePath}")
|
||||
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: Uri, isGif : Boolean = false) {
|
||||
Blog.LOGE("url.lastPathSegment ${url.lastPathSegment}")
|
||||
val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg"
|
||||
val fileName = url.host + "_${SimpleDateFormat("yyyyMMddHHmmsss").format(Date())}.${if(isGif){"gif"}else{"jpg"}}"
|
||||
val request = DownloadManager.Request(url)
|
||||
request.setTitle(fileName)
|
||||
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
|
||||
request.setDescription("이미지 다운로드 중...")
|
||||
request.setAllowedOverMetered(true) // 선택 사항 - 데이터 요금제 네트워크에서도 허용
|
||||
request.setVisibleInDownloadsUi(true)
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
|
||||
// 네트워크타입, 알림설정 등 옵션 추가 가능
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
|
||||
val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
dm.enqueue(request)
|
||||
|
||||
Toast.makeText(context, "다운로드 시작: $fileName", Toast.LENGTH_SHORT).show()
|
||||
val downloadId = dm.enqueue(request)
|
||||
monitorDownloadStatus(dm, downloadId, context)
|
||||
}
|
||||
fun monitorDownloadStatus(dm: DownloadManager, downloadId: Long, context: Context) {
|
||||
val handler = CoroutineExceptionHandler { _, exception ->
|
||||
// 에러 처리 로직 (선택)
|
||||
exception.printStackTrace()
|
||||
}
|
||||
|
||||
// 백그라운드에서 5초 간격으로 상태 체크
|
||||
CoroutineScope(Dispatchers.IO + handler).launch {
|
||||
while (true) {
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
val cursor = dm.query(query)
|
||||
var downloadFinished = false
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
when (status) {
|
||||
DownloadManager.STATUS_SUCCESSFUL -> {
|
||||
// 다운로드 성공 처리
|
||||
withContext(Dispatchers.Main) {
|
||||
// UI 갱신 등 메인 스레드 작업 (필요 시)
|
||||
}
|
||||
downloadFinished = true
|
||||
}
|
||||
DownloadManager.STATUS_FAILED -> {
|
||||
val reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON))
|
||||
// 여기에 reason값에 따라 적절한 처리 또는 로깅 수행
|
||||
Log.e("DownloadManager", "Download failed with reason code: $reason")
|
||||
// 다운로드 실패 처리
|
||||
withContext(Dispatchers.Main) {
|
||||
// UI 갱신 등 메인 스레드 작업 (필요 시)
|
||||
}
|
||||
downloadFinished = true
|
||||
}
|
||||
else -> {
|
||||
Blog.LOGE("DownloadManager.STATUS >> ${status}")
|
||||
}
|
||||
// 진행 중, 대기 중 등 기타 상태는 계속 확인
|
||||
}
|
||||
}
|
||||
cursor?.close()
|
||||
|
||||
if (downloadFinished) break
|
||||
|
||||
delay(5000L) // 5초 대기 후 다시 반복
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
|
||||
val contentDelegate = object : GeckoSession.ContentDelegate {
|
||||
override fun onTitleChange(
|
||||
@ -361,6 +441,8 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
override fun onPageStart(session: GeckoSession, url: String) {
|
||||
super.onPageStart(session, url)
|
||||
markdownContents = null
|
||||
markdownUri = null
|
||||
if (url.contains(getFilterF()) && privateMode) {
|
||||
this@GeckoWeb.visibility = View.INVISIBLE
|
||||
}
|
||||
@ -418,14 +500,17 @@ class GeckoWeb : BWebview {
|
||||
loadUrl(uri)
|
||||
} else {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||
builder.setTitle("Move To")
|
||||
builder.setTitle("Move To\n${uri}")
|
||||
val viewInflated: View = LayoutInflater.from(context)
|
||||
.inflate(R.layout.text_inpu_password, null, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
(viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox)?.let { it.visibility = View.GONE }
|
||||
input.visibility = View.GONE
|
||||
builder.setView(viewInflated)
|
||||
builder.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
"브라우저로 이동",
|
||||
DialogInterface.OnClickListener { dialog, which ->
|
||||
dialog.dismiss()
|
||||
context.startActivity(Intent().apply {
|
||||
@ -435,6 +520,12 @@ class GeckoWeb : BWebview {
|
||||
data = it
|
||||
})
|
||||
})
|
||||
builder.setNeutralButton(
|
||||
"페이지 이동",
|
||||
DialogInterface.OnClickListener { dialog, which ->
|
||||
loadUrl(uri)
|
||||
dialog.cancel()
|
||||
})
|
||||
builder.setNegativeButton(
|
||||
android.R.string.cancel,
|
||||
DialogInterface.OnClickListener { dialog, which -> dialog.cancel() })
|
||||
@ -481,6 +572,16 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
|
||||
}
|
||||
fun saveMd() {
|
||||
val message: JSONObject = JSONObject()
|
||||
try {
|
||||
message.put("type", "saveContent")
|
||||
} catch (ex: JSONException) {
|
||||
throw RuntimeException(ex)
|
||||
}
|
||||
Blog.LOGE(Gson().toJson(message))
|
||||
mPort?.postMessage(message)
|
||||
}
|
||||
|
||||
val portDelegate: PortDelegate =
|
||||
object : PortDelegate {
|
||||
@ -520,6 +621,27 @@ class GeckoWeb : BWebview {
|
||||
|
||||
}
|
||||
}
|
||||
"MainContentsEl"->{
|
||||
try {
|
||||
val doc: Document = Jsoup.parse(lPortMessage.contents)
|
||||
val combinedHtml = doc.html()
|
||||
val converter = FlexmarkHtmlConverter.builder().htmlNodeRendererFactory { options -> CustomVideoNodeRenderer(options) }.build()
|
||||
markdownContents = converter.convert(combinedHtml)
|
||||
markdownUri = lPortMessage.currentPage?.toUri()
|
||||
markdownContents?.let {
|
||||
if (it.length > 40) {
|
||||
scrapWebToMd(context, markdownUri, it)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
markdownContents = null
|
||||
markdownUri = null
|
||||
}
|
||||
|
||||
|
||||
// scrapWepToMd(context, Uri.parse(lPortMessage.currentPage), markdown)
|
||||
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
@ -542,6 +664,9 @@ class GeckoWeb : BWebview {
|
||||
}
|
||||
}
|
||||
|
||||
var markdownContents : String? = null
|
||||
var markdownUri : Uri? = null
|
||||
|
||||
val cacheDelegate: PortDelegate =
|
||||
object : PortDelegate {
|
||||
override fun onPortMessage(
|
||||
|
||||
@ -277,7 +277,9 @@ internal class RssHome : Fragment() {
|
||||
val viewInflated: View = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.parivate_mode) as CheckBox
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox
|
||||
val addVote = viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox
|
||||
val addRead = viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox
|
||||
privateMode.setOnCheckedChangeListener { v,c->
|
||||
binding.geckoWeb.privateMode = c
|
||||
}
|
||||
@ -290,7 +292,7 @@ internal class RssHome : Fragment() {
|
||||
dialog.dismiss()
|
||||
var command = input.editableText?.toString()
|
||||
if (command?.length ?: 0 > 0) {
|
||||
queryInfos(keywords = command!!.split(" ")!!)
|
||||
queryInfos(keywords = command!!.split(" ")!!, addVote.isChecked, addRead.isChecked)
|
||||
}
|
||||
})
|
||||
builder.setNegativeButton(
|
||||
@ -301,13 +303,16 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun ask() {
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
|
||||
builder.setTitle("Command Line")
|
||||
val viewInflated: View = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
|
||||
val input = viewInflated.findViewById<View>(R.id.input) as EditText
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.parivate_mode) as CheckBox
|
||||
val privateMode = viewInflated.findViewById<CheckBox>(R.id.private_mode) as CheckBox
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_vote) as CheckBox)?.let{ it.visibility = View.GONE}
|
||||
(viewInflated.findViewById<CheckBox>(R.id.add_read) as CheckBox)?.let{ it.visibility = View.GONE}
|
||||
privateMode.setOnCheckedChangeListener { v,c->
|
||||
binding.geckoWeb.privateMode = c
|
||||
}
|
||||
@ -447,6 +452,9 @@ internal class RssHome : Fragment() {
|
||||
vote()
|
||||
}
|
||||
}
|
||||
binding.share.setOnClickListener {
|
||||
binding.geckoWeb.saveMd()
|
||||
}
|
||||
Blog.LOGE("useHiddenMenu >>> $useHiddenMenu")
|
||||
if (useHiddenMenu) {
|
||||
binding.search.setOnLongClickListener {
|
||||
@ -533,6 +541,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
queryInfos()
|
||||
|
||||
binding.geckoWeb.progress = binding.progressBar
|
||||
binding.geckoWeb.jxInteface = { jxEvent ->
|
||||
when (jxEvent) {
|
||||
@ -560,6 +569,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
fun vote() {
|
||||
binding.geckoWeb?.saveMd()
|
||||
currentRss?.originPage.let {
|
||||
Blog.LOGE("Arrow Center Click")
|
||||
WorkersDb.getRealm().apply {
|
||||
@ -627,6 +637,7 @@ internal class RssHome : Fragment() {
|
||||
}
|
||||
|
||||
fun updateQuery(q: RealmQuery<RssData>) {
|
||||
Blog.LOGE("updateQuery >>> ${q.description()}")
|
||||
infosJob?.cancel()
|
||||
commandHandler.removeCallbacks(infoUpdate)
|
||||
|
||||
|
||||
@ -188,59 +188,64 @@ internal class RssItemAdapter (
|
||||
|
||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||
override fun onBindViewHolder(holder: RssHolder, position: Int) {
|
||||
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||
val rssData = rssDataItemLis[position]
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams =
|
||||
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||
.into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener {
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||
"JX-12",
|
||||
true
|
||||
) == true || event.device.name?.equals("J06", true) == true)
|
||||
) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
synchronized(rssDataItemLis) {
|
||||
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
|
||||
try {
|
||||
val rssData = rssDataItemLis.get(position)
|
||||
if (rssData.pubDate() > 1000L) {
|
||||
holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
|
||||
} else {
|
||||
return false
|
||||
holder.view.date.text = emptyDate
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
holder.view.title.text = "".plus(if (rssData.vote) " * " else "")
|
||||
.plus(rssData.title().plus("[R:${rssData.read}]"))
|
||||
holder.view.desc.text = rssData.description()
|
||||
|
||||
var param = holder.view.circlePreview.layoutParams
|
||||
holder.view.circlePreview.layoutParams =
|
||||
ConstraintLayout.LayoutParams(rssData.category().defaultImgSize(), param.height)
|
||||
holder.view.circlePreview.visibility = rssData.category().getDefaultVisibiliy()
|
||||
Picasso.get().cancelRequest(holder.view.circlePreview)
|
||||
|
||||
if (rssData.thumbnailUrl()?.length ?: 0 > 6) {
|
||||
Picasso.get().load(rssData.thumbnailUrl().replace("&", "&").toUri())
|
||||
.into(holder.view.circlePreview)
|
||||
} else if (rssData.category().getResId() > 0) {
|
||||
holder.view.circlePreview.setImageResource(rssData.category().getResId())
|
||||
} else {
|
||||
holder.view.circlePreview.setImageDrawable(null)
|
||||
}
|
||||
|
||||
holder.itemView.tag = rssData
|
||||
holder.itemView.setOnClickListener(dateViewClick)
|
||||
holder.itemView.setOnTouchListener(object : View.OnTouchListener {
|
||||
override fun onTouch(
|
||||
v: View,
|
||||
event: MotionEvent
|
||||
): Boolean {
|
||||
if (event.device != null && event.device.name != null && (event.device.name?.contains(
|
||||
"JX-12",
|
||||
true
|
||||
) == true || event.device.name?.equals("J06", true) == true)
|
||||
) {
|
||||
Blog.LOGE("event.device.name >>> ${event.device.name}")
|
||||
return true//mSimpleFingerGestures.onTouch(v,event)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
// v.setOnLongClickListener {
|
||||
// WorkersDb.getRealm().apply {
|
||||
// copyFromRealm(rss)
|
||||
// }
|
||||
// }
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
holder.itemView.setOnLongClickListener(mLongClickListener)
|
||||
} catch (e: Exception){}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +273,8 @@ internal class RssItemAdapter (
|
||||
rssDataItemLis.clear()
|
||||
rssDataItemLis.addAll(newList)
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
|
||||
notifyDataSetChanged()
|
||||
|
||||
// CoroutineScope(Dispatchers.IO).launch {
|
||||
// rssList.clear()
|
||||
|
||||
@ -22,57 +22,57 @@ class ArcaGetter : BaseGetter {
|
||||
}
|
||||
|
||||
override fun realWork(): Result {
|
||||
RssDataType.ARCA.isOn {
|
||||
try {
|
||||
Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||
temp.clear()
|
||||
val urls = arrayListOf(
|
||||
"https://arca.live/b/singbung?mode=best",
|
||||
// "https://arca.live/b/headline",
|
||||
// "https://arca.live/b/live",
|
||||
"https://arca.live/b/namuhotnow",
|
||||
"https://arca.live/b/society",
|
||||
// "https://arca.live/b/replay",
|
||||
// "https://arca.live/b/breaking"
|
||||
)
|
||||
urls.forEach {
|
||||
try {
|
||||
Jsoup.connect(it)
|
||||
.userAgent(USAGT)
|
||||
.header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
|
||||
.header("accept-language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
.header("cache-control", "no-cache")
|
||||
.header("pragma", "no-cache")
|
||||
.ignoreContentType(true)
|
||||
.timeout(5000)
|
||||
.get().let { arca ->
|
||||
// BLog.LOGE("url >> ${it} >> ${arca}")
|
||||
arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
|
||||
if (araca_li.html().contains("title ") == true) {
|
||||
parseArcaLi(araca_li).apply {
|
||||
this.forEach {
|
||||
if (it.pubDate() > commicsDateTime) {
|
||||
temp.add(it.getRssData())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
|
||||
// BLog.LOGE("projectj >>>>> ${projectj}")
|
||||
// RssDataType.ARCA.isOn {
|
||||
// try {
|
||||
// Blog.LOGE("realWork() ${this::class.simpleName}")
|
||||
// temp.clear()
|
||||
// val urls = arrayListOf(
|
||||
// "https://arca.live/b/singbung?mode=best",
|
||||
//// "https://arca.live/b/headline",
|
||||
//// "https://arca.live/b/live",
|
||||
// "https://arca.live/b/namuhotnow",
|
||||
// "https://arca.live/b/society",
|
||||
//// "https://arca.live/b/replay",
|
||||
//// "https://arca.live/b/breaking"
|
||||
// )
|
||||
// urls.forEach {
|
||||
//// try {
|
||||
//// Jsoup.connect(it)
|
||||
//// .userAgent(USAGT)
|
||||
//// .header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
|
||||
//// .header("accept-language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
//// .header("cache-control", "no-cache")
|
||||
//// .header("pragma", "no-cache")
|
||||
//// .ignoreContentType(true)
|
||||
//// .timeout(5000)
|
||||
//// .get().let { arca ->
|
||||
////// BLog.LOGE("url >> ${it} >> ${arca}")
|
||||
//// arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
|
||||
//// if (araca_li.html().contains("title ") == true) {
|
||||
//// parseArcaLi(araca_li).apply {
|
||||
//// this.forEach {
|
||||
//// if (it.pubDate() > commicsDateTime) {
|
||||
//// temp.add(it.getRssData())
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// } catch (e : Exception) {
|
||||
//// e.printStackTrace()
|
||||
//// }
|
||||
//
|
||||
// }
|
||||
//// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
|
||||
//// BLog.LOGE("projectj >>>>> ${projectj}")
|
||||
//// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
// }
|
||||
return Result.success().apply {
|
||||
WorkersDb.insertBulkData(temp)
|
||||
// WorkersDb.insertBulkData(temp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +45,7 @@ import io.realm.kotlin.query.RealmQuery
|
||||
import io.realm.kotlin.query.Sort
|
||||
import io.realm.kotlin.types.BaseRealmObject
|
||||
import io.realm.kotlin.types.TypedRealmObject
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
@ -104,34 +105,32 @@ object WorkersDb {
|
||||
|
||||
// val blockKeyword = arrayListOf<String>("붕괴 스타레일","붕괴 스타일","트릭컬 RE:VIVE","원신","메이플스토리","")
|
||||
fun insertBulkData(rssDatas: Collection<RssData>) {
|
||||
rssDatas.forEach {
|
||||
try {
|
||||
getRealm().writeBlocking {
|
||||
try {
|
||||
rssDatas.forEach { t ->
|
||||
var results= query<RssData>("originPage == $0", t.originPage).find()
|
||||
if (results.isEmpty()) {
|
||||
if(it.category().equals(RssDataType.PRIVATE)) {
|
||||
it.pubDate = afterDay(it.pubDate)
|
||||
}
|
||||
this.copyToRealm(t, UpdatePolicy.ERROR)
|
||||
} else {
|
||||
if(it.category().equals(RssDataType.PRIVATE)) {
|
||||
it.pubDate = afterDay(it.pubDate)
|
||||
it.vote = results.first().vote
|
||||
it.read = results.first().read
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
}
|
||||
try {
|
||||
getRealm().writeBlocking {
|
||||
try {
|
||||
rssDatas.forEach { t ->
|
||||
var results= query<RssData>("originPage == $0", t.originPage).find()
|
||||
if (results.isEmpty()) {
|
||||
if(t.category().equals(RssDataType.PRIVATE)) {
|
||||
t.pubDate = afterDay(t.pubDate)
|
||||
}
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
} else {
|
||||
if(t.category().equals(RssDataType.PRIVATE)) {
|
||||
t.pubDate = afterDay(t.pubDate)
|
||||
}
|
||||
t.vote = results.first().vote
|
||||
t.read = results.first().read
|
||||
this.copyToRealm(t, UpdatePolicy.ALL)
|
||||
}
|
||||
|
||||
} catch (e : Exception) {
|
||||
|
||||
}
|
||||
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,20 @@
|
||||
tools:ignore="ContentDescription"
|
||||
android:layout_height="40dp"
|
||||
/>
|
||||
<ImageButton
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/hide"
|
||||
android:id="@+id/share"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="visible"
|
||||
android:background="@null"
|
||||
android:tint="@color/white"
|
||||
android:foregroundTint="@color/white"
|
||||
android:src="@drawable/ic_share"
|
||||
android:layout_width="40dp"
|
||||
tools:ignore="ContentDescription"
|
||||
android:layout_height="40dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/home"
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
android:textColor="@color/black"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/parivate_mode"
|
||||
android:id="@+id/private_mode"
|
||||
android:checked="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user