Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- #
- # Downloads all your JManga purchases.
- # Obviously requires Python installed and I don't
- # use windows so this should work but
- # I have no way to test it.
- #
- # If you don't know how to run a python script
- # ask someone who does.
- #
- # I really wanted JManga to succeed and was working
- # on an iOS client. I should have seen this coming but
- # I really wanted to believe. I assumed that with all the
- # publishers behind it they would be in it for the long
- # haul. Oh well. Here we are.
- #
- # Since I would really hate for people to lose all the
- # cool obscure manga they bought I'm providing this
- # downloader script. Just give it your username and
- # password and it'll download all your manga. I don't
- # have much manga to test with so I'm not entirely
- # sure what will happen if you have a huge library but
- # it should be fine.
- #
- # Shame they sent out the announcement email after they
- # had turned off points purchasing. I would have bought
- # a bunch of the stuff I was holding off on buying.
- # Why did I wait? I wanted to read them on my iPad
- # not my computer.
- #
- # Please don't put your manga on file sharing sites. :(
- #
- import sys
- import urllib
- import urllib2
- import cookielib
- import json
- import os
- def getCredentials():
- global username
- username = ""
- password = ""
- if len(sys.argv) != 3:
- username = raw_input('Username: ')
- password = raw_input('Password: ')
- else:
- username = sys.argv[1]
- password = sys.argv[2]
- if len(username) == 0:
- print 'error: did not enter a username'
- exit(1)
- if len(password) == 0:
- print 'error: did not enter a password'
- exit(1)
- return username, password
- def getCookie(cookieJar, cookieName):
- for index, cookie in enumerate(cookieJar):
- if cookie.name == cookieName:
- return cookie.value
- return ''
- def login(username, password):
- cookieJar = cookielib.CookieJar()
- opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookieJar))
- loginString = {'formname' : 'RpcApiUser_Login', 'fail_url' : '/login', 'email' : username, 'password' : password, 'x' : '30', 'y' : '7'}
- loginCredentials = urllib.urlencode(loginString)
- result = opener.open('https://www.jmanga.com/formhandler', loginCredentials)
- result.read()
- if len(getCookie(cookieJar, 'manga_user')) == 0:
- print 'error: login failed'
- exit(1)
- print 'logged in'
- return opener
- #result = opener.open('http://jmanga.com/profile')
- #print result.read()
- def extractSeriesIDs(html):
- seriesIDs = {}
- targetString = 'series_id='
- startOffset = 0
- while startOffset >= 0:
- startOffset = html.find(targetString, startOffset)
- if startOffset < 0:
- return seriesIDs.keys()
- startOffset += len(targetString)
- endIndex = html.find('&', startOffset)
- seriesIDs[html[startOffset:endIndex]] = True
- return seriesIDs.keys()
- def decrypt(stringInput):
- b = bytearray(stringInput)
- key = b[0] ^ 0xff
- for i in range(len(b)):
- b[i] ^= key
- return b
- def getBaseNameFromURL(url):
- filename = url.split('/')[-1]
- return filename.split('.')[0]
- def downloadEncryptedImage(opener, url, name):
- imageBytes = decrypt(opener.open(url).read())
- with open(name, 'wb') as f:
- f.write(imageBytes)
- global username
- f.write(username)
- def getChapterInfo(opener, chapterID):
- infoURL = 'http://api.jmanga.com/chapter?chapter%5Fid=' + chapterID
- return json.loads(opener.open(infoURL).read())
- def downloadPage(opener, page, directory):
- locales = page['locale']
- preferredLocale = 'enUS'
- localeNames = locales.keys()
- # not all locales have an image
- # so we try our preferred locale and if that
- # fails then we try the others until we find
- # a valid one (assuming that, in this case,
- # they are all equivalent)
- try:
- i = localeNames.index(preferredLocale)
- localeNames.pop(i)
- localeNames.insert(0, preferredLocale)
- except ValueError:
- pass
- filename = os.path.join(directory, '{:04}.jpg'.format(int(page['number'])+1))
- imageKey = 'encrypted_composed_image_url'
- for localeName in localeNames:
- # Find the first image
- locale = locales[localeName]
- if imageKey in locale and not os.path.exists(filename):
- downloadEncryptedImage(opener, locale[imageKey], filename)
- break
- def safeMakeDirs(path):
- if not os.path.exists(path):
- os.makedirs(path)
- def downloadChapter(opener, chapter, directory):
- number = chapter['number']
- print 'chapter ' + number
- chapterDir = os.path.join(directory, '{:04}'.format(int(number)))
- safeMakeDirs(chapterDir)
- chapterInfo = getChapterInfo(opener, chapter['chapter_id'])
- pages = chapterInfo['pages']
- for index, page in enumerate(pages):
- sys.stdout.write('\t{0}/{1}\r'.format(int(index)+1, len(pages)))
- sys.stdout.flush()
- downloadPage(opener, page, chapterDir)
- sys.stdout.write('\n')
- def downloadSeriesWithID(opener, seriesID):
- seriesInfoURL = 'http://api.jmanga.com/chapters?series%5Fid=' + seriesID
- result = opener.open(seriesInfoURL)
- seriesInfo = json.loads(result.read())
- series = seriesInfo['series']
- localizedInfo = series['locale']['enUS']
- print localizedInfo['name']
- directory = os.path.join('jmanga', seriesID)
- safeMakeDirs(directory)
- downloadEncryptedImage(opener, localizedInfo['encrypted_image_url'], directory + '.jpg')
- chapters = seriesInfo['chapters']
- for chapter in chapters:
- if chapter['purchased']:
- downloadChapter(opener, chapter, directory)
- def getMangaSeries(opener):
- listAddress = 'http://www.jmanga.com/ajax/'
- requestData = 'req=RpcApiUser_LoadMyManga&_='
- result = opener.open(listAddress, requestData)
- seriesIDs = extractSeriesIDs(result.read())
- for seriesID in seriesIDs:
- downloadSeriesWithID(opener, seriesID)
- def main():
- username, password = getCredentials()
- opener = login(username, password)
- getMangaSeries(opener)
- if __name__ == "__main__":
- main()
Add Comment
Please, Sign In to add comment