egg-mode-rs / egg-mode Goto Github PK
View Code? Open in Web Editor NEWa twitter api crate for rust
Home Page: https://crates.io/crates/egg-mode
License: Mozilla Public License 2.0
a twitter api crate for rust
Home Page: https://crates.io/crates/egg-mode
License: Mozilla Public License 2.0
There is a newish API for "Subscribing to account activity": https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/overview
So far I'm happy just issuing my own requests for that, but I figured a 'let you know' / 'tracking issue' wouldn't go amiss.
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.
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.
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):
lastly, thanks for creating this crate! it's been fun using this project to learn rust!
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).
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:
auth
to determine what can reasonably be made publicauth
things that i don't want to expose, but are still used outside the auth module, to common
and make auth
publicToken
docs to auth
module docs, since that's a way better place for the authentication overviewauth
that i wind up exposingcommon::response::make_future
into TwitterFuture::new
, make it publiccommon::response::rate_headers
into Response::<()>::from_headers
, make it publicauth::raw
as something approaching a generic OAuth libraryThe 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.
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.
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
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.
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.
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
?
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 Timeline
s 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.
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?
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.
➜ 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?
I'd like to begin the process of adding support for lists. I've already added some (very basic) functionality. Should I continue?
Twitter search API has the include_entities param that I need to use, but it is not yet available con egg_mode
https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html
https://developer.twitter.com/en/docs/tweets/filter-realtime/guides/basic-stream-parameters
filter_level
This parameter may be used on all streaming endpoints, unless explicitly noted.
language
This parameter may be used on all streaming endpoints, unless explicitly noted.
GET statuses/sample
can take these parameters, too. It would be great if egg_mode::stream::sample
provided interface for them.
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 :)
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 :)
I should bump egg-mode to take advantage of the new release of hyper. This issue collects my thoughts on what it would take.
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 directlymake_future
's closure takes the headers, so that would need to take a HeaderMap
insteadHandle
, as the tokio runtime can implicitly use one
>_>
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.
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
It seems for Tweet only Deserialize is implemented and not Serialize
https://github.com/egg-mode-rs/egg-mode/blob/master/src/tweet/mod.rs#L236
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 1.41.0
[dependencies]
egg-mode = { version = "0.13", features = ["hyper-rustls"], default-features = false }
futures = "0.3"
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();
}
$ 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.
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.
The last update on crates.io from November 30 2016; the library seems to have changed fairly significantly since then.
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!
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"}
TimelineFuture
and UploadFuture
)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
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.
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.
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.
Currently, tweet::TimelineFuture
and user::UserSearch
do not implement Send
, and this is due to FutureResponse<T>
, which is defined as below.
Is it possible to change this into Pin<Box<dyn Future<Output = error::Result<Response<T>>> + Send>>
?
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!
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?
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.
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.
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.
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.
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
:'(
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
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.)
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.
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?
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.
From a discussion on IRC a while back, there are a few issues with using some of the API structs as-is:
.char_indices().enumerate()
to actually slice out the text in questionThese 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.
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.
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!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.