[pixiv] cache login sessions

This commit is contained in:
Mike Fährmann
2016-03-06 21:00:42 +01:00
parent 738c65d54f
commit c8e83f6560
2 changed files with 34 additions and 46 deletions

View File

@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2014, 2015 Mike Fährmann # Copyright 2014-2016 Mike Fährmann
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation. # published by the Free Software Foundation.
__author__ = "Mike Fährmann" __author__ = "Mike Fährmann"
__copyright__ = "Copyright 2014, 2015 Mike Fährmann" __copyright__ = "Copyright 2014-2016 Mike Fährmann"
__license__ = "GPLv2" __license__ = "GPLv2"
__version__ = "0.4.1" __version__ = "0.4.1"
@@ -15,9 +15,8 @@ __maintainer__ = "Mike Fährmann"
__email__ = "mike_faehrmann@web.de" __email__ = "mike_faehrmann@web.de"
import os import os
import sys
import argparse import argparse
from . import config, extractor, jobs from . import config, extractor, jobs, cache
def build_cmdline_parser(): def build_cmdline_parser():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@@ -81,6 +80,7 @@ def main():
else: else:
if not args.urls: if not args.urls:
parser.error("the following arguments are required: URL") parser.error("the following arguments are required: URL")
cache.init_database()
if args.list_urls: if args.list_urls:
jobtype = jobs.UrlJob jobtype = jobs.UrlJob
elif args.list_keywords: elif args.list_keywords:

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2014, 2015 Mike Fährmann # Copyright 2014-2016 Mike Fährmann
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as # it under the terms of the GNU General Public License version 2 as
@@ -10,6 +10,7 @@
from .common import Extractor, Message from .common import Extractor, Message
from .. import config, text from .. import config, text
from ..cache import cache
import re import re
import json import json
import time import time
@@ -192,10 +193,7 @@ class PixivBookmarkExtractor(PixivFavoriteExtractor):
def require_login(func): def require_login(func):
"""Decorator: auto-login before api-calls""" """Decorator: auto-login before api-calls"""
def wrap(self, *args): def wrap(self, *args):
now = time.time() self.login()
if now - self.last_login > PixivAPI.token_timeout:
self.login()
self.last_login = now
return func(self, *args) return func(self, *args)
return wrap return wrap
@@ -207,52 +205,19 @@ class PixivAPI():
For in-depth information regarding the Pixiv Public-API, see For in-depth information regarding the Pixiv Public-API, see
- http://blog.imaou.com/opensource/2014/10/09/pixiv_api_for_ios_update.html - http://blog.imaou.com/opensource/2014/10/09/pixiv_api_for_ios_update.html
""" """
token_timeout = 50*60 # 50 minutes
def __init__(self, session): def __init__(self, session):
self.last_login = 0
self.session = session self.session = session
self.session.headers.update({ self.session.headers.update({
"Referer": "http://www.pixiv.net/", "Referer": "http://www.pixiv.net/",
"User-Agent": "PixivIOSApp/5.8.0", "User-Agent": "PixivIOSApp/5.8.0",
}) })
config.setdefault(("extractor", "pixiv"), {}) self.username = config.interpolate(("extractor", "pixiv", "username"))
self.password = config.interpolate(("extractor", "pixiv", "password"))
def login(self): def login(self):
"""Login and gain a Pixiv Public-API access token""" """Login and gain a Pixiv Public-API access token"""
pconf = config.get(("extractor", "pixiv")) self.user_id, token = self._do_login(self.username, self.password)
token = pconf.get("access-token") self.session.headers["Authorization"] = "Bearer " + token
now = time.time()
if token:
timestamp = pconf.get("access-token-timestamp", 0)
if now - timestamp > PixivAPI.token_timeout:
token = None
if not token:
data = {
"username": pconf.get("username"),
"password": pconf.get("password"),
"grant_type": "password",
"client_id": "bYGKuGVw91e0NMfPGp44euvGt59s",
"client_secret": "HP3RmkgAmEGro0gn1x9ioawQE8WMfvLXDz3ZqxpK",
}
response = self.session.post(
"https://oauth.secure.pixiv.net/auth/token", data=data
)
if response.status_code not in (200, 301, 302):
raise Exception("login() failed! check username and password.\n"
"HTTP %s: %s" % (response.status_code, response.text))
try:
response = self._parse(response)["response"]
token = response["access_token"]
self.token_timeout = response["expires_in"]
self.user_id = response["user"]["id"]
except:
raise Exception("Get access_token error! Response: %s" % (token))
pconf["access-token"] = token
pconf["access-token-timestamp"] = now - 1
self.session.headers["Authorization"] = (
"Bearer " + token
)
@require_login @require_login
def user(self, user_id): def user(self, user_id):
@@ -304,6 +269,29 @@ class PixivAPI():
) )
return self._parse(response) return self._parse(response)
@cache(maxage=50*60, keyarg=1)
def _do_login(self, username, password):
data = {
"username": username,
"password": password,
"grant_type": "password",
"client_id": "bYGKuGVw91e0NMfPGp44euvGt59s",
"client_secret": "HP3RmkgAmEGro0gn1x9ioawQE8WMfvLXDz3ZqxpK",
}
response = self.session.post(
"https://oauth.secure.pixiv.net/auth/token", data=data
)
if response.status_code not in (200, 301, 302):
raise Exception("login() failed! check username and password.\n"
"HTTP %s: %s" % (response.status_code, response.text))
try:
response = self._parse(response)["response"]
token = response["access_token"]
user = response["user"]["id"]
except:
raise Exception("Get access_token error! Response: %s" % (token))
return user, token
@staticmethod @staticmethod
def _parse(response): def _parse(response):
"""Parse a Pixiv Public-API response""" """Parse a Pixiv Public-API response"""