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... " )
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 " :
2018-04-12 15:03:58 +02:00
raise Exception ( " You have probably set use_all_accounts to ' no ' and haven ' t 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 :
group = rep_json [ 0 ] [ " success_schedules " ] [ 0 ] [ " group " ]
text = rep_json [ 0 ] [ " text " ]
track = resolve ( track_url )
if track :
return text + " \n See https://scplanner.net/calendar/reposts/ {0} / {1} / {2} " . format ( soundcloud_id , track . id , group )
else :
2018-04-12 15:03:58 +02:00
raise Exception ( " Schedule was done but I could not find track :( " )
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. " )
return
if not has_role ( user , config [ " CONFIG " ] [ " reposters_role " ] ) :
await bot . say ( " You do no have the required role. " )
return
2018-04-12 03:13:12 +02:00
try :
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__ ' :
start_bot ( )
#auto("https://soundcloud.com/toto/totooooo")