Снова всех приветствую. В моей прошлой статье "Как превратить статус Telegram в статус Steam" вдохновленной статьей "Как превратить свою аватарку в Telegram в часы" я описал интересную концепцию. Почитав комментарии с обеих статей, я пришел к еще одной идее. А именно - аватар с термометром. Это будет последняя статья, которая будет описывать скрипты для стилизации вашего аккаунта в ТГ.

Да, может я и высасываю идею из пальца, но мне показалось это весьма интересным. Ведь статус не очень заметен, а смена аватара часов очень любит вызывать flood-бан.

Перейдем к коду

Здесь более массивный список библиотек, чем в прошлой статье

pip install requests
pip install Telethon
pip install pillow
pip install beautifulsoup4

И давайте сразу импортируем все модули

import requests
from bs4 import BeautifulSoup as bs
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
from telethon import TelegramClient
from telethon.tl.functions.photos import UploadProfilePhotoRequest, DeletePhotosRequest
from telethon.tl.types import InputPhoto
import time

Также инициализируем все классы и зададим переменные

URL_TEMPLATE = "https://pogoda.mail.ru/prognoz/krasnodar/24hours/"
FONT_LARGE = ImageFont.truetype("shr1.ttf", 80)
FONT_SMALL = ImageFont.truetype("shr2.ttf", 30)
client = TelegramClient("anon", api_id, "api_hash")
client.start()
city = "Krasnodar"

URL_TEMPLATE - Ссылка на сайт для парсинга. Просто заходите сюда.
FONT_LARGE и FONT_SMALL - шрифты. Можете скачать любой и указать их тут. Я, к сожалению, уже не смогу сказать, какие использовал я, ибо шрифты были переименованны.
client - Инициализация клиента telethon. Вы можете взять api_id и api_hash здесь.
city - Надпись под температурой

Парсинг погоды

Здесь мы будем использовать requests для подключения и bs4 для чтения страницы. Парсить мы будем с сайта pogoda.mail.ru

upd: я потом чуть изменил код, где мы парсим дополнительно с Яндекса. Увидеть код можете в разделе "Весь код"

def weather_parse():
    r = requests.get(URL_TEMPLATE)
    soup = bs(r.text, "html.parser")
    temperature = soup.find_all('span', class_='p-forecast__temperature-value')[0]  #   <span class="p-forecast__temperature-value">+24°</span>
    return temperature.text

Очень простой код, который парсит погоду. Просто заходите сюда, ищите свой город и вставляете ссылку в переменную URL_TEMPLATE.

Создание изображения с температурой

