Initial commit

This commit is contained in:
Andreas Bielawski 2017-11-22 19:57:35 +01:00
parent e953514c3f
commit 60a08f4b6c
6 changed files with 131 additions and 59 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# Byte-compiled / optimized / DLL files / pip / IDE
__pycache__/
*.py[cod]
*$py.class
src/
.idea/
# Config
config.ini

View File

@ -1,22 +1,17 @@
# Pi Hole stats tweeter
I want to send a a daily tweet with the results of what my Pi-Hole blocked. Here is the code, run in Python3.
# Pi-Hole stats tweeter
Send a daily tweet with your Pi-Hole statistics!
# How to use
Install following python dependencies with sudo pip install:
tweepy
datetime
json
urllib
Download python file and replace it with your own account data and link to your own path/to/admin/api.php
1. Install Python 3
2. `pip install -U - r requirements.txt`
3. Copy config.ini.example to config.ini and adjust it
3.1. `api_path` = Path to your /admin/api.php of Pi-Hole
3.2. Tokens: Create an application [here](https://apps.twitter.com/)
4. Run it!
# Cronjob
This will tweet your stats at 23:59 everyday
This will tweet your stats at 23:59 everyday and redirects output to /dev/null:
59 23 * * * sudo python3 /home/pi/Desktop/twittertweeter.py >/dev/null 2>&1
# Twitter acces keys and tokens
On their own website it is quite clearly explained: https://dev.twitter.com/oauth/overview/application-owner-access-tokens
# Reddit
https://www.reddit.com/r/pihole/comments/67umvj/need_help_with_doing_a_daily_pihole_tweet/
```
59 23 * * * python3 /path/to/pihole_tweeter.py >/dev/null 2>&1
```

6
config.ini.example Normal file
View File

@ -0,0 +1,6 @@
[DEFAULT]
api_path = http://localhost/admin/api.php
consumer_key = CONSUMERKEY
consumer_secret = CONSUMERSECRET
access_token = ACCESS-TOKEN
access_token_secret = ACCESSTOKENSECRET

102
pihole_tweeter.py Normal file
View File

@ -0,0 +1,102 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from configparser import ConfigParser
from datetime import datetime
import tweepy
from requests import get
config = ConfigParser()
try:
config.read_file(open('config.ini'))
except FileNotFoundError:
print('config.ini not found.')
sys.exit(1)
# API path
try:
api_path = config['DEFAULT']['api_path']
consumer_key = config['DEFAULT']['consumer_key']
consumer_secret = config['DEFAULT']['consumer_secret']
access_token = config['DEFAULT']['access_token']
access_token_secret = config['DEFAULT']['access_token_secret']
except KeyError as exception:
print('Please check your config.ini.')
sys.exit(1)
if not (api_path, consumer_key, consumer_key, consumer_secret, access_token, access_token_secret):
print('2 Please check your config.ini.')
sys.exit(1)
def comma_value(num):
"""Helper function for thousand separators"""
return "{:,}".format(int(num)).replace(',', '.')
def get_api():
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
return tweepy.API(auth)
def get_pihole_data():
try:
res = get(api_path)
except Exception as exception:
print('Could not contact API: ' + str(exception))
return
if res.status_code != 200:
print('Could not get data from Pi-Hole API.')
return
try:
data = res.json()
except:
print('Got no or invalid JSON.')
return
if not all(k in data for k in
('ads_blocked_today', 'ads_percentage_today', 'dns_queries_today', 'domains_being_blocked')):
print('This is not Pi-Hole JSON...')
return
return data
def construct_tweet(data):
today = datetime.today().strftime("%d.%m.%Y")
tweet = 'Pi-Hole-Statistik für den {date}:\n'.format(date=today)
tweet += 'Blockierte Werbung: ' + str(comma_value(data['ads_blocked_today']))
tweet += ' (' + str(round(data['ads_percentage_today'], 2)).replace('.', ',') + ' %)\n'
tweet += 'DNS-Abfragen: ' + str(comma_value(data['dns_queries_today'])) + '\n'
tweet += 'Domains auf der Blacklist: ' + str(comma_value(data['domains_being_blocked']))
return tweet
def main():
# Twitter login
api = get_api()
try:
print('Logged in as @' + api.me().screen_name)
except tweepy.error.TweepError:
print('Error while logging in - check your credentials.')
return
# Get Pi-Hole info from API
data = get_pihole_data()
if not data:
return
# Tweet it!
tweet = construct_tweet(data)
try:
status = api.update_status(status=tweet)
except tweepy.error.TweepError:
print('Status could not be posted.')
return
print('Status posted! https://twitter.com/' + status.author.screen_name + '/status/' + status.id_str)
if __name__ == '__main__':
main()

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
requests
tweepy

View File

@ -1,42 +0,0 @@
#Send tweet when script is called
import tweepy
import datetime
import json
import urllib
from urllib.request import urlopen
# Retrieve data and load it into a dictionary
data = urlopen('path/to/admin/api.php').read() #bytes
body = data.decode('utf-8')
data = json.loads(body)
# Create tweet, adjust %.2f for amount of decimals you want or %i for a whole number
template_tweet = "\nAds Blocked: %s\nAds Percentage Today: %.2f\nDNS Queries Today: %s\nDomains Being Blocked: %s"
data = template_tweet % (data['ads_blocked_today'],
float (data['ads_percentage_today']),
data['dns_queries_today'],
data['domains_being_blocked']
)
def get_api(cfg):
auth = tweepy.OAuthHandler(cfg['consumer_key'], cfg['consumer_secret'])
auth.set_access_token(cfg['access_token'], cfg['access_token_secret'])
return tweepy.API(auth)
def main():
# Fill in the values noted in previous step here
cfg = {
"consumer_key" : "VALUE",
"consumer_secret" : "VALUE",
"access_token" : "VALUE",
"access_token_secret" : "VALUE"
}
api = get_api(cfg)
tweet = datetime.datetime.today().strftime("%Y-%m-%d") + " Daily Pi-Hole report\n " + data
status = api.update_status(status=tweet)
# Yes, tweet is called 'status' rather confusing
if __name__ == "__main__":
main()