OSDN Git Service

support for one or more bot systems
[radegast/radegast.git] / plugins / Radegast.Plugin.EVOVend / EVOvendPlugin.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using OpenMetaverse;
10 using OpenMetaverse.StructuredData;
11 using System.Threading;
12 using System.IO;
13 using System.Net;
14
15 namespace Radegast.Plugin.EVOVend
16 {
17     [Radegast.Plugin(Name = "EVOvend Plugin", Description = "EVO Vendor Delivery System", Version = "1.0")]
18     public partial class EVOvendPlugin : RadegastTabControl, IRadegastPlugin
19     {
20         public int DELIVERY_INTERVAL
21         {
22             get
23             {
24                 return (int)numDeliveryInterval.Value;
25             }
26             set
27             {
28                 numDeliveryInterval.Value = value;
29             }
30         }
31
32         public int STARTUP_DELAY
33         {
34             get
35             {
36                 return (int)numStartupDelay.Value;
37             }
38             set
39             {
40                 numStartupDelay.Value = value;
41             }
42         }
43
44         public OSDMap config;
45
46         public static System.Threading.Timer timer;
47         private InventoryManager Manager;
48         private OpenMetaverse.Inventory Inventory;
49
50         private string vendURL = @"http://evosl.org/TREK/SL/SLvendor.php";
51         private string loginURL = @"http://evosl.org/TREK/SL/vendor.php";
52         List<InventoryBase> searchRes = new List<InventoryBase>();
53
54         /*private GridClient Client { get { return instance.Client; } }*/
55
56         static string tabID = "evovend_tab";
57         static string tabLabel = "EVOvend";
58
59         private string pluginName = "EVOvend";
60         private string version = "1.0";
61         private ToolStripMenuItem EVOButton;
62
63         public EVOvendPlugin()
64         {
65             //this.InitializeComponent();
66         }
67
68         public EVOvendPlugin(RadegastInstance instance, bool unused) : base(instance)
69         {
70             //this.instance = instance;
71             Init();
72             Disposed += new EventHandler(EVOvendTab_Disposed);
73             RegisterClientEvents(client);
74         }
75
76         void RegisterClientEvents(GridClient client)
77         {
78             //instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
79             //client.Self.ChatFromSimulator += new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);
80         }
81
82         void UnregisterClientEvents(GridClient client)
83         {
84             //if (client == null) return;
85         }
86
87         private UUID offeredObject;
88         private UUID offeredAgent;
89
90         void Inventory_InventoryObjectOffered(object sender, InventoryObjectOfferedEventArgs e)
91         {
92             offeredObject = e.ObjectID;
93             offeredAgent = e.Offer.FromAgentID;
94         }
95
96         void Inventory_ItemReceived(object sender, ItemReceivedEventArgs e)
97         {
98             if (offeredObject != e.Item.UUID) return;
99             if (offeredAgent == UUID.Zero)
100             {
101                 return;
102             }
103             
104             Dictionary<string, string> param = new Dictionary<string, string>();
105             param.Add("invUUID", e.Item.UUID.ToString());
106             param.Add("userUUID", offeredAgent.ToString());
107             param.Add("name", e.Item.Name);
108
109             if(e.Item.SaleType != SaleType.Not)
110                 param.Add("price", e.Item.SalePrice.ToString());
111             else
112                 param.Add("price", "0");
113             param.Add("texture", "");
114             param.Add("botUUID", client.Self.AgentID.ToString());
115             string str = this.RequestVendor("ADDPRODUCT", param);
116             int result = Int32.Parse(str);
117
118             if(result > 0){
119                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Product " + e.Item.Name + " from Agent " + offeredAgent.ToString() + " accepted and inserted", ChatBufferTextStyle.StatusBlue);
120                  client.Self.InstantMessage(offeredAgent, "Your Object has been transfered successfully. Please visit " + this.loginURL + " for further steps"); 
121             } else
122                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Failed to insert " + e.Item.Name + " from Agent " + offeredAgent.ToString(), ChatBufferTextStyle.Error);
123
124             offeredAgent = UUID.Zero;
125         }
126         
127
128         void EVOvendTab_Disposed(object sender, EventArgs e)
129         {
130             this.writeConfig();
131             UnregisterClientEvents(client);
132             //instance.ClientChanged -= new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
133         }
134
135         public void StartPlugin(RadegastInstance inst)
136         {
137             instance = inst;
138             instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + " version " + version + " loaded");
139
140             Init();
141
142             EVOButton = new ToolStripMenuItem(tabLabel, null, OnEVOButtonClicked);
143             instance.MainForm.PluginsMenu.DropDownItems.Add(EVOButton);
144
145             // setup timer
146             timer = new System.Threading.Timer(new TimerCallback(productCallback));
147             this.SetupTimer();
148             // invenotry receiving
149             client.Inventory.ItemReceived += Inventory_ItemReceived;
150             client.Inventory.InventoryObjectOffered +=Inventory_InventoryObjectOffered;
151         }
152
153         public void SetupTimer(){
154             if (timer == null) return;
155             timer.Change((STARTUP_DELAY * 1000), (DELIVERY_INTERVAL * 1000));
156             instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ":  Waiting " + STARTUP_DELAY + " seconds before start...");
157         }
158
159         private void Init()
160         {
161             this.InitializeComponent();
162             this.RegisterClientEvents(client);
163             if (instance != null)
164             {
165                 this.readConfig();
166             }
167         }
168
169         private void readConfig()
170         {
171             config = instance.GlobalSettings["plugin." + pluginName] as OSDMap;
172
173             if (config == null)
174             {
175                 config = new OSDMap();
176                 config["startup_delay"] = new OSDInteger(60);
177                 config["delivery_interval"] = new OSDInteger(60);
178                 instance.GlobalSettings["plugin." + pluginName] = config;
179             }
180
181             if (!config.ContainsKey("startup_delay"))
182                 config["startup_delay"] = 60;
183             if (!config.ContainsKey("delivery_interval"))
184                 config["delivery_interval"] = 60;
185
186             STARTUP_DELAY = config["startup_delay"].AsInteger();
187             DELIVERY_INTERVAL = config["delivery_interval"].AsInteger();
188         }
189
190         private void writeConfig()
191         {
192             config = instance.GlobalSettings["plugin." + pluginName] as OSDMap;
193
194             if (config != null)
195             {
196                 config["startup_delay"] = STARTUP_DELAY;
197                 config["delivery_interval"] = DELIVERY_INTERVAL;
198                 //instance.GlobalSettings["plugin." + pluginName] = config;
199             }
200
201             instance.GlobalSettings.Save();
202         }
203
204         void OnEVOButtonClicked(object sender, EventArgs e)
205         {
206             if (instance.TabConsole.TabExists(tabID))
207             {
208                 instance.TabConsole.Tabs[tabID].Select();
209             }
210             else
211             {
212                 instance.TabConsole.AddTab(tabID, tabLabel, new EVOvendPlugin(instance, true));
213                 instance.TabConsole.Tabs[tabID].Select();
214             }
215         }
216
217         public void StopPlugin(RadegastInstance instance)
218         {
219             // kill timer
220             timer.Dispose();
221             EVOButton.Dispose();
222             // unregister inventory receiver events
223             client.Inventory.ItemReceived -= Inventory_ItemReceived;
224             client.Inventory.InventoryObjectOffered -= Inventory_InventoryObjectOffered;
225         }
226
227         private string m_searchString;
228         public string searchString
229         {
230             get
231             {
232                 return m_searchString;
233             }
234             set
235             {
236                 m_searchString = value;
237                 if (!String.IsNullOrEmpty(value))
238                     PerformRecursiveSearch(0, Inventory.RootFolder.UUID);
239             }
240         }
241
242         void PerformRecursiveSearch(int level, UUID folderID)
243         {
244             var me = Inventory.Items[folderID].Data;
245             var sorted = Inventory.GetContents(folderID);
246
247             sorted.Sort((InventoryBase b1, InventoryBase b2) =>
248             {
249                 if (b1 is InventoryFolder && !(b2 is InventoryFolder))
250                 {
251                     return -1;
252                 }
253                 else if (!(b1 is InventoryFolder) && b2 is InventoryFolder)
254                 {
255                     return 1;
256                 }
257                 else
258                 {
259                     return string.Compare(b1.Name, b2.Name);
260                 }
261             });
262
263             foreach (var item in sorted)
264             {
265                 if (item is InventoryFolder)
266                 {
267                     PerformRecursiveSearch(level + 1, item.UUID);
268                 }
269                 else
270                 {
271                     var it = item as InventoryItem;
272
273                     if (it.UUID.ToString().Contains(searchString))
274                         searchRes.Add(it);
275                 }
276             }
277         }
278
279         class DeliveryQueue
280         {
281             public string ClassName { get; set; }
282             public string id { get; set; }
283             public string userUUID { get; set; }
284             public string objectUUID { get; set; }
285             public int price { get; set; }
286             public int nextperm { get; set; }
287             public string created { get; set; }
288             public string delivered { get; set; }
289             
290         }
291
292         private string RequestVendor(string action, Dictionary<string, string> param = null)
293         {
294             try
295             {
296                 var webRequest = WebRequest.Create(this.vendURL);
297
298                 string postData = "action=" + action;
299                 if (param != null && param.Count > 0)
300                 {
301                     var kv = param.Select(p => "&" + p.Key + "=" + p.Value);
302                     postData += String.Join("", kv.ToArray());
303                 }
304                 byte[] byteArray = Encoding.UTF8.GetBytes(postData);
305
306                 webRequest.Method = "POST";
307                 webRequest.ContentType = "application/x-www-form-urlencoded";
308                 webRequest.ContentLength = byteArray.Length;
309
310                 // add post data to request
311                 Stream postStream = webRequest.GetRequestStream();
312                 postStream.Write(byteArray, 0, byteArray.Length);
313                 postStream.Flush();
314                 postStream.Close();
315
316                 using (var response = webRequest.GetResponse())
317                 using (var content = response.GetResponseStream())
318                 using (var reader = new System.IO.StreamReader(content))
319                 {
320                     return reader.ReadToEnd();
321                 }
322             }
323             catch { }
324             return null;
325         }
326
327         private List<DeliveryQueue> parseResponse(string content)
328         {
329             List<DeliveryQueue> queue = new List<DeliveryQueue>();
330
331             if (String.IsNullOrEmpty(content)) return queue;
332
333             try
334             {
335                 System.Reflection.PropertyInfo[] propertyInfos = typeof(DeliveryQueue).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
336
337                 string field_separator = "|";
338
339                 var lines = content.Split("\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
340                 foreach (string l in lines)
341                 {
342                     int lastPos = 0;
343
344                     var deliveryQ = new DeliveryQueue();
345                     foreach (System.Reflection.PropertyInfo pInfo in propertyInfos)
346                     {
347                         var nextPos = l.IndexOf(field_separator, lastPos);
348                         if (nextPos > -1)
349                         {
350                             object o = Convert.ChangeType(l.Substring(lastPos, nextPos - lastPos), pInfo.PropertyType);
351                             pInfo.SetValue(deliveryQ, o, null);
352                         }
353                         lastPos = nextPos + 1;
354                     }
355
356                     queue.Add(deliveryQ);
357                 }
358             }
359             catch (Exception ex)
360             {
361                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Failed to read DeliveryQ -  " + ex.Message, ChatBufferTextStyle.Error);
362             }
363             return queue;
364         }
365
366         private bool SendObject(DeliveryQueue p)
367         {
368             searchRes.Clear();
369             searchString = p.objectUUID;
370             if (searchRes.Count <= 0)
371             {
372                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Product not found '" + searchString + "' for user '" + p.userUUID + "'", ChatBufferTextStyle.Error);
373                 return false;
374             }
375             if (searchRes.Count > 1)
376             {
377                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": More then one product found for '" + searchString + "'", ChatBufferTextStyle.Error);
378                 return false;
379             }
380
381             var inv = searchRes[0] as InventoryItem;
382             if (inv == null)
383             {
384                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Product found, but not an inventory item", ChatBufferTextStyle.Error);
385                 return false;
386             }
387
388
389             Dictionary<string, string> param = new Dictionary<string, string>();
390             param.Add("id", p.id);
391             var str = this.RequestVendor("SETDELIVERED", param);
392             if (str != "1")
393             {
394                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Product found, but user " + p.userUUID + " might not have enough funds", ChatBufferTextStyle.Normal);
395                 // a message to the user would be helpful later
396                 return false;
397             }
398             instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": SETDELIVERED: " + str, ChatBufferTextStyle.StatusBlue);
399
400             inv.Permissions.NextOwnerMask = (PermissionMask)p.nextperm;
401             client.Inventory.RequestUpdateItem(inv);
402             client.Inventory.RequestFetchInventory(inv.UUID, inv.OwnerID);
403
404             Manager.GiveItem(inv.UUID, inv.Name, inv.AssetType, OpenMetaverse.UUID.Parse(p.userUUID), false);
405             instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": PRODUCT '" + searchRes[0].Name + "' SENT TO " + p.userUUID, ChatBufferTextStyle.StatusBlue);
406
407             return true;
408         }
409
410         private bool isSending = false;
411         private void productCallback(object obj)
412         {
413             Manager = client.Inventory;
414             Inventory = Manager.Store;
415             if (Inventory == null)
416             {
417                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Waiting for Inventory...");
418                 return;
419             }
420
421             if (isSending == true)
422             {
423                 instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Waiting...");
424                 return;
425             }
426             isSending = true;
427             
428             Inventory.RootFolder.OwnerID = client.Self.AgentID;
429             
430             Dictionary<string, string> param = new Dictionary<string, string>();
431             param.Add("botUUID", client.Self.AgentID.ToString());
432             var strContent = this.RequestVendor("GETOUTSTANDING", param);
433             List<DeliveryQueue> queue = this.parseResponse(strContent);
434             instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": " + queue.Count + " Items in Queue List");
435
436             // check if something neddc to be done
437             if (queue.Count > 0)
438             {
439                 foreach (DeliveryQueue p in queue)
440                     this.SendObject(p);
441             }
442
443             isSending = false;
444         }
445
446         private void numStartupDelay_ValueChanged(object sender, EventArgs e)
447         {
448             this.SetupTimer();
449         }
450
451         private void numDeliveryInterval_ValueChanged(object sender, EventArgs e)
452         {
453             this.SetupTimer();
454         }
455     }
456 }
457