Login to https website with Python with request - html

I'd like to access some content from https://bato.to/ that requires me to login first. Their login page is: https://bato.to/forums/index.php?app=core&module=global&section=login
I've opened chrome's web developer tools to inspect the POST that's sent when I click login. The 'Form Data' inside the POST is:
auth_key:880ea6a14ea49e853634fbdc5015a024
referer:https://bato.to/forums/
ips_username:startwinkling
ips_password:password1
rememberMe:1
So I've tried to implement this with the code:
Code so far
from requests import session
import re
AUTH_KEY = re.compile(r"<input type='hidden' name='auth_key' value='(.*?)' \/>")
payload = {
'ips_username': 'startwinkling',
'ips_password': 'password1',
'rememberMe' : '1',
'referer' : 'https://bato.to/forums/'
}
with session() as c:
login_url = 'https://bato.to/forums/index.php?app=core&module=global&section=login'
page = c.get(login_url)
auth_key = AUTH_KEY.search(page.text).group(1)
payload['auth_key'] = auth_key
print("auth_key: %s" % auth_key)
page = c.post(login_url, data=payload)
page = c.get('https://bato.to/reader#4b57865eb3a9a9a6')
print(page.text)
I believe I'm grabbing and passing in the auth_key properly since the code outputs:
auth_key: 880ea6a14ea49e853634fbdc5015a024
But the HTML that's printed out indicate that I haven't been able to successfully log in. What am I missing here?

The URL you use for POST is not correct.
The correct one should be https://bato.to/forums/index.php?app=core&module=global&section=login&do=process, it's not the same as login landing page, notice the extra do=process part.
Codes:
from requests import session
import re
AUTH_KEY = re.compile(r"<input type='hidden' name='auth_key' value='(.*?)' \/>")
payload = {
'ips_username': 'startwinkling',
'ips_password': 'password1',
'rememberMe' : '1',
'referer' : 'https://bato.to/forums/'
}
with session() as c:
login_url = 'https://bato.to/forums/index.php?app=core&module=global&section=login'
page = c.get(login_url)
auth_key = AUTH_KEY.search(page.text).group(1)
payload['auth_key'] = auth_key
print("auth_key: %s" % auth_key)
page = c.post(login_url + '&do=process', data=payload)
page = c.get('https://bato.to/reader#4b57865eb3a9a9a6')
print(page.text)
P.S. I would suggest you to add some headers(not use default headers) as well, you might not want to appear as User-Agent: python-requests/1.2.3 CPython/2.7.3 Windows/7 on their analytics, also in case they set some limits on certain pages for "non-browser" visit.

Related

Why am I getting Error "404 Not Found" when routing to certain pages in Bottle?

I am trying to build a simple shopping website but for some routes I keep getting 404 Not Found. I am pretty new to the Bottle Framework and having trouble figuring out the problem. Any help is greatly appreciated.
Here is the code:
import random
from bottle import Bottle,route,template, static_file, request, redirect, abort, view
import model
import session
app = Bottle()
#app.route('/')
def index(db):
info = {
'title': "Our Products"
}
all_products = model.product_list(db)
return template('index', info, products=all_products)
#app.route('/product/<id>', method='GET')
def product(db, id):
product = model.product_get(db, id)
return template('product.html', product=product)
#app.route('/views/men', method='GET')
def product(db):
products = model.product_list(db, 'Men')
return template('views/men.html', products=products)
#app.route('/', method='POST')
def cart(db):
id = request.query.id
quantity = request.forms.get('quantity')
product = model.product_get(db, id);
session.add_to_cart(db, id, quantity);
cart = session.get_cart_contents()
return template('cart.html', cart=cart)
#app.route('/cart')
def show_cart():
cart = session.get_cart_contents()
return template('cart.html', cart=cart)
#app.route('/static/<filename:path>')
def static(filename):
return static_file(filename=filename, root='static')
if __name__ == '__main__':
from bottle import run
from bottle.ext import sqlite, beaker
from dbschema import DATABASE_NAME
# install the database plugin
app.install(sqlite.Plugin(dbfile=DATABASE_NAME))
# install beaker
session_opts = {
'session.type': 'memory',
}
beaker_app = beaker.middleware.SessionMiddleware(app, session_opts)
run(app=beaker_app, debug=True, port=8010)
The home page works fine. It loads and I can see all the products. When I click on a product, it takes me to 'http://127.0.0.1:8010/product/1' and everything works fine. At this point, I click on add to cart and it takes me to the cart. But when I change the route to '/cart', I get 404 Not Found, when I set it to '/' , it works fine. When I route to 'views/men' , I get a 404 Not Found. I don't understand whats happening.

Django send an email on post_save with templates

I'm attempting to send an email our admin when new data is submitted to our website from the users. We are using a Django for the backend and Vue for the front end, even though that probably doesn't matter. Here is the code:
#receiver(post_save)
def send_update(sender, created, **kwargs):
if created:
data=kwargs['instance']
try:
if data.admin_approved == False:
print("point 1 reached")
name = data.submitted_by_name
body = data.body
content_type = str(sender).split(".")[2][:-2]
print("point 2 reached")
link = "https://link_to_website.com" + content_type.lower()
subject = "New " + content_type + " submitted"
print("point 3 reached")
from_email = "NoReply#web_site.com"
to_email = "my_email#address.com"
print("pre-html point reached")
html_message = get_template('./email/template.html')
text_message = get_template('./email/textplate.txt')
data = {
'user_name': name,
'submission': data.body,
'type': content_type,
'link': link,
'body': body
}
content_text = text_message.render(data)
content_html = html_message.render(data)
print("ready to send email!")
msg = EmailMultiAlternatives(subject, content_text, from_email, [to_email])
msg.attach_alternative(content_html, "text/html")
msg.send()
except:
print("Data was not submitted by an non-admin user.")
The try/except is included so that data that is submitted directly through the django admin page does not trigger the email function.
the function works up until "pre-html point reached", I'm guessing the issue is somewhere within the msg and msg.send() but I am not receiving any error functions.
Thanks for the help!

Flask Oauth2 get Google+ profile-picture-url from the profile-picture-json

I have a problem here in obtaining the Google+ profile-picture-url from the profile-picture-json. I'm quite a beginner and this is my first webapp so please take this into account.
My callback function:
def callback(self):
self.validate_oauth2callback()
oauth_session = self.service.get_auth_session(
data={'code': request.args['code'],
'grant_type': 'authorization_code',
'redirect_uri': self.get_callback_url()
},
decoder=jsondecoder
)
me = oauth_session.get('').json()
social_id = 'google$' + me['sub']
username = me.get('name', None) if me.get('name', None) else me['email'].split('#')[0]
email = me['email'] if me['email_verified'] == True else None
url = me.get('profile', None)
image_json = 'https://www.googleapis.com/plus/v1/people/' + me['sub'] + '?fields=image&key=AIz..yAl..juCqj..sjj9y..PuM..R..9..F8p..mo'
image = image_json['image'] # <-- THIS DOESN'T WORK
return social_id, username, email, url, image, me
My problem is that the variable image_json contains the following:
{
"image": {
"url": "https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50",
"isDefault": false
}
}
and I have to extract the profile-picture-url from that. A substring method doesn't work since in order to get that code I have to "run" the url saved in image_json.
What I need is something like image = image_json['image'] to retrieve the string:
"https://lh6.googleusercontent.com/-f..i0..dl..Gc/AAAAAAAAAAI/AAAAAAAAABQ/iNw-IEz...o/photo.jpg?sz=50"
and I would like to change that size in 256 instead of 50.
I have followed many posts but I didn't found a solution for this thing.
The view that will call this function is the following:
#auth.route('/callback/<provider>')
def oauth_callback(provider):
oauth = OAuthSignIn.get_provider(provider)
social_id, username, email, url, image, jsonme = oauth.callback()
if social_id is None:
flash('Authentication failed! Access to ' + provider + ' denied.')
return redirect(url_for('main.home'))
user = User.query.filter_by(email=email).first()
if not user:
user = User(social_id=social_id, username=username, email=email, social_page=url, social_image=image)
db.session.add(user)
db.session.commit()
else:
...
login_user(user, True)
return redirect(url_for('main.home'))

Django email message as HTML

