#!/usr/bin/env python3
import urllib.parse
import math
import re
import html as htmllib
import bottle
import api
import config
# from https://s.pximg.net/www/js/build/spa.illust.43512305451e699294de.js
emojis_raw = [(101,"normal"),(102,"surprise"),(103,"serious"),(104,"heaven"),(105,"happy"),(106,"excited"),(107,"sing"),(108,"cry"),(201,"normal2"),(202,"shame2"),(203,"love2"),(204,"interesting2"),(205,"blush2"),(206,"fire2"),(207,"angry2"),(208,"shine2"),(209,"panic2"),(301,"normal3"),(302,"satisfaction3"),(303,"surprise3"),(304,"smile3"),(305,"shock3"),(306,"gaze3"),(307,"wink3"),(308,"happy3"),(309,"excited3"),(310,"love3"),(401,"normal4"),(402,"surprise4"),(403,"serious4"),(404,"love4"),(405,"shine4"),(406,"sweat4"),(407,"shame4"),(408,"sleep4"),(501,"heart"),(502,"teardrop"),(503,"star")]
emojis = { emoji_name: emoji_id for emoji_id, emoji_name in emojis_raw }
def render_header():
html = ''
html += 'freexiv
'
return html
def render_illusts_general(illusts):
html = ''
for illust in illusts:
try:
url = urllib.parse.urlsplit(illust['url'])
html += f""
except KeyError:
pass
return html
def render_illusts_user(illusts):
html = ''
for illust_id, illust in illusts:
url = illust['url']
url_split = urllib.parse.urlsplit(url)
html += f""
return html
def render_paged_illusts(illusts, render_fun=render_illusts_general):
num_of_pages = math.ceil(len(illusts) / api.RECOMMENDS_PAGE_SIZE)
html = render_fun(illusts[:api.RECOMMENDS_PAGE_SIZE])
for page in range(1, num_of_pages):
html += 'load more
'
html += render_fun(illusts[page * api.RECOMMENDS_PAGE_SIZE: page * api.RECOMMENDS_PAGE_SIZE + api.RECOMMENDS_PAGE_SIZE])
for page in range(num_of_pages):
html += '
'
return html
def render_user_header(user_id, user_top):
html = render_header()
ogp = user_top['body']['extraData']['meta']['ogp']
illusts = user_top['body']['illusts']
if len(illusts) > 0:
for illust_id, illust in illusts.items():
image_url = illust['profileImageUrl']
image_split = urllib.parse.urlsplit(image_url)
html += f""
break
html += htmllib.escape(ogp['title']) + '' + htmllib.escape(ogp['description']) + '
'
html += f''
return html
def render_pager(p, max_p):
html = ''
if p > 1:
html += '
<< '
html += f'
< '
lowest = max(p - 3, 1)
highest = min(lowest + 6, max_p)
if max_p > 6 and highest - lowest < 6:
lowest = highest - 6
for i in range(highest - lowest + 1):
cur = lowest + i
html += f'
{cur} '
if p < max_p:
html += f'
> '
html += f'
>>'
html += '
'
return html
@bottle.get('/')
def landing():
html = render_header()
landing_page = api.fetch_landing_page().json()
html += render_paged_illusts(landing_page['body']['thumbnails']['illust'])
return html
@bottle.get('/en/artworks/')
def artworks(illust_id):
html = render_header()
pages = api.fetch_illust_pages(illust_id).json()
for page in pages['body']:
regular_url = page['urls']['regular']
regular_url_split = urllib.parse.urlsplit(regular_url)
original_url = page['urls']['original']
original_url_split = urllib.parse.urlsplit(original_url)
html += f''
illust = api.fetch_illust(illust_id).json()['body']
html += '' + htmllib.escape(illust['illustTitle']) + '
'
html += f"{illust['description']}
"
html += f"" + htmllib.escape(illust['userName']) + ''
html += f"Comments
"
comments = api.fetch_comments(illust_id).json()
for comment in comments['body']['comments']:
img = comment['img']
img_split = urllib.parse.urlsplit(img)
html += f"{comment['userName']}: "
if len(comment['comment']) != 0:
def replacer(matchobj):
key = matchobj.group(1)
if key in emojis:
return f'
'
else:
return key
comment = htmllib.escape(comment['comment'])
comment = re.sub('\(([^)]+)\)', replacer, comment)
html += comment
else:
html += f"
"
html += "
"
recommends = api.fetch_illust_recommends_init(illust_id, api.MAX_RECOMMENDS_PAGE_SIZE).json()
html += "Recommended
"
html += render_paged_illusts(recommends['body']['illusts'])
return html
@bottle.get('/en/users/')
def user(user_id):
user_top = api.fetch_user_top(user_id).json()
user_all = api.fetch_user_all(user_id).json()
html = render_user_header(user_id, user_top)
illusts = user_top['body']['illusts']
if len(illusts) > 0:
if len(illusts.items()) == len(user_all['body']['illusts'].items()):
html += render_paged_illusts(list(illusts.items()), render_illusts_user)
else:
illust_ids = list(user_all['body']['illusts'].keys())
max_num_of_ids_per_page = 100
illusts = {}
for page in range(math.ceil(len(illust_ids) / max_num_of_ids_per_page)):
illusts |= api.fetch_user_illusts(user_id, illust_ids[page * max_num_of_ids_per_page: page * max_num_of_ids_per_page + max_num_of_ids_per_page]).json()
html += render_paged_illusts(list(illusts['body']['works'].items()), render_illusts_user)
return html
@bottle.get('/en/users//bookmarks/artworks')
def user_bookmarks(user_id):
p = int(bottle.request.params.get('p', default=1))
items_per_page = 48
user_top = api.fetch_user_top(user_id).json()
bookmarks = api.fetch_user_bookmarks(user_id, (p - 1) * items_per_page, items_per_page).json()
html = render_user_header(user_id, user_top)
max_p = math.ceil(bookmarks['body']['total'] / items_per_page)
html += render_pager(p, max_p)
illusts = bookmarks['body']['works']
html += render_illusts_general(illusts)
html += render_pager(p, max_p)
return html
@bottle.get('/user_banner/')
def user_banner(user_id):
resp = api.fetch_user_banner(user_id)
bottle.response.set_header('content-type', resp.headers.get('content-type'))
return resp.content
@bottle.get('/search')
def search():
html = render_header()
search_term = bottle.request.query.q
search_term_encoded = urllib.parse.quote(search_term)
search_results = api.fetch_search_results(search_term).json()
illusts = search_results['body']['illustManga']['data']
html += render_paged_illusts(illusts)
return html
bottle.run(host=config.BIND_ADDRESS, server=config.SERVER, port=config.BIND_PORT)