From 19ac9aa209f0543e567eb31853ab0ed794e30892 Mon Sep 17 00:00:00 2001 From: Pylogmon Date: Mon, 25 Sep 2023 11:22:22 +0800 Subject: [PATCH] feat: Support Shanbay --- README.md | 71 +-------------------------------------------------- README_EN.md | 71 +-------------------------------------------------- anki.svg | 1 - icon.png | Bin 0 -> 10135 bytes info.json | 10 ++++---- src/lib.rs | 55 +++++++++++++++++++++++++++++---------- 6 files changed, 48 insertions(+), 160 deletions(-) delete mode 100644 anki.svg create mode 100644 icon.png diff --git a/README.md b/README.md index a462e0b..8f88461 100644 --- a/README.md +++ b/README.md @@ -1,70 +1 @@ -# Pot-App 生词本插件模板仓库 (以 [Anki](https://apps.ankiweb.net) 为例) - -### [English](./README_EN.md) | 简体中文 - -### 此仓库为模板仓库,编写插件时可以直接由此仓库创建插件仓库 - -## 插件编写指南 - -### 1. 插件仓库创建 - -- 以此仓库为模板创建一个新的仓库 -- 仓库名为 `pot-app-collection-plugin-<插件名>`,例如 `pot-app-collection-plugin-anki` - -### 2. 插件信息配置 - -编辑 `info.json` 文件,修改以下字段: - -- `id`:插件唯一 id,必须以`[plugin]`开头,例如 `[plugin].com.pot-app.anki` -- `homepage`: 插件主页,填写你的仓库地址即可,例如 `https://github.com/pot-app/pot-app-collection-plugin-template` -- `display`: 插件显示名称,例如 `Anki` -- `icon`: 插件图标,例如 `anki.svg` -- `needs`: 插件依赖,一个数组,每个依赖为一个对象,包含以下字段: - - `key`: 依赖 key,对应该项依赖在配置文件中的名称,例如 `port` - - `display`: 依赖显示名称,对应用户显示的名称,例如 `端口号` - -### 3. 插件编写/编译 - -编辑 `src/lib.rs` 实现 `collection` 函数 - -#### 输入参数 - -```rust - source: &str, // 原文 - target: &str, // 译文 - from: &str, // 原文语言代码 - to: &str, // 译文语言代码 - needs: HashMap, // 插件需要的其他配置信息,由info.json定义 -``` - -#### 返回值 - -```rust -// 返回用Value包裹的true - return Ok(Value::Bool(true)); -``` - -#### 测试/编译 - -```bash -cargo test --package plugin --lib -- tests --nocapture # 运行测试用例 -cargo build --release # 编译 -``` - -### 4. 打包 pot 插件 - -1. 在`target/release`目录找到`plugin.dll`(Windows)/`libplugin.dylib`(MacOS)/`libplugin.so`(Linux)文件,统一删除`lib`前缀. - -2. 将`plugin.dll`/`libplugin.dylib`/`libplugin.so`文件和`info.json`以及图标文件压缩为 zip 文件。 - -3. 将文件重命名为`<插件id>.potext`,例如`[plugin].com.pot-app.anki.potext`,即可得到 pot 需要的插件。 - -## 自动编译打包 - -本仓库配置了 Github Actions,可以实现推送后自动编译打包插件。 - -每次将仓库推送到 GitHub 之后 actions 会自动运行,将打包好的插件上传到 artifact,在 actions 页面可以下载 - -每次提交 Tag 之后,actions 会自动运行,将打包好的插件上传到 release,在 release 页面可以下载打包好的插件 - -> 注意需要在仓库设置中添加一个名为`TOKEN`的 secret,值为一个有权限的 GitHub Token,用于上传 release +# Pot-App 扇贝生词本插件 diff --git a/README_EN.md b/README_EN.md index 748cb84..8406a05 100644 --- a/README_EN.md +++ b/README_EN.md @@ -1,70 +1 @@ -# Pot-App Collection Plugin Template Repository (Take [Anki](https://apps.ankiweb.net) for example) - -### English | [简体中文](./README.md) - -### This repository is a template repository. You can directly create a plugin repository from this repository when writing plugins - -## Plugin Writing Guide - -### 1. Create a plugin repository - -- Create a new repository using this repository as a template -- Named `pot-app-collection-plugin-`,Eg: `pot-app-collection-plugin-anki` - -### 2. Plugin information configuration - -Edit the `info.json` file and modify the following fields: - -- `id`: The unique ID of the plugin, which must start with `[plugin]`, for example `[plugin].com.pot-app.anki` -- `homepage`: The homepage of the plugin, simply fill in your repository address, for example `https://github.com/pot-app/pot-app-collection-plugin-template` -- `display`: The display name of the plugin, for example `Anki` -- `icon`: The icon of the plugin, for example `anki.svg` -- `needs`: Dependencies required by the plugin. It is an array where each dependency is an object that includes the following fields: - - `key`: The key of the dependency, corresponding to its name in the configuration file. For example,`port`. - - `display`: The display name of the dependency as shown to users. For example,`Port`. - -### 3. Plugin writing/compiling - -Edit `src/lib.rs` to implement `collection` function - -#### Input parameters - -```rust -source: &str, // source text -target: &str, // target text -from: &str, // source language code -to: &str, // target language code -needs: HashMap, // Additional configuration information required by the plugin, defined by info.json -``` - -#### Return value - -```rust -// Return the true wrapped by Value -return Ok(Value::Bool(true)) -``` - -#### Test/Compile - -```bash -cargo test --package plugin --lib -- tests --nocapture # run the test case -cargo build --release # Compile -``` - -### 4. Package pot Plugin - -1. Find the `plugin.dll` (Windows)/`libplugin.dylib` (MacOS)/`libplugin.so` (Linux) file in the `target/release` directory and delete the prefix `lib`. - -2. Compress the `plugin.dll`/`libplugin.dylib`/`libplugin.so`, with the `info.json` and icon files, into a zip file. - -3. Rename the file as `.potext`, for example `[plugin].com.pot-app.anki.potext`, to obtain the plugin required by pot. - -## Automatic Compilation and Package - -This repository is configured with Github Actions, which allows for automatic compilation and packaging of plugins after pushing. - -Every time the commit is pushed to GitHub, actions will run automatically and upload the packaged plugin to artifacts. The packaged plugin can be downloaded from the actions page. - -After each tag submission, actions will also run automatically and upload the packaged plugin to releases. The packaged plugin can be downloaded from the release page. - -> Please note that you need to add a secret named `TOKEN` in the repository settings. The value should be a GitHub Token with appropriate permissions, which will be used for uploading releases. +# Pot-App Shanbay Collection Plugin diff --git a/anki.svg b/anki.svg deleted file mode 100644 index 9f81442..0000000 --- a/anki.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..319c668c9c100d4ac73bf71ffc3186cef5cf5189 GIT binary patch literal 10135 zcmds71z6KzwO+hl{c8dG6oux%;`di!ePMbq3mlv;Y7wXlfwzNzY2# z4{9pX-+UX#G13!=ps%h16hG#8M|#7J($Loi01tiu@CyQfb<&dGTL5qt1Ar-W0DxTu z02YVj+EenR4H^fHvjhMTIlTP~1h^x2=-pNW7A}cE^Dh3sWLct^nFu@&1M7n`- zgu`D*zVRS11eBAF1JMSL{-(rVsYv3#B_dh#pKJ6z9Z1oZ-wq^fTRVH_?Tj$Q*%0AS`JMRwy8I(S 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 z zAS!e)`Md_NGPJI$Z=SiIHIU+XY-T;nu~~31evs(YX=1yq!x8L=m91@S0h;&3JR7La z(53}Mc`VLP@j~K@_KKCgw^~@)vN*>hF{iDL?B~M_)o0OnT2{C90{0gP`yM( zNAR5 z#Y|DLo#8@P3^W_qCXZaGuDu`)SeSYglWB0Z`d~iL)=A^xa_Tgh>%@J<;tG{T+D1cq zR%KI^UZ2X-hf)>^?utkUILHtPxF#pS{i)k1V12=GK_DY`c`|?3Z0W^< zUSGuN%Vtp`iRCm-RmBf>-&s(fS>kwIUrcw68mGTF8%Ci8O@iWJECXTlEIqc@tcYw* zQTX-OwV)>t=iY)mymN|&ba+~nvuYnuT$kl_y?pxwaVSG0%_{}WC~ zk+p;E#bIr?N1Z{SC!u7@R^CLJvl+tv3Gj&L&ogEjB1$yxVZD(0K&a;IFvAhK&DUo) z%-STm4vmsN`1AOtym#|rZu5m1&bfFA;$HTAro?i6qMG!PN!|VrI88MjM6rr_z<&V! CfdnN0 literal 0 HcmV?d00001 diff --git a/info.json b/info.json index 1926bbb..854105f 100644 --- a/info.json +++ b/info.json @@ -1,8 +1,8 @@ { - "id": "[plugin].com.pot-app.anki", + "id": "[plugin].com.pot-app.shanbay", "plugin_type": "collection", - "icon": "anki.svg", - "display": "Anki", - "homepage": "https://github.com/pot-app/pot-app-collection-plugin-template", - "needs": [{ "key": "port", "display": "端口号" }] + "icon": "icon.png", + "display": "扇贝单词本", + "homepage": "https://github.com/pot-app/pot-app-collection-plugin-shanbay", + "needs": [{ "key": "auth_token", "display": "Auth Token" }] } diff --git a/src/lib.rs b/src/lib.rs index 321a001..0c94b4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,25 +1,52 @@ -use serde_json::Value; +use serde_json::{json, Value}; use std::collections::HashMap; use std::error::Error; #[no_mangle] pub fn collection( source: &str, - target: &str, - from: &str, - to: &str, + _target: &str, + _from: &str, + _to: &str, needs: HashMap, ) -> Result> { let client = reqwest::blocking::ClientBuilder::new().build()?; - let port = match needs.get("port") { - Some(port) => port.to_string(), - None => "8765".to_string(), + let token = match needs.get("auth_token") { + Some(token) => token.to_string(), + None => return Err("Please provide token".into()), }; + let body = json!({ + "business_id": 6, + "words":[source] + }); + let res: Value = client + .post("https://apiv3.shanbay.com/wordscollection/words_bulk_upload") + .header("Cookie", format!("auth_token={}", token)) + .header("Content-Type", "application/json;charset=UTF-8") + .json(&body) + .send()? + .json()?; - let url = format!("http://localhost:{port}"); - - // Impl... - + if let Some(json) = res.as_object() { + if let Some(msg) = json.get("msg") { + return Err(msg.as_str().unwrap().to_string().into()); + } + if let Some(id) = json.get("task_id") { + let check_res: Value = client + .get("https://apiv3.shanbay.com/wordscollection/words_bulk_upload") + .query(&[("business_id", "6"), ("task_id", id.as_str().unwrap())]) + .header("Cookie", format!("auth_token={}", token)) + .send()? + .json()?; + if let Some(json) = check_res.as_object() { + if let Some(count) = json.get("failed_count") { + if count.as_u64().unwrap() > 0 { + return Err("Failed to add words".into()); + } + } + } + } + } Ok(Value::Bool(true)) } @@ -29,8 +56,8 @@ mod tests { #[test] fn try_request() { let mut needs = HashMap::new(); - needs.insert("port".to_string(), "8765".to_string()); - let result = collection("Hello", "你好", "en", "zh_cn", needs).unwrap(); - println!("{result}"); + needs.insert("auth_token".to_string(), "".to_string()); + let result = collection("pot", "你好", "en", "zh_cn", needs); + println!("{result:?}"); } }