본문 바로가기

프로그래밍/Delphi

Twitter for Delphi(델파이를 이용한 트위터 클라이언트 제작)


1. Twitter for Delphi code
  델파이를 이용한 트위터 클라이언트 제작이 가능하도록 하기 위해 만들어진 MPL(Mozilla Public License) API Source Code 입니다. SourceForge.com에 프로젝트에는 아직 등록되지 않았지만 계속 개발중인 버전이고 해서 아직 모든 예외처리는 되어 있지 않은듯 한데 델파이를 이용하여 트위터 클라이언트를 제작하고자 한다면 좋은 출발 코드가 될 듯 합니다.

{
      Mozilla Public License.

      ``The contents of this file are subject to the Mozilla Public License
      Version 1.1 (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.mozilla.org/MPL/

      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.

      The Original Code is Twitter - Delphi implementation.

      The Initial Developer of the Original Code is CB2 Enterprises, Inc.
      Portions created by

      CB2 Enterprises, Inc. are Copyright (C) 2009.
      All Rights Reserved.

      Contributor(s): ______________________________________.

      Alternatively, the contents of this file may be used under the terms
      of the _____ license (the  [___] License), in which case the provisions
      of [______] License are applicable  instead of those above.
      If you wish to allow use of your version of this file only under the terms
      of the [____] License and not to allow others to use your version of this
      file under the MPL, indicate your decision by deleting  the provisions
      above and replace  them with the notice and other provisions required
      by the [___] License.  If you do not delete the provisions above,
      a recipient may use your version of this file under either the MPL or the
      [___] License."
}

unit Twitter;

interface

uses
  Classes, IDHttp, TypInfo, SysUtils, OAuth;

type
  TTwitterDirectMessage = (ddirect_messages, dsent, dnew, ddestroy);

  TTwitterFriendship = (fcreate, fdestroy, fexists);

  TTwitterOutputFormatType = (json, xml, rss, atom);

  TTwitterObjectType = (statuses, account, users, friends, friendships,
                        direct_messages, followers, favorites, notifications,
                        blocks, help);

  TTwitterStatus = (spublic_timeline, sfriends_timeline, suser_timeline,
                    sshow, supdate, sreplies, sdestroy);

  TTwitterUser = (ufriends, ufollowers, ushow);

  TTwitter = class(TObject)
    private
      FHTTP: TIdCustomHTTP;
      FSource: string;
      FTwitterClient: string;
      FTwitterClientVersion: string;
      FTwitterClientURL: string;
      FUserName: string;
      FPassword: string;
      FConsumer: TOAuthConsumer;
      FToken: TOAuthToken;
      FRequest: TOAuthRequest;
      FHMAC: TOAuthSignatureMethod_HMAC_SHA1;
      FKey: string;
      FSecret: string;
      FOAuth_token: string;
      FOAuth_token_secret: string;
      procedure SetSource(const Value: string);
      procedure SetTwitterClient(const Value: string);
      procedure SetTwitterClientVersion(const Value: string);
      procedure SetTwitterCLientURL(const Value: string);
      function UrlEncode(const S : String) : String;
      function _IntToHex(Value: Integer; Digits: Integer): string;
      function DeleteFirstChar(input: string): string;
    protected
      function GetTwitterOutputFormatType(TwitterOutputFormatType: TTwitterOutputFormatType): string;
      function GetTwitterObjectType(TwitterObjectType: TTwitterObjectType): string;
      function GetTwitterStatus(TwitterStatus: TTwitterStatus): string;
      function GetTwitterDirectMessage(TwitterDirectMessage: TTwitterDirectMessage): string;
      function GetTwitterFriendship(TwitterFriendship: TTwitterFriendship): string;
      function GetTwitterUser(TwitterUser: TTwitterUser): string;

      function GETCommand(URL: string): string;
      function POSTCommand(URL: string; Data: TStringList): string;
    public
      constructor Create;
      function GetPublicTimeLine(OutputFormatType: TTwitterOutputFormatType): string;
      function GetUserTimeLine(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string;
      function GetFriendsTimeLine(OutputFormatType: TTwitterOutputFormatType; since_id: string = '';
                                  max_id: string = ''; count: string = '' ; page: string = ''): string;
      function GetFriends(OutputFormatType: TTwitterOutputFormatType): string;
      function GetUserFollowers(OutputFormatType: TTwitterOutputFormatType): string; overload;
      function GetUserFollowers(parm: string; OutputFormatType: TTwitterOutputFormatType): string; overload;

      function Update(Status: string; OutputFormatType: TTwitterOutputFormatType): string;
      function Show(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string;
      function GetReplies(OutputFormatType: TTwitterOutputFormatType): string;
      function GetDirectMessages(OutputFormatType: TTwitterOutputFormatType): string;
      function GetDirectMessagesSent(OutputFormatType: TTwitterOutputFormatType): string;
      function PostDirectMessagesNew(OutputFormatType: TTwitterOutputFormatType; user, text: string): string;
      function PostDirectMessagesDestroy(id: string; OutputFormatType: TTwitterOutputFormatType): string;
      property Source: string read FSource write SetSource;
      property TwitterClient: string read FTwitterClient write SetTwitterClient;
      property TwitterClientVersion: string read FTwitterClientVersion write SetTwitterClientVersion;
      property TwitterClientURL: string read FTwitterClientURL write SetTwitterClientURL;
      property Consumer: TOAuthConsumer read FConsumer write FConsumer;
      property Token: TOAuthToken read FToken write FToken;
      property Request: TOAuthRequest read FRequest write FRequest;
      property HMAC: TOAuthSignatureMethod_HMAC_SHA1 read FHMAC write FHMAC;
      property Key: string read FKey write FKey;
      property Secret: string read FSecret write FSecret;
      property OAuth_token: string read FOAuth_token write FOAuth_token;
      property OAuth_token_secret: string read FOAuth_token_secret write FOAuth_token_secret;
  end;

const
  TwitterBaseURLFormat = 'http://twitter.com/%s/%s.%s';
  TwitterBaseURLFormat2 = 'http://twitter.com/%s.%s';

implementation

{ TTwitter }

constructor TTwitter.Create;
begin
  FHTTP := TIdCustomHTTP.Create(nil);
  FHTTP.Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
  FHTTP.Request.Accept := 'text/html, */*';
  FHTTP.HTTPOptions := [hoForceEncodeParams, hoInProcessAuth];
  FHTTP.MaxAuthRetries := 3;
  FHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
end;

function TTwitter.DeleteFirstChar(input: string): string;
begin
  Delete(input, 1, 1);
  Result := input;
end;

function TTwitter.GETCommand(URL: string): string;
var
  pos: integer;
begin
  FConsumer := nil;
  FConsumer := TOAuthConsumer.Create(FKey, FSecret, 'http://www.chuckbeasley.com');
  FRequest := TOAuthRequest.Create(URL);
  FRequest := Request.FromConsumerAndToken(FConsumer, nil, URL);
  FRequest.HTTPURL := URL;
  FToken := TOAuthToken.Create(FOAuth_token, FOAuth_token_secret);
  FRequest := Request.FromConsumerAndToken(FConsumer, FToken, URL);
  FRequest.Sign_Request(HMAC, Consumer, Token);
  pos := AnsiPos('?', URL);
  if pos = 0 then
    URL := URL + '?' + Request.GetString
  else
    URL := URL + '&' + Request.GetString;
  Result := FHTTP.Get(URL);
end;

function TTwitter.GetUserFollowers(OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('GetUserFollowers supports only XML and JSON output format.');
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterUser(ufollowers),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetUserFollowers(parm: string;
  OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('GetUserFollowers supports only XML and JSON output format.');

  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterUser(ufollowers),
                GetTwitterOutputFormatType(OutputFormatType) + '?' + parm]);
  Result := GETCommand(URL);
end;

function TTwitter.GetDirectMessages(
  OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  URL := Format(TwitterBaseURLFormat2, [GetTwitterDirectMessage(ddirect_messages),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetDirectMessagesSent(
  OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  URL := Format(TwitterBaseURLFormat, [GetTwitterDirectMessage(ddirect_messages),
                GetTwitterDirectMessage(dsent),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetFriends(OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('GetFriends supports only XML and JSON output format.');
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterUser(ufriends),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetFriendsTimeLine(OutputFormatType: TTwitterOutputFormatType;
                                     since_id: string = ''; max_id: string = '';
                                     count: string = '' ; page: string = ''): string;
var
  URL: string;
  parm_cnt: integer;
begin
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterStatus(sfriends_timeline),
                GetTwitterOutputFormatType(OutputFormatType)]);
  parm_cnt := 0;
  if ((since_id <> '') or (max_id <> '') or (count <>  '')  or (page <> '')) then
  begin
    URL := URL + '?';
    Inc(parm_cnt);

    if (since_id <> '') then
    begin
      if (parm_cnt > 1) then
      begin
        URL := URL + '&';
        Inc(parm_cnt);
      end;
      URL := URL + 'since_id=' + since_id;
    end;

    if (count <> '') then
    begin
      if (parm_cnt > 1) then
      begin
        URL := URL + '&';
        Inc(parm_cnt);
      end;
      URL := URL + 'count=' + count;
    end;

    if (max_id <> '') then
    begin
      if (parm_cnt > 1) then
      begin
        URL := URL + '&';
        Inc(parm_cnt);
      end;
      URL := URL + 'max_id=' + max_id;
    end;

    if (page <> '') then
    begin
      if (parm_cnt > 1) then
      begin
        URL := URL + '&';
        Inc(parm_cnt);
      end;
      URL := URL + 'page=' + page;
    end;
 end;
  Result := GETCommand(URL);
end;

function TTwitter.GetPublicTimeLine(OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterStatus(spublic_timeline),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetReplies(OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterStatus(sreplies),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.GetTwitterDirectMessage(
  TwitterDirectMessage: TTwitterDirectMessage): string;
var
  x: string;
begin
  x := GetEnumName(TypeInfo(TTwitterDirectMessage),  Ord(TwitterDirectMessage));
  Result := DeleteFirstChar(x);
end;

function TTwitter.GetTwitterFriendship(
  TwitterFriendship: TTwitterFriendship): string;
var
  x: string;
begin
  x := GetEnumName(TypeInfo(TTwitterFriendship),  Ord(TwitterFriendship));
  Result := DeleteFirstChar(x);
end;

function TTwitter.GetTwitterObjectType(
  TwitterObjectType: TTwitterObjectType): string;
begin
  Result := GetEnumName(TypeInfo(TTwitterObjectType),  Ord(TwitterObjectType));
end;

function TTwitter.GetTwitterOutputFormatType(
  TwitterOutputFormatType: TTwitterOutputFormatType): string;
begin
  Result := GetEnumName(TypeInfo(TTwitterOutputFormatType),  Ord(TwitterOutputFormatType));
end;

function TTwitter.GetTwitterStatus(TwitterStatus: TTwitterStatus): string;
var
  x: string;
begin
  x:= GetEnumName(TypeInfo(TTwitterStatus),  Ord(TwitterStatus));
  Result := DeleteFirstChar(x);
end;

function TTwitter.GetTwitterUser(TwitterUser: TTwitterUser): string;
var
  x: string;
begin
  x:= GetEnumName(TypeInfo(TTwitterUser),  Ord(TwitterUser));
  Result := DeleteFirstChar(x);
end;

function TTwitter.GetUserTimeLine(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  if (ScreenName = '') then
    URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                  GetTwitterStatus(suser_timeline),
                  GetTwitterOutputFormatType(OutputFormatType)])
  else
    URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                  GetTwitterStatus(suser_timeline) + '/' + ScreenName,
                  GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.POSTCommand(URL: string; Data: TStringList): string;
begin

  if Source <> '' then
    Data.Add('&source=' + URLEncode(Source));
  Result := FHTTP.Post(URL, Data);
end;

function TTwitter.PostDirectMessagesDestroy(id: string;
  OutputFormatType: TTwitterOutputFormatType): string;
var
  Data: TStringList;
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('Direct_messages/destroy supports only XML and JSON output format.');

  Data := TStringlist.Create;
  URL := Format(TwitterBaseURLFormat, [GetTwitterDirectMessage(ddirect_messages),
                GetTwitterDirectMessage(ddestroy) + '/' + id,
                GetTwitterOutputFormatType(OutputFormatType)]);
  Data := TStringlist.Create;
  Result := POSTCommand(URL, Data);
  Data.Free;
end;

function TTwitter.PostDirectMessagesNew(
  OutputFormatType: TTwitterOutputFormatType; user, text: string): string;
var
  Data: TStringList;
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('Direct_messages/new supports only XML and JSON output format.');

  URL := Format(TwitterBaseURLFormat, [GetTwitterDirectMessage(ddirect_messages),
                GetTwitterDirectMessage(dnew),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Data := TStringlist.Create;
  Data.Add(user);
  Data.Add(text);
  Result := POSTCommand(URL, Data);
  Data.Free;
end;

procedure TTwitter.SetSource(const Value: string);
begin
  FSource := Value;
end;

procedure TTwitter.SetTwitterClient(const Value: string);
begin
  FTwitterCLient := Value;
end;

procedure TTwitter.SetTwitterCLientURL(const Value: string);
begin
  FTwitterCLientURL := Value;
end;

procedure TTwitter.SetTwitterClientVersion(const Value: string);
begin
  FTwitterCLientVersion := Value;
end;

function TTwitter.Show(ScreenName: string; OutputFormatType: TTwitterOutputFormatType): string;
var
  URL: string;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('Show supports only XML and JSON output format.');
    URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(users),
                  GetTwitterUser(ushow) + '/' + ScreenName,
                  GetTwitterOutputFormatType(OutputFormatType)]);
  Result := GETCommand(URL);
end;

function TTwitter.Update(Status: string; OutputFormatType: TTwitterOutputFormatType): string;
var
  Text, URL: string;
  Data: TStringList;
begin
  if ((OutputFormatType <> JSON) and (OutputFormatType <> XML)) then
    raise Exception.Create('Update supports only XML and JSON output format.');
  URL := Format(TwitterBaseURLFormat, [GetTwitterObjectType(Statuses),
                GetTwitterStatus(supdate),
                GetTwitterOutputFormatType(OutputFormatType)]);
  Data := TStringlist.Create;
  Text := Format('status=%s', [status]);
  Data.Add(Text);
  Result := POSTCommand(URL, Data);
  Data.Free;
end;

function TTwitter.UrlEncode(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
          Result := Result + '%' + _IntToHex(Ord(Ch), 2);
  end;
end;

function TTwitter._IntToHex(Value, Digits: Integer): String;
begin
  Result := SysUtils.IntToHex(Value, Digits);
end;

end.
2. 추가 참고자료
Twitter Checker : Delphi 2009 버전으로 만들어진 간단한 트레이 방식의 트위터 체크 프로그램(OpenSource)
Dwitterphi - the Delphi native Twitter client : Delphi 2009로 만들어진 매우 가벼운 트위터 클라이언트(Open Source)
Twitter Desktop Client - powered by Delphi any by Andreano Lanusse
Using Twitter API with Delphi