Merge pull request #228 from shikorism/develop

Release 20190629.1945
This commit is contained in:
shibafu 2019-06-29 19:50:51 +09:00 committed by GitHub
commit bcf78df2fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 26330 additions and 402 deletions

View File

@ -1,4 +1,5 @@
version: 2
jobs:
build:
docker:
@ -67,7 +68,14 @@ jobs:
- run:
command: |
mkdir -p /tmp/phpunit
./vendor/bin/phpunit --log-junit /tmp/phpunit/phpunit.xml
./vendor/bin/phpunit --log-junit /tmp/phpunit/phpunit.xml --coverage-clover=/tmp/phpunit/coverage.xml
when: always
- store_test_results:
path: /tmp/phpunit
- store_artifacts:
path: /tmp/phpunit/coverage.xml
# Upload coverage
- run:
command: bash <(curl -s https://codecov.io/bash) -f /tmp/phpunit/coverage.xml
when: always

21
.editorconfig Normal file
View File

@ -0,0 +1,21 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_size = 2
[*.json]
indent_size = 2
[composer.json]
indent_size = 4

View File

@ -5,6 +5,9 @@ APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost
# テストにモックを使用するか falseの場合は実際のHTML等を取得してテストする
TEST_USE_HTTP_MOCK=true
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432

1
.stylelintignore Normal file
View File

@ -0,0 +1 @@
/tests/fixture/*

View File

@ -36,6 +36,7 @@ docker-compose up -d
4. Composer と yarn を使い必要なライブラリをインストールします。
```
docker-compose exec web composer global require hirak/prestissimo
docker-compose exec web composer install
docker-compose exec web yarn install
```
@ -50,7 +51,7 @@ docker-compose exec web php artisan migrate
6. ファイルに書き込めるように権限を設定します。
```
docker-compose exec web chown -R www-data /var/www/html
docker-compose exec web chown -R www-data /var/www/html/storage
```
7. アセットをビルドします。

View File

@ -51,6 +51,8 @@ class CardController
$metadata->tags()->sync($tagIds);
}
$metadata->load('tags');
$response = response($metadata);
if (!config('app.debug')) {
$response = $response->setCache(['public' => true, 'max_age' => 86400]);

View File

@ -35,9 +35,27 @@ class ProfileStatsComposer
}
// 概況欄のデータ取得
$average = DB::select(<<<'SQL'
SELECT
avg(span) AS average
FROM
(
SELECT
extract(epoch from ejaculated_date - lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)) AS span
FROM
ejaculations
WHERE
user_id = :user_id
ORDER BY
ejaculated_date DESC
LIMIT
30
) AS temp
SQL
, ['user_id' => $user->id]);
$summary = DB::select(<<<'SQL'
SELECT
avg(span) AS average,
max(span) AS longest,
min(span) AS shortest,
sum(span) AS total_times,
@ -56,6 +74,6 @@ FROM
SQL
, ['user_id' => $user->id]);
$view->with(compact('latestEjaculation', 'currentSession', 'summary'));
$view->with(compact('latestEjaculation', 'currentSession', 'average', 'summary'));
}
}

View File

@ -11,7 +11,7 @@ class Metadata extends Model
protected $keyType = 'string';
protected $fillable = ['url', 'title', 'description', 'image', 'expires_at'];
protected $visible = ['url', 'title', 'description', 'image', 'expires_at'];
protected $visible = ['url', 'title', 'description', 'image', 'expires_at', 'tags'];
protected $dates = ['created_at', 'updated_at', 'expires_at'];

View File

@ -21,23 +21,91 @@ class DLsiteResolver implements Resolver
$this->ogpResolver = $ogpResolver;
}
/**
* HTMLからタグとして利用可能な情報を抽出する
* @param string $html ページ HTML
* @return string[] タグ
*/
public function extractTags(string $html): array
{
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new \DOMXPath($dom);
$genreNode = $xpath->query("//div[@class='main_genre'][1]");
if ($genreNode->length === 0) {
return [];
}
$tagsNode = $genreNode->item(0)->getElementsByTagName('a');
$tags = [];
for ($i = 0; $i <= $tagsNode->length - 1; $i++) {
$tags[] = $tagsNode->item($i)->textContent;
}
// 重複削除
$tags = array_values(array_unique($tags));
return $tags;
}
public function resolve(string $url): Metadata
{
//スマホページの場合はPCページに正規化
if (strpos($url, '-touch') !== false) {
$url = str_replace('-touch', '', $url);
}
$res = $this->client->get($url);
if ($res->getStatusCode() === 200) {
$metadata = $this->ogpResolver->parse($res->getBody());
// 抽出
preg_match('~\[(.+)\] \| DLsite$~', $metadata->title, $match);
$maker = $match[1];
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
$xpath = new \DOMXPath($dom);
// OGPタイトルから[]に囲まれているmakerを取得する
// 複数の作者がいる場合スペース区切りになるためexplodeしている
// スペースを含むmakerの場合名前の一部しか取れないが動作には問題ない
preg_match('~ \[([^\[\]]*)\] (予告作品 )?\| DLsite(がるまに)?$~', $metadata->title, $match);
$makers = explode(' ', $match[1]);
//フォローボタン(.btn_follow)はテキストを含んでしまうことがあるので要素を削除しておく
$followButtonNode = $xpath->query('//*[@class="btn_follow"]')->item(0);
$followButtonNode->parentNode->removeChild($followButtonNode);
// maker, makerHeadを探す
// makers
// #work_makerから「makerを含むテキスト」を持つ要素を持つtdを探す
// 作者名単体の場合もあるし、"作者A / 作者B"のようになることもある
$makersNode = $xpath->query('//*[@id="work_maker"]//*[contains(text(), "' . $makers[0] . '")]/ancestor::td')->item(0);
$makers = trim($makersNode->textContent);
// makersHaed
// $makerNode(td)に対するthを探す
// "著者", "サークル名", "ブランド名"など
$makersHeadNode = $xpath->query('preceding-sibling::th', $makersNode)->item(0);
$makersHead = trim($makersHeadNode->textContent);
// 余分な文を消す
$metadata->title = trim(preg_replace('~ \[.+\] \| DLsite$~', '', $metadata->title));
$metadata->description = trim(preg_replace('~「DLsite.+」は同人誌・同人ゲーム・同人音声のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」$~', '', $metadata->description));
// OGPタイトルから作者名とサイト名を消す
$metadata->title = trim(preg_replace('~ \[[^\[\]]*\] (予告作品 )?\| DLsite(がるまに)?$~', '', $metadata->title));
// OGP説明文から定型文を消す
if (strpos($url, 'dlsite.com/eng/') || strpos($url, 'dlsite.com/ecchi-eng/')) {
$metadata->description = trim(preg_replace('~DLsite.+ is a download shop for .+With a huge selection of products, we\'re sure you\'ll find whatever tickles your fancy\. DLsite is one of the greatest indie contents download shops in Japan\.$~', '', $metadata->description));
} else {
$metadata->description = trim(preg_replace('~「DLsite.+」は.+のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」$~', '', $metadata->description));
}
// 整形
$metadata->description = 'サークル: ' . $maker . PHP_EOL . $metadata->description;
$metadata->description = $makersHead . ': ' . $makers . PHP_EOL . $metadata->description;
$metadata->image = str_replace('img_sam.jpg', 'img_main.jpg', $metadata->image);
$metadata->tags = $this->extractTags($res->getBody());
return $metadata;
} else {

View File

@ -15,9 +15,10 @@ class MetadataResolver implements Resolver
'~www\.melonbooks\.co\.jp/detail/detail\.php~' => MelonbooksResolver::class,
'~ec\.toranoana\.(jp|shop)/(tora|joshi)(_[rd]+)?/(ec|digi)/item/~' => ToranoanaResolver::class,
'~iwara\.tv/videos/.*~' => IwaraResolver::class,
'~www\.dlsite\.com/.*/work/=/product_id/..\d+(\.html)?~' => DLsiteResolver::class,
'~dlsite\.jp/mawtw/..\d+~' => DLsiteResolver::class,
'~www\.dlsite\.com/.*/(work|announce)/=/product_id/..\d+(\.html)?~' => DLsiteResolver::class,
'~dlsite\.jp/...tw/..\d+~' => DLsiteResolver::class,
'~www\.pixiv\.net/member_illust\.php\?illust_id=\d+~' => PixivResolver::class,
'~www\.pixiv\.net/user/\d+/series/\d+~' => PixivResolver::class,
'~fantia\.jp/posts/\d+~' => FantiaResolver::class,
'~dmm\.co\.jp/~' => FanzaResolver::class,
'~www\.patreon\.com/~' => PatreonResolver::class,
@ -26,6 +27,7 @@ class MetadataResolver implements Resolver
'~ci-en\.jp/creator/\d+/article/\d+~' => CienResolver::class,
'~www\.plurk\.com\/p\/.*~' => PlurkResolver::class,
'~(adult\.)?contents\.fc2\.com\/article_search\.php\?id=\d+~' => FC2ContentsResolver::class,
'~store\.steampowered\.com/app/\d+~' => SteamResolver::class,
];
public $mimeTypes = [

View File

@ -21,21 +21,6 @@ class PixivResolver implements Resolver
$this->ogpResolver = $ogpResolver;
}
/**
* サムネイル画像 URL から最大長辺 1200px の画像 URL に変換する
*
* @param string $thumbnailUrl サムネイル画像 URL
*
* @return string 1200px の画像 URL
*/
public function thumbnailToMasterUrl(string $thumbnailUrl): string
{
$temp = str_replace('/c/128x128', '', $thumbnailUrl);
$largeUrl = str_replace('square1200.jpg', 'master1200.jpg', $temp);
return $largeUrl;
}
/**
* 直リン可能な pixiv.cat のプロキシ URL に変換する
* HUGE THANKS TO PIXIV.CAT!
@ -49,45 +34,20 @@ class PixivResolver implements Resolver
return str_replace('i.pximg.net', 'i.pixiv.cat', $pixivUrl);
}
/**
* HTMLからタグとして利用可能な情報を抽出する
* @param string $html ページ HTML
* @return string[] タグ
*/
public function extractTags(string $html): array
{
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new \DOMXPath($dom);
$nodes = $xpath->query("//meta[@name='keywords']");
if ($nodes->length === 0) {
return [];
}
$keywords = $nodes->item(0)->getAttribute('content');
$tags = [];
foreach (mb_split(',', $keywords) as $keyword) {
$keyword = trim($keyword);
if (empty($keyword)) {
continue;
}
// 一部の固定キーワードは無視
if (array_search($keyword, ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true)) {
continue;
}
$tags[] = preg_replace('/\s/', '_', $keyword);
}
return $tags;
}
public function resolve(string $url): Metadata
{
if (preg_match('~www\.pixiv\.net/user/\d+/series/\d+~', $url, $matches)) {
$res = $this->client->get($url);
if ($res->getStatusCode() === 200) {
$metadata = $this->ogpResolver->parse($res->getBody());
$metadata->image = $this->proxize($metadata->image);
return $metadata;
} else {
throw new \RuntimeException("{$res->getStatusCode()}: $url");
}
}
parse_str(parse_url($url, PHP_URL_QUERY), $params);
$illustId = $params['illust_id'];
$page = 0;
@ -95,27 +55,31 @@ class PixivResolver implements Resolver
// 漫画ページページ数はmanga_bigならあるかも
if ($params['mode'] === 'manga_big' || $params['mode'] === 'manga') {
$page = $params['page'] ?? 0;
// 未ログインでは漫画ページを開けないため、URL を作品ページに変換する
$url = preg_replace('~mode=manga(_big)?~', 'mode=medium', $url);
}
$res = $this->client->get($url);
$res = $this->client->get('https://www.pixiv.net/ajax/illust/' . $illustId);
if ($res->getStatusCode() === 200) {
$metadata = $this->ogpResolver->parse($res->getBody());
$json = json_decode($res->getBody()->getContents(), true);
$metadata = new Metadata();
preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}(_p0)?_square1200\.jpg~", $res->getBody(), $match);
$illustThumbnailUrl = $match[0];
$metadata->title = $json['body']['illustTitle'] ?? '';
$metadata->description = '投稿者: ' . $json['body']['userName'] . PHP_EOL . strip_tags(str_replace('<br />', PHP_EOL, $json['body']['illustComment'] ?? ''));
$metadata->image = $this->proxize($json['body']['urls']['regular'] ?? '');
// ページ数の指定がある場合は画像URLをそのページにする
if ($page != 0) {
$illustThumbnailUrl = str_replace('_p0', '_p'.$page, $illustThumbnailUrl);
$metadata->image = str_replace('_p0', '_p'.$page, $metadata->image);
}
$illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl);
$metadata->image = $this->proxize($illustUrl);
$metadata->tags = $this->extractTags($res->getBody());
// タグ
if (!empty($json['body']['tags']['tags'])) {
foreach ($json['body']['tags']['tags'] as $tag) {
// 一部の固定キーワードは無視
if (array_search($tag['tag'], ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true) === false) {
$metadata->tags[] = preg_replace('/\s/', '_', $tag['tag']);
}
}
}
return $metadata;
} else {

View File

@ -0,0 +1,44 @@
<?php
namespace App\MetadataResolver;
use GuzzleHttp\Client;
class SteamResolver implements Resolver
{
/**
* @var Client
*/
private $client;
public function __construct(Client $client)
{
$this->client = $client;
}
public function resolve(string $url): Metadata
{
if (preg_match('~store\.steampowered\.com/app/(\d+)~', $url, $matches) !== 1) {
throw new \RuntimeException("Unmatched URL Pattern: $url");
}
$appid = $matches[1];
$res = $this->client->get('https://store.steampowered.com/api/appdetails/?l=japanese&appids=' . $appid);
if ($res->getStatusCode() === 200) {
$json = json_decode($res->getBody()->getContents(), true);
if ($json[$appid]['success'] === false) {
throw new \RuntimeException("API response [$appid][success] is false: $url");
}
$data = $json[$appid]['data'];
$metadata = new Metadata();
$metadata->title = $data['name'] ?? '';
$metadata->description = strip_tags(str_replace('<br />', PHP_EOL, html_entity_decode($data['short_description'] ?? '')));
$metadata->image = $data['header_image'] ?? '';
return $metadata;
} else {
throw new \RuntimeException("{$res->getStatusCode()}: $url");
}
}
}

View File

@ -11,6 +11,9 @@ class Tag extends Model
protected $fillable = [
'name'
];
protected $visible = [
'name'
];
public function ejaculations()
{

View File

@ -41,7 +41,7 @@ class User extends Authenticatable
{
$hash = md5(strtolower(trim($this->email)));
return '//www.gravatar.com/avatar/' . $hash . '?s=' . $size;
return '//www.gravatar.com/avatar/' . $hash . '?s=' . $size . '&d=retro';
}
/**

View File

@ -35,7 +35,7 @@ class Formatter
*/
public function linkify($text)
{
return $this->linkify->processUrls($text);
return $this->linkify->processUrls($text, ['attr' => ['target' => '_blank', 'rel' => 'noopener']]);
}
/**

View File

@ -50,7 +50,7 @@
"@php artisan package:discover"
],
"fix": [
"php-cs-fixer fix"
"php-cs-fixer fix --config=.php_cs.dist"
],
"test": [
"phpunit"

View File

@ -11,6 +11,7 @@
"stylelint": "stylelint resources/assets/sass/**/*"
},
"devDependencies": {
"@types/jquery": "^3.3.29",
"bootstrap": "^4.3.1",
"cal-heatmap": "^3.3.10",
"chart.js": "^2.7.1",
@ -28,7 +29,12 @@
"sass-loader": "^7.1.0",
"stylelint": "^9.10.1",
"stylelint-config-recess-order": "^2.0.1",
"vue-template-compiler": "^2.6.6"
"ts-loader": "^6.0.1",
"typescript": "^3.4.5",
"vue": "^2.6.10",
"vue-class-component": "^7.1.0",
"vue-property-decorator": "^8.1.1",
"vue-template-compiler": "^2.6.10"
},
"stylelint": {
"extends": "stylelint-config-recess-order"
@ -39,6 +45,13 @@
}
},
"lint-staged": {
"*.{css,scss}": ["stylelint --fix", "git add"]
"*.{css,scss}": [
"stylelint --fix",
"git add"
],
"*.php": [
"composer fix",
"git add"
]
}
}

