-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from caarmen/modularize-code
Modularize code
- Loading branch information
Showing
13 changed files
with
273 additions
and
208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.env* | ||
.resources | ||
.vscode/ | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
for project in . | ||
for project in wspp | ||
do | ||
black $project | ||
ruff check $project | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import io | ||
from pathlib import Path | ||
|
||
from PIL import Image | ||
|
||
_resources_dir = Path(__file__).parent.parent / "resources" | ||
|
||
|
||
def create_profile_photo(background: Path, foreground: Path) -> io.BytesIO: | ||
""" | ||
:return: the binary data of an image containing the given background image, with | ||
the provided foreground image on top. | ||
""" | ||
background_image = Image.open(background) | ||
foreground_image = Image.open(foreground).convert("RGBA") | ||
new_image = Image.new( | ||
mode="RGB", | ||
size=background_image.size, | ||
) | ||
new_image.paste(background_image) | ||
new_image.paste(foreground_image, (0, 0), foreground_image) | ||
bio = io.BytesIO() | ||
new_image.save(bio, format="JPEG") | ||
bio.seek(0) | ||
return bio | ||
|
||
|
||
def get_image_file(prefix: str) -> Path: | ||
""" | ||
:return: the background image file starting with the given prefix | ||
""" | ||
return next(_resources_dir.glob(f"{prefix}*")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
""" | ||
Script which periodically: | ||
* fetches the weather condition of a specified location, | ||
* selects a background image based on the weather condition, | ||
* creates a new profile photo using this background image and a provided profile photo, | ||
* and updates the user's profile photo in Slack with this new profile photo. | ||
""" | ||
|
||
import dataclasses | ||
import logging | ||
from pathlib import Path | ||
from threading import Event | ||
from typing import Optional | ||
|
||
from pydantic import BaseSettings, DirectoryPath, PositiveInt | ||
|
||
from wspp import image, schedule, slack, weatherstack | ||
from wspp.sunrisesunset import SunriseSunset | ||
|
||
|
||
class Settings(BaseSettings): | ||
weatherstack: weatherstack.WeatherstackSettings | ||
slack: slack.SlackSettings | ||
latitude: float | ||
longitude: float | ||
profile_photos_dir: DirectoryPath = Path(__file__).parent.parent / "profile_photos" | ||
polling_interval_s: PositiveInt = 7200 | ||
|
||
class Config: | ||
env_file = ".env" | ||
env_nested_delimiter = "__" | ||
|
||
|
||
settings = Settings() | ||
|
||
|
||
@dataclasses.dataclass | ||
class Cache: | ||
last_weather_code: Optional[int] = None | ||
|
||
|
||
cache = Cache() | ||
|
||
|
||
def setup_logging(): | ||
logging.basicConfig( | ||
level=logging.INFO, | ||
format="%(asctime)s %(levelname)s %(message)s", | ||
) | ||
|
||
|
||
def update_profile_photo_from_weather(): | ||
""" | ||
Update the profile photo on slack based on the current weather condition. | ||
""" | ||
try: | ||
sunrise_sunset = SunriseSunset.create( | ||
latitude=settings.latitude, longitude=settings.longitude | ||
) | ||
weather_code = weatherstack.get_current_weather_code( | ||
settings=settings.weatherstack, | ||
latitude=settings.latitude, | ||
longitude=settings.longitude, | ||
is_day=sunrise_sunset.is_day_now, | ||
) | ||
if cache.last_weather_code != weather_code: | ||
cache.last_weather_code = weather_code | ||
|
||
background_image_file = image.get_image_file(prefix=str(weather_code)) | ||
foreground_image_file = Path(settings.profile_photos_dir) / ( | ||
"photo.png" if sunrise_sunset.is_day_now else "night_photo.png" | ||
) | ||
profile_photo = image.create_profile_photo( | ||
background=background_image_file, | ||
foreground=foreground_image_file, | ||
) | ||
slack.set_profile_photo(settings.slack, profile_photo) | ||
logging.info( | ||
f"updated profile photo based on weather_code {weather_code}" | ||
+ f" and background image {background_image_file}" | ||
) | ||
else: | ||
logging.info(f"No weather change since last time ({weather_code})") | ||
except Exception: | ||
logging.error("Error updating profile photo", exc_info=True) | ||
|
||
schedule.schedule( | ||
daytime_interval_s=settings.polling_interval_s, | ||
sunrise_sunset=sunrise_sunset, | ||
function=update_profile_photo_from_weather, | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
setup_logging() | ||
update_profile_photo_from_weather() | ||
Event().wait() |
Oops, something went wrong.