#!/bin/bash # Transmission BitTorrent blocklist downloader # Copyright (C) 2018 Pekka Helenius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### # TODO Remove duplicate IP's from list files (does Transmission do this automatically?) # TODO Support more archive/text formats # Only zip & gz archives are currently supported # TODO "Older than XX days" check not always working? ########################################################################### # Usage: # bash transmission_blocklists.sh # bash transmission_blocklists.sh -y # where -y parameter passes all Yes/No questions with auto-yes answer # Exception: internet connection test # Requirements: # Unix-based OS # Bash shell 4.0 or above # Internet connection # Transmission client installed # gzip ########################################################################### # BLOCKLISTS typeset -A BLOCKLISTS ##################################### # Blocklist syntax: # [list_1-friendly-name]="list_1_URL" # [list_2-friendly-name]="list_2_URL" # ... # where list_URL must point to some of the following archive types: zip, gz # For example: # [Yoyo-adservers]="http://list.iblocklist.com/?list=zhogegszwduurnvsyhdf&fileformat=p2p&archiveformat=gz" ##################################### BLOCKLISTS=( [Yoyo-adservers]="http://list.iblocklist.com/?list=zhogegszwduurnvsyhdf&fileformat=p2p&archiveformat=gz" ) ########################################################################### # Basic configuration # Older blocklist files than this should be updated. Value in days. UPDATELIMIT_DAYS=15 # Timeout for wget in getfile function, seconds WGET_TIMEOUT=30 # Transmission client blocklist directory for the current user TRANSMISSION_BLOCKLISTDIR=$HOME/.config/transmission/blocklists/ # We need to make internet connection test. The following URL is used for # testing. TEST_PROVIDER="www.github.com" ########################################################################### if [[ $1 == "-y" ]]; then autoyes='' fi ########################################################################### # Commands required by this script COMMANDS=(bash transmission-cli wget gzip date find kill awk sed grep ping unzip mv wc) for command in "${COMMANDS[@]}"; do if [[ $(echo $(which "${command}" &>/dev/null)$?) -ne 0 ]]; then echo "Command ${command} not found. Can't run the script." exit 1 fi done ########################################################################### for transmission_bin in transmission-qt transmission-gtk; do if [[ $(pidof $transmission_bin | wc -l) -ne 0 ]]; then echo -e "\nClose all running Transmission client instances and run this script again.\n" exit 1 fi done DAYS_AGO=$(date -d "now - $UPDATELIMIT_DAYS days" +%s) ########################################################################### # Check bash version BASH_CHECK=$(ps | grep `echo $$` | awk '{ print $4 }') if [ ${BASH_CHECK} != "bash" ]; then echo " Please run this script using bash (/usr/bin/bash). " exit 1 else if [[ $(bash --version | sed -n '1p' | awk '{print $4}' | sed 's/\..*$//g') -lt 4 ]]; then echo "Use bash version 4 or newer." exit fi fi ########################################################################### # Internet connection test CONNECTION=false while [[ $CONNECTION == "false" ]]; do INTERNET_TEST=$(ping -c 1 ${TEST_PROVIDER} 2>&1 | grep -c "Name or service not known") if [[ ! $INTERNET_TEST -eq 0 ]]; then echo -e "\nCan't connect to ${TEST_PROVIDER}. Please check your internet connection and try again.\n" read -r -p "Retry connection? [y/N] " connect_answer if [[ ! $(echo $connect_answer | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then exit fi else CONNECTION="true" fi done ########################################################################### # Delete all old bin files which are not in the list above if [[ $(find "${TRANSMISSION_BLOCKLISTDIR}" -type f -iname "*.bin") ]]; then p=0 for oldfile in $(find "${TRANSMISSION_BLOCKLISTDIR}" -type f -iname "*.bin"); do COMPLISTS[$p]=$(echo ${oldfile} | sed 's/.*\///; s/\.[^.]*$//') let p++ done typeset -A DIFFARRAY a=0 for olditem in "${COMPLISTS[@]}"; do skip= for item in "${!BLOCKLISTS[@]}"; do if [[ ${olditem} == ${item} ]]; then skip=1 break fi done [[ -n $skip ]] || DIFFARRAY[$a]=${olditem} let a++ done if [[ "${#DIFFARRAY[@]}" -ne 0 ]]; then for delfile in "${DIFFARRAY[@]}"; do rm "${TRANSMISSION_BLOCKLISTDIR}/${delfile}.bin" echo -e "Deleted old blocklist '${delfile}'." done fi fi ############################################################ i=1 itemcount="${#BLOCKLISTS[@]}" for listfile in "${!BLOCKLISTS[@]}"; do listfile_bin=$(printf '%s%s.bin' "${TRANSMISSION_BLOCKLISTDIR}" "${listfile}") listfile_url=$(printf '%s' "${BLOCKLISTS[$listfile]}") function getfile() { # TODO check existence of '&' symbol? if [[ $(wget -S --timeout=${WGET_TIMEOUT} --spider $(echo "${listfile_url}" | awk -F "&" '{print $1}') 2>&1 | grep 'Remote file exists' | wc -l) -ge 1 ]]; then echo "$i/$itemcount - Downloading blocklist '${listfile}'" wget -q --show-progress -O - "$listfile_url" > "${TRANSMISSION_BLOCKLISTDIR}/${listfile}" MIMETYPE=$(mimetype "${TRANSMISSION_BLOCKLISTDIR}/$listfile" | awk '{print $2}') if [[ $MIMETYPE == "application/gzip" ]]; then #This is only for gzip... mv "${TRANSMISSION_BLOCKLISTDIR}"/$listfile "${TRANSMISSION_BLOCKLISTDIR}/$listfile.gz" gzip -d "${TRANSMISSION_BLOCKLISTDIR}/$listfile.gz" elif [[ $MIMETYPE == "application/zip" ]]; then unzip -o -qq "${TRANSMISSION_BLOCKLISTDIR}/$listfile" -d "${TRANSMISSION_BLOCKLISTDIR}" fi else echo "$i/$itemcount - Couldn't find blocklist '$listfile'. Please check and either update or delete URL of this file." if [[ ! -v autoyes ]]; then read -r -p "Continue? [y/N] " response else response="y" fi if [[ ! $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then exit fi fi } # Check existence of old blocklist files. if [[ -f "${listfile_bin}" ]]; then # File creation time listfiletime=$(date -r "${listfile_bin}" +%s) if [[ $listfiletime -le $DAYS_AGO ]]; then echo -e "$i/$itemcount - Blocklist '$listfile' is older than $UPDATELIMIT_DAYS days.\nChecking if newer version exists." getfile else echo -e "$i/$itemcount - Blocklist '$listfile' is already updated." fi else getfile fi let i++ done # Generates blocklist.bin # Transmission doesn't have any internal switch to generate only blocklists so # we launch the client with invalid torrent parameter 'dummy' # Blocklist gets generated automatically after which the torrent file gets loaded # into the program. Because there is no an actual torrent file, we get # "Unrecognized torrent" error, in which case we kill the program # Before this error is reached, Transmission has generated a correct blocklist file. # This is just a dirty workaround. # transmission-cli -b dummytorrent |& while read -r line; do if [[ $(echo ${line} | grep "Unrecognized torrent" | wc -l) -eq 1 ]]; then kill $(pidof transmission-cli) 2> /dev/null fi done #for listfile in "${!BLOCKLISTS[@]}"; do # if [[ -f $TRANSMISSION_BLOCKLISTDIR/$listfile ]]; then # rm $TRANSMISSION_BLOCKLISTDIR/$listfile # fi #done # If not a bin file... find $TRANSMISSION_BLOCKLISTDIR -type f ! -iname '*.bin' -delete for file in $(ls $TRANSMISSION_BLOCKLISTDIR/*.bin); do # If bin files are empty... if [[ ! -s ${file} ]]; then rm ${file} fi # Delete the following patterns in the names of existing .bin files. This is just because the names must match with the array LISTS keys # For example ipfilter_AAA.p2p.bin -> ipfilter_AAA.bin -> ipfilter_AAA -> matches BLOCKLISTS array key # pattern=".p2p" if [[ ${file} =~ $pattern ]]; then mv ${file} $(echo ${file} | sed 's/\.p2p//g') fi done unset autoyes unset response unset connect_answer unset BLOCKLISTS