This commit is contained in:
lunaticbum 2025-08-21 17:20:03 +09:00
parent 2f63f8550a
commit 634d703572
16 changed files with 407 additions and 141 deletions

View File

@ -9,7 +9,7 @@
"name": "Sample Extension", "name": "Sample Extension",
"background": { "background": {
"scripts": ["background.js"] "scripts": ["Dotax.js", "background.js"]
}, },
"content_scripts": [ "content_scripts": [
{ {

View File

@ -1,5 +1,55 @@
function pubDateNumber(tdateTime) {
let date = new Date();
let dateTime = date.getTime();
let before = 0;
try {
let targetDate = tdateTime || "";
if (targetDate.length > 1) {
let dateDesc = targetDate;
let isBefore = dateDesc.includes("전");
let dayString = dateDesc.replace(/[^0-9]/g, "");
before = parseInt(dayString);
if (dateDesc.includes("년")) {
before = 365 * before;
dateTime = isBefore ? this.beforeDayBy(date, before) : this.afterDay(date, before);
} else if (dateDesc.includes("월")) {
before = 30 * before;
dateTime = isBefore ? this.beforeDayBy(date, before) : this.afterDay(date, before);
} else if (dateDesc.includes("주")) {
before = 7 * before;
dateTime = isBefore ? this.beforeDayBy(date, before) : this.afterDay(date, before);
} else if (dateDesc.includes("일")) {
dateTime = isBefore ? this.beforeDayBy(date, before) : this.afterDay(date, before);
} else if (dateDesc.includes("시간")) {
dateTime = isBefore ? dateTime - before * 60 * 60 * 1000 : dateTime + before * 60 * 60 * 1000;
} else if (dateDesc.includes("분")) {
dateTime = isBefore ? dateTime - before * 60 * 1000 : dateTime + before * 60 * 1000;
} else if (dateDesc.includes("초")) {
dateTime = isBefore ? dateTime - before * 1000 : dateTime + before * 1000;
}
}
} catch (e) {
// 예외 무시
} finally {
}
return dateTime;
}
// Kotlin의 beforeDayBy 대응 - date에서 before일 전 타임스탬프 계산 함수
function beforeDayBy(date, before) {
return date.getTime() - before * 24 * 60 * 60 * 1000;
}
// Kotlin의 afterDay 대응 - date에서 before일 후 타임스탬프 계산 함수
function afterDay(date, before) {
return date.getTime() + before * 24 * 60 * 60 * 1000;
}
const port = browser.runtime.connectNative("browser"); const port = browser.runtime.connectNative("browser");
port.onMessage.addListener(response => { port.onMessage.addListener(response => {
var type= response["type"]; var type= response["type"];
@ -360,9 +410,9 @@ function autoScrollAndSave(senContents) {
}catch (e) { } }catch (e) { }
try { try {
// 공통 광고 요소 제거는 항상 실행 // 공통 광고 요소 제거는 항상 실행
handleCommon(); handleCommon();
}catch (e) { } }catch (e) { }
if (mainContentsEl == null) { if (mainContentsEl == null) {
mainContentsEl = document.body.outerHTML mainContentsEl = document.body.outerHTML
} }
@ -397,6 +447,7 @@ const domainRules = [
{ test: url => url.includes("acrofan.com") && document.querySelectorAll('[id^="wide"]').length > 0, handler: handleAcrofan }, { test: url => url.includes("acrofan.com") && document.querySelectorAll('[id^="wide"]').length > 0, handler: handleAcrofan },
{ test: url => url.includes("yna.co.kr") && document.querySelectorAll('[class^="wrapper"]').length > 0, handler: handleYna }, { test: url => url.includes("yna.co.kr") && document.querySelectorAll('[class^="wrapper"]').length > 0, handler: handleYna },
{ test: url => url.includes("yt1d.com/"), handler: ytDown }, { test: url => url.includes("yt1d.com/"), handler: ytDown },
{ test: url => url.includes("daum.net/dotax/"), handler: autoScrollAndHandleDotax },
{ test: url => url.includes("clien") && document.querySelectorAll('[class^="content_view"]').length > 0, handler: handleClien }, { test: url => url.includes("clien") && document.querySelectorAll('[class^="content_view"]').length > 0, handler: handleClien },
{ test: url => url.includes("toki") && (document.querySelectorAll('[id^="id_mbv"]').length > 0 || document.querySelectorAll('[class^="basic-banner"]').length > 0), handler: handleToki }, { test: url => url.includes("toki") && (document.querySelectorAll('[id^="id_mbv"]').length > 0 || document.querySelectorAll('[class^="basic-banner"]').length > 0), handler: handleToki },
]; ];
@ -820,3 +871,35 @@ function handleClien() {
function handleToki() { function handleToki() {
document.querySelectorAll('[id^="id_mbv"], [class^="basic-banner"]').forEach(e => e.remove()); document.querySelectorAll('[id^="id_mbv"], [class^="basic-banner"]').forEach(e => e.remove());
} }
function delaysend() {
if(location.pathname.endsWith("Elgq")) {
sendMessage(
{
type: "DOTAX"
}
);
}
}
function autoScrollAndHandleDotax() {
if(location.pathname.endsWith("Elgq")) {
//
//
// let count = 0;
// const scrollAmount = 800;
// const maxCount = 8;
//
// function scrollAndSend() {
// window.scrollBy(0, scrollAmount);
delaysend();
// count++;
// if (count < maxCount) {
// setTimeout(scrollAndSend, 1500); // 1초 후 재실행
// }
// }
//
// // 시작
// scrollAndSend();
// }
}

View File

@ -63,6 +63,7 @@ import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import bums.lunatic.launcher.helpers.ForeGroundService import bums.lunatic.launcher.helpers.ForeGroundService
import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver
import bums.lunatic.launcher.home.GeckoWeb
import bums.lunatic.launcher.home.RssHome import bums.lunatic.launcher.home.RssHome
import bums.lunatic.launcher.home.RssViewBuilder import bums.lunatic.launcher.home.RssViewBuilder
import bums.lunatic.launcher.model.RssData import bums.lunatic.launcher.model.RssData
@ -112,52 +113,20 @@ open class LauncherActivity : CommonActivity() {
@JvmStatic var lActivity: LauncherActivity? = null @JvmStatic var lActivity: LauncherActivity? = null
// fun refreshDeviceData()
// {
//
// mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
// mWorkManager?.enqueueUniquePeriodicWork(
// SMS_WORK_TAG,
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
// PeriodicWorkRequestBuilder<RecentSmsGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
// .addTag(SMS_WORK_TAG)
// .build())
// mWorkManager?.cancelAllWorkByTag(RecentCallGetter.TAG)
// mWorkManager?.enqueueUniquePeriodicWork(
// RecentCallGetter.TAG,
// ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
// PeriodicWorkRequestBuilder<RecentCallGetter>(PrefLong.longTimePeriod.get(), TimeUnit.MINUTES)
// .addTag(RecentCallGetter.TAG)
// .build())
//
// mWorkManager?.cancelAllWorkByTag(ContactInfoGetter.TAG)
// mWorkManager?.enqueueUniquePeriodicWork(
// ContactInfoGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
// PeriodicWorkRequestBuilder<ContactInfoGetter>(12, TimeUnit.HOURS)
// .addTag(ContactInfoGetter.TAG)
// .build())
//
// mWorkManager?.enqueue(OneTimeWorkRequest.from(AppInfoGetter::class.java))
//
// }
// fun runWeatherGetter() {
// Executors.newSingleThreadScheduledExecutor().schedule({
// mWorkManager?.enqueue(OneTimeWorkRequest.from(OpenWeatherGetter::class.java))
// }, 200L, TimeUnit.MILLISECONDS)
// }
// fun getCal() {
// Executors.newSingleThreadScheduledExecutor().schedule({
// mWorkManager?.enqueue(OneTimeWorkRequest.from(CalendarGetter::class.java))
// }, 5, TimeUnit.SECONDS)
// }
} }
var hiddenLoader : GeckoWeb? = null
fun contentsLoad(url : String){
if (isDestroyed == false && isFinishing == false) {
if (hiddenLoader == null) {
GeckoWeb(this).apply {
hiddenLoader = this
loadUrl(url)
}
} else {
hiddenLoader?.loadUrl(url)
}
}
}
@SuppressLint("MissingSuperCall") @SuppressLint("MissingSuperCall")
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
@ -171,23 +140,7 @@ open class LauncherActivity : CommonActivity() {
val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL) val nullCursor = PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL)
binding.root.setPointerIcon(nullCursor) binding.root.setPointerIcon(nullCursor)
} }
// override fun onKeyClick(keyCode: Int): Boolean {
// when (keyCode) {
// KeyEvent.KEYCODE_VOLUME_DOWN -> {
// actionNextEvent()
// }
//
// KeyEvent.KEYCODE_VOLUME_UP -> {
// actionPrevEvent()
// }
//
// KeyEvent.KEYCODE_VOLUME_MUTE -> {
// actionNextEvent()
// }
//
// }
// return super.onKeyClick(keyCode)
// }
var actionButtonPressX = 0f var actionButtonPressX = 0f
var actionButtonPressY = 0f var actionButtonPressY = 0f
var onExit = false var onExit = false
@ -257,28 +210,36 @@ open class LauncherActivity : CommonActivity() {
return true return true
} }
else { else {
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) { val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
return when (ev.keyCode) { when(currentFragment) {
KeyEvent.KEYCODE_VOLUME_DOWN -> { is Novels -> {
if(currentFragment is Novels){ currentFragment.actionNextEvent() } if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
true return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if(currentFragment is Novels){ currentFragment.actionNextEvent() }
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if(currentFragment is Novels){ currentFragment.actionPrevEvent() }
true
}
else -> false
}
} else {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
true
}
else -> false
}
} }
KeyEvent.KEYCODE_VOLUME_UP -> {
if(currentFragment is Novels){ currentFragment.actionPrevEvent() }
true
}
else -> false
}
} else {
return when (ev.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
true
}
KeyEvent.KEYCODE_VOLUME_UP -> {
true
}
else -> false
} }
else -> return super.dispatchKeyEvent(ev)
} }
} }
return super.dispatchKeyEvent(ev) return super.dispatchKeyEvent(ev)

