Stapi&Imapi
Meditly ComputerSavvyMedic
It has been 0 days since the last update of this post. Some contents may be outdated. Please pay attention to screening.

Guapi实现方法,使用Cloudflare Workers实现功能。
本来想模仿一言做一个访问后就能随机输出句子的API,随后查找相关资料后发现相关实现方法也适用于构建一个图片API,于是Stapi(Sentence API)和Imapi(Image API)就应运而生了。在这两个API中,都使用正则表达式拦截发往相关域名的所有流量,随意修改访问目录和查询字符串都可以正常得到返回结果。
目前这两个功能都由我一人维护,所以可能出现工作量过大导致内容质量不够好。
STAPI中一共收录了2023条语句,IMAPI收录1123张图片,准备停止增加收录量,优化语句与图片质量。
在本站的画廊可以查看并发99次的Imapi运行结果。

为什么要搭建该服务

其实网络上有很多的API可以提供随机图片和随机输出一句话的功能,比如一言就很不错。但是因为我的API主要用于自己的博客以及一些个人的导航页之类的,而且本人也收集了一些比较好看的图片以及比较有触动的文字,所以想完全保证API的内容是自己可控的。

早期API实现方法

早期建站使用服务器,主要语言使用PHP,尝试了Wordpress、Typecho以及Catfish CMS等程序。所以早期API主要考虑使用PHP随机重定向请求至图片地址,直接使用了他人整理的新浪图床的一个TXT文件,在这个文件里有很多新浪图床图片地址,使用PHP语言实现转发,效果不错。但是后期为了实现内容自主化,而且也希望将网站静态化来避免攻击以及网站被黑入的风险,故弃用此实现方法。

Workers代码

使用Cloudflare Workers实现类似早期API中的PHP脚本的转发功能,而且转发后URL不变。var background_urls = []方括号内填写图片的URL,即可实现自动转发流量至这些图片中的一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {

var background_urls = [
//Stapi 'https://stece.luyaoguagua.top/0.html', ......
//Imapi 'https://image.luyaoguagua.top/0.jpg', ......
]
var index = Math.floor((Math.random()*background_urls.length));
res = await fetch(background_urls[index])
return new Response(res.body, {
//Stapi headers: { 'content-type': 'text/plain;charset=utf-8' , 'Access-Control-Allow-Origin': '*' },
//Imapi headers: { 'content-type': 'image/jpeg' , 'Access-Control-Allow-Origin': '*' },
})
}

Stece&Image

如上述,在Cloudflare Workers代码中需要准备大量图片/文字URL,可以使用他人的图床地址。如需实现内容自主可控,那么还需要自建图片库。如果是搭建文字API的话,需自建文字库。在保存文字库的HTML文件时建议使用utf-8编码,避免出现API乱码。

自动生成Workers代码

用于生成适合填入Cloudflare Workers代码中的大量图片地址。

1
2
3
4
5
6
7
8
9
10
mode = eval(input('Input a num. 0.stapi OR 1.imapi\n'))
start_num = eval(input('define start_num:\n'))
if mode == 0 :
while True :
print('{2}{0}{1}.html{2},'.format('https://stece.luyaoguagua.top/',start_num,"'"))
start_num += 1
if mode == 1 :
while True :
print('{2}{0}{1}.jpg{2},'.format('https://image.luyaoguagua.top/',start_num,"'"))
start_num += 1

后期管理

管理这么多自建图片库以及文字库是工作量很大的,本人使用Python统一管理。

STAPI

使用maintain.txt记录维护状态和可替换语句的索引。本API设计时一般不考虑更改已经部署好的Cloud flare Workers代码,因此语句总量不变。但是有些不合适的语句删除后可能导致API返回空值或者请求失败,所以随机使用empty列表中的语句库填充,同时遍历文件内容如果包含在empty列表中则认为本文件内容可以替换为新的。在文件操作时,一律使用utf-8编码,同时使用strip函数清除文件内语句两端包含的空格和换行符等,避免在网站渲染时出错(有些网站效果如在语句末闪烁的光标如遇换行符则无法显示)。