I have an email template that I use to send emails of different kinds. I'd rather not keep multiple email HTML templates, so the best way to handle this is to customize the message contents. Like so:
def email_form(request):
html_message = loader.render_to_string(
'register/email-template.html',
{
'hero': 'email_hero.png',
'message': 'We\'ll be contacting you shortly! If you have any questions, you can contact us at meow#something.com',
'from_email': 'lala#lala.com',
}
)
email_subject = 'Thank you for your beeswax!'
to_list = 'johndoe#whatever.com'
send_mail(email_subject, 'message', 'from_email', [to_list], fail_silently=False, html_message=html_message)
return
When the email is sent however, the html codes don't work. The message appears as it is exactly, angled brackets and all. Is there a way for me to force it to render as HTML tags?
Use EmailMessage to do it with less trouble:
First import EmailMessage:
from django.core.mail import EmailMessage
Then use this code to send html email:
email_body = """\
<html>
<head></head>
<body>
<h2>%s</h2>
<p>%s</p>
<h5>%s</h5>
</body>
</html>
""" % (user, message, email)
email = EmailMessage('A new mail!', email_body, to=['someEmail#gmail.com'])
email.content_subtype = "html" # this is the crucial part
email.send()
Solved it. Not very elegant, but it does work. In case anyone's curious, the variable placed in the email template should be implemented as so:
{{ your_variable|safe|escape }}
Then it works! Thanks guys!
You can use EmailMultiAlternatives feature present in django instead of sending mail using send mail. Your code should look like the below snipet.
from django.core.mail import EmailMultiAlternatives
def email_form(request):
html_message = loader.render_to_string(
'register/email-template.html',
{
'hero': 'email_hero.png',
'message': 'We\'ll be contacting you shortly! If you have any questions, you can contact us at meow#something.com',
'from_email': 'lala#lala.com',
}
)
email_subject = 'Thank you for your beeswax!'
to_list = 'johndoe#whatever.com'
mail = EmailMultiAlternatives(
email_subject, 'This is message', 'from_email', [to_list])
mail.attach_alternative(html_message, "text/html")
try:
mail.send()
except:
logger.error("Unable to send mail.")

Ruby - Scraping HTML : If url does not exist then skip to next

I am currently working on a html scraper that takes a list of anime-planet url's from a text file and then loops through them, parses and stores the data in a database.
The scraper is working nicely however if I put in a large list then the chances of the url not linking to a series properly and throwing an error is quite high. I want to try make it so that IF the url does not work then it notes down the url in an array named 'error-urls' and just skips the record.
The end result being that the script finishes all working url's and returns a list of non working urls i can work with later (maybe in a text file, or just display in console).
I am currently using a rake task for this which is working quite nicely. If anyone could help me with implementing the error handling functionality it would be much appreciated. Cheers!
scrape.rake:
task :scrape => :environment do
require 'nokogiri'
require 'open-uri'
text = []
File.read("text.txt").each_line do |line|
text << line.chop
end
text.each do |series|
url = "http://www.anime-planet.com/anime/" + series
data = Nokogiri::HTML(open(url))
title = data.at_css('.theme').text
synopsis = data.at_css('.synopsis').text.strip
synopsis.slice! "Synopsis:\r\n\t\t\t\t\t"
eps = data.at_css('.type').text
year = data.at_css('.year').text
rating = data.at_css('.avgRating').text
categories = data.at_css('.categories')
genre = categories.css('li').text.to_s
image = data.at_css('#screenshots img')
imagePath = "http://www.anime-planet.com" + image['src']
anime = Series.create({:title => title, :image => imagePath, :description => synopsis, :eps => eps, :year => year, :rating => rating})
anime.tag_list = genre
anime.save()
end
end
Small example of list.txt
5-Centimeters-Per-Second
11Eyes
A-Channel
Air
Air-Gear
Aishiteru-Ze-Baby
You can use open-uri's error handling. See this for more details.
url = "http://www.anime-planet.com/anime/" + series
begin
doc = open(url)
rescue OpenURI::HTTPError => http_error
# bad status code returned
// do something here
status = http_error.io.status[0].to_i # => 3xx, 4xx, or 5xx
puts "Got a bad status code #{status}"
# http_error.message is the numeric code and text in a string
end
data = Nokogiri::HTML(doc)