Changeset 391
- Timestamp:
- 05/18/08 11:24:50 (6 months ago)
- Location:
- TwitterIrcGateway/branches/im-support
- Files:
-
- 3 modified
-
TwitterIrcGatewayCLI/Program.cs (modified) (1 diff)
-
TwitterIrcGatewayCore/Session.cs (modified) (13 diffs)
-
TwitterIrcGatewayCore/TwitterService.cs (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
TwitterIrcGateway/branches/im-support/TwitterIrcGatewayCLI/Program.cs
r389 r391 19 19 IPAddress bindAddress = IPAddress.Loopback; 20 20 Encoding encoding = Encoding.GetEncoding("ISO-2022-JP"); 21 IWebProxy proxy = Web Proxy.GetDefaultProxy();21 IWebProxy proxy = WebRequest.DefaultWebProxy; 22 22 23 23 CommandLineOptions options; -
TwitterIrcGateway/branches/im-support/TwitterIrcGatewayCore/Session.cs
r389 r391 29 29 private TwitterIMService _twitterIm; 30 30 private LinkedList<Int32> _lastStatusIdsFromGateway; 31 private Timer _timer;32 private Timer _timerDirectMessage;33 private Timer _timerReplies;34 31 private Groups _groups; 35 32 private Filters _filter; 36 33 private Config _config; 37 34 38 private DateTime _lastAccessTimeline = new DateTime();39 private DateTime _lastAccessReplies = new DateTime();40 35 private List<String> _nickNames = new List<string>(); 41 36 private Boolean _isFirstTime = true; 42 private Boolean _isFirstTimeReplies = true; 43 private DateTime _lastAccessDirectMessage = DateTime.Now; 44 private Int32 _bufferSize = 250; 45 private LinkedList<Status> _statusBuffer; 46 private LinkedList<Status> _repliesBuffer; 37 47 38 private TraceListener _traceListeneer; 48 39 … … 80 71 _server = server; 81 72 _tcpClient = tcpClient; 82 _statusBuffer = new LinkedList<Status>();83 _repliesBuffer = new LinkedList<Status>();84 73 _lastStatusIdsFromGateway = new LinkedList<int>(); 85 _timer = new Timer(new TimerCallback(OnTimerCallback), null, Timeout.Infinite, Timeout.Infinite);86 _timerDirectMessage = new Timer(new TimerCallback(OnTimerCallbackDirectMessage), null, Timeout.Infinite, Timeout.Infinite);87 _timerReplies = new Timer(new TimerCallback(OnTimerCallbackReplies), null, Timeout.Infinite, Timeout.Infinite);88 74 } 89 75 … … 121 107 { 122 108 return _clientHost; 123 }124 }125 126 /// <summary>127 ///128 /// </summary>129 /// <param name="stateObject"></param>130 private void OnTimerCallback(Object stateObject)131 {132 RunCallback(_timer, delegate133 {134 SendPing();135 136 // 初回だけは先にチェックしておかないとnamesが後から来てジャマ137 if (_isFirstTime)138 {139 CheckFriends();140 }141 142 // Friendsをチェックするのは成功して、チェックが必要となったとき143 Boolean friendsCheckRequired = false;144 if (CheckNewTimeLine(out friendsCheckRequired) && friendsCheckRequired && !_server.DisableUserList)145 {146 CheckFriends();147 }148 });149 }150 151 /// <summary>152 ///153 /// </summary>154 /// <param name="stateObject"></param>155 private void OnTimerCallbackDirectMessage(Object stateObject)156 {157 RunCallback(_timerDirectMessage, delegate158 {159 CheckDirectMessage();160 });161 }162 163 /// <summary>164 ///165 /// </summary>166 /// <param name="stateObject"></param>167 private void OnTimerCallbackReplies(Object stateObject)168 {169 RunCallback(_timerReplies, delegate170 {171 CheckNewReplies();172 });173 }174 175 /// <summary>176 ///177 /// </summary>178 private delegate void CallbackProcedure();179 180 /// <summary>181 /// タイマーコールバックの処理を実行します。182 /// </summary>183 /// <param name="timer"></param>184 /// <param name="callbackProcedure"></param>185 private void RunCallback(Timer timer, CallbackProcedure callbackProcedure)186 {187 // あまりに処理が遅れると二重になる可能性がある188 if (Monitor.TryEnter(timer))189 {190 try191 {192 callbackProcedure();193 }194 finally195 {196 Monitor.Exit(timer);197 }198 109 } 199 110 } … … 613 524 //_username = e.Message.CommandParams[0]; // usernameがtwitterのIDとなる 614 525 _username = e.Message.CommandParams[3]; 615 _twitter = new TwitterService(_username, _password);616 _twitter.CookieLoginMode = _server.CookieLoginMode;617 if (_server.Proxy != null)618 _twitter.Proxy = _server.Proxy;619 526 620 527 Type t = typeof(Server); … … 646 553 Send(autoMsg); 647 554 555 // 556 // Twitte Service Setup 557 // 558 _twitter = new TwitterService(_username, _password); 559 _twitter.CookieLoginMode = _server.CookieLoginMode; 560 _twitter.Interval = _server.Interval; 561 _twitter.IntervalDirectMessage = _server.IntervalDirectMessage; 562 _twitter.IntervalReplies = _server.IntervalReplies; 563 _twitter.EnableRepliesCheck = _server.EnableRepliesCheck; 564 _twitter.RepliesReceived += new EventHandler<StatusesUpdatedEventArgs>(twitter_RepliesReceived); 565 _twitter.TimelineStatusesReceived += new EventHandler<StatusesUpdatedEventArgs>(twitter_TimelineStatusesReceived); 566 _twitter.CheckError += new EventHandler<ErrorEventArgs>(twitter_CheckError); 567 _twitter.DirectMessageReceived += new EventHandler<DirectMessageEventArgs>(twitter_DirectMessageReceived); 568 if (_server.Proxy != null) 569 _twitter.Proxy = _server.Proxy; 570 571 _twitter.Start(); 572 648 573 OnSessionStarted(_username); 649 574 Trace.WriteLine(String.Format("SessionStarted: UserName={0}; Nickname={1}", _username, _nick)); 650 651 _timer.Change(0, _server.Interval * 1000);652 _timerDirectMessage.Change(0, _server.IntervalDirectMessage * 1000);653 if (_server.EnableRepliesCheck)654 {655 _timerReplies.Change(0, _server.IntervalReplies * 1000);656 }657 575 } 658 576 … … 995 913 { 996 914 _isFirstTime = false; // IMが先にきてしまったらあきらめる 997 if (ProcessDropProtection(_statusBuffer, e.Status))915 _twitter.ProcessStatus(e.Status, (s) => 998 916 { 999 917 Boolean friendsCheckRequired = false; 1000 918 ProcessTimelineStatus(e.Status, ref friendsCheckRequired); 919 }); 920 } 921 #endregion 922 923 #region Twitter Service イベント 924 void twitter_CheckError(object sender, ErrorEventArgs e) 925 { 926 SendServerErrorMessage(e.Exception.Message); 927 } 928 929 void twitter_DirectMessageReceived(object sender, DirectMessageEventArgs e) 930 { 931 DirectMessage message = e.DirectMessage; 932 String text = (_server.ResolveTinyUrl) ? Utility.ResolveTinyUrlInMessage(message.Text) : message.Text; 933 String[] lines = text.Split(new Char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); 934 935 foreach (String line in lines) 936 { 937 PrivMsgMessage privMsg = new PrivMsgMessage(); 938 privMsg.SenderNick = message.SenderScreenName; 939 privMsg.SenderHost = "twitter@" + Server.ServerName; 940 privMsg.Receiver = _nick; 941 //privMsg.Content = String.Format("{0}: {1}", screenName, text); 942 privMsg.Content = line; 943 Send(privMsg); 944 } 945 } 946 947 void twitter_TimelineStatusesReceived(object sender, StatusesUpdatedEventArgs e) 948 { 949 SendPing(); 950 951 if (_isFirstTime && e.IsFirstTime) 952 _isFirstTime = e.IsFirstTime; 953 954 // 初回だけは先にチェックしておかないとnamesが後から来てジャマ 955 if (_isFirstTime) 956 { 957 CheckFriends(); 958 } 959 960 Boolean friendsCheckRequired = e.FriendsCheckRequired; 961 foreach (Status status in e.Statuses.Status) 962 { 963 ProcessTimelineStatus(status, ref friendsCheckRequired); 964 } 965 966 // Friendsをチェックするのは成功して、チェックが必要となったとき 967 if (e.FriendsCheckRequired && !_server.DisableUserList) 968 { 969 CheckFriends(); 970 } 971 } 972 973 void twitter_RepliesReceived(object sender, StatusesUpdatedEventArgs e) 974 { 975 Boolean dummy = false; 976 foreach (Status status in e.Statuses.Status) 977 { 978 ProcessTimelineStatus(status, ref dummy); 1001 979 } 1002 980 } … … 1166 1144 }); 1167 1145 } 1168 1169 private Boolean CheckNewTimeLine(out Boolean friendsCheckRequired) 1170 { 1171 Boolean friendsCheckRequiredAnon = false; 1172 Boolean returnValue = RunCheck(delegate 1173 { 1174 Statuses statuses = _twitter.GetTimeline(_lastAccessTimeline); 1175 Array.Reverse(statuses.Status); 1176 foreach (Status status in statuses.Status) 1177 { 1178 // 差分チェック 1179 if (ProcessDropProtection(_statusBuffer, status)) 1180 { 1181 ProcessTimelineStatus(status, ref friendsCheckRequiredAnon); 1182 } 1183 } 1184 1185 if (_isFirstTime && _server.EnableDropProtection) 1186 { 1187 _lastAccessTimeline = DateTime.Now; 1188 } 1189 _isFirstTime = false; 1190 }); 1191 1192 friendsCheckRequired = friendsCheckRequiredAnon; 1193 return returnValue; 1194 } 1195 1196 private Boolean CheckNewReplies() 1197 { 1198 Boolean friendsCheckRequired = false; 1199 return RunCheck(delegate 1200 { 1201 Statuses statuses = _twitter.GetReplies(); 1202 Array.Reverse(statuses.Status); 1203 bool dummy = false; 1204 foreach (Status status in statuses.Status) 1205 { 1206 if (status.CreatedAt < _lastAccessReplies) 1207 continue; 1208 // 差分チェック 1209 if (ProcessDropProtection(_repliesBuffer, status) && ProcessDropProtection(_statusBuffer, status)) 1210 { 1211 // Here I pass dummy, because no matter how the replier flags 1212 // friendsCheckRequired, we cannot receive his or her info 1213 // through get_friends. 1214 ProcessTimelineStatus(status, ref dummy); 1215 } 1216 } 1217 1218 if (_isFirstTimeReplies && _server.EnableDropProtection) 1219 { 1220 _lastAccessReplies = DateTime.Now; 1221 } 1222 _isFirstTimeReplies = false; 1223 }); 1224 } 1225 1226 /// <summary> 1227 /// 既に受信したstatusかどうかをチェックします。既に送信済みの場合falseを返します。 1228 /// </summary> 1229 /// <param name="statusBuffer"></param> 1230 /// <param name="status"></param> 1231 /// <returns></returns> 1232 private Boolean ProcessDropProtection(LinkedList<Status> statusBuffer, Status status) 1233 { 1234 // 差分チェック 1235 if (_server.EnableDropProtection) 1236 { 1237 if (statusBuffer.Contains(status)) 1238 return false; 1239 1240 statusBuffer.AddLast(status); 1241 if (statusBuffer.Count > _bufferSize) 1242 { 1243 // 一番古いのを消す 1244 //Status oldStatus = null; 1245 //foreach (Status statTmp in _statusBuffer) 1246 //{ 1247 // if (oldStatus == null || oldStatus.CreatedAt > statTmp.CreatedAt) 1248 // { 1249 // oldStatus = statTmp; 1250 // } 1251 //} 1252 //_statusBuffer.Remove(oldStatus); 1253 statusBuffer.RemoveFirst(); 1254 } 1255 } 1256 1257 return true; 1258 } 1259 1146 1260 1147 private void ProcessTimelineStatus (Status status, ref Boolean friendsCheckRequired) 1261 1148 { 1262 1263 1149 // チェック 1264 1150 if (status.User == null || String.IsNullOrEmpty(status.User.ScreenName)) … … 1330 1216 } 1331 1217 } 1332 }1333 }1334 1335 // 最終更新時刻1336 if (_server.EnableDropProtection)1337 {1338 // 取りこぼし防止しているときは一番古い日付1339 if (status.CreatedAt < _lastAccessTimeline)1340 {1341 _lastAccessTimeline = status.CreatedAt;1342 }1343 }1344 else1345 {1346 if (status.CreatedAt > _lastAccessTimeline)1347 {1348 _lastAccessTimeline = status.CreatedAt;1349 1218 } 1350 1219 } … … 1375 1244 } 1376 1245 1377 /// <summary> 1378 /// 1379 /// </summary> 1380 private void CheckDirectMessage() 1381 { 1382 RunCheck(delegate 1383 { 1384 DirectMessages directMessages = _twitter.GetDirectMessages(_lastAccessDirectMessage); 1385 Array.Reverse(directMessages.DirectMessage); 1386 foreach (DirectMessage message in directMessages.DirectMessage) 1387 { 1388 // チェック 1389 if (message == null || String.IsNullOrEmpty(message.SenderScreenName)) 1390 { 1391 continue; 1392 } 1393 1394 String text = (_server.ResolveTinyUrl) ? Utility.ResolveTinyUrlInMessage(message.Text) : message.Text; 1395 String[] lines = text.Split(new Char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); 1396 1397 foreach (String line in lines) 1398 { 1399 PrivMsgMessage privMsg = new PrivMsgMessage(); 1400 privMsg.SenderNick = message.SenderScreenName; 1401 privMsg.SenderHost = "twitter@" + Server.ServerName; 1402 privMsg.Receiver = _nick; 1403 //privMsg.Content = String.Format("{0}: {1}", screenName, text); 1404 privMsg.Content = line; 1405 Send(privMsg); 1406 } 1407 // 最終更新時刻 1408 if (message.CreatedAt > _lastAccessDirectMessage) 1409 { 1410 _lastAccessDirectMessage = message.CreatedAt; 1411 } 1412 } 1413 }); 1414 } 1415 1416 private delegate void CheckProcedure(); 1246 private delegate void Procedure(); 1417 1247 /// <summary> 1418 1248 /// チェックを実行します。例外が発生した場合には自動的にメッセージを送信します。 … … 1420 1250 /// <param name="proc">実行するチェック処理</param> 1421 1251 /// <returns></returns> 1422 private Boolean RunCheck( CheckProcedure proc)1252 private Boolean RunCheck(Procedure proc) 1423 1253 { 1424 1254 try … … 1431 1261 { 1432 1262 // not-modified 以外 1433 SendServerErrorMessage(ex.Message);1263 twitter_CheckError(_twitter, new ErrorEventArgs(ex)); 1434 1264 return false; 1435 1265 } … … 1437 1267 catch (TwitterServiceException ex2) 1438 1268 { 1439 SendServerErrorMessage(ex2.Message);1269 twitter_CheckError(_twitter, new ErrorEventArgs(ex2)); 1440 1270 return false; 1441 1271 } 1442 1443 1272 return true; 1444 1273 } 1445 1274 1446 1447 1275 /// <summary> 1448 1276 /// … … 1472 1300 { 1473 1301 Trace.Listeners.Remove(_traceListeneer); 1474 }1475 1476 if (_timer != null)1477 {1478 _timer.Dispose();1479 _timer = null;1480 }1481 if (_timerDirectMessage != null)1482 {1483 _timerDirectMessage.Dispose();1484 _timerDirectMessage = null;1485 }1486 if (_timerReplies != null)1487 {1488 _timerReplies.Dispose();1489 _timerReplies = null;1490 1302 } 1491 1303 -
TwitterIrcGateway/branches/im-support/TwitterIrcGatewayCore/TwitterService.cs
r390 r391 22 22 private String _userName; 23 23 private Boolean _cookieLoginMode = false; 24 private Boolean _enableDropProtection = true; 25 26 private Timer _timer; 27 private Timer _timerDirectMessage; 28 private Timer _timerReplies; 29 30 private DateTime _lastAccessTimeline = new DateTime(); 31 private DateTime _lastAccessReplies = new DateTime(); 32 private DateTime _lastAccessDirectMessage = DateTime.Now; 33 private Boolean _isFirstTime = true; 34 private Boolean _isFirstTimeReplies = true; 35 36 private Int32 _bufferSize = 250; 37 private LinkedList<Status> _statusBuffer; 38 private LinkedList<Status> _repliesBuffer; 39 40 public event EventHandler<ErrorEventArgs> CheckError; 41 public event EventHandler<StatusesUpdatedEventArgs> TimelineStatusesReceived; 42 public event EventHandler<StatusesUpdatedEventArgs> RepliesReceived; 43 public event EventHandler<DirectMessageEventArgs> DirectMessageReceived; 24 44 25 45 public static readonly String ServiceServerPrefix = "http://twitter.com"; … … 36 56 37 57 _userName = userName; 58 59 _timer = new Timer(new TimerCallback(OnTimerCallback), null, Timeout.Infinite, Timeout.Infinite); 60 _timerDirectMessage = new Timer(new TimerCallback(OnTimerCallbackDirectMessage), null, Timeout.Infinite, Timeout.Infinite); 61 _timerReplies = new Timer(new TimerCallback(OnTimerCallbackReplies), null, Timeout.Infinite, Timeout.Infinite); 62 63 _statusBuffer = new LinkedList<Status>(); 64 _repliesBuffer = new LinkedList<Status>(); 38 65 39 66 //_webClient = new PreAuthenticatedWebClient(); … … 67 94 set { _cookieLoginMode = value; } 68 95 } 96 97 /// <summary> 98 /// �����ڂ��h�~����邩�ǂ�����肵�܂��B 99 /// </summary> 100 public Boolean EnableDropProtection 101 { 102 get { return _enableDropProtection; } 103 set { _enableDropProtection = value; } 104 } 105 106 /// <summary> 107 /// �^�C�����C����F�b�N�����u��肵�܂��B 108 /// </summary> 109 public Int32 Interval 110 { 111 get; 112 set; 113 } 114 115 /// <summary> 116 /// �_�C���N�g���b�Z�[�W��F�b�N�����u��肵�܂��B 117 /// </summary> 118 public Int32 IntervalDirectMessage 119 { 120 get; 121 set; 122 } 123 124 /// <summary> 125 /// Replies��F�b�N�����u��肵�܂��B 126 /// </summary> 127 public Int32 IntervalReplies 128 { 129 get; 130 set; 131 } 132 133 /// <summary> 134 /// Replies�̃`�F�b�N��s���邩�ǂ�����肵�܂��B 135 /// </summary> 136 public Boolean EnableRepliesCheck 137 { 138 get; 139 set; 140 } 69 141 70 142 /// <summary> … … 75 147 { 76 148 String encodedMessage = TwitterService.EncodeMessage(message); 77 try149 return ExecuteRequest<Status>(() => 78 150 { 79 151 String responseBody = POST(String.Format("/statuses/update.xml?status={0}&source={1}", encodedMessage, TwitterService.ClientName), Encoding.Default.GetBytes("1")); … … 87 159 return status; 88 160 } 89 } 90 catch (WebException we) 91 { 92 throw; 93 } 94 catch (InvalidOperationException ioe) 95 { 96 // XmlSerializer 97 throw new TwitterServiceException(ioe); 98 } 99 catch (XmlException xe) 100 { 101 throw new TwitterServiceException(xe); 102 } 103 catch (IOException ie) 104 { 105 throw new TwitterServiceException(ie); 106 } 161 }); 107 162 } 108 163 … … 115 170 { 116 171 String encodedMessage = TwitterService.EncodeMessage(message); 117 try172 ExecuteRequest(() => 118 173 { 119 174 String responseBody = POST(String.Format("/direct_messages/new.xml?user={0}&text={1}", targetId, encodedMessage), new Byte[0]); 120 } 121 catch (WebException we) 122 { 123 throw; 124 } 125 catch (InvalidOperationException ioe) 126 { 127 // XmlSerializer 128 throw new TwitterServiceException(ioe); 129 } 130 catch (XmlException xe) 131 { 132 throw new TwitterServiceException(xe); 133 } 134 catch (IOException ie) 135 { 136 throw new TwitterServiceException(ie); 137 } 175 }); 138 176 } 139 177 … … 147 185 List<User> usersList = new List<User>(); 148 186 Int32 page = 0; 149 try187 return ExecuteRequest<User[]>(() => 150 188 { 151 189 while (page++ != 1 /*10*/) … … 171 209 // ���܂������ꍇ�͂����܂ŁB 172 210 return usersList.ToArray(); 173 } 174 catch (WebException we) 175 &nb