def img_weather(hour, show=False):
    temperature = weather_parse()
    print(temperature)
    if hour < 6:
        color = "#0000CD"
    elif hour < 12:
        color = "#FFD700"
    elif hour < 18:
        color = "#FFFACD"
    else:
        color = "#FF8C00" 
    image = Image.new('RGB', (256, 256), color='black')
    draw = ImageDraw.Draw(image)
    text_width = draw.textlength(temperature, font=FONT_LARGE)
    draw.text(((256 - text_width) // 2, 80), temperature, font=FONT_LARGE, fill="white")
    subtext = city
    subtext_width = draw.textlength(subtext, font=FONT_SMALL)
    draw.text(((256 - subtext_width) // 2, 150), subtext, font=FONT_SMALL, fill=color)
    if show:
        image.show()
    return image

Здесь интересней. Как видите, мы передаем в аргументы переменную hour. Это час времени, который сейчас на дворе. Потом идет сравнение, сколько сейчас времени. От этого параметра зависит цвет надписи под температурой. Возможно, вам стоит поменять эти цвета, ибо я дальтоник :D
Задаем черный фон, указываем все по середине и на нужной дистанции, а формат изображения 256*256 (квадрат, который требует Telegram).

3 часа
3 часа

По итогу получаем вот такое вот изображение. Мне лично нравится, оставлю так. Может можно туда засунуть что-то еще.

Обновление аватара

async def update_profile_photo(hour):
    try:
        try:
            # Удаляем старую фотографию (с await)
            photos = await client.get_profile_photos('me')
            if photos:
                await client(DeletePhotosRequest(
                    id=[InputPhoto(
                        id=photos[0].id,
                        access_hash=photos[0].access_hash,
                        file_reference=photos[0].file_reference
                    )]
                ))
        except Exception as e:
            print("Нет аватарок или ошибка удаления:", e)
        image = img_weather(hour)
        image.save("vrem.png")
        with open("vrem.png", 'rb') as file:
            file1 = await client.upload_file(file)
            await client(UploadProfilePhotoRequest(file=file1))
        return "True"
    except Exception as e:
        return str(e)

Здесь все просто. Удаляем старую аватарку, сохраняем новую и публикуем ее как аватар. Если выводит ошибку, значит аватарок нету.

Main()

async def main():
    await client.start()
    last_time = ""
    while True:
        current_time = datetime.now().hour
        if current_time != last_time:
            last_time = current_time
            result = await update_profile_photo(current_time)
            if result != "True":
                print(f"Ошибка: {result}")
            else:
                print(f"{current_time}hour - Удачная смена")
        await asyncio.sleep(20)
if __name__ == "__main__":
    with client:
        client.loop.run_until_complete(main())

Здесь мы просто сравниваем каждые 20 секунд час, если час изменится, то вызывается функция для смены аватара. Зачем мониторить именно смену каждого часа? Это за тем, чтобы менять градус точь-в-точь с прогнозом. В прочем не сложно.

Тест

Вот так вот выглядит наш профиль

Полный код
import asyncio
import requests
from bs4 import BeautifulSoup as bs
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
from telethon import TelegramClient
from telethon.tl.functions.photos import UploadProfilePhotoRequest, DeletePhotosRequest
from telethon.tl.types import InputPhoto
url_yandex = "https://yandex.ru/pogoda/ru/krasnodar"
url_mail = "https://pogoda.mail.ru/prognoz/krasnodar/24hours/"
FONT_LARGE = ImageFont.truetype("porn2.ttf", 80)
FONT_SMALL = ImageFont.truetype("porn3.ttf", 30)
client = TelegramClient("anon", api_id, "api_hash")
city = "Krasnodar"
def weather_parse():
    try:  # парсинг яндекс погоды (более точная)
        r = requests.get(url_yandex)
        soup = bs(r.text, "html.parser")
        temperature = soup.find_all('span', class_='AppFactTemperature_value__2qhsG')[0]
        if temperature.text.strip() == "0":
            return "0"
        znak = soup.find_all('span', class_='AppFactTemperature_sign__1MeN4')[0]
        return f"{znak.text}{temperature.text}°"
    except:   # парсинг маил ру на случай поломки яндекса
        r = requests.get(url_mail)
        soup = bs(r.text, "html.parser")
        temperature = soup.find_all('span', class_='p-forecast__temperature-value')[0]
        return temperature.text
def img_weather(hour, show=False):
    temperature = weather_parse()
    print(temperature)
    if hour < 6:
        color = "#0000CD"
    elif hour < 12:
        color = "#FFD700"
    elif hour < 18:
        color = "#FFFACD"
    else:
        color = "#FF8C00" 
    image = Image.new('RGB', (256, 256), color='black')
    draw = ImageDraw.Draw(image)
    text_width = draw.textlength(temperature, font=FONT_LARGE)
    draw.text(((256 - text_width) // 2, 80), temperature, font=FONT_LARGE, fill="white")
    subtext = city
    subtext_width = draw.textlength(subtext, font=FONT_SMALL)
    draw.text(((256 - subtext_width) // 2, 150), subtext, font=FONT_SMALL, fill=color)
    if show:
        image.show()
    return image
async def update_profile_photo(hour):
    try:
        try:
            # Удаляем старую фотографию (с await)
            photos = await client.get_profile_photos('me')
            if photos:
                await client(DeletePhotosRequest(
                    id=[InputPhoto(
                        id=photos[0].id,
                        access_hash=photos[0].access_hash,
                        file_reference=photos[0].file_reference
                    )]
                ))
        except Exception as e:
            print("Нет аватарок или ошибка удаления:", e)
        image = img_weather(hour)
        image.save("vrem.png")
        with open("vrem.png", 'rb') as file:
            file1 = await client.upload_file(file)
            await client(UploadProfilePhotoRequest(file=file1))
        return "True"
    except Exception as e:
        return str(e)
async def main():
    await client.start()
    last_time = ""
    while True:
        current_time = datetime.now().hour
        if current_time != last_time:
            last_time = current_time
            result = await update_profile_photo(current_time)
            if result != "True":
                print(f"Ошибка: {result}")
            else:
                print(f"{current_time}hour - Удачная смена")
        await asyncio.sleep(20)
if __name__ == "__main__":
    with client:
        client.loop.run_until_complete(main())

Итог

Получилось довольно занимательно. Это еще один из способов выделиться из толпы, который вы можете использовать. Креативничайте, добавляйте свои идеи и модернизируйте вашу аватарку. Всем спасибо

Комментарии (24)