This commit is contained in:
lunaticbum 2025-08-01 18:36:16 +09:00
parent 2a25b49baa
commit 1272c91430
15 changed files with 1051 additions and 676 deletions

View File

@ -115,8 +115,8 @@ dependencies {
// implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407") // implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407")
// https://mvnrepository.com/artifact/org.mozilla.geckoview/geckoview // https://mvnrepository.com/artifact/org.mozilla.geckoview/geckoview
implementation("org.mozilla.geckoview:geckoview:139.0.20250523173407") 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") // implementation("org.opencv:opencv-android:4.11.0")

View File

@ -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

View File

@ -74,13 +74,7 @@ port.onMessage.addListener(response => {
} }
break; break;
case "saveContent":{ case "saveContent":{
sendMessage( scrollToLazyImg()
{
type: "SHOWVIEWER",
contents : document.documentElement.outerHTML
}
);
} }
default: default:
port.postMessage(`Received: ${JSON.stringify(response)}`); 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) { function getList(children) {
// port.postMessage("Start of getList!" + children); // port.postMessage("Start of getList!" + children);
@ -213,7 +202,7 @@ function scrollByPercent(current , max) {
const moveAmount = pageHeight / max; const moveAmount = pageHeight / max;
window.scrollTo({ top: moveAmount * current, behavior: "smooth" }); window.scrollTo({ top: moveAmount * current, behavior: "smooth" });
} }
document.querySelector(".header__inner")
function scrollByPercentUpDown(isToDown , max) { function scrollByPercentUpDown(isToDown , max) {
const pageHeight = Math.max( const pageHeight = Math.max(
document.body.scrollHeight, document.body.scrollHeight,
@ -227,364 +216,68 @@ function scrollByPercentUpDown(isToDown , max) {
const moveAmount = Math.max(pageHeight / max,150); const moveAmount = Math.max(pageHeight / max,150);
window.scrollTo({ top: currentScroll + (moveAmount * isToDown) , behavior: "smooth" }); window.scrollTo({ top: currentScroll + (moveAmount * isToDown) , behavior: "smooth" });
} }
function loadComplete() { function loadComplete() {
// try {port.postMessage(JSON.stringify({type: "NotRegistered"}));}catch (e) {} // try {port.postMessage(JSON.stringify({type: "NotRegistered"}));}catch (e) {}
} }
function sendMessage(msg) { function sendMessage(msg) {
port.postMessage(JSON.stringify(msg)); port.postMessage(JSON.stringify(msg));
} }
function toast(msg) { function toast(msg) {
port.postMessage(JSON.stringify({type:"MSG",msg:msg})); port.postMessage(JSON.stringify({type:"MSG",msg:msg}));
} }
var time1 = null
var mainContentsEl = null
if (port) { 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
);
function scrollStep() {
time1 = setTimeout( // 페이지 최대값(일정 margin 여유)
maxY = Math.max(
document.body.scrollHeight,
function(){ document.documentElement.scrollHeight
if (location.hostname.search("clien") > -1 && document.querySelectorAll('[class^="view_top"]')) { );
document.querySelectorAll('[class^="view_top"]').forEach(e => e.remove()) if (currentY + step < maxY - window.innerHeight) {
} currentY += step;
window.scrollTo({ top: currentY, behavior: 'smooth' });
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[id^="id_mbv"]')) { setTimeout(scrollStep, delay);
document.querySelectorAll('[id^="id_mbv"]').forEach(e => e.remove()) } else {
} // 끝까지 도달하면 마지막으로 최하단 이동
if (location.hostname.search("toki") > -1 && document.querySelectorAll('[class^="basic-banner"]')) { window.scrollTo({ top: maxY, behavior: 'smooth' });
document.querySelectorAll('[class^="basic-banner"]').forEach(e => e.remove()) setTimeout(function() {
} // == 여기에 저장 등 후처리 콜백 코드 호출 ==
if (document.querySelector(".top_google_ad_space")) { if (typeof autoScrollAndSave === 'function') {
document.querySelector(".top_google_ad_space").remove() autoScrollAndSave(true);
} } else {
if (document.querySelectorAll(".adv-group")) { // 직접 메시지 보내거나, 원하는 최종 동작 실행
document.querySelectorAll(".adv-group").forEach(e => // 예: window.postMessage('saveToObsidian', '*');
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()
} }
}) }, 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("&amp;", "&");
}
})
})
}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 targetUrl = ""
var time2 = null var time2 = null
var time1 = null
function gotoNext() { function gotoNext() {
clearTimeout(time1) clearTimeout(time1)
try{ try{
@ -614,4 +307,484 @@ function gotoNext() {
} catch (e) { } 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("&amp;", "&");
}
})
})
} 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});
}
} }

