#!/usr/bin/env python3 """ A really lazy bot for idling in OppaiTime's announce channel and downloading every torrent with matching tags. """ import os import re import functools import configparser import http.cookiejar import requests from twisted.internet import protocol, reactor from twisted.words.protocols import irc HEADERS = {"User-Agent": "spaghetti is a faggot"} class OppaiBot(irc.IRCClient): def __init__(self, config): self.config = config self.tracker = self.config.name self.nickname = self.config["nickname"] self.username = self.config["ident"] self.cj = http.cookiejar.MozillaCookieJar(self.config["cookies_txt"]) self.cj.load() self.watch_dir = self.config["watch_dir"] self.tags = self.config["tags"].split(",") def save_torrent(self, url, directory): """ Downloads and saves the torrent file to the given directory. """ res = requests.get(url, cookies=self.cj, headers=HEADERS, verify=True) res.raise_for_status() fname = re.search(r'filename="(.+)"',res.headers['content-disposition']) fname = fname.group(1) fname = fname.replace(u"â\x80\x93", "–") print(self.tracker + ": Saving torrent:", fname) with open(os.path.join(directory, fname), "wb") as file: for chunk in res.iter_content(100000): file.write(chunk) def privmsg(self, user, channel, message): """ Called when the bot receives a PRIVMSG, which can come from channels or users alike. """ # More advanced logic is left as an exercise to the reader. tags_in_msg = [tag in message for tag in self.tags] if any(tags_in_msg): url = re.findall(r"(http.+?) ", message)[1] self.save_torrent(url, self.watch_dir) def joined(self, channel): """Called when the bot joins a new channel.""" print(self.tracker + ": Joined", channel) def signedOn(self): """Called when the bot successfully connects to the server.""" print(self.tracker + ": Signed on as", self.nickname) self.mode(self.nickname, True, "B") # set +B on self self.msg(self.config["tracker_bot"], self.config["auth_msg"]) def nickChanged(self, nick): """Called when my nick has been changed.""" print(self.tracker + ": Nick changed to", nick) class OppaiBotFactory(protocol.ReconnectingClientFactory): # black magic going on here protocol = property(lambda s: functools.partial(OppaiBot, s.config)) def __init__(self, config): self.config = config if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description="Downloads new torrents from a torrent tracker's IRC " \ + "announce channel.") parser.add_argument( "-c", "--config", default="config.cfg", help="Specify an alternate config file to use.") args = parser.parse_args() config = configparser.ConfigParser() config.read(args.config) for tracker in config.sections(): tracker_config = config[tracker] server = tracker_config["server"] port = tracker_config.getint("port") print("Connecting to:", tracker_config.name) reactor.connectTCP(server, port, OppaiBotFactory(tracker_config)) reactor.run()