安全提醒:在git push时这些管理用文件也会同时被提交至服务器,为避免带来安全隐患,建议在文件名中加入一串难以猜测的字符串,如maintain.q5JrZ3zXmLUVy$hTSbpH.txt

Troubleshooting:本程序不能创建maintain.txt,这样做是避免覆盖了与本程序不相关的文件(如网站内本来就有一个文件叫做maintain.txt),若根目录没有这个文件则程序会报错。
请创建maintain.txt并输入

1
2
1
[]

然后再运行脚本。

下面是管理脚本,使用Python语言写成。没有写错误处理与分析结构,目前以实用为主。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import random

empty=['不乱于心,不困于情。不畏将来,不念过往。如此,安好!','深谋若谷,深交若水。深明大义,深悉小节。已然,静舒!','善宽以怀,善感以恩。善博以浪,善精以业。这般,最佳!','勿感于时,勿伤于怀。勿耽美色,勿沉虚妄。从今,进取!','无愧于天,无愧于地。无怍于人,无惧于鬼。这样,人生!','上士闻道,勤而行之。','中士闻道,若存若亡。','下士闻道,大笑之,不笑不足以为道。']
with open('maintain.txt','r',encoding='utf-8') as f:
s=eval(f.readline())
if s>=2014:
s=1
can=eval(f.readline())
print('Start from:',s,'.html\n')
print('There are',len(can),'Containers, shall we update Container\'s List?')
if input()=='1':
print('\nUpdating Container\'s List......\n')
stece=[]
for i in range(1,2024):
fn=str(i)+'.html'
with open(fn,'r',encoding='utf-8') as f:
item=f.read().strip()
if item in stece:
replace=empty[random.randint(0,7)]
with open(fn,'w',encoding='utf-8') as f:
f.write(replace)
else:
stece.append(item)
can=[]
for i in range(1,2024):
fn=str(i)+'.html'
with open(fn,'r',encoding='utf-8') as f:
content=f.read().strip()
if content=='十年忘不掉的是回忆,继续的是生活,错过的,就当是路过。' or content=='' or content in empty:
can.append(i)
with open('maintain.txt','w',encoding='utf-8') as f:
f.write(str(s))
f.write('\n')
f.write(str(can))
print('Container\'s List has been updated, now we have',len(can),'Containers.\n')

print('Please select mode:\n')
mode=eval(input('0: Select Containers.\n1: Add new sentences.\n'))
print()
if mode==0:
while True:
for i in range(61):
num=str(int(s)+i)
fn=num+'.html'
with open(fn,'r',encoding='utf-8') as f:
raw=f.read()
polish=raw.strip()
if polish != raw:
with open(fn,'w',encoding='utf-8') as f:
f.write(polish)
if polish == '十年忘不掉的是回忆,继续的是生活,错过的,就当是路过。':
print('<!--more-->')
else:
print(num,'、',polish)

kill=input('Please select sentences to del (separate No. with space).').split()
for i in kill:
fn=i+'.html'
with open(fn,'w',encoding='utf-8') as f:
f.write('十年忘不掉的是回忆,继续的是生活,错过的,就当是路过。')
with open('maintain.txt','w',encoding='utf-8') as f:
maintain=str(int(num)+1)
f.write(maintain)
f.write('\n')
f.write(str(can))


if mode==1:
while True:
stece=input('Please input your sentence:').strip()
fn=str(can[0])+'.html'
with open(fn,'w',encoding='utf-8') as f:
f.write(stece)
print('Done! We modified',can[0],'.html this time.')
del can[0]

IMAPI

功能比较鸡肋,只能删除不想要的图片并使用0.jpg替换。正在完善

1
2
3
4
5
6
7
8
9
import os
while True:
i=input('Change which picture?\n')
fn=str(i)+'.jpg'
cmd='copy 0.jpg '+i+'.jpg'
print(cmd)
os.remove(fn)
os.system(cmd)
print('Done!')
 Comments
Comment plugin failed to load
Loading comment plugin