Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ runs:
- name: Build release
if: ${{ inputs.release == 'true' }}
shell: bash
run: cargo build --target ${{ inputs.target }} -r
run: cargo build --release --target ${{ inputs.target }} -r
7 changes: 1 addition & 6 deletions .github/workflows/build-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
override: true
toolchain: nightly-2023-09-06
components: rustfmt, clippy
uses: dsherret/rust-toolchain-file@v1

- name: Show Rust toolchain version
shell: bash
Expand Down
10 changes: 2 additions & 8 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
ref: ${{ github.ref }} # github.ref 变量将自动填充为触发事件的分支或标签名

- name: Setup Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
override: true
toolchain: nightly-2023-09-06
components: rustfmt, clippy
uses: dsherret/rust-toolchain-file@v1

- name: Setup musl-tools
if: matrix.targets.target == 'x86_64-unknown-linux-musl'
Expand Down Expand Up @@ -99,4 +94,3 @@ jobs:
uses: softprops/action-gh-release@v1
with:
files: ${{ steps.gen-name.outputs.NAME }}.zip

8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "cnb"
name = "cnblogs_lib"
# WRN: Version will be updated by CI while create a tag, NERVER change this.
version = "0.0.0-dev"
edition = "2021"
Expand All @@ -8,6 +8,7 @@ license = "MIT"
repository = "https://github.com/cnblogs/cli"
keywords = ["cli", "cnblogs", "blog"]
categories = ["command-line-utilities"]
default-run = "cnb"

[profile.dev]
lto = true
Expand Down Expand Up @@ -47,3 +48,7 @@ colored = "2.0.4"
terminal_size = "0.2.6"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[bin]]
name = "cnb"
path = "src/bin/cnb.rs"
70 changes: 70 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Cnblogs 命令行工具

[![Build / Release](https://github.com/cnblogs/cli/actions/workflows/build-release.yml/badge.svg)](https://github.com/cnblogs/cli/actions/workflows/build-release.yml)
[![Build / Development](https://github.com/cnblogs/cli/actions/workflows/build-dev.yml/badge.svg)](https://github.com/cnblogs/cli/actions/workflows/build-dev.yml)

从 CLI 访问 cnblogs。

## Cnbogs Cli 设计

从Cnblogs的[OpenAPI](https://api.cnblogs.com/help)来说,API主要有以下几类:

1. Token: 认证
2. Users: 仅提供当前登录用户信息
3. Blogs: 博客的CURD及其评论的查看和增加,
4. Marks: 收藏的CURD
5. News: 新闻的查询,新闻评论的CURD
6. Statuses: 闪存CURD。
7. Questions: 问题相关操作
8. Edu: 班级相关
9. Articles: 知识库的查找。
10. Zzk: 找找看

### cli的使用

目前cli的使用如下:

```shell
# Check your post list
cnb post --list
# Check your post
cnb --id 114514 post --show
# Create and publish post
cnb post create --title 'Hello' --body 'world!' --publish
# Change your post body
cnb --id 114514 post update --body 'niconiconiconi'

# Show ing list
cnb ing list
# Publish ing
cnb ing --publish 'Hello world!'
# Comment to ing
cnb --id 114514 ing --comment 'Awesome!'

# Check your user infomation
cnb user --info
```

大体上使用如上的设计,支持子命令,相关操作的设计按照RESTFUL的思路设计实现,博客的相关操作设计如下:

```shell
cnb posts [comment] [list,create,query,delete,update] --[id/file/quertset] --[pagesize,pagecount]
```

## 闪存cli

闪存cli设计如下:

```sh
cnb ing query # 默认10条s
cnb ing query --id 123456 --id 123
cnb ing query -n 1 -s 10
cnb ing query --type f -n 2 -s 10
# 根据tag查找,-g为tag名称 -n 2 -s 10 分页
cnb ing query -t t -g Linux
cnb ing create hello --private --lucky
cnb ing create hello --private --lucky --tag hello
cnb ing delete --id 123456
```

TODO: “提到我”存在解析问题。待完善。
5 changes: 5 additions & 0 deletions rust-fmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
max_width = 79 # 设置最大行宽为 100 个字符
tab_spaces = 4 # 设置缩进宽度为 4 个空格
edition = "2021" # 设置 Rust 版本(根据实际项目版本进行调整)
use_small_heuristics = "Max" # 设置换行策略
newline_style = "Auto" # 设置换行符风格,根据平台自动选择
5 changes: 3 additions & 2 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[toolchain]
profile = "default"
channel = "nightly-2023-12-27"
profile = "minimal"
channel = "nightly-2024-01-01"
components = [ "rustfmt", "clippy" ]
61 changes: 61 additions & 0 deletions src/apis/ing/comment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! 闪存评论相关
//!

use anyhow::{Ok, Result};
use reqwest::{Client, Response};
use serde::{Deserialize, Serialize};

use crate::{api::ing::get_comment_list::IngCommentEntry, infra::http::RequestBuilderExt, openapi};

/// 闪存评论及评论回复
///
/// replay_to: 在web端有一个ReplyToUserId,这里盲猜是这个
/// parent_comment_id: 0 是对某条闪存评论,如果对闪存评论要回应,这里则是闪存评论的id
/// content: 评论内容。 如果是对闪存评论回应,则应加上`@用户名称`
///
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")]
#[serde(default)]
pub struct StatusComment {
#[serde(skip)]
pub status_id: String,
pub replay_to: u64,
pub parent_comment_id: u64,
pub content: String,
}

/// 根据闪存ID发表一个评论
pub async fn post(token: String, sc: StatusComment) -> Result<Response> {
let r = Client::new()
.post(openapi!("/statuses/{}/comments", sc.parent_comment_id))
.pat_auth(token.as_str())
.form(&sc)
.send()
.await?
.error_for_status()?;
Ok(r)
}

/// 根据闪存ID获取评论
pub async fn get(token: &str, status_id: &str) -> Result<Vec<IngCommentEntry>> {
let r = Client::new()
.get(openapi!("/statuses/{}/comments", status_id))
.pat_auth(token)
.send()
.await?
.error_for_status()?
.json()
.await?;
Ok(r)
}

/// 根据闪存ID和commentid删除评论
pub async fn delete(token: &str, status_id: &str, comment_id: &str) -> Result<()> {
Client::new()
.delete(openapi!("/statuses/{}/comments/{}", status_id, comment_id))
.pat_auth(token)
.send()
.await?
.error_for_status()?;
Ok(())
}
Loading