Автопостинг в Telegram из Google Sheets
Ведёшь контент-план в Google Таблицах — скрипт сам берёт посты по расписанию и публикует в Telegram-канал. Удобно для команды: редактор заполняет таблицу, публикация происходит автоматически.
Время настройки: 30–40 минут
Стек: Python + gspread + Telegram Bot API + systemd
Нужен: VPS, Google-аккаунт, Telegram-канал/группа
Что получится
В Google Таблице создаёшь строки с постами:
| Дата | Время | Текст | Статус |
|---|---|---|---|
| 2025-06-01 | 10:00 | Привет! Новый пост. | |
| 2025-06-01 | 18:00 | Вечерний контент... | |
| 2025-06-02 | 09:00 | Пост на завтра | Опубликовано |
Скрипт запускается каждые 5 минут, находит строки с наступившим временем и ещё не опубликованные — публикует и ставит статус «Опубликовано».
Шаг 1: Настрой Google Sheets API
Нужен сервисный аккаунт — это «технический» пользователь Google которому дашь доступ к таблице.
- Открой console.cloud.google.com
- Создай проект (или выбери существующий)
- Включи API: Библиотека → найди «Google Sheets API» → Включить
- Включи API: Библиотека → найди «Google Drive API» → Включить
- Credentials → Create Credentials → Service Account
- Имя:
sheets-bot, нажми Done - Открой созданный сервис-аккаунт → Keys → Add Key → JSON
- Скачается файл
project-id-xxxxx.json— это твои credentials
Шаг 2: Создай Google Таблицу
- Создай новую таблицу на sheets.google.com
- Первая строка — заголовки:
Дата | Время | Текст | Статус - Скопируй ID таблицы из URL:
https://docs.google.com/spreadsheets/d/**ЭТОТ_ID**/edit - Дай доступ сервис-аккаунту: Поделиться → вставь email сервис-аккаунта (из JSON-файла, поле
client_email) → роль «Редактор»
Шаг 3: Создай Telegram-бота
Если бот уже есть — пропусти. Для публикации в канал бот должен быть добавлен в канал как администратор с правом публикации.
Узнать ID канала: перешли любое сообщение из канала боту @userinfobot. Или используй -100123456789 формат (в API негативный ID с префиксом -100).
Шаг 4: Разверни скрипт
mkdir -p /opt/sheets-bot
cd /opt/sheets-botСкопируй credentials JSON-файл:
# На своей машине:
scp project-id-xxxxx.json user@server:/opt/sheets-bot/credentials.jsonСоздай скрипт:
nano /opt/sheets-bot/bot.pyimport gspread
from google.oauth2.service_account import Credentials
import requests
import os
from datetime import datetime
from dotenv import load_dotenv
load_dotenv()
SPREADSHEET_ID = os.getenv("SPREADSHEET_ID")
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
CHANNEL_ID = os.getenv("TELEGRAM_CHANNEL_ID")
CREDENTIALS_FILE = "/opt/sheets-bot/credentials.json"
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
def get_sheet():
creds = Credentials.from_service_account_file(CREDENTIALS_FILE, scopes=SCOPES)
client = gspread.authorize(creds)
return client.open_by_key(SPREADSHEET_ID).sheet1
def send_message(text: str) -> bool:
response = requests.post(
f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage",
json={
"chat_id": CHANNEL_ID,
"text": text,
"parse_mode": "HTML",
},
timeout=15,
)
return response.ok
def main():
sheet = get_sheet()
rows = sheet.get_all_records()
now = datetime.now()
for i, row in enumerate(rows, start=2): # строки начинаются с 2 (1 = заголовок)
if row.get("Статус") == "Опубликовано":
continue
try:
post_time = datetime.strptime(
f"{row['Дата']} {row['Время']}", "%Y-%m-%d %H:%M"
)
except (ValueError, KeyError):
continue # пропускаем строки с неверным форматом
if now >= post_time:
text = row.get("Текст", "").strip()
if not text:
continue
if send_message(text):
sheet.update_cell(i, 4, "Опубликовано") # колонка 4 = Статус
print(f"Опубликовано: {text[:50]}...")
else:
print(f"Ошибка публикации строки {i}")
if __name__ == "__main__":
main()Шаг 5: Установи зависимости и настрой окружение
cd /opt/sheets-bot
python3 -m venv .venv
source .venv/bin/activate
pip install gspread google-auth requests python-dotenvСоздай .env:
nano /opt/sheets-bot/.envSPREADSHEET_ID=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms
TELEGRAM_BOT_TOKEN=1234567890:ABCdef...
TELEGRAM_CHANNEL_ID=-1001234567890Протестируй:
source .venv/bin/activate
python bot.pyДобавь строку в таблицу с прошедшим временем — должно опубликовать.
Шаг 6: Запуск по расписанию
sudo nano /etc/systemd/system/sheets-bot.service[Unit]
Description=Google Sheets Telegram Bot
After=network.target
[Service]
Type=oneshot
WorkingDirectory=/opt/sheets-bot
ExecStart=/opt/sheets-bot/.venv/bin/python bot.py
EnvironmentFile=/opt/sheets-bot/.envsudo nano /etc/systemd/system/sheets-bot.timer[Unit]
Description=Sheets Bot Timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable sheets-bot.timer
sudo systemctl start sheets-bot.timer
systemctl list-timers sheets-bot.timerРасширения
Публикация с медиа
Добавь колонку «Фото» в таблицу (URL картинки):
photo_url = row.get("Фото", "").strip()
if photo_url:
requests.post(
f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto",
json={
"chat_id": CHANNEL_ID,
"photo": photo_url,
"caption": text,
"parse_mode": "HTML",
}
)
else:
send_message(text)Несколько каналов
Добавь колонку «Канал» в таблицу с разными channel_id. Скрипт смотрит куда публиковать каждый пост.
Черновики
Добавь статус «Готово» — скрипт публикует только строки со статусом «Готово» (а не все пустые).
if row.get("Статус") != "Готово":
continueМеняешь статус на «Готово» — подтверждаешь что пост проверен и готов к публикации.
Устранение проблем
gspread.exceptions.SpreadsheetNotFound — неверный ID таблицы или не дал доступ сервис-аккаунту. Проверь: таблица → Поделиться → там должен быть email из credentials.json.
403 Forbidden от Telegram — бот не является администратором канала. Зайди в настройки канала → Администраторы → добавь бота.
Дата/время парсится неверно — проверь формат в таблице. Скрипт ожидает YYYY-MM-DD и HH:MM. Если в таблице другой формат — измени строку datetime.strptime(...).
Связанные темы
- Python-скрипты — паттерны и шаблоны
- Мониторинг — следить что скрипт работает
- Внешние API — как работать с API в общем