View File

@ -22,6 +22,7 @@ import android.app.Application
import android.content.ComponentCallbacks2 import android.content.ComponentCallbacks2
import android.content.Context import android.content.Context
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import bums.lunatic.launcher.helpers.HourlyLogWriter
import bums.lunatic.launcher.helpers.PrefHelper import bums.lunatic.launcher.helpers.PrefHelper
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import com.squareup.picasso.OkHttp3Downloader import com.squareup.picasso.OkHttp3Downloader
@ -41,7 +42,7 @@ import java.util.concurrent.TimeUnit
internal class LunaticLauncher : Application() { internal class LunaticLauncher : Application() {
companion object { companion object {
var appContext : LunaticLauncher? = null var appContext : LunaticLauncher? = null
var mHourlyLogWriter : HourlyLogWriter? = null
} }
override fun onCreate() { override fun onCreate() {
@ -49,7 +50,14 @@ internal class LunaticLauncher : Application() {
appContext = this appContext = this
Base.initialize(this) Base.initialize(this)
PrefHelper.initialize(this) PrefHelper.initialize(this)
val dir = File("/storage/emulated/0/bums_ob/BUM'S PACED /scraped/logs")
///BUM'S PACED/pdfs
if (!dir.exists()) {
dir.mkdirs()
} else {
dir.listFiles().forEach { Blog.LOGE("child -> ${it.absolutePath}") }
}
mHourlyLogWriter = HourlyLogWriter(dir)
val cacheSize = 1024L * 1024 * 1024 // 60MB val cacheSize = 1024L * 1024 * 1024 // 60MB
val cache = Cache(File(this.filesDir, "picasso-cache"), cacheSize) val cache = Cache(File(this.filesDir, "picasso-cache"), cacheSize)
val okHttpClient = OkHttpClient.Builder() val okHttpClient = OkHttpClient.Builder()

View File

@ -0,0 +1,43 @@
package bums.lunatic.launcher.helpers
import android.content.Context
import bums.lunatic.launcher.utils.Blog
import kotlinx.coroutines.*
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.atomic.AtomicReference
class HourlyLogWriter(private val logDir: File) {
private val ioScope = CoroutineScope(Dispatchers.IO)
private val lastFilePath = AtomicReference<String?>(null)
// 파일명 생성 (yyyyMMdd_HH)
private fun getLogFileName(): String {
val sdf = SimpleDateFormat("yyyyMMdd_HH", Locale.getDefault())
return "${sdf.format(Date())}.text"
}
// 로그 기록 함수 (비동기)
fun writeLog(data: String) {
Blog.LOGE("writeLog >>> ${data}")
ioScope.launch {
try {
if (!logDir.exists()) logDir.mkdirs()
val fileName = getLogFileName()
val logFile = File(logDir, fileName)
// 파일이 바뀌었으면 기록 경로 갱신
lastFilePath.set(logFile.absolutePath)
logFile.appendText("${System.currentTimeMillis()},$data\n")
Blog.LOGE("writeLog >>> ${logFile.length()}")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// 최근 로그 파일 경로 조회 (1시간 단위)
fun getCurrentLogFilePath(): String? = lastFilePath.get()
}

View File

@ -44,6 +44,7 @@ enum class PrefBoolean : PrefKey<Boolean> {
location, location,
rootPermisssion, rootPermisssion,
isConnectedCar, isConnectedCar,
usePublicTransportation,
useQuickLaunch, useQuickLaunch,
openWithKayboard, openWithKayboard,
showAppResultCount, showAppResultCount,

View File

@ -38,8 +38,12 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.work.Worker
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.model.Dotax
import bums.lunatic.launcher.model.DotaxArticles
import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.model.others.Button import bums.lunatic.launcher.model.others.Button
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
@ -51,6 +55,7 @@ import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLRequest import com.yausername.youtubedl_android.YoutubeDLRequest
import com.yausername.youtubedl_android.YoutubeDLResponse import com.yausername.youtubedl_android.YoutubeDLResponse
import io.realm.kotlin.ext.isValid
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -117,6 +122,7 @@ class GeckoWeb : BWebview {
session.navigationDelegate = navigationDelegate session.navigationDelegate = navigationDelegate
it.webExtensionController.setAddonManagerDelegate(addonManagerDelegate) it.webExtensionController.setAddonManagerDelegate(addonManagerDelegate)
session.mediaDelegate = mediaDelegate session.mediaDelegate = mediaDelegate
session.promptDelegate = promptDelegate
session.mediaSessionDelegate = mediaSessionDelegate session.mediaSessionDelegate = mediaSessionDelegate
// session.permissionDelegate = (object : PermissionDelegate { // session.permissionDelegate = (object : PermissionDelegate {
// override fun onContentPermissionRequest( // override fun onContentPermissionRequest(
@ -236,7 +242,32 @@ class GeckoWeb : BWebview {
} }
} }
val promptDelegate = object : GeckoSession.PromptDelegate {
override fun onAlertPrompt(
session: GeckoSession,
prompt: GeckoSession.PromptDelegate.AlertPrompt
): GeckoResult<GeckoSession.PromptDelegate.PromptResponse?>? {
if(lastedUrl?.contains("daum.net/dotax") == true) {
try {
Gson().fromJson<DotaxArticles>(prompt.message,DotaxArticles::class.java)?.let {
Blog.LOGE("it.Articles >>> ${it.Articles?.size}")
it.Articles?.forEach {
Dotax("${it.fldid}/${it.dataid}","dotax",it.articleElapsedTime!!,it.title!!,it.thumbnailImageUrl!!)?.let {
it.getRssData().let {
WorkersDb.insertData(it)
}
}
}
}
} catch (e: Exception) {
}
}
Blog.LOGE("prompt >>> ${prompt.message}")
prompt.dismiss()
return super.onAlertPrompt(session, prompt)
}
}
val mediaDelegate = object : GeckoSession.MediaDelegate { val mediaDelegate = object : GeckoSession.MediaDelegate {
override fun onRecordingStatusChanged( override fun onRecordingStatusChanged(
session: GeckoSession, session: GeckoSession,
@ -681,11 +712,11 @@ class GeckoWeb : BWebview {
) { ) {
if (element.baseUri?.contains("youtube") == true) { if (element.baseUri?.contains("youtube") == true) {
lastedUrl?.let { videoUrl -> // lastedUrl?.let { videoUrl ->
lastedUrl?.let { // lastedUrl?.let {
videoDlownLoad(it) // videoDlownLoad(it)
} // }
} // }
} else { } else {
Blog.LOGE("onContextMenu:: x = ${x}, y = ${y} , element = ${Gson().toJson(element)}") Blog.LOGE("onContextMenu:: x = ${x}, y = ${y} , element = ${Gson().toJson(element)}")
if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) { if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) {
@ -859,6 +890,8 @@ class GeckoWeb : BWebview {
lastedUrl = url lastedUrl = url
} }
checkIfDownloadable(url) checkIfDownloadable(url)
} }
@ -924,6 +957,12 @@ class GeckoWeb : BWebview {
} }
"SHOWVIEWER" -> { "SHOWVIEWER" -> {
} }
"DOTAX"->{
val script = "alert(JSON.stringify({Articles : window.articles}))"
val encodedJs = Uri.encode(script)
val jsUri = "javascript:$encodedJs"
session?.loadUri(jsUri)
}
"PRIVATES"->{ "PRIVATES"->{
lPortMessage.privates?.let { lPortMessage.privates?.let {
context.toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}") context.toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}")

View File

@ -301,6 +301,30 @@ class RssData : RealmObject, RssDataInterface {
} }
class DotaxArticles {
var Articles : ArrayList<DotaxArticle> ? = null
}
class DotaxArticle {
var dataid : String? = null //4623278
var fldid : String? = null //"Elgq"
var title : String? = null //"손 크다고 자랑하는 여직원"
var thumbnailImageUrl : String? = null //"https://img1.daumcdn.net/thumb/C52x52/?fname=https://t1.daumcdn.net/cafeattach/mEr9/e62d71b492cb60155d32a649df324a990564c06f"
var viewCount : String? = null //116
var commentCount : String? = null //0
var writerNickname : String? = null //"녹두로로"
var articleElapsedTime : String? = null //"방금전"
var hasMovie : String? = null //false
var hasParentArticle : String? = null //false
var articleWriter : String? = null //false
var newArticle : String? = null //true
var headCont : String? = null //""
var escrow : String? = null //false
var hasSoldItem : String? = null //false
var bbsDepth : String? = null //"0JOj0zzzzzzzzzzzzzzzzzzzzzzzzz"
}
open class Dotax(var pageLink : String, open class Dotax(var pageLink : String,
var desc : String, var desc : String,
var dateTime : String, var dateTime : String,
@ -323,7 +347,7 @@ open class Dotax(var pageLink : String,
} }
override fun originPage(): String { override fun originPage(): String {
return "https://m.cafe.daum.net".plus(pageLink) return "https://m.cafe.daum.net/dotax/".plus(pageLink)
} }
override fun description(): String { override fun description(): String {

View File

@ -1,11 +1,14 @@
package bums.lunatic.launcher.receiver package bums.lunatic.launcher.receiver
import android.Manifest
import android.app.Notification import android.app.Notification
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.location.Geocoder
import android.location.Location
import android.media.MediaMetadata import android.media.MediaMetadata
import android.media.session.MediaSessionManager import android.media.session.MediaSessionManager
import android.media.session.PlaybackState.STATE_PLAYING import android.media.session.PlaybackState.STATE_PLAYING
@ -13,15 +16,41 @@ import android.os.Build
import android.service.notification.NotificationListenerService import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import bums.lunatic.launcher.LunaticLauncher.Companion.mHourlyLogWriter
import bums.lunatic.launcher.common.letTrue
import bums.lunatic.launcher.helpers.ForeGroundService import bums.lunatic.launcher.helpers.ForeGroundService
import bums.lunatic.launcher.helpers.ForeGroundService.Companion.ACTION_SENDMSG
import bums.lunatic.launcher.helpers.ForeGroundService.Companion.EXTRA_MSGKEY
import bums.lunatic.launcher.helpers.PrefBoolean
import bums.lunatic.launcher.helpers.PrefString
import bums.lunatic.launcher.model.CurrentPlayItem import bums.lunatic.launcher.model.CurrentPlayItem
import bums.lunatic.launcher.model.LocationLog
import bums.lunatic.launcher.model.NotificationItem import bums.lunatic.launcher.model.NotificationItem
import bums.lunatic.launcher.utils.BitmapConverter import bums.lunatic.launcher.utils.BitmapConverter
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import bums.lunatic.launcher.workers.LocationUpdateService.Companion.inRangeLocation
import bums.lunatic.launcher.workers.WorkersDb import bums.lunatic.launcher.workers.WorkersDb
import com.google.android.gms.location.LocationServices
import com.google.gson.Gson
import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import io.realm.kotlin.query.Sort
import okhttp3.ConnectionPool
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.ResponseBody
import java.io.File
import java.io.IOException
import java.lang.Exception
import java.util.Base64
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
class NLService : NotificationListenerService() { class NLService : NotificationListenerService() {
@ -46,12 +75,6 @@ class NLService : NotificationListenerService() {
Blog.LOGE("onNotificationPosted ${sbn}") Blog.LOGE("onNotificationPosted ${sbn}")
val notification = sbn.notification val notification = sbn.notification
val extras = notification.extras val extras = notification.extras
when (sbn.packageName){
"com.kakao.talk" -> {
}
}
val title = extras.getString(Notification.EXTRA_TITLE) ?: "" val title = extras.getString(Notification.EXTRA_TITLE) ?: ""
val text = extras.getCharSequence(Notification.EXTRA_TEXT)?.toString() ?: "" val text = extras.getCharSequence(Notification.EXTRA_TEXT)?.toString() ?: ""
val bigText = extras.getCharSequence(Notification.EXTRA_BIG_TEXT)?.toString() ?: "" val bigText = extras.getCharSequence(Notification.EXTRA_BIG_TEXT)?.toString() ?: ""
@ -60,9 +83,72 @@ class NLService : NotificationListenerService() {
val conversationTitle = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE)?.toString() ?: "" val conversationTitle = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE)?.toString() ?: ""
val summaryText = extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT)?.toString() ?: "" val summaryText = extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT)?.toString() ?: ""
val verificationText = extras.getCharSequence(Notification.EXTRA_VERIFICATION_TEXT)?.toString() ?: "" val verificationText = extras.getCharSequence(Notification.EXTRA_VERIFICATION_TEXT)?.toString() ?: ""
val stringBuffer = StringBuffer()
stringBuffer.append(title).append("\n")
stringBuffer.append(text).append("\n")
stringBuffer.append(bigText).append("\n")
stringBuffer.append(extraInfo).append("\n")
stringBuffer.append(subText).append("\n")
stringBuffer.append(conversationTitle).append("\n")
stringBuffer.append(summaryText).append("\n")
stringBuffer.append(verificationText).append("\n")
Blog.LOGE("title >> ${title} text >> ${text} bigText >> ${bigText} extraInfo >> ${extraInfo} subText >> ${subText} conversationTitle >> ${conversationTitle} summaryText >> ${summaryText} verificationText >> ${verificationText}") Blog.LOGE("title >> ${title} text >> ${text} bigText >> ${bigText} extraInfo >> ${extraInfo} subText >> ${subText} conversationTitle >> ${conversationTitle} summaryText >> ${summaryText} verificationText >> ${verificationText}")
mHourlyLogWriter?.writeLog("${sbn.packageName}\n${stringBuffer.toString()}")
when (sbn.packageName){
"com.kakao.talk" -> {
}
"kakaopay.app" -> {
if (stringBuffer.contains("모바일") && stringBuffer.contains("교통카드")) {
var usePublicTransportation = PrefBoolean.usePublicTransportation.get(false)
PrefBoolean.usePublicTransportation.set(!usePublicTransportation)
val actionIntent = Intent(this, ForeGroundService::class.java).apply {
action = ACTION_SENDMSG
putExtra(EXTRA_MSGKEY, "돼지가 대중교통에${if (!usePublicTransportation){" 탑승 "} else {" 하차"}} 했다요~!") // 전달할 데이터
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(actionIntent)
} else {
startService(actionIntent)
}
}
}
}
}
@RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
fun pushLocation(context: Context) {
try {
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let {
val latitude = it.latitude
val longitude = it.longitude
// 현 위치 사용
val geocoder = Geocoder(context, Locale.getDefault())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
geocoder.getFromLocation(latitude, longitude, 1) { addresses ->
addresses.first()?.let {
it.getAddressLine(0)?.let { addr ->
val actionIntent = Intent(this, ForeGroundService::class.java).apply {
action = ACTION_SENDMSG
putExtra(EXTRA_MSGKEY, "대중교통 이용 위치:\n${addr}") // 전달할 데이터
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(actionIntent)
} else {
startService(actionIntent)
}
}
}
}
}
}
}
} catch (e: IOException) {
e.printStackTrace()
}
} }
override fun onNotificationRemoved(sbn: StatusBarNotification) { override fun onNotificationRemoved(sbn: StatusBarNotification) {

View File

@ -161,8 +161,7 @@ class PagedTextView : AppCompatTextView {
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh) super.onSizeChanged(w, h, oldw, oldh)
Blog.LOGD(log = "onSizeChanged>> ${this::class.java.name}") pageHeight = h - (paddingTop + paddingBottom) // 마진 제외
pageHeight = ((h - (marginTop + marginBottom + paddingTop + paddingBottom)) * 1f).toInt()
} }
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
@ -221,25 +220,27 @@ class PagedTextView : AppCompatTextView {
private fun from(layout: Layout): Layout = private fun from(layout: Layout): Layout =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
(StaticLayout( StaticLayout(
originalText, originalText,
paint, paint,
layout.width, layout.width - paddingLeft - paddingRight, // margin 제외
layout.alignment, layout.alignment,
lineSpacingMultiplier, lineSpacingMultiplier,
lineSpacingExtra, lineSpacingExtra,
includeFontPadding includeFontPadding
)) )
} else { } else {
StaticLayout.Builder StaticLayout.Builder
.obtain(originalText, 0, originalText.length, paint, ((layout.width - (paddingLeft + paddingRight + marginLeft + marginRight) * 0.85f)).toInt()) .obtain(
originalText, 0, originalText.length, paint,
(layout.width - paddingLeft - paddingRight)
)
.setAlignment(layout.alignment) .setAlignment(layout.alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier) .setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(includeFontPadding) .setIncludePad(includeFontPadding)
.setUseLineSpacingFromFallbacks() .setUseLineSpacingFromFallbacks()
.setBreakStrategy(breakStrategy) .setBreakStrategy(breakStrategy)
.setHyphenationFrequency(hyphenationFrequency) .setHyphenationFrequency(hyphenationFrequency)
// .setJustificationMode()
.setMaxLines(maxLines) .setMaxLines(maxLines)
.build() .build()
} }

View File

@ -11,7 +11,11 @@ object RssList {
"https://www.youtube.com/@sungsikyung", "https://www.youtube.com/@sungsikyung",
"https://www.youtube.com/@%EC%A7%80%EB%AC%B4%EB%B9%84", "https://www.youtube.com/@%EC%A7%80%EB%AC%B4%EB%B9%84",
"https://www.youtube.com/@gyeomsonisnothing", "https://www.youtube.com/@gyeomsonisnothing",
"https://www.youtube.com/@ddeunddeun" "https://www.youtube.com/@ddeunddeun",
"https://www.youtube.com/@fairyjaehyung",
"https://www.youtube.com/@15ya_egg",
"https://www.youtube.com/@%EC%A7%80%EB%AC%B4%EB%B9%84",
"https://www.youtube.com/"
) )
val newsFeeds = arrayListOf( val newsFeeds = arrayListOf(
"https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko", "https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko",

View File

@ -22,7 +22,7 @@ open abstract class BaseGetter : Worker {
} }
} }
val USAGT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" val USAGT = "Mozilla/5.0 (Android 15; Mobile; rv:141.0) Gecko/141.0 Firefox/141.0"
val limitDateTime = beforeOneDay() val limitDateTime = beforeOneDay()
val commicsDateTime = beforeDay(1) val commicsDateTime = beforeDay(1)

View File

@ -3,10 +3,16 @@ package bums.lunatic.launcher.workers
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.home.GeckoWeb
import bums.lunatic.launcher.model.Dotax import bums.lunatic.launcher.model.Dotax
import bums.lunatic.launcher.model.RssDataType import bums.lunatic.launcher.model.RssDataType
import bums.lunatic.launcher.model.getRssData import bums.lunatic.launcher.model.getRssData
import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.Blog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jsoup.Jsoup import org.jsoup.Jsoup
class DotaxGetter : BaseGetter { class DotaxGetter : BaseGetter {
@ -23,33 +29,41 @@ class DotaxGetter : BaseGetter {
try { try {
Blog.LOGE("realWork() ${this::class.simpleName}") Blog.LOGE("realWork() ${this::class.simpleName}")
temp.clear() temp.clear()
val dotaxUrls = arrayListOf("https://m.cafe.daum.net/dotax", // val dotaxUrls = arrayListOf("https://cafe.daum.net/dotax",
"https://m.cafe.daum.net/dotax/_rec?page=2", // "https://m.cafe.daum.net/dotax/Elgq"
// "https://m.cafe.daum.net/dotax/_rec?page=3" //// "https://m.cafe.daum.net/dotax/_rec?page=3"
) // )
dotaxUrls?.forEach { // dotaxUrls?.forEach { url ->
Jsoup.connect(it).userAgent(USAGT).get()?.let { dotax -> CoroutineScope(Dispatchers.Main).launch {
dotax.getElementsByTag("li").forEach { dotax_li -> withContext(Dispatchers.Main) {
Blog.LOGE("dotax_li >>> ${dotax_li.text()}") LauncherActivity.lActivity?.let {
if (dotax_li.getElementsByTag("a").size > 0 && dotax_li.getElementsByClass("board_name") it.contentsLoad("https://m.cafe.daum.net/dotax/Elgq")
.html().contains("웃긴")
) {
val pageLink = dotax_li.getElementsByTag("a").get(0).attr("href")
val desc = dotax_li.getElementsByClass("board_name").text()
val dateTime = dotax_li.getElementsByClass("created_at").text()
val title = dotax_li.getElementsByClass("txt_detail").text()
val thumbnail = dotax_li.getElementsByClass("article_thumb").text()
if (pageLink.length > 0 && desc.length > 0 && dateTime.length > 0 && title.length > 0) {
Dotax(pageLink, desc, dateTime, title, thumbnail).let { dotax ->
if(dotax.pubDate() > commicsDateTime) {
temp.add(dotax.getRssData())
}
}
}
} }
} }
} }
} // }
// dotaxUrls?.forEach {
// Jsoup.connect(it).timeout(3000).userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36").get()?.let { dotax ->
// Blog.LOGE("dotax.html() >>> ${dotax.html()}")
// dotax.getElementsByTag("tr").forEach { dotax_li ->
// Blog.LOGE("dotax_li >>> ${dotax_li.text()}")
// if (dotax_li.getElementsByTag("a").size > 0) {
// val pageLink = dotax_li.getElementsByTag("a").get(0).attr("href")
// val desc = dotax_li.getElementsByClass("board_name").text()
// val dateTime = dotax_li.getElementsByClass("created_at").text()
// val title = dotax_li.getElementsByClass("txt_detail").text()
// val thumbnail = dotax_li.getElementsByClass("article_thumb").text()
// if (pageLink.length > 0 && desc.length > 0 && dateTime.length > 0 && title.length > 0) {
// Dotax(pageLink, desc, dateTime, title, thumbnail).let { dotax ->
// if(dotax.pubDate() > commicsDateTime) {
// temp.add(dotax.getRssData())
// }
// }
// }
// }
// }
// }
// }
} 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

@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit
class LocationUpdateService : Service(), LocationListener { class LocationUpdateService : Service(), LocationListener {
companion object { companion object {
fun pushLocation(context: Context, lat :Double, long : Double) { fun pushLocation(context: Context, lat :Double, long : Double) {
try { try {
val geocoder = Geocoder(context, Locale.getDefault()) val geocoder = Geocoder(context, Locale.getDefault())
@ -176,6 +177,7 @@ class LocationUpdateService : Service(), LocationListener {
pushLocation(this.applicationContext, location.latitude, location.longitude) pushLocation(this.applicationContext, location.latitude, location.longitude)
} }
} }
} catch (e : Exception) { } catch (e : Exception) {
} }

View File

@ -25,7 +25,7 @@
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
<View <View
android:id="@+id/demp" android:id="@+id/demp"
android:visibility="gone" android:visibility="invisible"
android:layout_margin="5dp" android:layout_margin="5dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_width="0dp" android:layout_width="0dp"
@ -55,7 +55,7 @@
android:gravity="start" android:gravity="start"
android:includeFontPadding="false" android:includeFontPadding="false"
android:lineSpacingExtra="0dp" android:lineSpacingExtra="0dp"
android:visibility="gone" android:visibility="invisible"
android:id="@+id/sencond_view" android:id="@+id/sencond_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"