first commit
This commit is contained in:
commit
d368165bb0
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.cfg
|
||||
*.txt
|
33
README.md
Normal file
33
README.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
# OppaiBot
|
||||
It sits in a torrent tracker's IRC announce channel and downloads any new torrent matching it's filters and saves them to a directory. This is a really lazy bot and has all of about <1 hour of work put into it.
|
||||
|
||||
This bot was designed with Oppaitime in mind (hence the name) but it's general enough that it should work with any tracker. Because I'm too lazy to make it login to the tracker site properly, it requires you to extract your session cookie for the site into a text file. How you do that is up to you.
|
||||
|
||||
In the future I might add functionality to work on multiple sites at once.
|
||||
|
||||
## Requirements
|
||||
Python 3+
|
||||
Python modules: `requests, twisted`
|
||||
|
||||
## Config
|
||||
`server` - This is the address of the IRC server the bot should connect to.
|
||||
`port` - This is the server port the bot should use. SSL probably won't work and isn't recommended.
|
||||
`nickname` - This is the nickname the bot will use to initially connect to the server with. It's not actually important since the tracker's bot will (usually) rename you upon authentication.
|
||||
`ident` - This is the IRC username (aka ident) the bot uses to connect to the server. This rarely makes any different.
|
||||
`tracker_bot` - The name of the tracker's IRC bot to authenticate with.
|
||||
`auth_msg` - The message to send to the `tracker_bot` to authenticate with and access the announce channel. It's up to you figure it out.
|
||||
`watch_dir` - The directory to save torrents to.
|
||||
`cookies_txt` - The path to where you session cookie is stored. Should be in Netscape format.
|
||||
|
||||
### Example config.cfg
|
||||
```
|
||||
[oppaitime]
|
||||
server = irc.oppaiti.me
|
||||
port = 6667
|
||||
nickname = iou1name
|
||||
ident = OppaiBot
|
||||
tracker_bot = Udon
|
||||
auth_msg = BOT #oppaitime-announce iou1name SpaghettiIsAFaggot
|
||||
watch_dir = /home/iou1name/torrent/oppaitime/Watch/
|
||||
cookies_txt = cookies.txt
|
||||
```
|
104
oppaiBot.py
Executable file
104
oppaiBot.py
Executable file
|
@ -0,0 +1,104 @@
|
|||
#!/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.nickname = self.config["nickname"]
|
||||
self.username = self.config["ident"]
|
||||
|
||||
cookies_txt = self.config["cookies_txt"]
|
||||
self.cookies = http.cookiejar.MozillaCookieJar(cookies_txt)
|
||||
self.cookies.load()
|
||||
|
||||
self.watch_dir = self.config["watch_dir"]
|
||||
|
||||
|
||||
def save_torrent(self, url, directory):
|
||||
"""
|
||||
Downloads and saves the torrent file to the given directory.
|
||||
"""
|
||||
res = requests.get(url, cookies=self.cookies, headers=HEADERS,
|
||||
verify=True)
|
||||
res.raise_for_status()
|
||||
fname = re.search("filename=(.+)", res.headers['content-disposition'])
|
||||
fname = fname.group(1)
|
||||
print("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.
|
||||
if "English" in message or "Dual Language" in message:
|
||||
url = message.split(" - ")[1].split(" / ")[1]
|
||||
save_torrent(url, self.watch_dir)
|
||||
|
||||
|
||||
def joined(self, channel):
|
||||
"""Called when the bot joins a new channel."""
|
||||
print("Joined", channel)
|
||||
|
||||
|
||||
def signedOn(self):
|
||||
"""Called when the bot successfully connects to the server."""
|
||||
print("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("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)
|
||||
tracker = config.sections()[0]
|
||||
config = config[tracker] # only handle the entry for now
|
||||
|
||||
server = config["server"]
|
||||
port = int(config["port"])
|
||||
reactor.connectTCP(server, port, OppaiBotFactory(config))
|
||||
reactor.run()
|
Loading…
Reference in New Issue
Block a user