Advertisement
Guest User

anthony

a guest
Jul 3rd, 2010
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.37 KB | None | 0 0
  1. use Irssi;
  2. use Irssi::Irc;
  3. use strict;
  4. use vars qw($VERSION %IRSSI $DEBUG);
  5.  
  6. #
  7. # autobleh is an irssi helper script for IRC Channel OPs
  8. # and IRC Network Staff.
  9. #
  10. # Version:
  11. # $Id: autobleh.pl 17 2009-03-28 19:34:05Z sysdef $
  12. #
  13. # Contact:
  14. # email: sysdef@projectnet.org
  15. # project website: http://autobleh.projectnet.org/
  16. # support channel: irc://chat.freenode.net/#autobleh
  17. # repository: https://guest:guest@svn.projectnet.org/svn/autobleh/
  18. #
  19. # This script is licensed under GPL Version 3
  20. # License - http://www.gnu.org/licenses/gpl.html
  21. #
  22. # Please send all your thanks, money, donations, coffee, code, suggestions,
  23. # fixes and patches or hardware to the projects 'Main Contact' but please
  24. # write an email first.
  25. #
  26. # Sometimes it's possible to directly send gifts to the developer who needs
  27. # the part you want to give away so we can save additional shipment fees.
  28. #
  29. # Please also read the 'Need Help' page of the project first before you send
  30. # your coffee back to Columbia. (example)
  31. #
  32. # You will find your thanks and contributions in-kind listed on the project
  33. # website and details on how it was shared and helped our development or
  34. # developers.
  35. #
  36.  
  37. $VERSION = q$Rev: 17 $;
  38. %IRSSI = (
  39. authors => 'Juergen (sysdef) Heine, Tom (tomaw) Wesley. based on auto_bleh.pl by Don Armstrong',
  40. name => 'autobleh',
  41. description => 'Provides /ak /aq /ab /abr /abrn /arn /amb /amr /at /op /topicset /modeset /af',
  42. license => 'GPL3',
  43. changed => q$Id: autobleh.pl 17 2009-03-28 19:34:05Z sysdef $,
  44. );
  45.  
  46. # CHANGELOG
  47. # ????-??-?? - tomaw - add irssi setting bleh_deop_after_action
  48. # 2008-01-08 - sysdef - add irssi setting bleh_remove_message
  49. # 2008-01-08 - sysdef - add command op
  50. # 2008-01-08 - sysdef - add command topicset
  51. # 2008-01-08 - sysdef - add command modeset
  52. # 2008-01-22 - sysdef - solve the 'Unable to find nick: CHANSERV' error
  53. # 2008-01-22 - sysdef - add aliases /remove
  54. # 2008-01-25 - sysdef - add command af (auto forward / forward ban)
  55.  
  56. # read the config file
  57. open ( CONF, ".irssi/autobleh.conf" ) or Irssi::print("warning: '~/.irssi/autobleh.conf' doesn't exist.");
  58. Irssi::print("loading autobleh config ...");
  59. my $category;
  60. my $config;
  61. my $val;
  62. my $key;
  63. foreach my $line ( <CONF> ) {
  64. chomp $line;
  65. # filter empty lines
  66. if ( $line =~ /^\s*$/ ) {
  67. #Irssi::print("space : $line");
  68. }
  69. # new category
  70. elsif ( $line =~ /^\[/ ) {
  71. $line =~ /\[(.*)\]/;
  72. $category = $1;
  73. #Irssi::print("category : $line ($1)");
  74. }
  75. # filter comments
  76. elsif ( $line =~ /^#\s+/ ) {
  77. #Irssi::print("comment : $line");
  78. }
  79. # get key/value pair
  80. elsif ( $line =~ /^([^ ]+)\s*=\s*([^ ]+)$/ ) {
  81. Irssi::print("from config : $category $1 => $2");
  82. $config->{$category}{$1} = $2;
  83. }
  84. # crap line
  85. else {
  86. Irssi::print("config : $line");
  87. }
  88. }
  89. close CONF;
  90.  
  91. $DEBUG = 1;# unless defined $DEBUG;
  92.  
  93. my ($actions, %defaults);
  94.  
  95. %defaults = (
  96. GET_OP => 1, # Should we try to get opped when we bleh?
  97. USE_CHANSERV => 1, # Should we use chanserv to get opped?
  98. EXPIRE => 6000, # Do not try to do anything if the action is more than 6000 seconds old.
  99. TIMEOUT => 10, # Timeout /at bans after 10 minutes
  100. DEOP => 1, # We want to deop after action
  101. );
  102.  
  103. my %command_bindings = (
  104.  
  105. op => 'cmd_op',
  106.  
  107. ams => 'cmd_modeset',
  108. modeset => 'cmd_modeset',
  109.  
  110. ats => 'cmd_topicset',
  111. topicset => 'cmd_topicset',
  112.  
  113. af => 'cmd_af',
  114. forward => 'cmd_af',
  115.  
  116. ak => 'cmd_ak',
  117. kick => 'cmd_ak',
  118.  
  119. ab => 'cmd_ab',
  120. ban => 'cmd_ab',
  121.  
  122. aq => 'cmd_aq',
  123. quit => 'cmd_aq',
  124.  
  125. ar => 'cmd_ar',
  126. remove => 'cmd_ar',
  127.  
  128. abr => 'cmd_abr',
  129. removeban => 'cmd_abr',
  130.  
  131. abk => 'cmd_abk',
  132. kickban => 'cmd_abk',
  133.  
  134. abrn => 'cmd_abrn',
  135. removeban_notice => 'cmd_abrn',
  136.  
  137. abkn => 'cmd_abkn',
  138. kickban_notice => 'cmd_abkn',
  139.  
  140. arn => 'cmd_arn',
  141. remove_notice => 'cmd_arn',
  142.  
  143. amb => 'cmd_amb',
  144. massban => 'cmd_amb',
  145.  
  146. amr => 'cmd_amr',
  147. massremove => 'cmd_amr',
  148.  
  149. at => 'cmd_at',
  150. quiet_temp => 'cmd_at',
  151.  
  152. );
  153.  
  154. my %bans_to_remove;
  155.  
  156. sub cmd_op {
  157. my ($data, $server, $witem) = @_;
  158. # return get_op($data,$server,$witem);
  159. return do_bleh('op',$data,$server,$witem);
  160. }
  161.  
  162. sub cmd_modeset {
  163. my ($data, $server, $witem) = @_;
  164. return do_bleh('modeset',$data,$server,$witem);
  165. }
  166.  
  167. sub cmd_topicset {
  168. my ($data, $server, $witem) = @_;
  169. return do_bleh('topicset',$data,$server,$witem);
  170. }
  171.  
  172. sub cmd_at {
  173. my ($data, $server, $witem) = @_;
  174. return do_bleh('timeout',$data,$server,$witem);
  175. }
  176.  
  177. sub cmd_ak {
  178. my ($data, $server, $witem) = @_;
  179. return do_bleh('kick',$data,$server,$witem);
  180. }
  181.  
  182. sub cmd_af {
  183. my ($data, $server, $witem) = @_;
  184.  
  185. if ( defined $config->{forwardban}{$witem->{name}} ) {
  186. # channel -> $config->{forwardban}{$witem->{name}}
  187. my $targetchannel = $witem;
  188. my $channel = $server->channel_find($config->{forwardban}{$witem->{name}});
  189. if (!$channel) {
  190. Irssi::print("Error: i'm not in channel ".$config->{forwardban}{$witem->{name}}." right now.");
  191. return;
  192. }
  193. # TODO: Check if channel is +i and not +Q
  194. do_bleh('modeset',"+I ".$data,$server,$channel);
  195. return do_bleh('forward, kick',$data,$server,$witem);
  196. }
  197. else {
  198. Irssi::print("Error: forward channel for $witem->{name} was not set. Please edit section [forwardban] in ~/.irssi/autobleh.conf");
  199. }
  200. }
  201.  
  202. sub cmd_abk {
  203. my ($data, $server, $witem) = @_;
  204. return do_bleh('kick,ban',$data,$server,$witem);
  205. }
  206.  
  207. sub cmd_abkn {
  208. my ($data, $server, $witem) = @_;
  209. return do_bleh('kick,ban,notice',$data,$server,$witem);
  210. }
  211.  
  212. sub cmd_amb{
  213. my ($data, $server, $witem) = @_;
  214. my @nicks = split /\s+/, $data;
  215. for (@nicks) {
  216. next unless /\w/;
  217. do_bleh('ban',$_,$server,$witem);
  218. }
  219. }
  220.  
  221. sub cmd_ab {
  222. my ($data, $server, $witem) = @_;
  223. return do_bleh('ban',$data,$server,$witem);
  224. }
  225.  
  226. sub cmd_aq {
  227. my ($data, $server, $witem) = @_;
  228. return do_bleh('quiet',$data,$server,$witem);
  229. }
  230.  
  231. sub cmd_amr{
  232. my ($data, $server, $witem) = @_;
  233. my @nicks = split /\s+/, $data;
  234. for (@nicks) {
  235. next unless /\w/;
  236. do_bleh('remove',$_,$server,$witem);
  237. }
  238. }
  239.  
  240. sub cmd_ar {
  241. my ($data, $server, $witem) = @_;
  242. return do_bleh('remove',$data,$server,$witem);
  243. }
  244.  
  245. sub cmd_abr{
  246. my ($data, $server, $witem) =@_;
  247. return do_bleh('remove,ban',$data,$server,$witem);
  248. }
  249.  
  250. sub cmd_abrn{
  251. my ($data, $server, $witem) =@_;
  252. return do_bleh('remove,ban,notice',$data,$server,$witem);
  253. }
  254.  
  255. sub cmd_arn{
  256. my ($data, $server, $witem) =@_;
  257. return do_bleh('remove,notice',$data,$server,$witem);
  258. }
  259.  
  260. sub do_bleh {
  261. my ($cmd, $data, $server, $witem, $duration) = @_;
  262.  
  263. if (!$server || !$server->{connected}) {
  264. Irssi::print("Not connected to server");
  265. return;
  266. }
  267.  
  268. # fix the error: "Can't use string ("0") as a HASH ref while "strict refs" in use at..."
  269. if ( $witem eq 0 ) {
  270. Irssi::print("Can't autokick on a non-channel.");
  271. return;
  272. }
  273.  
  274. if ($witem->{type} ne 'CHANNEL') {
  275. Irssi::print("Can't autokick on a non-channel. [$witem->{type}]");
  276. return;
  277. }
  278.  
  279. # set the network that we're on, the channel and the nick to kick
  280. # once we've been opped
  281.  
  282. $data =~ /^\s*([^\s]+)\s*(\d+)?\s*(.+?|)\s*$/;
  283. my $nick = $1;
  284. my $timeout = $2;
  285. my $reason = $3;
  286. $timeout = $defaults{TIMEOUT} if not defined $timeout or $timeout eq '';
  287.  
  288. if ( $cmd =~ /^(topicset|modeset)$/ ) {
  289. $reason = $nick.' '.$reason;
  290. $nick = "CHANSERV";
  291. }
  292. else {
  293. $reason = Irssi::settings_get_str('bleh_remove_message') if not defined $reason or $reason eq '';
  294. }
  295.  
  296. my $nick_rec = $witem->nick_find($nick);
  297. if ( $nick ne 'CHANSERV' ) {
  298. if (not defined $nick_rec) {
  299. Irssi::print("Unable to find nick: $nick");
  300. return;
  301. }
  302. }
  303.  
  304. my $hostname = $nick_rec->{host} if defined $nick_rec;
  305. if ( $nick ne 'CHANSERV' ) {
  306. Irssi::print("Unable to find hostname for $nick") if not defined $hostname or $hostname eq '';
  307. }
  308. my $username = $hostname;
  309. $hostname =~ s/.+\@//;
  310. $username =~ s/@.*//;
  311. $username =~ s/.*=//;
  312.  
  313. Irssi::print("Nick set to '$nick' from '$data', reason set to '$reason'.") if $DEBUG;
  314.  
  315. my $action = {
  316. type => $cmd,
  317. nick => $nick,
  318. nick_rec => $nick_rec,
  319. network => $witem->{server}->{chatnet},
  320. server => $witem->{server},
  321. completed => 0,
  322. inserted => time,
  323. channel => $witem->{name},
  324. reason => $reason,
  325. hostname => $hostname,
  326. username => $username,
  327. timeout => $timeout,
  328. };
  329.  
  330. Irssi::print(i_want($action)) if $DEBUG;
  331.  
  332. if ($witem->{chanop}) {
  333. Irssi::print("DEBUG: take action $action") if $DEBUG;
  334. take_action($action,$server,$witem);
  335. }
  336. else {
  337. Irssi::print("DEBUG: try to get op in $action->{channel}") if $DEBUG;
  338. $actions->{$data.$action->{inserted}}=$action;
  339. get_op($server, $action->{channel}) if $defaults{GET_OP};
  340. }
  341.  
  342. }
  343.  
  344. sub get_op {
  345. my ($server,$channel) = @_;
  346.  
  347. Irssi::print("QUOTE CS op $channel") if $DEBUG;
  348. $server->command("QUOTE CS op $channel") if $defaults{USE_CHANSERV};
  349. }
  350.  
  351. sub i_want {
  352. my $action = shift;
  353. return "I've wanted to $action->{type} $action->{nick} in $action->{channel} on $action->{network} since $action->{inserted}";
  354. }
  355.  
  356. sub take_action {
  357. my ($action,$server,$channel) = @_;
  358.  
  359. local $_ = $action->{type};
  360. # Now support multiple actions against a single nick (to FE, kick ban, or remove ban). See /abr foo
  361.  
  362. if ( /op/ ) {
  363. Irssi::print( "Give OP only" ) if $DEBUG;
  364. %defaults->{DEOP} = 0;
  365. }
  366.  
  367. if ( /modeset/ ) {
  368. Irssi::print( "Setmode on $action->{channel}" ) if $DEBUG;
  369. # Set channel mode
  370. $channel->command( "/mode ". $action->{reason} );
  371. }
  372.  
  373. if ( /topicset/ ) {
  374. Irssi::print( "Settopic on $action->{channel}" ) if $DEBUG;
  375. # Set topic
  376. $channel->command( "/topic ". $action->{reason} );
  377. # we have to deop us here becaue we receive no modechange
  378. if ( Irssi::settings_get_bool('bleh_deop_after_action') ) {
  379. Irssi::print("MODE $channel->{name} -o $channel->{ownnick}->{nick}") if $DEBUG;
  380. $channel->command("/deop $channel->{ownnick}->{nick}");
  381. }
  382. }
  383.  
  384. if (/timeout/) {
  385. if ($action->{hostname} =~ /gateway\/web\/.+/) {
  386. Irssi::print("Quieting $action->{nick} on $action->{channel} with username $action->{username} for $action->{timeout} seconds") if $DEBUG;
  387. $channel->command("/quote MODE $action->{channel} +q *!*=".$action->{username}."@*") if $action->{username} ne ''; #quiet username
  388. }
  389. else {
  390. Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname} for $action->{timeout} seconds") if $DEBUG;
  391. $channel->command("/quote MODE $action->{channel} +q *!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
  392. }
  393. $bans_to_remove{"$action->{nick}$action->{inserted}"} = $action;
  394. # don't deop on a short time
  395. if ( $action->{timeout} < Irssi::settings_get_str('bleh_at_stay_opped') ) {
  396. Irssi::print("I'll stay opped until unquiet because $action->{timeout} < ".Irssi::settings_get_str('bleh_at_stay_opped')) if $DEBUG;
  397. %defaults->{DEOP} = 0;
  398. }
  399. else {
  400. Irssi::print("I'll NOT stay opped until unquiet because $action->{timeout} < ".Irssi::settings_get_str('bleh_at_stay_opped')) if $DEBUG;
  401. }
  402. }
  403.  
  404. if (/quiet/) {
  405. if ($action->{hostname} =~ /gateway\/web\/.+/) {
  406. Irssi::print("Quieting $action->{nick} on $action->{channel} with username $action->{username}") if $DEBUG;
  407. # Find hostname
  408. $channel->command("/quote MODE $action->{channel} +q *!*=".$action->{username}."@*") if $action->{username} ne ''; #quiet hostname
  409. }
  410. else {
  411. Irssi::print("Quieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
  412. # Find hostname
  413. $channel->command("/quote MODE $action->{channel} +q *!*@".$action->{hostname}) if $action->{hostname} ne ''; #quiet hostname
  414. }
  415. }
  416.  
  417. if (/ban/) {
  418. if ($action->{hostname} =~ /gateway\/web\/.+/) {
  419. Irssi::print("Banning $action->{nick} from $action->{channel} with username $action->{username}") if $DEBUG;
  420. $channel->command("/quote MODE $action->{channel} +b *!*=".$action->{username}."@*") if $action->{username} ne ''; # ban username
  421. }
  422. else {
  423. Irssi::print("Banning $action->{nick} from $action->{channel} with hostname $action->{hostname}") if $DEBUG;
  424. $channel->command("/quote MODE $action->{channel} +b *!*@".$action->{hostname}) if $action->{hostname} ne ''; # ban hostname
  425. }
  426. }
  427.  
  428. if (/set_invite/) {
  429. Irssi::print("Set +I for $action->{nick} in $action->{channel} with hostname $action->{hostname}") if $DEBUG;
  430. $channel->command("/quote MODE $action->{channel} +I $action->{nick}!*@".$action->{hostname})
  431. if $action->{hostname} ne '';
  432. }
  433.  
  434. if (/forward/) {
  435. if ( defined $config->{forwardban}{$action->{channel}} ) {
  436. my $fwchan = $config->{forwardban}{$action->{channel}};
  437. Irssi::print("Forward ".$action->{nick}." from ".$action->{channel}." to $fwchan with hostname ".$action->{hostname}) if $DEBUG;
  438. # ban hostname
  439. $channel->command("/quote MODE $action->{channel} +b $action->{nick}!*@".$action->{hostname}.'!'.${fwchan}) if $action->{hostname} ne '';
  440. # # invite user to fwchan
  441. # Irssi::print("INVITE user to $fwchan") if $DEBUG;
  442. # $channel->command("/quote invite $action->{nick} $fwchan");
  443. # notice user
  444. $channel->command("/NOTICE $action->{nick} You got a FORWARD BAN from $action->{channel} to $fwchan. Please rejoin channel $action->{channel}");
  445. }
  446. else {
  447. Irssi::print("ATTENTION: add line \"".$action->{channel}." <targetchannel>\" to [forwardban] section in ./irssi/autobleh.conf");
  448. return;
  449. }
  450. }
  451.  
  452. if (/kick/) {
  453. Irssi::print("Kicking $action->{nick} from $action->{channel}") if $DEBUG;
  454. #wtf? -> if ($action->{reason} =~ /\s/) {
  455. $channel->command("/quote KICK $action->{channel} $action->{nick} :$action->{reason}");
  456. #}
  457. #else {
  458. # $channel->command("/quote REMOVE $action->{channel} $action->{nick} $action->{reason}");
  459. #}
  460. }
  461.  
  462. if (/remove/) {
  463. Irssi::print("Removing $action->{nick} from $action->{channel}") if $DEBUG;
  464. if ($action->{reason} =~ /\s/) {
  465. $channel->command("/quote REMOVE $action->{channel} $action->{nick} :$action->{reason}");
  466. } else {
  467. $channel->command("/quote REMOVE $action->{channel} $action->{nick} $action->{reason}");
  468. }
  469. }
  470.  
  471. if (/notice/) {
  472. Irssi::print("Noticing $action->{nick} with $action->{reason}") if $DEBUG;
  473. $channel->command("/NOTICE $action->{nick} $action->{reason}");
  474. }
  475.  
  476. if (/teiuq/) {
  477. if ($action->{hostname} =~ /gateway\/web\/.+/) {
  478. Irssi::print("Unquieting $action->{nick} on $action->{channel} with username $action->{username}") if $DEBUG;
  479. $channel->command("/quote MODE $action->{channel} -q *!*=".$action->{username}."@*");
  480. }
  481. else {
  482. Irssi::print("Unquieting $action->{nick} on $action->{channel} with hostname $action->{hostname}") if $DEBUG;
  483. $channel->command("/quote MODE $action->{channel} -q *!*@".$action->{hostname});
  484. }
  485. }
  486. return; #for now.
  487. }
  488.  
  489. sub deop_us {
  490. my ($rec) = @_;
  491. my $channel = $rec->{channel};
  492. my $server = $rec->{server};
  493.  
  494. Irssi::print("MODE $channel->{name} -o $channel->{ownnick}->{nick}") if $DEBUG;
  495. $channel->command("/deop $channel->{ownnick}->{nick}");
  496. }
  497.  
  498. sub sig_mode_change {
  499. my ($channel,$nick) = @_;
  500.  
  501. # Are there any actions to process?
  502. # See if we got opped.
  503. return if scalar(keys %$actions) eq 0;
  504.  
  505. my @deop_array;
  506. if ($channel->{server}->{nick} eq $nick->{nick} and $nick->{op}) {
  507. Irssi::print("We've been opped") if $DEBUG;
  508. foreach (keys %$actions) {
  509. # See if this action is too old
  510. if (time - $actions->{$_}->{inserted} > $defaults{EXPIRE}) {
  511. Irssi::print("Expiring action: \"".i_want($actions->{$_})."\" because of time") if $DEBUG;
  512. delete $actions->{$_};
  513. next;
  514. }
  515. Irssi::print(i_want($actions->{$_})) if $DEBUG;
  516. # Find the server to take action on
  517. my $server = $actions->{$_}->{server};
  518. Irssi::print("Unable to find server for chatnet: $actions->{$_}->{network}") and return if not defined $server;
  519. Irssi::print("Found server for chatnet: $actions->{$_}->{network}") if $DEBUG;
  520. # Find the channel to take action on
  521. my $channel = $server->channel_find($actions->{$_}->{channel});
  522. Irssi::print("Unable to find channel for channel: $actions->{$_}->{channel}") and return if not defined $channel;
  523. Irssi::print("Found channel for channel: $actions->{$_}->{channel}") if $DEBUG;
  524. Irssi::print("We are opped on the channel!") if $DEBUG;
  525. take_action($actions->{$_},$server,$channel);
  526. if ( Irssi::settings_get_bool('bleh_deop_after_action') and %defaults->{DEOP} eq 1 ) {
  527. push @deop_array,{server=>$server,channel=>$channel};
  528. }
  529. %defaults->{DEOP} = 1;
  530. delete $actions->{$_}; # Do not repeat this action.
  531. }
  532. foreach (@deop_array) {
  533. deop_us($_);
  534. }
  535. } else {
  536. Irssi::print("Fooey. Not opped.") if $DEBUG;
  537. }
  538. }
  539.  
  540. sub try_to_remove_bans {
  541. return unless keys %bans_to_remove;
  542. for my $key (keys %bans_to_remove) {
  543. if (($bans_to_remove{$key}{inserted} + $bans_to_remove{$key}{timeout}) < time) {
  544. $bans_to_remove{$key}{type} = 'teiuq'; #unquiet
  545. $actions->{$key} = $bans_to_remove{$key};
  546. delete $bans_to_remove{$key};
  547. # TODO: only try to get op if we're not opped
  548. # if ($witem->{chanop}) {
  549. # Irssi::print("DEBUG: take action $action") if $DEBUG;
  550. # take_action($action,$server,$witem);
  551. # }
  552. # else {
  553. # Irssi::print("DEBUG: try to get op in $action->{channel}") if $DEBUG;
  554. # $actions->{$data.$action->{inserted}}=$action;
  555. # get_op($server, $action->{channel}) if $defaults{GET_OP};
  556. # }
  557. get_op($actions->{$key}{server}, $actions->{$key}{channel}) if $defaults{GET_OP};
  558. }
  559. }
  560. }
  561.  
  562. # call the try to remove bans function every minute
  563. Irssi::timeout_add(1000*5,'try_to_remove_bans',undef);
  564. Irssi::signal_add_last('nick mode changed','sig_mode_change');
  565. my ($command,$function);
  566.  
  567. while (($command,$function) = each %command_bindings) {
  568. Irssi::command_bind($command,$function, 'bleh');
  569. }
  570.  
  571. Irssi::settings_add_bool($IRSSI{name}, 'bleh_deop_after_action', 1);
  572. Irssi::settings_add_str($IRSSI{name}, 'bleh_remove_message', 'you should know better');
  573. Irssi::settings_add_str($IRSSI{name}, 'bleh_at_stay_opped', 10);
  574.  
  575. # find text for antispam
  576. #Irssi::signal_add_last( "message public", "msg_public" );
  577.  
  578. 1;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement