Twitter library for Delphi
2013 fix/update: http://code.google.com/p/delphi-twitter-library/
Edit: As of December 2012 Twitter api is using GZip in every callback, so you’ll have to enable content encoding before every Get/Post call, and then load the result from a gzipped stream in the RequestDone procs.
Edit June 2012: This twitter library is now deprecated and will no longer be updated. I’ve rewritten it as a generic OAuth lib to use with both Twitter and Imgur (and any other OAuth 1.0 services) for a closed source project.
This is my take on Open Auth and Twitter for Delphi. I recently had to look into it to update a twitter plugin for my Mal Upater application, so I made this small library along with a test application TwitMee. There is barely nothing at all for Delphi, and the little
I found was overcomplicated and didn’t work with Unicode (f.e. japanese symbols etc) (my library does).
I’ve been asked by a few people to make it open source, so here’s the code, use it freely as long you comply with the GPL v3 license.
Requirements: one of the latest versions of Delphi which includes Unicode. (probably easy to adapt using Jedi’s jcl implementation
for unicode strings as well).
[download#7#format=2]
[download#7#format=1]Twitter object unit:
{ You can contact me at: https://eden.fm License Version: GPL v3 The contents of this file are subject to the GPL License Version 3 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.gnu.org/licenses/gpl.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. You may use the code freely for freeware and commercial applications, as long you keep a notice the software is using my library, and the original source of my code isn't modified. TwitterLib for Delphi v0.1. Developed by https://eden.fm Usage: see usage.pas for details. 3rd party: I'm using ICS' overbyte winsock library, which you can get at www.overbyte.be After you install that, you need to overwrite (or place in your app folder) the file "OverbyteIcsHttpProt.pas" which is included in the rar where you obtained this file. It's a slightly modified version of the ICS THttpCli component to ease a bit the header modifications before a call. - b64asm: this is a very fast implementation I found to encode into base64 I was originally using madshi's madCrypt unit, which was actually as fast, but this should be easier to distribute. } unit TwitterLib; interface Uses Windows, SysUtils, Classes, StdCtrls, b64ASM, OverbyteIcsSha1, OverbyteIcsHttpProt; Const RequestTokenURL = 'http://api.twitter.com/oauth/request_token'; RequestAccessURL = 'http://api.twitter.com/oauth/access_token'; RequestTwitURL = 'http://api.twitter.com/1/statuses/update.xml'; shell32 = 'shell32.dll'; {$EXTERNALSYM ShellExecute} function ShellExecute(hWnd: hWnd; Operation, FileName, Parameters, Directory: PWideChar; ShowCmd: Integer): HINST; stdcall; Type TwitterRequests = (trDummy, trRequestToken, trRequestAccess, trTwit); Type TwitterCli = class(TObject) private FOnReqDone: TNotifyEvent; FOnBeforeSocketCall: TNotifyEvent; // use this to set socket proxy option, since sockets are created/destroyed on demand procedure TriggerReqDone; virtual; procedure TriggerBeforeSocketCall; virtual; procedure RecreateSocket; // CallbackProc: pointer; // VCL handlers procedure HTTPClientDocEnd(Sender: TObject); procedure HTTPClientHeaderEnd(Sender: TObject); procedure HTTPClientRequestDone(Sender: TObject; RqType: THttpRequest; ErrCode: Word); procedure HTTPClientBeforeHeaderSend(Sender: TObject; const Method: string; Headers: TStrings); procedure BuildSignature; procedure GetTimeStamp; procedure GetNonce; procedure GenerateBaseURL(Method, url: string); procedure ParseTokenandTokenSecret(rawResult: string); procedure ParseAccessData(rawResult: string); public ConsumerKey: string; ConsumerSecret: string; OAuthToken: string; OAuthTokenSecret: string; AccessToken: string; AccessTokenSecret: string; AccessUserID: string; AccessScreenName: string; URLRequestToken: string; URLRequestAccess: string; URLTwit: string; SignBase: string; TStamp: string; Nonce: string; Signature: string; Postvars: Ansistring; AuthHeader: string; HTTPClient: THttpCli; RefURL: string; ResultStrings: TStringList; LastReq: TwitterRequests; DebugMode: Boolean; DebugMemo: TMemo; LastHttpStatus: Integer; AccessPIN: String; SendStatus: String; Constructor Create(CKey, CSecret: string); // virtual; Destructor Destroy; override; procedure RequestToken; // socket call procedure RequestAccess; // socket call procedure SendTwit(twit: string); // socket call procedure RequestPIN; // call browser function RequestPinURL: string; procedure SetStoredLogin(AToken, ATokenSecret: string); published property OnReqDone: TNotifyEvent read FOnReqDone write FOnReqDone; property OnBeforeSocketCall: TNotifyEvent read FOnBeforeSocketCall write FOnBeforeSocketCall; end; function UrlEncode2(const S: String): String; function UrlEncodeExceptUnicode(const S: String): String; function DateTimeToUnix(DelphiTime: TDateTime): Int64; function urlEncodeRFC3986(url: string): string; function HasUnicode(src: string): Boolean; function BuildHexedUtf8String(src: string): string; implementation function ShellExecute; external shell32 name 'ShellExecuteW'; function BuildHexedUtf8String(src: string): string; Var ut: utf8string; a: Integer; BinarySize: Integer; InputString: utf8string; StringAsBytes: array of Byte; begin Result := ''; for a := 1 to length(src) do begin if Ord(src[a]) < 255 then begin if src[a] = ' ' then Result := Result + '%2520' else Result := Result + UrlEncode2(src[a]); end else begin ut := src[a]; BinarySize := 3; // (Length(InputString) + 1) * SizeOf(Char); SetLength(StringAsBytes, BinarySize); Move(ut[1], StringAsBytes[0], BinarySize); Result := Result + '%25' + IntToHex(StringAsBytes[0], 2); Result := Result + '%25' + IntToHex(StringAsBytes[1], 2); Result := Result + '%25' + IntToHex(StringAsBytes[2], 2); end; end; end; function HasUnicode(src: string): Boolean; Var a: Integer; begin Result := False; for a := 1 to length(src) do if Ord(src[a]) > 255 then Exit(True); end; function DateTimeToUnix(DelphiTime: TDateTime): Int64; begin Result := Round((DelphiTime - 25569) * 86400); end; function UrlEncode2(const S: String): String; var I: Integer; Ch: Char; begin Result := ''; for I := 1 to length(S) do begin Ch := S[I]; if ((Ch >= '0') and (Ch <= '9')) or ((Ch >= 'a') and (Ch <= 'z')) or ((Ch >= 'A') and (Ch <= 'Z')) or (Ch = '.') or (Ch = '-') or (Ch = '_') or (Ch = '~') then Result := Result + Ch else begin // if HasUnicode(Ch) then Result := Result + BuildHexedUtf8String(Ch) { else } Result := Result + '%' + IntToHex(Ord(Ch), 2); end; end; end; function UrlEncodeExceptUnicode(const S: String): String; var I: Integer; Ch: Char; begin Result := ''; for I := 1 to length(S) do begin Ch := S[I]; if ((Ch >= '0') and (Ch <= '9')) or ((Ch >= 'a') and (Ch <= 'z')) or ((Ch >= 'A') and (Ch <= 'Z')) or (Ch = '.') or (Ch = '-') or (Ch = '_') or (Ch = '~') or HasUnicode(Ch) then Result := Result + Ch else Result := Result + '%' + IntToHex(Ord(Ch), 2); end; end; function urlEncodeRFC3986(url: string): string; var URL1: string; begin URL1 := UrlEncode2(url); URL1 := StringReplace(URL1, '+', ' ', [rfReplaceAll, rfIgnoreCase]); Result := URL1; end; Constructor TwitterCli.Create(CKey, CSecret: string); begin inherited Create; ConsumerKey := CKey; ConsumerSecret := CSecret; DebugMode := False; URLRequestToken := RequestTokenURL; URLRequestAccess := RequestAccessURL; URLTwit := RequestTwitURL; ResultStrings := TStringList.Create; end; Destructor TwitterCli.Destroy; begin ResultStrings.Free; inherited Destroy; end; procedure TwitterCli.BuildSignature; Var SignKey: string; begin SignKey := UrlEncode2(ConsumerSecret) + '&' + UrlEncode2(OAuthTokenSecret); Signature := { madCrypt.Encode } b64ASM.Base64Encode (HMAC_SHA1_EX(SignBase, SignKey)); if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Build Signature -'); Lines.Add('SignKey=' + SignKey); Lines.Add('Signature=' + Signature); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.GetTimeStamp; begin TStamp := IntToStr(DateTimeToUnix(Now)); end; procedure TwitterCli.GetNonce; Var a: Integer; begin Nonce := ''; for a := 1 to 20 do Nonce := Nonce + Chr(Random(26) + 65); end; procedure TwitterCli.GenerateBaseURL(Method, url: string); Var ver, tok, cbak: string; begin GetNonce; GetTimeStamp; if AccessPIN <> '' then ver := 'oauth_verifier=' + AccessPIN + '&' else ver := ''; // if OAuthToken <> '' then tok := 'oauth_token=' + OAuthToken + '&' else tok := ''; tok := 'oauth_token=' + OAuthToken + '&'; if LastReq <> trTwit then cbak := 'oauth_callback=oob&'; SignBase := Method + '&' + UrlEncode2(url) + '&' + UrlEncode2(cbak + 'oauth_consumer_key=' + ConsumerKey + '&' + 'oauth_nonce=' + Nonce + '&' + 'oauth_signature_method=HMAC-SHA1' + '&' + 'oauth_timestamp=' + TStamp + '&' + tok + ver // access PIN if any + 'oauth_version=1.0'); if SendStatus <> '' then SignBase := SignBase + UrlEncode2('&status=') + BuildHexedUtf8String (SendStatus); if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Generate Base URL -'); Lines.Add('base=' + SignBase); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.RequestToken; begin LastReq := trRequestToken; OAuthToken := ''; OAuthTokenSecret := ''; AccessToken := ''; AccessTokenSecret := ''; AccessPIN := ''; GenerateBaseURL('GET', URLRequestToken); BuildSignature; Postvars := 'oauth_consumer_key' + '=' + ConsumerKey + '&' + 'oauth_signature_method' + '=' + 'HMAC-SHA1' + '&' + 'oauth_signature' + '=' + UrlEncode2(Signature) + '' + '&' + 'oauth_timestamp' + '=' + TStamp + '&' + 'oauth_nonce' + '=' + Nonce + '&' + 'oauth_token' + '=' + OAuthToken + '&' + 'oauth_callback' + '=' + 'oob' + '&' + 'oauth_version' + '=' + '1.0'; RecreateSocket; HTTPClient.ExtraSendHeader := 'Authorization: OAuth oauth_nonce="' + Nonce + '", oauth_callback="oob", oauth_token="' + OAuthToken + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + TStamp + '", oauth_consumer_key="' + ConsumerKey + '", oauth_signature="' + UrlEncode2(Signature) + '", oauth_version="1.0"'; With HTTPClient do begin Reference := RefURL; RcvdStream := TMemoryStream.Create; // SendStream := TMemoryStream.Create; // SendStream.Write(postvars[1], Length(postvars)); // SendStream.Seek(0, soFromBeginning); Accept := '*/*'; url := URLRequestToken; // + '?' + postvars; ResultStrings.Clear; if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Request Token Start -'); Lines.Add('postvars=' + Postvars); Lines.Add('url=' + url); Lines.Add('----------------------------------'); end; try GetAsync; except on E: Exception do begin RcvdStream.Destroy; RcvdStream := nil; // SendStream.Destroy; SendStream := nil; ResultStrings.Text := 'ERROR ' + E.Message; LastHttpStatus := HTTPClient.StatusCode; TriggerReqDone; FreeAndNil(HTTPClient); Exit; end; end; // try end; // with end; procedure TwitterCli.RequestAccess; begin LastReq := trRequestAccess; GenerateBaseURL('GET', URLRequestAccess); BuildSignature; Postvars := 'oauth_consumer_key' + '=' + ConsumerKey + '&' + 'oauth_nonce' + '=' + Nonce + '&' + 'oauth_signature_method' + '=' + 'HMAC-SHA1' + '&' + 'oauth_signature' + '=' + UrlEncode2(Signature) + '' + '&' + 'oauth_timestamp' + '=' + TStamp + '&' + 'oauth_token' + '=' + OAuthToken + '&' + 'oauth_callback' + '=' + 'oob' + '&' + 'oauth_verifier' + '=' + AccessPIN + '&' + 'oauth_version' + '=' + '1.0'; // + '&' + // 'oauth_callback' + '=' + 'oob' + '&' + RecreateSocket; HTTPClient.ExtraSendHeader := 'Authorization: OAuth oauth_nonce="' + Nonce + '", oauth_callback="oob", oauth_token="' + OAuthToken + '", oauth_verifier="' + AccessPIN + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + TStamp + '", oauth_consumer_key="' + ConsumerKey + '", oauth_signature="' + UrlEncode2(Signature) + '", oauth_version="1.0"'; With HTTPClient do begin Reference := RefURL; RcvdStream := TMemoryStream.Create; url := URLRequestAccess; // + '?' + postvars; ResultStrings.Clear; if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Request Access Start -'); Lines.Add('postvars=' + Postvars); Lines.Add('url=' + url); Lines.Add('----------------------------------'); end; try GetAsync; except on E: Exception do begin RcvdStream.Destroy; RcvdStream := nil; ResultStrings.Text := 'ERROR ' + E.Message; LastHttpStatus := HTTPClient.StatusCode; FreeAndNil(HTTPClient); TriggerReqDone; Exit; end; end; // try end; // with end; procedure TwitterCli.SendTwit(twit: string); begin // showmessage(twit); // twit := URLEncode2(twit); // fix issue, # + unicode fails LastReq := trTwit; if HasUnicode(twit) then begin twit := UrlEncodeExceptUnicode(twit); // StringReplace(twit,'#','%2523',[rfReplaceAll]); SendStatus := twit; end else SendStatus := UrlEncode2(utf8Encode(twit)); AccessPIN := ''; GenerateBaseURL('POST', URLTwit); BuildSignature; Postvars := 'oauth_consumer_key' + '=' + ConsumerKey + '&' + 'oauth_nonce' + '=' + Nonce + '&' + 'oauth_signature_method' + '=' + 'HMAC-SHA1' + '&' + 'oauth_signature' + '=' + UrlEncode2(Signature) + '' + '&' + 'oauth_timestamp' + '=' + TStamp + '&' + 'oauth_token' + '=' + AccessToken + '&' + 'oauth_callback' + '=' + 'oob' + '&' + 'oauth_version' + '=' + '1.0'; if HasUnicode(twit) then Postvars := 'status=' + { urlencode2 } ((utf8Encode(twit))) else Postvars := 'status=' + UrlEncode2(twit); SendStatus := ''; RecreateSocket; HTTPClient.ExtraSendHeader := 'Authorization: OAuth ' + 'oauth_consumer_key="' + ConsumerKey + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + TStamp + '", oauth_nonce="' + Nonce + '", oauth_version="1.0", oauth_token="' + AccessToken + '", oauth_signature="' + UrlEncode2(Signature) + '"'; With HTTPClient do begin Reference := RefURL; RcvdStream := TMemoryStream.Create; SendStream := TMemoryStream.Create; SendStream.Write(Postvars[1], length(Postvars)); SendStream.Seek(0, soFromBeginning); url := URLTwit; // + '?' + postvars; ResultStrings.Clear; if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Request twit Start -'); Lines.Add('postvars=' + Postvars); Lines.Add('url=' + url); Lines.Add('----------------------------------'); end; try PostAsync; except on E: Exception do begin RcvdStream.Destroy; RcvdStream := nil; SendStream.Destroy; SendStream := nil; ResultStrings.Text := 'ERROR ' + E.Message; LastHttpStatus := HTTPClient.StatusCode; FreeAndNil(HTTPClient); TriggerReqDone; Exit; end; end; // try end; // with end; procedure TwitterCli.TriggerReqDone; begin if Assigned(FOnReqDone) then FOnReqDone(Self); end; procedure TwitterCli.TriggerBeforeSocketCall; begin if Assigned(FOnBeforeSocketCall) then FOnBeforeSocketCall(Self); end; procedure TwitterCli.HTTPClientDocEnd(Sender: TObject); begin // end; procedure TwitterCli.HTTPClientBeforeHeaderSend(Sender: TObject; const Method: string; Headers: TStrings); begin if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Socket Before Header Send -'); Lines.Add(Headers.Text); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.HTTPClientHeaderEnd(Sender: TObject); begin if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Socket Header End -'); Lines.Add(HTTPClient.RcvdHeader.Text); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.HTTPClientRequestDone(Sender: TObject; RqType: THttpRequest; ErrCode: Word); Label CleanUp; begin if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Request Done Socket DocEnd -'); Lines.Add('result=' + ResultStrings.Text); Lines.Add('status code=' + IntToStr(HTTPClient.StatusCode)); Lines.Add('headers=' + HTTPClient.RcvdHeader.Text); Lines.Add('----------------------------------'); end; if (RqType = httpGET) or (RqType = httpPOST) then begin if (ErrCode <> 0) or (HTTPClient.StatusCode <> 200) then Goto CleanUp; end else Exit; try HTTPClient.RcvdStream.WriteBuffer(#0' ', 1); HTTPClient.RcvdStream.Position := 0; ResultStrings.LoadFromStream(HTTPClient.RcvdStream); finally end; LastHttpStatus := HTTPClient.StatusCode; if (LastReq = trRequestToken) and (LastHttpStatus = 200) then ParseTokenandTokenSecret(ResultStrings.Text); if (LastReq = trRequestAccess) and (LastHttpStatus = 200) then ParseAccessData(ResultStrings.Text); CleanUp: HTTPClient.RcvdStream.Destroy; HTTPClient.RcvdStream := nil; if LastReq = trTwit then begin HTTPClient.SendStream.Destroy; HTTPClient.SendStream := nil; end; FreeAndNil(HTTPClient); TriggerReqDone; end; procedure TwitterCli.RecreateSocket; begin HTTPClient := THttpCli.Create(nil); With HTTPClient do begin OnDocEnd := HTTPClientDocEnd; OnHeaderEnd := HTTPClientHeaderEnd; OnRequestDone := HTTPClientRequestDone; OnBeforeHeaderSend := HTTPClientBeforeHeaderSend; TriggerBeforeSocketCall; end; end; procedure TwitterCli.ParseTokenandTokenSecret(rawResult: string); begin // parse tokens after request token if Pos('oauth_callback_confirmed=true', rawResult) = 0 then begin LastHttpStatus := 0; Exit; end; try Delete(rawResult, 1, Pos('=', rawResult)); OAuthToken := Copy(rawResult, 1, Pos('&oauth_token_secret=', rawResult) - 1); Delete(rawResult, 1, Pos('=', rawResult)); OAuthTokenSecret := Copy(rawResult, 1, Pos('&oauth_callback_confirmed=true', rawResult) - 1); except LastHttpStatus := 0; end; if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Parse Token and TokenSecret -'); Lines.Add('Token=' + OAuthToken); Lines.Add('TokenSecret=' + OAuthTokenSecret); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.RequestPIN; begin ShellExecute(0, nil, PChar('https://twitter.com/oauth/authorize?oauth_token=' + OAuthToken), '', '', SW_SHOWNORMAL); end; function TwitterCli.RequestPinURL; begin Result := 'https://twitter.com/oauth/authorize?oauth_token=' + OAuthToken; end; procedure TwitterCli.ParseAccessData(rawResult: string); begin // parse tokens after request acccess if Pos('user_id', rawResult) = 0 then begin LastHttpStatus := 0; Exit; end; try Delete(rawResult, 1, Pos('=', rawResult)); AccessToken := Copy(rawResult, 1, Pos('&oauth_token_secret=', rawResult) - 1); Delete(rawResult, 1, Pos('=', rawResult)); AccessTokenSecret := Copy(rawResult, 1, Pos('&user_id=', rawResult) - 1); Delete(rawResult, 1, Pos('=', rawResult)); AccessUserID := Copy(rawResult, 1, Pos('&screen_name=', rawResult) - 1); Delete(rawResult, 1, Pos('=', rawResult)); AccessScreenName := rawResult; OAuthToken := AccessToken; OAuthTokenSecret := AccessTokenSecret; except LastHttpStatus := 0; end; if DebugMode then if Assigned(DebugMemo) then with TMemo(DebugMemo) do begin Lines.Add('- Parse Access Data -'); Lines.Add('AccessToken=' + AccessToken); Lines.Add('AccessTokenSecret=' + AccessTokenSecret); Lines.Add('AccessUserID=' + AccessUserID); Lines.Add('AccessScreenName=' + AccessScreenName); Lines.Add('----------------------------------'); end; end; procedure TwitterCli.SetStoredLogin(AToken: string; ATokenSecret: string); begin AccessToken := AToken; AccessTokenSecret := ATokenSecret; OAuthToken := AccessToken; OAuthTokenSecret := AccessTokenSecret; end; end.
usage
// start by defining and creating the twitter object: Var Twit: TwitterCli; Twit := TwitterCli.Create(TKey, TSecret); with Twit do begin // You can specify a TMemo here for debugging purposes, which will output relevant // data sent and received to twitter. // DebugMode := True; // DebugMemo := Memo1; OnReqDone := TwitterCallBackProc; RefURL := 'https://eden.fm'; end; // TwitterCallBackProc is a simple method that's called after each request: procedure TTwitMeMain.TwitterCallBackProc(Sender: TObject); // TKey and TSecret are your app key and secret you get from Twitter after // you register your app with them // you can also specify a callback for TriggerBeforeSocketCall // which will trigger just before a socket call. Here you can alter // the socket to specify a proxy by accessing Twit.HTTPClient // (as per ICS THttpCli properties) // Next we need to request a token from Twitter: // If you had already done this step before you can skip it, look at the // end of this doc for details Twit.RequestToken; // Right after the call, control is given back to your application, since the // call is asynchronous (non-blocking). the callback proc will be called after // after we get the initial token from twitter, we need to send the user to // twitter.com so they will login and get a PIN code to enter in your app Twit.RequestPIN; // you could also use Twit.RequestPinURL // to get the URL in a string if you wish to copy it to the user in the // clipboard or any other means, in case your app fails to launch the URL // in the browser // once done, the user has to give the PIN to us, in an edit box for example, // then we tell the library the pin and request the final access tokens: Twit.AccessPIN := Edit1.Text; Twit.RequestAccess; // our callback proc will be called once again and we are ready to send // messages to twitter // always check Twit.LastHttpStatus in the callback proc, if not 200 then // something went wrong. You can check the variables ResultStrings.Text // and LastHttpStatus for details on what went wrong // now we can send a message with Twit.SendTwit('test message'); // you can also use unicode here, like Japanese kanjis // tested also with problematic symbols like # $ ! ' & etc // * Note about access request: after you complete the acess steps, // you can store these 2 string variables: // // Twit.AccessToken // Twit.AccessTokenSecret // and simply do: SetStoredLogin(a,b); // after creating the twitter object (a and b being those 2 vars we stored // and your app is ready to send without any previous steps // And that's it, pretty simple. Note that this is a very simple implementation // and we should check for other status codes from Twitter. I will be updating // the library to fully implement the entire API eventually. // a little more help. this is what my callback proc on TwitMee looks like: procedure TTwitMeMain.TwitterCallBackProc(Sender: TObject); begin if Twit.LastHttpStatus <> 200 then begin Label1.Font.Color := clRed; Label1.Caption := 'Error communicating with Twitter.'; Exit; end; if Twit.LastReq = trRequestToken then begin FlatEdit1.Text := 'Enter PIN here and click on Send button'; Twit.RequestPIN; Exit; end; if Twit.LastReq = trRequestAccess then begin Label1.Font.Color := clWhite; Label1.Caption := 'Ready to send.'; Authenticated := True; FlatEdit1.Text := ''; SaveSettings; Exit; end; if Twit.LastReq = trTwit then begin FlatEdit1.Text := ''; Label1.Caption := 'Message sent.'; Exit; end; end;
I didn’t have time to convert my generic OAuth1 lib for this, but I uploaded a fixed version of the older Twitter lib, you can get it here: http://code.google.com/p/delphi-twitter-library/
sorry, those are properties of THttpCli, so like.. with HttpCli1 do begin.. Options := etc
Hi Brian, that is Excellent, Thank you so much, I guess the new library will also get around the December 2012 issues that I have also been posting about.
Hi Brian, thanks for the response, maybe I’m a bit stupid or something, but if I put that code on any line it simply gives me the error of
Undeclared Identifier Options, and Undeclared identifier httpoEnableContentcoding.
Clearly I am not really understanding what you are suggesting, though I have no doubt that what you say works when correctly implemented
Yeah.. that was a workaround I used at the time. Well I’ll do something, give me a couple days and I’ll release my new generic library with a new demo app for twitter; watch the front page for the post.
The above code doesn’t work for me because I get ” Undeclared Identifier ExtraSendHeader “. I have tried to look that up but all I can find is some relatively old posts on ICS where it seems to say that it is to do with a custom mod that you made to ICS , but would no longer be using because there was some slightly modified code that made it unnecessary.
I would sincerely appreciate a solution.
Many thanks
just replace it with a normal TEdit
You have to modify my code, and before any Get/Post calls, simply add “Options := [httpoEnableContentCoding];”
That doesn’t work for me not least of which because it uses TFlatEditUnit which I can’t seem to locate a working download/install for D2007
Is it possible to give some more detailed instructions for those of us that aren’t that clever. I am using D2007 and I can’t really get it to work at all and I am sure it is related to what you are saying above
Hi Stephen, Sorry to say I don’t really understand a word about what you are saying with enable content encoding. Could you possibly give some code as to what I should put and where. Many thanks
Thanks for your swift reply. I think I’ve got it working in Delphi6 now.
Also add OverbyteIcsHttpCCodZLib to project source.
that’s all you need, but stable ics release doesn’t work properly with gzip, install the latest daily v8: http://wiki.overbyte.be/arch/icsv8w.zip
[re:As of December 2012 Twitter api is using GZip in every callback]…so you’ll have to enable content encoding before every Get/Post call,I guess that means adding this line (please confirm)
Options := [httpoEnableContentCoding];
…and then load the result from a gzipped stream in the RequestDone procs.
Please give an example of the Delphi code I need to put in the RequestDone procs.
I’m using ICS V1.94 which I believe already handles gzip content encoding.
this code only utf-8 but i need this char (ü,i,ğ,ç,ö). can u help for this?
i cant use ‘ü,ğ,ç,ı’ and i need.
Sorry for the late reply; haven’t worked on this for ages, maybe I’ll review it sometime, been wanting to make a full OAuth1/2 lib for a while.
Hi, not sure what’s your issue.
Hi Brian. Thanks a lot. But i have some problem about charset.
How can i change charset?
I need iso8959-9
. Please help me
http://eden.fm/twitmee/
http://eden.fm/twitmee/
Dear brian..
Can I receive 0.22 example source ?Thank you.
Thanks for your source.
Can I receive delphi example source file ?
Hello Brian.
I’m testing your code but I have some trouble with accented characters which are really common in Italian language. If i try to tweet the message “Questa è una prova”, the TwitMee app gets an OAuth error. How can I solve this?
You need the ICS sockets library: http://www.overbyte.be
Dear brian, The rar that I downloaded had only the TwitterLib.pas file, seems it didn’t include the two other files you used:
OverbyteIcsHttpProt.pas
OverbyteIcsSha1.pas
useage.pas b64ASM.pasIf possible, please send these through to [email protected]
regards Joan
Sorry I got no time for free support on this 🙁
i have error in utf8 tweets : how can i fix it ? ( i use last version
tnx for help and great library 🙂
If you are interested I’ll let you know when my app. is released.Great work and thanks for sharing your skills.
web Design london
Dear Steve,
I would like to receive your implementation in Delphi 6, it’s the only I can use in my activities. Thanks in advance.
Antonio Borges
Those files are from the ICS package as mentioned in the info about the library.
Dear brian, The rar that I downloaded had only the TwitterLib.pas file, seems it didn’t include the two other files you used:
OverbyteIcsHttpProt.pas
OverbyteIcsSha1.pas
useage.pasb64ASM.pasIf possible, please send these through to groupby at gmail.comthanks and regards,Jane
Hi brian, also the rar that I downloaded had only the TwitterLib.pas file, and didn’t include the two other files you mention:
OverbyteIcsHttpProt.pas
useage.pas
could you also please send these through to adamr99 at gmail.com
thanks and regards,
adam
Hi brian, thanks for posting this code. I’ve been comparing this code to other delphi twitter libraries and am still a bit unclear on how to make it work. As below it would be great to get the source to the latest TwitMee app so I could see where I was going wrong. please send to adamr99 at gmail.com
thanks in advance.
regards,
adam
Thanks you very much for the fast reply!
sent
hi brian,
This is a nice work you have done:)
Unfortunately, I am having difficulties in making the library work with a test sample i built with delphi 2010.
If it is possible, I would love as well to receive the source code for the TwitMee 0.22. My email is victorvicente at netcabo.pt
Thanks a lot!
Victor
Many thanks for the source brian,
I was able to get it working in Delphi6 (and with Unicode too I think). I’m using the TntComponents for Unicode.
Great work and thanks for sharing your skills.
If you are interested I’ll let you know when my app. is released.
Hi, it was made for Unicode Delphi, it won’t work as it is for 6 without some changes. I’ll send you the little app source anyway 🙂
Hello,
I’ve spent a fair while trying to get your code to work in Delphi6.
Unfortunately I’m still getting ‘Status: 401 Unauthorized’ errors’.
I’m nearly there but am now stuck.
Would it be possible for you to send me the source for TwitMee V0.22 so I can see where I’m going wrong.
My email is ‘twitter at play-time.demon.co.uk’
Many Thanks in advance
this is superb blog and i got a lot from this blog. thanks a lot form sharing this useful stuffs with us.
Hi! Nice Stuff. I want to see TwitMee sources or another example for this lib. Of course if possible. Please sent to “purrpurrpurr11 at gmail.com”. Thx. =)
sent 🙂
Hello
Please could you send me the source of the “TwitMee – 0:22” as an example of using the “Delphi library for Twitter”?
If possible, please send to “[email protected].”
Thank you.