Skip to content

Commit

Permalink
feat: complete basic hitokoto functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
WRXinYue committed Jul 5, 2024
1 parent fc8aaa3 commit 4e2867c
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 9 deletions.
191 changes: 185 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,199 @@
# valaxy-addon-template
<h1 align="center">valaxy-addon-hitokoto</h1>

## Usage
<pre align="center">
一言指的是一句话,可以是动漫中的台词,也可以是网络上的各种小段子。或是感动,或是开心,有或是单纯的回忆...
</pre>

<p align="center">
<a href="https://www.npmjs.com/package/valaxy-addon-hitokoto" rel="nofollow"><img src="https://img.shields.io/npm/v/valaxy-addon-hitokoto?color=0078E7" alt="NPM version"></a>
</p>

## 安装插件

### 基础使用

插件直接可以安装使用,通常不需要过多繁琐配置:

```bash
npm i valaxy-addon-template
pnpm add valaxy-addon-hitokoto
```

### 加载插件
```ts
import { defineValaxyConfig } from 'valaxy'
import { addonHitokoto } from 'valaxy-addon-hitokoto'

export default defineValaxyConfig({
addons: [
addonHitokoto(),
],
})
```

### 简单配置

如果您想获取指定类型的句子,或者是特定长度的句子,可以参考以下配置示例:

```ts
import { defineValaxyConfig } from 'valaxy'
import { addonTemplate } from 'valaxy-addon-template'
import { HitokotoType, addonHitokoto } from 'valaxy-addon-hitokoto'

export default defineValaxyConfig({
addons: [
addonTemplate(),
addonHitokoto({
args: [HitokotoType.Animation, HitokotoType.Comic], // 句子类型
minLength: 0, // 最短句子长度
maxLength: 30 // 最长句子长度
}),
],
})
```

