GithubHelp home page GithubHelp logo

egg-mode-rs / egg-mode Goto Github PK

View Code? Open in Web Editor NEW
372.0 7.0 65.0 1.37 MB

a twitter api crate for rust

Home Page: https://crates.io/crates/egg-mode

License: Mozilla Public License 2.0

Rust 100.00%
twitter twitter-api rust

egg-mode's People

Contributors

a2aaron avatar adwhit avatar alyoshavasilieva avatar beanieboi avatar briansmith avatar bryanhitc avatar d12i avatar doumanash avatar frewsxcv avatar hdevalence avatar itok01 avatar jkarns275 avatar kenkoooo avatar klausi avatar kuretchi avatar mehcode avatar passcod avatar quietmisdreavus avatar randers00 avatar rinhizakura avatar rksm avatar sapphire-arches avatar serprex avatar tesaguri avatar travisbrown avatar uasi avatar uesugi6111 avatar umurgdk avatar vickenty avatar wezm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

egg-mode's Issues

migrate repo to github organization

Since it's been a while since i've actively worked on this library, we should probably migrate it to its own organization so that it has its own name instead of just mine on it. We could also solve the "repo name isn't egg-mode" problem at the same time, while we're at it.

I imagine the organization members would just be me and @adwhit to begin with, since we're the current people with push access. I would also like to move the egg-mode-text library as well, even though i'm still the only maintainer of that one. I consider it to be "part of egg-mode" even though it's a separate library, so it would be nice for them to live together.

Change license to MPL?

When I initially released egg-mode, I wanted to release it under the LGPL, hoping that the library itself would be copyleft without forcing its consumers to be. However, since the terms of the LGPL specifically mention dynamic linking, this would be difficult-to-impossible to actually carry out in the Rust world, where libraries on crates.io are distributed as source and statically built into the final binary. Once this was pointed out to me, I quickly relicensed 0.1.1 as Apache2 and carried on.

Recently, the Mozilla Public License was pointed out to me. It seems to be a less-stringent copyleft, where the license applies to marked source files themselves, rather than the compilation unit as a whole. In other words, forks are copyleft, consumers aren't, just like I wanted in the beginning.

If this were still early days, I could switch and carry on. However, I'm not the only one with code in this repo any more. Fortunately, there's not that many, so I can feasibly just ask everyone in here.

To be sure, the question being asked of everyone mentioned here is: Are you okay if I relicense the next version of egg-mode to MPL? This would relicense your code contributions, so I'd like your approval before I make the switch.

tweet seems to hang when using image_gif

here is the mod i wrote: https://github.com/rickycodes/retrorecord/blob/master/src/tweet/mod.rs

this works fine when the media type is image_png, but when I try to use gif it hangs around here: https://github.com/rickycodes/retrorecord/blob/master/src/tweet/mod.rs#L47

I am calling the mod's tweet function here: https://github.com/rickycodes/retrorecord/blob/master/src/main.rs#L80

again, this works fine when called from here: https://github.com/rickycodes/retrorecord/blob/master/src/main.rs#L38

perhaps I am missing something super obvious?

here's my terminal's output (so you can see where it hangs):

image

lastly, thanks for creating this crate! it's been fun using this project to learn rust!

Occasional panics while using streaming API

While using the streaming API I occasionally get panics like

thread 'main' panicked at 'byte index 140 is out of bounds of `Woo! 🙌 CC Search now includes openly licensed images from @smithsonian, @Europeanaeu, and @sciencemuseum! 🔎 https://t.co/76rOFxYXsc`', /home/hdevalence/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/str/mod.rs:1920:47

The tweet is here: https://twitter.com/creativecommons/status/1275116645225299976

I think this is maybe related to the transformation mentioned in #90 (changing between codepoint offsets and byte offsets).

refactor the auth module so i can (finally) expose it