View File

@ -1,58 +0,0 @@
function updateTags() {
$('input[name=tags]').val(
$('#tags')
.find('li')
.map(function () {
return $(this).data('value');
})
.get()
.join(' ')
);
}
function insertTag(value) {
$('<li class="list-inline-item badge badge-primary" style="cursor: pointer;"><span class="oi oi-tag"></span> <span></span> | x</li>')
.data('value', value)
.children(':last-child')
.text(value)
.end()
.appendTo('#tags');
}
var initTags = $('input[name=tags]').val();
if (initTags.trim() !== '') {
initTags.split(' ').forEach(function (value) {
insertTag(value);
});
}
$('#tagInput').on('keydown', function (ev) {
var $this = $(this);
if ($this.val().trim() !== '') {
switch (ev.key) {
case 'Tab':
case 'Enter':
case ' ':
if (ev.originalEvent.isComposing !== true) {
insertTag($this.val().trim());
$this.val('');
updateTags();
}
ev.preventDefault();
break;
}
} else if (ev.key === 'Enter') {
// 誤爆防止
ev.preventDefault();
}
});
$('#tags')
.on('click', 'li', function (ev) {
$(this).remove();
updateTags();
})
.parent()
.on('click', function (ev) {
$('#tagInput').focus();
});

View File

@ -0,0 +1,66 @@
import Vue from 'vue';
import TagInput from "./components/TagInput.vue";
import MetadataPreview from './components/MetadataPreview.vue';
export const bus = new Vue({name: "EventBus"});
export enum MetadataLoadState {
Inactive,
Loading,
Success,
Failed,
}
new Vue({
el: '#app',
data: {
metadata: null,
metadataLoadState: MetadataLoadState.Inactive,
},
components: {
TagInput,
MetadataPreview
},
mounted() {
// オカズリンクにURLがセットされている場合は、すぐにメタデータを取得する
const linkInput = this.$el.querySelector<HTMLInputElement>("#link");
if (linkInput && /^https?:\/\//.test(linkInput.value)) {
this.fetchMetadata(linkInput.value);
}
},
methods: {
// オカズリンクの変更時
onChangeLink(event: Event) {
if (event.target instanceof HTMLInputElement) {
const url = event.target.value;
if (url.trim() === '' || !/^https?:\/\//.test(url)) {
this.metadata = null;
this.metadataLoadState = MetadataLoadState.Inactive;
return;
}
this.fetchMetadata(url);
}
},
// メタデータの取得
fetchMetadata(url: string) {
this.metadataLoadState = MetadataLoadState.Loading;
$.ajax({
url: '/api/checkin/card',
method: 'get',
type: 'json',
data: {
url
}
}).then(data => {
this.metadata = data;
this.metadataLoadState = MetadataLoadState.Success;
}).catch(e => {
this.metadata = null;
this.metadataLoadState = MetadataLoadState.Failed;
});
}
}
});

View File

@ -0,0 +1,119 @@
<template>
<div class="form-row" v-if="state !== MetadataLoadState.Inactive">
<div class="form-group col-sm-12">
<div class="card link-card-mini mb-2 px-0">
<div v-if="state === MetadataLoadState.Loading" class="row no-gutters">
<div class="col-12">
<div class="card-body">
<h6 class="card-title text-center font-weight-bold text-info" style="font-size: small;"><span class="oi oi-loop-circular"></span> オカズの情報を読み込んでいます</h6>
</div>
</div>
</div>
<div v-else-if="state === MetadataLoadState.Success" class="row no-gutters">
<div v-if="hasImage" class="col-4 justify-content-center align-items-center">
<img :src="metadata.image" alt="Thumbnail" class="card-img-top-to-left bg-secondary">
</div>
<div :class="descClasses">
<div class="card-body">
<h6 class="card-title font-weight-bold" style="font-size: small;">{{ metadata.title }}</h6>
<template v-if="suggestions.length > 0">
<p class="card-text mb-2" style="font-size: small;">タグ候補<br><span class="text-secondary">(クリックするとタグ入力欄にコピーできます)</span></p>
<ul class="list-inline d-inline">
<li v-for="tag in suggestions"
class="list-inline-item badge badge-primary metadata-tag-item"
@click="addTag(tag)"><span class="oi oi-tag"></span> {{ tag }}</li>
</ul>
</template>
</div>
</div>
</div>
<div v-else class="row no-gutters">
<div class="col-12">
<div class="card-body">
<h6 class="card-title text-center font-weight-bold text-danger" style="font-size: small;"><span class="oi oi-circle-x"></span> オカズの情報を読み込めませんでした</h6>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import {Vue, Component, Prop} from "vue-property-decorator";
import {bus, MetadataLoadState} from "../checkin";
type Metadata = {
url: string,
title: string,
description: string,
image: string,
expires_at: string | null,
tags: {
name: string
}[],
};
@Component
export default class MetadataPreview extends Vue {
@Prop() readonly state!: MetadataLoadState;
@Prop() readonly metadata!: Metadata | null;
// for use in v-if
private readonly MetadataLoadState = MetadataLoadState;
addTag(tag: string) {
bus.$emit("add-tag", tag);
}
get suggestions() {
if (this.metadata === null) {
return [];
}
return this.metadata.tags.map(t => t.name);
}
get hasImage() {
return this.metadata !== null && this.metadata.image !== ''
}
get descClasses() {
return {
"col-8": this.hasImage,
"col-12": !this.hasImage,
};
}
}
</script>
<style lang="scss" scoped>
.link-card-mini {
$height: 150px;
.row > div {
overflow: hidden;
}
.row > div:first-child {
display: flex;
&:not([display=none]) {
min-height: $height;
img {
position: absolute;
}
}
}
.card-text {
white-space: pre-line;
}
}
.metadata-tag-item {
cursor: pointer;
user-select: none;
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<div :class="containerClass" @click="$refs.input.focus()">
<input :name="name" type="hidden" :value="tagValue">
<ul class="list-inline d-inline">
<li v-for="(tag, i) in tags"
class="list-inline-item badge badge-primary tag-item"
@click="removeTag(i)"><span class="oi oi-tag"></span> {{ tag }} | x</li>
</ul>
<input :id="id"
ref="input"
type="text"
class="tag-input"
v-model="buffer"
@keydown="onKeyDown">
</div>
</template>
<script lang="ts">
import {Vue, Component, Prop} from "vue-property-decorator";
import {bus} from "../checkin";
@Component
export default class TagInput extends Vue {
@Prop(String) readonly id!: string;
@Prop(String) readonly name!: string;
@Prop(String) readonly value!: string;
@Prop(Boolean) readonly isInvalid!: boolean;
tags: string[] = this.value.trim() !== "" ? this.value.trim().split(" ") : [];
buffer: string = "";
created() {
bus.$on("add-tag", (tag: string) => this.tags.indexOf(tag) === -1 && this.tags.push(tag));
}
onKeyDown(event: KeyboardEvent) {
if (this.buffer.trim() !== "") {
switch (event.key) {
case 'Tab':
case 'Enter':
case ' ':
if ((event as any).isComposing !== true) {
this.tags.push(this.buffer);
this.buffer = "";
}
event.preventDefault();
break;
}
} else if (event.key === "Enter") {
//
event.preventDefault();
}
}
removeTag(index: number) {
this.tags.splice(index, 1);
}
get containerClass(): object {
return {
"form-control": true,
"h-auto": true,
"is-invalid": this.isInvalid
};
}
get tagValue(): string {
return this.tags.join(" ");
}
}
</script>
<style lang="scss" scoped>
.tag-item {
cursor: pointer;
}
.tag-input {
border: 0;
outline: 0;
}
</style>

4
resources/assets/js/vue-shims.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}

View File

@ -1,8 +1,18 @@
.link-card {
.row > div:last-child {
.row > div {
max-height: 400px;
overflow: hidden;
}
.row > div:first-child {
display: flex;
&:not([display=none]) {
height: 400px;
}
}
.row > div:last-child {
// 省略を表す影を付けるやつ
&::before {
position: absolute;
@ -11,7 +21,7 @@
width: 100%;
height: 100%;
content: '';
background: linear-gradient(transparent 320px, white);
background: linear-gradient(rgba(255, 255, 255, 0) 320px, white);
}
}

View File

@ -1,7 +1,7 @@
<div class="card link-card mb-2 px-0 col-12 d-none" style="font-size: small;">
<a class="text-dark card-link" href="{{ $link }}" target="_blank" rel="noopener">
<div class="row no-gutters">
<div class="col-12 col-md-6">
<div class="col-12 col-md-6 justify-content-center align-items-center">
<img src="" alt="Thumbnail" class="card-img-top-to-left bg-secondary">
</div>
<div class="col-12 col-md-6">

View File

@ -8,7 +8,7 @@
@endif
<h6 class="font-weight-bold"><span class="oi oi-graph"></span> 概況</h6>
<p class="card-text mb-0">平均記録: {{ Formatter::formatInterval($summary[0]->average) }}</p>
<p class="card-text mb-0">平均記録: {{ Formatter::formatInterval($average[0]->average) }}</p>
<p class="card-text mb-0">最長記録: {{ Formatter::formatInterval($summary[0]->longest) }}</p>
<p class="card-text mb-0">最短記録: {{ Formatter::formatInterval($summary[0]->shortest) }}</p>
<p class="card-text mb-0">合計時間: {{ Formatter::formatInterval($summary[0]->total_times) }}</p>

View File

@ -3,7 +3,7 @@
@section('title', 'チェックイン')
@section('content')
<div class="container">
<div id="app" class="container">
<h2>今致してる?</h2>
<hr>
<div class="row justify-content-center mt-5">
@ -38,12 +38,8 @@
</div>
<div class="form-row">
<div class="form-group col-sm-12">
<input name="tags" type="hidden" value="{{ old('tags') ?? $defaults['tags'] }}">
<label for="tagInput"><span class="oi oi-tags"></span> タグ</label>
<div class="form-control h-auto {{ $errors->has('tags') ? ' is-invalid' : '' }}">
<ul id="tags" class="list-inline d-inline"></ul>
<input id="tagInput" type="text" style="outline: 0; border: 0;">
</div>
<tag-input id="tagInput" name="tags" value="{{ old('tags') ?? $defaults['tags'] }}" :is-invalid="{{ $errors->has('tags') ? 'true' : 'false' }}"></tag-input>
<small class="form-text text-muted">
Tab, Enter, 半角スペースのいずれかで入力確定します。
</small>
@ -56,7 +52,9 @@
<div class="form-row">
<div class="form-group col-sm-12">
<label for="link"><span class="oi oi-link-intact"></span> オカズリンク</label>
<input id="link" name="link" type="text" autocomplete="off" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}" placeholder="http://..." value="{{ old('link') ?? $defaults['link'] }}">
<input id="link" name="link" type="text" autocomplete="off" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}"
placeholder="http://..." value="{{ old('link') ?? $defaults['link'] }}"
@change="onChangeLink">
<small class="form-text text-muted">
オカズのURLを貼り付けて登録することができます。
</small>
@ -65,6 +63,7 @@
@endif
</div>
</div>
<metadata-preview :metadata="metadata" :state="metadataLoadState"></metadata-preview>
<div class="form-row">
<div class="form-group col-sm-12">
<label for="note"><span class="oi oi-comment-square"></span> ノート</label>

View File

@ -3,7 +3,7 @@
@section('title', 'チェックインの修正')
@section('content')
<div class="container">
<div id="app" class="container">
<h2>チェックインの修正</h2>
<hr>
<div class="row justify-content-center mt-5">
@ -39,12 +39,8 @@
</div>
<div class="form-row">
<div class="form-group col-sm-12">
<input name="tags" type="hidden" value="{{ old('tags') ?? $ejaculation->textTags() }}">
<label for="tagInput"><span class="oi oi-tags"></span> タグ</label>
<div class="form-control h-auto {{ $errors->has('tags') ? ' is-invalid' : '' }}">
<ul id="tags" class="list-inline d-inline"></ul>
<input id="tagInput" type="text" style="outline: 0; border: 0;">
</div>
<tag-input id="tagInput" name="tags" value="{{ old('tags') ?? $ejaculation->textTags() }}" :is-invalid="{{ $errors->has('tags') ? 'true' : 'false' }}"></tag-input>
<small class="form-text text-muted">
Tab, Enter, 半角スペースのいずれかで入力確定します。
</small>
@ -57,7 +53,9 @@
<div class="form-row">
<div class="form-group col-sm-12">
<label for="link"><span class="oi oi-link-intact"></span> オカズリンク</label>
<input id="link" name="link" type="text" autocomplete="off" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}" placeholder="http://..." value="{{ old('link') ?? $ejaculation->link }}">
<input id="link" name="link" type="text" autocomplete="off" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}"
placeholder="http://..." value="{{ old('link') ?? $ejaculation->link }}"
@change="onChangeLink">
<small class="form-text text-muted">
オカズのURLを貼り付けて登録することができます。
</small>
@ -66,6 +64,7 @@
@endif
</div>
</div>
<metadata-preview :metadata="metadata" :state="metadataLoadState"></metadata-preview>
<div class="form-row">
<div class="form-group col-sm-12">
<label for="note"><span class="oi oi-comment-square"></span> ノート</label>