> [!TIP]
> 关于 `HitokotoType` 类别的更多信息,请参见 [HitokotoType](https://github.com/valaxyjs/valaxy-addon-hitokoto/tree/master/client/enum.ts)
## 使用插件

以下是简洁快捷的使用例子:

```vue
<script setup lang="ts">
import { HitokotoType, useAddonHitokoto } from 'valaxy-addon-hitokoto'
const { hitokoto } = useAddonHitokoto()
</script>
<template>
<span>一言: {{ hitokoto.hitokoto }}</span>
<span>来自: {{ hitokoto.from }}</span>
</template>
```

### 自动刷新

如果您想在网站上定时自动刷新获取一言句子,可以参考如下例子。每六秒调用 `fetchHitokoto` 实现刷新:

```vue
<script setup lang="ts">
import { useIntervalFn } from '@vueuse/core'
import { HitokotoType, useAddonHitokoto } from 'valaxy-addon-hitokoto'
const { hitokoto, fetchHitokoto } = useAddonHitokoto()
useIntervalFn(() => {
fetchHitokoto()
}, 6000)
</script>
<template>
<span>一言: {{ hitokoto.hitokoto }}</span>
<span>来自: {{ hitokoto.from }}</span>
</template>
```

### 手动刷新

如果您希望在点击某个按钮时手动刷新 hitokoto 句子,可以参考如下例子:

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { HitokotoType, useAddonHitokoto } from 'valaxy-addon-hitokoto'
const { hitokoto, fetchHitokoto } = useAddonHitokoto()
const isLoading = ref(false)
async function manualRefresh() {
isLoading.value = true
await fetchHitokoto()
isLoading.value = false
}
</script>
<template>
<span>一言: {{ hitokoto.hitokoto }}</span>
<span>来自: {{ hitokoto.from }}</span>
<button :disabled="isLoading" @click="manualRefresh">
{{ isLoading ? '刷新中...' : '手动刷新' }}
</button>
</template>
```

> [!IMPORTANT]
> 为降低运算服务器的负载,hitokoto 国际站目前由于持续的流量、负载和攻击问题,启用了缓存机制,缓存时间为2秒。这意味着在同一地区、同一路线且使用相同参数的访问者在短时间内将获得相同的句子, 进多信息请参阅 [一言开发者中心](https://developer.hitokoto.cn/sentence/#请求地址)
## 多页面

如果您有多个页面,想在不同页面设置不同的配置,可以在 `useAddonHitokoto` 中传入您想要设置的配置:

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { HitokotoType, useAddonHitokoto } from 'valaxy-addon-hitokoto'
const { hitokoto } = useAddonHitokoto({ args: [HitokotoType.Animation, HitokotoType.Comic] })
</script>
<template>
<span>一言: {{ hitokoto.hitokoto }}</span>
<span>来自: {{ hitokoto.from }}</span>
</template>
```

## 动态切换

你也可以在 `fetchHitokoto` 函数中动态添加配置,以实现不同类型句子的切换:

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { HitokotoType, useAddonHitokoto } from 'valaxy-addon-hitokoto'
const { hitokoto, fetchHitokoto } = useAddonHitokoto()
const isLoading = ref(false)
async function switchHitokotoType(newTypes: HitokotoType[]) {
isLoading.value = true
await fetchHitokoto({ args: newTypes })
isLoading.value = false
}
</script>
<template>
<span>Hitokoto: {{ hitokoto.hitokoto }}</span>
<span>From: {{ hitokoto.from }}</span>
<button :disabled="isLoading" @click="switchHitokotoType([HitokotoType.Game, HitokotoType.Literature])">
{{ isLoading ? '切换中...' : '切换到游戏或文学' }}
</button>
<button :disabled="isLoading" @click="switchHitokotoType([HitokotoType.Movie, HitokotoType.Poetry])">
{{ isLoading ? '切换中...' : '切换到影视或诗词' }}
</button>
</template>
```

## 配置 / Options

| 属性名 | 类型 | 默认值 | 说明 |
| ---- | ---- | ---- | ---- |
| api | `string` | --- | `'intl'` 为海外线路,默认为国际线路。填入其他为自定义 API, 返回 JSON 则为一言 API,数组类型取第一个元素,字符串类型直接取值 |
| args | `string` | `HitokotoType[]` | 获取指定句子类型, 类型详见 [HitokotoType](https://github.com/valaxyjs/valaxy-addon-hitokoto/tree/master/client/enum.ts)|
| minLength | `number` | `0` | API 获取的最短句子长度 |
| maxLength | `number` | `30` | API 获取的最长句子长度 |

> [!NOTE]
> 关于自定义 API,这里有一个示例:将 `api` 填入 `https://el-bot-api.elpsy.cn/api/words/young`,由于返回值是一个数组,因此取其中的一个元素作为一句话
## 其他

自行部署: <https://developer.hitokoto.cn/sentence/deploy.html>
语句库: <https://github.com/hitokoto-osc/sentences-bundle>

请求地址:

| 地址 | 协议 | 方法 | QPS 限制 | 线路 |
| ---- | ---- | ---- | ---- | ---- |
| `v1.hitokoto.cn` | HTTPS | Any | 2 | 全球 |
| `international.v1.hitokoto.cn` | HTTPS | Any | 20(含缓存*) | 海外 |

## 致谢

- [Hitokoto](https://hitokoto.cn/)
57 changes: 57 additions & 0 deletions client/composable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ref } from 'vue'
import type { Hitokoto, HitokotoOptions } from '../types'
import { generateUrl, isHitokotoOptions, toCamelCase } from '../utils'
import { useAddonHitokotoConfig } from './options'

export function useAddonHitokoto(options: HitokotoOptions | null = null) {
const hitokotoOptions = useAddonHitokotoConfig()

const intlUrl = 'https://international.v1.hitokoto.cn'
const defaultUrl = 'https://v1.hitokoto.cn'

const hitokoto = ref<Hitokoto>({
id: 0,
uuid: '',
hitokoto: '',
type: '',
from: '',
fromWho: '',
creator: '',
creatorUid: 0,
reviewer: 0,
commitFrom: '',
createdAt: '',
length: 0,
} as any)

const fetchHitokoto = async (fetchOptions: HitokotoOptions = options || hitokotoOptions.value) => {
if (!isHitokotoOptions(fetchOptions))
console.error('Invalid argument: fetchOptions must be of type HitokotoOptions', fetchOptions)

const baseUrl = fetchOptions.api === 'intl' ? intlUrl : fetchOptions.api || defaultUrl

const finalUrl = generateUrl(baseUrl, fetchOptions)

try {
const response = await fetch(finalUrl)
if (!response.ok)
throw new Error(`Network response was not ok.`)

const data = await response.json()

if (Array.isArray(data))
hitokoto.value.hitokoto = data[0]
else if (typeof data === 'object')
hitokoto.value = toCamelCase(data)
else if (typeof data === 'string')
hitokoto.value.hitokoto = data
}
catch (error) {
console.error('Error fetching visitor count:', error)
}
}

fetchHitokoto()

return { hitokoto, fetchHitokoto }
}
26 changes: 26 additions & 0 deletions client/enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export enum HitokotoType {
/** 动画 */
Animation = 'a',
/** 漫画 */
Comic = 'b',
/** 游戏 */
Game = 'c',
/** 文学 */
Literature = 'd',
/** 原创 */
Original = 'e',
/** 来自网络 */
FromInternet = 'f',
/** 其他 */
Others = 'g',
/** 影视 */
Movie = 'h',
/** 诗词 */
Poetry = 'i',
/** 网易云 */
NetEaseCloud = 'j',
/** 哲学 */
Philosophy = 'k',
/** 抖机灵 */
Wit = 'l',
}
3 changes: 3 additions & 0 deletions client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './composable'
export * from './options'
export * from './enum'
15 changes: 15 additions & 0 deletions client/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { computed } from 'vue'
import type { ValaxyAddon } from 'valaxy'
import { useRuntimeConfig } from 'valaxy'
import type { HitokotoOptions } from '../types'

export function useAddonHitokotoConfig() {
const runtimeConfig = useRuntimeConfig()
return computed<HitokotoOptions>(() => {
const options = (runtimeConfig.value.addons['valaxy-addon-hitokoto'] as ValaxyAddon<HitokotoOptions>).options

return {
...options,
}
})
}
3 changes: 3 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './client'
export * from './types'
export * from './node'
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './node'
export * from './client'
3 changes: 2 additions & 1 deletion node/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { defineValaxyAddon } from 'valaxy'
import pkg from '../package.json'
import type { HitokotoOptions } from '../types'

export const addonHitokoto = defineValaxyAddon(options => ({
export const addonHitokoto = defineValaxyAddon<HitokotoOptions>(options => ({
name: pkg.name,
enable: true,
options,
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "valaxy-addon-hitokoto",
"version": "0.0.1",
"description": "Template for Valaxy Addon.",
"description": "Hitokoto Composition API for Valaxy",
"repository": "https://github.com/valaxyjs/valaxy-addon-hitokoto",
"keywords": [
"valaxy",
"addon",
"valaxy-addon",
"hitokoto"
],
"main": "index.ts"
"main": "index.ts",
"types": "index.d.ts"
}
23 changes: 23 additions & 0 deletions types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { HitokotoType } from '../client/enum'

export interface HitokotoOptions {
api?: string
args?: HitokotoType[]
minLength?: number
maxLength?: number
}

export interface Hitokoto {
id: number
uuid: string
hitokoto: string
type: HitokotoType
from: string
fromWho: string
creator: string
creatorUid: number
reviewer: number
commitFrom: string
createdAt: string
length: number
}
Loading

0 comments on commit 4e2867c

Please sign in to comment.