mirror of
https://github.com/Death916/deathclock.git
synced 2026-04-10 03:04:40 -07:00
added news.py weather.py
This commit is contained in:
parent
962637383c
commit
1272853df6
10 changed files with 319 additions and 30 deletions
BIN
deathclock/__pycache__/news.cpython-311.pyc
Normal file
BIN
deathclock/__pycache__/news.cpython-311.pyc
Normal file
Binary file not shown.
BIN
deathclock/__pycache__/weather.cpython-311.pyc
Normal file
BIN
deathclock/__pycache__/weather.cpython-311.pyc
Normal file
Binary file not shown.
|
|
@ -4,15 +4,13 @@ import time
|
|||
import sys
|
||||
from PySide6.QtGui import QGuiApplication
|
||||
from PySide6.QtQml import QQmlApplicationEngine
|
||||
from PySide6.QtCore import QTimer, QObject, Signal, Slot
|
||||
from PySide6.QtCore import QTimer, QObject, Signal, Slot, Property
|
||||
from time import strftime, localtime
|
||||
import requests
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.service import Service
|
||||
|
||||
|
||||
|
||||
|
||||
import os
|
||||
import news
|
||||
|
||||
|
||||
class clock():
|
||||
|
|
@ -23,7 +21,7 @@ class clock():
|
|||
|
||||
|
||||
return curr_time
|
||||
# TODO: ADD date
|
||||
|
||||
|
||||
def time_and_date():
|
||||
print(time.asctime())
|
||||
|
|
@ -36,32 +34,60 @@ class clock():
|
|||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class weather():
|
||||
|
||||
#save radar map from https://radar.weather.gov/?settings=v1_eyJhZ2VuZGEiOnsiaWQiOiJ3ZWF0aGVyIiwiY2VudGVyIjpbLTExOS44NzYsMzcuNjcxXSwibG9jYXRpb24iOlstMTIwLjY2NiwzNy4wNDRdLCJ6b29tIjo3LjU0ODYxNTg5NDY1NTIyN30sImFuaW1hdGluZyI6ZmFsc2UsImJhc2UiOiJzdGFuZGFyZCIsImFydGNjIjpmYWxzZSwiY291bnR5IjpmYWxzZSwiY3dhIjpmYWxzZSwicmZjIjpmYWxzZSwic3RhdGUiOmZhbHNlLCJtZW51Ijp0cnVlLCJzaG9ydEZ1c2VkT25seSI6ZmFsc2UsIm9wYWNpdHkiOnsiYWxlcnRzIjowLjgsImxvY2FsIjowLjYsImxvY2FsU3RhdGlvbnMiOjAuOCwibmF0aW9uYWwiOjAuNn19
|
||||
@staticmethod
|
||||
def __init__(self, image_provider):
|
||||
self.image_provider = image_provider
|
||||
#save radar map from google weather
|
||||
|
||||
|
||||
def download_sacramento_weather_map():
|
||||
def download_sacramento_weather_map(self):
|
||||
url = "https://www.google.com/search?q=weather&hl=en-GB"
|
||||
service = Service(executable_path='/home/death916/code/python/deathclock/deathclock/chromedriver')
|
||||
options = webdriver.ChromeOptions()
|
||||
#options.add_argument('--headless')
|
||||
driver = webdriver.Chrome(service=service, options=options)
|
||||
options.add_argument('--force-dark-mode')
|
||||
driver.get(url)
|
||||
map_element = driver.find_element('id', 'wob_wc')
|
||||
map_element.screenshot('sacramento_weather_map.png')
|
||||
image = map_element.screenshot('sacramento_weather_map.png')
|
||||
print("screen shot taken")
|
||||
self.image_provider.source = 'sacramento_weather_map.png'
|
||||
|
||||
driver.quit()
|
||||
return image
|
||||
|
||||
def cur_weather():
|
||||
# scrape weather from web
|
||||
|
||||
|
||||
pass
|
||||
def delete_old_screen_shot(self):
|
||||
# delete old screen shot from downloads weather map
|
||||
file = '/home/death916/code/python/deathclock/sacramento_weather_map.png'
|
||||
os.remove(file)
|
||||
print("old screen shot deleted")
|
||||
|
||||
|
||||
class WeatherImageProvider(QObject):
|
||||
"""weather image provider class to provide image to qml when timer is up"""
|
||||
sourceChanged = Signal()
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._source = ""
|
||||
|
||||
@Property(str, notify=sourceChanged)
|
||||
def source(self):
|
||||
return self._source
|
||||
|
||||
@source.setter
|
||||
def source(self, value):
|
||||
if self._source != value:
|
||||
self._source = value
|
||||
self.sourceChanged.emit()
|
||||
|
||||
|
||||
"""
|
||||
class gui():
|
||||
def handleTouchAreaPressed(self, signal):
|
||||
|
|
@ -73,23 +99,49 @@ class gui():
|
|||
"""
|
||||
def main():
|
||||
#gui_obj = gui()
|
||||
weather_obj = weather()
|
||||
#weather_obj.download_sacramento_weather_map()
|
||||
|
||||
app = QGuiApplication(sys.argv)
|
||||
global engine
|
||||
engine = QQmlApplicationEngine()
|
||||
engine.quit.connect(app.quit)
|
||||
|
||||
engine.load( 'main.qml')
|
||||
# create instance of weather image provider
|
||||
image_provider = WeatherImageProvider()
|
||||
|
||||
# set context property for weather image provider
|
||||
context = engine.rootContext()
|
||||
context.setContextProperty("imageProvider", image_provider)
|
||||
|
||||
# create instance of weather class
|
||||
weather_obj = weather(image_provider)
|
||||
weather_obj.download_sacramento_weather_map()
|
||||
|
||||
# create instance of clock class
|
||||
timeupdate = clock()
|
||||
timer = QTimer()
|
||||
weatherTimer = QTimer()
|
||||
weatherTimer.start()
|
||||
# set timer for weather map
|
||||
weatherTimer.setInterval(600000) # 10 minutes
|
||||
weatherTimer.timeout.connect(weather_obj.download_sacramento_weather_map)
|
||||
timer.setInterval(100) # msecs 100 = 1/10th sec
|
||||
timer.timeout.connect(timeupdate.update_time)
|
||||
|
||||
|
||||
weather_obj.delete_old_screen_shot()
|
||||
|
||||
timer.start()
|
||||
news_obj = news.news()
|
||||
news_ticker = news_obj.get_news()
|
||||
#print(news_obj._news_dict)
|
||||
print(news_ticker)
|
||||
news_context = engine.rootContext()
|
||||
news_context.setContextProperty("news", str(news_ticker))
|
||||
#start timer for news
|
||||
news_timer = QTimer()
|
||||
news_timer.timeout.connect(news_obj.get_news)
|
||||
news_timer.setInterval(600000) # 10 minutes
|
||||
|
||||
|
||||
news_timer.start()
|
||||
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
|
@ -98,3 +150,7 @@ def main():
|
|||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
#TODO: add weather to qml
|
||||
#TODO: move weather to own file
|
||||
|
||||
60
deathclock/news.py
Normal file
60
deathclock/news.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#news.py
|
||||
# News module for DeathClock
|
||||
|
||||
import feedparser
|
||||
|
||||
class news():
|
||||
|
||||
def __init__(self):
|
||||
self._news = ""
|
||||
self._news_list = []
|
||||
self._news_list_index = 0
|
||||
self._news_list_length = 0
|
||||
self._news_list_index_max = 0
|
||||
self._news_dict = {}
|
||||
self._news_dict_length = 0
|
||||
|
||||
def get_news(self):
|
||||
feeds = []
|
||||
#load rss feed list from file
|
||||
with open("feeds.txt", "r") as f:
|
||||
for line in f:
|
||||
feeds.append(line.strip())
|
||||
#print source and headline from last 10 entries
|
||||
for feed in feeds:
|
||||
d = feedparser.parse(feed)
|
||||
for post in d.entries:
|
||||
if self._news_list_length == 10:
|
||||
self._news_list.pop(0)
|
||||
self._news_list.append(post.title)
|
||||
|
||||
self._news_list.append(post.title)
|
||||
self._news_list_length += 1
|
||||
# only store last 20 entries in dict
|
||||
if self._news_dict_length == 20:
|
||||
self._news_dict = {}
|
||||
self._news_dict[post.title] = {
|
||||
'source': d.feed.title,
|
||||
'publish_date': post.published,
|
||||
'headline': post.title,
|
||||
'summary': post.summary
|
||||
}
|
||||
self._news_dict_length += 1
|
||||
#for i in self._news_dict:
|
||||
# print(self._news_dict[i])
|
||||
return self._news_dict
|
||||
|
||||
|
||||
def main():
|
||||
news_obj = news()
|
||||
news_obj.get_news()
|
||||
print(news_obj._news_dict)
|
||||
return news_obj._news_dict
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
#TODO hash the news_dict and compare to previous hash to see if news has changed
|
||||
#TODO add news to qml
|
||||
#TODO limit entries from each source to some number mayb 3ish
|
||||
68
deathclock/weather.py
Normal file
68
deathclock/weather.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.service import Service
|
||||
from PySide6.QtCore import QObject, Signal, Property
|
||||
import os
|
||||
from PySide6.QtQuick import QQuickImageProvider
|
||||
from PySide6.QtGui import QImage, QPixmap
|
||||
|
||||
class weather():
|
||||
|
||||
|
||||
|
||||
def download_sacramento_weather_map(self):
|
||||
url = "https://www.google.com/search?q=weather&hl=en-GB"
|
||||
service = Service(executable_path='/home/death916/code/python/deathclock/deathclock/chromedriver')
|
||||
options = webdriver.ChromeOptions()
|
||||
#options.add_argument('--headless')
|
||||
driver = webdriver.Chrome(service=service, options=options)
|
||||
options.add_argument('--force-dark-mode')
|
||||
driver.get(url)
|
||||
map_element = driver.find_element('id', 'wob_wc')
|
||||
image = map_element.screenshot('sacramento_weather_map.png')
|
||||
print("screen shot taken")
|
||||
self.image_provider.source = 'sacramento_weather_map.png'
|
||||
|
||||
driver.quit()
|
||||
return image
|
||||
|
||||
def cur_weather():
|
||||
# scrape weather from web
|
||||
|
||||
|
||||
pass
|
||||
def delete_old_screen_shot(self):
|
||||
# delete old screen shot from downloads weather map
|
||||
|
||||
file = '/home/death916/code/python/deathclock/sacramento_weather_map.png'
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
print("old screen shot deleted")
|
||||
|
||||
|
||||
class WeatherImageProvider(QQuickImageProvider):
|
||||
"""weather image provider class to provide image to qml when timer is up"""
|
||||
sourceChanged = Signal()
|
||||
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(QQuickImageProvider.Image)
|
||||
self._source = ""
|
||||
|
||||
@Property(str, notify=sourceChanged)
|
||||
def source(self):
|
||||
return self._source
|
||||
|
||||
@source.setter
|
||||
def source(self, value):
|
||||
if self._source != value:
|
||||
self._source = value
|
||||
self.sourceChanged.emit()
|
||||
|
||||
def requestImage(self, id, size):
|
||||
image = QImage("/home/death916/code/python/deathclock/sacramento_weather_map.png") # Load the image from a file
|
||||
size = image.size() # Get the size of the image
|
||||
return image, size
|
||||
|
||||
|
||||
|
||||
|
||||
4
feeds.txt
Normal file
4
feeds.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
http://feeds.bbci.co.uk/news/rss.xml
|
||||
http://feeds.feedburner.com/hiphopdx/news
|
||||
https://news.google.com/news?hl=en&gl=us&q=sacramento+bee&um=1&ie=UTF-8&output=rss
|
||||
https://morss.it/https://feeds.npr.org/1001/rss.xml
|
||||
63
main.qml
63
main.qml
|
|
@ -21,6 +21,7 @@ ApplicationWindow {
|
|||
|
||||
// Left touch area
|
||||
MouseArea {
|
||||
id : scoreArea
|
||||
anchors.left: parent.left
|
||||
width: 70
|
||||
height: parent.height // Full height
|
||||
|
|
@ -47,7 +48,7 @@ ApplicationWindow {
|
|||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
width: 70
|
||||
height: parent.height
|
||||
height: parent.height - newsArea.height // Full height
|
||||
color: Qt.rgba(0, 0, 1, 0.3) // Slightly opaque blue
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +81,8 @@ ApplicationWindow {
|
|||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: "/home/death916/code/python/deathclock/sacramento_weather_map.png"
|
||||
fillMode: Image.fill
|
||||
source: imageProvider.source
|
||||
//fillMode: Image.fill // Fill the entire area // Uncomment this line to fill the entire area
|
||||
}
|
||||
|
||||
// Additional weather content can be added here
|
||||
|
|
@ -105,6 +106,62 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
//bottom news scroll area
|
||||
Rectangle {
|
||||
id: newsArea
|
||||
width: parent.width
|
||||
height: parent.height * 1 / 6
|
||||
color: Qt.rgba(0, 0, 1, 0.5) // Semi-transparent blue
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
|
||||
// Text "News" at the top
|
||||
Text {
|
||||
id: newsHeader
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: 30
|
||||
text: "News"
|
||||
font.pixelSize: 20
|
||||
color: "white"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
|
||||
id: newsText
|
||||
text: news
|
||||
font.pixelSize: 15
|
||||
color: "white"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
x: parent.width
|
||||
anchors.top: newsHeader.bottom
|
||||
|
||||
SequentialAnimation on x {
|
||||
loops: Animation.Infinite
|
||||
running: true
|
||||
|
||||
PropertyAnimation {
|
||||
from: parent.width
|
||||
to: -newsText.width
|
||||
duration: 2000000 // 10 seconds (in milliseconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: newsTimer
|
||||
interval: 600005// 10 minutes
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
newsText.text = news // Update the news text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ... Additional UI elements as needed ...
|
||||
}
|
||||
}
|
||||
|
|
|
|||
47
poetry.lock
generated
47
poetry.lock
generated
|
|
@ -219,6 +219,36 @@ files = [
|
|||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.0"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
|
||||
{file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "feedparser"
|
||||
version = "6.0.11"
|
||||
description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "feedparser-6.0.11-py3-none-any.whl", hash = "sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45"},
|
||||
{file = "feedparser-6.0.11.tar.gz", hash = "sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
sgmllib3k = "*"
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
|
|
@ -454,6 +484,17 @@ trio = ">=0.17,<1.0"
|
|||
trio-websocket = ">=0.9,<1.0"
|
||||
urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
|
||||
|
||||
[[package]]
|
||||
name = "sgmllib3k"
|
||||
version = "1.0.0"
|
||||
description = "Py3k port of sgmllib."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shiboken6"
|
||||
version = "6.6.1"
|
||||
|
|
@ -507,6 +548,7 @@ files = [
|
|||
[package.dependencies]
|
||||
attrs = ">=20.1.0"
|
||||
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
|
||||
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
|
||||
idna = "*"
|
||||
outcome = "*"
|
||||
sniffio = ">=1.3.0"
|
||||
|
|
@ -525,6 +567,7 @@ files = [
|
|||
]
|
||||
|
||||
[package.dependencies]
|
||||
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
|
||||
trio = ">=0.11"
|
||||
wsproto = ">=0.14"
|
||||
|
||||
|
|
@ -577,5 +620,5 @@ h11 = ">=0.9.0,<1"
|
|||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">3.11,<3.13"
|
||||
content-hash = "069d9a60c7b307e1b8ebd1c38d81345dbbe3bfb1988ff2b5cdbfe91cd58b13f0"
|
||||
python-versions = ">=3.8,<3.11.4"
|
||||
content-hash = "e49deef9d89870657d29a30af42917cb501aba95518998bf640b4b065c0a1406"
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ description = ""
|
|||
authors = ["Death916 <tavn1992@gmail.com>"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">3.11,<3.13"
|
||||
python = ">=3.8,<3.11.4"
|
||||
pyside6 = "^6.6.1"
|
||||
requests = "^2.31.0"
|
||||
selenium = "^4.16.0"
|
||||
feedparser = "^6.0.11"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^5.2"
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
Loading…
Add table
Add a link
Reference in a new issue