View File

@ -18,48 +18,212 @@ class DLsiteResolverTest extends TestCase
}
}
public function testProduct()
public function testHome()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testProduct.html');
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testHome.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/maniax/work/=/product_id/RJ171695.html');
$this->assertEquals('【骨伝導風】道草屋 たびらこ-一緒にはみがき【耳かき&はみがき】', $metadata->title);
$this->assertStringEndsWith('少しお母さんっぽい店員さんに、歯磨きからおやすみまでお世話されます。はみがきで興奮しちゃった旦那様のも、しっかりお世話してくれます。歯磨き音は特殊なマイクを使用、骨伝導風ハイレゾバイノーラル音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ172000/RJ171695_img_main.jpg', $metadata->image);
$metadata = $this->resolver->resolve('https://www.dlsite.com/home/work/=/product_id/RJ221761.html');
$this->assertEquals('ひつじ、数えてあげるっ', $metadata->title);
$this->assertEquals('サークル名: Butterfly Dream' . PHP_EOL . '眠れないあなたに彼女が羊を数えてくれる音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ222000/RJ221761_img_main.jpg', $metadata->image);
$this->assertEquals(['癒し','バイノーラル/ダミヘ','日常/生活','ほのぼの','恋人同士'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/maniax/work/=/product_id/RJ171695.html', (string) $this->handler->getLastRequest()->getUri());
$this->assertSame('https://www.dlsite.com/home/work/=/product_id/RJ221761.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testProductSP()
public function testSoft()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testProductSP.html');
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testSoft.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/home/work/=/product_id/RJ234446.html');
$this->assertEquals('【大人向け耳かき】道草屋 はこべら5 時計修理のはこべらさん。他【汗の匂い】', $metadata->title);
$this->assertStringEndsWith('夏の終わり、二人で遠くの花火を眺めます。耳かきの他、クラシックシェービング、氷を含んだあまがみ、冷紅茶、ジャズ、時計の修理、それから大人向けの汗の匂い。色々な事のある、二泊三日の田舎宿音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ235000/RJ234446_img_main.jpg', $metadata->image);
$metadata = $this->resolver->resolve('https://www.dlsite.com/soft/work/=/product_id/VJ011276.html');
$this->assertEquals('ことのはアムリラート', $metadata->title);
$this->assertEquals('メーカー名: SukeraSparo' . PHP_EOL . '異世界へと迷い込んだ凜に救いの手を差し伸べるルカ――。これは、ふたりが手探りの意思疎通(ことのは)で織りなす、もどかしくも純粋な……女の子同士の物語。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/professional/VJ012000/VJ011276_img_main.jpg', $metadata->image);
$this->assertEquals(['少女','日常/生活','純愛','百合'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/home/work/=/product_id/RJ234446.html', (string) $this->handler->getLastRequest()->getUri());
$this->assertSame('https://www.dlsite.com/soft/work/=/product_id/VJ011276.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testProductShortLink()
public function testComic()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testProduct.html');
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testComic.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://dlsite.jp/mawtw/RJ171695.html');
$this->assertEquals('【骨伝導風】道草屋 たびらこ-一緒にはみがき【耳かき&はみがき】', $metadata->title);
$this->assertStringEndsWith('少しお母さんっぽい店員さんに、歯磨きからおやすみまでお世話されます。はみがきで興奮しちゃった旦那様のも、しっかりお世話してくれます。歯磨き音は特殊なマイクを使用、骨伝導風ハイレゾバイノーラル音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ172000/RJ171695_img_main.jpg', $metadata->image);
$metadata = $this->resolver->resolve('https://www.dlsite.com/comic/work/=/product_id/BJ138581.html');
$this->assertEquals('快楽ヒストリエ', $metadata->title);
$this->assertEquals('著者: 火鳥' . PHP_EOL . '天地創造と原初の人類を描いた「創世編」をはじめ、英雄たちの偉業を大真面目に考証した正真正銘の学術コミック全15編。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/books/BJ139000/BJ138581_img_main.jpg', $metadata->image);
$this->assertEquals(['おっぱい','ロリ','ショタ','妹','男性/おやじ','女王様/お姫様','王子様/王子系','戦士','セーラー服','着物/和服','青年コミック','ギャグ','コメディ','歴史/時代物','褐色/日焼け','爺'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://dlsite.jp/mawtw/RJ171695.html', (string) $this->handler->getLastRequest()->getUri());
$this->assertSame('https://www.dlsite.com/comic/work/=/product_id/BJ138581.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testManiax()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testManiax.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/maniax/work/=/product_id/RJ205445.html');
$this->assertEquals('催眠術で新婚人妻マナカさんとエッチしよう', $metadata->title);
$this->assertEquals('サークル名: デルタブレード' . PHP_EOL . '催眠術で新婚人妻マナカさんの愛する夫にすり替わって子作りラブラブエッチをするCG集です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ206000/RJ205445_img_main.jpg', $metadata->image);
$this->assertEquals(['断面図','人妻','中出し','妊娠/孕ませ','催眠','口内射精'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/maniax/work/=/product_id/RJ205445.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testPro()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testPro.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/pro/work/=/product_id/VJ008455.html');
$this->assertEquals('euphoria HDリマスター Best Price版', $metadata->title);
$this->assertEquals('ブランド名: CLOCK UP' . PHP_EOL . 'インモラルハードコアADV「euphoria」が高解像度1024×768版、「euphoria HDリマスター」となって登場', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/professional/VJ009000/VJ008455_img_main.jpg', $metadata->image);
$this->assertEquals(['アブノーマル','幼なじみ','女教師','退廃/背徳/インモラル','拘束','強制/無理矢理','スカトロ','アヘ顔','拷問','血液/流血','狂気'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/pro/work/=/product_id/VJ008455.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testBooks()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testBooks.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/books/work/=/product_id/BJ191317.html');
$this->assertEquals('永遠娘 vol.6', $metadata->title);
$this->assertEquals('著者: あまがえる / 玉之けだま / びんせん / 甘露アメ / 源五郎 / すみやお / 宇宙烏賊 / 毒茸人 / あやね / ガロウド / ハードボイルドよし子 / 夜歌 / 黒青郎君' . PHP_EOL . '君の命はどんな味なのだろうな?', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/books/BJ192000/BJ191317_img_main.jpg', $metadata->image);
$this->assertEquals(['ツンデレ','ロリ','妖怪','人外娘/モンスター娘','セーラー服','メイド','ストッキング','ファンタジー','ぶっかけ','中出し','近親相姦','アヘ顔','口内射精'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/books/work/=/product_id/BJ191317.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testGirls()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testGirls.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/girls/work/=/product_id/RJ217995.html');
$this->assertEquals('体イク教師', $metadata->title);
$this->assertEquals('サークル名: Dusk' . PHP_EOL . '思い込みの激しい体育教師に執着されるお話', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ218000/RJ217995_img_main.jpg', $metadata->image);
$this->assertEquals(['教師','中出し','陵辱','変態','強制/無理矢理','レイプ'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/girls/work/=/product_id/RJ217995.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testGirlsPro()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testGirlsPro.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/girls-pro/work/=/product_id/BJ170641.html');
$this->assertEquals('×××レクチャー', $metadata->title);
$this->assertEquals('著者: 江口尋' . PHP_EOL . '昔、告白してくれた地味な同級生・瀬尾は超人気セクシー男優になっていて!?', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/books/BJ171000/BJ170641_img_main.jpg', $metadata->image);
$this->assertEquals(['メガネ','芸能人/アイドル/モデル','俺様','ラブコメ','ラブラブ/あまあま','ティーンズラブ','調教','褐色/日焼け'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/girls-pro/work/=/product_id/BJ170641.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testBL()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testBL.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/bl/work/=/product_id/RJ244977.html');
$this->assertEquals('秘密に堕つ', $metadata->title);
$this->assertEquals('サークル名: ナゲットぶん投げ屋さん' . PHP_EOL . 'とある村に越してきた新婚夫婦。村の集会所で行われた歓迎会で犯される花婿。村の男達に犯され続けた花婿にある変化が…?', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ245000/RJ244977_img_main.jpg', $metadata->image);
$this->assertEquals(['既婚者','中出し','強制/無理矢理','レイプ','モブ姦'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/bl/work/=/product_id/RJ244977.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testEng()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testEng.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/eng/work/=/product_id/RE228866.html');
$this->assertEquals('With Your First Girlfriend, at a Ghostly Night [Ear Cleaning] [Sleep Sharing]', $metadata->title);
$this->assertEquals('Circle: Triangle!' . PHP_EOL . 'You go with a girl of your first love and enjoy going to haunted places and her massage, ear cleaning, sleep sharing etc. (CV: Yui Asami)', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ229000/RJ228866_img_main.jpg', $metadata->image);
$this->assertEquals(['Healing','Binaural','ASMR','Childhood Friend','Ear Cleaning','Romance'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/eng/work/=/product_id/RE228866.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testEcchiEng()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testEcchiEng.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/ecchi-eng/work/=/product_id/RE144678.html');
$this->assertEquals('NEKOPARA vol.1', $metadata->title);
$this->assertEquals('Circle: NEKO WORKs' . PHP_EOL . 'Chocolat and Vanilla star in a rich adult eroge series with E-mote system and animated H scenes', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ145000/RJ144678_img_main.jpg', $metadata->image);
$this->assertEquals(['Moe','Master and Servant','Funny Love Story','Nekomimi (Cat Ears)'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/ecchi-eng/work/=/product_id/RE144678.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testSPLink()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testHome.html');
// SP版touchのURLのテストだがリゾルバ側でURLから-touchを削除してPC版を取得するので、PC版の内容を使用する
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.dlsite.com/home-touch/work/=/product_id/RJ221761.html');
$this->assertEquals('ひつじ、数えてあげるっ', $metadata->title);
$this->assertEquals('サークル名: Butterfly Dream' . PHP_EOL . '眠れないあなたに彼女が羊を数えてくれる音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ222000/RJ221761_img_main.jpg', $metadata->image);
$this->assertEquals(['癒し','バイノーラル/ダミヘ','日常/生活','ほのぼの','恋人同士'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.dlsite.com/home/work/=/product_id/RJ221761.html', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testShortLink()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/DLsite/testHome.html');
$this->createResolver(DLsiteResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://dlsite.jp/howtw/RJ221761.html');
$this->assertEquals('ひつじ、数えてあげるっ', $metadata->title);
$this->assertEquals('サークル名: Butterfly Dream' . PHP_EOL . '眠れないあなたに彼女が羊を数えてくれる音声です。', $metadata->description);
$this->assertEquals('https://img.dlsite.jp/modpub/images2/work/doujin/RJ222000/RJ221761_img_main.jpg', $metadata->image);
$this->assertEquals(['癒し','バイノーラル/ダミヘ','日常/生活','ほのぼの','恋人同士'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://dlsite.jp/howtw/RJ221761.html', (string) $this->handler->getLastRequest()->getUri());
}
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace Tests\Unit\MetadataResolver;
use App\MetadataResolver\KomifloResolver;
use Tests\TestCase;
class KomifloResolverTest extends TestCase
{
use CreateMockedResolver;
public function setUp()
{
parent::setUp();
if (!$this->shouldUseMock()) {
sleep(1);
}
}
public function testComic()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/Komiflo/comic.json');
$this->createResolver(KomifloResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://komiflo.com/#!/comics/5490');
$this->assertEquals('魔法少女とえっち物語', $metadata->title);
$this->assertEquals('薙派 - メガストアα 19.07', $metadata->description);
$this->assertEquals('https://t.komiflo.com/564_mobile_large_3x/contents/23a4cd530060b8607aa434f4b299b249e71a4d5c.jpg', $metadata->image);
$this->assertEquals(['薙派','お姉さん','ショタ','ファンタジー','巨乳','野外・露出','羞恥'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://api.komiflo.com/content/id/5490', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testComicWithNoParents()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/Komiflo/comicWithNoParents.json');
$this->createResolver(KomifloResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://komiflo.com/#!/comics/3414');
$this->assertEquals('生まれなおしプログラム', $metadata->title);
$this->assertEquals('EROKI - ?', $metadata->description);
$this->assertEquals('https://t.komiflo.com/564_mobile_large_3x/contents/71cfb83640aead3cdd35e4329c4e2f427606a11d.jpg', $metadata->image);
$this->assertEquals(['EROKI','お姉さん','しつけ','オリジナル','ショートカット','逆転','巨乳'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://api.komiflo.com/content/id/3414', (string) $this->handler->getLastRequest()->getUri());
}
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace Tests\Unit\MetadataResolver;
use App\MetadataResolver\PixivResolver;
use Tests\TestCase;
class PixivResolverTest extends TestCase
{
use CreateMockedResolver;
public function setUp()
{
parent::setUp();
if (!$this->shouldUseMock()) {
sleep(1);
}
}
public function testIllust()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/Pixiv/illust.json');
$this->createResolver(PixivResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=68188073');
$this->assertEquals('coffee break', $metadata->title);
$this->assertEquals('投稿者: 裕' . PHP_EOL, $metadata->description);
$this->assertEquals('https://i.pixiv.cat/img-master/img/2018/04/12/00/01/28/68188073_p0_master1200.jpg', $metadata->image);
$this->assertEquals(['オリジナル','カフェ','眼鏡','イヤホン','ぱっつん','艶ぼくろ','眼鏡っ娘','オリジナル5000users入り'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.pixiv.net/ajax/illust/68188073', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testIllustMultiPages()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/Pixiv/illustMultiPages.json');
$this->createResolver(PixivResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=74939802');
$this->assertEquals('T-20S', $metadata->title);
$this->assertEquals('投稿者: amssc' . PHP_EOL . 'JUST FOR FUN' . PHP_EOL . '现在可以做到游戏内立绘修改拉!立绘动态皮肤都可以支持,想要资助获得新技术请站内信联系我。', $metadata->description);
$this->assertEquals('https://i.pixiv.cat/img-master/img/2019/05/28/01/16/24/74939802_p0_master1200.jpg', $metadata->image);
$this->assertEquals(['巨乳','母乳','lastorigin','Last_Origin','T-20S','おっぱい','라스트오리진','노움'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.pixiv.net/ajax/illust/74939802', (string) $this->handler->getLastRequest()->getUri());
}
}
public function testManga()
{
$responseText = file_get_contents(__DIR__.'/../../fixture/Pixiv/manga.json');
$this->createResolver(PixivResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://www.pixiv.net/member_illust.php?mode=medium&illust_id=46713544');
$this->assertEquals('冬の日ラブラブ', $metadata->title);
$this->assertEquals('投稿者: Aza' . PHP_EOL . 'ラブラブエッチのらくがき' . PHP_EOL . PHP_EOL . '三万フォロワー感謝します~' . PHP_EOL . PHP_EOL . '最近忙しいので、自分の時間が少ない・・・', $metadata->description);
$this->assertEquals('https://i.pixiv.cat/img-master/img/2014/10/25/00/06/58/46713544_p0_master1200.jpg', $metadata->image);
$this->assertEquals(['落書き','おっぱい','オリジナル','パイズリ','中出し','だいしゅきホールド','愛のあるセックス','黒髪ロング','オリジナル10000users入り'], $metadata->tags);
if ($this->shouldUseMock()) {
$this->assertSame('https://www.pixiv.net/ajax/illust/46713544', (string) $this->handler->getLastRequest()->getUri());
}
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Tests\Unit\MetadataResolver;
use App\MetadataResolver\SteamResolver;
use Tests\TestCase;
class SteamResolverTest extends TestCase
{
use CreateMockedResolver;
public function setUp()
{
parent::setUp();
if (!$this->shouldUseMock()) {
sleep(1);
}
}
public function test()
{
$responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/test.json');
$this->createResolver(SteamResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://store.steampowered.com/app/333600');
$this->assertEquals('NEKOPARA Vol. 1', $metadata->title);
$this->assertEquals('水無月嘉祥(みなづき かしょう)は伝統ある老舗和菓子屋である実家を出て、 パティシエとして自身のケーキ屋『ラ・ソレイユ』を一人で開店する。 しかし実家から送った引っ越し荷物の中に、 実家で飼っていた人型ネコのショコラとバニラが紛れ込んでいた。', $metadata->description);
$this->assertStringStartsWith('https://steamcdn-a.akamaihd.net/steam/apps/333600/header.jpg?t=', $metadata->image);
}
public function testR18()
{
$responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/testR18.json');
$this->createResolver(SteamResolver::class, $responseText);
$metadata = $this->resolver->resolve('https://store.steampowered.com/app/1077580');
$this->assertEquals('Broke Girl | 負債千金', $metadata->title);
$this->assertEquals('苦労知らずに育ったお嬢様は一夜にして1000万の借金を背負うことになった。借金を返済するために働かなければならない。しかし世間には悪意が満ちており、男達はお金で彼女を誘うか凌辱することしか考えていない。', $metadata->description);
$this->assertStringStartsWith('https://steamcdn-a.akamaihd.net/steam/apps/1077580/header.jpg?t=', $metadata->image);
}
public function testNotFound()
{
$this->expectException(\RuntimeException::class);
$responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/testNotFound.json');
$this->createResolver(SteamResolver::class, $responseText);
$this->resolver->resolve('https://store.steampowered.com/app/1');
}
}

View File

@ -1 +1 @@
* -text
* -text linguist-vendored

1995
tests/fixture/DLsite/testBL.html vendored Normal file

File diff suppressed because it is too large Load Diff

1953
tests/fixture/DLsite/testBooks.html vendored Normal file

File diff suppressed because it is too large Load Diff

2020
tests/fixture/DLsite/testComic.html vendored Normal file

File diff suppressed because it is too large Load Diff

1976
tests/fixture/DLsite/testEcchiEng.html vendored Normal file

File diff suppressed because it is too large Load Diff

1677
tests/fixture/DLsite/testEng.html vendored Normal file

File diff suppressed because it is too large Load Diff

2340
tests/fixture/DLsite/testGirls.html vendored Normal file

File diff suppressed because it is too large Load Diff

1744
tests/fixture/DLsite/testGirlsPro.html vendored Normal file

File diff suppressed because it is too large Load Diff

2159
tests/fixture/DLsite/testHome.html vendored Normal file

File diff suppressed because it is too large Load Diff

2262
tests/fixture/DLsite/testManiax.html vendored Normal file

File diff suppressed because it is too large Load Diff

2464
tests/fixture/DLsite/testPro.html vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=991">
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta name="google-site-verification" content="S2Jzwn_Dm4hGoyTfPnxEUSKnbHSuT73N6SZbTanWbEM" />
<link rel="apple-touch-icon" href="/images/web/common/apple_touch_icon_57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="/images/web/common/apple_touch_icon_72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/images/web/common/apple_touch_icon_76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/images/web/common/apple_touch_icon_114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/images/web/common/apple_touch_icon_120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/images/web/common/apple_touch_icon_144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/images/web/common/apple_touch_icon_152x152.png">
<meta name="msapplication-config" content="/browserconfig.xml" />
<link rel="shortcut icon" href="/images/web/common/favicon.ico">
<link rel="canonical" href="https://www.dlsite.com/maniax/work/=/product_id/RJ171695.html" />
<link rel="alternate" media="only screen and (max-width: 640px)" href="https://www.dlsite.com/maniax-touch/work/=/product_id/RJ171695.html" class="alternate_smartphone" />
<link rel="alternate" hreflang="ja" href="https://www.dlsite.com/maniax/work/=/product_id/RJ171695.html" />
<link rel="alternate" hreflang="en" href="https://www.dlsite.com/ecchi-eng/work/=/product_id/RE171695.html" /> <meta name="description" content="少しお母さんっぽい店員さんに、歯磨きからおやすみまでお世話されます。はみがきで興奮しちゃった旦那様のも、しっかりお世話してくれます。歯磨き音は特殊なマイクを使用、骨伝導風ハイレゾバイーラル音声です。「DLsite 同人 - R18」は同人誌・同人ゲーム・同人音声のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」">
<title>【骨伝導風】道草屋 たびらこ-一緒にはみがき【耳かき&amp;はみがき】 [桃色CODE] | DLsite 同人 - R18</title>
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@DLsiteManiax">
<meta name="twitter:image:src" content="https://img.dlsite.jp/modpub/images2/work/doujin/RJ172000/RJ171695_img_main.jpg" />
<meta property="og:title" content="【骨伝導風】道草屋 たびらこ-一緒にはみがき【耳かき&amp;はみがき】 [桃色CODE] | DLsite" />
<meta property="og:type" content="website" />
<meta property="og:description" content="少しお母さんっぽい店員さんに、歯磨きからおやすみまでお世話されます。はみがきで興奮しちゃった旦那様のも、しっかりお世話してくれます。歯磨き音は特殊なマイクを使用、骨伝導風ハイレゾバイーラル音声です。「DLsite 同人 - R18」は同人誌・同人ゲーム・同人音声のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」" />
<meta property="og:url" content="https://www.dlsite.com/maniax/work/=/product_id/RJ171695.html" />
<meta property="og:image" content="https://img.dlsite.jp/modpub/images2/work/doujin/RJ172000/RJ171695_img_sam.jpg" />
<meta property="og:site_name" content="DLsite" />
<meta property="fb:app_id" content="226115600829997" />
<meta property="mixi:content-rating" content="1" />
<meta property="mixi:device-smartphone" content="https://www.dlsite.com/maniax-touch/work/=/product_id/RJ171695.html" />
</head>
<body></body>
</html>

View File

@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" >
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta name="google-site-verification" content="S2Jzwn_Dm4hGoyTfPnxEUSKnbHSuT73N6SZbTanWbEM">
<link rel="apple-touch-icon" href="/images/web/common/apple_touch_icon_57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="/images/web/common/apple_touch_icon_72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/images/web/common/apple_touch_icon_76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/images/web/common/apple_touch_icon_114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/images/web/common/apple_touch_icon_120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/images/web/common/apple_touch_icon_144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/images/web/common/apple_touch_icon_152x152.png">
<meta name="msapplication-config" content="/browserconfig.xml" />
<link rel="shortcut icon" href="/images/web/common/favicon.ico">
<link rel="canonical" href="https://www.dlsite.com/maniax/work/=/product_id/RJ234446.html" />
<link rel="alternate" hreflang="ja" href="https://www.dlsite.com/maniax/work/=/product_id/RJ234446.html" />
<link rel="alternate" hreflang="en" href="https://www.dlsite.com/ecchi-eng/work/=/product_id/RE234446.html" /> <meta name="description" content="夏の終わり、二人で遠くの花火を眺めます。耳かきの他、クラシックシェービング、氷を含んだあまがみ、冷紅茶、ジャズ、時計の修理、それから大人向けの汗の匂い。色々な事のある、二泊三日の田舎宿音声です。「DLsite 同人 - R18」は同人誌・同人ゲーム・同人音声のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」">
<title>【大人向け耳かき】道草屋 はこべら5 時計修理のはこべらさん。他【汗の匂い】 [桃色CODE] | DLsite 同人 - R18</title>
<meta property="og:title" content="【大人向け耳かき】道草屋 はこべら5 時計修理のはこべらさん。他【汗の匂い】 [桃色CODE] | DLsite" />
<meta property="og:type" content="website" />
<meta property="og:description" content="夏の終わり、二人で遠くの花火を眺めます。耳かきの他、クラシックシェービング、氷を含んだあまがみ、冷紅茶、ジャズ、時計の修理、それから大人向けの汗の匂い。色々な事のある、二泊三日の田舎宿音声です。「DLsite 同人 - R18」は同人誌・同人ゲーム・同人音声のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」" />
<meta property="og:url" content="https://www.dlsite.com/maniax-touch/work/=/product_id/RJ234446.html" />
<meta property="og:image" content="https://img.dlsite.jp/modpub/images2/work/doujin/RJ235000/RJ234446_img_sam.jpg" />
<meta property="og:site_name" content="DLsite" />
<meta property="fb:app_id" content="226115600829997" />
<meta property="mixi:content-rating" content="1" />
</head>
<body></body>
</html>

2154
tests/fixture/DLsite/testSoft.html vendored Normal file

File diff suppressed because it is too large Load Diff

437
tests/fixture/Komiflo/comic.json vendored Normal file
View File

@ -0,0 +1,437 @@
{
"content": {
"attributes": {
"artists": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"name": "Artists"
},
"id": 2,
"name_read": "Artists",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.304746387Z",
"slug": "artists",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "薙派",
"name_en": "chiba",
"published": "",
"searchTerms": "ちば,チバ",
"tankoubonLabel": "",
"visibility": true
},
"id": 1722,
"name_read": "ちば",
"new_content_count": 0,
"pages": null,
"parent_id": 2,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303687274Z",
"slug": "chiba",
"source": "live",
"visibility": 1
}
]
},
"label": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "Labels",
"name_en": "",
"searchTerms": "",
"visibility": true
},
"id": 638,
"name_read": "",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.304743971Z",
"slug": "label",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "First double page",
"name_en": "",
"searchTerms": "",
"visibility": true
},
"id": 659,
"name_read": "",
"new_content_count": 0,
"pages": null,
"parent_id": 638,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.30368064Z",
"slug": "label-firstdoublepage",
"source": "live",
"visibility": 1
}
]
},
"tags": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"name": "Tags"
},
"id": 1,
"name_read": "Tags",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.304745145Z",
"slug": "tags",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "お姉さん",
"name_en": "Mature sister",
"published": "",
"searchTerms": "おねえさん,年上,おねーさん,オネエサン",
"tankoubonLabel": "",
"visibility": true
},
"id": 59,
"name_read": "おねえさん",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303682097Z",
"slug": "oneesan",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "ショタ",
"name_en": "Little boy",
"published": "",
"searchTerms": "しょた,ショタコン,小学生,中学生",
"tankoubonLabel": "",
"visibility": true
},
"id": 75,
"name_read": "しょた",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303683565Z",
"slug": "shota",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "ファンタジー",
"name_en": "",
"published": "",
"searchTerms": "ふぁんたじー,SF,妖怪",
"tankoubonLabel": "",
"visibility": true
},
"id": 98,
"name_read": "ふぁんたじー",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.30368434Z",
"slug": "fantasy",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "巨乳",
"name_en": "Big breasts",
"published": "",
"searchTerms": "きょにゅう,キョニュウ,爆乳",
"tankoubonLabel": "",
"visibility": true
},
"id": 37,
"name_read": "きょにゅう",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303686492Z",
"slug": "kyonyu",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "野外・露出",
"name_en": "In public",
"published": "",
"searchTerms": "やがい,ろしゅつ,露出狂,アオカン,青姦",
"tankoubonLabel": "",
"visibility": true
},
"id": 53,
"name_read": "やがい",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.30368814Z",
"slug": "yagai",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "羞恥",
"name_en": "Shy girl",
"published": "",
"searchTerms": "しゅうち,シュウチ,羞恥プレイ",
"tankoubonLabel": "",
"visibility": true
},
"id": 47,
"name_read": "しゅうち",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303688932Z",
"slug": "shuchi",
"source": "live",
"visibility": 1
}
]
},
"tags-hidden": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "Hidden tags",
"name_en": "",
"published": "",
"searchTerms": "",
"tankoubonLabel": "",
"visibility": true
},
"id": 783,
"name_read": "",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.304741513Z",
"slug": "tags-hidden",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "COMICメガストアαsearch",
"name_en": "",
"published": "",
"searchTerms": "メガストア,めがすとあ",
"tankoubonLabel": "",
"visibility": true
},
"id": 1009,
"name_read": "",
"new_content_count": 0,
"pages": null,
"parent_id": 783,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:56:11.303678935Z",
"slug": "megastore-search",
"source": "live",
"visibility": 1
}
]
}
},
"body": "",
"cdn_public": "https://cdn.komiflo.com/resized",
"cdn_thumbs": "",
"children": [],
"comments_count": 3,
"data": {
"category": "",
"censorship": "モザイク修正",
"download_type": "",
"isbn": "",
"link_amazon": "",
"link_dlsite": "",
"link_dmm": "",
"link_wani": "",
"msrp": "",
"naughty": "",
"restricted": "",
"size": "",
"title": "魔法少女とえっち物語",
"url": ""
},
"expiry": "2020-06-20T15:00:00Z",
"id": 5490,
"imgs": null,
"key_data": "",
"key_hash": "",
"liked": false,
"likes_count": 127,
"named_imgs": {
"cover": {
"id": 79325,
"original": 81185,
"width": 4299,
"height": 6071,
"ident": "cover",
"filename": "contents/23a4cd530060b8607aa434f4b299b249e71a4d5c.jpg",
"variants": [
"148_desktop_small",
"296_desktop_small_2x",
"198_desktop_medium",
"396_desktop_medium_2x",
"247_desktop_large",
"494_desktop_large_2x",
"160_mobile_narrow",
"320_mobile_narrow_2x",
"207_mobile_medium",
"414_mobile_medium_2x",
"188_mobile_large",
"376_mobile_large_2x",
"564_mobile_large_3x",
"346_mobile"
]
}
},
"page_count": 0,
"parents": [
{
"body": "",
"cdn_public": "",
"cdn_thumbs": "",
"data": {
"category": "",
"download_type": "",
"isbn": "",
"link_amazon": "",
"link_dlsite": "",
"link_dmm": "",
"link_wani": "",
"msrp": "780",
"release_date": "",
"size": "",
"title": "メガストアα 19.07",
"url": ""
},
"expiry": "2020-06-20T15:00:00Z",
"id": 5474,
"likes_count": 0,
"page_count": null,
"premium": false,
"public": false,
"published": "2019-06-20T15:00:00Z",
"reading_lists": null,
"signature": "",
"signature_expires": "2019-06-27T02:56:11Z",
"slug": null,
"source": "cache",
"type": "volume"
}
],
"premium": false,
"public": true,
"published": "2019-06-20T15:00:00Z",
"reading_lists": [],
"signature": "?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4ua29taWZsby5jb20vKi9jb250ZW50cy8qIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIzOS4xMTEuMjE4LjE2MC8zMiJ9LCJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTU2MTYwNDE3MX19fV19&Signature=ilu4WlHoMMecmk8Ab3UuJ3LBTe~FhQxoGVdPbBF9CTrTB-Teockvf43MgWuAzWgsfFrwmCeV-hedV-iEx07B3S~D7ObXWCFcbPd1rb12D0qY~NF2SfGTv8lIbCDMQkc9wyUtE5K4MlZ35Bm4mZRv9HtEZkX1yjkVuAV7sBScBfJUkfnlg6yYsL2d2g4tDkN8gCOjZChUODetZPm05qwTmItIbq0kQhirgXNV~R1z~kFRwsgoBYClCq3vpQCsCy7tbKGmzHz6ku-PgpopqsOCmAaCl9Jh4D2pw8R64aREw6SX4tSoe7NPKG4KbtLzBsio260luuORDeaFcTjvlQI0~g__&Key-Pair-Id=APKAIILYVN5NFPDL7WIA",
"signature_expires": "2019-06-27T02:56:11Z",
"slug": null,
"source": "live",
"type": "chapter"
},
"success": true
}

View File

@ -0,0 +1,298 @@
{
"content": {
"attributes": {
"artists": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"name": "Artists"
},
"id": 2,
"name_read": "Artists",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.176026561Z",
"slug": "artists",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "EROKI",
"name_en": "eroki",
"published": "",
"searchTerms": "えろき,エロキ",
"tankoubonLabel": "",
"visibility": true
},
"id": 836,
"name_read": "えろき",
"new_content_count": 0,
"pages": null,
"parent_id": 2,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174698472Z",
"slug": "eroki",
"source": "live",
"visibility": 1
}
]
},
"tags": {
"meta": {
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"name": "Tags"
},
"id": 1,
"name_read": "Tags",
"new_content_count": 0,
"pages": null,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.176028723Z",
"slug": "tags",
"source": "live",
"visibility": 1
},
"children": [
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "お姉さん",
"name_en": "Mature sister",
"published": "",
"searchTerms": "おねえさん,年上,おねーさん,オネエサン",
"tankoubonLabel": "",
"visibility": true
},
"id": 59,
"name_read": "おねえさん",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174699935Z",
"slug": "oneesan",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "しつけ",
"name_en": "Discipline",
"published": "",
"searchTerms": "しつけ,躾,シツケ",
"tankoubonLabel": "",
"visibility": true
},
"id": 69,
"name_read": "しつけ",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174701095Z",
"slug": "shitsuke",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "オリジナル",
"name_en": "",
"published": "",
"searchTerms": "おりじなる,オリジナル",
"tankoubonLabel": "",
"visibility": true
},
"id": 534,
"name_read": "おりじなる",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174702761Z",
"slug": "original",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "ショートカット",
"name_en": "",
"published": "",
"searchTerms": "ショートヘアー,ショート,しょーと,しょーとへあ",
"tankoubonLabel": "",
"visibility": true
},
"id": 798,
"name_read": "しょーとかっと",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174703509Z",
"slug": "shorthair",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "逆転",
"name_en": "",
"published": "",
"searchTerms": "ぎゃくてん,女性優位,ギャクテン",
"tankoubonLabel": "",
"visibility": true
},
"id": 74,
"name_read": "ぎゃくてん",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174705548Z",
"slug": "gyakuten",
"source": "live",
"visibility": 1
},
{
"cdn_public": "",
"cdn_thumbs": "",
"content_count": 0,
"data": {
"href": "",
"ipRestrict": "",
"name": "巨乳",
"name_en": "Big breasts",
"published": "",
"searchTerms": "きょにゅう,キョニュウ,爆乳",
"tankoubonLabel": "",
"visibility": true
},
"id": 37,
"name_read": "きょにゅう",
"new_content_count": 0,
"pages": null,
"parent_id": 1,
"published": null,
"signature": "",
"signature_expires": "2019-06-26T14:50:55.174706294Z",
"slug": "kyonyu",
"source": "live",
"visibility": 1
}
]
}
},
"body": "",
"cdn_public": "https://cdn.komiflo.com/resized",
"cdn_thumbs": "",
"children": [],
"comments_count": 26,
"data": {
"category": "",
"censorship": "黒棒による修正",
"download_type": "",
"isbn": "",
"link_amazon": "",
"link_dlsite": "",
"link_dmm": "",
"link_wani": "",
"msrp": "",
"naughty": "",
"restricted": "",
"size": "",
"title": "生まれなおしプログラム",
"url": ""
},
"expiry": null,
"id": 3414,
"imgs": null,
"key_data": "",
"key_hash": "",
"liked": false,
"likes_count": 627,
"named_imgs": {
"cover": {
"id": 49645,
"original": 50622,
"width": 4299,
"height": 6071,
"ident": "cover",
"filename": "contents/71cfb83640aead3cdd35e4329c4e2f427606a11d.jpg",
"variants": [
"148_desktop_small",
"296_desktop_small_2x",
"198_desktop_medium",
"396_desktop_medium_2x",
"247_desktop_large",
"494_desktop_large_2x",
"160_mobile_narrow",
"320_mobile_narrow_2x",
"207_mobile_medium",
"414_mobile_medium_2x",
"188_mobile_large",
"376_mobile_large_2x",
"564_mobile_large_3x",
"346_mobile"
]
}
},
"page_count": 0,
"parents": [],
"premium": false,
"public": true,
"published": "2018-04-10T15:00:00Z",
"reading_lists": [],
"signature": "?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4ua29taWZsby5jb20vKi9jb250ZW50cy8qIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIzOS4xMTEuMjE4LjE2MC8zMiJ9LCJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTU2MTYwMzg1NX19fV19&Signature=bZFuvU1rgv2iBSSFlxyoexOIjjacWW4Sxe--EEjI2ruQPNnZE8iU542yCsWBSrmHfFOXFcYNKIf3PmTAxwjS-CeoyRc~O0VO6T9bNdlinFICMezNTPlYe0Ri~nUWxQ8Oy364ik5zrd5RwHmEOVMjfuc96N6ivrcL9Q5tfi-2sFs~8S9m-IH76Kf7dLXn8~TRPfGFj8bfyoDcn42YfCvfXzl4D92EnKjQO52x2~KICQR3X7igirQ6X1GmuYEoJd9GAYZlKNKUEQch7T6dpR-uJZEJ5hOJDsWrIJkvoMu9ZTBgdZOZGuNLfWunAJ0NhovNlN6-D8PmlhSd79Mu0P2LUA__&Key-Pair-Id=APKAIILYVN5NFPDL7WIA",
"signature_expires": "2019-06-27T02:50:55Z",
"slug": null,
"source": "live",
"type": "chapter"
},
"success": true
}

824
tests/fixture/Pixiv/illust.json vendored Normal file
View File

@ -0,0 +1,824 @@
{
"error": false,
"message": "",
"body": {
"illustId": "68188073",
"illustTitle": "coffee break",
"illustComment": "",
"id": "68188073",
"title": "coffee break",
"description": "",
"illustType": 0,
"createDate": "2018-04-11T15:01:28+00:00",
"uploadDate": "2018-04-11T15:01:28+00:00",
"restrict": 0,
"xRestrict": 0,
"sl": 2,
"urls": {
"mini": "https://i.pximg.net/c/48x48/img-master/img/2018/04/12/00/01/28/68188073_p0_square1200.jpg",
"thumb": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/04/12/00/01/28/68188073_p0_square1200.jpg",
"small": "https://i.pximg.net/c/540x540_70/img-master/img/2018/04/12/00/01/28/68188073_p0_master1200.jpg",
"regular": "https://i.pximg.net/img-master/img/2018/04/12/00/01/28/68188073_p0_master1200.jpg",
"original": "https://i.pximg.net/img-original/img/2018/04/12/00/01/28/68188073_p0.jpg"
},
"tags": {
"authorId": "17810",
"isLocked": false,
"tags": [
{
"tag": "オリジナル",
"locked": true,
"deletable": false,
"userId": "17810",
"romaji": "orijinaru",
"translation": {
"en": "original"
},
"userName": "裕"
},
{
"tag": "カフェ",
"locked": true,
"deletable": false,
"userId": "17810",
"romaji": "kafe",
"translation": {
"en": "cafe"
},
"userName": "裕"
},
{
"tag": "眼鏡",
"locked": true,
"deletable": false,
"userId": "17810",
"romaji": "megane",
"translation": {
"en": "glasses"
},
"userName": "裕"
},
{
"tag": "イヤホン",
"locked": true,
"deletable": false,
"userId": "17810",
"romaji": "iyahonn",
"translation": {
"en": "earphones"
},
"userName": "裕"
},
{
"tag": "ぱっつん",
"locked": false,
"deletable": false,
"romaji": "pattsunn",
"translation": {
"en": "straight fringe"
}
},
{
"tag": "艶ぼくろ",
"locked": false,
"deletable": false,
"romaji": "tsuyabokuro"
},
{
"tag": "眼鏡っ娘",
"locked": false,
"deletable": false,
"romaji": "meganekko",
"translation": {
"en": "girl with glasses"
}
},
{
"tag": "オリジナル5000users入り",
"locked": false,
"deletable": false,
"romaji": "orijinarugosennyu-za-zuiri",
"translation": {
"en": "original 5000+ bookmarks"
}
}
],
"writable": false
},
"storableTags": [
"RTJMXD26Ak",
"-UnxstvmLW",
"Nbvc4l7O_x",
"FTUtcpiOkA",
"w0fH70xUZS",
"27uevOlfIe",
"Sjwi7bh6-s",
"_pwIgrV8TB"
],
"userId": "17810",
"userName": "裕",
"userAccount": "youcapriccio",
"userIllusts": {
"14053843": null,
"14053937": null,
"14054027": null,
"14054186": null,
"14062828": null,
"14477076": null,
"14792405": null,
"16046742": null,
"16138239": null,
"16352926": null,
"16452748": null,
"16915557": null,
"17083628": null,
"17210510": null,
"17386995": null,
"17423518": null,
"17448062": null,
"17543415": null,
"17568036": null,
"17593779": null,
"17619003": null,
"17628888": null,
"17698823": null,
"17817803": null,
"17942662": null,
"18161965": null,
"18212527": null,
"18837942": null,
"19413060": null,
"19692459": null,
"19966924": null,
"19972770": null,
"20324120": null,
"20340204": null,
"20366995": null,
"20471558": null,
"20602724": null,
"20604539": null,
"20688177": null,
"21091157": null,
"21458619": null,
"21465117": null,
"21499486": null,
"21761917": null,
"22045640": null,
"22123124": null,
"22197758": null,
"22218971": null,
"22234319": null,
"22283588": null,
"22646212": null,
"22671292": null,
"23077173": null,
"23652482": null,
"24064845": null,
"24665326": null,
"24679135": null,
"24712190": null,
"24947762": null,
"25329936": null,
"26366272": null,
"27393935": null,
"27485745": null,
"27666949": null,
"28259132": null,
"28342787": null,
"28472420": null,
"28542432": null,
"28802580": null,
"28944777": null,
"29191265": null,
"29205875": null,
"29684473": null,
"29783263": null,
"30192166": null,
"31110886": null,
"31537645": null,
"32646946": null,
"32750353": null,
"33202416": null,
"33395376": null,
"33440266": null,
"35365709": null,
"35460263": null,
"36004858": null,
"36165748": null,
"36700962": null,
"36701188": null,
"36701484": null,
"36701689": null,
"37016640": null,
"37095482": null,
"37547592": null,
"39164365": null,
"40884078": null,
"41559080": null,
"46072865": null,
"46201289": null,
"46278624": null,
"47055452": null,
"47778617": null,
"48069391": null,
"48695249": null,
"48803034": null,
"49208325": null,
"49928045": null,
"51884036": null,
"51945556": null,
"52323083": null,
"52335660": null,
"52420382": null,
"52665902": null,
"52698908": null,
"52879266": null,
"53242280": null,
"53349656": null,
"53416534": null,
"53539911": null,
"53691135": null,
"53883574": null,
"53883648": null,
"54260186": null,
"54772276": null,
"54804756": null,
"54928943": null,
"54959965": null,
"55189849": null,
"55486830": null,
"55608689": null,
"55624737": null,
"55722012": null,
"55758248": null,
"55882194": null,
"56678994": null,
"57209033": null,
"57249918": null,
"57330537": null,
"57405593": null,
"57420595": null,
"57775178": null,
"58076340": null,
"59119603": null,
"59261109": null,
"59561361": null,
"59575686": null,
"60021663": null,
"60053226": null,
"60083767": null,
"60421993": null,
"60619841": null,
"60865442": null,
"61015613": null,
"61198859": null,
"61367766": null,
"61544285": null,
"61717134": null,
"61824584": null,
"61914664": null,
"62114491": null,
"62226468": null,
"62991520": null,
"63100455": null,
"63227860": null,
"63515109": null,
"63867496": null,
"64082433": null,
"64304193": null,
"64516472": null,
"64723379": null,
"64930347": null,
"64975155": null,
"65195542": null,
"65405890": null,
"65655985": null,
"65671343": null,
"65690745": null,
"65706774": null,
"65736319": null,
"65982587": null,
"66005055": null,
"66106458": null,
"66414630": null,
"66494466": null,
"66595810": null,
"66681398": null,
"66700481": null,
"66716698": null,
"66772099": null,
"67134385": null,
"67148315": null,
"67207903": null,
"67496395": null,
"67656921": null,
"67868039": null,
"67881973": null,
"67882087": {
"illustId": "67882087",
"illustTitle": "魔龍",
"id": "67882087",
"title": "魔龍",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/03/24/00/05/13/67882087_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"ドラゴン",
"魔龍",
"仕事絵"
],
"userId": "17810",
"userName": "裕",
"width": 1494,
"height": 1000,
"pageCount": 2,
"isBookmarkable": null,
"bookmarkData": null
},
"67932654": {
"illustId": "67932654",
"illustTitle": "武器デザイン",
"id": "67932654",
"title": "武器デザイン",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/03/27/00/16/43/67932654_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"仕事絵",
"ファンタジー",
"武器"
],
"userId": "17810",
"userName": "裕",
"width": 1383,
"height": 1573,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"67932696": {
"illustId": "67932696",
"illustTitle": "ファンタジーキャラ×6",
"id": "67932696",
"title": "ファンタジーキャラ×6",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/03/27/00/18/33/67932696_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"仕事絵",
"ファンタジー",
"デフォルメ",
"SD"
],
"userId": "17810",
"userName": "裕",
"width": 970,
"height": 812,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"67947316": {
"illustId": "67947316",
"illustTitle": "春ピンク🌸",
"id": "67947316",
"title": "春ピンク🌸",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/03/28/00/05/33/67947316_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"女の子",
"ファッション",
"カチューシャ編み",
"ピアス",
"アイシャドウ",
"マニキュア",
"茶髪"
],
"userId": "17810",
"userName": "裕",
"width": 1173,
"height": 1227,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68064045": {
"illustId": "68064045",
"illustTitle": "Girls🌸",
"id": "68064045",
"title": "Girls🌸",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/04/04/00/00/32/68064045_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"ガールズイラスト",
"ファッション",
"ピアス",
"アイシャドウ",
"マニキュア",
"茶髪",
"パーマ"
],
"userId": "17810",
"userName": "裕",
"width": 800,
"height": 1148,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68146376": {
"illustId": "68146376",
"illustTitle": "ねこ娘",
"id": "68146376",
"title": "ねこ娘",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/04/09/00/14/20/68146376_p0_square1200.jpg",
"description": "",
"tags": [
"ゲゲゲの鬼太郎",
"ねこ娘",
"6期猫娘",
"ゲゲゲの鬼太郎1000users入り"
],
"userId": "17810",
"userName": "裕",
"width": 1200,
"height": 1697,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68188073": {
"illustId": "68188073",
"illustTitle": "coffee break",
"id": "68188073",
"title": "coffee break",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/04/12/00/01/28/68188073_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"カフェ",
"眼鏡",
"イヤホン",
"ぱっつん",
"艶ぼくろ",
"眼鏡っ娘",
"オリジナル5000users入り"
],
"userId": "17810",
"userName": "裕",
"width": 1200,
"height": 842,
"pageCount": 1,
"isBookmarkable": true,
"bookmarkData": null
},
"68232025": {
"illustId": "68232025",
"illustTitle": "木漏れ日",
"id": "68232025",
"title": "木漏れ日",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/04/15/00/07/57/68232025_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"女の子",
"木漏れ日",
"猫",
"オフショルダー",
"猫と女の子",
"オリジナル500users入り"
],
"userId": "17810",
"userName": "裕",
"width": 1200,
"height": 1446,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68561488": {
"illustId": "68561488",
"illustTitle": "雨上がりとJK",
"id": "68561488",
"title": "雨上がりとJK",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/05/04/00/38/19/68561488_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"女子高生",
"コミティア",
"COMITIA124",
"制服",
"白ハイソックス",
"魅惑のすね",
"ロングヘアー",
"オリジナル10000users入り"
],
"userId": "17810",
"userName": "裕",
"width": 600,
"height": 767,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68625248": {
"illustId": "68625248",
"illustTitle": "ドット柄×眼鏡",
"id": "68625248",
"title": "ドット柄×眼鏡",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/05/07/00/57/20/68625248_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"女の子",
"女子高生",
"ドット柄",
"眼鏡",
"制服",
"腕時計",
"リュックサック",
"リボン",
"オリジナル5000users入り"
],
"userId": "17810",
"userName": "裕",
"width": 600,
"height": 848,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68684760": {
"illustId": "68684760",
"illustTitle": "告白の日",
"id": "68684760",
"title": "告白の日",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/05/11/00/00/14/68684760_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"仕事絵",
"女子高生",
"制服",
"カルピス",
"ラブレター",
"カルピスウォーター",
"オリジナル1000users入り"
],
"userId": "17810",
"userName": "裕",
"width": 1400,
"height": 700,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68780252": {
"illustId": "68780252",
"illustTitle": "たとえばお伽噺に出てくるような、そんな魔法使い",
"id": "68780252",
"title": "たとえばお伽噺に出てくるような、そんな魔法使い",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/05/17/00/03/26/68780252_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"仕事絵",
"蒼空",
"オリジナル500users入り"
],
"userId": "17810",
"userName": "裕",
"width": 800,
"height": 1141,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"68936315": {
"illustId": "68936315",
"illustTitle": "謎のヒロインX",
"id": "68936315",
"title": "謎のヒロインX",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/05/27/00/01/02/68936315_p0_square1200.jpg",
"description": "",
"tags": [
"Fate/GrandOrder",
"謎のヒロインX",
"FGO",
"Fate/GO1000users入り",
"FGOイラコン2"
],
"userId": "17810",
"userName": "裕",
"width": 2893,
"height": 4092,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"69000379": null,
"69045498": null,
"69138520": null,
"69204438": null,
"69263984": null,
"69311774": null,
"69326765": null,
"69340502": null,
"69390965": null,
"69419351": null,
"69498750": null,
"69755373": null,
"69781341": null,
"69972875": null,
"70042642": null,
"70272492": null,
"70419208": null,
"70959974": null,
"70992219": null,
"71006962": null,
"71022606": null,
"71056067": null,
"71076458": null,
"71094391": null,
"71274492": null,
"71462679": null,
"72235293": null,
"72480342": null,
"72514297": null,
"72535044": null,
"72551222": null,
"72565887": null,
"72581189": null,
"72596181": null,
"72611658": null,
"72629786": null,
"72648764": null,
"72668158": null,
"72683532": null,
"72698000": null,
"72712777": null,
"72744221": null,
"72764549": null,
"72780210": null,
"72795236": null,
"72810723": null,
"72826398": null,
"72841779": null,
"72859874": null,
"72879945": null,
"72894635": null,
"73169245": null,
"73169325": null,
"73206108": null,
"73600652": null,
"74143168": null,
"74157207": null,
"74170787": null,
"74187191": null,
"74208185": null,
"74223553": null,
"74251605": null,
"74265532": null,
"74451789": null,
"74478687": null,
"74502113": null,
"74542366": null,
"74650363": null,
"74664239": null,
"74666682": null,
"74791171": null,
"74827564": null,
"75226739": null,
"75242973": null
},
"likeData": false,
"width": 1200,
"height": 842,
"pageCount": 1,
"bookmarkCount": 5431,
"likeCount": 4324,
"commentCount": 10,
"responseCount": 0,
"viewCount": 35092,
"isHowto": false,
"isOriginal": true,
"imageResponseOutData": [],
"imageResponseData": [],
"imageResponseCount": 0,
"pollData": null,
"seriesNavData": null,
"descriptionBoothId": null,
"descriptionYoutubeId": null,
"comicPromotion": null,
"contestBanners": [],
"factoryGoods": {
"integratable": true,
"integrated": false
},
"isBookmarkable": true,
"bookmarkData": null,
"contestData": null,
"zoneConfig": {
"responsive": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_responsive&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdceqt404kl9&num=5d06c0df289"
},
"300x250": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_rectangle&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdcett5g1ucx&num=5d06c0df449"
},
"header": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=header&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdcewbo66sio&num=5d06c0df704"
},
"footer": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=footer&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdceypre876g&num=5d06c0df256"
},
"expandedFooter": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=multiple_illust_viewer&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdcf11vpcj6t&num=5d06c0df904"
},
"logo": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=logo_side&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdcf3cd2h2z3&num=5d06c0df383"
},
"500x500": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=bigbanner&format=js&s=0&up=0&ng=w&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg43qwdcf5o97vzyt&num=5d06c0df945"
}
},
"extraData": {
"meta": {
"title": "【オリジナル】「coffee break」/「裕」のイラスト [pixiv]",
"description": "この作品 「coffee break」 は 「オリジナル」「カフェ」 等のタグがつけられた「裕」さんのイラストです。 「」",
"keywords": "オリジナル,カフェ,眼鏡,イヤホン,ぱっつん,艶ぼくろ,眼鏡っ娘,オリジナル5000users入り,イラスト,pixiv,ピクシブ",
"canonical": "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=68188073"
}
},
"noLoginData": {
"breadcrumbs": [
"創作",
"オリジナル"
],
"zengoIdWorks": {
"prev": {
"id": "68188072",
"title": "Winter Soldier_Infinity War ver."
},
"next": {
"id": "68188074",
"title": "【腐】翔太受けまとめ"
}
}
}
}
}

