Skypeメッセージによる検索フィルター

昨日、Skypeログが.sqliteに保存されていることを突然知りました。 まあ、私は週末のレッスンがあると思った。

今日、私はハブに目を向け、ベース自体の説明に特化したトピック - トピックを見つけました。また、このまさにベース- トピックとSkypeLogViewerの言及を復元しました。 素晴らしい、私は別の硬い自転車を書く時が来たと思った。

アイデアは簡単です:luaを使用してチャットを選択およびフィルタリングするのは、lua、sqlクエリ、およびlinqのluaアナログを少し練習したい人や、標準のSkype検索に慣れていない人向けです。 アプリケーション自体はC#(WPF)で記述されています。

何が起こった-カットの下を見てください。





それでは、簡単なものから始めましょう-luaとsqliteで動作するために必要なライブラリを接続します。



選択はそれぞれNLuaとSystem.Data.Sqliteに当てはまりました。 インストールにはNuGetを使用します。



インストールパッケージnlua

インストールパッケージsystem.data.sqlite



便宜上、すべての消防士のために、luaの小さなラッパークラスを作成します



public class LuaLogic { public Lua lua = new Lua(); //     public -   C#    lua public void reg(object target, string funcname) { try { lua.RegisterFunction(funcname, target, target.GetType().GetMethod(funcname)); } catch (Exception ex) { } } // lua-   public object[] call(string lua_func, params object[] args) { try { var func = lua[lua_func] as LuaFunction; return func.Call(args); } catch (Exception ex) { return null; } } }
      
      







そして、はい、多くの人が例外をスローすべきだと考えていることを知っています-この特定のケースではこれの必要性が見えないだけです。



ここではコードで使用されるGUI要素の説明があるため、GUIのマークアップを投稿しません。



出力-下品なジョークやアスキーアートなど、あらゆる種類の情報を出力するためのRichTextBox

runlua-ボタン。luaコードを実行します。 実際には、 FileSystemWatcherを使用してファイルを変更することで一時停止できますが、これはすべてのユーザー向けではありません

アカウント-ComboBox。コンピューターにログオンしたことのあるSkypeユーザーを一覧表示します。



それでは、コードに移りましょう。 ヘルパー関数から始めましょう。



 static LuaLogic logic = new LuaLogic(); public string current_path = ""; private List<Dictionary<string, object>> data; //   .    -    . private List<Dictionary<string, object>> _query(string comm) { var result = new List<Dictionary<string, object>>(); using (var db = new SQLiteConnection(@"data source=" + current_path)) { db.Open(); using (var command = new SQLiteCommand(comm, db)) { command.CommandTimeout = 999; using (var reader = command.ExecuteReader()) { while (reader.Read()) { result.Add(Enumerable.Range(0, reader.FieldCount) .ToDictionary( reader.GetName, reader.GetValue)); } } } db.Close(); } return result; } //       lua .  ,    List<Dictionary<string, object>>  lua    .    lua-,   lua-. public LuaTable genTable(List<Dictionary<string, object>> d) { logic.lua.NewTable("datatable"); var table = logic.lua.GetTable("datatable"); for(int i=0; i<d.Count; i++) { logic.lua.NewTable("f"); table[i] = logic.lua.GetTable("f"); foreach (var entry in d[i]) { ((LuaTable) table[i])[entry.Key] = entry.Value; } } return table; } /*** ,   lua ***/ //,   .     lua   . public void scanDB(string request=null) { if(data!=null) data.Clear(); data = new List<Dictionary<string, object>>(); data = _query(request??"select from_dispname,body_xml,timestamp from messages order by timestamp desc"); genTable(data); } //   RichTextBox public void _print(object obj) { Dispatcher.Invoke(() =>output.AppendText(obj + "\n")); } // 1     RichTextBox.  . public void _printblock(string text) { Dispatcher.Invoke(() => output.Document.Blocks.Add(new Paragraph(new Run(text)) { Margin = new Thickness(0) })); } // RichTextBox public void _clear() { Dispatcher.Invoke(() => output.Document.Blocks.Clear()); }
      
      







そして今-アプリケーションロジック!



 public MainWindow() { InitializeComponent(); //    .        -   ,      var searchpath = Environment.ExpandEnvironmentVariables("%AppData%\\Skype"); var dirs = Directory.GetDirectories(searchpath); //       ,       var userlist = dirs.Where(dir => File.Exists(dir + "\\main.db")).Select(x=>x.Replace(searchpath+"\\", "")).ToList(); accounts.ItemsSource = userlist; accounts.SelectedItem = accounts.Items[0]; //           ComboBox' accounts.SelectionChanged += (sender, args) => current_path = Environment.ExpandEnvironmentVariables("%AppData%\\Skype") + "\\" + accounts.SelectedItem + "\\main.db"; if(userlist.Count>0) current_path = Environment.ExpandEnvironmentVariables("%AppData%\\Skype") + "\\" + userlist[0] + "\\main.db"; else { _print("    ,      ?"); } //      Lua logic.reg(this, "_print"); logic.reg(this, "_clear"); logic.reg(this, "_printblock"); logic.reg(this, "scanDB"); runlua.Click += (sender, args) => { try { new Thread(() => { // 2 -    linq- where  select , ,  . Lua-linq         <a href="http://codea.io/talk/discussion/618/linq-for-lua-functional-collection-class/p1"></a>. logic.lua.DoFile(@"scripts\pseudolinq.lua"); logic.lua.DoFile(@"scripts\script.lua"); // ,    lua-. , ,          lua- logic.call("search_pattern"); }).Start(); } catch (Exception ex) { _printblock(ex.Message); } }; //  ,  ,           Closing += (sender, args) => Process.GetCurrentProcess().Kill(); }
      
      







まあ、軽食のために-ルアコード。



pseudolinq.lua

 LinqArray = {} function LinqArray:new( arr ) Ret = {} Ret.arr = arr; setmetatable( Ret , self ) self.__index = self; return Ret; end --[[function LinqArray:init(items) if items then self:addRange(items) end end]]-- function LinqArray:add(item) table.insert(self.arr, item) end function LinqArray:addRange(items) for k,v in ipairs(items) do self.arr:add(v) end end function LinqArray:where(func) local results = {}; for k, v in ipairs(self.arr) do if func(v) then table.insert(results, v); end end return LinqArray:new(results) end function LinqArray:select(func) local results = {} for k, v in ipairs(self.arr) do _print(func(v)); table.insert(results, func(v)); end return LinqArray:new(results) end
      
      







script.lua



 function search_pattern() --     _clear(); local f = LinqArray:new(datatable); --  - linq-  local filtered = f:where(function(x) return string.len(x["from_dispname"])>1; end):select(function(x) return x["from_dispname"]; end); --     .  .      ,   , .   -  . local i=0; for i=1,#filtered.arr,1 do local arg = filtered.arr[i]; _printblock(arg["from_dispname"]..": "); _print(arg["body_xml"]); end end --,   .       .   ,    1 ,       lua,    if(datatable==nil) then scanDB("select * from messages limit 100"); end
      
      







フィルターについて詳しく説明します。

一般に、linqのような形式で行う必要はなく、フィルター自体はリクエストで作成できますが、これは「異常なプログラミング」ハブであるため、明らかでない何かを追加する必要があります。

停止が完了しました。



原則として、それだけです。

ご清聴ありがとうございました!



All Articles