From 3708f094bd4750cc5859f3328bdec40dbaf35285 Mon Sep 17 00:00:00 2001 From: lunaticbum <> Date: Tue, 3 Sep 2024 17:37:58 +0900 Subject: [PATCH] .... --- .../rasel/lunar/launcher/LauncherActivity.kt | 93 +++-- .../rasel/lunar/launcher/feeds/Feeds.kt | 31 +- .../rasel/lunar/launcher/home/LauncherHome.kt | 19 +- .../lunar/launcher/model/CommunityData.kt | 319 ++++++++++++------ .../rasel/lunar/launcher/todos/RssDataItem.kt | 2 + .../lunar/launcher/todos/RssItemAdapter.kt | 29 +- .../rasel/lunar/launcher/utils/DataManager.kt | 27 +- app/src/main/res/drawable/arca.xml | 21 ++ app/src/main/res/drawable/dcinside.png | Bin 0 -> 13512 bytes 9 files changed, 380 insertions(+), 161 deletions(-) create mode 100644 app/src/main/res/drawable/arca.xml create mode 100644 app/src/main/res/drawable/dcinside.png diff --git a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt index c4515a4c..648cf537 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt @@ -85,6 +85,8 @@ import rasel.lunar.launcher.home.LauncherHome.Companion.listTags import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet import rasel.lunar.launcher.home.RssItem import rasel.lunar.launcher.home.RssTagItem +import rasel.lunar.launcher.model.ArcaGetter +import rasel.lunar.launcher.model.DCGetter import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.ComicsGetter import rasel.lunar.launcher.utils.ComicsGetter2 @@ -121,9 +123,9 @@ internal class LauncherActivity : AppCompatActivity() { val COMIC_WORK_TAG = "ComicGetter" val COMIC2_WORK_TAG = "ComicGetter2" val REDDIT_WORK_TAG = "RedditGetter" - val shortTimePeriod = 60L + val shortTimePeriod = 15L val longTimePeriod = 60L - val midTimePeriod = 60L + val midTimePeriod = 30L var isOpendFold = false var rssSetTouchCount = 0 @@ -184,14 +186,15 @@ internal class LauncherActivity : AppCompatActivity() { }, 2, TimeUnit.SECONDS) } fun refreshComics() { + refreshComics3() Executors.newSingleThreadScheduledExecutor().schedule({ mWorkManager?.cancelAllWorkByTag(COMIC_WORK_TAG) mWorkManager?.enqueueUniquePeriodicWork( COMIC_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, - PeriodicWorkRequestBuilder(shortTimePeriod, TimeUnit.MINUTES) + PeriodicWorkRequestBuilder(midTimePeriod, TimeUnit.MINUTES) .addTag(COMIC_WORK_TAG) .build()) - refreshComics2() + refreshComics2() }, 2, TimeUnit.SECONDS) } fun refreshComics2() { @@ -199,11 +202,35 @@ internal class LauncherActivity : AppCompatActivity() { mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG) mWorkManager?.enqueueUniquePeriodicWork( COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, - PeriodicWorkRequestBuilder(shortTimePeriod, TimeUnit.MINUTES) + PeriodicWorkRequestBuilder(midTimePeriod, TimeUnit.MINUTES) .addTag(COMIC2_WORK_TAG) .build()) }, 2, TimeUnit.SECONDS) } + fun refreshComics3() { + Executors.newSingleThreadScheduledExecutor().schedule({ + mWorkManager?.cancelAllWorkByTag(DCGetter.TAG) + mWorkManager?.enqueueUniquePeriodicWork( + DCGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, + PeriodicWorkRequestBuilder(midTimePeriod, TimeUnit.MINUTES) + .addTag(DCGetter.TAG) + .build()) + refreshArca() + }, 2, TimeUnit.SECONDS) + } + + fun refreshArca() { + Executors.newSingleThreadScheduledExecutor().schedule({ + mWorkManager?.cancelAllWorkByTag(ArcaGetter.TAG) + mWorkManager?.enqueueUniquePeriodicWork( + ArcaGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, + PeriodicWorkRequestBuilder(midTimePeriod, TimeUnit.MINUTES) + .addTag(ArcaGetter.TAG) + .build()) + + }, 2, TimeUnit.SECONDS) + } + fun workmanager() : WorkManager? { if (mWorkManager == null && lActivity != null) { mWorkManager = WorkManager.getInstance(lActivity!!) @@ -468,10 +495,10 @@ internal class LauncherActivity : AppCompatActivity() { BLog.LOGE("binding.otherCheck before ThreadRun") binding.searcher01.webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { - view?.loadUrl(url!!) - return false - } +// override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { +//// view?.loadUrl(url!!) +// return false +// } override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}") @@ -482,7 +509,7 @@ internal class LauncherActivity : AppCompatActivity() { request: WebResourceRequest?, error: WebResourceError? ) { - super.onReceivedError(view, request, error) +// super.onReceivedError(view, request, error) } override fun onReceivedSslError( view: WebView?, @@ -531,12 +558,15 @@ internal class LauncherActivity : AppCompatActivity() { // .timeout(30000).get()?.apply { // BLog.LOGE("Jsoup.connect(missAv).get() ${this}") // } + try { + this.removeJavascriptInterface("MyJavaScriptInterface") + }catch (e :Exception) {} this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface") setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정 setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결 try { settings.apply { - userAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" +// userAgentString = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정 loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드 useWideViewPort = true // 화면에 맞게 페이지 확대/축소 @@ -549,8 +579,11 @@ internal class LauncherActivity : AppCompatActivity() { allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부 layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정 } - } catch (ignore: NoSuchMethodError) {} - loadUrl(url) // 웹페이지 연결 + } catch (ignore: NoSuchMethodError) { + + }.apply { + loadUrl(url) // 웹페이지 연결 + } } } @@ -614,21 +647,22 @@ internal class LauncherActivity : AppCompatActivity() { // listItem.sortByDescending { it.date } // binding.searcher01.postDelayed({binding.searcher01.loadUrl(prevUrl)}, 5000L) //// } else { - var itemC = 0 - listItem.sortByDescending { it.date } - listItem?.forEach { - if(it.date > beforeDay(Date(),1)) { - if (itemC < 10) { - it.date = it.date + (10000L * itemC) - rssSet.put(it.pageLink, it) - } - itemC = itemC + 1 + var itemC = 0 + listItem.sortByDescending { it.date } + listItem?.forEach { + if(it.date > beforeDay(Date(),1)) { + if (itemC < 10) { + it.date = it.date + (10000L * itemC) + rssSet.put(it.pageLink, it) } + itemC = itemC + 1 } - BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}") - Toast.makeText(this@LauncherActivity, - "Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}] \n set in ${itemC}", Toast.LENGTH_LONG).show() + } + BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}") + Toast.makeText(this@LauncherActivity, + "Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}] \n set in ${itemC}", Toast.LENGTH_LONG).show() // } + binding.searcher01?.post { binding.searcher01.loadData("",null,null) } this@LauncherActivity.callBack?.invoke() } } @@ -659,7 +693,7 @@ internal class LauncherActivity : AppCompatActivity() { @JavascriptInterface fun sendValueFromHtml(result: String) { - + BLog.LOGE("binding.otherCheck start with ${result}") if (lastedFinishedPageUrl.contains(jGuruMain)) { var htmlString = result.replace("\\u003","<") val doc: Document = Jsoup.parse(htmlString) @@ -669,16 +703,19 @@ internal class LauncherActivity : AppCompatActivity() { ) { jGuruMain(doc) } else if (lastedFinishedPageUrl?.contains("/most-watched-rank") == true) { -jGuruToday(doc) + jGuruToday(doc) } else if (lastedFinishedPageUrl?.contains("/tags/") == true) { jGuruTag(doc) } } else if (lastedFinishedPageUrl?.contains("youtube") == true) { // val doc: Document = Jsoup.parse(result) // ytChannel(doc) - } else if (lastedFinishedPageUrl?.contains("missav")==true) { + } else if (lastedFinishedPageUrl?.contains("missjav")==true) { val doc: Document = Jsoup.parse(result) BLog.LOGE("missav >>> ${doc}") + doc.getElementsByTag("li").forEach { miss_li -> + BLog.LOGE("miss_li >>>> ${miss_li}") + } } BLog.LOGE("binding.otherCheck after ThreadRun") } diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt index 6edae365..d7ea0df4 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt @@ -40,6 +40,10 @@ import kotlinx.coroutines.* import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetHost import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetManager import rasel.lunar.launcher.LauncherActivity.Companion.lActivity +import rasel.lunar.launcher.LauncherActivity.Companion.refreshComics +import rasel.lunar.launcher.LauncherActivity.Companion.refreshFeeds +import rasel.lunar.launcher.LauncherActivity.Companion.refreshReddit +import rasel.lunar.launcher.LauncherActivity.Companion.refreshYoutube import rasel.lunar.launcher.R import rasel.lunar.launcher.databinding.FeedsBinding import rasel.lunar.launcher.feeds.rss.RssAdapter @@ -145,8 +149,19 @@ internal class Feeds : Fragment() { DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() when(input.text.toString()) { - "jJguru","vVioPup*383v" -> { - + "ytb" -> { + refreshYoutube() + } + "reddit"->{ + refreshReddit() + } + "fedd"->{ + refreshFeeds() + } + "comic"->{ + refreshComics() + } + "jshow" -> { binding.feedsRss.apply { rss.adapter = mRssAdapter loading.visibility = View.VISIBLE @@ -169,12 +184,20 @@ internal class Feeds : Fragment() { },500L) } } - } } } } - "jJTag"-> { + "jjp" -> { + lActivity?.doWebParseStart("https://projectjav.com") {} + } + "jmiss" -> { + lActivity?.doWebParseStart("https://missjav.com") {} + } + "jreq" -> { + lActivity?.doWebParseStart(jGuruMain) {} + } + "jtag"-> { // lActivity?.doWebPare(TEST_PAG.plus("tags")) { binding.feedsRss.apply { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt index e5d1064d..31e2daaf 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt @@ -70,6 +70,8 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.canAuthenticate import rasel.lunar.launcher.helpers.UniUtils.Companion.expandNotificationPanel import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod import rasel.lunar.launcher.home.weather.WeatherExecutor +import rasel.lunar.launcher.model.ArcaGetter +import rasel.lunar.launcher.model.DCGetter import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.todos.MissedCallsAdapter @@ -183,9 +185,22 @@ internal class LauncherHome : Fragment() { commandHandler.postDelayed(infoUpdate,UPDATE_DELAY) it.clear() } + workmanager()?.getWorkInfosByTagLiveData(FEDDS_WORK_TAG)?.observeForever { + commandHandler.removeCallbacks(infoUpdate) + commandHandler.postDelayed(infoUpdate,UPDATE_DELAY) + it.clear() + } + workmanager()?.getWorkInfosByTagLiveData(ArcaGetter.TAG)?.observeForever { + commandHandler.removeCallbacks(infoUpdate) + commandHandler.postDelayed(infoUpdate,UPDATE_DELAY) + it.clear() + } - - + workmanager()?.getWorkInfosByTagLiveData(DCGetter.TAG)?.observeForever { + commandHandler.removeCallbacks(infoUpdate) + commandHandler.postDelayed(infoUpdate,UPDATE_DELAY) + it.clear() + } nReceiver = NotificationReceiver() val filter = IntentFilter() // filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") diff --git a/app/src/main/kotlin/rasel/lunar/launcher/model/CommunityData.kt b/app/src/main/kotlin/rasel/lunar/launcher/model/CommunityData.kt index c97fa95b..79eb8942 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/model/CommunityData.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/model/CommunityData.kt @@ -4,23 +4,187 @@ import android.annotation.SuppressLint import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters -import com.google.gson.Gson -import org.json.JSONObject import org.jsoup.Jsoup -import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import org.jsoup.select.Elements import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet -import rasel.lunar.launcher.todos.Root import rasel.lunar.launcher.todos.RssDataItem import rasel.lunar.launcher.todos.RssDataType -import rasel.lunar.launcher.todos.RssFeedsParser import rasel.lunar.launcher.utils.BLog -import rasel.lunar.launcher.utils.RssList -import rasel.lunar.launcher.utils.RssList.feedJsons +import rasel.lunar.launcher.utils.USAGT +import rasel.lunar.launcher.utils.afterDay import rasel.lunar.launcher.utils.beforeDay import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date +import java.util.TimeZone +class ArcaGetter : Worker { + companion object { + val TAG = "DCGetter" + } + constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) { + + } + override fun doWork(): Result { + var tempArray = arrayListOf() + + try { + val urls = arrayListOf( + "https://arca.live/b/singbung?mode=best", + "https://arca.live/b/headline", + "https://arca.live/b/live", + "https://arca.live/b/namuhotnow", + "https://arca.live/b/society", + "https://arca.live/b/replay", + "https://arca.live/b/breaking" + ) + urls.forEach { + Jsoup.connect(it) + .userAgent(USAGT) + .get().let { arca -> +// BLog.LOGE("url >> ${it} >> ${arca}") + arca.getElementsByClass("vrow hybrid").forEach { araca_li -> + if (araca_li.html().contains("title ") == true) { + parseArcaLi(araca_li).apply { + tempArray.addAll(this) + } + } + } + } + } +// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj -> +// BLog.LOGE("projectj >>>>> ${projectj}") +// } + } catch (e:Exception){e.printStackTrace()} + + return tempArray.forEach { + rssSet.put(it.originPage(),it) + }.run { + Result.success() + } + } + + private fun parseArcaLi(aracaLi: Element) : ArrayList { + var tempArray = arrayListOf() +// BLog.LOGE("aracaLi >>> ${aracaLi}") + var title = aracaLi.getElementsByClass("title hybrid-title").getT() + var desc = aracaLi.getElementsByClass("badge").getT() + desc.plus(aracaLi.getElementsByClass("user-info ").getT()) + var dateTime = aracaLi.getElementsByTag("time").attr("datetime") + var tumbnail = aracaLi.getElementsByTag("img").attr("src") + var link = "https://arca.live".plus(if(aracaLi.getElementsByClass("title hybrid-title").size > 0) aracaLi.getElementsByClass("title hybrid-title").get(0).attr("href") else if(aracaLi.getElementsByTag("a").size > 0) aracaLi.getElementsByTag("a").get(0).attr("href") else "") + if (title.length > 0 && link.length > 20) { + Arca().apply { + this.link = link + this.title = title + if (tumbnail.length > 0) { + this.thumbnail = "https:".plus(tumbnail) +// +// BLog.LOGE("Arca thumbnail >>> ${thumbnail}") + } + this.desc = desc + this.dateTiem = dateTime + }.apply { +// BLog.LOGE("parseArcaLi >>>> ${this}") + if(this.pubDate() > beforeDay(Date(),3)) { + tempArray.add(this) + } + } + } + return tempArray + } + + fun Elements.getT() = if (size > 0) get(0).text() else "" +} +class Arca : RssDataItem { + var link : String? = null + var title : String? = null + var thumbnail : String? = null + var desc : String? = null + var dateTiem : String? = null +var updateDateTime : Long = 0L + override fun title(): String { + return title ?: "" + } + + override fun thumbnailUrl(): String { + return thumbnail ?: "" + } + + override fun originPage(): String { + return link ?: "" + } + + override fun description(): String { + return desc ?: "" + } + val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd") + override fun pubDate(): Long { + var date = Date() + var dateTime = date.time + var before = 0 + if (updateDateTime == 0L) { + try { + BLog.LOGE("this.dateTiem >>> ${this.dateTiem}") + val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + sdf.timeZone = TimeZone.getTimeZone("GMT") + updateDateTime = sdf.parse(this.dateTiem!!).time + BLog.LOGE("updateDateTime >>>> ${dateFormat.format(Date(updateDateTime))}" ) +// var targetDate = this.dateTiem ?: "" +// if (targetDate?.length ?: 0 > 1) { +// var dateDesc = targetDate +// var isBefore = dateDesc.contains("전") +// val dayString = dateDesc.replace("[^0-9]".toRegex(), "") +// before = dayString.toInt() +// if (dateDesc.contains("년")) { +// before = 365 * before +// dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before) +// } else if (dateDesc.contains("월")) { +// before = 30 * before +// dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before) +// } else if (dateDesc.contains("주")) { +// before = 7 * before +// dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before) +// } else if (dateDesc.contains("일")) { +// dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before) +// } else if (dateDesc.contains("시간")) { +// dateTime = +// if (isBefore) dateTime.minus(before.times(1000L * 60L * 60L)) else dateTime.plus( +// before.times(1000L * 60L * 60L) +// ) +// } else if (dateDesc.contains("분")) { +// dateTime = +// if (isBefore) dateTime.minus(before.times(1000L * 60L)) else dateTime.plus( +// before.times(1000L * 60L) +// ) +// } +// else if (dateDesc.contains("초")) { +// dateTime = +// if (isBefore) dateTime.minus(before.times(1000L)) else dateTime.plus( +// before.times(1000L) +// ) +// } +// } + + } catch (e: Exception) { + + } finally { +// updateDateTime = dateTime + } + } else { + dateTime = updateDateTime + } + + return dateTime + } + + override fun category(): RssDataType { + return RssDataType.Arca + } +} + class DCGetter : Worker { companion object { val TAG = "DCGetter" @@ -55,11 +219,11 @@ class DCGetter : Worker { .get(0).text() else "" link = link.replace("&","&") thumbnail = thumbnail.replace("&","&") - BLog.LOGE("DC_LI >>>> link >>>> ${link}") - BLog.LOGE("DC_LI >>>> title >>>> ${title}") - BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}") - BLog.LOGE("DC_LI >>>> desc >>>> ${desc}") - BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}") +// BLog.LOGE("DC_LI >>>> link >>>> ${link}") +// BLog.LOGE("DC_LI >>>> title >>>> ${title}") +// BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}") +// BLog.LOGE("DC_LI >>>> desc >>>> ${desc}") +// BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}") if (title.length > 0 && link.length > 0) { DcInside().apply { this.link = link @@ -82,7 +246,9 @@ class DCGetter : Worker { try { val testUrl2 = "https://www.dcinside.com/" - Jsoup.connect(testUrl2).userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15").get().let { dc -> + Jsoup.connect(testUrl2) + .userAgent(USAGT) + .get().let { dc -> // BLog.LOGE("test ${testUrl2} >> ${this}") dc.getElementsByTag("li").forEach { dc_li -> if (dc_li.html().contains("main_log") == true) { @@ -92,6 +258,8 @@ class DCGetter : Worker { } } } + + } catch (e:Exception){e.printStackTrace()} return tempArray.forEach { rssSet.put(it.originPage(),it) @@ -103,51 +271,7 @@ class DCGetter : Worker { -fun parseDcLi(dc_li : org.jsoup.nodes.Element) : ArrayList{ - var temp = arrayListOf() - if (dc_li.html().contains("
    ") && dc_li.html().contains("con_list img")) { - dc_li.child(0).getElementsByTag("li").forEach { - parseDcLi(it) - } - } else { - var link = if (dc_li.getElementsByTag("a").size > 0) dc_li.getElementsByTag("a").get(0) - .attr("href") else "" - var title = - if (dc_li.getElementsByClass("box besttxt").size > 0) dc_li.getElementsByClass("box besttxt") - .get(0) - .text() else if (dc_li.getElementsByClass("tit").size > 0) dc_li.getElementsByClass( - "tit" - ).get(0).text() else "" - var thumbnail = - if (dc_li.getElementsByTag("img").size > 0) dc_li.getElementsByTag("img").get(0) - .attr("src") else "" - var desc = - if (dc_li.getElementsByClass("box best_info").size > 0) dc_li.getElementsByClass("box best_info") - .get(0).text() else "" - var dateTiem = - if (dc_li.getElementsByClass("time").size > 0) dc_li.getElementsByClass("time") - .get(0).text() else "" - link = link.replace("&","&") - thumbnail = thumbnail.replace("&","&") - BLog.LOGE("DC_LI >>>> link >>>> ${link}") - BLog.LOGE("DC_LI >>>> title >>>> ${title}") - BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}") - BLog.LOGE("DC_LI >>>> desc >>>> ${desc}") - BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}") - if (title.length > 0 && link.length > 0) { - DcInside().apply { - this.link = link - this.title = title - this.thumbnail = thumbnail - this.desc = desc - this.dateTiem = dateTiem - }.apply { - temp.add(this) - } - } - } - return temp -} + class DcInside : RssDataItem { var link : String? = null @@ -156,8 +280,11 @@ class DcInside : RssDataItem { var desc : String? = null var dateTiem : String? = null - val dateF = SimpleDateFormat("MM:dd") - val timeF = SimpleDateFormat("hh:mm") + var dateTiemL : Long = 0L + + + val dateF = SimpleDateFormat("MM-dd") + val timeF = SimpleDateFormat("HH:mm") override fun title(): String { return title ?:"" } @@ -175,56 +302,34 @@ class DcInside : RssDataItem { } override fun pubDate(): Long { - return if(dateTiem?.contains(":") == true) timeF.parse(dateTiem).time else dateF.parse(dateTiem).time + if (dateTiemL < 1L) { + if (dateTiem?.length ?: 0 < 1) return 0L + return if (dateTiem?.contains(":") == true) { + val cal: Calendar = Calendar.getInstance() + cal.setTime(Date()) + cal.set(Calendar.HOUR_OF_DAY, dateTiem!!.split(":")[0].toInt()- 1) + cal.set(Calendar.MINUTE, dateTiem!!.split(":")[1].toInt()) +// cal.set(Calendar.MINUTE, dateTiem!!.split(":")[1].toI nt()) + dateTiemL = cal.timeInMillis + dateTiemL + } else if (dateTiem?.contains("-") == true) { + val cal: Calendar = Calendar.getInstance() + cal.setTime(Date()) + cal.set(Calendar.MONTH, dateTiem!!.split("-")[0].toInt() - 1) + cal.set(Calendar.DAY_OF_MONTH, dateTiem!!.split("-")[1].toInt()) + cal.add(Calendar.DAY_OF_MONTH, -1) + dateTiemL = cal.timeInMillis + dateTiemL + } else { + 0L + } + } else { + return dateTiemL + } } override fun category(): RssDataType { - return RssDataType.NewsFeed + return RssDataType.DcInside } - fun parseDcLi(dc_li : org.jsoup.nodes.Element) : ArrayList{ - var temp = arrayListOf() - if (dc_li.html().contains("
      ") && dc_li.html().contains("con_list img")) { - dc_li.child(0).getElementsByTag("li").forEach { - parseDcLi(it) - } - } else { - var link = if (dc_li.getElementsByTag("a").size > 0) dc_li.getElementsByTag("a").get(0) - .attr("href") else "" - var title = - if (dc_li.getElementsByClass("box besttxt").size > 0) dc_li.getElementsByClass("box besttxt") - .get(0) - .text() else if (dc_li.getElementsByClass("tit").size > 0) dc_li.getElementsByClass( - "tit" - ).get(0).text() else "" - var thumbnail = - if (dc_li.getElementsByTag("img").size > 0) dc_li.getElementsByTag("img").get(0) - .attr("src") else "" - var desc = - if (dc_li.getElementsByClass("box best_info").size > 0) dc_li.getElementsByClass("box best_info") - .get(0).text() else "" - var dateTiem = - if (dc_li.getElementsByClass("time").size > 0) dc_li.getElementsByClass("time") - .get(0).text() else "" - link = link.replace("&","&") - thumbnail = thumbnail.replace("&","&") - BLog.LOGE("DC_LI >>>> link >>>> ${link}") - BLog.LOGE("DC_LI >>>> title >>>> ${title}") - BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}") - BLog.LOGE("DC_LI >>>> desc >>>> ${desc}") - BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}") - if (title.length > 0 && link.length > 0) { - DcInside().apply { - this.link = link - this.title = title - this.thumbnail = thumbnail - this.desc = desc - this.dateTiem = dateTiem - }.apply { - temp.add(this) - } - } - } - return temp - } } \ No newline at end of file diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssDataItem.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssDataItem.kt index 9118f3bc..6dc35dcb 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssDataItem.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssDataItem.kt @@ -9,6 +9,8 @@ enum class RssDataType { REDDIT, Dotax, FmKorae, + DcInside, + Arca, } interface RssDataItem { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt index 0aa837e8..9b5121d0 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt @@ -120,19 +120,35 @@ internal class RssItemAdapter ( holder.view.circlePreview.setImageResource(R.drawable.reddit) holder.view.circlePreview.visibility = View.VISIBLE holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,120) - } else if( todo.category().equals(RssDataType.FmKorae)) { + } else if( todo.category().equals(RssDataType.FmKorae) ) { holder.view.circlePreview.setImageResource(R.drawable.fmk) holder.view.circlePreview.visibility = View.VISIBLE holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,120) + } else if(todo.category().equals(RssDataType.DcInside)) { + holder.view.circlePreview.setImageResource(R.drawable.dcinside) + holder.view.circlePreview.visibility = View.VISIBLE + holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,120) + } else if(todo.category().equals(RssDataType.Arca)) { + holder.view.circlePreview.setImageResource(R.drawable.arca) + holder.view.circlePreview.visibility = View.VISIBLE + holder.view.circlePreview.layoutParams = ConstraintLayout.LayoutParams(120,120) } + if(todo.thumbnailUrl()?.length ?: 0 > 6) { Picasso.get().load(todo.thumbnailUrl().toUri()).into(holder.view.circlePreview) } holder.view.desc.text = todo.description().plus(" ").plus(todo.category().name) holder.view.desc.visibility = View.VISIBLE - holder.view.date.visibility = View.VISIBLE + holder.view.date.setOnClickListener { + if (holder.view.desc.visibility == View.GONE) { + holder.view.circlePreview.visibility = View.VISIBLE + holder.view.circlePreview.postDelayed({ + holder.view.circlePreview.visibility = View.GONE + }, 1000L) + } + } // holder.view.date.setOnTouchListener { v,e -> // if (holder.view.date.equals(v)) { // when(e.action) { @@ -144,12 +160,7 @@ internal class RssItemAdapter ( // false // } - holder.view.date.setOnClickListener { - holder.view.circlePreview.visibility = View.VISIBLE - holder.view.circlePreview.postDelayed({ - holder.view.circlePreview.visibility = View.GONE - },1000L) - } + holder.view.root.setOnLongClickListener { if ( todo.category().equals(RssDataType.GURU)) { openOpera(todo.originPage()) @@ -157,7 +168,7 @@ internal class RssItemAdapter ( openReddit(todo.originPage()) } else if( todo.category().equals(RssDataType.Dotax)) { openDotax(todo.originPage()) - }else if( todo.category().equals(RssDataType.FmKorae)) { + }else if(todo.category().equals(RssDataType.FmKorae)|| todo.category().equals(RssDataType.DcInside)|| todo.category().equals(RssDataType.Arca)) { openNews(todo.originPage()) } true diff --git a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt index 13ba6c70..bf2c650f 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt @@ -134,6 +134,8 @@ class MissedCallGetter : Worker { } +val USAGT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15" + fun before30Min(date: Date): Long { val cal: Calendar = Calendar.getInstance() cal.setTime(date) @@ -142,7 +144,7 @@ fun before30Min(date: Date): Long { } fun beforeDay(date: Date?, day: Int): Long { - val cal: Calendar = Calendar.getInstance() + val cal: Calendar = Calendar.getInstance() cal.setTime(date) cal.add(Calendar.DAY_OF_YEAR, Math.abs(day) * -1) return cal.timeInMillis @@ -576,7 +578,7 @@ class YoutubeGetter : Worker { rssUrls.addAll(RssList.youtubeUrls) val temp = arrayListOf() for (url in rssUrls) { - ytChannel(Jsoup.connect(url).get()) + ytChannel(Jsoup.connect(url).userAgent(USAGT).get()) } return temp.forEach { synchronized(rssSet){ @@ -592,6 +594,8 @@ class YoutubeGetter : Worker { if(it.html().contains("var ytInitialData", false)) {/**/ var ytInitialData = it.html().split("var ytInitialData = ")[1].split("")[0].toString() var tempJSONObject : JSONObject? = null + + JSONObject(ytInitialData).apply{ tempJSONObject = this val root = Gson().fromJson(tempJSONObject.toString(), Root::class.java) @@ -646,10 +650,10 @@ class ComicsGetter : Worker { val now = Date() try { val fmkoreaUrls = arrayListOf("https://www.fmkorea.com", -// "https://www.fmkorea.com/index.php?mid=best&page=2", -// "https://www.fmkorea.com/index.php?mid=best&page=3" + "https://www.fmkorea.com/index.php?mid=best&page=2", + "https://www.fmkorea.com/index.php?mid=best&page=3" ) - fmkoreaUrls.forEach { Jsoup.connect(it).get().let { fmkorea -> + fmkoreaUrls.forEach { Jsoup.connect(it).userAgent(USAGT).get().let { fmkorea -> // BLog.LOGE("fmkorea >>> ${fmkorea.title()}") fmkorea.getElementsByTag("li").forEach { fmkorea_li -> if (fmkorea_li.getElementsByClass("title").text().length > 0 && fmkorea_li.getElementsByTag("a").size > 0 &&fmkorea_li.getElementsByTag("a").get(0).attr("href").length > 0) { @@ -697,24 +701,25 @@ class ComicsGetter2 : Worker { val now = Date() try { val dotaxUrls = arrayListOf("https://m.cafe.daum.net/dotax", -// "https://m.cafe.daum.net/dotax/_rec?page=2", -// "https://m.cafe.daum.net/dotax/_rec?page=3" + "https://m.cafe.daum.net/dotax/_rec?page=2", + "https://m.cafe.daum.net/dotax/_rec?page=3" ) dotaxUrls?.forEach { - Jsoup.connect(it)?.get()?.let { dotax -> - BLog.LOGE("dotax_li >>> ${dotax.title()}") + Jsoup.connect(it).userAgent(USAGT).get()?.let { dotax -> +// BLog.LOGE("dotax_li >>> ${dotax.title()}") dotax.getElementsByTag("li").forEach { dotax_li -> if (dotax_li.getElementsByTag("a").size > 0 && dotax_li.getElementsByClass("board_name") .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("sr_only").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) { + BLog.LOGE("dotax_li >>> ${dotax_li}") Dotax(pageLink, desc, dateTime, title, thumbnail).apply { - BLog.LOGE("dotax_li >>> ${Gson().toJson(this)}") +// BLog.LOGE("dotax_li >>> ${Gson().toJson(this)}") if(this.pubDate() > before30Min(now)) { temp.add(this) } diff --git a/app/src/main/res/drawable/arca.xml b/app/src/main/res/drawable/arca.xml new file mode 100644 index 00000000..f13a3b87 --- /dev/null +++ b/app/src/main/res/drawable/arca.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/app/src/main/res/drawable/dcinside.png b/app/src/main/res/drawable/dcinside.png new file mode 100644 index 0000000000000000000000000000000000000000..8d855b7abfe31e50c0f9a4e43188dc244c498d21 GIT binary patch literal 13512 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 literal 0 HcmV?d00001