Skip to content

Commit

Permalink
v1.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
kamolgks committed Jul 17, 2024
1 parent 59c3151 commit a0a1eb2
Show file tree
Hide file tree
Showing 18 changed files with 255 additions and 135 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
API_KEY=''
BOT_TOKEN=''
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,63 @@
<p align="center">
<!-- <p align="center">
<a href="https://t.me/weatherv_robot">
<img src="https://te.legra.ph/file/c47319f50a8a426e1a415.jpg" alt="bot">
<img src="https://te.legra.ph/file/c47319f50a8a426e1a415.jpg" alt="bot_img">
</a>
</p>
</p> -->

[![bot_img](https://te.legra.ph/file/c47319f50a8a426e1a415.jpg)](https://t.me/weatherv_robot)

# WeatherBot

## Description

Weather-Bot is a chatbot designed to provide current weather information. The bot uses the weather API to retrieve weather data and can provide the user with up-to-date information about temperature, humidity, wind speed and other meteorological parameters.
***Weather-Bot is a chatbot designed to provide current weather information. The bot uses the weather API to retrieve weather data and can provide the user with up-to-date information about temperature, humidity, wind speed and other meteorological parameters.***

## Installation

1. Clone the repository:

```bash
```sh
git clone https://github.com/kamolgks/Weather-Bot.git && cd Weather-Bot
```

2. Install dependencies:

```bash
```sh
pip install -r requirements.txt
```

3. Get the API key for the weather API (OpenWeatherMap) and add it to the file (`main.py`):

```python
# main.py
# you will find in the code, the api_key field
3. Create a .env file in the root directory of your project and add your weather API ([OpenWeatherMap](http://api.openweathermap.org)) and your bot's token:

api_key = "your_api_key"
```

4. Insert your bot token into (`main.py`):

```python
# main.py
TOKEN = getenv("BOT_TOKEN", "YOUR_BOT_TOKEN")
API_KEY='YOUR_API_KEY'
BOT_TOKEN='YOUR_BOT_TOKEN'
```

## Usage

1. Launch the bot:

```bash
python3 main.py
```
- **Linux**
- ```python3 main.py```

- **Windows**

- Launch ***"start.bat"***

2. Connect to chat with the bot.

3. Enter the command to add your city:

`/weather_sity `

```
/weather_sity Tashkent
(can also be entered in Russian)
and send name of your city
Tashkent
```

<img src="https://i.imgur.com/Aoeu5Pj.jpeg" alt="city">
<img src="https://i.imgur.com/MQSUFI1.jpeg" alt="city">

And then:

Expand All @@ -67,17 +67,17 @@ And then:

The bot will respond with the current weather in Tashkent.

<img src="https://i.imgur.com/SfXRaA3.jpeg" alt="result">
<img src="https://i.imgur.com/KddA1xS.jpeg" alt="result">

## Teams

- `/weather_sity <city>`: Save your city.
- `/weather_sity` -> `City`: Save your city.
- `/weather`: Get the current weather for the specified city.

## Technologies

- Python
- Aiogram
- Aiogram
- [Weather API](http://api.openweathermap.org)

## License
Expand Down
Empty file added config/__init__.py
Empty file.
29 changes: 29 additions & 0 deletions config/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
images = {
"clear sky": "https://te.legra.ph/file/59fb2206eef46231322fd.jpg",
"smoke": "https://te.legra.ph/file/fb713f2fc775f2d410150.jpg",
"scattered clouds": "https://te.legra.ph/file/fb713f2fc775f2d410150.jpg",
"few clouds": "https://te.legra.ph/file/fb713f2fc775f2d410150.jpg"
}

welcome_gif = "https://x0.at/GfoN.mp4"
send_welcome = """
🪄 <b>Heeey! I am a weather bot. Enter the name of your city.</b>
<b>Enter this command:</b> /weather_city <b>and send the name of your city</b>
<b>Then send this command to view the weather</b>: /weather
"""

city_is_not_set = """
<b>🚫 Default city is not set. Use the command</b> /weather_city <b>city to set a default city.</b>
"""

send_weather = """
<b>❔ Here is the weather in your city</b>:
<pre><code class='language-weather'>🌤 <b>City</b>: {}
{} <b>Temperature:</b> <u>{}°C</u>
💧 <b>Humidity</b>: {}%
💨 <b>Wind speed</b>: {} m/s
☀️ <b>Description:</b> {}</code></pre>
"""
Empty file added database/__init__.py
Empty file.
Binary file added database/data.db
Binary file not shown.
54 changes: 54 additions & 0 deletions database/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import sqlite3

class Database:
def __init__(self, db_path='database/data.db'):
self.conn = sqlite3.connect(db_path)
self.cursor = self.conn.cursor()
self.create_table()

def create_table(self):
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
username TEXT,
nickname TEXT,
city TEXT
)
''')
self.conn.commit()

def close(self):
self.conn.close()

def add_user(self, user_id, username, nickname):
self.cursor.execute(
"INSERT OR IGNORE INTO users (user_id, username, nickname) VALUES (?, ?, ?)",
(user_id, username, nickname)
)
self.conn.commit()

def update_user_city(self, user_id, city):
self.cursor.execute(
"UPDATE users SET city = ? WHERE user_id = ?",
(city, user_id)
)
self.conn.commit()

def get_user_city(self, user_id):
self.cursor.execute(
"SELECT city FROM users WHERE user_id = ?",
(user_id,)
)
result = self.cursor.fetchone()
return result[0] if result else None

def get_all_users(self):
self.cursor.execute("SELECT * FROM users")
return self.cursor.fetchall()

def get_user_by_id(self, user_id):
self.cursor.execute(
"SELECT * FROM users WHERE user_id = ?",
(user_id,)
)
return self.cursor.fetchone()
Empty file added handlers/__init__.py
Empty file.
85 changes: 85 additions & 0 deletions handlers/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import aiohttp

from os import getenv
from aiogram import Router
from aiogram.filters import Command, CommandStart
from aiogram.types import Message, ReplyKeyboardRemove
from aiogram.fsm.context import FSMContext

from database.db import Database
from states.user_states import WeatherState
from keyboards.keyboard import get_cancel_keyboard
from config.config import city_is_not_set, send_weather, images, welcome_gif, send_welcome

router = Router()
db = Database()

@router.message(CommandStart())
async def send_welcome_message(message: Message):
await message.answer_video(video=welcome_gif, caption=send_welcome)

@router.message(Command("weather_city"))
async def prompt_for_city(message: Message, state: FSMContext):
await message.answer("Please enter your city:", reply_markup=get_cancel_keyboard())
await state.set_state(WeatherState.waiting_for_city)

@router.message(WeatherState.waiting_for_city)
async def process_city_submission(message: Message, state: FSMContext):
city = message.text

user_id = message.from_user.id
username = message.from_user.username
nickname = message.from_user.first_name

db.add_user(user_id, username, nickname)
db.update_user_city(user_id, city)

if city == "🚫 Cancel":
await state.clear()
await message.reply("OK")
else:
await message.answer(f"<b>🫶 Your current city</b>: <code>{city}</code>", reply_markup=ReplyKeyboardRemove())
await state.clear()

@router.message(Command("weather"))
async def send_weather_info(message: Message):
user_id = message.from_user.id
city = db.get_user_city(user_id)

if not city:
return await message.answer(city_is_not_set)

api_key = getenv('API_KEY')
api_url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"

try:
async with aiohttp.ClientSession() as session:
async with session.get(api_url) as response:
response.raise_for_status()
weather_data = await response.json()

temperature = weather_data["main"]["temp"]
humidity = weather_data["main"]["humidity"]
wind_speed = weather_data["wind"]["speed"]
weather_description = weather_data["weather"][0]["description"]

temperature_emoji = "🌡" if temperature > 0 else "❄️"
photo_url = images.get(
weather_description,
"https://te.legra.ph/file/a370559984d0da124b97a.jpg",
)

await message.answer_photo(
photo=photo_url,
caption=send_weather.format(
city,
temperature_emoji,
temperature,
humidity,
wind_speed,
weather_description,
),
)

except aiohttp.ClientError:
await message.answer("<b>🚫 Error retrieving weather data. Please try again later.</b>")
Empty file added keyboards/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions keyboards/keyboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton

def get_cancel_keyboard():
keyboard = ReplyKeyboardMarkup(
keyboard=[
[
KeyboardButton(text="🚫 Cancel"),
],
],
one_time_keyboard=True,
resize_keyboard=True,
)
return keyboard
Loading

0 comments on commit a0a1eb2

Please sign in to comment.