View File

@ -0,0 +1,227 @@
{
"error": false,
"message": "",
"body": {
"illustId": "74939802",
"illustTitle": "T-20S",
"illustComment": "JUST FOR FUN<br />现在可以做到游戏内立绘修改拉!立绘动态皮肤都可以支持,想要资助获得新技术请站内信联系我。",
"id": "74939802",
"title": "T-20S",
"description": "JUST FOR FUN<br />现在可以做到游戏内立绘修改拉!立绘动态皮肤都可以支持,想要资助获得新技术请站内信联系我。",
"illustType": 0,
"createDate": "2019-05-27T16:16:24+00:00",
"uploadDate": "2019-05-27T16:16:24+00:00",
"restrict": 0,
"xRestrict": 1,
"sl": 6,
"urls": {
"mini": "https://i.pximg.net/c/48x48/img-master/img/2019/05/28/01/16/24/74939802_p0_square1200.jpg",
"thumb": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2019/05/28/01/16/24/74939802_p0_square1200.jpg",
"small": "https://i.pximg.net/c/540x540_70/img-master/img/2019/05/28/01/16/24/74939802_p0_master1200.jpg",
"regular": "https://i.pximg.net/img-master/img/2019/05/28/01/16/24/74939802_p0_master1200.jpg",
"original": "https://i.pximg.net/img-original/img/2019/05/28/01/16/24/74939802_p0.jpg"
},
"tags": {
"authorId": "17702579",
"isLocked": false,
"tags": [
{
"tag": "R-18",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": null,
"userName": "amssc"
},
{
"tag": "巨乳",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": "kyonyuu",
"translation": {
"en": "large breasts"
},
"userName": "amssc"
},
{
"tag": "母乳",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": "bonyuu",
"translation": {
"en": "breast milk"
},
"userName": "amssc"
},
{
"tag": "lastorigin",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": null,
"userName": "amssc"
},
{
"tag": "Last_Origin",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": null,
"userName": "amssc"
},
{
"tag": "T-20S",
"locked": true,
"deletable": false,
"userId": "17702579",
"romaji": null,
"userName": "amssc"
},
{
"tag": "おっぱい",
"locked": false,
"deletable": false,
"romaji": "oppai",
"translation": {
"en": "breasts"
}
},
{
"tag": "라스트오리진",
"locked": false,
"deletable": false,
"romaji": null
},
{
"tag": "노움",
"locked": false,
"deletable": false,
"romaji": null
}
],
"writable": false
},
"storableTags": [
"0xsDLqCEW6",
"5oPIfUbtd6",
"zZZn32I7eS",
"NLCPvW6hqg",
"uMloBPsM69",
"4HYAnF33v5",
"Ie2c51_4Sp",
"I8DVKb4T8n",
"HAtQGc-2dA"
],
"userId": "17702579",
"userName": "amssc",
"userAccount": "amsscggy",
"userIllusts": {
"74939802": {
"illustId": "74939802",
"illustTitle": "T-20S",
"id": "74939802",
"title": "T-20S",
"illustType": 0,
"xRestrict": 1,
"restrict": 0,
"sl": 6,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2019/05/28/01/16/24/74939802_p0_square1200.jpg",
"description": "JUST FOR FUN<br />现在可以做到游戏内立绘修改拉!立绘动态皮肤都可以支持,想要资助获得新技术请站内信联系我。",
"tags": [
"R-18",
"巨乳",
"母乳",
"lastorigin",
"Last_Origin",
"T-20S",
"おっぱい",
"라스트오리진",
"노움"
],
"userId": "17702579",
"userName": "amssc",
"width": 1842,
"height": 3461,
"pageCount": 2,
"isBookmarkable": true,
"bookmarkData": null
}
},
"likeData": false,
"width": 1842,
"height": 3461,
"pageCount": 2,
"bookmarkCount": 1874,
"likeCount": 843,
"commentCount": 18,
"responseCount": 0,
"viewCount": 15890,
"isHowto": false,
"isOriginal": false,
"imageResponseOutData": [],
"imageResponseData": [],
"imageResponseCount": 0,
"pollData": null,
"seriesNavData": null,
"descriptionBoothId": null,
"descriptionYoutubeId": null,
"comicPromotion": null,
"contestBanners": [],
"factoryGoods": {
"integratable": false,
"integrated": false
},
"isBookmarkable": true,
"bookmarkData": null,
"contestData": null,
"zoneConfig": {
"responsive": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_responsive&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1bldte0zwn&num=5d124549863"
},
"300x250": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_rectangle&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1bolgkimxn&num=5d124549198"
},
"500x500": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=bigbanner&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1br3q3ejn9&num=5d124549470"
},
"header": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=header&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1bthomvkhj&num=5d124549448"
},
"footer": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=footer&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1bvuhatw9l&num=5d124549678"
},
"expandedFooter": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=multiple_illust_viewer&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1by6cv5o74&num=5d124549963"
},
"logo": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=logo_side&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4duho1c0k739zyq&num=5d124549322"
}
},
"extraData": {
"meta": {
"title": "[R-18] 【巨乳】「T-20S」/「amssc」のイラスト [pixiv]",
"description": "この作品 「T-20S」 は 「R-18」「巨乳」 等のタグがつけられた「amssc」さんのイラストです。 「JUST FOR FUN现在可以做到游戏内立绘修改拉立绘动态皮肤都可以支持想要资助获得新技术请站内信联系我。」",
"keywords": "R-18,巨乳,母乳,lastorigin,Last_Origin,T-20S,おっぱい,라스트오리진,노움,イラスト,pixiv,ピクシブ",
"canonical": "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=74939802"
}
},
"noLoginData": {
"breadcrumbs": [
"日常",
"R-18"
],
"zengoIdWorks": {
"prev": {
"id": "74939801",
"title": "秋めいてるようで春にも見える"
},
"next": {
"id": "74939803",
"title": "愛言葉lll"
}
}
}
}
}

604
tests/fixture/Pixiv/manga.json vendored Normal file
View File

@ -0,0 +1,604 @@
{
"error": false,
"message": "",
"body": {
"illustId": "46713544",
"illustTitle": "冬の日ラブラブ",
"illustComment": "ラブラブエッチのらくがき<br /><br />三万フォロワー感謝します~<br /><br />最近忙しいので、自分の時間が少ない・・・",
"id": "46713544",
"title": "冬の日ラブラブ",
"description": "ラブラブエッチのらくがき<br /><br />三万フォロワー感謝します~<br /><br />最近忙しいので、自分の時間が少ない・・・",
"illustType": 1,
"createDate": "2014-10-24T15:06:58+00:00",
"uploadDate": "2014-10-24T15:06:58+00:00",
"restrict": 0,
"xRestrict": 1,
"sl": 6,
"urls": {
"mini": "https://i.pximg.net/c/48x48/img-master/img/2014/10/25/00/06/58/46713544_p0_square1200.jpg",
"thumb": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2014/10/25/00/06/58/46713544_p0_square1200.jpg",
"small": "https://i.pximg.net/c/540x540_70/img-master/img/2014/10/25/00/06/58/46713544_p0_master1200.jpg",
"regular": "https://i.pximg.net/img-master/img/2014/10/25/00/06/58/46713544_p0_master1200.jpg",
"original": "https://i.pximg.net/img-original/img/2014/10/25/00/06/58/46713544_p0.jpg"
},
"tags": {
"authorId": "502217",
"isLocked": false,
"tags": [
{
"tag": "R-18",
"locked": true,
"deletable": false,
"userId": "502217",
"romaji": null,
"userName": "Aza"
},
{
"tag": "落書き",
"locked": true,
"deletable": false,
"userId": "502217",
"romaji": "rakugaki",
"translation": {
"en": "doodle"
},
"userName": "Aza"
},
{
"tag": "おっぱい",
"locked": true,
"deletable": false,
"userId": "502217",
"romaji": "oppai",
"translation": {
"en": "breasts"
},
"userName": "Aza"
},
{
"tag": "オリジナル",
"locked": true,
"deletable": false,
"userId": "502217",
"romaji": "orijinaru",
"translation": {
"en": "original"
},
"userName": "Aza"
},
{
"tag": "パイズリ",
"locked": false,
"deletable": false,
"romaji": "paizuri",
"translation": {
"en": "paizuri"
}
},
{
"tag": "中出し",
"locked": false,
"deletable": false,
"romaji": "nakadashi",
"translation": {
"en": "creampie"
}
},
{
"tag": "だいしゅきホールド",
"locked": false,
"deletable": false,
"romaji": "daishukiho-rudo",
"translation": {
"en": "leg lock"
}
},
{
"tag": "愛のあるセックス",
"locked": false,
"deletable": false,
"romaji": "ainoarusekkusu",
"translation": {
"en": "love-making"
}
},
{
"tag": "黒髪ロング",
"locked": false,
"deletable": false,
"romaji": "kurokamironngu",
"translation": {
"en": "long black hair"
}
},
{
"tag": "オリジナル10000users入り",
"locked": false,
"deletable": false,
"romaji": "orijinaruichimannyu-za-zuiri",
"translation": {
"en": "original 10000+ bookmarks"
}
}
],
"writable": false
},
"storableTags": [
"0xsDLqCEW6",
"KvAGITxIxH",
"Ie2c51_4Sp",
"RTJMXD26Ak",
"AI_aJCDFn0",
"MM6RXH_rlN",
"MmtTUk7gNU",
"LEmyJ-RN72",
"pYlUxeIoeg",
"jH0uD88V6F"
],
"userId": "502217",
"userName": "Aza",
"userAccount": "zaxwu",
"userIllusts": {
"2982154": null,
"3232171": null,
"9683924": null,
"9982638": null,
"10486890": null,
"13450140": null,
"13594508": null,
"15091512": null,
"15584077": null,
"18502761": null,
"19428567": null,
"21337912": null,
"23139081": null,
"26446486": null,
"26602193": null,
"29381152": null,
"30918820": null,
"31543061": null,
"32237888": null,
"32760977": null,
"32797035": null,
"33407004": null,
"34272641": null,
"35659365": {
"illustId": "35659365",
"illustTitle": "Redial",
"id": "35659365",
"title": "Redial",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2013/05/13/00/41/01/35659365_p0_square1200.jpg",
"description": "",
"tags": [
"初音ミク",
"Redial",
"無限ループ",
"ミクダヨー",
"ポリン",
"VOCALOID1000users入り",
"VOCALOID"
],
"userId": "502217",
"userName": "Aza",
"width": 1650,
"height": 1300,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"36344943": {
"illustId": "36344943",
"illustTitle": "バニーちーちゃん",
"id": "36344943",
"title": "バニーちーちゃん",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2013/06/14/10/20/58/36344943_p0_square1200.jpg",
"description": "",
"tags": [
"佐々木千穂",
"バニーガール",
"はたらく魔王さま!",
"おっぱい",
"パンスト",
"ロリ爆乳",
"黒バニー",
"ちーちゃん",
"手袋",
"はたらく魔王さま!500users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 1200,
"height": 1350,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"38288483": {
"illustId": "38288483",
"illustTitle": "ログインゲーム",
"id": "38288483",
"title": "ログインゲーム",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2013/09/04/10/37/02/38288483_p0_square1200.jpg",
"description": "",
"tags": [
"ファイナルファンタジー14",
"ララフェル",
"FF100users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 600,
"height": 1128,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"40513649": {
"illustId": "40513649",
"illustTitle": "クリスマス",
"id": "40513649",
"title": "クリスマス",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2013/12/26/00/13/24/40513649_p0_square1200.jpg",
"description": "",
"tags": [
"オリジナル",
"クリスマス",
"ハイヒール",
"オリジナル100users入り",
"女の子"
],
"userId": "502217",
"userName": "Aza",
"width": 900,
"height": 900,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"40865549": {
"illustId": "40865549",
"illustTitle": "ヲ級",
"id": "40865549",
"title": "ヲ級",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2014/01/10/00/48/39/40865549_p0_square1200.jpg",
"description": "",
"tags": [
"艦これ",
"空母ヲ級",
"落書き",
"深海棲艦",
"艦隊これくしょん",
"艦これ100users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 800,
"height": 1056,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"44463100": {
"illustId": "44463100",
"illustTitle": "ノアちゃん",
"id": "44463100",
"title": "ノアちゃん",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2014/07/03/00/06/00/44463100_p0_square1200.jpg",
"description": "",
"tags": [
"パズドラ",
"ノア",
"パズドラ100users入り",
"おでこ"
],
"userId": "502217",
"userName": "Aza",
"width": 1200,
"height": 1200,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"46713544": {
"illustId": "46713544",
"illustTitle": "冬の日ラブラブ",
"id": "46713544",
"title": "冬の日ラブラブ",
"illustType": 1,
"xRestrict": 1,
"restrict": 0,
"sl": 6,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2014/10/25/00/06/58/46713544_p0_square1200.jpg",
"description": "ラブラブエッチのらくがき<br /><br />三万フォロワー感謝します~<br /><br />最近忙しいので、自分の時間が少ない・・・",
"tags": [
"R-18",
"落書き",
"おっぱい",
"オリジナル",
"パイズリ",
"中出し",
"だいしゅきホールド",
"愛のあるセックス",
"黒髪ロング",
"オリジナル10000users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 800,
"height": 800,
"pageCount": 20,
"isBookmarkable": true,
"bookmarkData": null
},
"49623591": {
"illustId": "49623591",
"illustTitle": "らくがきまとめ4",
"id": "49623591",
"title": "らくがきまとめ4",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2015/04/03/00/15/53/49623591_p0_square1200.jpg",
"description": "",
"tags": [
"落書き",
"極上の尻",
"パズドラ",
"ぴっちりスーツ",
"魔性の潮",
"加賀",
"艦これ100users入り",
"潮(艦隊これくしょん)",
"100users入り",
"バニーガール"
],
"userId": "502217",
"userName": "Aza",
"width": 1000,
"height": 1080,
"pageCount": 38,
"isBookmarkable": null,
"bookmarkData": null
},
"51747015": {
"illustId": "51747015",
"illustTitle": "バニー潮ちゃん",
"id": "51747015",
"title": "バニー潮ちゃん",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2015/08/03/21/22/52/51747015_p0_square1200.jpg",
"description": "",
"tags": [
"艦これ",
"バニーガール",
"バニーの日",
"潮っぱい",
"魔性の潮",
"まったく、駆逐艦は最高だぜ!!",
"艦々バニー",
"潮(艦隊これくしょん)",
"艦隊これくしょん",
"艦これ1000users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 1000,
"height": 1421,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"52206867": {
"illustId": "52206867",
"illustTitle": "水着おっぱいまとめ",
"id": "52206867",
"title": "水着おっぱいまとめ",
"illustType": 1,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2015/08/27/00/55/49/52206867_p0_square1200.jpg",
"description": "",
"tags": [
"おっぱい",
"水着",
"落書き",
"巨乳",
"挟まれたい谷間",
"デカァァァァァいッ説明不要!!",
"愛宕/パチュリー/千斗いすず/柏崎星奈/丹生谷森夏/ハトホル",
"千斗いすず"
],
"userId": "502217",
"userName": "Aza",
"width": 500,
"height": 875,
"pageCount": 7,
"isBookmarkable": null,
"bookmarkData": null
},
"52584590": {
"illustId": "52584590",
"illustTitle": "楓ちゃん",
"id": "52584590",
"title": "楓ちゃん",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2015/09/18/23/35/41/52584590_p0_square1200.jpg",
"description": "",
"tags": [
"アイドルマスターシンデレラガールズ",
"オッドアイ",
"高垣楓",
"アイマス1000users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 900,
"height": 900,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"64877227": {
"illustId": "64877227",
"illustTitle": "マシュ",
"id": "64877227",
"title": "マシュ",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2017/09/10/00/10/03/64877227_p0_square1200.jpg",
"description": "",
"tags": [
"マシュ",
"Fate/GrandOrder",
"素晴らしすぎる",
"極上の乳",
"マシュ・キリエライト",
"Fate/GO1000users入り",
"濡れ透け",
"マシュマロおっぱい"
],
"userId": "502217",
"userName": "Aza",
"width": 1000,
"height": 1000,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"66698671": {
"illustId": "66698671",
"illustTitle": "モテそうですよね",
"id": "66698671",
"title": "モテそうですよね",
"illustType": 0,
"xRestrict": 0,
"restrict": 0,
"sl": 2,
"url": "https://i.pximg.net/c/250x250_80_a2/img-master/img/2018/01/08/00/47/32/66698671_p0_square1200.jpg",
"description": "",
"tags": [
"輝夜月",
"バーチャルYouTuber",
"魅惑の谷間",
"バーチャルYouTuber1000users入り"
],
"userId": "502217",
"userName": "Aza",
"width": 1200,
"height": 1200,
"pageCount": 1,
"isBookmarkable": null,
"bookmarkData": null
},
"69620476": null
},
"likeData": false,
"width": 800,
"height": 800,
"pageCount": 20,
"bookmarkCount": 16448,
"likeCount": 13048,
"commentCount": 70,
"responseCount": 0,
"viewCount": 483175,
"isHowto": false,
"isOriginal": true,
"imageResponseOutData": [],
"imageResponseData": [],
"imageResponseCount": 0,
"pollData": null,
"seriesNavData": null,
"descriptionBoothId": null,
"descriptionYoutubeId": null,
"comicPromotion": null,
"contestBanners": [],
"factoryGoods": {
"integratable": false,
"integrated": false
},
"isBookmarkable": true,
"bookmarkData": null,
"contestData": null,
"zoneConfig": {
"responsive": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_responsive&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjl9lcz20o&num=5d1245e1507"
},
"300x250": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=illust_rectangle&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjo8fldij4&num=5d1245e15"
},
"500x500": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=bigbanner&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjqltfp2la&num=5d1245e182"
},
"header": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=header&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjsv9fca5h&num=5d1245e1969"
},
"footer": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=footer&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjv5vqfo0g&num=5d1245e1914"
},
"expandedFooter": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=multiple_illust_viewer&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjxd4y5zlv&num=5d1245e1125"
},
"logo": {
"url": "https://pixon.ads-pixiv.net/show?zone_id=logo_side&format=js&s=0&up=0&ng=g&l=ja&uri=%2Fajax%2Fillust%2F_PARAM_&is_spa=1&ab_test_digits_first=5&ab_test_digits_second=5&Yuid=MjgDVlY&suid=Pg4dukaxjzmhr6fid&num=5d1245e1989"
}
},
"extraData": {
"meta": {
"title": "[R-18] 【落書き】「冬の日ラブラブ」/「Aza」のマンガ [pixiv]",
"description": "この作品 「冬の日ラブラブ」 は 「R-18」「落書き」 等のタグがつけられた「Aza」さんの漫画です。 「ラブラブエッチのらくがき三万フォロワー感謝します~最近忙しいので、自分の時間が少ない・・・」",
"keywords": "R-18,落書き,おっぱい,オリジナル,パイズリ,中出し,だいしゅきホールド,愛のあるセックス,黒髪ロング,オリジナル10000users入り,イラスト,pixiv,ピクシブ",
"canonical": "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=46713544"
}
},
"noLoginData": {
"breadcrumbs": [
"日常",
"R-18"
],
"zengoIdWorks": {
"prev": {
"id": "46713543",
"title": "ゆい様"
},
"next": {
"id": "46713545",
"title": "木吉"
}
}
}
}
}

10
tests/fixture/Steam/test.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"333600": {
"success": true,
"data": {
"name": "NEKOPARA Vol. 1",
"short_description": "水無月嘉祥(みなづき かしょう)は伝統ある老舗和菓子屋である実家を出て、 パティシエとして自身のケーキ屋『ラ・ソレイユ』を一人で開店する。 しかし実家から送った引っ越し荷物の中に、 実家で飼っていた人型ネコのショコラとバニラが紛れ込んでいた。",
"header_image": "https://steamcdn-a.akamaihd.net/steam/apps/333600/header.jpg?t=1558382831"
}
}
}

1
tests/fixture/Steam/testNotFound.json vendored Normal file
View File

@ -0,0 +1 @@
{"1":{"success":false}}

10
tests/fixture/Steam/testR18.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"1077580": {
"success": true,
"data": {
"name": "Broke Girl | 負債千金",
"short_description": "苦労知らずに育ったお嬢様は一夜にして1000万の借金を背負うことになった。借金を返済するために働かなければならない。しかし世間には悪意が満ちており、男達はお金で彼女を誘うか凌辱することしか考えていない。",
"header_image": "https://steamcdn-a.akamaihd.net/steam/apps/1077580/header.jpg?t=1559506319"
}
}
}

13
tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"sourceMap": true,
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"strict": true,
"experimentalDecorators": true
},
"include": [
"resources/assets/js/**/*"
]
}

2
webpack.mix.js vendored
View File

@ -16,7 +16,7 @@ mix.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/home.js', 'public/js')
.js('resources/assets/js/user/stats.js', 'public/js/user')
.js('resources/assets/js/setting/privacy.js', 'public/js/setting')
.js('resources/assets/js/checkin.js', 'public/js')
.ts('resources/assets/js/checkin.ts', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.autoload({
'jquery': ['$', 'jQuery', 'window.jQuery']

402
yarn.lock
View File

@ -710,6 +710,13 @@
"@types/minimatch" "*"
"@types/node" "*"
"@types/jquery@^3.3.29":
version "3.3.29"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.29.tgz#680a2219ce3c9250483722fccf5570d1e2d08abd"
integrity sha512-FhJvBninYD36v3k6c+bVk1DSZwh7B5Dpb/Pyk3HKVsiohn0nhbefZZ+3JXbWQhFyt0MxSl2jRDdGQPHeOHFXrQ==
dependencies:
"@types/sizzle" "*"
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@ -725,6 +732,11 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18"
integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==
"@types/sizzle@*":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
"@types/unist@*", "@types/unist@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
@ -923,6 +935,14 @@ accepts@~1.3.4, accepts@~1.3.5:
mime-types "~2.1.18"
negotiator "0.6.1"
accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
dependencies:
mime-types "~2.1.24"
negotiator "0.6.2"
acorn-dynamic-import@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
@ -933,12 +953,7 @@ acorn-walk@^6.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913"
integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==
acorn@^6.0.5:
version "6.1.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818"
integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==
acorn@^6.0.7:
acorn@^6.0.5, acorn@^6.0.7:
version "6.1.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f"
integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==
@ -1281,31 +1296,36 @@ binary-extensions@^1.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1"
integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==
bluebird@^3.1.1, bluebird@^3.5.1, bluebird@^3.5.3:
bluebird@^3.1.1, bluebird@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
bluebird@^3.5.1:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
body-parser@1.18.3:
version "1.18.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
dependencies:
bytes "3.0.0"
bytes "3.1.0"
content-type "~1.0.4"
debug "2.6.9"
depd "~1.1.2"
http-errors "~1.6.3"
iconv-lite "0.4.23"
http-errors "1.7.2"
iconv-lite "0.4.24"
on-finished "~2.3.0"
qs "6.5.2"
raw-body "2.3.3"
type-is "~1.6.16"
qs "6.7.0"
raw-body "2.4.0"
type-is "~1.6.17"
bonjour@^3.5.0:
version "3.5.0"
@ -1353,6 +1373,13 @@ braces@^2.3.1, braces@^2.3.2:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@ -1469,6 +1496,11 @@ bytes@3.0.0:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
bytes@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
cacache@^11.0.2:
version "11.3.2"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
@ -1603,7 +1635,7 @@ chalk@^1.0.0, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2:
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -1859,9 +1891,9 @@ commander@2.17.x, commander@~2.17.1:
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commander@^2.14.1, commander@^2.18.0, commander@^2.9.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
commondir@^1.0.1:
version "1.0.1"
@ -1944,10 +1976,12 @@ constants-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
content-disposition@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
content-disposition@0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
dependencies:
safe-buffer "5.1.2"
content-type@~1.0.4:
version "1.0.4"
@ -1971,10 +2005,10 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
cookie@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
copy-concurrently@^1.0.0:
version "1.0.5"
@ -2631,7 +2665,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
enhanced-resolve@^4.1.0:
enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==
@ -2824,38 +2858,38 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
homedir-polyfill "^1.0.1"
express@^4.16.2, express@^4.16.3:
version "4.16.4"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
dependencies:
accepts "~1.3.5"
accepts "~1.3.7"
array-flatten "1.1.1"
body-parser "1.18.3"
content-disposition "0.5.2"
body-parser "1.19.0"
content-disposition "0.5.3"
content-type "~1.0.4"
cookie "0.3.1"
cookie "0.4.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "~1.1.2"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.1.1"
finalhandler "~1.1.2"
fresh "0.5.2"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.2"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
proxy-addr "~2.0.4"
qs "6.5.2"
range-parser "~1.2.0"
proxy-addr "~2.0.5"
qs "6.7.0"
range-parser "~1.2.1"
safe-buffer "5.1.2"
send "0.16.2"
serve-static "1.13.2"
setprototypeof "1.1.0"
statuses "~1.4.0"
type-is "~1.6.16"
send "0.17.1"
serve-static "1.14.1"
setprototypeof "1.1.1"
statuses "~1.5.0"
type-is "~1.6.18"
utils-merge "1.0.1"
vary "~1.1.2"
@ -2999,17 +3033,24 @@ fill-range@^4.0.0:
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
finalhandler@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
finalhandler@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
dependencies:
debug "2.6.9"
encodeurl "~1.0.2"
escape-html "~1.0.3"
on-finished "~2.3.0"
parseurl "~1.3.2"
statuses "~1.4.0"
parseurl "~1.3.3"
statuses "~1.5.0"
unpipe "~1.0.0"
find-cache-dir@^2.0.0:
@ -3368,12 +3409,12 @@ growly@^1.3.0:
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
gzip-size@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80"
integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==
version "5.1.1"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==
dependencies:
duplexer "^0.1.1"
pify "^3.0.0"
pify "^4.0.1"
handle-thing@^2.0.0:
version "2.0.0"
@ -3573,7 +3614,18 @@ http-deceiver@^1.2.7:
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
http-errors@1.7.2, http-errors@~1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-errors@~1.6.2:
version "1.6.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
@ -3628,14 +3680,7 @@ husky@^1.3.1:
run-node "^1.0.0"
slash "^2.0.0"
iconv-lite@0.4.23:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.4.4:
iconv-lite@0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -3818,12 +3863,7 @@ ip@^1.1.0, ip@^1.1.5:
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
ipaddr.js@1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
ipaddr.js@^1.5.2:
ipaddr.js@1.9.0, ipaddr.js@^1.5.2:
version "1.9.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
@ -4022,6 +4062,11 @@ is-number@^3.0.0:
dependencies:
kind-of "^3.0.2"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-obj@^1.0.0, is-obj@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@ -4182,9 +4227,9 @@ js-tokens@^3.0.2:
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
js-yaml@^3.12.0, js-yaml@^3.9.0:
version "3.12.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600"
integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
@ -4804,6 +4849,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, mic
snapdragon "^0.8.1"
to-regex "^3.0.2"
micromatch@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
dependencies:
braces "^3.0.1"
picomatch "^2.0.5"
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
@ -4812,6 +4865,11 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
mime-db@1.40.0:
version "1.40.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
"mime-db@>= 1.36.0 < 2", mime-db@~1.38.0:
version "1.38.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad"
@ -4824,10 +4882,17 @@ mime-types@~2.1.17, mime-types@~2.1.18:
dependencies:
mime-db "~1.38.0"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
mime-types@~2.1.24:
version "2.1.24"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
dependencies:
mime-db "1.40.0"
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.3.1:
version "2.4.0"
@ -4953,8 +5018,9 @@ move-concurrently@^1.0.1:
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
ms@2.1.1, ms@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
@ -5008,6 +5074,11 @@ negotiator@0.6.1:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
neo-async@^2.5.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
@ -5497,6 +5568,11 @@ parseurl@~1.3.2:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
pascalcase@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@ -5560,6 +5636,11 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
picomatch@^2.0.5:
version "2.0.7"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -6072,13 +6153,13 @@ property-expr@^1.5.0:
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f"
integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==
proxy-addr@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
proxy-addr@~2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==
dependencies:
forwarded "~0.1.2"
ipaddr.js "1.8.0"
ipaddr.js "1.9.0"
prr@~1.0.1:
version "1.0.1"
@ -6146,10 +6227,10 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qs@6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
querystring-es3@^0.2.0:
version "0.2.1"
@ -6186,19 +6267,24 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
range-parser@^1.0.3, range-parser@~1.2.0:
range-parser@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
raw-body@2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raw-body@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
dependencies:
bytes "3.0.0"
http-errors "1.6.3"
iconv-lite "0.4.23"
bytes "3.1.0"
http-errors "1.7.2"
iconv-lite "0.4.24"
unpipe "1.0.0"
rc@^1.2.7:
@ -6683,10 +6769,15 @@ semver-compare@^1.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
send@0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
semver@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b"
integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
dependencies:
debug "2.6.9"
depd "~1.1.2"
@ -6695,12 +6786,12 @@ send@0.16.2:
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "~1.6.2"
mime "1.4.1"
ms "2.0.0"
http-errors "~1.7.2"
mime "1.6.0"
ms "2.1.1"
on-finished "~2.3.0"
range-parser "~1.2.0"
statuses "~1.4.0"
range-parser "~1.2.1"
statuses "~1.5.0"
serialize-javascript@^1.4.0:
version "1.6.1"
@ -6720,15 +6811,15 @@ serve-index@^1.7.2:
mime-types "~2.1.17"
parseurl "~1.3.2"
serve-static@1.13.2:
version "1.13.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
serve-static@1.14.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.2"
send "0.16.2"
parseurl "~1.3.3"
send "0.17.1"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
@ -6765,6 +6856,11 @@ setprototypeof@1.1.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
setprototypeof@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.11"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
@ -7030,16 +7126,11 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"
"statuses@>= 1.4.0 < 2":
"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
statuses@~1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
stream-browserify@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
@ -7435,6 +7526,13 @@ to-regex-range@^2.1.0:
is-number "^3.0.0"
repeat-string "^1.6.1"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@ -7445,6 +7543,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
@ -7480,6 +7583,17 @@ tryer@^1.0.0:
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
ts-loader@^6.0.1:
version "6.0.3"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.0.3.tgz#6ef6f086d7080b9cf02ed1945377aeb5ed1b5cf6"
integrity sha512-iICBD4PryhnGNdtaDva49UGODHFVcuK7p4+G8CP1TVcUhTC4hkcy4MC2dzWwALSnpOzfUfA/4u8B2F64wsMgjQ==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
loader-utils "^1.0.2"
micromatch "^4.0.0"
semver "^6.0.0"
tslib@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@ -7490,19 +7604,24 @@ tty-browserify@0.0.0:
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
type-is@~1.6.16:
version "1.6.16"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==
type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
dependencies:
media-typer "0.3.0"
mime-types "~2.1.18"
mime-types "~2.1.24"
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^3.4.5:
version "3.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c"
integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==
uglify-js@3.4.x:
version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
@ -7783,6 +7902,11 @@ vm-browserify@0.0.4:
dependencies:
indexof "0.0.1"
vue-class-component@^7.0.1, vue-class-component@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-7.1.0.tgz#b33efcb10e17236d684f70b1e96f1946ec793e87"
integrity sha512-G9152NzUkz0i0xTfhk0Afc8vzdXxDR1pfN4dTwE72cskkgJtdXfrKBkMfGvDuxUh35U500g5Ve4xL8PEGdWeHg==
vue-hot-reload-api@^2.3.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.2.tgz#1fcc1495effe08a790909b46bf7b5c4cfeb6f21b"
@ -7799,6 +7923,13 @@ vue-loader@^15.4.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-property-decorator@^8.1.1:
version "8.1.1"
resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-8.1.1.tgz#80dadbe5ffa0e7eb6a0ba0a07036365471a7d5ee"
integrity sha512-K+PUT17ZEMWyhrKZnl4Fc9qMyFpMcjVbZJBwx4BpA8BXfaspaTeFdoHuk1aywC/+4G86sxIr/5n4IQUQLecSWw==
dependencies:
vue-class-component "^7.0.1"
vue-style-loader@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8"
@ -7807,10 +7938,10 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
vue-template-compiler@^2.6.6:
version "2.6.6"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.6.tgz#a807acbf3d51971d3721d75ecb1b927b517c1a02"
integrity sha512-OakxDGyrmMQViCjkakQFbDZlG0NibiOzpLauOfyCUVRQc9yPmTqpiz9nF0VeA+dFkXegetw0E5x65BFhhLXO0A==
vue-template-compiler@^2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc"
integrity sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@ -7820,6 +7951,11 @@ vue-template-es2015-compiler@^1.8.2:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a"
integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA==
vue@^2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
watchpack@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
@ -7837,9 +7973,9 @@ wbuf@^1.1.0, wbuf@^1.7.3:
minimalistic-assert "^1.0.0"
webpack-bundle-analyzer@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.1.0.tgz#2f19cbb87bb6d4f3cb4e59cb67c837bd9436e89d"
integrity sha512-nyDyWEs7C6DZlgvu1pR1zzJfIWSiGPbtaByZr8q+Fd2xp70FuM/8ngCJzj3Er1TYRLSFmp1F1OInbEm4DZH8NA==
version "3.3.2"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz#3da733a900f515914e729fcebcd4c40dde71fc6f"
integrity sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA==
dependencies:
acorn "^6.0.7"
acorn-walk "^6.1.1"
@ -8054,9 +8190,9 @@ write@1.0.3:
mkdirp "^0.5.1"
ws@^6.0.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526"
integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w==
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
dependencies:
async-limiter "~1.0.0"