├── server ├── .meteor │ ├── .gitignore │ ├── release │ ├── platforms │ ├── .finished-upgraders │ ├── .id │ ├── packages │ └── versions ├── private │ └── admin.txt ├── public │ ├── title_icon.png │ ├── wechat_icon.png │ ├── discNGOS-qrcode.jpg │ ├── bootstrap │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── css │ │ │ └── bootstrap-theme.min.css │ └── bootstrap-datepicker │ │ ├── locales │ │ ├── bootstrap-datepicker.kr.min.js │ │ ├── bootstrap-datepicker.ja.min.js │ │ ├── bootstrap-datepicker.zh-TW.min.js │ │ ├── bootstrap-datepicker.zh-CN.min.js │ │ ├── bootstrap-datepicker.he.min.js │ │ ├── bootstrap-datepicker.bg.min.js │ │ ├── bootstrap-datepicker.cy.min.js │ │ ├── bootstrap-datepicker.ms.min.js │ │ ├── bootstrap-datepicker.sw.min.js │ │ ├── bootstrap-datepicker.nb.min.js │ │ ├── bootstrap-datepicker.sk.min.js │ │ ├── bootstrap-datepicker.sq.min.js │ │ ├── bootstrap-datepicker.sl.min.js │ │ ├── bootstrap-datepicker.th.min.js │ │ ├── bootstrap-datepicker.da.min.js │ │ ├── bootstrap-datepicker.eu.min.js │ │ ├── bootstrap-datepicker.id.min.js │ │ ├── bootstrap-datepicker.pt.min.js │ │ ├── bootstrap-datepicker.az.min.js │ │ ├── bootstrap-datepicker.hr.min.js │ │ ├── bootstrap-datepicker.kk.min.js │ │ ├── bootstrap-datepicker.fa.min.js │ │ ├── bootstrap-datepicker.mk.min.js │ │ ├── bootstrap-datepicker.pt-BR.min.js │ │ ├── bootstrap-datepicker.rs.min.js │ │ ├── bootstrap-datepicker.sr.min.js │ │ ├── bootstrap-datepicker.ar.min.js │ │ ├── bootstrap-datepicker.is.min.js │ │ ├── bootstrap-datepicker.no.min.js │ │ ├── bootstrap-datepicker.bs.min.js │ │ ├── bootstrap-datepicker.cs.min.js │ │ ├── bootstrap-datepicker.fo.min.js │ │ ├── bootstrap-datepicker.lv.min.js │ │ ├── bootstrap-datepicker.ro.min.js │ │ ├── bootstrap-datepicker.tr.min.js │ │ ├── bootstrap-datepicker.gl.min.js │ │ ├── bootstrap-datepicker.hu.min.js │ │ ├── bootstrap-datepicker.pl.min.js │ │ ├── bootstrap-datepicker.rs-latin.min.js │ │ ├── bootstrap-datepicker.sr-latin.min.js │ │ ├── bootstrap-datepicker.sv.min.js │ │ ├── bootstrap-datepicker.es.min.js │ │ ├── bootstrap-datepicker.nl.min.js │ │ ├── bootstrap-datepicker.ca.min.js │ │ ├── bootstrap-datepicker.de.min.js │ │ ├── bootstrap-datepicker.fr-CH.min.js │ │ ├── bootstrap-datepicker.kh.min.js │ │ ├── bootstrap-datepicker.lt.min.js │ │ ├── bootstrap-datepicker.me.min.js │ │ ├── bootstrap-datepicker.en-GB.min.js │ │ ├── bootstrap-datepicker.ru.min.js │ │ ├── bootstrap-datepicker.it.min.js │ │ ├── bootstrap-datepicker.nl-BE.min.js │ │ ├── bootstrap-datepicker.uk.min.js │ │ ├── bootstrap-datepicker.vi.min.js │ │ ├── bootstrap-datepicker.fi.min.js │ │ ├── bootstrap-datepicker.hy.min.js │ │ ├── bootstrap-datepicker.it-CH.min.js │ │ ├── bootstrap-datepicker.fr.min.js │ │ ├── bootstrap-datepicker.ka.min.js │ │ ├── bootstrap-datepicker.el.min.js │ │ └── bootstrap-datepicker.et.min.js │ │ └── css │ │ ├── bootstrap-datepicker.min.css │ │ ├── bootstrap-datepicker.standalone.min.css │ │ └── bootstrap-datepicker.css ├── client │ ├── templates │ │ ├── about.css │ │ ├── about.js │ │ ├── chat-record-detail.html │ │ ├── wechat-live-server.js │ │ ├── top-activity.html │ │ ├── user-records.html │ │ ├── history.js │ │ ├── top-activity.js │ │ ├── history.html │ │ ├── wechat-live-server.html │ │ ├── chat-record-detail.js │ │ ├── about.html │ │ ├── user-records.js │ │ └── wechat-live-server.css │ └── head.html ├── lib │ ├── top-collections.js │ ├── router.js │ └── collections.js └── server │ └── server.js ├── phone ├── libs │ ├── Android-DDP.jar │ └── android-support-v4.jar ├── res │ ├── drawable-hdpi │ │ └── icon.png │ ├── xml │ │ └── wxlive_accessibility_service_config.xml │ ├── values-zh-rCN │ │ └── strings.xml │ ├── values │ │ └── strings.xml │ └── layout │ │ └── main.xml ├── .gitignore ├── src │ └── mobi │ │ └── espier │ │ └── lgc │ │ ├── util │ │ ├── WeakHandlerTemplate.java │ │ ├── SecurityUtils.java │ │ ├── LgcUtils.java │ │ ├── LogUtils.java │ │ └── PreferencesUtil.java │ │ ├── data │ │ ├── LgcDBHelper.java │ │ ├── LgcDataUtil.java │ │ ├── UploadHelper.java │ │ ├── LgcProvider.java │ │ └── MeteorHelper.java │ │ ├── service │ │ └── LgcAccessibilityService.java │ │ ├── LgcApp.java │ │ └── LgcActivity.java └── AndroidManifest.xml └── README.md /server/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /server/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.1.0.2 2 | -------------------------------------------------------------------------------- /server/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /server/private/admin.txt: -------------------------------------------------------------------------------- 1 | {"username":"username","password":"password"} 2 | -------------------------------------------------------------------------------- /phone/libs/Android-DDP.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/libs/Android-DDP.jar -------------------------------------------------------------------------------- /server/public/title_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/title_icon.png -------------------------------------------------------------------------------- /server/public/wechat_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/wechat_icon.png -------------------------------------------------------------------------------- /phone/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/libs/android-support-v4.jar -------------------------------------------------------------------------------- /phone/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /server/client/templates/about.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | 3 | .indent_p { 4 | text-indent: 2em; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /server/public/discNGOS-qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/discNGOS-qrcode.jpg -------------------------------------------------------------------------------- /server/public/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /server/public/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /server/public/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /server/public/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /phone/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.apk 3 | *.ap_ 4 | *.swp 5 | tags 6 | bin/ 7 | gen/ 8 | proguard/ 9 | .classpath 10 | .project 11 | tests/ 12 | .settings/ 13 | format.sh 14 | project.properties 15 | local.properties 16 | *.properties 17 | -------------------------------------------------------------------------------- /server/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | -------------------------------------------------------------------------------- /server/client/templates/about.js: -------------------------------------------------------------------------------- 1 | Template.about.onRendered(function () { 2 | var self = this; 3 | var div = self.find('#list_content_ul'); 4 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight; 5 | var header = self.find('#panel_heading'); 6 | div.style.height = iHeight - 5 - header.offsetHeight + "px"; 7 | }); 8 | -------------------------------------------------------------------------------- /server/.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 1fu1e451yg2hsx17ba4ha 8 | -------------------------------------------------------------------------------- /server/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-platform 8 | iron:router 9 | jparker:crypto-core 10 | jparker:crypto-md5 11 | accounts-password 12 | -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일","일요일"],daysShort:["일","월","화","수","목","금","토","일"],daysMin:["일","월","화","수","목","금","토","일"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜","日曜"],daysShort:["日","月","火","水","木","金","土","日"],daysMin:["日","月","火","水","木","金","土","日"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",clear:"クリア"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["週日","週一","週二","週三","週四","週五","週六","週日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今天",format:"yyyy年mm月dd日",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["周日","周一","周二","周三","周四","周五","周六","周日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今日",format:"yyyy年mm月dd日",weekStart:1,clear:"清空"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.he={days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון"],daysShort:["א","ב","ג","ד","ה","ו","ש","א"],daysMin:["א","ב","ג","ד","ה","ו","ש","א"],months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthsShort:["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],today:"היום",rtl:!0}}(jQuery); -------------------------------------------------------------------------------- /server/client/templates/chat-record-detail.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота","Неделя"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб","Нед"],daysMin:["Н","П","В","С","Ч","П","С","Н"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn","Sul"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad","Sul"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa","Su"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ms={days:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu","Ahad"],daysShort:["Aha","Isn","Sel","Rab","Kha","Jum","Sab","Aha"],daysMin:["Ah","Is","Se","Ra","Kh","Ju","Sa","Ah"],months:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],today:"Hari Ini"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sw={days:["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi","Jumapili"],daysShort:["J2","J3","J4","J5","Alh","Ij","J1","J2"],daysMin:["2","3","4","5","A","I","1","2"],months:["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],monthsShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],today:"Leo"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nb.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.nb={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag","Søndag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør","Søn"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø","Sø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I Dag"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota","Nedeľa"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob","Ned"],daysMin:["Ne","Po","Ut","St","Št","Pia","So","Ne"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë","E Diel"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu","Die"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht","Di"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],today:"Sot"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota","Nedelja"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob","Ned"],daysMin:["Ne","Po","To","Sr","Če","Pe","So","Ne"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.th={days:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัส","ศุกร์","เสาร์","อาทิตย์"],daysShort:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],daysMin:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],months:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthsShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],today:"วันนี้"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.da={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag","Søndag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør","Søn"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø","Sø"],months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"I Dag",clear:"Nulstil"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata","Igandea"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr","Ig"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr","Ig"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu"],daysShort:["Mgu","Sen","Sel","Rab","Kam","Jum","Sab","Mgu"],daysMin:["Mg","Sn","Sl","Ra","Ka","Ju","Sa","Mg"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ags","Sep","Okt","Nov","Des"],today:"Hari Ini",clear:"Kosongkan"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.pt={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb","Dom"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa","Do"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",clear:"Limpar"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə","Bazar"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş.","B."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş.","B."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.hr={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su","Ne"],months:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthsShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],today:"Danas"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.kk={days:["Жексенбі","Дүйсенбі","Сейсенбі","Сәрсенбі","Бейсенбі","Жұма","Сенбі","Жексенбі"],daysShort:["Жек","Дүй","Сей","Сәр","Бей","Жұм","Сен","Жек"],daysMin:["Жк","Дс","Сс","Ср","Бс","Жм","Сн","Жк"],months:["Қаңтар","Ақпан","Наурыз","Сәуір","Мамыр","Маусым","Шілде","Тамыз","Қыркүйек","Қазан","Қараша","Желтоқсан"],monthsShort:["Қаң","Ақп","Нау","Сәу","Мамыр","Мау","Шлд","Тмз","Қыр","Қзн","Қар","Жел"],today:"Бүгін",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fa={days:["یک‌شنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنج‌شنبه","جمعه","شنبه","یک‌شنبه"],daysShort:["یک","دو","سه","چهار","پنج","جمعه","شنبه","یک"],daysMin:["ی","د","س","چ","پ","ج","ش","ی"],months:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthsShort:["ژان","فور","مار","آور","مه","ژون","ژوی","اوت","سپت","اکت","نوا","دسا"],today:"امروز",clear:"پاک کن",weekStart:1,format:"yyyy/mm/dd"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.mk={days:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота","Недела"],daysShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб","Нед"],daysMin:["Не","По","Вт","Ср","Че","Пе","Са","Не"],months:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],today:"Денес",format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["pt-BR"]={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb","Dom"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa","Do"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",clear:"Limpar"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота","Недеља"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб","Нед"],daysMin:["Н","По","У","Ср","Ч","Пе","Су","Н"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sr={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота","Недеља"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб","Нед"],daysMin:["Н","По","У","Ср","Ч","Пе","Су","Н"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.is={days:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur","Sunnudagur"],daysShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau","Sun"],daysMin:["Su","Má","Þr","Mi","Fi","Fö","La","Su"],months:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],today:"Í Dag"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.no={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I dag",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota","Neděle"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob","Ned"],daysMin:["Ne","Po","Út","St","Čt","Pá","So","Ne"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",weekStart:1,format:"d.m.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fo={days:["Sunnudagur","Mánadagur","Týsdagur","Mikudagur","Hósdagur","Fríggjadagur","Leygardagur","Sunnudagur"],daysShort:["Sun","Mán","Týs","Mik","Hós","Frí","Ley","Sun"],daysMin:["Su","Má","Tý","Mi","Hó","Fr","Le","Su"],months:["Januar","Februar","Marts","Apríl","Mei","Juni","Juli","August","Septembur","Oktobur","Novembur","Desembur"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"Í Dag",clear:"Reinsa"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena","Svētdiena"],daysShort:["Sv","P","O","T","C","Pk","S","Sv"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se","Sv"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],today:"Šodien",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă","Duminică"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm","Dum"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ","Du"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.tr={days:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi","Pazar"],daysShort:["Pz","Pzt","Sal","Çrş","Prş","Cu","Cts","Pz"],daysMin:["Pz","Pzt","Sa","Çr","Pr","Cu","Ct","Pz"],months:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthsShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],today:"Bugün",clear:"Temizle",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.gl={days:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado","Domingo"],daysShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb","Dom"],daysMin:["Do","Lu","Ma","Me","Xo","Ve","Sa","Do"],months:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthsShort:["Xan","Feb","Mar","Abr","Mai","Xun","Xul","Ago","Sep","Out","Nov","Dec"],today:"Hoxe",clear:"Limpar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.hu={days:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat","Vasárnap"],daysShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo","Vas"],daysMin:["Va","Hé","Ke","Sz","Cs","Pé","Sz","Va"],months:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthsShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Sze","Okt","Nov","Dec"],today:"Ma",weekStart:1,format:"yyyy.mm.dd"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.pl={days:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota","Niedziela"],daysShort:["Nie","Pn","Wt","Śr","Czw","Pt","So","Nie"],daysMin:["N","Pn","Wt","Śr","Cz","Pt","So","N"],months:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthsShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],today:"Dzisiaj",weekStart:1,clear:"Wyczyść"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota","Nedelja"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["sr-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota","Nedelja"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag","Söndag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör","Sön"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö","Sö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb","Dom"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa","Do"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.nl={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag"],daysShort:["zo","ma","di","wo","do","vr","za","zo"],daysMin:["zo","ma","di","wo","do","vr","za","zo"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",clear:"Wissen",weekStart:1,format:"dd-mm-yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ca={days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte","Diumenge"],daysShort:["Diu","Dil","Dmt","Dmc","Dij","Div","Dis","Diu"],daysMin:["dg","dl","dt","dc","dj","dv","ds","dg"],months:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],today:"Avui",clear:"Esborrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam","Son"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa","So"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fr={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam","Dim"],daysMin:["D","L","Ma","Me","J","V","S","D"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",clear:"Effacer",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.lt={days:["Sekmadienis","Pirmadienis","Antradienis","Trečiadienis","Ketvirtadienis","Penktadienis","Šeštadienis","Sekmadienis"],daysShort:["S","Pr","A","T","K","Pn","Š","S"],daysMin:["Sk","Pr","An","Tr","Ke","Pn","Št","Sk"],months:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthsShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],today:"Šiandien",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.me={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su","Ne"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,clear:"Izbriši",format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["en-GB"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота","Воскресенье"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб","Вск"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб","Вс"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato","Domenica"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab","Dom"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa","Do"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates["nl-BE"]={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag"],daysShort:["zo","ma","di","wo","do","vr","za","zo"],daysMin:["zo","ma","di","wo","do","vr","za","zo"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",clear:"Leegmaken",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота","Неділя"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб","Нед"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб","Нд"],months:["Cічень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.vi={days:["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy","Chủ nhật"],daysShort:["CN","Thứ 2","Thứ 3","Thứ 4","Thứ 5","Thứ 6","Thứ 7","CN"],daysMin:["CN","T2","T3","T4","T5","T6","T7","CN"],months:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],monthsShort:["Th1","Th2","Th3","Th4","Th5","Th6","Th7","Th8","Th9","Th10","Th11","Th12"],today:"Hôm nay",clear:"Xóa",format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai","sunnuntai"],daysShort:["sun","maa","tii","kes","tor","per","lau","sun"],daysMin:["su","ma","ti","ke","to","pe","la","su"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",weekStart:1,format:"d.m.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ","Կիրակի"],daysShort:["Կիր","Երկ","Երք","Չոր","Հնգ","Ուր","Շաբ","Կիր"],daysMin:["Կի","Եկ","Եք","Չո","Հի","Ու","Շա","Կի"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հնվ","Փետ","Մար","Ապր","Մայ","Հուն","Հուլ","Օգս","Սեպ","Հոկ","Նոյ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato","Domenica"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab","Dom"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa","Do"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.fr={days:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"],daysShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam.","dim."],daysMin:["d","l","ma","me","j","v","s","d"],months:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthsShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],today:"Aujourd'hui",clear:"Effacer",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი","კვირა"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ","კვი"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა","კვ"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο","Κυριακή"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ","Κυρ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα","Κυ"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/public/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.datepicker.dates.et={days:["Pühapäev","Esmaspäev","Teisipäev","Kolmapäev","Neljapäev","Reede","Laupäev","Pühapäev"],daysShort:["Pühap","Esmasp","Teisip","Kolmap","Neljap","Reede","Laup","Pühap"],daysMin:["P","E","T","K","N","R","L","P"],months:["Jaanuar","Veebruar","Märts","Aprill","Mai","Juuni","Juuli","August","September","Oktoober","November","Detsember"],monthsShort:["Jaan","Veebr","Märts","Apr","Mai","Juuni","Juuli","Aug","Sept","Okt","Nov","Dets"],today:"Täna",clear:"Tühjenda",weekStart:1,format:"dd.mm.yyyy"}}(jQuery); -------------------------------------------------------------------------------- /server/client/templates/wechat-live-server.js: -------------------------------------------------------------------------------- 1 | 2 | Template.wechatLiveMain.helpers({ 3 | chat_records: function () { 4 | return ChatRecords.liveItems(); 5 | }, 6 | 7 | today: function() { 8 | return new Date().Format("yyyy-MM-dd"); 9 | } 10 | }); 11 | 12 | Template.wechatLiveMain.onRendered(function () { 13 | Session.set('detail_mode','live'); 14 | var div = document.getElementById('list_content_ul'); 15 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight; 16 | var header = document.getElementById('panel_heading'); 17 | div.style.height = iHeight - header.offsetHeight - 15 + "px"; 18 | 19 | div.scrollTop = div.scrollHeight; 20 | }); 21 | 22 | 23 | -------------------------------------------------------------------------------- /server/lib/top-collections.js: -------------------------------------------------------------------------------- 1 | TopRecords = new Mongo.Collection("wx_top_records"); 2 | //nickId, chatCount, lastContent 3 | 4 | TopRecords.addOrInsertRecord = function (nickId, lastContent) { 5 | //console.log("......nickId:"+ nickId+ " "+lastContent); 6 | var topR = TopRecords.findOne({nickId: nickId}); 7 | var result; 8 | if (topR === undefined) { 9 | var count = ChatRecords.rank(nickId); 10 | result = TopRecords.insert({nickId: nickId, chatCount: count, lastContent: lastContent}); 11 | } else { 12 | result = TopRecords.update({nickId: nickId}, { 13 | nickId: nickId, 14 | chatCount: topR.chatCount + 1, 15 | lastContent: lastContent 16 | }); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /server/client/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 直播“下一代智能操作系统开发讨论” 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | -------------------------------------------------------------------------------- /server/client/templates/top-activity.html: -------------------------------------------------------------------------------- 1 | 26 | 27 | 35 | -------------------------------------------------------------------------------- /server/client/templates/user-records.html: -------------------------------------------------------------------------------- 1 | 26 | 27 | 41 | 42 | -------------------------------------------------------------------------------- /phone/res/xml/wxlive_accessibility_service_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 28 | 29 | -------------------------------------------------------------------------------- /server/.meteor/versions: -------------------------------------------------------------------------------- 1 | accounts-base@1.2.0 2 | accounts-password@1.1.1 3 | autoupdate@1.2.1 4 | base64@1.0.3 5 | binary-heap@1.0.3 6 | blaze@2.1.2 7 | blaze-tools@1.0.3 8 | boilerplate-generator@1.0.3 9 | callback-hook@1.0.3 10 | check@1.0.5 11 | ddp@1.1.0 12 | deps@1.0.7 13 | ejson@1.0.6 14 | email@1.0.6 15 | fastclick@1.0.3 16 | geojson-utils@1.0.3 17 | html-tools@1.0.4 18 | htmljs@1.0.4 19 | http@1.1.0 20 | id-map@1.0.3 21 | iron:controller@1.0.7 22 | iron:core@1.0.7 23 | iron:dynamic-template@1.0.7 24 | iron:layout@1.0.7 25 | iron:location@1.0.7 26 | iron:middleware-stack@1.0.7 27 | iron:router@1.0.7 28 | iron:url@1.0.7 29 | jparker:crypto-core@0.1.0 30 | jparker:crypto-md5@0.1.1 31 | jquery@1.11.3_2 32 | json@1.0.3 33 | launch-screen@1.0.2 34 | livedata@1.0.13 35 | localstorage@1.0.3 36 | logging@1.0.7 37 | meteor@1.1.6 38 | meteor-platform@1.2.2 39 | minifiers@1.1.5 40 | minimongo@1.0.8 41 | mobile-status-bar@1.0.3 42 | mongo@1.1.0 43 | npm-bcrypt@0.7.8_2 44 | observe-sequence@1.0.6 45 | ordered-dict@1.0.3 46 | random@1.0.3 47 | reactive-dict@1.1.0 48 | reactive-var@1.0.5 49 | reload@1.1.3 50 | retry@1.0.3 51 | routepolicy@1.0.5 52 | service-configuration@1.0.4 53 | session@1.1.0 54 | sha@1.0.3 55 | spacebars@1.0.6 56 | spacebars-compiler@1.0.6 57 | srp@1.0.3 58 | templating@1.1.1 59 | tracker@1.0.7 60 | ui@1.0.6 61 | underscore@1.0.3 62 | url@1.0.4 63 | webapp@1.2.0 64 | webapp-hashing@1.0.3 65 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/util/WeakHandlerTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under the terms of the 5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3 6 | * of the License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * Affero General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Affero General Public License along with this program. 13 | * If not, see . 14 | */ 15 | package mobi.espier.lgc.util; 16 | 17 | import java.lang.ref.WeakReference; 18 | 19 | import android.os.Handler; 20 | 21 | public class WeakHandlerTemplate extends Handler { 22 | private final WeakReference mContext; 23 | 24 | public WeakHandlerTemplate(T context) { 25 | mContext = new WeakReference(context); 26 | } 27 | 28 | public WeakHandlerTemplate(T context, Callback cb) { 29 | super(cb); 30 | mContext = new WeakReference(context); 31 | } 32 | 33 | protected T getObject() { 34 | if (mContext != null) return mContext.get(); 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /server/client/templates/history.js: -------------------------------------------------------------------------------- 1 | 2 | HISTORY_RECORDS_SIZE = "historyBlockSize"; 3 | HISTORY_DATE = "historyDate"; 4 | 5 | Session.setDefault(HISTORY_RECORDS_SIZE, FIRST_BLOCK_SIZE); 6 | 7 | Template.history.helpers({ 8 | chat_records: function () { 9 | return ChatRecords.findBlockHistoryItemsByDay(this.time, ASC_SORT, 10 | Session.get(HISTORY_RECORDS_SIZE)); 11 | } 12 | }); 13 | 14 | Template.history.events({ 15 | 'scroll ul': function (event) { 16 | var div = document.getElementById("list_content_ul"); 17 | 18 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) { 19 | console.log('screenTop=' + div.scrollTop + ' get more'); 20 | Session.set(HISTORY_RECORDS_SIZE, Session.get(HISTORY_RECORDS_SIZE) + INCREASE_BLOCK_SIZE); 21 | 22 | } 23 | } 24 | }); 25 | 26 | Template.history.rendered = function() { 27 | this.autorun(function() { 28 | Meteor.subscribe("recordsInDay", Session.get(HISTORY_DATE), ASC_SORT, 29 | Session.get(HISTORY_RECORDS_SIZE)); 30 | }); 31 | }; 32 | 33 | Template.history.onRendered(function () { 34 | Session.set('detail_mode','history'); 35 | var div = document.getElementById('list_content_ul'); 36 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight; 37 | var header = document.getElementById('panel_heading'); 38 | div.style.height = iHeight - header.offsetHeight - 15 + "px"; 39 | }); 40 | -------------------------------------------------------------------------------- /phone/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 群聊直播 13 | 群聊直播描述 14 | 通知服务 : 正在运行 15 | 通知服务 : 已停止 16 | 辅助功能 17 | WebSocket URL : 18 | "ws://ip:port/xxx" 19 | 用户名 : 20 | 密码 : 21 | 启动 22 | 停止 23 | "参数不能为空" 24 | "登录失败 : " 25 | 26 | "正在连接服务器 ..." 27 | "服务器连接成功 ..." 28 | "用户登录 ..." 29 | "用户登录成功 ..." 30 | "用户登录失败 ..." 31 | "断开连接原因 : " 32 | "上传数据 : " 33 | 34 | 35 | -------------------------------------------------------------------------------- /server/client/templates/top-activity.js: -------------------------------------------------------------------------------- 1 | USER_RANK_SIZE = "userRankSize"; 2 | Session.setDefault(USER_RANK_SIZE, FIRST_BLOCK_SIZE); 3 | 4 | Template.userRank.helpers({ 5 | users: function () { 6 | return TopRecords.find({}, {sort: {chatCount: DESC_SORT}}).map( 7 | function (doc, index, cursor) { 8 | var i = _.extend(doc, {index: index}); 9 | return i; 10 | }); 11 | } 12 | }); 13 | 14 | Template.userRank.events({ 15 | 'scroll ul': function (event) { 16 | var div = document.getElementById("list_content_ul"); 17 | 18 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) { 19 | if (TopRecords.find().count() >= Session.get(USER_RANK_SIZE)) 20 | Session.set(USER_RANK_SIZE, Session.get(USER_RANK_SIZE) + INCREASE_BLOCK_SIZE); 21 | } 22 | } 23 | }); 24 | 25 | Template.userRank.rendered = function() { 26 | this.autorun(function() { 27 | Meteor.subscribe("userRanks", DESC_SORT, Session.get(USER_RANK_SIZE)); 28 | }); 29 | }; 30 | 31 | Template.userRank.onRendered(function () { 32 | var self = this; 33 | userIndex = 0; 34 | var div = self.find('#list_content_ul'); 35 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight; 36 | var header = self.find('#panel_heading'); 37 | div.style.height = iHeight - 5 - header.offsetHeight + "px"; 38 | }); 39 | 40 | Template.userItem.helpers({ 41 | bg: function (index) { 42 | return index % 2 == 0 ? " list-group-item-info" : ""; 43 | } 44 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Live Group Chat 2 | 3 | Live Group Chat can broadcast the group chat records of WeChat (or other Instant Messaging apps) to a web page. 4 | 5 | Live Group Chat contains an Android app and a web site. The former hooks to the Android notification system and send the chat records to the web site via WebSocket; the latter receives the chat records and shows them in a web page. 6 | 7 | The web site is developed by using [Meteor](https://www.meteor.com). 8 | 9 | For a live demonstration, please visit [NGOS live discussion site](http://ngsos.fullstackengineer.net/). 10 | 11 | ## Usage 12 | ### Android app 13 | * Install Live Group Chat app. 14 | * Enable Notification service (Settings->Acessibility->Live Group Chat). 15 | * Input correct websocket url, username and password. 16 | * Click Start button. 17 | 18 | ### Web site 19 | #### Build meteor application bundle 20 | ``` shell 21 | $ cd live-group-chat/server 22 | $ meteor build dest_dir # the output directory will contain just a tarball that includes everything necessary to run the application server. (server.tar.gz) 23 | ``` 24 | #### Deploy application on the internet 25 | * External dependency:[Node.js 0.10.36](http://nodejs.org/dist/v0.10.36/), [MongoDB](http://www.mongodb.org/downloads). 26 | * To run the application: 27 | ``` shell 28 | $ (cd programs/server && npm install) 29 | $ export PORT="3000" 30 | $ export MONGO_URL='mongodb://user:password@host:port/databasename' 31 | $ export ROOT_URL='http://example.com' 32 | $ export MAIL_URL='smtp://user:password@mailhost:port/' 33 | $ node main.js # PORT="80", need root privileges 34 | ``` 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /server/client/templates/history.html: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /server/client/templates/wechat-live-server.html: -------------------------------------------------------------------------------- 1 | 42 | 43 | -------------------------------------------------------------------------------- /server/client/templates/chat-record-detail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by xwyan on 15/4/17. 3 | */ 4 | Template.chat_record_detail.helpers({ 5 | createdAtHuman : function(createdAt) { 6 | if (Session.get('detail_mode') == 'live') { 7 | var div = document.getElementById("list_content_ul"); 8 | if (div && div.scrollTop + div.offsetHeight >= div.scrollHeight) 9 | Session.set("scrollToBottom", true); 10 | else 11 | Session.set("scrollToBottom", false); 12 | } 13 | return ChatRecords.date(createdAt, "hh:mm"); 14 | } 15 | }); 16 | 17 | function Linkify(inputText) { 18 | //URLs starting with http://, https://, or ftp:// 19 | var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; 20 | var replacedText = inputText.replace(replacePattern1, '$1'); 21 | 22 | //URLs starting with www. (without // before it, or it'd re-link the ones done above) 23 | var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; 24 | var replacedText = replacedText.replace(replacePattern2, '$1$2'); 25 | 26 | //Change email addresses to mailto:: links 27 | var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim; 28 | var replacedText = replacedText.replace(replacePattern3, '$1'); 29 | 30 | return replacedText; 31 | } 32 | 33 | Template.chat_record_detail.onRendered (function () { 34 | var detail = this.$('div.content'); 35 | var html = Linkify (detail.text ()); 36 | detail.html (html); 37 | 38 | if(Session.get('detail_mode') == 'live' && Session.get("scrollToBottom")) { 39 | var div = document.getElementById("list_content_ul"); 40 | div.scrollTop = div.scrollHeight; 41 | } 42 | }); 43 | 44 | -------------------------------------------------------------------------------- /server/lib/router.js: -------------------------------------------------------------------------------- 1 | 2 | Router.configure({ 3 | waitOn: function() { 4 | return [Meteor.subscribe('liveRecords', LIVE_TIME)]; 5 | } 6 | }); 7 | 8 | Router.map(function() { 9 | this.route('wechatLiveMain', { 10 | path: '/' 11 | }); 12 | 13 | this.route('userRank', { 14 | path: '/users', 15 | onBeforeAction: function() { 16 | Meteor.subscribe('userRanks', DESC_SORT, FIRST_BLOCK_SIZE); 17 | this.next(); 18 | }, 19 | 20 | action: function() { 21 | this.render(); 22 | } 23 | }); 24 | 25 | this.route('userRecords', { 26 | path: '/users/:nickId', 27 | 28 | onBeforeAction: function() { 29 | Session.set(USER_RECORDS_SIZE, FIRST_BLOCK_SIZE); 30 | Session.set(HISTORY_NICKID, this.params.nickId); 31 | Meteor.subscribe('recordsInNick', this.params.nickId, ASC_SORT,FIRST_BLOCK_SIZE); 32 | this.next(); 33 | }, 34 | 35 | data: function() { 36 | return {nickId: this.params.nickId}; 37 | }, 38 | 39 | action: function() { 40 | this.render(); 41 | } 42 | }); 43 | 44 | 45 | this.route('history', { 46 | path: '/history/:date', 47 | 48 | onBeforeAction: function() { 49 | time = new Date(this.params.date).getTime(); 50 | Session.set(HISTORY_RECORDS_SIZE, FIRST_BLOCK_SIZE); 51 | Session.set(HISTORY_DATE, time); 52 | Meteor.subscribe('recordsInDay', time, ASC_SORT, FIRST_BLOCK_SIZE); 53 | this.next(); 54 | }, 55 | 56 | data: function() { 57 | return {time: new Date(this.params.date).getTime(), date: this.params.date}; 58 | }, 59 | 60 | action: function() { 61 | this.render(); 62 | } 63 | }) 64 | 65 | this.route('about', { 66 | path: '/about' 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /server/client/templates/about.html: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /server/client/templates/user-records.js: -------------------------------------------------------------------------------- 1 | USER_RECORDS_SIZE = "userBlockSize"; 2 | HISTORY_NICKID = "historyNickId"; 3 | 4 | Session.setDefault(USER_RECORDS_SIZE, FIRST_BLOCK_SIZE); 5 | 6 | Template.userRecords.helpers({ 7 | records : function(id) { 8 | return ChatRecords.find({nickId:id}, {sort: {createdAt: ASC_SORT}}).map(function (doc, index, cursor) { 9 | var i = _.extend(doc, {index: index}); 10 | return i; 11 | }); 12 | } 13 | }); 14 | 15 | Template.userRecords.events({ 16 | 'scroll ul': function (event) { 17 | var div = document.getElementById("list_content_ul"); 18 | 19 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) { 20 | Session.set(USER_RECORDS_SIZE, Session.get(USER_RECORDS_SIZE) + INCREASE_BLOCK_SIZE); 21 | } 22 | } 23 | }); 24 | 25 | Template.userRecords.rendered = function() { 26 | this.autorun(function() { 27 | Meteor.subscribe("recordsInNick", Session.get(HISTORY_NICKID), 28 | ASC_SORT, Session.get(USER_RECORDS_SIZE)); 29 | }); 30 | }; 31 | 32 | 33 | Template.userRecords.onRendered(function(){ 34 | var self=this; 35 | var div = self.find('#list_content_ul'); 36 | var iHeight = document.documentElement.clientHeight||document.body.clientHeight; 37 | var header = self.find('#panel_heading'); 38 | div.style.height = iHeight- 15 -header.offsetHeight+"px"; 39 | var title_div = self.find('#title'); 40 | var container = self.find('#container'); 41 | title_div.style.width = container.offsetWidth-150 +"px"; 42 | }); 43 | 44 | 45 | Template.userRecordItem.helpers({ 46 | createdAtHuman : function(createdAt) { 47 | return ChatRecords.date(createdAt,"MM-dd hh:mm"); 48 | }, 49 | bg:function(index){ 50 | return index % 2 == 0 ? "list-group-item-info" : ""; 51 | } 52 | }); 53 | 54 | Template.userRecordItem.onRendered (function () { 55 | var detail = this.$('div.content'); 56 | var html = Linkify (detail.text ()); 57 | detail.html (html); 58 | 59 | }); 60 | -------------------------------------------------------------------------------- /server/server/server.js: -------------------------------------------------------------------------------- 1 | var timeInterval = 24*60*60*1000; 2 | 3 | Meteor.publish('recordsInDay', function(dayms, sort, limitSize) { 4 | var time = beginTime(dayms); 5 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$lt: time+timeInterval, $gte:time}}, 6 | {sort: {createdAt : sort}, limit : limitSize}); 7 | }); 8 | 9 | Meteor.publish('recordsInNick',function(nickid, sort, limitSize) { 10 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, nickId: nickid}, 11 | {sort: {createdAt : sort}, limit : limitSize}); 12 | }); 13 | 14 | Meteor.publish('liveRecords', function(time) { 15 | var result = ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$lt : time}}, {sort: {createdAt : -1}, 16 | limit : 20}); 17 | var resultArray = result.fetch(); 18 | if (resultArray.length != 0) { 19 | time = resultArray[resultArray.length-1].createdAt; 20 | } 21 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$gte : time}}, {sort: {createdAt : 1}}); 22 | }); 23 | 24 | Meteor.publish("userRanks", function (sort, limit) { 25 | return TopRecords.find({nickId: {$ne: ''}}, {sort: {chatCount: sort}, limit: limit}); 26 | }); 27 | 28 | Accounts.onCreateUser(function(options, user) { 29 | if (options.profile) 30 | user.profile = options.profile; 31 | 32 | var admin = JSON.parse(Assets.getText("admin.txt")); 33 | user.admin = (user.username === admin.username); 34 | 35 | return user; 36 | }); 37 | 38 | if (Meteor.isServer) { 39 | Meteor.startup(function () { 40 | // code to run on server at startup 41 | try { 42 | var admin = JSON.parse(Assets.getText("admin.txt")); 43 | 44 | if(!Meteor.users.findOne({username: admin.username})) { 45 | Accounts.createUser({ 46 | username: admin.username, 47 | password: admin.password 48 | }); 49 | } else { 50 | console.log('admin exists'); 51 | } 52 | } catch (error) { 53 | console.log(error.reason); 54 | } 55 | 56 | ChatRecords.find({createdAt: {$gte:new Date().getTime()}}).observe({ 57 | added:function(record){ 58 | TopRecords.addOrInsertRecord(record.nickId,record.content); 59 | } 60 | }); 61 | 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/data/LgcDBHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | * 17 | */ 18 | package mobi.espier.lgc.data; 19 | 20 | import android.content.Context; 21 | import android.database.sqlite.SQLiteDatabase; 22 | import android.database.sqlite.SQLiteOpenHelper; 23 | 24 | public class LgcDBHelper extends SQLiteOpenHelper { 25 | 26 | private static final int DB_VERSION = 1; 27 | private static final String DB_NAME = "wxlive.db"; 28 | public static final String TABLE_NAME = "notifications"; 29 | 30 | public LgcDBHelper(Context context) { 31 | super(context, DB_NAME, null, DB_VERSION); 32 | } 33 | 34 | @Override 35 | public void onCreate(SQLiteDatabase db) { 36 | db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + LgcProvider.DataColumns._ID 37 | + " INTEGER PRIMARY KEY, " + LgcProvider.DataColumns.NAME + " TEXT, " 38 | + LgcProvider.DataColumns.CONTENT + " TEXT, " + LgcProvider.DataColumns.TYPE 39 | + " INTEGER, " + LgcProvider.DataColumns.TIME + " INTEGER, " 40 | + LgcProvider.DataColumns.HASH + " TEXT, " + LgcProvider.DataColumns.SYNC 41 | + " INTEGER " + " );"); 42 | } 43 | 44 | @Override 45 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 46 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); 47 | onCreate(db); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /phone/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | Live Group Chat 23 | Live chat group description. 24 | Notification service : Running 25 | Notification service : Stopped 26 | Accessibility 27 | WebSocket URL : 28 | "ws://ip:port/xxx" 29 | Username : 30 | Password : 31 | Start 32 | Stop 33 | "Parameters must not be null" 34 | "Login failed : " 35 | 36 | 37 | "connect to server ..." 38 | "connect ok ..." 39 | "user login ..." 40 | "user login ok ..." 41 | "user login failed ..." 42 | "disconnect reason : " 43 | "update data : " 44 | 45 | 46 | -------------------------------------------------------------------------------- /server/lib/collections.js: -------------------------------------------------------------------------------- 1 | ChatRecords = new Mongo.Collection("wx_chat_records"); 2 | //nickId, content, contentType, createdAt, hash, comment, commentId, commentAt 3 | 4 | LIVE_TIME = new Date().getTime(); 5 | FIRST_BLOCK_SIZE = 30; 6 | INCREASE_BLOCK_SIZE = 20; 7 | 8 | DESC_SORT = -1; 9 | ASC_SORT = 1; 10 | 11 | var timeInterval = 24*60*60*1000; 12 | 13 | beginTime = function(ms) { 14 | var date = new Date(ms); 15 | return ms - date.getHours()*60*60*1000 - date.getMinutes()*60*1000 - date.getSeconds()*1000 - date.getMilliseconds(); 16 | 17 | } 18 | 19 | ChatRecords.allow({ 20 | insert: function (userId) { 21 | var user = Meteor.users.findOne(userId); 22 | return user && user.admin; 23 | }, 24 | update: function (userId) { 25 | var user = Meteor.users.findOne(userId); 26 | return user && user.admin; 27 | } 28 | }); 29 | 30 | ChatRecords.liveItems = function() { 31 | time = LIVE_TIME; 32 | var starttime = beginTime(time); 33 | var result = ChatRecords.find({createdAt: {$lt : time, $gte: starttime}}, {sort: {createdAt : DESC_SORT}, 34 | limit : FIRST_BLOCK_SIZE}); 35 | var resultArray = result.fetch(); 36 | if (resultArray.length != 0) { 37 | time = resultArray[resultArray.length-1].createdAt; 38 | } 39 | return ChatRecords.find({createdAt: {$gte : time}}, {sort: {createdAt : ASC_SORT}}); 40 | } 41 | 42 | ChatRecords.findBlockHistoryItemsByDay = function(msInDay, sort, limitSize) { 43 | var time = beginTime(msInDay); 44 | return ChatRecords.find({createdAt: {$lt : time + timeInterval, $gte: time}}, {sort: {createdAt : sort}, 45 | limit: limitSize}); 46 | } 47 | 48 | ChatRecords.rank = function(nickId) { 49 | return ChatRecords.find({nickId: nickId}).count(); 50 | } 51 | 52 | Date.prototype.Format = function (fmt) { //author: meizz 53 | var o = { 54 | "M+": this.getMonth() + 1, //月份 55 | "d+": this.getDate(), //日 56 | "h+": this.getHours(), //小时 57 | "m+": this.getMinutes(), //分 58 | "s+": this.getSeconds(), //秒 59 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 60 | "S": this.getMilliseconds() //毫秒 61 | }; 62 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 63 | for (var k in o) 64 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 65 | return fmt; 66 | } 67 | 68 | ChatRecords.date = function(ms,format) { 69 | return new Date(ms).Format(format); 70 | } 71 | -------------------------------------------------------------------------------- /server/client/templates/wechat-live-server.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | body { 3 | font-family: sans-serif; 4 | background-color: white; 5 | background-attachment: fixed; 6 | 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | left: 0; 11 | right: 0; 12 | 13 | padding: 0; 14 | margin: 0; 15 | } 16 | 17 | .item{ 18 | width:100%; 19 | } 20 | 21 | #container { 22 | max-width: 768px; 23 | background:#ecefef; 24 | margin: 0 auto; 25 | min-height: 100%; 26 | position:relative; 27 | } 28 | 29 | .nickId { 30 | font-size: 14px; 31 | margin-bottom:5px; 32 | width:50%; 33 | background: transparent; 34 | color:#666666; 35 | float:left; 36 | } 37 | 38 | .createdAt { 39 | font-size: 12px; 40 | margin-bottom:5px; 41 | float:right; 42 | width:50%; 43 | background: transparent; 44 | text-align:right; 45 | color:#666666; 46 | } 47 | 48 | .content { 49 | font-size: 16px; 50 | padding:10px; 51 | border:1px solid; 52 | border-color:#b3b3b3; 53 | border-radius:7px; 54 | float:left; 55 | margin-bottom:25px; 56 | background:white; 57 | word-break:break-all; 58 | } 59 | 60 | #panel_heading { 61 | margin: 0; 62 | background: -webkit-gradient(linear, 0% 0%, 0% 100%,from(#573e7d ), to(#6f5499)); 63 | background: -moz-linear-gradient(top, #573e7d, #6f5499); 64 | background: -o-linear-gradient(top,#573e7d, #6f5499); 65 | color: #ffffff; 66 | padding: 5px 15px 5px 15px; 67 | min-height: 50px; 68 | position: relative; 69 | text-align:center; 70 | vertical-align:middle; 71 | } 72 | #panel_body { 73 | padding: 0; 74 | margin: 0; 75 | } 76 | 77 | 78 | #title { 79 | font-size: 18px; 80 | margin: 0; 81 | min-height: 40px; 82 | line-height: 40px; 83 | text-align: center; 84 | display: inline-block; 85 | white-space:nowrap; 86 | text-overflow:ellipsis; 87 | -o-text-overflow:ellipsis; 88 | overflow:hidden; 89 | } 90 | 91 | #img_title_icon{ 92 | width: 30px; 93 | height: 22px; 94 | } 95 | 96 | ul { 97 | margin-left:20px; 98 | padding: 0; 99 | padding-right: 20px; 100 | background: transparent; 101 | height: 650px; 102 | overflow-x:hidden; 103 | overflow-y:scroll; 104 | } 105 | 106 | .top_ul { 107 | margin-left:0px; 108 | padding: 0; 109 | padding-right: 2px; 110 | background: transparent; 111 | word-break: break-all; 112 | height: 650px; 113 | overflow-x:hidden; 114 | overflow-y:scroll; 115 | } 116 | 117 | .span_icon { 118 | font-size: 26px; 119 | text-align: center; 120 | } 121 | 122 | #btn_glyphicon { 123 | color: white; 124 | } 125 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/util/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under the terms of the 5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3 6 | * of the License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * Affero General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Affero General Public License along with this program. 13 | * If not, see . 14 | */ 15 | 16 | package mobi.espier.lgc.util; 17 | 18 | import java.security.InvalidKeyException; 19 | import java.security.MessageDigest; 20 | import java.security.NoSuchAlgorithmException; 21 | 22 | import javax.crypto.Mac; 23 | import javax.crypto.spec.SecretKeySpec; 24 | 25 | 26 | public class SecurityUtils { 27 | private static final String TAG = "SecrityUtils"; 28 | 29 | public static String hmacMd5(String data, String key) { 30 | Mac mac; 31 | try { 32 | mac = Mac.getInstance("HmacMD5"); 33 | SecretKeySpec sk = new SecretKeySpec(key.getBytes(), mac.getAlgorithm()); 34 | mac.init(sk); 35 | byte[] result = mac.doFinal(data.getBytes()); 36 | 37 | StringBuilder sb = new StringBuilder(); 38 | for (byte b : result) { 39 | sb.append(String.format("%02x", b)); 40 | } 41 | 42 | return sb.toString(); 43 | 44 | } catch (NoSuchAlgorithmException e) {} catch (InvalidKeyException e) {} 45 | 46 | return ""; 47 | } 48 | 49 | public static String md5(String key) { 50 | return md5(key.getBytes()); 51 | } 52 | 53 | public static String md5(byte[] input) { 54 | String cacheKey = null; 55 | try { 56 | final MessageDigest mDigest = MessageDigest.getInstance("MD5"); 57 | mDigest.update(input); 58 | cacheKey = bytesToHexString(mDigest.digest()); 59 | } catch (NoSuchAlgorithmException e) {} 60 | return cacheKey; 61 | } 62 | 63 | private static String bytesToHexString(byte[] bytes) { 64 | // http://stackoverflow.com/questions/332079 65 | StringBuilder sb = new StringBuilder(); 66 | for (int i = 0; i < bytes.length; i++) { 67 | String hex = Integer.toHexString(0xFF & bytes[i]); 68 | if (hex.length() == 1) { 69 | sb.append('0'); 70 | } 71 | sb.append(hex); 72 | } 73 | return sb.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/util/LgcUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under the terms of the 5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3 6 | * of the License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * Affero General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Affero General Public License along with this program. 13 | * If not, see . 14 | */ 15 | package mobi.espier.lgc.util; 16 | 17 | 18 | import android.content.Context; 19 | 20 | public class LgcUtils { 21 | public static final int UPLOAD_DELAYED = 30000; 22 | public static final int UPLOAD_LIMIT = 10; 23 | 24 | public static final String KEY_UPLOAD_DELAYED = "key_upload_delayed"; 25 | public static final String KEY_WEBSOCKET_URL = "key_websocket_url"; 26 | public static final String KEY_USERNAME = "key_username"; 27 | public static final String KEY_PASSWORD = "key_password"; 28 | public static final String KEY_REASON = "key_reason"; 29 | public static final String KEY_METEOR_LOGIN_RESULT = "key_meteor_login_result"; 30 | public static final String KEY_METEOR_STATE = "key_meteor_state"; 31 | 32 | public static final String ACTION_DATA_CHANGE = "action_data_change"; 33 | public static final String ACTION_METEOR_LOGIN_RESULT = "action_meteor_login_result"; 34 | public static final String ACTION_METEOR_STATE = "action_meteor_state"; 35 | 36 | public static final int METEOR_LOGIN_FAILED = 0; 37 | public static final int METEOR_LOGIN_OK = 1; 38 | 39 | public static int getUploadDelayed(Context context) { 40 | return PreferencesUtil.getInt(context, KEY_UPLOAD_DELAYED, UPLOAD_DELAYED); 41 | } 42 | 43 | public static void setUploadDelayed(Context context, int delayed) { 44 | PreferencesUtil.putInt(context, KEY_UPLOAD_DELAYED, delayed); 45 | } 46 | 47 | public static String getWebsocketUrl(Context context, String defUrl) { 48 | return PreferencesUtil.getString(context, KEY_WEBSOCKET_URL, defUrl); 49 | } 50 | 51 | public static void setWebsocketUrl(Context context, String url) { 52 | PreferencesUtil.putString(context, KEY_WEBSOCKET_URL, url); 53 | } 54 | 55 | public static String getUsername(Context context) { 56 | return PreferencesUtil.getString(context, KEY_USERNAME, null); 57 | } 58 | 59 | public static void setUsername(Context context, String username) { 60 | PreferencesUtil.putString(context, KEY_USERNAME, username); 61 | } 62 | 63 | public static String getPasword(Context context) { 64 | return PreferencesUtil.getString(context, KEY_PASSWORD, null); 65 | } 66 | 67 | public static void setPasswrod(Context context, String password) { 68 | PreferencesUtil.putString(context, KEY_PASSWORD, password); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /phone/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/util/LogUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | * 17 | */ 18 | package mobi.espier.lgc.util; 19 | 20 | import mobi.espier.lgc.BuildConfig; 21 | import android.util.Log; 22 | 23 | /** 24 | * API for sending log output. 25 | * 26 | * Generally, use the LogUtils.v() LogUtils.d() LogUtils.i() LogUtils.w() and LogUtils.e() methods. 27 | *

28 | * public static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE) || BuildConfig.DEBUG; 29 | *

30 | * By default(release), LogUtils.DEBUG is false, only print the log which priority > Log.INFO. If 31 | * you want to show all log. You can use the following command : adb shell setprop 32 | * log.tag.WxLiveLogUtils VERBOSE 33 | *

34 | * 35 | */ 36 | final public class LogUtils { 37 | private static final String TAG = "WxLiveLogUtils"; 38 | 39 | public static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE) || BuildConfig.DEBUG; 40 | 41 | public static int v(String tag, String msg) { 42 | return println(Log.VERBOSE, tag, msg); 43 | } 44 | 45 | public static int v(String tag, String msg, Throwable tr) { 46 | return println(Log.VERBOSE, tag, msg + '\n' + getStackTraceString(tr)); 47 | } 48 | 49 | public static int d(String tag, String msg) { 50 | return println(Log.DEBUG, tag, msg); 51 | } 52 | 53 | public static int d(String tag, String msg, Throwable tr) { 54 | return println(Log.DEBUG, tag, msg + '\n' + getStackTraceString(tr)); 55 | } 56 | 57 | public static int i(String tag, String msg) { 58 | return println(Log.INFO, tag, msg); 59 | } 60 | 61 | public static int i(String tag, String msg, Throwable tr) { 62 | return println(Log.INFO, tag, msg + '\n' + getStackTraceString(tr)); 63 | } 64 | 65 | public static int w(String tag, String msg) { 66 | return println(Log.WARN, tag, msg); 67 | } 68 | 69 | public static int w(String tag, String msg, Throwable tr) { 70 | return println(Log.WARN, tag, msg + '\n' + getStackTraceString(tr)); 71 | } 72 | 73 | public static int w(String tag, Throwable tr) { 74 | return println(Log.WARN, tag, getStackTraceString(tr)); 75 | } 76 | 77 | public static int e(String tag, String msg) { 78 | return println(Log.ERROR, tag, msg); 79 | } 80 | 81 | public static int e(String tag, String msg, Throwable tr) { 82 | return println(Log.ERROR, tag, msg + '\n' + getStackTraceString(tr)); 83 | } 84 | 85 | public static String getStackTraceString(Throwable tr) { 86 | return Log.getStackTraceString(tr); 87 | } 88 | 89 | public static int println(int priority, String tag, String msg) { 90 | if (priority > Log.INFO || DEBUG) { 91 | return Log.println(priority, tag, msg); 92 | } else { 93 | return 0; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/util/PreferencesUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under the terms of the 5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3 6 | * of the License, or (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | * Affero General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Affero General Public License along with this program. 13 | * If not, see . 14 | */ 15 | package mobi.espier.lgc.util; 16 | 17 | import android.content.Context; 18 | import android.content.SharedPreferences; 19 | import android.preference.PreferenceManager; 20 | 21 | public class PreferencesUtil { 22 | 23 | public static boolean getBoolean(Context context, String key, boolean def) { 24 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 25 | return sp.getBoolean(key, def); 26 | } 27 | 28 | public static void putBoolean(Context context, String key, boolean value) { 29 | SharedPreferences.Editor editPrefs = 30 | PreferenceManager.getDefaultSharedPreferences(context).edit(); 31 | editPrefs.putBoolean(key, value); 32 | editPrefs.commit(); 33 | } 34 | 35 | public static String getString(Context context, String key, String def) { 36 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 37 | return sp.getString(key, def); 38 | } 39 | 40 | public static void putString(Context context, String key, String value) { 41 | SharedPreferences.Editor editPrefs = 42 | PreferenceManager.getDefaultSharedPreferences(context).edit(); 43 | editPrefs.putString(key, value); 44 | editPrefs.commit(); 45 | } 46 | 47 | public static Long getLong(Context context, String key, Long def) { 48 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 49 | return sp.getLong(key, def); 50 | } 51 | 52 | public static void putLong(Context context, String key, Long value) { 53 | SharedPreferences.Editor editPrefs = 54 | PreferenceManager.getDefaultSharedPreferences(context).edit(); 55 | editPrefs.putLong(key, value); 56 | editPrefs.commit(); 57 | } 58 | 59 | public static int getInt(Context context, String key, int def) { 60 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 61 | return sp.getInt(key, def); 62 | } 63 | 64 | public static void putInt(Context context, String key, int value) { 65 | SharedPreferences.Editor editPrefs = 66 | PreferenceManager.getDefaultSharedPreferences(context).edit(); 67 | editPrefs.putInt(key, value); 68 | editPrefs.commit(); 69 | } 70 | 71 | public static float getFloat(Context context, String key, float def) { 72 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); 73 | return sp.getFloat(key, def); 74 | } 75 | 76 | public static void putFloat(Context context, String key, int value) { 77 | SharedPreferences.Editor editPrefs = 78 | PreferenceManager.getDefaultSharedPreferences(context).edit(); 79 | editPrefs.putFloat(key, value); 80 | editPrefs.commit(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /phone/src/mobi/espier/lgc/service/LgcAccessibilityService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio) 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Affero General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Affero General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Affero General Public License 15 | * along with this program. If not, see . 16 | * 17 | */ 18 | package mobi.espier.lgc.service; 19 | 20 | import mobi.espier.lgc.LgcApp; 21 | import mobi.espier.lgc.util.LogUtils; 22 | import android.accessibilityservice.AccessibilityService; 23 | import android.accessibilityservice.AccessibilityServiceInfo; 24 | import android.app.Notification; 25 | import android.content.Intent; 26 | import android.os.Build; 27 | import android.view.accessibility.AccessibilityEvent; 28 | 29 | public class LgcAccessibilityService extends AccessibilityService { 30 | private static final String TAG = "WxLiveAccessibilibyService"; 31 | 32 | private static boolean run = false; 33 | private static boolean enabled = true; 34 | 35 | public static boolean isRuning() { 36 | return run; 37 | } 38 | 39 | public static void setEnabled(boolean b) { 40 | enabled = b; 41 | } 42 | 43 | public LgcAccessibilityService() {} 44 | 45 | @Override 46 | public void onAccessibilityEvent(AccessibilityEvent event) { 47 | if (!enabled) { 48 | return; 49 | } 50 | if (AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED == event.getEventType()) { 51 | Notification notification = (Notification) event.getParcelableData(); 52 | if (notification != null) { 53 | LogUtils.d(TAG, "receive notification from " + event.getPackageName() 54 | + "|title is " + notification.tickerText); 55 | LgcApp.getInstance().onNotification(event.getPackageName(), notification, 56 | System.currentTimeMillis()); 57 | } 58 | } else if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) { 59 | // find in android sources event.getPackageName() will not be null, but crash collect 60 | // show it is may be null 61 | CharSequence package_name = event.getPackageName(); 62 | if (package_name != null) { 63 | LogUtils.d(TAG, "current package is : " + package_name); 64 | } 65 | } 66 | } 67 | 68 | @Override 69 | public void onInterrupt() { 70 | run = false; 71 | } 72 | 73 | @Override 74 | protected void onServiceConnected() { 75 | super.onServiceConnected(); 76 | run = true; 77 | if (Build.VERSION.SDK_INT < 14) { 78 | AccessibilityServiceInfo serverInfo = new AccessibilityServiceInfo(); 79 | serverInfo.eventTypes = 80 | AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED 81 | | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; 82 | serverInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_VISUAL; 83 | serverInfo.flags = AccessibilityServiceInfo.DEFAULT; 84 | serverInfo.notificationTimeout = 0L; 85 | setServiceInfo(serverInfo); 86 | } 87 | } 88 | 89 | @Override 90 | public void onDestroy() { 91 | run = false; 92 | super.onDestroy(); 93 | } 94 | 95 | @Override 96 | public void onRebind(Intent intent) { 97 | run = true; 98 | super.onRebind(intent); 99 | } 100 | 101 | @Override 102 | public boolean onUnbind(Intent intent) { 103 | run = false; 104 | return super.onUnbind(intent); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /phone/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 26 | 32 | 37 |