Guest User

Untitled

a guest
Jun 24th, 2015
335
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 22.50 KB | None | 0 0
  1. use Win32::GUI();
  2. use Win32::GUI::Constants qw(WS_BORDER MB_OK MB_ICONERROR MB_ICONINFORMATION MB_ICONWARNING ILC_MASK ILC_COLOR24 MB_YESNO MB_ICONQUESTION IDYES ES_READONLY);
  3. use Cwd;
  4. use DBI;
  5. use NET::XMPP;
  6. #use NET::XMPP::Namespaces qw(add_ns);
  7. use threads;
  8. use Text::Iconv;
  9. #use AnyEvent;
  10. use Encode qw(decode encode);
  11. use Win32::Sound;
  12. use MIME::Base64 qw(encode_base64 decode_base64);
  13.  
  14. use warnings;
  15. use strict;
  16.  
  17.  
  18. #####################
  19. #use feature 'say';
  20. #use Data::Dumper;
  21. #use Lingua::DetectCharset;
  22. #$| = 1;
  23. ######################
  24.  
  25.  
  26. my $VERSION = '1.0.0.1';
  27.  
  28. use constant {
  29.     PROG_NAME => 'BILCO',
  30.     CHECK_MESSAGES_INTERVAL => 3000,
  31.     MAX_TRANSFER_FILE_SIZE => 10 * 1024 * 1024,
  32.     MAX_TRANSFER_FILE_SIZE_STRING => '10 Мб'
  33. };
  34.  
  35.  
  36. sub db_connect();
  37. sub show_error($;$);
  38. sub wnd_terminate();
  39. sub xmpp_connect();
  40. sub xmpp_disconnect_callback();
  41. sub first_run();
  42. sub get_option($);
  43.  
  44.  
  45.  
  46. my $dir = cwd . '\\';
  47. my $utf8_to_cp1251 = Text::Iconv->new("utf-8", "cp1251");
  48. my $cp1251_to_utf8 = Text::Iconv->new("cp1251", "utf-8");
  49. my $query_id = 0;
  50.  
  51.  
  52. my %icons;
  53. $icons{prog} = new Win32::GUI::Icon($dir . 'icons\\prog.ico');
  54. #$icons{online} = new Win32::GUI::Icon($dir . 'icons\\online.ico');
  55. #$icons{offline} = new Win32::GUI::Icon($dir . 'icons\\offline.ico');
  56. $icons{connected} = new Win32::GUI::Icon($dir . 'icons\\connected.ico');
  57. $icons{connecting} = new Win32::GUI::Icon($dir . 'icons\\connecting.ico');
  58. $icons{disconnected} = new Win32::GUI::Icon($dir . 'icons\\disconnected.ico');
  59. $icons{offline} = new Win32::GUI::Icon($dir . 'icons\\offline.ico');
  60. $icons{online} = new Win32::GUI::Icon($dir . 'icons\\online.ico');
  61. $icons{emoticon_grin} = new Win32::GUI::Icon($dir . 'icons\\emoticons\grin.ico');
  62. $icons{emoticon_smile} = new Win32::GUI::Icon($dir . 'icons\\emoticons\smile.ico');
  63. $icons{emoticon_surprised} = new Win32::GUI::Icon($dir . 'icons\\emoticons\surprised.ico');
  64. $icons{emoticon_unhappy} = new Win32::GUI::Icon($dir . 'icons\\emoticons\unhappy.ico');
  65. $icons{upload} = new Win32::GUI::Icon($dir . 'icons\\upload.ico');
  66.  
  67.  
  68. my $status_imagelist = new Win32::GUI::ImageList(16, 16, ILC_MASK | ILC_COLOR24, 5, 5);
  69. $status_imagelist->AddIcon($icons{offline});
  70. $status_imagelist->AddIcon($icons{online});
  71.  
  72. my @users_info;
  73.  
  74. #my $cv = AnyEvent->condvar();
  75. my ($timer, $first_run_wnd);
  76.  
  77.  
  78. #####  Создание главного окна программы   #####
  79. my $menu =  Win32::GUI::MakeMenu(
  80.    'Меню' => 0,
  81.     ' > Настройки'  => {
  82.         -onClick => \&show_settings_wnd,
  83.     },
  84.     ' > О программе'   => {
  85.         -onClick => sub { },
  86.     },
  87.     ' > Выход'   => {
  88.         -onClick => \&wnd_terminate
  89.     }
  90. );
  91.  
  92. my $wnd;
  93. my $accel = new Win32::GUI::AcceleratorTable(
  94.     #'Ctrl-Return' => sub {
  95.         #add_new_line() if ($wnd->GetFocus == $wnd->message->{-handle}); # Перевод строки в поле ввода сообщения по CtrlEnter
  96.     #},
  97.     'Return' => sub {
  98.         send_message() if ($wnd->GetFocus == $wnd->message->{-handle}); # Отправка по нажатию Enter
  99.     }
  100. );
  101.  
  102. $wnd = new Win32::GUI::Window(
  103.     -name => 'wnd',
  104.     -size => [600, 450],
  105.     -minsize => [600, 450],
  106.     -text => PROG_NAME,
  107.     -maximizebox => 1,
  108.     -minimizebox => 1,
  109.     -sizable => 1,
  110.     -resizable => 1,
  111.     -menu => $menu,
  112.     -onTerminate => \&wnd_terminate,
  113.     -onTimer => \&process,
  114.     -onResize => \&resize,
  115.     -accel => $accel
  116. );
  117.  
  118. $wnd->SetIcon($icons{prog});
  119.  
  120.  
  121. $wnd->AddListView(
  122.     -name => 'userlist',
  123.     -pos => [10, 10],
  124.     -width => 150,
  125.     #-sort => 1,
  126.     -vscroll => 1,
  127.     -popstyle => WS_BORDER,
  128.     -gridlines => 0,
  129.     -nocolumnheader => 1,
  130.     #-singlesel => 1,
  131.     -showselalways => 1,
  132.     -fullrowselect => 1,
  133.     #-oneclickactivate => 1,
  134.     #-subitemimages => 1
  135.     -imagelist => $status_imagelist,
  136.     -onClick => \&user_change_callback
  137. );
  138.  
  139. $wnd->userlist->InsertColumn(
  140.     -width => 100
  141. );
  142.  
  143. $wnd->userlist->InsertColumn(
  144.     -width => 40,
  145.     -align => 'center'
  146. );
  147.  
  148. $wnd->AddRichEdit(
  149.     -name => 'messages',
  150.     -pos => [180, 10],
  151.     #-popstyle => WS_BORDER,
  152.     -vscroll => 1,
  153.     -readonly => 1
  154.     #-pushstyle => ES_READONLY
  155. );
  156. $wnd->messages->AutoURLDetect(1);
  157. $wnd->messages->SetWrapMode(1);
  158.  
  159. $wnd->AddTextfield(
  160.     -name => 'message',
  161.     -left => 180,
  162.     -height => 80,
  163.     -popstyle => WS_BORDER,
  164.     -multiline => 1,
  165.     -vscroll => 1
  166. );
  167.  
  168. $wnd->AddButton(
  169.     -name => 'send_file_btn',
  170.     -size => [24, 24],
  171.     -icon => $icons{upload},
  172.     -onClick => \&send_file
  173. );
  174.  
  175. $wnd->AddButton(
  176.     -name => 'send_message_btn',
  177.     -text => 'Отправить',
  178.     -size => [100, 24],
  179.     -onClick => \&send_message
  180. );
  181.  
  182. $wnd->AddButton(
  183.     -name => 'emoticon_smile_btn',
  184.     -left => 180,
  185.     -size => [24, 24],
  186.     -icon => $icons{emoticon_smile},
  187.     -onClick => sub {insert_emoticon('smile');}
  188. );
  189.  
  190. $wnd->AddButton(
  191.     -name => 'emoticon_unhappy_btn',
  192.     -left => 214,
  193.     -size => [24, 24],
  194.     -icon => $icons{emoticon_unhappy},
  195.     -onClick => sub {insert_emoticon('unhappy');}
  196. );
  197.  
  198. $wnd->AddButton(
  199.     -name => 'emoticon_surprised_btn',
  200.     -left => 248,
  201.     -size => [24, 24],
  202.     -icon => $icons{emoticon_surprised},
  203.     -onClick => sub {insert_emoticon('surprised');}
  204. );
  205.  
  206. $wnd->AddButton(
  207.     -name => 'emoticon_grin_btn',
  208.     -left => 282,
  209.     -size => [24, 24],
  210.     -icon => $icons{emoticon_grin},
  211.     -onClick => sub {insert_emoticon('grin');}
  212. );
  213.  
  214. $wnd->AddStatusBar(
  215.     -name => 'statusbar'
  216. );
  217.  
  218. $wnd->statusbar->SetParts(120);
  219.  
  220. xmpp_disconnect_callback();
  221.  
  222. $wnd->Center;
  223. $wnd->Show;
  224.  
  225.  
  226.  
  227. #####  Создание окна настроек  #####
  228. my $settings_wnd = new Win32::GUI::DialogBox(
  229.     -name => 'settings_wnd',
  230.     -title => 'Настройки',
  231.     -size => [400, 300],
  232.     -parent => $wnd,
  233.     -hashelp => 0
  234. );
  235.  
  236. $settings_wnd->SetIcon($icons{prog});
  237.  
  238. $settings_wnd->AddGroupbox(
  239.     -name => 'acc_group',
  240.     -text => 'Аккаунт',
  241.     -pos => [10, 10],
  242.     -size => [$settings_wnd->ScaleWidth - 20, 90]
  243. );
  244.  
  245. $settings_wnd->AddTextfield(
  246.     -name => 'login',
  247.     -prompt => ['Логин:', 60],
  248.     -size => [150, 20],
  249.     -pos => [20, 30],
  250.     -popstyle => WS_BORDER,
  251.     -tabstop => 1
  252. );
  253.  
  254. $settings_wnd->AddTextfield(
  255.     -name => 'password',
  256.     -prompt => ['Пароль:', 60],
  257.     -size => [150, 20],
  258.     -pos => [20, 60],
  259.     -popstyle => WS_BORDER,
  260.     -tabstop => 1
  261. );
  262.  
  263. $settings_wnd->AddGroupbox(
  264.     -name => 'connect_group',
  265.     -text => 'Подключение',
  266.     -pos => [10, 120],
  267.     -size => [$settings_wnd->ScaleWidth - 20, 90]
  268. );
  269.  
  270. $settings_wnd->AddTextfield(
  271.     -name => 'server',
  272.     -prompt => ['Сервер:', 60],
  273.     -size => [150, 20],
  274.     -pos => [20, 140],
  275.     -popstyle => WS_BORDER,
  276.     -tabstop => 1
  277. );
  278.  
  279. $settings_wnd->AddTextfield(
  280.     -name => 'port',
  281.     -prompt => ['Порт:', 60],
  282.     -size => [50, 20],
  283.     -pos => [20, 170],
  284.     -popstyle => WS_BORDER,
  285.     -tabstop => 1
  286. );
  287.  
  288. $settings_wnd->AddButton(
  289.     -name => 'save_btn',
  290.     -text => 'Сохранить',
  291.     -pos => [$settings_wnd->ScaleWidth - 220, $settings_wnd->ScaleHeight - 34],
  292.     -size => [100, 24],
  293.     -ok => 1,
  294.     -onClick => \&save_settings,
  295.     -tabstop => 1
  296. );
  297.  
  298. $settings_wnd->AddButton(
  299.     -name => 'cancel_btn',
  300.     -text => 'Отмена',
  301.     -pos => [$settings_wnd->ScaleWidth - 110, $settings_wnd->ScaleHeight - 34],
  302.     -size => [100, 24],
  303.     -cancel => 1,
  304.     -onClick => sub {return -1;},
  305.     -tabstop => 1
  306. );
  307.  
  308. #$settings_wnd->Center;
  309. #$settings_wnd->Show;
  310.  
  311.  
  312. #####  Выполнение операций при запуске программы  #####
  313.  
  314. my $dbh;
  315. unless ($dbh = db_connect()) {
  316.     show_error("Ошибка подключения к БД:\n\n$DBI::errstr");
  317.     wnd_terminate();
  318. }
  319.  
  320. first_run() if get_option('first_run');
  321.  
  322. $dbh->do('DELETE FROM `messages` WHERE julianday("now") - julianday(`date`) > 7'); # Удаляем из истории старые сообщения
  323.  
  324. my $client = new Net::XMPP::Client(
  325.     #debuglevel => 1,
  326.     #debugfile => $dir . 'xmpp.log'
  327. );
  328. $client->SetCallBacks(
  329.     onauth => \&xmpp_connect_callback(),
  330.     ondisconnect => \&xmpp_disconnect_callback(),
  331.     message => \&recieve_message_callback,
  332.     presence => \&presence_callback,
  333.     iq => \&iq_callback
  334. );
  335. # Расширение для передачи файлов
  336. my %args = (
  337.     ns => "file-transfer",
  338.     tag => "file",
  339.     xpath => {
  340.         Filename => {
  341.             path => '@Filename'
  342.         },
  343.         Content => {
  344.             path => 'text()'
  345.         }
  346.     }
  347. );
  348. Net::XMPP::Namespaces::add_ns(%args);
  349. xmpp_connect();
  350.  
  351.  
  352. Win32::GUI::Dialog();
  353.  
  354. exit 0;
  355.  
  356.  
  357. sub wnd_terminate() {
  358.     if (Win32::GUI::MessageBox($wnd, 'Вы уверены, что хотите завершить работу?', 'Выход', MB_YESNO | MB_ICONQUESTION) == IDYES) {
  359.         db_disconnect();
  360.         xmpp_disconnect();
  361.         return -1;
  362.     } else {
  363.         return 0;
  364.     }
  365.  
  366. }
  367.  
  368. sub show_error($;$) {
  369.     my ($message, $w) = @_;
  370.     $w = $wnd unless defined $w;
  371.     Win32::GUI::MessageBox($w, $message, '', MB_OK | MB_ICONERROR);
  372. }
  373.  
  374. sub show_info($;$) {
  375.     my ($message, $w) = @_;
  376.     $w = $wnd unless defined $w;
  377.     Win32::GUI::MessageBox($w, $message, '', MB_OK | MB_ICONINFORMATION);
  378. }
  379. sub show_warning($;$) {
  380.     my ($message, $w) = @_;
  381.     $w = $wnd unless defined $w;
  382.     Win32::GUI::MessageBox($w, $message, '', MB_OK | MB_ICONWARNING);
  383. }
  384.  
  385. sub db_connect() {
  386.     my $dsn='dbi:SQLite:dbname=db.sqlite';
  387.     my %opts = (
  388.         PrintError => 1,
  389.         RaiseError => 1
  390.     );
  391.     return DBI->connect($dsn, '', '', \%opts);
  392. }
  393.  
  394. sub db_disconnect() {
  395.     $dbh->disconnect() if defined $dbh;
  396. }
  397.  
  398. sub xmpp_connect() {
  399.     #async {
  400.         $wnd->statusbar->SetIcon(0, $icons{connecting});
  401.         $wnd->statusbar->SetText(0, 'Подключение');
  402.  
  403.         #my $status = 0;
  404.         my $result = $client->Connect(
  405.             hostname => get_option('server'),
  406.             port => get_option('port'),
  407.             timeout => 7
  408.         );
  409.         if ($result) {
  410.             my @result = $client->AuthSend(
  411.                 username => get_option('login'),
  412.                 password => get_option('password'),
  413.                 resource => 'bilco'
  414.             );
  415.             if ($result[0] eq 'ok') {
  416.                 #$status = 1;
  417.             }
  418.         }
  419.  
  420.         #print "$!\n" unless $status;
  421.         #if ($status) {
  422.         my $status = $client->Connected();
  423.         if ($status) {
  424.             xmpp_connect_callback();
  425.         } else {
  426.             #xmpp_disconnect_callback();
  427.         }
  428.     #};
  429.  
  430.     return $status;
  431. }
  432.  
  433. sub xmpp_disconnect() {
  434.     #my $pres = Net::XMPP::Presence->new();
  435.     #$pres->SetType('unavailable');
  436.     #$client->Send($pres);
  437.     $client->Disconnect unless defined $client;
  438. }
  439.  
  440. sub xmpp_reconnect() {
  441.     xmpp_disconnect();
  442.     xmpp_connect();
  443. }
  444.  
  445. sub xmpp_connect_callback() {
  446.     if ($client->Connected) {
  447.         $wnd->statusbar->SetIcon(0, $icons{connected});
  448.         $wnd->statusbar->SetText(0, 'Подключён');
  449.         update_user_list();
  450.         my $pres = Net::XMPP::Presence->new();
  451.         $pres->SetType('available');
  452.         $client->Send($pres);
  453.         $wnd->send_message_btn->Enable;
  454.  
  455.  
  456.         #$cv->begin;
  457.         #while (1) {
  458.         #   if ($client->Connected) {
  459.         #       $client->Connect() unless defined $client->Process(1);
  460.         #   } else {
  461.         #       last unless $client->Connect();
  462.         #   }
  463.         #
  464.         #   sleep CHECK_MESSAGES_INTERVAL;
  465.         #}
  466.         #$cv->end;
  467.  
  468.         $timer = $wnd->AddTimer('timer', CHECK_MESSAGES_INTERVAL);
  469.  
  470.     }
  471. }
  472.  
  473. sub xmpp_disconnect_callback() {
  474.     $wnd->statusbar->SetIcon(0, $icons{disconnected});
  475.     $wnd->statusbar->SetText(0, 'Отключён');
  476.     $wnd->userlist->Clear;
  477.     #$wnd->messages->Clear;
  478.     $wnd->messages->Text('');
  479.     $wnd->userlist->Clear;
  480.     $wnd->send_message_btn->Disable;
  481.     $timer->Kill(1) if defined $timer;
  482. }
  483.  
  484.  
  485. sub show_settings_wnd() {
  486.     $settings_wnd->login->Text(get_option('login'));
  487.     $settings_wnd->password->Text(get_option('password'));
  488.     $settings_wnd->server->Text(get_option('server'));
  489.     $settings_wnd->port->Text(get_option('port'));
  490.  
  491.     $settings_wnd->Center($wnd);
  492.     $settings_wnd->Show;
  493.     $settings_wnd->DoModal;
  494.     #return 1;
  495. }
  496.  
  497. sub save_settings() {
  498.     update_option('login', $settings_wnd->login->Text);
  499.     update_option('password', $settings_wnd->password->Text);
  500.     update_option('server', $settings_wnd->server->Text);
  501.     update_option('port', $settings_wnd->port->Text);
  502.     xmpp_reconnect();
  503.     return -1;
  504. }
  505.  
  506. sub get_option($) {
  507.     my ($name) = @_;
  508.     my $sth = $dbh->prepare('SELECT `value` FROM `settings` WHERE `name` = ?');
  509.     $sth->bind_param(1, $name);
  510.     $sth->execute;
  511.     my ($val) = $sth->fetchrow;
  512.     return $val;
  513. }
  514.  
  515. sub update_option($$) {
  516.     my ($name, $value) = @_;
  517.     my $sth = $dbh->prepare('UPDATE `settings` SET `value` = ? WHERE `name` = ?');
  518.     $sth->bind_param(1, $value);
  519.     $sth->bind_param(2, $name);
  520.     $sth->execute;
  521. }
  522.  
  523. sub update_user_list() {
  524.     if ($client->Connected) {
  525.         # Обновновление список контактов
  526.         #$client->RosterRequest();
  527.         my %roster = $client->RosterGet();
  528.         #my $roster = $client->Roster();
  529.         #my $pres = Net::XMPP::Presence->new();
  530.         #my $type = $pres->GetType;
  531.         $wnd->userlist->DeleteAllItems;
  532.         @users_info = ();
  533.         my $server = get_option('server');
  534.         foreach my $jid (sort(keys %roster)) {
  535.             my $user_id = str_replace('@' . $server, '', $jid);
  536.             my $user_name;
  537.             if ($roster{$jid}{name}) {
  538.                 $user_name = $roster{$jid}{name};
  539.             } else {
  540.                 $user_name = $user_id;
  541.             }
  542.             #$wnd->userlist->Add($utf8_to_cp1251->convert($user_name));
  543.             my $unread_count = 0; # TODO читать сохранённое значение
  544.             $wnd->userlist->InsertItem(
  545.                 -image => 0,
  546.                 -text => [$utf8_to_cp1251->convert($user_name), $unread_count ? "($unread_count)" : '']
  547.             );
  548.             push(@users_info, {
  549.                 id => $user_id,
  550.                 name => $user_name,
  551.                 unread => $unread_count
  552.             });
  553.         }
  554.     } else {
  555.         $wnd->userlist->DeleteAllItems;
  556.     }
  557. }
  558.  
  559.  
  560. sub str_replace($$$) {
  561.     my ($search, $replace, $subject) = @_;
  562.     my $pos = index($subject, $search);
  563.     while($pos > -1) {
  564.         substr($subject, $pos, length($search), $replace);
  565.         $pos = index($subject, $search, $pos + length($replace));
  566.     }
  567.     return $subject;
  568. }
  569.  
  570. sub user_change_callback() {
  571.     clear_messages();
  572.     my ($idx) = $wnd->userlist->SelectedItems();
  573.     unless ($idx == -1) {
  574.         my $user_id = $users_info[$idx]{id};
  575.         my $user_name = $users_info[$idx]{name};
  576.  
  577.         my $sth = $dbh->prepare('SELECT * FROM `messages` WHERE `user_id` = ? ORDER BY `date` ASC');
  578.         $sth->bind_param(1, $user_id);
  579.         $sth->execute;
  580.         while (my $row = $sth->fetchrow_hashref) {
  581.             show_message(
  582.                 $row->{income} ? $user_name : get_option('login'), #TODO имя если есть
  583.                 $row->{income},
  584.                 $row->{date},
  585.                 $row->{text}
  586.             );
  587.         }
  588.         $wnd->userlist->SetItemText($idx, '', 1);
  589.         $users_info[$idx]{unread} = 0;
  590.     } else {
  591.         # ...
  592.     }
  593. }
  594.  
  595. sub show_message($$$$) {
  596.     my ($user_name, $income, $date, $text) = @_; #TODO можно имя выбранного пользователя брать
  597.     #$user_name = $utf8_to_cp1251->convert($user_name);
  598.     my $color = $income ? 0x0000D0 : 0xA40000;
  599.     my ($year, $mon, $day, $hour, $min, $sec) = $date =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/;
  600.     my (undef, undef, undef, $day2, $mon2, $year2) = localtime(time);
  601.     $mon2++;
  602.     $year2 += 1900;
  603.     if ($day == $day2 && $mon == $mon2 && $year == $year2) {
  604.         $date = sprintf('%02d:%02d:%02d', $hour, $min, $sec);
  605.     } else {
  606.         $date = sprintf('%02d.%02d.%04d %02d:%02d:%02d', $day, $mon, $year, $hour, $min, $sec);
  607.     }
  608.     #$text = $utf8_to_cp1251->convert($text);;
  609.  
  610.     $wnd->messages->SetCharFormat(
  611.         -color => $color
  612.     );
  613.     $wnd->messages->SetSel($wnd->messages->TextLength, $wnd->messages->TextLength);
  614.     $wnd->messages->ReplaceSel("[$date] <$user_name>: ");
  615.  
  616.     $wnd->messages->SetCharFormat(
  617.         -color => 0x000000
  618.     );
  619.     $wnd->messages->SetSel($wnd->messages->TextLength, $wnd->messages->TextLength);
  620.     $wnd->messages->ReplaceSel("$text\n");
  621.  
  622.     $wnd->messages->ScrollCaret;
  623.     #$wnd->messages->Redraw(1);
  624.  
  625.     ######################################
  626.     #say Lingua::DetectCharset::Detect ($text) . " - $text";
  627.     ######################################
  628. }
  629.  
  630. sub clear_messages() {
  631.     #$wnd->messages->Clear;
  632.     $wnd->messages->Text('');
  633. }
  634.  
  635. sub send_message() {
  636.     my ($idx) = $wnd->userlist->SelectedItems();
  637.     my $to = $users_info[$idx]{id} . '@' . get_option('server');
  638.     my $message = $wnd->message->Text();
  639.     $client->MessageSend(
  640.         to => $cp1251_to_utf8->convert($to),
  641.         type => 'chat',
  642.         body => $cp1251_to_utf8->convert($message)
  643.     );
  644.     $wnd->message->Text('');
  645.     #todo меняем на имя
  646.     my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
  647.     $mon++;
  648.     $year += 1900;
  649.     my $date = sprintf('%04d-%02d-%02d %02d:%02d:%02d', $year, $mon, $day, $hour, $min, $sec);
  650.     show_message(get_option('login'), 0, $date, $message); # TODO addmessge -> show_message
  651.     my $sth = $dbh->prepare('INSERT INTO `messages` (`user_id`, `income`, `date`, `text`) VALUES(?, 0, ?, ?)');
  652.     $sth->bind_param(1, $users_info[$idx]{id});
  653.     $sth->bind_param(2, $date);
  654.     $sth->bind_param(3, $message);
  655.     $sth->execute;
  656. }
  657.  
  658. sub recieve_message_callback() {
  659.     my ($mid, $message) = @_;
  660.  
  661.     my ($current_idx) = $wnd->userlist->SelectedItems;
  662.  
  663.     my $user_id = $utf8_to_cp1251->convert($message->GetFrom('jid')->GetUserID);
  664.     my $idx = get_user_idx_by_id($user_id);
  665.     my $user_name = $users_info[$idx]{name};
  666.     my $text = $utf8_to_cp1251->convert(decode('utf-8', $message->GetBody));
  667.     my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
  668.     $mon++;
  669.     $year += 1900;
  670.     my $date = sprintf('%04d-%02d-%02d %02d:%02d:%02d', $year, $mon, $day, $hour, $min, $sec);
  671.  
  672.     my $sth = $dbh->prepare('INSERT INTO `messages` (`user_id`, `income`, `date`, `text`) VALUES(?, 1, ?, ?)');
  673.     $sth->bind_param(1, $user_id);
  674.     $sth->bind_param(2, $date);
  675.     $sth->bind_param(3, $text);
  676.     $sth->execute;
  677.  
  678.     if ($current_idx eq $idx) {
  679.         #say Lingua::DetectCharset::Detect ($text) . " - $text";
  680.         show_message($user_name, 1, $date, $text); # TODO addmessge -> show_message
  681.     } else {
  682.         my $unread_count = ++$users_info[$idx]{unread};
  683.         $wnd->userlist->SetItemText($idx, "($unread_count)", 1);
  684.     }
  685.  
  686.     Win32::Sound::Stop;
  687.     Win32::Sound::Play($dir . 'notify.wav');
  688. }
  689.  
  690. sub process() {
  691.     #if ($client->Connected) {
  692.     #   $client->Connect() unless defined $client->Process(0);
  693.     #} else {
  694.     #   last unless $client->Connect();
  695.     #}
  696.     unless (defined $client->Process(0)) {
  697.         #unless ($client->Connected) {
  698.             $timer->Kill(1);
  699.             ##########
  700.             #print "Disconnected: " . $! . "\n";
  701.             #print "Disconnected: " . $! . "\n";
  702.             ###########
  703.             xmpp_disconnect_callback;
  704.         #}
  705.     }
  706. }
  707.  
  708. sub get_user_idx_by_id($) {
  709.     my ($user_id) = @_;
  710.     foreach (0 .. $wnd->userlist->Count) {
  711.         if ($users_info[$_]{id} eq $user_id) {
  712.             return $_;
  713.         }
  714.     }
  715.     return -1;
  716. }
  717.  
  718. sub presence_callback() {
  719.     my $pres = $_[1];
  720.     my $user_id = $pres->GetFrom("jid")->GetUserID;
  721.     my $type = $pres->GetType;
  722.     #print "$user_id  $type\n";
  723.     my $idx = get_user_idx_by_id($user_id);
  724.     unless ($idx == -1) {
  725.         $wnd->userlist->ChangeItem(-image => $type eq 'unavailable' ? 0 : 1);
  726.     }
  727.  
  728. }
  729.  
  730. sub insert_emoticon($) {
  731.     my ($emoticon) = @_;
  732.     $emoticon = ':-)' if $emoticon eq 'smile';
  733.     $emoticon = ':-(' if $emoticon eq 'unhappy';
  734.     $emoticon = ':-D' if $emoticon eq 'grin';
  735.     $emoticon = ':-o' if $emoticon eq 'surprised';
  736.     $wnd->message->ReplaceSel(" $emoticon ");
  737. }
  738.  
  739. sub resize() {
  740.     my $w = $wnd->ScaleWidth;
  741.     my $h = $wnd->ScaleHeight;
  742.     $wnd->userlist->Height($h - 50);
  743.     $wnd->messages->Resize($w - 190, $h - 180);
  744.     $wnd->message->Top($h - 150);
  745.     $wnd->message->Width($w - 190);
  746.     $wnd->send_message_btn->Move($w - 110, $h - 60);
  747.     $wnd->send_file_btn->Move($w - 150, $h - 60);
  748.     $wnd->emoticon_smile_btn->Top($h - 60);
  749.     $wnd->emoticon_unhappy_btn->Top($h - 60);
  750.     $wnd->emoticon_surprised_btn->Top($h - 60);
  751.     $wnd->emoticon_grin_btn->Top($h - 60);
  752.     $wnd->statusbar->Move(0, $h - $wnd->statusbar->Height());
  753.     $wnd->statusbar->Resize($w, $h);
  754. }
  755.  
  756. sub send_file() {
  757.     my $file_path = Win32::GUI::GetOpenFileName(
  758.         -title  => 'Выберите файл для отправки'
  759.     );
  760.     if ($file_path) {
  761.         my $file_size = -s $file_path;
  762.         if ($file_size > MAX_TRANSFER_FILE_SIZE) {
  763.             show_warning('Размер файла не должен превышать ' . MAX_TRANSFER_FILE_SIZE_STRING . '!');
  764.         } else {
  765.             my $iq = new Net::XMPP::IQ;
  766.             my $idx = $wnd->userlist->SelectedItems;
  767.             $iq->SetIQ(
  768.                 to => $users_info[$idx]{id} . '@' . get_option('server') . '/bilco',
  769.                 from => get_option('login') . '@' . get_option('server') . '/bilco',
  770.                 id => $query_id++,
  771.                 type => 'set'
  772.             );
  773.             my $query = $iq->NewChild('file-transfer');
  774.             my ($file_name) = $file_path =~ /([^\\]+)$/;
  775.             my $content;
  776.             open(my $fh, "< $file_path"); #TODO сообщения об ошибках
  777.             binmode($fh);
  778.             read($fh, $content, $file_size);
  779.             close($fh);
  780.  
  781.             $query->SetFilename($file_name);
  782.             $query->SetContent(encode_base64($content));
  783.  
  784.             $client->Send($iq);
  785.         }
  786.     }
  787. }
  788.  
  789. sub iq_callback() {
  790.     #use Data::Dumper;
  791.     #print "=========IQ=============\n";
  792.     #print Dumper(\@_) . "\n\n";
  793.     my ($id, $iq) = @_;
  794.  
  795.     my $query = $iq->GetQuery;
  796.     #print "recieved iq " . $iq->GetQueryXMLNS() . "\n";
  797.  
  798.     if ($iq->GetQueryXMLNS() eq 'file-transfer') {
  799.         if ($iq->DefinedError()) {
  800.             print "file transfer error: (" . $iq->GetErrorCode . ") " . $iq->GetError();
  801.         } else {
  802.             my $file_name = $query->GetFilename();
  803.             print "recieved file $file_name\n";
  804.  
  805.             # Doing something with file ...
  806.         }
  807.     }
  808. }
  809.  
  810. sub first_run() {
  811.     $first_run_wnd = new Win32::GUI::DialogBox(
  812.         -size => [220, 150],
  813.         #-size => [220, 210],
  814.         -parent => $wnd,
  815.         -hashelp => 0
  816.     );
  817.  
  818.     $first_run_wnd->AddTextfield(
  819.         -name => 'login',
  820.         -pos => [10, 10],
  821.         -size => [$first_run_wnd->ScaleWidth - 70, 20],
  822.         -prompt => ['Логин:', 50],
  823.         -popstyle => WS_BORDER
  824.     );
  825.  
  826.     $first_run_wnd->AddTextfield(
  827.         -name => 'password',
  828.         -pos => [10, 40],
  829.         -size => [$first_run_wnd->ScaleWidth - 70, 20],
  830.         -prompt => ['Пароль:', 50],
  831.         -popstyle => WS_BORDER
  832.     );
  833.  
  834.     $first_run_wnd->AddTextfield(
  835.         -name => 'fio',
  836.         -pos => [10, 70],
  837.         -size => [$first_run_wnd->ScaleWidth - 70, 20],
  838.         -prompt => ['ФИО:', 50],
  839.         -popstyle => WS_BORDER,
  840.         -visible => 0
  841.     );
  842.  
  843.     $first_run_wnd->AddTextfield(
  844.         -name => 'email',
  845.         -pos => [10, 100],
  846.         -size => [$first_run_wnd->ScaleWidth - 70, 20],
  847.         -prompt => ['Email:', 50],
  848.         -popstyle => WS_BORDER,
  849.         -visible => 0
  850.     );
  851.  
  852.     #$first_run_wnd->AddButton(
  853.     #   -name => 'sign_up_btn',
  854.     #   -text => 'Регистрация',
  855.     #   -pos => [$first_run_wnd->ScaleWidth / 2 - 50, 140],
  856.     #   -size => [100, 24]
  857.     #);
  858.  
  859.  
  860.     $first_run_wnd->AddButton(
  861.         -name => 'sign_in_btn',
  862.         -text => 'Войти',
  863.         -pos => [10, 80],
  864.         -size => [80, 24]
  865.     );
  866.  
  867.     $first_run_wnd->AddButton(
  868.         -name => 'sign_up_btn',
  869.         -text => 'Регистрация',
  870.         -pos => [$first_run_wnd->ScaleWidth - 110, 80],
  871.         -size => [100, 24],
  872.         -onClick => \&show_reg
  873.     );
  874.  
  875.     $first_run_wnd->Center;
  876.     $first_run_wnd->Show;
  877.  
  878.     Win32::GUI::Dialog;
  879. }
  880.  
  881. sub show_reg() {
  882.     $first_run_wnd->Height(210);
  883.     $first_run_wnd->fio_Prompt->Show;
  884.     $first_run_wnd->fio->Show;
  885.     $first_run_wnd->email_Prompt->Show;
  886.     $first_run_wnd->email->Show;
  887.     $first_run_wnd->sign_in_btn->Hide;
  888.     $first_run_wnd->sign_up_btn->Move($first_run_wnd->ScaleWidth / 2 - 50, 140);
  889. }
Advertisement
Add Comment
Please, Sign In to add comment