Last active
January 7, 2020 17:02
-
-
Save marios8543/e90a839c3a01ca876440cdb0a7e76b38 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from feedparser import parse | |
from aiohttp import ClientSession | |
from discord.ext.commands import Bot | |
from os import getenv | |
from tinydb import TinyDB, Query | |
from os.path import join | |
from asyncio import sleep,get_event_loop | |
from traceback import print_exc | |
client = Bot('ab!') | |
QB_URL = getenv("qbit_url") | |
INTERVAL = int(getenv("INTERVAL")) if getenv("INTERVAL") else 300 | |
web = ClientSession() | |
db = TinyDB("/home/marios/Animebyter/animebyter.json") | |
chn = int(getenv("channel")) | |
downloading = [] | |
class Anime: | |
def __init__(self,name,le,tl,res): | |
self.title = name | |
self.last_episode = le | |
self.torrent_link = tl | |
self.resolution = res.strip() | |
async def login_qb(): | |
async with web.post(QB_URL+'/login',data={'username':getenv("qbit_user"),'password':getenv("qbit_pass")}) as res: | |
if res.status!=200: | |
print("Could not authenticate with qBittorrent. Exiting...") | |
exit(1) | |
else: | |
print("Logged in to qBittorrent") | |
async def get_airing(): | |
r = [] | |
res = await web.get("https://animebytes.tv/feed/rss_torrents_airing_anime/{}".format(getenv("ab_key"))) | |
if res.status==200: | |
txt = await res.text() | |
rss = parse(txt) | |
for i in rss['entries']: | |
try: | |
title = i['ab_grouptitle'] | |
ep = int((''.join(x for x in i['ab_torrentproperty'].split("|")[6] if x.isdigit())).strip()) | |
link = i['link'] | |
r.append(Anime(title,ep,link,i['ab_torrentproperty'].split("|")[3])) | |
except Exception: | |
continue | |
return r | |
async def add_torrent(anime): | |
print("Adding episode {} of {}".format(anime.last_episode,anime.title)) | |
path = "/mnt/Storage/Anime" | |
try: | |
res = await web.post(QB_URL+'/command/download',data={'urls':anime.torrent_link,'savepath':join(path,anime.title),'label':'Anime'}) | |
except Exception as e: | |
print(str(e)) | |
return | |
finally: | |
res.close() | |
if res.status==200: | |
msg = "Added episode {} of {}".format(anime.last_episode,anime.title) | |
print(msg) | |
return msg | |
else: | |
print("Failed to add episode {} of {} ({})".format(anime.last_episode,anime.title,res.status)) | |
async def main(): | |
print("Starting new episode checker") | |
while True: | |
try: | |
print("Checking for new episodes") | |
airing = await get_airing() | |
for i in airing: | |
res = db.search(Query().title==i.title) | |
if res: | |
le = res[0]['last_episode'] | |
if le<i.last_episode and i.resolution in ("1080p"): | |
msg = await add_torrent(i) | |
if msg: | |
await client.get_channel(chn).send(msg) | |
db.update({'last_episode':i.last_episode},Query().title==i.title) | |
except Exception as e: | |
print(str(e)) | |
print_exc() | |
continue | |
finally: | |
await sleep(INTERVAL) | |
async def dl_watchdog(): | |
print("Starting download watchdog") | |
while True: | |
try: | |
res = await web.get(QB_URL+"/query/torrents",params={'filter':'downloading','label':'Anime'}) | |
if res.status==200: | |
res = await res.json() | |
names = [] | |
for i in res: | |
names.append(i['name']) | |
if i['name'] not in downloading: | |
downloading.append(i['name']) | |
for i in downloading: | |
if i not in names: | |
try: | |
downloading.remove(i) | |
except ValueError: | |
pass | |
await client.get_channel(chn).send(":exclamation: <@!196224042988994560> {} has finished downloading.".format(i)) | |
else: | |
print("Something went wrong with fetching downloads ({}: {})".format(res.status,await res.text())) | |
except Exception as e: | |
print(str(e)) | |
print_exc() | |
continue | |
finally: | |
await sleep(10) | |
def chunks(s, n=1999): | |
for start in range(0, len(s), n): | |
yield s[start:start+n] | |
@client.command(pass_context=True) | |
async def add(ctx): | |
airing = await get_airing() | |
txt = "" | |
for i,v in enumerate(airing): | |
txt+="{}) {}\n".format(i,v.title) | |
msgs = [] | |
for i in chunks(txt): | |
msgs.append(await ctx.send(i)) | |
msg = await client.wait_for('message',check=lambda m: m.author==ctx.author and m.channel==ctx.channel) | |
await ctx.channel.delete_messages(msgs) | |
if msg: | |
try: | |
msg = int(msg.content) | |
except Exception as e: | |
return await ctx.send(e) | |
if msg>=len(airing): | |
return await ctx.send("Invalid number") | |
an = airing[msg] | |
db.insert({'title':an.title,'last_episode':an.last_episode-1}) | |
return await ctx.send("Added {}".format(an.title)) | |
@client.command(pass_context=True) | |
async def remove(ctx): | |
watching = db.all() | |
txt = "" | |
for i,v in enumerate(watching): | |
txt+="{}) {}\n".format(i,v['title']) | |
msgs = [] | |
for i in chunks(txt): | |
msgs.append(await ctx.send(i)) | |
msg = await client.wait_for('message',check=lambda m: m.author==ctx.author and m.channel==ctx.channel) | |
if len(msgs)==1: | |
await msgs[0].delete() | |
else: | |
await ctx.channel.delete_messages(msgs) | |
if msg: | |
try: | |
msg = int(msg.content) | |
except Exception as e: | |
return await ctx.send(e) | |
if msg>=len(watching): | |
return await ctx.send("Invalid number") | |
an = watching[msg] | |
db.remove(Query().title==an['title']) | |
return await ctx.send("Removed {}".format(an)) | |
@client.command(pass_context=True) | |
async def down(ctx): | |
airing = await get_airing() | |
txt = "" | |
for i,v in enumerate(airing): | |
txt+="{}) {} (Episode: {})[{}]\n".format(i,v.title,v.last_episode,v.resolution) | |
msgs = [] | |
for i in chunks(txt): | |
msgs.append(await ctx.send(i)) | |
msg = await client.wait_for('message',check=lambda m: m.author==ctx.author and m.channel==ctx.channel) | |
print(msg) | |
await ctx.channel.delete_messages(msgs) | |
if msg: | |
try: | |
msg = int(msg.content) | |
except Exception as e: | |
return await ctx.send(e) | |
if msg>=len(airing): | |
return await ctx.send("Invalid number") | |
await ctx.send(await add_torrent(airing[msg])) | |
async def execute(code,ctx): | |
# Make an async function with the code and `exec` it | |
exec( | |
f'async def __ex(ctx): ' + | |
''.join(f'\n {l}' for l in code.split('\n')) | |
) | |
return await locals()['__ex'](ctx) | |
@client.command(pass_context=True) | |
async def interpret(ctx): | |
if ctx.message.author.id!="196224042988994560": | |
return await ctx.send("Only the bot manager can use this") | |
await ctx.send("Switching on interpreter mode") | |
while True: | |
msg = await client.wait_for('message',check=lambda m: m.author==ctx.author and m.channel==ctx.channel) | |
if not msg: | |
continue | |
if msg.content=="quit": | |
return await ctx.send("Exiting interpreter mode") | |
try: | |
resp = await execute(msg.content,ctx) | |
if not resp: | |
await ctx.send("Evaluation returned None") | |
else: | |
await ctx.send(resp) | |
except Exception as e: | |
await ctx.send("Error ({})".format(str(e))) | |
@client.event | |
async def on_ready(): | |
print("Starting animebyter") | |
await login_qb() | |
client.loop.create_task(main()) | |
client.loop.create_task(dl_watchdog()) | |
client.run(getenv("discord_token")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment