├── .editorconfig ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── build.js ├── index.js ├── license ├── package.json ├── readme.md └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | meme.json 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /test.js 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '5' 4 | - '4' 5 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const cheerio = require('cheerio') 4 | const fetch = require('isomorphic-fetch') 5 | const lodash = require('lodash') 6 | 7 | const fn = (url) => { 8 | console.log(`fetching ${decodeURIComponent(url)}...`) 9 | return fetch(url) 10 | .then(data => data.text()) 11 | .then(data => { 12 | const $ = cheerio.load(data) 13 | const result = [] 14 | $('.navbox').first().find('.navbox-list').each(function () { 15 | const a = $(this).find('a') 16 | a.each(function () { 17 | const t = $(this).text() 18 | result.push(t) 19 | }) 20 | }) 21 | return result 22 | }) 23 | } 24 | 25 | Promise.all([ 26 | fn('https://zh.moegirl.org/Template:ACG%E7%BB%8F%E5%85%B8%E5%8F%B0%E8%AF%8D'), 27 | fn('https://zh.moegirl.org/Template:ACG%E5%9C%88%E7%94%A8%E8%AF%AD'), 28 | fn('https://zh.moegirl.org/Template:%E5%A4%A9%E6%9C%9D%E7%BD%91%E7%BB%9C%E6%B5%81%E8%A1%8C%E8%AF%AD%E5%8F%A5') 29 | ]).then(result => { 30 | console.log('writing memes...') 31 | fs.writeFileSync('meme.json', JSON.stringify(lodash.flatten(result), null, 2), 'utf8') 32 | }).catch(e => console.log(e.stack)) 33 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var unique = require('unique-random-array') 2 | var fetch = require('isomorphic-fetch') 3 | var meme = require('./meme') 4 | 5 | module.exports = unique(meme) 6 | module.exports.meme = meme 7 | module.exports.h = h 8 | 9 | function h() { 10 | return fetch('http://api.hitokoto.us/rand') 11 | .then(function (data) { 12 | return data.json() 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) EGOIST <0x142857@gmail.com> (github.com/egoist) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "saikou", 3 | "version": "1.1.0", 4 | "description": "Random text meme from ACG", 5 | "license": "MIT", 6 | "repository": "egoist/saikou", 7 | "author": { 8 | "name": "EGOIST", 9 | "email": "0x142857@gmail.com", 10 | "url": "github.com/egoist" 11 | }, 12 | "engines": { 13 | "node": ">=0.12.0" 14 | }, 15 | "scripts": { 16 | "test": "node build.js && xo && ava" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "meme.json" 21 | ], 22 | "keywords": [ 23 | "meme" 24 | ], 25 | "dependencies": { 26 | "isomorphic-fetch": "^2.2.1", 27 | "unique-random-array": "^1.0.0" 28 | }, 29 | "devDependencies": { 30 | "ava": "^0.8.0", 31 | "cheerio": "^0.19.0", 32 | "lodash": "^4.11.0", 33 | "xo": "^0.12.1" 34 | }, 35 | "xo": { 36 | "semicolon": false, 37 | "space": 2 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # saikou [![npm](https://img.shields.io/npm/v/saikou.svg?maxAge=2592000)](https://github.com/egoist/saikou) [![Build Status](https://travis-ci.org/egoist/saikou.svg?branch=master)](https://travis-ci.org/egoist/saikou) 2 | 3 | > 700 Random text memes from ACG world 4 | 5 | ![preview](http://i.imgur.com/0M5XsSA.png) 6 | 7 | ## Install 8 | 9 | ``` 10 | $ npm install --save saikou 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const saikou = require('saikou') 17 | 18 | saikou() 19 | //=> '画面太美我不敢看' 20 | 21 | saikou() 22 | //=> '我的麒麟臂又要发作了' 23 | 24 | saikou.h() 25 | .then(remoteMeme => { 26 | console.log(remoteMeme) 27 | /* 28 | { 29 | hitokoto: '越是锐利的小刀切完东西后就越容易变钝。', 30 | cat: 'c', 31 | author: '5454554a@2980.com', 32 | source: '东方永夜抄', 33 | like: 2, 34 | date: '2013.11.12 14:31:22', 35 | catname: 'Game - 游戏', 36 | id: 1384237882000 37 | } 38 | */ 39 | }) 40 | ``` 41 | 42 | ## License 43 | 44 | MIT © [EGOIST](https://github.com/egoist) 45 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import saikou, {meme, h} from './' 3 | 4 | test('main', t => { 5 | t.is(typeof saikou(), 'string') 6 | t.true(Array.isArray(meme)) 7 | }) 8 | 9 | test('h', async t => { 10 | const res = await h() 11 | t.is(typeof res.hitokoto, 'string') 12 | }) 13 | --------------------------------------------------------------------------------