8 Commits
8 changed files with 128 additions and 29 deletions

No files matched your search

+2
View File
@@ -1,2 +1,4 @@
.env .env
.venv .venv
__pychace__
*.pyc
+8
View File
@@ -1,3 +1,11 @@
WeatherCLI - Copyright (C) 2025 Lyxminx
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Binary file not shown.
Binary file not shown.
+26 -8
View File
@@ -1,29 +1,47 @@
# WeatherCLI
# Copyright (C) 2025 Lyxminx
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Imports
import requests import requests
from os import system, name from os import system, name
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
#Parts of this function is borrowed from William James Dominic Liwanag Shorter
# Gets the weather info of a city based on the url provided.
def get_Weather(url): def get_Weather(url):
# Gets the useragent from .env
load_dotenv() load_dotenv()
# Retrieve the user-agent from the environment variable
user_agent = os.getenv("USER_AGENT") user_agent = os.getenv("USER_AGENT")
# Use the user-agent in your headers
headers = { headers = {
"User-Agent": user_agent "User-Agent": user_agent
} }
# Gets the weather info based on url, and adds the User-Agent for identification
response = requests.get(url, headers=headers) response = requests.get(url, headers=headers)
# Checks if we get a valid reponse
if response.status_code == 200: if response.status_code == 200:
try: try:
# Gets all weatherdata in a json format
data = response.json() data = response.json()
details = data['properties']['timeseries'][0]['data']['instant']['details'] details = data['properties']['timeseries'][0]['data']['instant']['details']
# Sets the temperature and precipitation to either reflect the current weather conditions or sets it to None and 0 if the response doesn't work
airtemp = details.get('air_temperature', None) airtemp = details.get('air_temperature', None)
precipitation = details.get('precipitation_amount', 0) # Defaults to 0 if missing precipitation = details.get('precipitation_amount', 0)
except (KeyError, IndexError): except (KeyError, IndexError):
airtemp = None airtemp = None
@@ -31,9 +49,9 @@ def get_Weather(url):
else: else:
airtemp = None airtemp = None
precipitation = 0 precipitation = 0
# Returns a dictionary with the weather conditions
return {"airtemp":airtemp,"precipitation":precipitation} return {"airtemp":airtemp,"precipitation":precipitation}
def clear(): def clear():
# for windows # for windows
+55 -19
View File
@@ -1,73 +1,109 @@
# WeatherCLI
# Copyright (C) 2025 Lyxminx
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Imports
from functions import * from functions import *
from possistions import * from possistions import *
import readchar import readchar
import sys import sys
def selectCity(): def selectCity():
# Gets all cities from the dictionary in the possistions.py
from possistions import cities from possistions import cities
# Gets city names
cities = list(cities.keys()) cities = list(cities.keys())
# Adds exit option
cities.append('Exit') cities.append('Exit')
# For checking the selected city
selected = 0 selected = 0
# To enable and disable searchmode
search_mode = False search_mode = False
while True: while True:
clear() # Assuming you have a 'clear' function that clears the screen # Just clears the screen
clear()
print('Select a city or hit "/" to search:') print('Select a city or hit "/" to search:')
# Prints all cities and adds indentation before the name. Also adds an arrow to show which option is selected.
for i, city in enumerate(cities): for i, city in enumerate(cities):
prefix = "> " if i == selected else " " prefix = "> " if i == selected else " "
print(prefix + city) print(prefix + city)
# Starts listening for keypresses
key = readchar.readkey() key = readchar.readkey()
# Moves up if the up arrow or k is pressed
if key == readchar.key.UP or key == 'k' and selected > 0: if key == readchar.key.UP or key == 'k' and selected > 0:
selected -= 1 selected -= 1
# Moves down if the down arrow or j is pressed
elif key == readchar.key.DOWN or key == 'j' and selected < len(cities) - 1: elif key == readchar.key.DOWN or key == 'j' and selected < len(cities) - 1:
selected += 1 selected += 1
# selects option if Enter is pressed
elif key == readchar.key.ENTER: elif key == readchar.key.ENTER:
clear() clear()
# As long as it is not exit return the option that is selected
if cities[selected] != 'Exit': if cities[selected] != 'Exit':
return cities[selected] return cities[selected]
# If it is exit, stop the program
else: else:
sys.exit() sys.exit()
# Checks if / is pressed
elif key == "/": elif key == "/":
# Enables searchmode
search_mode = True search_mode = True
search_query = "" search_query = ""
all_cities = cities # Keep original city list all_cities = cities
filtered_cities = all_cities # Start with all cities filtered_cities = all_cities
while search_mode: while search_mode:
clear() clear()
print(f"Search mode ON | Query: {search_query}") print(f"Search mode ON | Query: {search_query}")
# Show filtered results #Prints all cities that match the query with indentation
for city in filtered_cities: for city in filtered_cities:
print(" " + city) print(" " + city)
key = readchar.readkey() key = readchar.readkey()
# If esc is pressed, exit search mode
if key == readchar.key.ESC: # Exit search mode if key == readchar.key.ESC:
search_mode = False search_mode = False
filtered_cities = all_cities # Reset filter filtered_cities = all_cities
search_query = "" search_query = ""
# Removes the last letter as long as the query is more than 0 characters long
elif key == readchar.key.BACKSPACE and len(search_query) > 0: # Delete last character elif key == readchar.key.BACKSPACE and len(search_query) > 0:
search_query = search_query[:-1] search_query = search_query[:-1]
# If enter is pressed it returns all cities that match the query
elif key == readchar.key.ENTER: # Exit search mode elif key == readchar.key.ENTER:
cities = filtered_cities cities = filtered_cities
search_mode = False search_mode = False
# Any other key will be added to the query
else: else:
search_query += key # Append new character search_query += key
# Makes an array with all cities that match the query
# Update filtered cities based on search query
filtered_cities = [city for city in all_cities if search_query.lower() in city.lower()] filtered_cities = [city for city in all_cities if search_query.lower() in city.lower()]
filtered_cities.append("Exit") # Adds Exit if it isn't in the filtered list.
if "Exit" not in filtered_cities:
filtered_cities.append("Exit")
# Runs the menu and saves the selected city
# Call the function to display and select a city
selected_city = selectCity() selected_city = selectCity()
# Gets the airtemperature of the selected city
airtemp = get_Weather(cities[selected_city])['airtemp'] airtemp = get_Weather(cities[selected_city])['airtemp']
# Gets the amount of precipitation (rain) of the selected city
precipitation = get_Weather(cities[selected_city])['precipitation'] precipitation = get_Weather(cities[selected_city])['precipitation']
# outputs based on temperature and precipitation
if airtemp is None: if airtemp is None:
print("Cannot fetch weatherdata, stick your head out of the window or smth IDK...") print("Cannot fetch weatherdata, stick your head out of the window or smth IDK...")
+21 -1
View File
@@ -1,6 +1,26 @@
# WeatherCLI
# Copyright (C) 2025 Lyxminx
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Add your cities here, by setting latitude and longitude.
cities = { cities = {
"Oslo" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=59.9333&lon=10.7166", "Oslo" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=59.9333&lon=10.7166",
"Trondheim" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=63.4308&lon=10.4034", "Trondheim" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=63.4308&lon=10.4034",
"Skien" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=59.2089&lon=9.606", "Skien" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=59.2089&lon=9.606",
"Tromsø" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=69.6827&lon=18.9427" "Tromsø" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=69.6827&lon=18.9427",
"Molde" : "https://api.met.no/weatherapi/nowcast/2.0/complete?lat=62.73724&lon=7.16073"
} }
+16 -1
View File
@@ -2,4 +2,19 @@
WeaterCLI is a simple weather application that uses the [NowCast from met.no](https://api.met.no/weatherapi/nowcast/2.0/documentation). \ WeaterCLI is a simple weather application that uses the [NowCast from met.no](https://api.met.no/weatherapi/nowcast/2.0/documentation). \
To use this you need to modify [.env.example](https://github.com/Lyxminxx/weatherCLI/blob/master/.env.example) and change the spot that says youremail to be your email. Then rename the file to .env\ To use this you need to modify [.env.example](https://github.com/Lyxminxx/weatherCLI/blob/master/.env.example) and change the spot that says youremail to be your email. Then rename the file to .env\
At this point just run ```pip install -r requirements.txt``` to install the dependencies. Then run [main.py](https://github.com/Lyxminxx/weatherCLI/blob/master/main.py).\ At this point just run ```pip install -r requirements.txt``` to install the dependencies. Then run [main.py](https://github.com/Lyxminxx/weatherCLI/blob/master/main.py).\
Feel free to add your own cities in norway by adding it to [possistions.py](https://github.com/Lyxminxx/weatherCLI/blob/master/possistions.py) Feel free to add your own cities in Norway, Sweden, Denmark or Finland by adding it to [possistions.py](https://github.com/Lyxminxx/weatherCLI/blob/master/possistions.py)
## Want to contribute?
Contributions are welcome! Whether it's adding new cities, improving the code, or suggesting features, your help makes **weatherCLI** better. Here's how you can contribute:
1. **Check the Issues Tab** – Look for open issues labeled `good first issue` or `help wanted`.
2. **Add More Cities** – Follow the guide above to add cities and submit a pull request.
3. **Suggest Features** – Open a discussion or issue if you have ideas to improve the project.
4. **Fix Bugs & Improve Code** – Found a bug? Want to optimize something? Submit a PR.
5. **Spread the Word** – If you like this project, give it a ⭐ and share it.
## License
This project is licensed under the GNU General Public License v3.0 or later - see the [LICENSE](LICENSE) file for details.