# coding: utf-8

###

### This script downloads comics from comico.jp.

### You need to have access to the comic from the app to use this. Tested with the Android app.

###

### Usage:

### - Get the login file from your phone (in my case it was in /sdcard/jp.comico) and

### save it as 'login.dat' in this directory.

### - Gain access to the comic you want to download from the app (use a レンタル券 or whatever)

### - Go to the same comic from a browser and identify the titleNo and articleNo values from the URL

### Then run `python comico.py <titleNo value> <articleNo value>`

### Example: If the URL is http://www.comico.jp/detail.nhn?titleNo=2&articleNo=167 then you should run

### python comico.py 2 167

###

import sys

import json

import Crypto. Cipher . AES as AES

import requests

import matplotlib. pyplot as plt

from cStringIO import StringIO

import datetime

import numpy as np

import argparse

import urllib

import os

TIMESTAMP_FMT = '%Y-%m-%d %H:%M:%S.000'

APP_VERSION = 164

CERT_FMT = '{deviceId};A;{timestamp};{version};{userNeoId};10021'

def makeCipher ( ) :

return AES. new ( ")kjkj@#hdf8*&Sdf" , mode = AES. MODE_CBC , IV = ' \x 00' * 16 )

def encrypt ( data ) :

x = 16 - ( len ( data ) % 16 )

data = data + chr ( x ) *x

d = makeCipher ( ) . encrypt ( data )

return d. encode ( 'base64' ) . replace ( '

' , '' )

def decrypt ( data ) :

d = makeCipher ( ) . decrypt ( data. decode ( 'base64' ) )

return d [ :- ord ( d [ - 1 ] ) ]

# smali/jp/comico/manager/ConnectManager:getCertification()

def makeCert ( device_id , user_id ) :

cert = CERT_FMT. format ( deviceId = device_id ,

timestamp = datetime . datetime . now ( ) . strftime ( TIMESTAMP_FMT ) ,

version = APP_VERSION ,

userNeoId = user_id )

return encrypt ( cert )

def downloadFromAuth ( auth_file ) :

baseurl = auth_file [ 'data' ] [ 'td' ]

urls = [ baseurl+decrypt ( x [ 'url' ] ) for x in auth_file [ 'data' ] [ 'imgs' ] ]

if len ( urls ) == 0 :

return None

imgs = [ ]

for i , url in enumerate ( urls ) :

print 'Downloading image %d of %d' % ( i + 1 , len ( urls ) )

data = requests. get ( url ) . content

imgs. append ( plt. imread ( StringIO ( data ) , 'jpg' ) )

return np. vstack ( imgs )

def main ( ) :

p = argparse. ArgumentParser ( )

p. add_argument ( '-l' , '--login-file' , default = os . path . join ( os . path . dirname ( __file__ ) , 'login.dat' ) )

p. add_argument ( 'titleNo' )

p. add_argument ( 'articleNo' )

args = p. parse_args ( )

with open ( args. login_file , 'rb' ) as fp:

login = json. loads ( decrypt ( fp. read ( ) ) )

device_id = login [ 'KEY_ANDROID_UUID' ]

access_token = urllib . unquote ( login [ 'userinfo' ] [ 'token' ] )

user_id = login [ 'userinfo' ] [ 'neoid' ]

cheader = makeCert ( device_id , user_id )

resp = requests. post ( 'http://api.comico.jp/article/getAuth.nhn' , headers = { 'cheader' : cheader } , data = {

'mode' : '' , 'accessToken' : access_token , 'titleNo' : args. titleNo , 'articleNo' : args. articleNo } )

image = downloadFromAuth ( resp. json ( ) )

if image is None :

print 'No images to download (make sure you have access from the app)'

sys . exit ( 1 )

fn = 'comico_%s_%s.png' % ( args. titleNo , args. articleNo )

print 'Saving to %s' % ( fn , )

plt. imsave ( fn , image )

if __name__ == '__main__' :