-
Notifications
You must be signed in to change notification settings - Fork 1
/
magnetix.py
265 lines (208 loc) · 9.37 KB
/
magnetix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os.path, base64, time, feedparser, argparse, subprocess
from urllib.request import Request, urlopen
os.system("clear")
### FORMATTED TERMINAL OUTPUT ###################################################################
AEC = {
"BLD":"\33[01m", "UND":"\33[04m",
"RED":"\33[91m", "GRN":"\33[92m", "YLW":"\33[93m", "BLU":"\33[94m", "CYN":"\33[36m",
"RSC":"\33[39m", "RST":"\33[00m",
"PASS":"[+]", "WARN":"[-]", "ERROR":"[x]",
}
### CREDITS #####################################################################################
PRONAME = os.path.basename(__file__)
VERSION = "v3.1"
print((
"""\n{BLD}""" + PRONAME + """, """ + VERSION + """{RST} | RSS Magnet Links Downloader
Downloads matching titles from an RSS and automatically queues
the torrents to a running transmission RPC.
License | Dio ( [email protected] ), {UND}3-Clause BSD License{RST}
Revision | """ + time.ctime(os.path.getmtime(__file__)) + """
Depends | python (os.path, base64, time, feedparser, argparse,
subprocess, urllib.request), transmission-remote
------------------------------------------------------------------------------
""").format(**AEC))
### CONFIGURATION ###############################################################################
DIRECTORY = os.path.dirname(__file__) + "/_magnetic/" # Absolute PATH of working directory
WATCHLIST = DIRECTORY + "series.db" # TV SERIES watchlist
HASHESLOG = DIRECTORY + "torrent.log" # History log of matched torrents w/ hashes
TORRENTDB = DIRECTORY + "torrent.db" # Matched torrents database w/ magnet links
BLACKLIST = DIRECTORY + "blacklist.db" # Do NOT download TORRENTS w/ these keywords
### SETTINGS ####################################################################################
RSSXMLURI = "https://showrss.info/other/all.rss" # RSS2.0 XML URI
TOR_WRITE = "ON" # Keep magnet URIs in Torrent DB [ON|OFF]
LOG_WRITE = "ON" # Keep torrents in history log [ON|OFF]
DAYS2KEEP = "3" # Clean history log after x days
BL_FILTER = "ON" # Activate blacklist filter [ON|OFF]
### TRANSMISSION DAEMON #########################################################################
ADDMAGNET = "ON" # Add magnet URIs to transmission [ON|OFF]
TRAN_HOST = "192.168.2.100" # Transmission Daemon Host
TRAN_PORT = "9091" # Transmission Daemon Port
USERNAME = "transmission" # Transmission Daemon Username
PASSWORD = "yourpassword_base64_encoded" # Transmission Daemon Password (base64)
### DEFINE VARIABLES ############################################################################
TVSERIESDB = []
TORRENT_DB = []
HISTORYLOG = []
FILTER_SPC = []
TORRENTSDT = {}
###################################################################################################
### Create data directory for the script if it does not exist
if (not os.path.exists(DIRECTORY)):
os.makedirs(DIRECTORY)
### Print the WATCHLIST
print((u" ::: {BLD}TV SERIES WATCHLIST{RST} ::::::::::::::::::::::::::::::::::::::::::::::::::::\n").format(**AEC))
try:
with open(WATCHLIST, "r") as TVSERIES:
### Alphabetical listing of watchlist
if TVSERIES != "\n":
TVSERIESDB = list(sorted(TVSERIES.read().strip().splitlines()))
if (os.path.getsize(WATCHLIST) > 0):
def TVSERIESTITLES(l, n):
for i in range(0, len(l), n):
yield l[i:i+n]
TVSERIESTITLES(TVSERIESDB,4)
for TVSERIESTITLE in TVSERIESTITLES(TVSERIESDB,4):
print(u" " + ", ".join(TVSERIESTITLE))
else:
print((u" {BLD}{YLW}{WARN}{RST} " + WATCHLIST + " is {BLD}{YLW}EMPTY{RST}").format(**AEC))
print((u" {BLD}{YLW}{WARN} ADD{RST} TV series titles, separated by a new line (e.g. Stranger Things)").format(**AEC))
exit(0)
print()
except IOError:
open(WATCHLIST, "w").close()
print((u" {BLD}{RED}{ERROR}{RST} " + WATCHLIST + " was {BLD}{GRN}CREATED{RST}").format(**AEC))
### PRINT BLACKLIST
if (BL_FILTER == "ON"):
try:
if (os.path.getsize(BLACKLIST) > 0):
print((u"\n ::: {BLD}BLACKLIST{RST} ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n").format(**AEC))
with open(BLACKLIST, "r") as BLIST:
BLACKLISTDB = list(sorted(BLIST.read().lower().strip().splitlines()))
### break the list every 4 keywords
def BLACKLISTED(l, n):
for i in range(0, len(l), n):
yield l[i:i+n]
BLACKLISTED(BLACKLISTDB,4)
for KEYWORD in BLACKLISTED(BLACKLISTDB,4):
print(u" " + ", ".join(KEYWORD))
print()
except IOError:
open(BLACKLIST, "w").close()
print((u" {BLD}{RED}{ERROR}{RST} " + BLACKLIST + " was {BLD}{GRN}CREATED{RST}").format(**AEC))
### PRINT MATCHES
print((u"\n ::: {BLD}TV SERIES MATCHES{RST} ::::::::::::::::::::::::::::::::::::::::::::::::::::::\n").format(**AEC))
### if HASHESLOG has not been modified for more than x days, start CLEAN
if (LOG_WRITE == "ON"):
### parse --clear-log 1 from the command line for debugging purposes
parser = argparse.ArgumentParser()
parser.add_argument('--clear-log', default=1)
args = parser.parse_args()
try:
CUR_TIME = time.time()
MOD_TIME = os.path.getmtime(HASHESLOG)
if (CUR_TIME - MOD_TIME >= int(DAYS2KEEP) * 24 * 3600 or args.clear_log == "1"):
open(HASHESLOG, "w").close()
print((u" {BLD}{YLW}{WARN}{RST} " + HASHESLOG + " was {BLD}{YLW}TRUNCATED{RST}\n").format(**AEC))
except IOError:
open(HASHESLOG, "w").close()
print((u" {BLD}{RED}{ERROR}{RST} " + HASHESLOG + " was {BLD}{GRN}CREATED{RST}\n").format(**AEC))
### Check the RSS2.0 URI and parse the XML
try:
### Open the RSS and store in variable
XML = urlopen(Request(RSSXMLURI, headers={'User-Agent': 'Gecko/4.0'}),timeout=15).read()
### Parse the XML with Feedparser
XML_PARSED = feedparser.parse(XML).entries
except:
print((u" {BLD}{RED}{ERROR}{RSC} HTTP {RED}TIMEOUT{RST} for URI " + RSSXMLURI + "\n").format(**AEC))
exit(0)
try:
for XMLENTRY in XML_PARSED:
### FETCH RSS VARIABLES
XMLTITLE = XMLENTRY.title
XML_RAWT = XMLENTRY.tv_raw_title
XML_HASH = XMLENTRY.tv_info_hash
XML_MAGN = XMLENTRY.link
for SERIES in TVSERIESDB:
### make SERIES TITLES lowercase for easier regex
if (SERIES.lower() in XMLTITLE.lower()):
### DO NOT download FILTERED names
if (BL_FILTER == "ON"):
if (any(FILTER in XML_RAWT.lower() for FILTER in BLACKLISTDB)):
FILTER_SPC = "1"
print((u" {BLD}{CYN}{WARN} FILTERED{RST} | " + XML_RAWT[:58]).format(**AEC))
continue
### Load historical hashes
with open(HASHESLOG, "r") as HISTORY:
for HASH in HISTORY:
HASH = HASH.strip()
if len(HASH):
HISTORYLOG.append(HASH)
### Check the HISTORY LOG for already downloaded torrents
if (XML_HASH in HISTORYLOG):
FILTER_SPC = "1"
print((u" {BLD}{YLW}{WARN} EXISTING{RST} | " + XML_RAWT[:58]).format(**AEC))
continue
else:
HISTORYLOG.append(XML_HASH)
### Check for existing MAGNET LINKS
if not (XML_MAGN in TORRENT_DB):
TORRENT_DB.append(XML_MAGN)
### Build the array with UNIQUE torrent matches based on infohash
TORRENTSDT[XML_HASH] = { "TITLE": XMLTITLE, }
### WRITE LOGS FOR MATCHED TORRENTS
LOGRESULTS = []
for TOR in TORRENTSDT:
### Write the TORRENT LOG. Append MAGNET URIs for MATCHED TORRENTS
if (TOR_WRITE == "ON"):
try:
with open(TORRENTDB, "w") as MAGNETDB:
for MAGNETURI in TORRENT_DB:
MAGNETDB.write(MAGNETURI + "\n")
except IOError:
print((u" {BLD}{RED}{ERROR}{RST} " + TORRENTDB + " was {BLD}{RED}NOT ACCESSIBLE{RST}").format(**AEC))
### Write the HISTORY LOG. We DO NOT WANT to DOWNLOAD torrents twice
if (LOG_WRITE == "ON"):
try:
with open(HASHESLOG, "w") as LOGDB:
for HASH in HISTORYLOG:
LOGDB.write(HASH + "\n")
except IOError:
print((u" {BLD}{RED}{ERROR}{RST} " + HASHESLOG + " was {BLD}{RED}NOT ACCESSIBLE{RST}").format(**AEC))
### TITLES of TORRENT DOWNLOADS
LOGRESULTS.append(TORRENTSDT[TOR]["TITLE"])
### PRINT TV SERIES MATCHES
if len(LOGRESULTS):
i = 1
for RESULT in LOGRESULTS:
print((u" {BLD}{GRN}{PASS} ADD {RSC}(" + str(i).zfill(2) + "){RST} | " + RESULT[:58]).format(**AEC))
i += 1
## IF NO TITLES EXIST, PRINT THIS MESSAGE
if (str(FILTER_SPC) != "1"):
print((u" {BLD}{YLW}{WARN} NO MATCH{RST} | No more torrents match your TV series watchlist.").format(**AEC))
except:
print((u" {BLD}{RED}{ERROR}{RSC} Something went {RED}WRONG{RSC}. Maybe check RSS field names.{RST}\n").format(**AEC))
exit(0)
### TRANSMISSION REMOTE
if (ADDMAGNET == "ON"):
try:
with open(TORRENTDB, "r") as MAGNETDB:
for TORR in MAGNETDB:
TORR = TORR.strip()
if len(TORR):
try:
TRANSMISSION = "transmission-remote " + TRAN_HOST + ":" + TRAN_PORT + " --auth " + USERNAME + ":" + str(base64.urlsafe_b64decode(PASSWORD), "ascii") + " --add " + TORR
subprocess.Popen(TRANSMISSION,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
### Clear the magnet links database
open(TORRENTDB, "w").close()
except:
print((u"\n {BLD}{RED}{ERROR}{RSC} Remote connection to Transmission RPC {RED}FAILED{RST}.\n Check configuration.\n Magnet links should still be safely stored.").format(**AEC))
except IOError:
open(TORRENTDB, "w").close()
print((u"\n {BLD}{RED}{ERROR}{RST} " + TORRENTDB + " was {BLD}{GRN}CREATED{RST}").format(**AEC))
print()
exit(0)
#
# EOF
#