#pocket #web-services #web-api #api #afterread #rust

getpocket

Rust 包用于 GetPocket API (https://getpocket.com/)

12 个版本

0.2.5-rc32024 年 1 月 9 日
0.2.5-rc12024 年 1 月 4 日
0.2.3 2023 年 3 月 27 日
0.2.2 2022 年 10 月 18 日
0.1.0 2022 年 8 月 26 日

#485网页编程

每月 31 次下载

自定义许可

47KB
909

GetPocket API 包

官方 GetPocket API 文档 https://getpocket.com/developer/docs/overview

Build Publish

许可: AGPL-3.0-only

Crates.io

https://crates.io/crates/getpocket

文档

https://docs.rs/getpocket/latest/getpocket/

如何使用

cargo add getpocket
use getpocket::{adding::AddingExt, GetPocket}; 

let get_pocket = GetPocket::new(consumer_key, redirect_url, access_token).await?;
get_pocket.add_item("https://getpocket.com/developer/docs/v3/add").await?;

可以通过内置的 GetPocket::init 方法获取 GetPocket 令牌,或者您可以使用现成的请求执行方法。

上下文

项目列表

fn main() {
    let consumer_key = std::env::var("GET_POCKET_CONSUMER_KEY").expect("ENV must be set");
    let redirect_url = std::env::var("GET_POCKET_REDIRECT_URL").expect("ENV must be set");
    let access_token = std::env::var("GET_POCKET_ACCESS_TOKEN").expect("ENV must be set");

    let get_pocket = GetPocket::new(consumer_key, redirect_url, access_token)
        .await
        .expect("Cannot init GetPocket instance");

    let _ = get_pocket.list_of_items().await.unwrap();
}

响应:项目列表

RecordItem {
    status: 1,
    complete: Some(
        1,
    ),
    error: None,
    since: 9999999999,
    list: {
        "3302700367": Object {
            "excerpt": String("What is"),
            "favorite": String("0"),
            "given_title": String(""),
            "given_url": String("https://www.site.com/path/"),
            "has_image": String("1"),
            "has_video": String("0"),
            "is_article": String("1"),
            "is_index": String("0"),
            "item_id": String("9999999999"),
            "lang": String("en"),
            "listen_duration_estimate": Number(9999),
            "resolved_id": String("9999999999"),
            "resolved_title": String("Top 25"),
            "resolved_url": String("https://www.site.com/path/"),
            "sort_id": Number(0),
            "status": String("0"),
            "time_added": String("9999999999"),
            "time_favorited": String("0"),
            "time_read": String("0"),
            "time_to_read": Number(99),
            "time_updated": String("9999999999"),
            "top_image_url": String("https://www.site.com/path.jpg"),
            "word_count": String("99"),
        },
    },
}

添加新项目

fn main() {
    let consumer_key = std::env::var("GET_POCKET_CONSUMER_KEY").expect("ENV must be set");
    let redirect_url = std::env::var("GET_POCKET_REDIRECT_URL").expect("ENV must be set");
    let access_token = std::env::var("GET_POCKET_ACCESS_TOKEN").expect("ENV must be set");

    let get_pocket = GetPocket::new(consumer_key, redirect_url, access_token)
        .await
        .expect("Cannot init GetPocket instance");

    let _ = get_pocket.add_item("https://getpocket.com/developer/docs/v3/add").await.unwrap();
}

响应:添加新项目

RecordAdded {
    item: {
        "authors": Array [],
        "content_length": String("9999"),
        "date_published": String("0000-00-00 00:00:00"),
        "date_resolved": String("9999-12-31 23:59:59"),
        "domain_id": String("9999999"),
        "domain_metadata": Object {
            "greyscale_logo": String("https://logo.clearbit.com/getpocket.com?size=800&greyscale=true"),
            "logo": String("https://logo.clearbit.com/getpocket.com?size=800"),
            "name": String("Pocket"),
        },
        "encoding": String("utf-8"),
        "excerpt": String("Allowing users to add articles, videos, images and URLs to Pocket is most likely the first type of integration that you’ll want to build into your application. Adding items to Pocket is easy. In order to use the /v3/add endpoint, your consumer key must have the \"Add\" permission."),
        "extended_item_id": String("999999999"),
        "given_url": String("https://getpocket.com/developer/docs/v3/add"),
        "has_image": String("0"),
        "has_video": String("0"),
        "images": Array [],
        "innerdomain_redirect": String("0"),
        "is_article": String("1"),
        "is_index": String("0"),
        "item_id": String("999999999"),
        "lang": String("en"),
        "login_required": String("0"),
        "mime_type": String("text/html"),
        "normal_url": String("http://getpocket.com/developer/docs/v3/add"),
        "origin_domain_id": String("9999999"),
        "resolved_id": String("999999999"),
        "resolved_normal_url": String("http://getpocket.com/developer/docs/v3/add"),
        "resolved_url": String("https://getpocket.com/developer/docs/v3/add"),
        "response_code": String("200"),
        "time_first_parsed": String("0"),
        "time_to_read": Number(9),
        "title": String("Pocket"),
        "used_fallback": String("0"),
        "videos": Array [],
        "word_count": String("999"),
    },
    status: 1,
}

访问令牌

async fn main() {
    let consumer_key = std::env::var("GET_POCKET_CONSUMER_KEY").expect("ENV must be set");
    let redirect_url = std::env::var("GET_POCKET_REDIRECT_URL").expect("ENV must be set");

    // This is necessary to set one times and save the token
    let pocket = GetPocket::init(consumer_key, redirect_url, |access_token| {
                // ! save ACCESS_TOKEN for next requests
                println!("Access token is {}",  access_token);
            }, |auth_url| {
                // ! redirect the user to Pocket WEB site to authorize this application's request token
                println!("Open in browser next URL {}",  auth_url);
            })
            .await
            .expect("Cannot init GetPocket instance");
}

可能的用途

extern crate getpocket;
use getpocket::GetPocket;
use webbrowser;
use std::{thread, time};

#[tokio::main]
async fn main() {
    let get_pocket: GetPocket = init_get_pocket().await;

    let _ = get_pocket.list_of_items_with_params(
        RecordItemState::All,
        RecordItemFavorite::All,
        RecordItemTag::All,
        RecordItemContentType::All,
        RecordItemSort::All,
        RecordItemDetailType::All,
        None,
        None,
        None,
        0,
        25,
    ).await.unwrap();
}

async fn init_get_pocket() -> GetPocket {
    let consumer_key = std::env::var("GET_POCKET_CONSUMER_KEY").expect("ENV must be set");
    let redirect_url = std::env::var("GET_POCKET_REDIRECT_URL").expect("ENV must be set");
    let mut current_path = std::env::current_exe().unwrap();
    current_path.pop();

    let db = rocksdb::DB::open_default(&format!("{}/database", current_path.display())).unwrap();

    let get_pocket = match db.get("access_token").unwrap() {
        Some(access_token) => {
            let access_token = String::from_utf8(access_token).unwrap();
            let pocket = GetPocket::new(consumer_key, redirect_url, access_token)
                .await
                .expect("Cannot init GetPocket instance");
            pocket
        }
        None => {
            let pocket = GetPocket::init(
                consumer_key,
                redirect_url,
                |access_token| {
                    db.put("access_token", access_token).unwrap();
                },
                |auth_url| {
                    let ret = webbrowser::open(auth_url).is_ok();

                    let wait_time = time::Duration::from_millis(6000);
                    thread::sleep(wait_time);

                    Ok(ret)
                },
            )
            .await
            .expect("Cannot init GetPocket instance");

            pocket
        }
    };

    get_pocket
}

直接使用 GetPocket API

目前,该包处于早期阶段,正在积极开发中。如果您没有找到所需的方法,我们建议使用 send_params_direct 函数向 GetPocket API 发送请求。此函数包括自动错误处理并传输请求所需的所有令牌。请放心,此方法将在包的后续版本中保留。您不必担心新版本会替换或更改它。

use serde::{Serialize, Deserialize};
use serde_urlencoded;

#[derive(Debug, Serialize, Deserialize)]
struct MyStruct {
    action: String,
    item_id: String,
    time: String,
}

fn main() {
    let my_struct = MyStruct {
        action: String::from("favorite"),
        item_id: String::from("229279689"),
        time: String::from("1348853312"),
    };

    let get_pocket = GetPocket::new(consumer_key, redirect_url, access_token)
        .await
        .expect("Cannot init GetPocket instance");

    let url_encoded_string = serde_urlencoded::to_string(&[("actions", serde_json::to_string(&vec![my_struct]).unwrap())]).unwrap();

    let _ = get_pocket
        .send_params_direct(&url_encoded_string)
        .await;
}

响应:存档项目

RecordModified {
    action_results: [
        true,
    ],
    status: 1,
}

运行示例

cargo run --example list
cargo run --example add
cargo run --example modify

运行测试

cargo tests

依赖项

  • tokio
  • reqwest
  • async-trait
  • serde
  • serde_json
  • serde_urlencoded
  • anyhow
  • thiserror

功能

此即将推出的功能使用新的 API,可能是不稳定的,API 可能会发生变化。请自行承担风险使用。

[dependencies]
getpocket = { version = "*", features = ["unstable"] }

文章查看 API 和 偏好 API (WIP)

[dependencies]
getpocket = { version = "*", features = ["extended"] }

依赖项

~6–18MB
~275K SLoC