forked from djib/PDMameUpdate
307 lines
9.6 KiB
Python
Executable File
307 lines
9.6 KiB
Python
Executable File
#!/usr/bin/python3
|
|
'''
|
|
Checks available MAME Torrents on PleasureDome
|
|
and updates the local versions if more recent
|
|
versions are detected
|
|
|
|
Basically what it does is:
|
|
* Get all torrents in a directory and filter MAME torrents
|
|
* Get all torrents from PleasureDome RSS
|
|
* Get all torrents currently active in Transmission
|
|
* Intersect the three lists to get updatable torrents
|
|
* And for each updatable torrent:
|
|
- remove the old torrent from Transmission,
|
|
- rename the local directory,
|
|
- add the new torrent
|
|
|
|
Work in progress…
|
|
* TODO: implement some error handling
|
|
|
|
Requirements:
|
|
* Transmission for Bitorrent
|
|
* A PleasureDome account
|
|
* A proper PDMameUpdate.json file (see PDMameUpdate.template.json)
|
|
* Python3 with the libraries below
|
|
- feedparser
|
|
- transmission-clutch
|
|
- tabulate
|
|
* Linux (untested on other OS, but it might work)
|
|
|
|
Notes
|
|
* This script logs in PleasureDome to get the proper cookies.
|
|
It seems you can also set your cookies in Transmission using
|
|
a cookies.txt file in the .config/transmission directory
|
|
See: https://forum.transmissionbt.com/viewtopic.php?t=7468
|
|
|
|
/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
|
|
/!\ Provided with no warranty whatsoever. /!\
|
|
/!\ Make sure you understand what the script /!\
|
|
/!\ does and adapt it to your context /!\
|
|
/!\ Use with caution. /!\
|
|
/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
|
|
'''
|
|
import argparse
|
|
import feedparser
|
|
import json
|
|
import logging
|
|
import os
|
|
import re
|
|
import requests
|
|
import time
|
|
import pathlib
|
|
from clutch.core import Client
|
|
from tabulate import tabulate
|
|
from collections import defaultdict
|
|
from pprint import pformat
|
|
from urllib.parse import quote
|
|
|
|
|
|
def open_config_file():
|
|
"""Reads configuration from PDMameUpdate.json file"""
|
|
|
|
for loc in os.environ.get("PDMAMEUPDATE_CONF"), "/etc", os.path.expanduser("~"), os.curdir:
|
|
if loc is not None:
|
|
config_path = loc + '/PDMameUpdate.json'
|
|
if pathlib.Path(config_path).is_file():
|
|
config_file_loc = config_path
|
|
break
|
|
|
|
logging.info('Opening config file: '+config_file_loc)
|
|
config_file = None;
|
|
with open(config_file_loc, 'r') as config_file:
|
|
config = json.load(config_file)
|
|
return config
|
|
|
|
|
|
def fetch_local_torrents():
|
|
"""Fetches local torrents versions"""
|
|
|
|
logging.info('Fetching current MAME versions')
|
|
directories = os.listdir(config['mame-directory'])
|
|
for directory in directories:
|
|
match = re_mame_version.match(directory)
|
|
if match:
|
|
torrents[match.group(2)]['local-version'] = int(match.group(1))
|
|
torrents[match.group(2)]['local-name'] = directory
|
|
logging.debug('Found the local torrent versions: %s', pformat(torrents))
|
|
|
|
|
|
def fetch_remote_torrents():
|
|
"""Fetches PleasureDome torrents versions"""
|
|
|
|
logging.info('Opening PleasureDome RSS feed')
|
|
d = feedparser.parse('http://www.pleasuredome.org.uk/rss.xml')
|
|
for post in d.entries:
|
|
match = re_mame_version.match(post.title)
|
|
if match:
|
|
matched_version = int(match.group(1))
|
|
matched_torrent = torrents[match.group(2)]
|
|
if matched_version > matched_torrent.get('remote-version', 0):
|
|
matched_torrent['remote-version'] = matched_version
|
|
matched_torrent['remote-link'] = post.link
|
|
matched_torrent['remote-name'] = post.title
|
|
else:
|
|
logging.info("Skipping '{}' version '{}'".format(
|
|
match.group(0),
|
|
matched_version
|
|
))
|
|
logging.debug('Found the remote torrent versions: %s', pformat(torrents))
|
|
|
|
|
|
def filter_updatable_torrents():
|
|
"""Checks if newer versions are available and prompt for update"""
|
|
|
|
for torrent, data in list(torrents.items()):
|
|
keys_to_check = {'local-version', 'remote-version', 'transmission-id'}
|
|
if (
|
|
keys_to_check.issubset(data.keys())
|
|
and
|
|
data['local-version'] < data['remote-version']
|
|
):
|
|
check_and_rewrite_download_url(data)
|
|
else:
|
|
del torrents[torrent]
|
|
|
|
logging.debug(
|
|
'The following torrents can be updated: %s',
|
|
[t for t in torrents.keys()]
|
|
)
|
|
|
|
|
|
def check_and_rewrite_download_url(torrent_data):
|
|
url_match = re.compile(
|
|
r"https?://www.pleasuredome.org.uk/details.php\?id=(.*)"
|
|
)
|
|
match = url_match.match(torrent_data['remote-link'])
|
|
if match:
|
|
url = ("http://www.pleasuredome.org.uk/download.php"
|
|
"?id={}&f={}.torrent&secure=no").format(
|
|
match.group(1),
|
|
quote('+'.join(torrent_data['remote-name'].split(' ')), safe='+')
|
|
)
|
|
logging.info('Changed url {} to {}'.format(
|
|
torrent_data['remote-link'],
|
|
url
|
|
))
|
|
torrent_data['remote-link'] = url
|
|
|
|
|
|
def prompt_for_update():
|
|
"""Ask for user confirmation before updating"""
|
|
|
|
output_header = ["Torrent", "from", "to"]
|
|
output = []
|
|
if len(torrents) > 0:
|
|
for torrent, data in torrents.items():
|
|
output.append([
|
|
torrent,
|
|
data['local-version'],
|
|
data['remote-version']
|
|
])
|
|
print(tabulate(output, headers=output_header, tablefmt="simple"))
|
|
print('Should I update the torrents listed above? (y/N)')
|
|
answer = input()
|
|
if answer.lower() != 'y':
|
|
logging.info('Quitting: user cancelled update')
|
|
print('Quitting…')
|
|
exit(0)
|
|
else:
|
|
logging.info('Quitting: no update candidate')
|
|
print('No update found…')
|
|
exit(0)
|
|
logging.info('User chose to update torrents')
|
|
|
|
|
|
def get_cookies_from_pleasuredome():
|
|
"""Connects to PleasureDome to retrieve Cookies"""
|
|
|
|
logging.info('Logging in PleasureDome')
|
|
data = {
|
|
'uid': config['pleasuredome-user'],
|
|
'pwd': config['pleasuredome-password']
|
|
}
|
|
r = requests.post('http://www.pleasuredome.org.uk/login2.php', data=data)
|
|
if r.status_code == 200:
|
|
logging.info('Connected to PleasureDome')
|
|
logging.info('Logging out')
|
|
requests.get('http://www.pleasuredome.org.uk/logout.php')
|
|
else:
|
|
logging.error(
|
|
'Connection to PleasureDome failed with status %s',
|
|
r.status_code
|
|
)
|
|
exit(1)
|
|
return {k: r.cookies[k] for k in ('uid', 'pass')}
|
|
|
|
|
|
def connect_to_transmission():
|
|
"""Connects to Transmission and return a Client object"""
|
|
|
|
logging.info('Connecting to Transmission Remote Control')
|
|
return Client(
|
|
username=config['transmission-user'],
|
|
password=config['transmission-password'],
|
|
port=config['transmission-port']
|
|
)
|
|
|
|
|
|
def fetch_transmission_torrents():
|
|
"""Gets the torrents id from Transmission"""
|
|
|
|
logging.info('Listing Transmission torrents')
|
|
for torrent in client.list().values():
|
|
match = re_mame_version.match(torrent['name'])
|
|
if match:
|
|
torrents[match.group(2)]['transmission-id'] = torrent['id']
|
|
logging.debug('Found the Transmission torrent ids: %s', pformat(torrents))
|
|
|
|
|
|
def update_torrents():
|
|
"""
|
|
Updates torrents:
|
|
* remove it from Transmission,
|
|
* rename the local directory,
|
|
* and add the new torrent
|
|
"""
|
|
logging.info('Updating torrents')
|
|
for torrent in torrents.values():
|
|
old_name = os.path.join(
|
|
config['mame-directory'],
|
|
torrent['local-name']
|
|
)
|
|
new_name = os.path.join(
|
|
config['mame-directory'],
|
|
torrent['remote-name']
|
|
)
|
|
new_torrent = os.path.join(
|
|
config['torrent-directory'],
|
|
torrent['remote-name']+'.torrent'
|
|
)
|
|
|
|
client.torrent.remove(torrent['transmission-id'])
|
|
os.rename(old_name, new_name)
|
|
client.torrent.add(
|
|
filename=torrent['remote-link'],
|
|
download_dir=config['mame-directory'],
|
|
cookies=cookies,
|
|
paused=False
|
|
)
|
|
|
|
if args.keep:
|
|
t = requests.get(torrent['remote-link'], verify=False)
|
|
open(new_torrent, 'wb').write(t.content)
|
|
|
|
if __name__ == '__main__':
|
|
logging.basicConfig(
|
|
level=logging.WARNING,
|
|
format=' %(asctime)s - %(levelname)s - %(message)s'
|
|
)
|
|
parser = argparse.ArgumentParser(
|
|
description='Update PleasureDome MAME Torrents'
|
|
)
|
|
parser.add_argument(
|
|
'-l', '--log',
|
|
action='store_true',
|
|
help='Display more log messages'
|
|
)
|
|
parser.add_argument(
|
|
'-d', '--debug',
|
|
action='store_true',
|
|
help='Display debugging messages'
|
|
)
|
|
parser.add_argument(
|
|
'-k', '--keep',
|
|
action='store_true',
|
|
help='Keep torrent files localy'
|
|
)
|
|
parser.add_argument(
|
|
'-c', '--countdown',
|
|
action='store_true',
|
|
help='Start with a 5 second countdown'
|
|
)
|
|
args = parser.parse_args()
|
|
if args.log:
|
|
logging.getLogger().setLevel(logging.INFO)
|
|
if args.debug:
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
if args.countdown:
|
|
print('PDMameUpdate is about to start')
|
|
# Useful if you run this script when your machine boots
|
|
for i in range(5, 0, -1):
|
|
print('{}\r'.format(i), end=''),
|
|
time.sleep(1)
|
|
|
|
re_mame_version = re.compile(r'MAME 0.(\d+) (.*)')
|
|
config = open_config_file()
|
|
torrents = defaultdict(dict)
|
|
|
|
client = connect_to_transmission()
|
|
cookies = get_cookies_from_pleasuredome()
|
|
|
|
fetch_local_torrents()
|
|
fetch_remote_torrents()
|
|
fetch_transmission_torrents()
|
|
filter_updatable_torrents()
|
|
prompt_for_update()
|
|
update_torrents()
|