~facundo/encuentro/trunk

« back to all changes in this revision

Viewing changes to encuentro/network.py

  • Committer: Facundo Batista
  • Date: 2014-06-07 00:37:54 UTC
  • mto: This revision was merged to the branch mainline in revision 219.
  • Revision ID: facundo@taniquetil.com.ar-20140607003754-9pe29clp9lgxcqx5
Use encuentro downloader for encuentro stuff, and auth correctly to download better videos.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
"""Some functions to deal with network and Encuentro site."""
20
20
 
21
 
import json
22
21
import logging
23
22
import os
24
 
import re
25
23
import sys
26
24
import time
 
25
import urllib
27
26
import urllib2
28
27
 
29
28
from threading import Thread, Event
33
32
import defer
34
33
import requests
35
34
 
 
35
if __name__ == '__main__':
 
36
    # special import before any other imports to configure GUI to use API 2; we
 
37
    # normally don't need to do this *here*, just a support for run
 
38
    # this as a script, for testing/development purpuses
 
39
    import sip
 
40
    for n in "QDate QDateTime QString QTextStream QTime QUrl QVariant".split():
 
41
        sip.setapi(n, 2)   # API v2 FTW!
 
42
 
36
43
from PyQt4 import QtNetwork, QtCore
37
44
 
38
45
from encuentro import multiplatform
39
46
from encuentro.config import config
40
47
 
41
 
# the URL to authenticate, with it's continuation
42
48
AUTH_URL = "http://registro.educ.ar/cuentas/ServicioLogin/index"
43
 
AUTH_CONTINUE = (
44
 
    "http%3A//www.encuentro.gob.ar/sitios/encuentro/Programas/"
45
 
    "loginCallBack%3Fmethod%3Dlogin"
46
 
)
47
 
 
48
 
# if we find this as a link, we're not correctly authenticated
49
 
LOGIN_URL = 'http://www.encuentro.gob.ar/sitios/encuentro/programas/login'
50
 
 
51
49
CHUNK = 16 * 1024
52
50
MB = 1024 ** 2
53
51
 
54
 
BAD_LOGIN_TEXT = "loginForm"
 
52
BAD_LOGIN_TEXT = u"Iniciá sesión"
55
53
 
56
54
DONE_TOKEN = "I positively assure that the download is finished (?)"
57
55
 
77
75
    """Threaded browser to do the download."""
78
76
 
79
77
    # we *are* calling parent's init; pylint: disable=W0231
80
 
    def __init__(self, authuser, authpass, url,
81
 
                 fname, output_queue, must_quit, url_extractor):
 
78
    def __init__(self, parent, authuser, authpass, url,
 
79
                 fname, output_queue, must_quit):
 
80
        self.parent = parent
82
81
        self.authinfo = authuser, authpass
83
82
        self.url = url
84
83
        self.fname = fname
85
84
        self.output_queue = output_queue
86
85
        self.must_quit = must_quit
87
 
        self.url_extractor = url_extractor
88
86
        super(MiBrowser, self).__init__()
89
87
 
90
88
    def _get_download_content(self):
91
89
        """Get the content handler to download."""
92
90
        # log in
93
91
        logger.debug("Browser download, authenticating")
94
 
        sess = requests.Session()
95
92
        usr, psw = self.authinfo
96
 
        data = dict(
 
93
        get_data = dict(
 
94
            servicio=self.parent.service,
 
95
            continuar=urllib.quote(self.url),
 
96
        )
 
97
        complete_auth_url = AUTH_URL + "?" + urllib.urlencode(get_data)
 
98
        post_data = dict(
97
99
            login_user_name=usr,
98
100
            login_user_password=psw,
99
 
            servicio='encuentro',
100
 
            continuar=AUTH_CONTINUE,
 
101
            r=complete_auth_url,
101
102
        )
102
 
        sess.post(AUTH_URL, data)
 
103
        sess = requests.Session()
 
104
        sess.post(complete_auth_url, post_data)
103
105
 
104
106
        # get page with useful link
105
107
        logger.debug("Browser download, getting html")
106
 
        html = sess.get(self.url).content
107
 
        logger.debug("Browser download, got html len %d", len(html))
108
 
 
109
 
        # get the new url
110
 
        new_url = self.url_extractor(html)
111
 
        if new_url == LOGIN_URL:
 
108
        html = sess.get(complete_auth_url).content
 
109
        if BAD_LOGIN_TEXT in html:
112
110
            logger.error("Wrong user or password sent")
113
111
            raise BadCredentialsError()
 
112
        logger.debug("Browser download, got html len %d", len(html))
114
113
 
 
114
        # download from the new url
 
115
        soup = bs4.BeautifulSoup(html)
 
116
        new_url = soup.find(attrs={'class': 'descargas'}).find('a')['href']
115
117
        logger.debug("Opening final url %r", new_url)
116
118
        content = urllib2.urlopen(new_url)
117
119
        try:
267
269
        logger.debug("Downloading to temporal file %r", tempf)
268
270
 
269
271
        logger.info("Download episode %r: browser started", url)
270
 
        brow = MiBrowser(authuser, authpass, url, tempf, qinput, bquit,
271
 
                         self._get_url_from_authenticated_html)
 
272
        brow = MiBrowser(self, authuser, authpass, url, tempf, qinput, bquit)
272
273
        brow.start()
273
274
 
274
275
        # loop reading until finished
311
312
 
312
313
class ConectarDownloader(AuthenticatedDownloader):
313
314
    """Episode downloader for Conectar site."""
314
 
 
315
 
    def _get_url_from_authenticated_html(self, html):
316
 
        """Get the video URL from the html."""
317
 
        m = re.search("\n var recurso = (.*);\n", html)
318
 
        raw = m.groups()[0]
319
 
        data = json.loads(raw)
320
 
 
321
 
        # try to get HD, fallback to SD
322
 
        videos = data['tipo_funcional']['data']
323
 
        hd = videos.get('streaming_hd', {}).get('file_id')
324
 
        if hd is None:
325
 
            file_id = videos['streaming_sd']['file_id']
326
 
        else:
327
 
            file_id = hd
328
 
        info = dict(rec_id=data['rec_id'], file_id=file_id)
329
 
        url = (
330
 
            "http://repositoriovideo-download.educ.ar/repositorio/Video/"
331
 
            "ver?rec_id=%(rec_id)s&file_id=%(file_id)s" % info
332
 
        )
333
 
        return url
 
315
    service = 'conectate'
334
316
 
335
317
 
336
318
class EncuentroDownloader(AuthenticatedDownloader):
337
319
    """Episode downloader for Conectar site."""
338
 
 
339
 
    def _get_url_from_authenticated_html(self, html):
340
 
        """Get the video URL from the html."""
341
 
        soup = bs4.BeautifulSoup(html)
342
 
        url = soup.find(attrs={'class': 'descargas'}).find('a')['href']
343
 
        return url
 
320
    service = 'encuentro'
344
321
 
345
322
 
346
323
class GenericDownloader(BaseDownloader):
477
454
    def download():
478
455
        """Download."""
479
456
        try:
480
 
            fname = yield downloader.download("test-ej-canal", "secc", "tit",
481
 
                                              _url, show)
 
457
            fname = yield downloader.download("test-ej-canal", "secc", "temp",
 
458
                                              "tit", _url, show)
482
459
            print "All done!", fname
483
460
        except CancelledError:
484
461
            print "--- cancelado!"