View File

@ -1,168 +1,168 @@
//package android.print; package android.print;
//
//import android.app.Activity; import android.app.Activity;
//import android.content.Context; import android.content.Context;
//import android.os.Bundle; import android.os.Bundle;
//import android.os.CancellationSignal; import android.os.CancellationSignal;
//import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
//import android.webkit.WebView; import android.webkit.WebView;
//import android.webkit.WebViewClient; import android.webkit.WebViewClient;
//
//import java.io.File; import java.io.File;
//import java.io.FileInputStream; import java.io.FileInputStream;
//import java.io.FileOutputStream; import java.io.FileOutputStream;
//import java.io.IOException; import java.io.IOException;
//import java.io.InputStream; import java.io.InputStream;
//import java.io.OutputStream; import java.io.OutputStream;
//
//public class PDFPrint { public class PDFPrint {
//
// public static void generatePDFFromHTML(final Context context, final File file, final String htmlString, final OnPDFPrintListener onPDFPrintListener) { public static void generatePDFFromHTML(final Context context, final File file, final String htmlString, final OnPDFPrintListener onPDFPrintListener) {
// final WebView mWebView = new WebView(context); final WebView mWebView = new WebView(context);
// mWebView.setWebViewClient(new WebViewClient() { mWebView.setWebViewClient(new WebViewClient() {
// @Override @Override
// public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
// PrintAttributes printAttributes = new PrintAttributes.Builder() PrintAttributes printAttributes = new PrintAttributes.Builder()
// .setMediaSize(PrintAttributes.MediaSize.ISO_A4) .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
// .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600)) .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
// .setMinMargins(PrintAttributes.Margins.NO_MARGINS) .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
// .build(); .build();
//
// final PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter(file.getName()); final PrintDocumentAdapter documentAdapter = mWebView.createPrintDocumentAdapter(file.getName());
// documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() { documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
// @Override @Override
// public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
// documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() { documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
//
// @Override @Override
// public void onWriteCancelled() { public void onWriteCancelled() {
// super.onWriteCancelled(); super.onWriteCancelled();
// onPDFPrintListener.onError(new Exception("PDF Write cancelled.")); onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
// } }
//
// @Override @Override
// public void onWriteFailed(CharSequence error) { public void onWriteFailed(CharSequence error) {
// super.onWriteFailed(error); super.onWriteFailed(error);
// onPDFPrintListener.onError(new Exception(error.toString())); onPDFPrintListener.onError(new Exception(error.toString()));
// } }
//
// @Override @Override
// public void onWriteFinished(PageRange[] pages) { public void onWriteFinished(PageRange[] pages) {
// super.onWriteFinished(pages); super.onWriteFinished(pages);
// onPDFPrintListener.onSuccess(file); onPDFPrintListener.onSuccess(file);
// } }
// }); });
// } }
// }, null); }, null);
// } }
// }); });
// mWebView.loadData(htmlString.replaceAll("#", "%23"), "text/HTML", "UTF-8"); mWebView.loadData(htmlString.replaceAll("#", "%23"), "text/HTML", "UTF-8");
// } }
//
// public static void generatePDFFromWebView(final File file, final WebView webView, final OnPDFPrintListener onPDFPrintListener) { public static void generatePDFFromWebView(final File file, final WebView webView, final OnPDFPrintListener onPDFPrintListener) {
// PrintAttributes printAttributes = new PrintAttributes.Builder() PrintAttributes printAttributes = new PrintAttributes.Builder()
// .setMediaSize(PrintAttributes.MediaSize.ISO_A4) .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
// .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600)) .setResolution(new PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
// .setMinMargins(PrintAttributes.Margins.NO_MARGINS) .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
// .build(); .build();
//
// final PrintDocumentAdapter documentAdapter = webView.createPrintDocumentAdapter(file.getName()); final PrintDocumentAdapter documentAdapter = webView.createPrintDocumentAdapter(file.getName());
// documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() { documentAdapter.onLayout(null, printAttributes, null, new PrintDocumentAdapter.LayoutResultCallback() {
// @Override @Override
// public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
// documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() { documentAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(file), null, new PrintDocumentAdapter.WriteResultCallback() {
//
// @Override @Override
// public void onWriteCancelled() { public void onWriteCancelled() {
// super.onWriteCancelled(); super.onWriteCancelled();
// onPDFPrintListener.onError(new Exception("PDF Write cancelled.")); onPDFPrintListener.onError(new Exception("PDF Write cancelled."));
// } }
//
// @Override @Override
// public void onWriteFailed(CharSequence error) { public void onWriteFailed(CharSequence error) {
// super.onWriteFailed(error); super.onWriteFailed(error);
// try { try {
// if (error != null && error.toString().length() > 0) { if (error != null && error.toString().length() > 0) {
// onPDFPrintListener.onError(new Exception(error.toString())); onPDFPrintListener.onError(new Exception(error.toString()));
// } else { } else {
// onPDFPrintListener.onError(new Exception("Empty Page")); onPDFPrintListener.onError(new Exception("Empty Page"));
// } }
// }catch (Exception e) {e.printStackTrace();} }catch (Exception e) {e.printStackTrace();}
// } }
//
// @Override @Override
// public void onWriteFinished(PageRange[] pages) { public void onWriteFinished(PageRange[] pages) {
// super.onWriteFinished(pages); super.onWriteFinished(pages);
// onPDFPrintListener.onSuccess(file); onPDFPrintListener.onSuccess(file);
// } }
// }); });
// } }
// }, null); }, null);
// } }
//
// private static ParcelFileDescriptor getOutputFile(File file) { private static ParcelFileDescriptor getOutputFile(File file) {
// try { try {
// if (!file.exists()) { if (!file.exists()) {
// file.createNewFile(); file.createNewFile();
// } }
// return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE); return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
// } catch (Exception e) { } catch (Exception e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// return null; return null;
// } }
//
// public static PrintJob printPDF(final Activity activity, final File pdfFileToPrint, final PrintAttributes printAttributes) { public static PrintJob printPDF(final Activity activity, final File pdfFileToPrint, final PrintAttributes printAttributes) {
// PrintManager printManager = (PrintManager) activity.getSystemService(Context.PRINT_SERVICE); PrintManager printManager = (PrintManager) activity.getSystemService(Context.PRINT_SERVICE);
// String jobName = Long.valueOf(System.currentTimeMillis()).toString(); String jobName = Long.valueOf(System.currentTimeMillis()).toString();
// return printManager.print(jobName, new PrintDocumentAdapter() { return printManager.print(jobName, new PrintDocumentAdapter() {
// @Override @Override
// public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) { public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
// InputStream input = null; InputStream input = null;
// OutputStream output = null; OutputStream output = null;
//
// try { try {
//
// input = new FileInputStream(pdfFileToPrint); input = new FileInputStream(pdfFileToPrint);
// output = new FileOutputStream(destination.getFileDescriptor()); output = new FileOutputStream(destination.getFileDescriptor());
//
// byte[] buf = new byte[1024]; byte[] buf = new byte[1024];
// int bytesRead; int bytesRead;
//
// while ((bytesRead = input.read(buf)) > 0) { while ((bytesRead = input.read(buf)) > 0) {
// output.write(buf, 0, bytesRead); output.write(buf, 0, bytesRead);
// } }
//
// callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES}); callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
//
// } catch (Exception e) { } catch (Exception e) {
// e.printStackTrace(); e.printStackTrace();
// } finally { } finally {
// try { try {
// input.close(); input.close();
// output.close(); output.close();
// } catch (IOException e) { } catch (IOException e) {
// e.printStackTrace(); e.printStackTrace();
// } }
// } }
// } }
//
// @Override @Override
// public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) { public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
// if (cancellationSignal.isCanceled()) { if (cancellationSignal.isCanceled()) {
// callback.onLayoutCancelled(); callback.onLayoutCancelled();
// return; return;
// } }
//
// PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(pdfFileToPrint.getName()).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build(); PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(pdfFileToPrint.getName()).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
// callback.onLayoutFinished(pdi, true); callback.onLayoutFinished(pdi, true);
// } }
// }, printAttributes); }, printAttributes);
// } }
//
// public interface OnPDFPrintListener { public interface OnPDFPrintListener {
// void onSuccess(File file); void onSuccess(File file);
//
// void onError(Exception exception); void onError(Exception exception);
// } }
//} }

