Projet du weekend: je me suis bricolé une bannière Twitter dynamique.
C’est à la mode sur Twitch/YT, j’avais envie de la même chose, on va voir comment j’ai codé ça.
Sur Twitter c’est pas répandu mais ce n’est pas une idée nouvelle.
J’ai vu récemment @tdinh_me et @acemtp se lancer là dedans, il y en a sans doute plein d’autres.
Pour faire ça il nous faut 3 trucs:
L’API Twitter est mal documentée sur https://developer.twitter.com, il y a 2 versions. On doit utiliser l’API version 1, pour laquelle on veut les droits en lecture/écriture. Je me suis fait mordre avec juste l’accès lecture. La version 2 ne permet pas de mettre à jour la bannière de profil. C’est dommage car c’est elle que Twitter compte privilégier à l’avenir.
Après avoir créé le projet correctement, on obtient des identifiants qui permettent alors d’effectuer des requêtes vers l’API.
On range les valeurs dans un fichier .env, pour ne pas inclure les clés directement dans le code versionné du projet.
# config.env
API_KEY="do"
API_KEY_SECRET="re"
ACCESS_TOKEN="mi"
ACCESS_TOKEN_SECRET="fa"
Passons au code Python : on veut récupérer la photo de profil des 5 derniers followers.
J’ai utilisé dotenv pour récupérer mes identifiants Twitter dans les variables d’environnement, et Tweepy pour solliciter l’API.
import os
import tweepy
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv("config.env")
if __name__ == "__main__":
auth = tweepy.OAuthHandler(os.getenv("API_KEY"), os.getenv("API_KEY_SECRET"))
auth.set_access_token(os.getenv("ACCESS_TOKEN"), os.getenv("ACCESS_TOKEN_SECRET"))
api = tweepy.API(auth)
latest_followers = api.get_followers(count=5, skip_status=True)
print([follower.profile_image_url_https for follower in latest_followers])
On tient quelque chose \o/
On peut maintenant générer la bannière complète :
J’ai utilisé la librairie PIL pour générer dynamiquement le reste :
Quand on est satisfait, on génère un fichier PNG et on l’envoie via l’API twitter
Il y a quelques optimisations, par exemple je mets en cache les images déjà téléchargées. En pseudo-code, l’esprit est le suivant:
# Load environment variables from .env file
load_dotenv("config.env")
if __name__ == "__main__":
auth = tweepy.OAuthHandler(os.getenv("API_KEY"), os.getenv("API_KEY_SECRET"))
auth.set_access_token(os.getenv("ACCESS_TOKEN"), os.getenv("ACCESS_TOKEN_SECRET"))
api = tweepy.API(auth)
latest_followers = api.get_followers(count=5, skip_status=True)
download_images(latest_followers)
image = generate_header(latest_followers, WIDTH, HEIGHT)
image.save(header_filename)
api.update_profile_banner(header_filename)
On a maintenant besoin de faire la mise à jour à intervalle régulier. Le plus simple, c’est cron, un outil linux qui sert à dire “execute telle opération à telle fréquence”
Mes machines pro/perso ne tournant pas en continu, il nous faut un serveur allumé en continu. J’ai des machines “labo” qui me servent pour ce genre de bricolages. J’utilise ansible pour gérer la configuration de mes outils. Oldie but very goodie.
J’ai donc déployé ce projet avec ansible sur la machine distante, en lui indiquant:
---
- name: Deploiement
hosts: bot_machine
become: yes
become_user: root
tasks:
- name: "Installe les dépendances"
apt:
pkg:
- python3
- python3-venv
- vim
state: latest
update_cache: true
- name: "Crée les répertoire nécessaires"
file:
path: ""
state: directory
with_items:
- '/twitter-banner'
- '/twitter-banner/cache'
- name: "Envoie le code"
copy: src= dest=
with_items:
- { src: 'twitter-header-bot-with-followers.py', dest: '/twitter-banner/bot.py' }
- { src: 'twitter-header-follow.png', dest: '/twitter-banner/twitter-header-follow.png' }
- { src: 'requirements.txt', dest: '/twitter-banner/requirements.txt' }
- { src: 'fonts', dest: '/twitter-banner/' }
- { src: 'config.env', dest: '/twitter-banner/config.env' }
- { src: 'cron.sh', dest: '/twitter-banner/cron.sh' }
- name: "Installe les dépendances du projet dans un environnement virtuel"
pip:
requirements: /twitter-banner/requirements.txt
virtualenv: /twitter-banner/venv
virtualenv_command: /usr/bin/python3 -m venv
- name: "Ajoute notre bot dans un cron"
ansible.builtin.cron:
name: "Bot"
minute: "*"
hour: "*"
job: "/bin/bash /twitter-banner/cron.sh"