Is there an implementation for Delphi, which connects to twitter new API, 1.1, and do operations on twitter?
they also removed all xml support, so there needs to be json operations.
the explanation from twitter site:
first we need to set an indy connection like so :
POST /oauth2/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJn
NmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip
grant_type=client_credentials
Then we could use the indy to get the twitter response :
HTTP/1.1 200 OK
Status: 200 OK
Content-Type: application/json; charset=utf-8
...
Content-Encoding: gzip
Content-Length: 140
{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}
this looks simple enough, however we need to use ssl, which force no debug with wireshark.
the code i used:
Uses EncdDecd;
Const
Consumer_Key = 'xvz1evFS4wEEPTGEFPHBog';
Consumer_Secret = 'L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg';
Host = 'api.twitter.com/';
Request_token_URL = 'https://api.twitter.com/oauth/request_token';
Twitter_Content_Type = 'application/x-www-form-urlencoded;charset=UTF-8';
var
Response:TStream;
twittersite:TIdHttp;// assume on Form
Trace:TMemo; //assume on Form
IdSSLIOHandlerSocketOpenSSL1:TIdSSLIOHandlerSocketOpenSSL;//assume on Form
function EncodeBase64String(s: string): string;
var
sIn:TSTringSTream;
begin
sIn := TStringStream.create(s);
result := String (EncodeBase64(Sin.Memory, sIn.Size));
sin.Free;
end;
begin
Response:= TMemoryStream.Create;
try
//Headers
twittersite.Request.Host := Host;
twitterSite.Request.UserAgent := 'Fucy Town 1.0';
twitterSite.Request.CustomHeaders.Add('Authorization=Basic '+EncodeBase64String(Consumer_Key+':'+Consumer_Secret));
twitterSite.Request.ContentType := Twitter_Content_Type;
twitterSite.Request.CustomHeaders.Add('grant_type=client_credentials');
//SSL
twitterSite.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
TwitterSite.Post(Request_token_URL,response);
Trace.Lines.LoadFromStream(Response);
finally
FreeAndNil(Response);
end;
end;
this result in 401 unauthorized.
what can be done to fix this code and get 200 ok?
DUMP
unit twitter;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdIntercept, IdLogBase, IdLogDebug, IdIOHandler, IdIOHandlerSocket,
IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdHTTP, StdCtrls, IdCoder, IdCoder3to4,
IdCoderMIME;
const
//https://dev.twitter.com/docs/auth/application-only-auth
URL = 'https://api.twitter.com/oauth2/token';
key = 'xvz1evFS4wEEPTGEFPHBog'; //this is example, replace with yours.
secret = 'L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg';//this is example, replace with yours.
type
TForm5 = class(TForm)
Button1: TButton;
Memo1: TMemo;
IdHTTP1: TIdHTTP;
IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
IdLogDebug1: TIdLogDebug;
IdEncoderMIME1: TIdEncoderMIME;
procedure IdLogDebug1Receive(ASender: TIdConnectionIntercept;
var ABuffer: TBytes);
procedure IdLogDebug1Send(ASender: TIdConnectionIntercept;
var ABuffer: TBytes);
procedure Button1Click(Sender: TObject);
private
parameters:TStringList;
ringBear:string;
keySecretBase64:string;
procedure initConnection;
function getRingBear(input:TStringstream):string;
function requestRingBear:TStringStream; //bearer token
procedure requestTwits;
function logoff:TStringStream;
public
{ Public declarations }
end;
var
Form5: TForm5;
implementation
{$R *.dfm}
uses IdGlobal, superobject;
procedure TForm5.initConnection;
begin
with IdSSLIOHandlerSocketOpenSSL1 do begin
SSLOptions.Method := sslvSSLv3;
SSLOptions.Mode := sslmUnassigned;
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 2;
end;
with IdHTTP1 do begin
IOHandler := IdSSLIOHandlerSocketOpenSSL1;
ReadTimeout := 0;
AllowCookies := True;
ProxyParams.BasicAuthentication := False;
ProxyParams.ProxyPort := 0;
Request.ContentLength := -1;
Request.ContentRangeEnd := 0;
Request.ContentRangeStart := 0;
Request.ContentType := 'application/x-www-form-urlencoded';
Request.Accept := 'text/html, */*';
Request.BasicAuthentication := False;
Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
HTTPOptions := [hoForceEncodeParams];
end;
IdHTTP1.Intercept := IdLogDebug1;
parameters.Clear;
IdHTTP1.Request.CustomHeaders.Clear;
end;
function TForm5.logoff:TStringStream;
begin
result := TStringStream.Create;
idhttp1.Request.CustomHeaders.AddValue('Authorization','Basic '+keySecretBase64);
parameters.Add('access_token='+ringBear);
IdHTTP1.Post('https://api.twitter.com/oauth2/invalidate_token',parameters,result);
keySecretBase64:='';
ringBear := '';
end; //the caller needs to free the stream
function TForm5.requestRingBear:TStringStream;
begin
result := TStringStream.create;
keySecretBase64 := TIdEncoderMIME.EncodeString(key+ ':' + secret, IndyTextEncoding_UTF8);
parameters.Add('grant_type=client_credentials');
Memo1.Lines.Add('secret and key ' + keySecretBase64);
IdHTTP1.Request.CustomHeaders.AddValue('Authorization','Basic '+keySecretBase64);
IdHTTP1.post(URL,parameters,result);
end;//the caller needs to free the stream
procedure TForm5.requestTwits;
begin
IdHTTP1.Request.CustomHeaders.AddValue('Authorization','Bearer ' + ringBear);
memo1.lines.add('twits response : ' +
IdHTTP1.Get('https://api.twitter.com/1.1/statuses/user_timeline.json?count=100&screen_name=twitterapi'));
end;
procedure TForm5.Button1Click(Sender: TObject);
var
json:ISuperObject;
stream:TStringStream;
begin
stream:=TStringStream.Create;
parameters:=TStringList.Create;
try
cursor := crHourGlass;
initConnection;
// return this: {"access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","token_type":"bearer"}
ringBear := getRingBear(requestRingBear);//the caller needs to free the stream
initConnection;
requestTwits;
initConnection;
logoff;//the caller needs to free the stream
finally
cursor := crDefault;
memo1.Lines.Add('stream reposne' +stream.DataString);
stream.Free;
parameters.Free;
end;
end;
function TForm5.getRingBear(input: TStringstream): string;
var
json : ISuperObject;
begin
json := TSuperObject.ParseStream(input,true);
result := json.S['access_token'];
input.Free;
end;
procedure TForm5.IdLogDebug1Receive(ASender: TIdConnectionIntercept;
var ABuffer: TBytes);
var
i: Integer;
s: String;
begin
s := '';
for i := Low(ABuffer) to High(ABuffer) do
s := s + chr(ABuffer[i]);
Memo1.Lines.Add('Recived: '+s);
end;
procedure TForm5.IdLogDebug1Send(ASender: TIdConnectionIntercept;
var ABuffer: TBytes);
var
i: Integer;
s: String;
begin
s := '';
for i := Low(ABuffer) to High(ABuffer) do
s := s + chr(ABuffer[i]);
Memo1.Lines.Add('SEND: '+s);
end;
end.
dfm needs to contain :
object Form5: TForm5
Left = 0
Top = 0
Caption = 'Form5'
ClientHeight = 546
ClientWidth = 605
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
DesignSize = (
605
546)
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 288
Top = 513
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 8
Top = 8
Width = 589
Height = 499
Anchors = [akLeft, akTop, akRight, akBottom]
Lines.Strings = (
'Memo1')
ScrollBars = ssVertical
TabOrder = 1
end
object IdHTTP1: TIdHTTP
Intercept = IdLogDebug1
IOHandler = IdSSLIOHandlerSocketOpenSSL1
AllowCookies = True
ProxyParams.BasicAuthentication = False
ProxyParams.ProxyPort = 0
Request.ContentLength = -1
Request.Accept = 'text/html, */*'
Request.BasicAuthentication = False
Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
HTTPOptions = [hoForceEncodeParams]
Left = 280
Top = 136
end
object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
Intercept = IdLogDebug1
MaxLineAction = maException
Port = 0
DefaultPort = 0
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
Left = 296
Top = 48
end
object IdLogDebug1: TIdLogDebug
OnReceive = IdLogDebug1Receive
OnSend = IdLogDebug1Send
Left = 136
Top = 192
end
object IdEncoderMIME1: TIdEncoderMIME
FillChar = '='
Left = 424
Top = 256
end
end
remarks:
you must have application registered in twitter.
you need the key and secret from the twitter.
this is application to application api mentioned here implementing the user oauth with pin code is another order of magnitude in complex, and need user activity to input the pin code. if you need more info on that look here which contains the detail explanation here with a very good diagram. the code there is not complete, and the dfm is missing. there is a full example somewhere on dropbox oauth, but i cant find it at the moment.
in delphi xe5 there is oauth client that comes with delphi, that should make your life easier.
the log out does not work.
and ringBear is reference to barney stinson ring bear in his wedding and not ring bearer, since twitter called it Bear(i think from beacon consents, not weddings)
The idea is simple. request a ringBear, then request the twits then logoff.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.