View File

@ -569,8 +569,11 @@ internal class LauncherActivity : CommonActivity() {
private fun initGeckoRuntime() { private fun initGeckoRuntime() {
if (sRuntime == null) { if (sRuntime == null) {
try { try {
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder().extensionsProcessEnabled(true) sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
.extensionsWebAPIEnabled(true).experimentDelegate(experimentDelegate) .extensionsProcessEnabled(true)
.extensionsWebAPIEnabled(true)
.experimentDelegate(experimentDelegate)
.debugLogging(false)
.remoteDebuggingEnabled(true).build()) .remoteDebuggingEnabled(true).build())
} catch (e : Exception) { } catch (e : Exception) {
e.printStackTrace() e.printStackTrace()
@ -717,6 +720,7 @@ internal class LauncherActivity : CommonActivity() {
} }
val callBackHandler = Handler(Looper.getMainLooper()) val callBackHandler = Handler(Looper.getMainLooper())
} }

View File

@ -73,9 +73,9 @@ class BluetoothManager : Service() {
val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED) val filter = IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)
registerReceiver(bluetoothreceiver, filter) registerReceiver(bluetoothreceiver, filter)
refreshFeeds() refreshFeeds()
// GeckoWeb(applicationContext).apply { GeckoWeb(applicationContext).apply {
// loadUrl("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=") loadUrl("https://arca.live/b/live")
// } }
} }
override fun onBind(intent: Intent?): IBinder? { override fun onBind(intent: Intent?): IBinder? {

View File

@ -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")
}
}
)
}
}

View File

@ -1,5 +1,6 @@
package bums.lunatic.launcher.home package bums.lunatic.launcher.home
import CustomVideoNodeRenderer
import android.app.DownloadManager import android.app.DownloadManager
import android.content.Context import android.content.Context
import android.content.DialogInterface 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.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Base64 import android.util.Base64
import android.util.Log 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.KeyEvent.KEYCODE_DPAD_UP
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.EditText import android.widget.EditText
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri
import androidx.core.view.isVisible import androidx.core.view.isVisible
import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime
import bums.lunatic.launcher.R 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.data.model.PortMessage
import bums.lunatic.launcher.tokiz.view.BWebview 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.Blog
import bums.lunatic.launcher.utils.afterDay
import bums.lunatic.launcher.workers.WorkersDb import bums.lunatic.launcher.workers.WorkersDb
import bums.lunatic.launcher.workers.WorkersDb.getRealm
import com.google.gson.Gson 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.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.mozilla.gecko.util.ThreadUtils import org.mozilla.gecko.util.ThreadUtils
import org.mozilla.geckoview.BuildConfig
import org.mozilla.geckoview.ExperimentDelegate import org.mozilla.geckoview.ExperimentDelegate
import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings
import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoView
import org.mozilla.geckoview.MediaSession import org.mozilla.geckoview.MediaSession
import org.mozilla.geckoview.WebExtension import org.mozilla.geckoview.WebExtension
import org.mozilla.geckoview.WebExtension.MessageDelegate 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.WebExtensionController.AddonManagerDelegate
import org.mozilla.geckoview.WebRequestError import org.mozilla.geckoview.WebRequestError
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date
class GeckoWeb : BWebview { class GeckoWeb : BWebview {
constructor(context: Context?) : super(context) { constructor(context: Context?) : super(context) {
@ -84,6 +85,7 @@ class GeckoWeb : BWebview {
val extId = "messaging@booktoki468.com" val extId = "messaging@booktoki468.com"
private fun buildWeb() { private fun buildWeb() {
getRuntime()?.let { getRuntime()?.let {
val session: GeckoSession = GeckoSession() val session: GeckoSession = GeckoSession()
session.open(it) session.open(it)
@ -275,30 +277,108 @@ class GeckoWeb : BWebview {
} }
fun showImageDownloadDialog(context: Context, imageUrl: Uri) { 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}") 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) val request = DownloadManager.Request(url)
request.setTitle(fileName) request.setTitle(fileName)
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
request.setDescription("이미지 다운로드 중...") request.setDescription("이미지 다운로드 중...")
request.setAllowedOverMetered(true) // 선택 사항 - 데이터 요금제 네트워크에서도 허용
request.setVisibleInDownloadsUi(true)
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
// 네트워크타입, 알림설정 등 옵션 추가 가능 // 네트워크타입, 알림설정 등 옵션 추가 가능
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
dm.enqueue(request)
Toast.makeText(context, "다운로드 시작: $fileName", Toast.LENGTH_SHORT).show() 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())) fun getFilterF() = String(java.util.Base64.getMimeDecoder().decode("aHR0cHM6Ly9pamF2dG9ycmVudC5jb20=".toByteArray()))
val contentDelegate = object : GeckoSession.ContentDelegate { val contentDelegate = object : GeckoSession.ContentDelegate {
override fun onTitleChange( override fun onTitleChange(
@ -361,6 +441,8 @@ class GeckoWeb : BWebview {
} }
override fun onPageStart(session: GeckoSession, url: String) { override fun onPageStart(session: GeckoSession, url: String) {
super.onPageStart(session, url) super.onPageStart(session, url)
markdownContents = null
markdownUri = null
if (url.contains(getFilterF()) && privateMode) { if (url.contains(getFilterF()) && privateMode) {
this@GeckoWeb.visibility = View.INVISIBLE this@GeckoWeb.visibility = View.INVISIBLE
} }
@ -418,14 +500,17 @@ class GeckoWeb : BWebview {
loadUrl(uri) loadUrl(uri)
} else { } else {
val builder: AlertDialog.Builder = AlertDialog.Builder(context) val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder.setTitle("Move To") builder.setTitle("Move To\n${uri}")
val viewInflated: View = LayoutInflater.from(context) val viewInflated: View = LayoutInflater.from(context)
.inflate(R.layout.text_inpu_password, null, false) .inflate(R.layout.text_inpu_password, null, false)
val input = viewInflated.findViewById<View>(R.id.input) as EditText 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 input.visibility = View.GONE
builder.setView(viewInflated) builder.setView(viewInflated)
builder.setPositiveButton( builder.setPositiveButton(
android.R.string.ok, "브라우저로 이동",
DialogInterface.OnClickListener { dialog, which -> DialogInterface.OnClickListener { dialog, which ->
dialog.dismiss() dialog.dismiss()
context.startActivity(Intent().apply { context.startActivity(Intent().apply {
@ -435,6 +520,12 @@ class GeckoWeb : BWebview {
data = it data = it
}) })
}) })
builder.setNeutralButton(
"페이지 이동",
DialogInterface.OnClickListener { dialog, which ->
loadUrl(uri)
dialog.cancel()
})
builder.setNegativeButton( builder.setNegativeButton(
android.R.string.cancel, android.R.string.cancel,
DialogInterface.OnClickListener { dialog, which -> dialog.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 = val portDelegate: PortDelegate =
object : 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 -> { else -> {
} }
@ -542,6 +664,9 @@ class GeckoWeb : BWebview {
} }
} }
var markdownContents : String? = null
var markdownUri : Uri? = null
val cacheDelegate: PortDelegate = val cacheDelegate: PortDelegate =
object : PortDelegate { object : PortDelegate {
override fun onPortMessage( override fun onPortMessage(

View File

@ -277,7 +277,9 @@ internal class RssHome : Fragment() {
val viewInflated: View = LayoutInflater.from(requireContext()) val viewInflated: View = LayoutInflater.from(requireContext())
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false) .inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
val input = viewInflated.findViewById<View>(R.id.input) as EditText 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-> privateMode.setOnCheckedChangeListener { v,c->
binding.geckoWeb.privateMode = c binding.geckoWeb.privateMode = c
} }
@ -290,7 +292,7 @@ internal class RssHome : Fragment() {
dialog.dismiss() dialog.dismiss()
var command = input.editableText?.toString() var command = input.editableText?.toString()
if (command?.length ?: 0 > 0) { if (command?.length ?: 0 > 0) {
queryInfos(keywords = command!!.split(" ")!!) queryInfos(keywords = command!!.split(" ")!!, addVote.isChecked, addRead.isChecked)
} }
}) })
builder.setNegativeButton( builder.setNegativeButton(
@ -301,13 +303,16 @@ internal class RssHome : Fragment() {
} }
fun ask() { fun ask() {
val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext()) val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
builder.setTitle("Command Line") builder.setTitle("Command Line")
val viewInflated: View = LayoutInflater.from(requireContext()) val viewInflated: View = LayoutInflater.from(requireContext())
.inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false) .inflate(R.layout.text_inpu_password, binding.root as ViewGroup?, false)
val input = viewInflated.findViewById<View>(R.id.input) as EditText 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-> privateMode.setOnCheckedChangeListener { v,c->
binding.geckoWeb.privateMode = c binding.geckoWeb.privateMode = c
} }
@ -447,6 +452,9 @@ internal class RssHome : Fragment() {
vote() vote()
} }
} }
binding.share.setOnClickListener {
binding.geckoWeb.saveMd()
}
Blog.LOGE("useHiddenMenu >>> $useHiddenMenu") Blog.LOGE("useHiddenMenu >>> $useHiddenMenu")
if (useHiddenMenu) { if (useHiddenMenu) {
binding.search.setOnLongClickListener { binding.search.setOnLongClickListener {
@ -533,6 +541,7 @@ internal class RssHome : Fragment() {
} }
queryInfos() queryInfos()
binding.geckoWeb.progress = binding.progressBar binding.geckoWeb.progress = binding.progressBar
binding.geckoWeb.jxInteface = { jxEvent -> binding.geckoWeb.jxInteface = { jxEvent ->
when (jxEvent) { when (jxEvent) {
@ -560,6 +569,7 @@ internal class RssHome : Fragment() {
} }
fun vote() { fun vote() {
binding.geckoWeb?.saveMd()
currentRss?.originPage.let { currentRss?.originPage.let {
Blog.LOGE("Arrow Center Click") Blog.LOGE("Arrow Center Click")
WorkersDb.getRealm().apply { WorkersDb.getRealm().apply {
@ -627,6 +637,7 @@ internal class RssHome : Fragment() {
} }
fun updateQuery(q: RealmQuery<RssData>) { fun updateQuery(q: RealmQuery<RssData>) {
Blog.LOGE("updateQuery >>> ${q.description()}")
infosJob?.cancel() infosJob?.cancel()
commandHandler.removeCallbacks(infoUpdate) commandHandler.removeCallbacks(infoUpdate)

View File

@ -188,59 +188,64 @@ internal class RssItemAdapter (
@SuppressLint("SetTextI18n", "ClickableViewAccessibility") @SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onBindViewHolder(holder: RssHolder, position: Int) { override fun onBindViewHolder(holder: RssHolder, position: Int) {
if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) { synchronized(rssDataItemLis) {
val rssData = rssDataItemLis[position] if (rssDataItemLis.isNotEmpty() && rssDataItemLis.size > position) {
if (rssData.pubDate() > 1000L) { try {
holder.view.date.text = dateFormat.format(Date(rssData.pubDate())) val rssData = rssDataItemLis.get(position)
} else { if (rssData.pubDate() > 1000L) {
holder.view.date.text = emptyDate holder.view.date.text = dateFormat.format(Date(rssData.pubDate()))
}
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("&amp;", "&").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 { } 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("&amp;", "&").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 { // v.setOnLongClickListener {
// WorkersDb.getRealm().apply { // WorkersDb.getRealm().apply {
// copyFromRealm(rss) // copyFromRealm(rss)
// } // }
// } // }
holder.itemView.setOnLongClickListener(mLongClickListener) holder.itemView.setOnLongClickListener(mLongClickListener)
} catch (e: Exception){}
}
} }
} }
@ -268,7 +273,8 @@ internal class RssItemAdapter (
rssDataItemLis.clear() rssDataItemLis.clear()
rssDataItemLis.addAll(newList) rssDataItemLis.addAll(newList)
} }
notifyDataSetChanged()
notifyDataSetChanged()
// CoroutineScope(Dispatchers.IO).launch { // CoroutineScope(Dispatchers.IO).launch {
// rssList.clear() // rssList.clear()

View File

@ -22,57 +22,57 @@ class ArcaGetter : BaseGetter {
} }
override fun realWork(): Result { override fun realWork(): Result {
RssDataType.ARCA.isOn { // RssDataType.ARCA.isOn {
try { // try {
Blog.LOGE("realWork() ${this::class.simpleName}") // Blog.LOGE("realWork() ${this::class.simpleName}")
temp.clear() // temp.clear()
val urls = arrayListOf( // val urls = arrayListOf(
"https://arca.live/b/singbung?mode=best", // "https://arca.live/b/singbung?mode=best",
// "https://arca.live/b/headline", //// "https://arca.live/b/headline",
// "https://arca.live/b/live", //// "https://arca.live/b/live",
"https://arca.live/b/namuhotnow", // "https://arca.live/b/namuhotnow",
"https://arca.live/b/society", // "https://arca.live/b/society",
// "https://arca.live/b/replay", //// "https://arca.live/b/replay",
// "https://arca.live/b/breaking" //// "https://arca.live/b/breaking"
) // )
urls.forEach { // urls.forEach {
try { //// try {
Jsoup.connect(it) //// Jsoup.connect(it)
.userAgent(USAGT) //// .userAgent(USAGT)
.header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8") //// .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("accept-language", "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7")
.header("cache-control", "no-cache") //// .header("cache-control", "no-cache")
.header("pragma", "no-cache") //// .header("pragma", "no-cache")
.ignoreContentType(true) //// .ignoreContentType(true)
.timeout(5000) //// .timeout(5000)
.get().let { arca -> //// .get().let { arca ->
// BLog.LOGE("url >> ${it} >> ${arca}") ////// BLog.LOGE("url >> ${it} >> ${arca}")
arca.getElementsByClass("vrow hybrid").forEach { araca_li -> //// arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
if (araca_li.html().contains("title ") == true) { //// if (araca_li.html().contains("title ") == true) {
parseArcaLi(araca_li).apply { //// parseArcaLi(araca_li).apply {
this.forEach { //// this.forEach {
if (it.pubDate() > commicsDateTime) { //// if (it.pubDate() > commicsDateTime) {
temp.add(it.getRssData()) //// temp.add(it.getRssData())
} //// }
} //// }
} //// }
} //// }
} //// }
} //// }
} catch (e : Exception) { //// } catch (e : Exception) {
e.printStackTrace() //// e.printStackTrace()
} //// }
//
} // }
// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj -> //// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
// BLog.LOGE("projectj >>>>> ${projectj}") //// BLog.LOGE("projectj >>>>> ${projectj}")
//// }
// } catch (e: Exception) {
// e.printStackTrace()
// } // }
} catch (e: Exception) { // }
e.printStackTrace()
}
}
return Result.success().apply { return Result.success().apply {
WorkersDb.insertBulkData(temp) // WorkersDb.insertBulkData(temp)
} }
} }

View File

@ -45,6 +45,7 @@ import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.Sort import io.realm.kotlin.query.Sort
import io.realm.kotlin.types.BaseRealmObject import io.realm.kotlin.types.BaseRealmObject
import io.realm.kotlin.types.TypedRealmObject import io.realm.kotlin.types.TypedRealmObject
import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -104,34 +105,32 @@ object WorkersDb {
// val blockKeyword = arrayListOf<String>("붕괴 스타레일","붕괴 스타일","트릭컬 RE:VIVE","원신","메이플스토리","") // val blockKeyword = arrayListOf<String>("붕괴 스타레일","붕괴 스타일","트릭컬 RE:VIVE","원신","메이플스토리","")
fun insertBulkData(rssDatas: Collection<RssData>) { fun insertBulkData(rssDatas: Collection<RssData>) {
rssDatas.forEach { try {
try { getRealm().writeBlocking {
getRealm().writeBlocking { try {
try { rssDatas.forEach { t ->
rssDatas.forEach { t -> var results= query<RssData>("originPage == $0", t.originPage).find()
var results= query<RssData>("originPage == $0", t.originPage).find() if (results.isEmpty()) {
if (results.isEmpty()) { if(t.category().equals(RssDataType.PRIVATE)) {
if(it.category().equals(RssDataType.PRIVATE)) { t.pubDate = afterDay(t.pubDate)
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)
}
} }
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()
} }
} }

View File

@ -53,6 +53,20 @@
tools:ignore="ContentDescription" tools:ignore="ContentDescription"
android:layout_height="40dp" 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 <ImageButton
android:id="@+id/home" android:id="@+id/home"

View File

@ -54,7 +54,7 @@
android:textColor="@color/black" android:textColor="@color/black"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:id="@+id/parivate_mode" android:id="@+id/private_mode"
android:checked="true" android:checked="true"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>