The auth code in egg-mode was literally the first thing i had to write, and in fact a lot of it is practically a rewrite of the same code from gifnksm/oauth-client-rs and gifnksm/twitter-api-rs because i had a hard time understanding Twitter's own documentation on it. When i was getting started, i saw several OAuth crates that were already released, but they seemed to be tied to a specific site, and built in service of another of the author's crates. I didn't want to contribute to the noise, and i felt that by pulling the authentication logic into the main crate i could polish the API surface much more.

At the same time, i didn't want to thoughtlessly expose the workings of authentication more than i needed to. To this day, the code is still rather unpolished, things are collected in a rather slipshod fashion, and now, just making the auth module public isn't enough to bind new endpoints. Ever since the async refactor, auth::{get, post} return a hyper::client::Request, which needs to be handed to TwitterFuture/RawFuture to actually execute it - an API which is also not public.

However, there's one major problem with keeping all the authentication code private: it locks down what people can do from the library. If i were actively adding more things this would be less of a problem, but egg-mode is not my primary side-project any more. Plus, Twitter is still adding and tweaking the public API, especially recently with the Direct Message events and the announcement of the Premium APIs. (Though i bet the latter is really them bringing their formerly-distinct acquisitions like Gnip into the same fold as the rest of the public API.)

From discussion in #30, i think it's possible to tweak out the code in the auth module to make more things worth exposing. Here's a rough outline of what i expect it to take:

  • Enumerate the contents of auth to determine what can reasonably be made public
  • Move auth things that i don't want to expose, but are still used outside the auth module, to common and make auth public
  • Migrate the current Token docs to auth module docs, since that's a way better place for the authentication overview
  • Do a full docs pass over everything in auth that i wind up exposing
  • Move common::response::make_future into TwitterFuture::new, make it public
  • Move common::response::rate_headers into Response::<()>::from_headers, make it public
  • Refactor the internal request-building code so i can expose auth::raw as something approaching a generic OAuth library

The functionality given to outside users will still be limited compared to what's inside the library (FromJson is still internal, and probably will never be because it's a terrible hack i wrote before i realized that the From trait exists, or that i was effectively reimplementing a deserialization library - so until i crack #11 you won't be getting full egg-mode objects from this) but it's still a way for people to use some of the machinery of egg-mode to wrap endpoints that egg-mode doesn't otherwise expose.

Anyway, i'm writing all this out to formally put it on my roadmap.

"missing field `target`" in user::relation

Consider the code:

let relation = user::relation("twitter", "jack", &token).await;
println!("relation: {:?}", relation);

This outputs:

relation: Err(DeserializeError(Error("missing field `target`", line: 1, column: 531)))

Other functions such as user::show work correctly, I only experience this error with user::relation.

The output of twurl --json-pretty '/1.1/friendships/show.json?source_screen_name=twitter& target_screen_name=jack' is:

{
  "relationship": {
    "source": {
      "id": 783214,
      "id_str": "783214",
      "screen_name": "Twitter",
      "following": false,
      "followed_by": true,
      "live_following": false,
      "following_received": null,
      "following_requested": null,
      "notifications_enabled": null,
      "can_dm": true,
      "blocking": null,
      "blocked_by": null,
      "muting": null,
      "want_retweets": null,
      "all_replies": null,
      "marked_spam": null
    },
    "target": {
      "id": 12,
      "id_str": "12",
      "screen_name": "jack",
      "following": true,
      "followed_by": false,
      "following_received": null,
      "following_requested": null
    }
  }
}

Please let me know if I am doing something incorrectly.

cannot parse tweet

UrlEntity::expanded_url is a nullable string.

diff --git a/src/entities.rs b/src/entities.rs
index 9245853..02c4cc7 100644
--- a/src/entities.rs
+++ b/src/entities.rs
@@ -192,7 +192,7 @@ pub struct UrlEntity {
     ///
     ///Meant to be used as hover-text when a user mouses over a link.
     #[serde(default)]
-    pub expanded_url: String,
+    pub expanded_url: Option<String>,
     ///The byte offsets in the companion text where the URL was extracted from.
     #[serde(rename = "indices")]
     pub range: (usize, usize),
diff --git a/src/tweet/mod.rs b/src/tweet/mod.rs
index 778eff4..5cadabc 100644

Using f32 for search::Distance enum for more accuracy

Official twitter docs says, when the accuracy parameter is just a number without a unit suffix (like km/ft) it should be considered as meters. But my tests showed sending meters doesn't works as expected on the twitter side. Surprisingly sending floating point numbers as km works much better (for example accuracy=0.4km) I needed that kind of accuracy in one of my projects, just cloned and maked the changes. I wanted to get your opinion about changung Distance unit's types to f32 from u32 before creating a pull request.

codepoints_to_bytes is buggy

Hi, thanks for this library. Recently I have jumped in to the codebase to hopefully add a few more features.

Now I might be misunderstanding this, but it appears that the codepoints_to_bytes function is wrong. Here is a failing test I put at the bottom of common/mod.rs

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_codepoints_to_bytes() {
        let unicode = "frônt Iñtërnâtiônàližætiøn ënd";
        // suppose we want to slice out the middle word.
        // 30 codepoints of which we want the middle 20;
        let mut range = (6, 26);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn");
    }
}

The problem is that *start is being mutated in place over and over again pushing it way past where it should stop. The same is true of *end although that doesn't show in this test.

The corresponding assertion at the end of the parse_basic is wrong also. It picks out the whole string but I think it should not pick the hyperlink at the end of the text.

Release current HEAD?

There's a lot of new changes from the latest released version (v0.3.0) (such as the corest features like posting tweets) and I'd like to use them, can you put up a release on crates.io?

Ability to pull DMs as a pre-sorted collection of streams by recipient

