-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tweet new threads in NG.announce #97
Comments
|
Here's a module ircsink;
import std.datetime;
import std.string;
import common;
import user;
import ae.net.oauth.common;
final class TwitterSink : NewsSink
{
static struct Config
{
string consumerKey;
string consumerKeySecret;
string oauthAccessToken;
string oauthAccessTokenSecret;
}
this(Config config)
{
this.config = config;
OAuthConfig oAuthConfig = {
consumerKey: config.consumerKey,
consumerSecret: config.consumerKeySecret
};
OAuthSession session = {
config: oAuthConfig,
token: config.oauthAccessToken,
tokenSecret: config.oauthAccessTokenSecret
};
this.session = session;
}
protected:
override void handlePost(Post post, Fresh fresh)
{
import std.uri;
if (!fresh)
return;
if (post.time < Clock.currTime() - dur!"days"(1))
return; // ignore posts older than a day old (e.g. StackOverflow question activity bumps the questions)
// TODO: if NG.announce
// TODO: get title + user
tweet("%s by %s #dlang".format("title", "author"));
}
void tweet(string message)
{
import std.algorithm, std.array;
import std.net.curl;
import std.format;
import std.datetime;
import std.stdio;
import ae.net.http.common;
import ae.net.ietf.url;
auto parameters = new UrlParameters[](1);
parameters[0]["status"] = message;
string url = "https://api.twitter.com/1.1/statuses/update.json";
string queryString = parameters.map!(ps => ps.pairs.map!(p => session.encode(p.key) ~ "=" ~ session.encode(p.value))).joiner.join("&");
auto http = HTTP((url ~ "?" ~ queryString));
http.method = HTTP.Method.post;
http.addRequestHeader("Authorization", session.prepareRequest(url, "POST", parameters).oauthHeader);
http.verbose = true;
http.contentLength = 0;
http.perform();
}
private:
immutable Config config;
OAuthSession session;
}(I won't have time to work on this for the next days - if you have time and want to finish this, please do) |
|
Thanks for this! I'll add this in a bit.
Wow, I totally forgot I wrote that.
Any reason this has to be an array that I'm not seeing?
Does Twitter really expect the GET parameters to be encoded exactly the same as OAuth ones? I.e. wouldn't a normal |
|
You are very welcome. As you know I have realized that things happen a lot faster when you do most of the work :)
That's what your oAuth API expects.
Yeah, it took a lot of trial and error to figure out how to do it correctly. Note that encode is a specific version of this: static alias oauthEncode = encodeUrlPart!(c => std.ascii.isAlphaNum(c) || c=='-' || c=='.' || c=='_' || c=='~'); |
The method is variadic, so it can either take an array or any number of arguments of that type. |
|
Hmm, I can't get it to work... just get 401 Unauthorized. Are you sure the OAuth session strings are meant to be part of the configuration, and we aren't supposed to get them from some authentication endpoint? Pushed a WIP: https://github.com/CyberShadow/DFeed/blob/master/src/dfeed/sinks/twitter.d |
|
Yeah, here's how I tested it without running DFeed: void main(string[] args)
{
import std.algorithm, std.array;
import std.net.curl;
import std.format;
import std.datetime;
import std.stdio;
import ae.net.oauth.common;
import ae.net.http.common;
import ae.net.ietf.url;
static struct Config
{
string consumerKey = "xxx";
string consumerKeySecret = "xxx";
string oauthAccessToken = "xxx";
string oauthAccessTokenSecret = "xxx";
}
Config config;
OAuthConfig oAuthConfig = {
consumerKey: config.consumerKey,
consumerSecret: config.consumerKeySecret
};
OAuthSession session = {
config: oAuthConfig, token:
config.oauthAccessToken,
tokenSecret: config.oauthAccessTokenSecret
};
auto parameters = new UrlParameters[](1);
parameters[0]["status"] = "%s by %s #dlang".format("title", "author");
string url = "https://api.twitter.com/1.1/statuses/update.json";
string queryString = parameters.map!(ps => ps.pairs.map!(p => session.encode(p.key) ~ "=" ~ session.encode(p.value))).joiner.join("&");
auto http = HTTP((url ~ "?" ~ queryString));
http.method = HTTP.Method.post;
http.addRequestHeader("Authorization", session.prepareRequest(url, "POST", parameters).oauthHeader);
http.verbose = true;
http.contentLength = 0;
http.perform();
} |
That's only if we would do OAuth for costumer - for sole API usage Twitter provides these "consumer keys". |
|
OK, figured it out. |
|
Deployed; hopefully it will work. BTW, a much simpler way to do this would have been to plug in https://forum.dlang.org/feed/threads/announce into https://ifttt.com/connect/feed/twitter OSLT. |
I made bad experiences with such services in the past. They tend to randomly break, limit the usage, or just start to charge you for it.
Awesome! Thanks! |
Ouch.
Yes, but Twitter already isn't, so how much worse can it get? :) |
|
Works nicely: https://twitter.com/dlang_ng/status/959511178656575489 :) Do you want to make a short announcement? |
|
Eh. Feel free to if you feel there should be one, you did the initial
implementation after all :)
…On Fri, Feb 2, 2018 at 7:42 PM, Sebastian Wilzbach ***@***.*** > wrote:
Works nicely: https://twitter.com/dlang_ng/status/959511178656575489 :)
Do you want to make a short announcement?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#97 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAJ0fk_u4Lj8GwbATYC1iuhYIAkuXUM-ks5tQ2UKgaJpZM4R1mNU>
.
|
From: https://forum.dlang.org/post/p4uubg$1rbl$1@digitalmars.com
<title> #dlangI went ahead and created an account: https://twitter.com/dlang_ng and have send you the credentials.
I will look now at how to do this best in DFeed, but maybe it's a simple change for you?
The text was updated successfully, but these errors were encountered: