scplanner-discord/bot.py

165 lines
4.6 KiB
Python
Raw Normal View History

2018-04-12 03:13:12 +02:00
import mechanicalsoup
import json
import requests
import soundcloud
import re
import discord
from discord.ext import commands
import asyncio
from bs4 import BeautifulSoup
import configparser
config = configparser.ConfigParser()
config.read('config.ini')
BASE = "https://scplanner.net/"
COOKIE_NAME = config["CONFIG"]["cookie_name"]
COOKIE_VALUE = config["CONFIG"]["cookie_value"]
def get_cookie_jar():
2018-04-12 15:03:58 +02:00
'''
Creates a cookie jar for the mechanicalsoup browser
'''
from http.cookiejar import Cookie, CookieJar
cj = CookieJar()
c = Cookie(version=0, name=COOKIE_NAME, value=COOKIE_VALUE, port=None, port_specified=False, domain='scplanner.net',
domain_specified=True, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest=None, rfc2109=True)
cj.set_cookie(c)
return cj
2018-04-12 03:13:12 +02:00
def resolve(url):
2018-04-12 15:03:58 +02:00
'''
Transforms a 'url' into a soundcloud object. False if not found.
'''
2018-04-12 03:13:12 +02:00
client_id = "nF5U0gNsNB8529U1rHetpIywdIlnEKk7"
client = soundcloud.Client(client_id=client_id)
try:
track = client.get("/resolve?url="+url)
return track
except:
new_client_id = get_client_id()
if not new_client_id:
return False
try:
client = soundcloud.Client(client_id=new_client_id)
track = client.get("/resolve?url="+url)
return track
except:
return False
def get_client_id():
2018-04-12 15:03:58 +02:00
'''
Tricky part to get the current public client_id of SoundCloud's website
'''
2018-04-12 03:13:12 +02:00
body = requests.get("https://soundcloud.com").text
reg_app = r'https:\/\/a-v2\.sndcdn\.com\/assets\/app(.*).js'
matches = re.search(reg_app,body)
if matches:
app_url = matches.group()
app_content = requests.get(app_url).text
reg_cid = r'client_id:"(\w+)"'
matches = re.search(reg_cid, app_content)
if matches:
client_id = matches.group(1)
return client_id
else:
return False
else:
return False
def auto(track_url):
"""Autoschedule a track link."""
br = mechanicalsoup.StatefulBrowser()
cj = get_cookie_jar()
br.set_cookiejar(cj)
rep = br.open(BASE+"network")
soup = BeautifulSoup(rep.text, "html.parser")
try:
user_url = soup.find("input", {"class": "form-control"})["value"]
soundcloud_id = resolve(user_url).id
except:
raise Exception("Could not determine logged in user...")
2018-07-12 18:01:13 +02:00
2018-04-12 03:13:12 +02:00
rep = br.open(BASE+"schedule")
try:
br.select_form("#autoschForm")
br["urls"] = track_url
2018-04-12 15:03:58 +02:00
use_all_accounts = False
try:
if config["AUTO"]["use_all_accounts"] == "yes":
soup = BeautifulSoup(rep.text, "html.parser")
accounts_select = soup.find("select", {"name": "account[]"})
accounts = []
for account_option in accounts_select.findAll("option"):
accounts.append(account_option["value"])
br["account[]"] = tuple(accounts)
#br["account[]"] = (107375074, 195766419)
except:
pass
2018-04-12 03:13:12 +02:00
rep = br.submit_selected()
except:
2018-04-12 15:03:58 +02:00
raise Exception("There was a problem when posting URL on SCPlanner. Is your account still valid?")
2018-04-12 03:13:12 +02:00
rep = rep.text
rep_json = json.loads(rep)
if not isinstance(rep_json, list):
if rep_json["title"] == "Error S-788":
raise Exception("You have probably set use_all_accounts to 'no' and have not set your account preferences. Please set them here: https://scplanner.net/account")
2018-04-12 03:13:12 +02:00
else:
print(rep_json)
2018-04-12 15:03:58 +02:00
raise Exception("Unknown error. Please fill an issue on https://github.com/jeantoulza/scplanner-discord.")
2018-04-12 03:13:12 +02:00
type = rep_json[0]["type"]
if type == "success" and len(rep_json[0]["success_schedules"]) > 0:
2018-07-12 17:40:50 +02:00
url = rep_json[0]["success_schedules"]["links"].strip()
2018-04-12 03:13:12 +02:00
text = rep_json[0]["text"]
2018-07-12 17:40:50 +02:00
return text+"\nSee {0}".format(url)
2018-04-12 03:13:12 +02:00
else:
2018-04-12 15:03:58 +02:00
raise Exception("Track not found, or something worse happened :(")
2018-04-12 03:13:12 +02:00
2018-04-12 15:03:58 +02:00
def has_role(user, role):
'''
Returns True if 'user' has the 'role' role, False otherwise.
'''
for u_role in user.roles:
if u_role.name == role:
return True
return False
2018-04-12 03:13:12 +02:00
def start_bot():
2018-04-12 15:03:58 +02:00
'''
Main bot loop
'''
2018-04-12 03:13:12 +02:00
bot = commands.Bot(command_prefix='!')
@bot.event
async def on_ready():
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
print('------')
2018-04-12 15:03:58 +02:00
@bot.command(pass_context=True)
async def repost(ctx, url : str):
2018-04-12 03:13:12 +02:00
"""Reposts an URL on SCPlanner."""
2018-04-12 15:03:58 +02:00
user = ctx.message.author
if not isinstance(user, discord.Member):
await bot.say("Please use this command in a server that the bot is located in.")
2018-04-12 15:03:58 +02:00
return
if not has_role(user, config["CONFIG"]["reposters_role"]):
await bot.say("You do not have the required role to repost or use this bot.")
2018-04-12 15:03:58 +02:00
return
2018-04-12 03:13:12 +02:00
try:
2018-07-12 18:01:13 +02:00
print("Autoscheduling "+url)
2018-04-12 03:13:12 +02:00
calendar_link = auto(url)
await bot.say(calendar_link)
except Exception as e:
await bot.say("ERROR: "+str(e))
bot.run(config["CONFIG"]["bot_token"])
if __name__ == '__main__':
2018-07-12 17:42:01 +02:00
start_bot()