The API hooks to pull direct messages are a little wonky, compared to the way they're shown on the Twitter website. The assumed user experience for DMs is that they're shown as distinct conversations to a single account (or group, but group DMs aren't available to API clients). However, the API hooks can only return a collection of DMs that were sent or received by the authenticated user, with no regard for who the other party to the message was. It's possible to sort these streams into the expected conversations, so I'd like to offer a function that calls both sent and received, weaves the streams together by their timestamp, then splits them apart based on the other party to the message.

The design of this should be similar to Timeline, but with the raw network calls removed, and with the traversal methods returning something like a HashMap<UserID, Vec<DirectMessage>> instead. As the API endpoints allow returning up to 200 DMs per call, I'd like to offer that hook to library consumers, so that it's possible to cursor through the set of DMs just as you would by using the Timelines directly.

A possible complication is that the API can show up to 800 sent messages, but only 200 received messages. My response to limitations like this in the past is to just document them, but since this hypothetical function will call two endpoints at the same time, their separate limitations could create an awkward situation. I don't anticipate this being a deal-breaker for the idea as a whole, just something that should be stressed in documentation.


EDIT: A potentially annoying snag is that in addition to wanting to show the DM conversation as separate threads per-recipient, from a user-experience perspective a consumer would want to load the conversations from this perspective as well. However, since the endpoints don't allow for filtering per-recipient as mentioned above, this could lead to a situation where a "Load More" button is made available and doesn't load anything for several presses until it disappears entirely (because all the available DMs have been spent with conversations from other people, or because there's no way to tell that a given message was the first one sent/received with a given recipient).

A related issue is how to integrate new sets of messages with previously-returned ones. It could be possible to provide a newtype wrapper DMConversations(pub HashMap<UserID, Vec<DirectMessage>>) that contains a convenience method to load a new conversation-set into the existing one. This could also impl Deref for its contained HashMap to allow for seamless integration with its contained conversations, without having to add .0 everywhere.

Also of note is how to support "topping off" a conversation-set, i.e. loading the newest set of messages after loading conversations. It would be prudent to retain the newest-message IDs for both the "sent" and "received" streams. If only one "newest" ID for both streams was kept and used on the refresh, there's a chance that a message could be missed due to poorly synchronizing the loading of the streams.

Feature hyper-rustls requires dynamically linked CA certificates

Even if I add egg-mode like this:

egg-mode = { version = "0.14", features = ["hyper-rustls"], default-features = false }

I run into the following errors:

WARN rustls::session            > Sending fatal alert BadCertificate
ERROR server::error             > Network error: error trying to connect: invalid certificate: UnknownIssuer

I figured out that hyper-rustls started to use rustls-native-certs from v18.

How can it be fixed without adding CA certs to the root?

`log` integration

egg-mode is a pretty huge library, and it would be nice to get some debug info thrown around so i can get useful info in case someone comes in with an issue.

Conversations example doesn't work

➜  cr --example conversations
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s                      
     Running `target/debug/examples/conversations`

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: TwitterError(TwitterErrors { errors: [TwitterErrorCode { message: "Sorry, that page does not exist.", code: 34 }] })', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Has the URL changed or been removed?

No support for lists

I'd like to begin the process of adding support for lists. I've already added some (very basic) functionality. Should I continue?

Remove TwitterFuture explicit lifetimes and just clone handle

Currently TwitterFuture has lifetime dependency due to storing reference to Core's handle.
Any lifetime on Future limits its usability due to the fact that anything aside from Core::run requires static lifetime on future.
It would be better to just follow hyper's example and clone handle.

User-wise it is not convenient if you'd require to run something more complex than just chain of futures (for example conditionally scheduling jobs using Handle::spawn).

P.s. coming from my own experience since I required to box multiple futures into array and join instead of just using Handle::spawn without any boxes :)

Unauthorized for Post Requests

Hi there,

I think I misunderstand how to use the library, but maybe you could help me.

I am using this code for posting stuff (the initial intention was to post an image, but I simplified the example as you can see):

        let image = read_file(image)?;
        let handle = core.handle();

        println!("Token: {:?}", &self.token);

//        let builder = UploadBuilder::new(image, media_types::image_png())
//            .alt_text(text.clone());
//        let media_handle = core.run(builder.call(&self.token, &handle))?;

        let draft = DraftTweet::new(text); //.media_ids(&[media_handle.id]);
        let _ = core.run(draft.send(&self.token, &handle))?;

The problem is, that I am always "unauthorized" and I don't know why.
See (the tokens are manipulated for this issue):

Token: Access { consumer: KeyPair { key: "nsWWFnFz3Lqes2KFj4UhgN1", secret: "RCLAcy4LGJbYSjn9rypyZwaBnp232ZBGP9FjRELxbdPSifmf" }, access: KeyPair { key: "982523490866749440-x0uooETBKPRQzhdtdAbtqyKz7xk3F", secret: "WhdGld88LIX9FjEDtqdHoaQIPE41PDDu78SwXbJTmdM" } }
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: APIError(BadStatus(Unauthorized))', libcore/result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

I am using the following version:

egg-mode = "0.12.0"
tokio-core = "0.1.16"

I haven't tested using a bearer token, but I rather want to use an OAuth token ;)

Thanks :)

migrate to hyper 0.12

I should bump egg-mode to take advantage of the new release of hyper. This issue collects my thoughts on what it would take.

  • Migrate from typed headers to http-style headers
    • auth::TwitterOAuth can change its Scheme impl to a Display impl, effectively formatting "OAuth {}" with the contents of fmt_scheme
    • ContentType is used to set either url-encoded or json, so i can cut out the mime crate and use the strings directly
    • make_future's closure takes the headers, so that would need to take a HeaderMap instead
    • the rate-limit parsing uses custom headers, which is the most common consumer of those headers
  • Functions no longer need to take a Handle, as the tokio runtime can implicitly use one
    • ...how does the tokio runtime work anyway >_> Need to decide how to adjust documentation, whether to build hyper with its tokio runtime re-export, etc

...not sure about what else? Will probably learn more as i start the switch.

Allow calling raw API

Currently this library can only call fixed endpoints with fixed parameters.
But this does not allow you to use hidden APIs and parameters
So I want a function that returns the serde_json::Value by freely passing the URL and parameters

Compilation error message "egg_mode::common::response::TwitterFuture<egg_mode::auth::KeyPair>: core::future::future::Future` is not satisfied"

I'm a Rust newbie.

I want to try to use the egg-mode.
I made the example repository.

But my code caused a compilation error.

rustc -V

rustc 1.41.0

Dependencies

[dependencies]
egg-mode = { version = "0.13", features = ["hyper-rustls"], default-features = false }
futures = "0.3"

Code

fn main() {
    let con_token = egg_mode::KeyPair::new("consumer key", "consumer secret");
    let request_token = futures::executor::block_on(egg_mode::request_token(&con_token, "oob"));
    //    let auth_url = egg_mode::authorize_url(&request_token);
    //
    //    let verifier = "123456";
    //    let (token, user_id, screen_name) =
    //        egg_mode::access_token(con_token, &request_token, verifier).await.unwrap();
}

Build and Error

$ cargo build
   Compiling twitter-rs-playground v0.1.0 (/Users/dyoshikawa/src/github.com/dyoshikawa/twitter-rs-playground)
error[E0277]: the trait bound `egg_mode::common::response::TwitterFuture<egg_mode::auth::KeyPair>: core::future::future::Future` is not satisfied

Do you have any ideas?
Thank you for reading.

Documentation for streaming content

There seems to be functionality to stream a users timeline, but I can figure out how to use it.
I haven't found the stream module in the documentation and no example using it.
Have I been looking in the wrong area?

If clone the repository and tried using the streaming feature in an example.

Update:
I found the relevant documentation, after I realized that the stream feature was only
on master and not the previous release. I now got it to build, but not to work properly.
I'll take another look in the morning.

Missing .try_for_each() method in stream::TwitterStream

Hey everyone!

While trying to use the streaming interface, I received this error using the example in the documentation:

error[E0599]: no method named `try_for_each` found for struct `egg_mode::stream::TwitterStream` in the current scope

My code:

    let stream = filter()
        // find tweets mentioning any of the following:
        .track(&["rustlang", "python", "java", "javascript"])
        .start(&token);

    stream
        .try_for_each(|m| {
            // Check the message type and print tweet to console
            if let StreamMessage::Tweet(tweet) = m {
                println!(
                    "Received tweet from {}:\n{}\n",
                    tweet.user.unwrap().name,
                    tweet.text
                );
            }
            futures::future::ok(())
        })
        .await
        .expect("Stream error");

Did this method disappeared? Thanks for your help!

Some users can not get

println!("{:?}", core.run(egg_mode::user::show("GJ_boy1", &token)));
// Err(DeserializeError(Error("invalid type: null, expected a string", line: 1, column: 351)))
{"id":251121418,"id_str":"251121418","name":"\u30ef\u30af\u30dc\uff11","screen_name":"GJ_boy1","location":"\u4eac\u90fd","profile_location":null,"description":"911S \/ VRSCAW \/ \u30b7\u30fc\u30de \/ \u30c7\u30a3\u30a2\u30d9\u30eb","url":"http:\/\/www.disney.co.jp\/","entities":{"url":{"urls":[{"url":"http:\/\/www.disney.co.jp\/","expanded_url":null,"indices":[0,24]}]},"description":{"urls":[]}},"protected":false,"followers_count":5833,"friends_count":564,"listed_count":598,"created_at":"Sat Feb 12 13:47:39 +0000 2011","favourites_count":394340,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":3261,"lang":null,"status":{"created_at":"Tue May 28 10:37:32 +0000 2019","id":1133321401748709377,"id_str":"1133321401748709377","text":"\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306f\u5171\u901a\u5316\u3057\u3066\u30b3\u30b9\u30c8\u30c0\u30a6\u30f3\u3001\u5148\u9032\u6280\u8853\u3084\u30e1\u30fc\u30bf\u30fc\u6db2\u6676\u306f\u5168\u3066\u30aa\u30d7\u30b7\u30e7\u30f3\u3001\u305d\u308c\u3067\u3082\u6700\u4f4e\u30b0\u30ec\u30fc\u30c9\u306e\u65e5\u672c\u4ed5\u69d8\u306f\u4e57\u308a\u51fa\u3057350\u4e07\u3066\u30de\u30b8\u30672\u30b7\u30ea\u30fc\u30ba\u30b0\u30e9\u30f3\u30c9\u30c4\u30a2\u30e9\u30fc\u8cb7\u3063\u305f\u3001\u8133\u306b\u969c\u5bb3\u3092\u304a\u6301\u3061\u306e\u65b9\u5411\u3051\u306e\u8eca\u306b\u306a\u308b\u3093\u3084\u308d\u306a\u2026\u2026","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]},"source":"\u003ca href=\"http:\/\/tapbots.com\/tweetbot\" rel=\"nofollow\"\u003eTweetbot for i\u039fS\u003c\/a\u003e","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":5,"favorited":false,"retweeted":false,"lang":"ja"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/1120737070685638656\/9yJF2CCN_normal.png","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/1120737070685638656\/9yJF2CCN_normal.png","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/251121418\/1551628385","profile_link_color":"E81C4F","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null,"translator_type":"none"}

0.14 release

  • Rewrite remaining futures impls using async (TimelineFuture and UploadFuture)
  • Figure out why the conversations example isn't working ("endpoint doesn't exist")
  • Audit and update all the documentation
  • Add a changelog with migration details
  • Check the minimum required rust version
  • Update README

Unstable use of struct

struct field shorthands are unstable (see issue #37340)
   --> /Users/l/.cargo/registry/src/github.com-1ecc6299db9ec823/untrusted-0.5.0/src/untrusted.rs:313:21
    |
313 |             Slice { bytes }
    |                     ^^^^^

error: struct field shorthands are unstable (see issue #37340)
   --> /Users/l/.cargo/registry/src/github.com-1ecc6299db9ec823/untrusted-0.5.0/src/untrusted.rs:327:51
    |
327 |             self.bytes.get(r).map(|bytes| Slice { bytes })
    |                                                   ^^^^^

error: aborting due to 2 previous errors

transitioning to the v2 API

Last week Twitter announced the version 2 of their public API, which looks like a promotion of some of their "Labs" endpoints, plus some reimaginings of their API structure in general, into a new API surface. It seems like the launch of the API itself was delayed due to the security incident that also occurred last week, but it's worth tracking it as it means new work for egg-mode.

The first change i notice when looking at the Labs APIs is that they allow you to specify which fields you want to retrieve in the API call, which is great for extensibility but makes returning a statically-defined data structure (like we have been doing in egg-mode) difficult. On the other hand, this could also allow us to trim down our biggest structures, by (for example) returning only a screen name/ID for the author of a tweet instead of serializing the entire TwitterUser out.

I've yet to do a complete read-through of the current Labs APIs (not to mention whatever it will look like when they properly release the v2 API) but it does seem like there will be some rework that needs to happen to support them properly.

Extended tweets

For search, streams and possibly elsewhere, twitter exposes tweet_mode=extended to request the whole tweet text rather than a truncated version. It would be nice if it was possible to request this extended version - as far as I can tell, at the moment the lib always fetches the truncated version.

Change KeyPair to use Cow<'static, str>?

Currently, there's some lifetime proliferation surrounding tokens because the elements of KeyPair are storing Cow<'a, str>. This is primarily used within the examples to allow for the use of string literals (via include_str!() for the consumer key. This can easily be accommodated with a Cow<'static, str> without adding lifetimes to KeyPair, and by extension Token. The only problem is that I don't know whether any users of egg-mode use a non-static lifetime here.

Create a 0.13 release

Hi there and thanks a lot for this super useful library!

There is currently stuff on the master branch to make egg-mode work with OpenSSL 1.1.1 (I think the Hyper update enables that). Could you make some kind of release so that I don't have to hack in the master branch as dependency for klausi/mastodon-twitter-sync#5 ? Maybe 0.13-beta1 or something?

Thanks!

Doc hosting options

I don't have access to @QuietMisdreavus site, so can't update the doc link.

But also, docs.rs is very decent these days, so I'm inclined to just use that as a host. We wouldn't be able to use it for the master branch, but that arguably isn't really necessary - if someone is using master, they can prob build their own. Thoughts?

No proxy support

I'm trying to use egg-mode in a network that requires me to use a proxy server for all traffic going out to the public internet. I can't seem to find any support for HTTP proxy in egg-mode (though if there is one, I can close the issue). I wanted to open this issue before starting work on a PR to add support.

link audit

At some point, Twitter redesigned their API documentation, and changed the URL structure they used for each page. Naturally, this broke every link i put in my docs that pointed to their site.

Fortunately, they made it easy to figure out whether a link is going to be redirected: They also changed the subdomain that the docs are served at. The new domain is developer.twitter.com, whereas the old one was just dev.twitter.com. A quick rg -trust "dev\.twitter\.com" and rg -tmarkdown "dev\.twitter\.com" tells me that a few dozen links to old docs are hanging around somewhere on this repo. It would be worth fixing all these links so they don't get redirected to somewhere mostly unrelated to what i was trying to point at.

Building with 'hyper-rustls' feature and without 'native-tls' still requires openssl-sys crate.

I'm trying to cross-compile an application from Windows to the Pi(armv7-unknown-linux-gnueabihf).
It seems egg_mode still uses the openssl-sys crate, and therefore requires linking to OpenSSL binaries/libs.

In Cargo.toml:
egg_mode={version="0.13.0", default-features=false, features=["hyper-rustls"]}

Command:
cargo build --release --target=armv7-unknown-linux-gnueabihf

Result:

error: failed to run custom build command for `openssl-sys v0.9.49`                                                        

Caused by:
  process didn't exit successfully: `D:\MyProjects\Rust\twitter_bot01\target\release\build\openssl-sys-a844bd1d65ed445b\build-script-main` (exit code: 101)
--- stdout
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_LIB_DIR
ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_INCLUDE_DIR
ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_DIR
ARMV7_UNKNOWN_LINUX_GNUEABIHF_OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_DIR
OPENSSL_DIR unset
run pkg_config fail: "Cross compilation detected. Use PKG_CONFIG_ALLOW_CROSS=1 to override"
note: vcpkg did not find openssl as libcrypto and libssl: the vcpkg-rs Vcpkg build helper can only find libraries built for the MSVC ABI.
note: vcpkg did not find openssl as ssleay32 and libeay32: the vcpkg-rs Vcpkg build helper can only find libraries built for the MSVC ABI.

--- stderr
thread 'main' panicked at '

Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
compilation process.

Make sure you also have the development packages of openssl installed.
For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.

If you're in a situation where you think the directory *should* be found
automatically, please open a bug at https://github.com/sfackler/rust-openssl
and include information about your system as well as this message.

$HOST = x86_64-pc-windows-msvc
$TARGET = armv7-unknown-linux-gnueabihf
openssl-sys = 0.9.49

', C:\Users\pc\.cargo\registry\src\github.com-1ecc6299db9ec823\openssl-sys-0.9.49\build\find_normal.rs:150:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

convert (usize, usize) for byte offsets into Range<usize>

Right now, anything that gives text spans gives offsets as a tuple. This requires any substring access to go through a cumbersome text[range.0..range.1] to get the substring. Using std::ops::Range for these would greatly simplify getting these substrings.

Does not build with openssl 1.1.1

egg-mode currently depends on hyper-tls 0.1, which pulls in openssl 0.9.24, which doesn't build with the most recent version of openssl (sfackler/rust-openssl#994). I tried to see if I could get away with just bumping hyper-tls and native-tls, but sadly that doesn't work either. hyper-tls 0.2 still uses the old openssl, and hyper-tls 0.3 requires hyper 0.12, and thus #45. It could be that there's some magical workaround, but for the time being, we're locked in a situation where the crate doesn't build until we bump hyper :'(

MissingValue("lang")

example:

core.run(
        egg_mode::tweet::user_timeline(sn, true, true, &token, &handle)
            .with_page_size(10)
            .start(),
    )
    .unwrap();

It occurs in all APIs as far as I confirm

migrate to serde and remove FromJson

With the official deprecation of rustc-serialize, it's worth investigating what it would take to migrate onto serde 1.0. A quick migration would just swap out rustc-serialize's json handling with serde-json, but it might be possible to take out FromJson entirely and just annotate the structs themselves with the special handling I've used there so far.

This will affect the minimum rust version that egg-mode will compile with: Right now I've had an unspoken goal to support a few versions back of Rust, without committing to anything specific. The last time I checked, the earliest version I could use was 1.13, due to *ring*. Moving fully over to serde would bump this up to 1.15, due to the use of custom derive. It's not that big of a deal, just something to note. (And something to add to the travis/appveyor configurations, when the switch happens, to formally commit to a minimum supported version.)

a more prominent "caveats about the examples in this documentation" section

I've gotten comments about how the examples assume a tokio Core and Handle, and how that could be confusing for newcomers to the library, or to Tokio in general. It would be worthwhile to create a separate heading in the crate-root docs to call out this requirement, and possibly either discuss other means of using the Futures, or to more directly call out the Tokio/Futures documentation.

Consider adding maintainers

Seems like development on this library has stalled. Not a big deal, it's open-source, it happens sometimes. However I think this is the most comprehensive Rust twitter library on crates.io, and based on the stars and PRs I'm sure the community would be interested in maintaining it - I certainly would. Would you consider adding some other maintainers to help work towards a 1.0 release?

asyncify everything

egg-mode got started before futures were a thing, so i wrote everything assuming blocking i/o. A straightforward conversion involves making some kind of custom future object so i could change all the calls that touch network to return a Future instead of the Result directly.

Also this would make adding streams support fairly straightforward, since i could just use the Streams.

processing of "raw" api structs into "processed" structs for ease of use

From a discussion on IRC a while back, there are a few issues with using some of the API structs as-is:

  • Text offsets are codepoint indices, not byte offsets, requiring users to iterate with .char_indices().enumerate() to actually slice out the text in question
  • Integer types were mainly chosen to be i32 without regard to their actual use, and could be unsigned, or converted to usize, etc.
  • Large API structs are more-or-less a direct translation of the JSON coming from Twitter, but could be meaningfully broken up:
    • For example, a processed Tweet could become a collection of structs lumping related data together, like ReplyTo, Retweet, Media, etc.

These conversion steps could be a separate step from the initial parsing - providing a split-layer of structs between the "raw" and "processed" versions - or could even take the place of the current API structs, where the processing would be done immediately upon receipt, in the FromJson impls. As a mostly-unspoken goal of egg-mode as been to provide for ease of use more than a direct Twitter API experience, I'm leaning toward the latter option. I might punt on breaking the structs up until I fill in the public API more, though.

extract the text module into its own crate

I'm pretty sure my implementation of twitter-text is out of date, most likely in the TLDs list if not in somewhere else too. And now with the announcement of twitter-text 2.0, forcing egg-mode-text to follow the same (slow) cadence of egg-mode is probably not the best thing. It's also really macro-heavy, so i wouldn't be surprised if it's dragging down compile times for egg-mode.

When i originally started egg-mode, i just wanted all the twitter things in one spot, but the text module is functionally distinct from everything else in egg-mode anyway, so now i just want to rip it out so i can at least try to update it more often.

Could use some help understanding error handling

I was kicking around some code with a friend last night and we were running into a couple of different errors while using your library.

Here's the relevant fragment of the program: https://github.com/bitemyapp/my-limes/blob/master/src/main.rs#L58-L81

I broke out that big dirty manual loop to try to poke at how the CursorIter et al. worked. I have a few questions:

  • Does CursorIter bump the page numbers forward when an error is received?

  • If not, can I just sleep until the epoch timestamp Twitter returns and re-attempt a manual call?

  • If it does, should I clone the CursorIter and hold onto the previous one before call'ing to handle potential errors?

  • Does the iteration API itself do anything to handle errors like RateLimit? It didn't seem like it.

  • Is it kosher to core.run the futures returned by the cursoriter/etc. in a loop?

Sorry for bothering you but it seemed like it'd be best to ask you directly as I thought there must be something I didn't understand in your design intent WRT handling error conditions.

Thank you for your time!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.