Advertisement
Guest User

Untitled

a guest
Mar 7th, 2018
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 75.12 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. Buddybot by odsum (https://github.com/odsum)
  4. Based off Tinybot by Nortxort (https://github.com/nortxort/tinybot-rtc)
  5. """
  6.  
  7. import logging
  8. import random
  9. import threading
  10. import time
  11.  
  12. import pinylib
  13.  
  14. from apis import youtube, other, locals_
  15. from page import privacy
  16. from util import tracklist, botdb
  17.  
  18. __version__ = '2.2.9.1'
  19.  
  20. log = logging.getLogger(__name__)
  21.  
  22.  
  23. class TinychatBot(pinylib.TinychatRTCClient):
  24.     privacy_ = None
  25.     timer_thread = None
  26.     playlist = tracklist.PlayList()
  27.     search_list = []
  28.     is_search_list_yt_playlist = False
  29.     joind_time = 0
  30.     joind_count = 0
  31.     bl_search_list = []
  32.     general = ["hey", "hi","yes","no","yo","sup","ya", "hello", "cheers","tokes"]
  33.     bad_nick = 0
  34.     autoban_time = 0
  35.     autoban_count = 0
  36.     ban_time = 0
  37.     lockdown = False
  38.     time_join = 0
  39.     dj_mode = 0
  40.  
  41.     djs = []
  42.     kick_pool = []
  43.     ban_pool = []
  44.     msgs = {}
  45.     tmp_announcement = None
  46.  
  47.     @property
  48.     def config_path(self):
  49.         """ Returns the path to the rooms configuration directory. """
  50.         return pinylib.CONFIG.CONFIG_PATH + self.room_name + '/'
  51.  
  52.     def db_setup(self):
  53.  
  54.         self.buddy_db = botdb.DataBase('users', self.config_path)
  55.         if not self.buddy_db.has_db_file():
  56.             self.buddy_db.create_db_path()
  57.             self.buddy_db.create_defaults()
  58.             self.console_write(pinylib.COLOR['green'], '[DB] Created for %s' % (self.room_name))
  59.  
  60.         self.buddy_db.load()
  61.         self.console_write(pinylib.COLOR['green'], '[DB] Loaded for %s' % (self.room_name))
  62.  
  63.     def on_joined(self, client_info):
  64.         """
  65.        Received when the client have joined the room successfully.
  66.  
  67.        :param client_info: This contains info about the client, such as user role and so on.
  68.        :type client_info: dict
  69.        """
  70.         log.info('client info: %s' % client_info)
  71.         self.client_id = client_info['handle']
  72.         self.is_client_mod = client_info['mod']
  73.         self.is_client_owner = client_info['owner']
  74.         client = self.users.add(client_info)
  75.         client.user_level = 2
  76.         self.console_write(pinylib.COLOR['white'], '[Bot] connected as %s:%s, joining room %s' % (client.nick, client.id, self.room_name))
  77.  
  78.         threading.Thread(target=self.options).start()
  79.  
  80.         self.db_setup()
  81.  
  82.         threading.Timer(30.0, self.worker_kicks).start()
  83.         threading.Timer(60.0, self.worker_bans).start()
  84.         threading.Timer(60.0, self.check_lockdown).start()
  85.  
  86.  
  87.     def on_join(self, join_info):
  88.         """
  89.        Received when a user joins the room.
  90.  
  91.        :param join_info: This contains user information such as role, account and so on.
  92.        :type join_info: dict
  93.        """
  94.  
  95.         self.time_join = time.time()
  96.  
  97.         log.info('user join info: %s' % join_info)
  98.         _user = self.users.add(join_info)
  99.  
  100.         if _user.nick in self.buddy_db.nick_bans:
  101.             if pinylib.CONFIG.B_USE_KICK_AS_AUTOBAN:
  102.                 if self.lockdown:
  103.                     self.process_kick(_user.id)
  104.                 else:
  105.                     self.send_kick_msg(_user.id)
  106.             else:
  107.                 if self.lockdown:
  108.                     self.process_ban(_user.id)
  109.                 else:
  110.                     self.send_ban_msg(_user.id)
  111.                 self.console_write(pinylib.COLOR['red'], '[Security] Banned: Nick %s' % _user.nick)
  112.  
  113.         threading.Thread(target=self.user_register, args=(_user,)).start()
  114.  
  115.     def on_nick(self, uid, nick):
  116.         """
  117.        Received when a user changes nick name.
  118.  
  119.        :param uid: The ID (handle) of the user.
  120.        :type uid: int
  121.        :param nick: The new nick name.
  122.        :type nick: str
  123.        """
  124.         _user = self.users.search(uid)
  125.         old_nick = _user.nick
  126.         _user.nick = nick
  127.  
  128.         if uid != self.client_id:
  129.             if _user.nick in self.buddy_db.nick_bans:
  130.                 if pinylib.CONFIG.B_USE_KICK_AS_AUTOBAN:
  131.                     if self.lockdown:
  132.                         self.process_kick(uid)
  133.                     else:
  134.                         self.send_kick_msg(uid)
  135.                 else:
  136.                     if self.lockdown:
  137.                         self.process_ban(uid)
  138.                     else:
  139.                         self.send_ban_msg(uid)
  140.  
  141.                 self.console_write(pinylib.COLOR['bright_cyan'], '[User] %s:%s Changed nick to: %s' %
  142.                                    (old_nick, uid, nick))
  143.  
  144.     def do_op_user(self, user_name):
  145.         """
  146.        Lets the room owner, a mod or a bot controller make another user a bot controller.
  147.  
  148.        :param user_name: The user to op.
  149.        :type user_name: str
  150.        """
  151.         if self.is_client_mod:
  152.             if len(user_name) is 0:
  153.                 self.send_private_msg(self.active_user.id, 'Missing username.')
  154.             else:
  155.                 _user = self.users.search_by_nick(user_name)
  156.                 if _user is not None:
  157.                     _user.user_level = 4
  158.                     self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  159.  
  160.     def do_deop_user(self, user_name):
  161.         """
  162.        Lets the room owner, a mod or a bot controller remove a user from being a bot controller.
  163.  
  164.        :param user_name: The user to deop.
  165.        :type user_name: str
  166.        """
  167.         if self.is_client_mod:
  168.             if len(user_name) is 0:
  169.                 self.send_private_msg(self.active_user.id, 'Missing username.')
  170.             else:
  171.                 _user = self.users.search_by_nick(user_name)
  172.  
  173.                 if _user is not None:
  174.  
  175.                     if _user.account is not None:
  176.                         _user.user_level = 6
  177.                     else:
  178.                         _user.user_level = 7
  179.                         self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  180.  
  181.     def do_clear(self):
  182.         """ Clears the chat box. """
  183.         self.send_chat_msg('\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
  184.                            '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n')
  185.  
  186.     def do_user_info(self, user_name):
  187.         """
  188.        Shows user object info for a given user name.
  189.        :param user_name: The user name of the user to show the info for.
  190.        :type user_name: str
  191.        """
  192.  
  193.         if self.is_client_mod:
  194.             if len(user_name) is 0:
  195.                 self.send_private_msg(self.active_user.id, 'Missing username.')
  196.             else:
  197.                 _user = self.users.search_by_nick(user_name)
  198.                 if _user is None:
  199.                     self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  200.                 else:
  201.                     if _user.account and _user.tinychat_id is None:
  202.                         user_info = pinylib.apis.tinychat.user_info(_user.account)
  203.                         if user_info is not None:
  204.                             _user.tinychat_id = user_info['tinychat_id']
  205.                             _user.last_login = user_info['last_active']
  206.                     online_time = (pinylib.time.time() - _user.join_time)
  207.  
  208.                     info = [
  209.                         'User Level: ' + str(_user.user_level),
  210.                         'Online Time: ' + self.format_time(online_time),
  211.                         'Last Message: ' + str(_user.last_msg)
  212.                     ]
  213.                     if _user.tinychat_id is not None:
  214.                         info.append('Account: ' + str(_user.account))
  215.                         info.append('Tinychat ID: ' + str(_user.tinychat_id))
  216.                         info.append('Last Login: ' + _user.last_login)
  217.  
  218.                     self.send_private_msg(self.active_user.id, '\n'.join(info))
  219.  
  220.     # == Bot Police ==
  221.  
  222.     def do_kick(self, user_name):
  223.         """
  224.        Kick a user out of the room.
  225.  
  226.        :param user_name: The username to kick.
  227.        :type user_name: str
  228.        """
  229.         if self.is_client_mod:
  230.             if len(user_name) is 0:
  231.                 self.send_private_msg(self.active_user.id, 'Missing username.')
  232.             elif user_name == self.nickname:
  233.                 self.send_private_msg(self.active_user.id, 'Action not allowed.')
  234.             else:
  235.                 if user_name.startswith('*'):
  236.                     user_name = user_name.replace('*', '')
  237.                     _users = self.users.search_containing(user_name)
  238.                     if len(_users) > 0:
  239.                         for i, user in enumerate(_users):
  240.                             if user.nick != self.nickname and user.user_level > self.active_user.user_level:
  241.                                 if i <= pinylib.CONFIG.B_MAX_MATCH_BANS - 1:
  242.                                     self.send_kick_msg(user.id)
  243.                 else:
  244.                     _user = self.users.search_by_nick(user_name)
  245.                     if _user is None:
  246.                         self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  247.                     elif _user.user_level < self.active_user.user_level:
  248.                         self.send_chat_msg(
  249.                             'imma let ya guys figure that out...')
  250.                     else:
  251.                         self.send_kick_msg(_user.id)
  252.  
  253.     def do_ban(self, user_name):
  254.         """
  255.        Ban a user from the room.
  256.  
  257.        :param user_name: The username to ban.
  258.        :type user_name: str
  259.        """
  260.         if self.is_client_mod:
  261.             if len(user_name) is 0:
  262.                 self.send_private_msg(self.active_user.id, 'Missing username.')
  263.             elif user_name == self.nickname:
  264.                 self.send_private_msg(self.active_user.id, 'Action not allowed.')
  265.             else:
  266.                 if user_name.startswith('*'):
  267.                     user_name = user_name.replace('*', '')
  268.                     _users = self.users.search_containing(user_name)
  269.                     if len(_users) > 0:
  270.                         for i, user in enumerate(_users):
  271.                             if user.nick != self.nickname and user.user_level > self.active_user.user_level:
  272.                                 if i <= pinylib.CONFIG.B_MAX_MATCH_BANS - 1:
  273.                                     self.send_ban_msg(user.id)
  274.                 else:
  275.                     _user = self.users.search_by_nick(user_name)
  276.                     if _user is None:
  277.                         self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  278.                     elif _user.user_level < self.active_user.user_level:
  279.                         self.send_chat_msg(
  280.                             'i dont wanna be a part of ya problems..')
  281.                     else:
  282.                         self.send_ban_msg(_user.id)
  283.  
  284.     def do_banlist_search(self, user_name):
  285.         """
  286.        Search the banlist for matches.
  287.        NOTE: This method/command was meant to be a private message command,
  288.        but it seems like the private messages is broken, so for now
  289.        it will be a room command.
  290.        :param user_name: The user name or partial username to search for.
  291.        :type user_name: str
  292.        """
  293.         if self.is_client_mod:
  294.             if len(user_name) == 0:
  295.                 self.send_private_msg(self.active_user.id, 'Missing user name to search for.')
  296.             else:
  297.                 self.bl_search_list = self.users.search_banlist_containing(user_name)
  298.                 if len(self.bl_search_list) == 0:
  299.                     self.send_private_msg(self.active_user.id, 'No banlist matches.')
  300.                 else:
  301.                     _ban_list_info = '\n'.join('(%s) %s:%s [%s]' % (i, user.nick, user.account, user.ban_id)
  302.                                                for i, user in enumerate(self.bl_search_list))
  303.                     # maybe user string_util.chunk_string here
  304.                     self.send_private_msg(self.active_user.id, _ban_list_info)
  305.  
  306.     def do_forgive(self, user_index):
  307.         """
  308.        Forgive a user from the ban list search.
  309.        NOTE: This method/command was meant to be a private message command,
  310.        but it seems like the private messages is broken, so for now
  311.        it will be a room command.
  312.        :param user_index: The index in the ban list search.
  313.        :type user_index: str | int
  314.        """
  315.         if self.is_client_mod:
  316.             try:
  317.                 user_index = int(user_index)
  318.             except ValueError:
  319.                 self.send_private_msg(self.active_user.id, 'Only numbers allowed (%s)' % user_index)
  320.             else:
  321.                 if len(self.bl_search_list) > 0:
  322.                     if user_index <= len(self.bl_search_list) - 1:
  323.                         self.send_unban_msg(self.bl_search_list[user_index].ban_id)
  324.                     else:
  325.                         if len(self.bl_search_list) > 1:
  326.                             self.send_private_msg(self.active_user.id, 'Please make a choice between 0-%s' % len(self.bl_search_list))
  327.                 else:
  328.                     self.send_private_msg(self.active_user.id, 'The ban search is empty.')
  329.  
  330.     def do_unban(self, user_name):
  331.         """
  332.        Un-ban the last banned user or a user by user name.
  333.        NOTE: experimental. In case the user name match more than one
  334.        user in the banlist, then the last banned user will be unbanned.
  335.        :param user_name: The exact user name to unban.
  336.        :type user_name: str
  337.        """
  338.         if self.is_client_mod:
  339.             if len(user_name.strip()) == 0:
  340.                 self.send_private_msg(self.active_user.id, 'Missing user name.')
  341.             elif user_name == '/':  # shortcut to the last banned user.
  342.                 last_banned_user = self.users.last_banned
  343.                 if last_banned_user is not None:
  344.                     self.send_unban_msg(last_banned_user.ban_id)
  345.                 else:
  346.                     self.send_private_msg(self.active_user.id, 'Failed to find the last banned user.')
  347.             else:
  348.                 banned_user = self.users.search_banlist_by_nick(user_name)
  349.                 if banned_user is not None:
  350.                     self.send_unban_msg(banned_user.ban_id)
  351.                 else:
  352.                     self.send_private_msg(self.active_user.id, 'No user named: %s in the banlist.' % user_name)
  353.  
  354.  
  355.     # == Tinychat Broadcasting ==
  356.  
  357.     def do_cam_approve(self, user_name):
  358.         """
  359.        Allow a user to broadcast in a green room enabled room.
  360.  
  361.        :param user_name:  The name of the user allowed to broadcast.
  362.        :type user_name: str
  363.        """
  364.         _user = self.users.search_by_nick(user_name)
  365.         if len(user_name) > 0:
  366.             if _user.is_waiting:
  367.                 self.send_cam_approve_msg(_user.id)
  368.                 _user.is_broadcasting = True
  369.         else:
  370.             self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  371.  
  372.     def do_close_broadcast(self, user_name):
  373.         """
  374.        Close a users broadcast.
  375.  
  376.        :param user_name: The name of the user to close.
  377.        :type user_name: str
  378.        """
  379.         if self.is_client_mod:
  380.             if len(user_name) == 0:
  381.                 self.send_private_msg(self.active_user.id, 'Mising user name.')
  382.             else:
  383.                 _user = self.users.search_by_nick(user_name)
  384.                 if _user is not None and _user.is_broadcasting:
  385.                     self.send_close_user_msg(_user.id)
  386.                 else:
  387.                     self.send_private_msg(self.active_user.id, 'No user named: %s' % user_name)
  388.  
  389.     def on_pending_moderation(self, pending):
  390.         _user = self.users.search(pending['handle'])
  391.         if _user is not None:
  392.             if _user.user_level < 5:
  393.                 self.send_cam_approve_msg(_user.id)
  394.             else:
  395.                 _user.is_waiting = True
  396.                 self.send_chat_msg('%s is waiting in the greenroom.' % _user.nick)
  397.  
  398.     # == Bot Cmd Handler ==
  399.  
  400.     def cmd_handler(self, msg):
  401.  
  402.         prefix = pinylib.CONFIG.B_PREFIX
  403.  
  404.         parts = msg.split(' ')
  405.         cmd = parts[0].lower().strip()
  406.         cmd_arg = ' '.join(parts[1:]).strip()
  407.  
  408.         _user = self.users.search_by_nick(self.active_user.nick)
  409.  
  410.         # == Moderator level ==
  411.  
  412.         if _user.user_level < 4:
  413.  
  414.             if cmd == prefix + 'chatmod':
  415.                 self.buddy_db.add_user(cmd_arg, 4)
  416.                 self.send_chat_msg(_user.id, '%s was added to Chat Mods.')
  417.  
  418.             elif cmd == prefix + 'rmchatmod':
  419.                 self.buddy_db.remove_user(cmd_arg)
  420.                 self.send_chat_msg(_user.id, '%s was removed from Chat Mods.')
  421.  
  422.             elif cmd == prefix + 'noguest':
  423.                 self.do_guests()
  424.  
  425.             elif cmd == prefix + 'greet':
  426.                 self.do_greet()
  427.  
  428.             elif cmd == prefix + 'lurkers':
  429.                 self.do_lurkers()
  430.  
  431.             if cmd == prefix + 'lockdown':
  432.                 self.do_lockdown(1)
  433.  
  434.             if self.is_client_owner:
  435.                 if cmd == prefix + 'lockup':
  436.                     self.do_lockdown(0)
  437.  
  438.             if cmd == prefix + 'announcement':
  439.                 self.do_announcement(cmd_arg)
  440.  
  441.         # == Administrator/Owner Level ==
  442.  
  443.         if _user.user_level == 2:
  444.  
  445.             if cmd == prefix + 'chatadmin':
  446.                 self.buddy_db.add_user(cmd_arg, 2)
  447.                 self.send_chat_msg(_user.id, '%s was removed from Chat Admins.')
  448.  
  449.             elif cmd == prefix + 'rmchatadmin':
  450.                 self.buddy_db.remove_user(cmd_arg)
  451.                 self.send_chat_msg(_user.id, '%s was removed from Chat Admins.')
  452.  
  453.             if self.is_client_owner:
  454.  
  455.                 if cmd == prefix + 'p2t':
  456.                     threading.Thread(target=self.do_push2talk).start()
  457.                 elif cmd == prefix == 'kb':
  458.                     self.do_kick_as_ban()
  459.                 elif cmd == prefix + 'reboot':
  460.                     self.do_reboot()
  461.                 elif cmd == prefix + 'dir':
  462.                     threading.Thread(target=self.do_directory).start()
  463.                 elif cmd == prefix + 'addmod':
  464.                     threading.Thread(target=self.do_make_mod, args=(cmd_arg,)).start()
  465.                 elif cmd == prefix + 'rmmod':
  466.                     threading.Thread(target=self.do_remove_mod, args=(cmd_arg,)).start()
  467.  
  468.         # == Moderator level users ==
  469.  
  470.         if _user.user_level < 5:
  471.  
  472.             if cmd == prefix + 'mod':
  473.                 self.do_op_user(cmd_arg)
  474.  
  475.             elif cmd == prefix + 'demod':
  476.                 self.do_deop_user(cmd_arg)
  477.  
  478.             elif cmd == prefix + 'who':
  479.                 self.do_user_info(cmd_arg)
  480.  
  481.             elif cmd == prefix + 'v':
  482.                 self.buddy_db.add_user(cmd_arg, 5)
  483.                 self.send_chat_msg(_user.id, '%s was added to verified accounts.')
  484.  
  485.             elif cmd == prefix + 'rmv':
  486.                 self.buddy_db.remove_user(cmd_arg)
  487.                 self.send_chat_msg(_user.id, '%s was removed from verified accounts.')
  488.  
  489.             elif cmd == prefix + 'clr':
  490.                 self.do_clear()
  491.  
  492.             elif cmd == prefix + 'sbl':
  493.                 self.do_banlist_search(cmd_arg)
  494.  
  495.             elif cmd == prefix + 'fg':
  496.                 self.do_forgive(cmd_arg)
  497.  
  498.             elif cmd == prefix + 'unb':
  499.                 self.do_unban(cmd_arg)
  500.  
  501.             elif cmd == prefix + 'kick':
  502.                 threading.Thread(target=self.do_kick,
  503.                                  args=(cmd_arg,)).start()
  504.  
  505.             elif cmd == prefix + 'ban':
  506.                 threading.Thread(target=self.do_ban,
  507.                                  args=(cmd_arg,)).start()
  508.  
  509.             elif cmd == prefix + 'cam':
  510.                 self.do_cam_approve(cmd_arg)
  511.  
  512.             elif cmd == prefix + 'close':
  513.                 self.do_close_broadcast(cmd_arg)
  514.  
  515.             elif cmd == prefix + 'badn':
  516.                 self.buddy_db.add_bad_nick(cmd_arg)
  517.                 self.send_chat_msg(_user.id, '%s was added to bad nicks')
  518.  
  519.             elif cmd == prefix + 'rmbadn':
  520.                 self.buddy_db.remove_bad_nick(cmd_arg)
  521.                 self.send_chat_msg(_user.id, '%s was removed from bad nicks.')
  522.  
  523.             elif cmd == prefix + 'banw':
  524.                 self.buddy_db.add_bad_word(cmd_arg)
  525.                 self.send_chat_msg(_user.id, '%s was added to banned words.')
  526.  
  527.             elif cmd == prefix + 'rmw':
  528.                 self.buddy_db.remove_bad_word(cmd_arg)
  529.                 self.send_chat_msg(_user.id, '%s was removed from banned words.')
  530.  
  531.             elif cmd == prefix + 'bada':
  532.                 self.buddy_db.add_bad_account(cmd_arg)
  533.                 self.send_chat_msg(_user.id, '%s was added to banned accounts.')
  534.  
  535.             elif cmd == prefix + 'rmbada':
  536.                 self.buddy_db.remove_bad_account(cmd_arg)
  537.                 self.send_chat_msg(_user.id, '%s was removed from banned accounts.')
  538.  
  539.             if cmd == prefix + 'dj':
  540.                 threading.Thread(target=self.do_dj,
  541.                                  args=(cmd_arg,)).start()
  542.             elif cmd == prefix + 'djmode':
  543.                 self.do_dj_mode()
  544.  
  545.         # == Known accounts only ==
  546.  
  547.         if _user.user_level < 6:
  548.  
  549.             canplay = 1
  550.  
  551.             if self.dj_mode:
  552.  
  553.                 canplay = 0
  554.  
  555.                 if _user.account in self.djs:
  556.                     canplay = 1
  557.  
  558.             if cmd == prefix + 'skip':
  559.                 if not canplay:
  560.                     self.do_djmsg()
  561.                 else:
  562.                     self.do_skip()
  563.  
  564.             elif cmd == prefix + 'media':
  565.                 self.do_media_info()
  566.  
  567.             elif cmd == prefix + 'yt':
  568.                 if not canplay:
  569.                     self.do_djmsg()
  570.                 else:
  571.                     threading.Thread(
  572.                         target=self.do_play_youtube, args=(cmd_arg,)).start()
  573.  
  574.             elif cmd == prefix + 'yts':
  575.                 if not canplay:
  576.                     self.do_djmsg()
  577.                 else:
  578.                     threading.Thread(
  579.                         target=self.do_youtube_search, args=(cmd_arg,)).start()
  580.  
  581.             elif cmd == prefix + 'del':
  582.                 if not canplay:
  583.                     self.do_djmsg()
  584.                 else:
  585.                     self.do_delete_playlist_item(cmd_arg)
  586.  
  587.             elif cmd == prefix + 'replay':
  588.                 if not canplay:
  589.                     self.do_djmsg()
  590.                 else:
  591.                     self.do_media_replay()
  592.  
  593.             elif cmd == prefix + 'play':
  594.                 if not canplay:
  595.                     self.do_djmsg()
  596.                 else:
  597.                     self.do_play_media()
  598.  
  599.             elif cmd == prefix + 'pause':
  600.                 if not canplay:
  601.                     self.do_djmsg()
  602.                 else:
  603.                     self.do_media_pause()
  604.  
  605.             elif cmd == prefix + 'seek':
  606.                 if not canplay:
  607.                     self.do_djmsg()
  608.                 else:
  609.                     self.do_seek_media(cmd_arg)
  610.  
  611.             elif cmd == prefix + 'stop':
  612.                 if not canplay:
  613.                     self.do_djmsg()
  614.                 else:
  615.                     self.do_close_media()
  616.  
  617.             elif cmd == prefix + 'reset':
  618.                 if not canplay:
  619.                     self.do_djmsg()
  620.                 else:
  621.                     self.do_clear_playlist()
  622.  
  623.             elif cmd == prefix + 'next':
  624.                 if not canplay:
  625.                     self.do_djmsg()
  626.                 else:
  627.                     self.do_next_tune_in_playlist()
  628.  
  629.             elif cmd == prefix + 'playlist':
  630.                 self.do_playlist_info()
  631.  
  632.             elif cmd == prefix + 'pyts':
  633.                 self.do_play_youtube_search(cmd_arg)
  634.  
  635.             elif cmd == prefix + 'pls':
  636.                 threading.Thread(
  637.                     target=self.do_youtube_playlist_search, args=(cmd_arg,)).start()
  638.  
  639.             elif cmd == prefix + 'plp':
  640.                 threading.Thread(
  641.                     target=self.do_play_youtube_playlist, args=(cmd_arg,)).start()
  642.  
  643.             elif cmd == prefix + 'ssl':
  644.                 self.do_show_search_list()
  645.  
  646.             elif cmd == prefix + 'whatsong':
  647.                 self.do_now_playing()
  648.  
  649.             if cmd == prefix + 'status':
  650.                 self.do_playlist_status()
  651.  
  652.             elif cmd == prefix + 'now':
  653.                 self.do_now_playing()
  654.  
  655.             elif cmd == prefix + 'whoplayed':
  656.                 self.do_who_plays()
  657.  
  658.         # == Any user can access ==
  659.         # == Tinychat API Cmds ==
  660.         if cmd == prefix + 'acspy':
  661.             threading.Thread(target=self.do_account_spy, args=(cmd_arg,)).start()
  662.  
  663.         elif cmd == prefix + 'help':
  664.             self.do_help()
  665.  
  666.         # == Other Cmds ==
  667.         if cmd == prefix + 'urb':
  668.             threading.Thread(target=self.do_search_urban_dictionary, args=(cmd_arg,)).start()
  669.  
  670.         elif cmd == prefix + 'wea':
  671.             threading.Thread(target=self.do_weather_search, args=(cmd_arg,)).start()
  672.  
  673.         elif cmd == prefix + 'ip':
  674.             threading.Thread(target=self.do_whois_ip, args=(cmd_arg,)).start()
  675.  
  676.         # == Fun APIs ==
  677.         elif cmd == prefix + 'cn':
  678.             threading.Thread(target=self.do_chuck_noris).start()
  679.  
  680.         elif cmd == prefix + '8ball':
  681.             self.do_8ball(cmd_arg)
  682.  
  683.         elif cmd == prefix + 'roll':
  684.             self.do_dice()
  685.  
  686.         elif cmd == prefix + 'flip':
  687.             self.do_flip_coin()
  688.  
  689.         self.console_write(pinylib.COLOR['green'], self.active_user.nick + ': ' + cmd + ' ' + cmd_arg)
  690.  
  691.     def message_handler(self, msg):
  692.         """
  693.        A basic handler for chat messages.
  694.  
  695.        Overrides message_handler in pinylib
  696.        to allow commands.
  697.  
  698.        :param msg: The chat message.
  699.        :type msg: str
  700.        """
  701.         prefix = pinylib.CONFIG.B_PREFIX
  702.  
  703.         if msg.startswith(prefix):
  704.             self.cmd_handler(msg)
  705.  
  706.         else:
  707.             if self.active_user.user_level > 4:
  708.                 threading.Thread(target=self.check_msg, args=(msg,)).start()
  709.  
  710.             self.console_write(pinylib.COLOR['white'], self.active_user.nick + ': ' + msg)
  711.             self.active_user.last_msg = msg
  712.  
  713.     def private_message_handler(self, private_msg):
  714.         """
  715.        Private message handler.
  716.  
  717.        Overrides private_message_handler in pinylib
  718.        to enable private commands.
  719.  
  720.        :param private_msg: The private message.
  721.        :type private_msg: str
  722.        """
  723.         prefix = pinylib.CONFIG.B_PREFIX
  724.  
  725.         if private_msg.startswith(prefix):
  726.             self.cmd_handler(private_msg)
  727.  
  728.         self.console_write(pinylib.COLOR['white'], '[PRIMSG] %s: %s' % (self.active_user.nick, private_msg))
  729.  
  730.     # Youtube (Nortxort)
  731.  
  732.     def do_play_youtube(self, search_str):
  733.         """
  734.        Plays a youtube video matching the search term.
  735.  
  736.        :param search_str: The search term.
  737.        :type search_str: str
  738.        """
  739.         log.info('user: %s:%s is searching youtube: %s' %
  740.                  (self.active_user.nick, self.active_user.id, search_str))
  741.         if self.is_client_mod:
  742.             if len(search_str) is 0:
  743.                 self.send_chat_msg('Please specify youtube title, id or link.')
  744.             else:
  745.                 _youtube = youtube.search(search_str)
  746.                 if _youtube is None:
  747.                     log.warning('youtube request returned: %s' % _youtube)
  748.                     self.send_chat_msg('Could not find video: ' + search_str)
  749.                 else:
  750.                     log.info('youtube found: %s' % _youtube)
  751.                     if self.playlist.has_active_track:
  752.                         track = self.playlist.add(
  753.                             self.active_user.nick, _youtube)
  754.                         self.send_chat_msg('(%s) %s %s' %
  755.                                            (self.playlist.last_index, track.title, self.format_time(track.time)))
  756.                     else:
  757.                         track = self.playlist.start(
  758.                             self.active_user.nick, _youtube)
  759.                         self.send_yut_play(track.id, track.time, track.title)
  760.                         self.timer(track.time)
  761.  
  762.     def do_playlist_status(self):
  763.         """ Shows the playlist queue. """
  764.         if self.is_client_mod:
  765.             if len(self.playlist.track_list) == 0:
  766.                 self.send_chat_msg('The playlist is empty.')
  767.             else:
  768.                 queue = self.playlist.queue
  769.                 if queue is not None:
  770.                     self.send_chat_msg('%s items in the playlist, %s still in queue.' %
  771.                                        (queue[0], queue[1]))
  772.  
  773.     def do_next_tune_in_playlist(self):
  774.         """ Shows the next track in the playlist. """
  775.         if self.is_client_mod:
  776.             if self.playlist.is_last_track is None:
  777.                 self.send_chat_msg('The playlist is empty.')
  778.             elif self.playlist.is_last_track:
  779.                 self.send_chat_msg('This is the last track.')
  780.             else:
  781.                 pos, next_track = self.playlist.next_track_info()
  782.                 if next_track is not None:
  783.                     self.send_chat_msg('(%s) %s %s' %
  784.                                        (pos, next_track.title, self.format_time(next_track.time)))
  785.  
  786.     def do_now_playing(self):
  787.         """ Shows what track is currently playing. """
  788.         if self.is_client_mod:
  789.             if self.playlist.has_active_track:
  790.                 track = self.playlist.track
  791.                 if len(self.playlist.track_list) > 0:
  792.                     self.send_private_msg(self.active_user.id,
  793.                                           '(%s) %s %s' % (self.playlist.current_index, track.title,
  794.                                                           self.format_time(track.time)))
  795.                 else:
  796.                     self.send_private_msg(self.active_user.id, '%s %s' %
  797.                                           (track.title, self.format_time(track.time)))
  798.             else:
  799.                 self.send_private_msg(
  800.                     self.active_user.nick, 'No track playing.')
  801.  
  802.     def do_who_plays(self):
  803.         """ Show who requested the currently playing track. """
  804.         if self.is_client_mod:
  805.             if self.playlist.has_active_track:
  806.                 track = self.playlist.track
  807.                 ago = self.format_time(
  808.                     int(pinylib.time.time() - track.rq_time))
  809.                 self.send_chat_msg(
  810.                     '%s requested this track %s ago.' % (track.owner, ago))
  811.             else:
  812.                 self.send_chat_msg('No track playing.')
  813.  
  814.     def do_media_replay(self):
  815.         """ Replay the currently playing track. """
  816.         if self.is_client_mod:
  817.             if self.playlist.track is not None:
  818.                 self.cancel_timer()
  819.                 track = self.playlist.replay()
  820.                 self.send_yut_play(track.id, track.time, track.title)
  821.                 self.timer(track.time)
  822.  
  823.     def do_play_media(self):
  824.         """ Play a track on pause . """
  825.         if self.is_client_mod:
  826.             if self.playlist.track is not None:
  827.                 if self.playlist.has_active_track:
  828.                     self.cancel_timer()
  829.                 if self.playlist.is_paused:
  830.                     self.playlist.play(self.playlist.elapsed)
  831.                     self.send_yut_play(self.playlist.track.id, self.playlist.track.time,
  832.                                        self.playlist.track.title, self.playlist.elapsed)  #
  833.                     self.timer(self.playlist.remaining)
  834.  
  835.     def do_media_pause(self):
  836.         """ Pause a track. """
  837.         if self.is_client_mod:
  838.             track = self.playlist.track
  839.             if track is not None:
  840.                 if self.playlist.has_active_track:
  841.                     self.cancel_timer()
  842.                 self.playlist.pause()
  843.                 self.send_yut_pause(track.id, track.time,
  844.                                     self.playlist.elapsed)
  845.  
  846.     def do_close_media(self):
  847.         """ Close a track playing. """
  848.         if self.is_client_mod:
  849.             if self.playlist.has_active_track:
  850.                 self.cancel_timer()
  851.                 self.playlist.stop()
  852.                 self.send_yut_stop(
  853.                     self.playlist.track.id, self.playlist.track.time, self.playlist.elapsed)
  854.  
  855.     def do_seek_media(self, time_point):
  856.         """
  857.        Time search a track.
  858.  
  859.        :param time_point: The time point in which to search to.
  860.        :type time_point: str
  861.        """
  862.         if self.is_client_mod:
  863.             if ('h' in time_point) or ('m' in time_point) or ('s' in time_point):
  864.                 offset = pinylib.string_util.convert_to_seconds(time_point)
  865.                 if offset == 0:
  866.                     self.send_chat_msg('Invalid seek time.')
  867.                 else:
  868.                     track = self.playlist.track
  869.                     if track is not None:
  870.                         if 0 < offset < track.time:
  871.                             if self.playlist.has_active_track:
  872.                                 self.cancel_timer()
  873.                             if self.playlist.is_paused:
  874.                                 self.playlist.pause(offset=offset)  #
  875.                                 self.send_yut_pause(
  876.                                     track.id, track.time, offset)
  877.                             else:
  878.                                 self.playlist.play(offset)
  879.                                 self.send_yut_play(
  880.                                     track.id, track.time, track.title, offset)
  881.                                 self.timer(self.playlist.remaining)
  882.  
  883.     def do_clear_playlist(self):
  884.         """ Clear the playlist for items."""
  885.         if self.is_client_mod:
  886.             if len(self.playlist.track_list) > 0:
  887.                 pl_length = str(len(self.playlist.track_list))
  888.                 self.playlist.clear()
  889.                 self.send_chat_msg(
  890.                     'Deleted %s items in the playlist.' % pl_length)
  891.             else:
  892.                 self.send_chat_msg('The playlist is empty, nothing to delete.')
  893.  
  894.     def do_playlist_info(self):  # TODO: this needs more work !
  895.         """ Shows the next tracks in the playlist. """
  896.         if self.is_client_mod:
  897.             if len(self.playlist.track_list) > 0:
  898.                 tracks = self.playlist.get_tracks()
  899.                 if len(tracks) > 0:
  900.                     # If i is 0 then mark that as the next track
  901.                     _ = '\n'.join('(%s) - %s %s' % (track[0], track[1].title, self.format_time(track[1].time))
  902.                                   for i, track in enumerate(tracks))
  903.                     self.send_chat_msg(_)
  904.  
  905.     def do_youtube_search(self, search_str):
  906.         """
  907.        Search youtube for a list of matching candidates.
  908.  
  909.        :param search_str: The search term to search for.
  910.        :type search_str: str
  911.        """
  912.         if self.is_client_mod:
  913.             if len(search_str) == 0:
  914.                 self.send_chat_msg('Missing search string.')
  915.             else:
  916.                 self.search_list = youtube.search_list(search_str, results=5)
  917.                 if len(self.search_list) > 0:
  918.                     self.is_search_list_yt_playlist = False
  919.                     _ = '\n'.join('(%s) %s %s' % (i, d['video_title'], self.format_time(d['video_time']))
  920.                                   for i, d in enumerate(self.search_list))  #
  921.                     self.send_chat_msg(_)
  922.                 else:
  923.                     self.send_chat_msg(
  924.                         'Could not find anything matching: %s' % search_str)
  925.  
  926.     def do_play_youtube_search(self, int_choice):
  927.         """
  928.        Play a track from a previous youtube search list.
  929.  
  930.        :param int_choice: The index of the track in the search.
  931.        :type int_choice: str | int
  932.        """
  933.         if self.is_client_mod:
  934.             if not self.is_search_list_yt_playlist:
  935.                 if len(self.search_list) > 0:
  936.                     try:
  937.                         int_choice = int(int_choice)
  938.                     except ValueError:
  939.                         self.send_chat_msg('Only numbers allowed.')
  940.                     else:
  941.                         if 0 <= int_choice <= len(self.search_list) - 1:
  942.  
  943.                             if self.playlist.has_active_track:
  944.                                 track = self.playlist.add(
  945.                                     self.active_user.nick, self.search_list[int_choice])
  946.                                 self.send_chat_msg('Added (%s) %s %s' %
  947.                                                    (self.playlist.last_index,
  948.                                                     track.title, self.format_time(track.time)))
  949.                             else:
  950.                                 track = self.playlist.start(
  951.                                     self.active_user.nick, self.search_list[int_choice])
  952.                                 self.send_yut_play(
  953.                                     track.id, track.time, track.title)
  954.                                 self.timer(track.time)
  955.                         else:
  956.                             self.send_chat_msg(
  957.                                 'Please make a choice between 0-%s' % str(len(self.search_list) - 1))
  958.                 else:
  959.                     self.send_chat_msg(
  960.                         'No youtube track id\'s in the search list.')
  961.             else:
  962.                 self.send_chat_msg(
  963.                     'The search list only contains youtube playlist id\'s.')
  964.  
  965.     def on_yut_play(self, yt_data):
  966.         """
  967.        Received when a youtube gets started or time searched.
  968.  
  969.        This also gets received when the client starts a youtube, the information is
  970.        however ignored in that case.
  971.  
  972.        :param yt_data: The event information contains info such as the ID (handle) of the user
  973.        starting/searching the youtube, the youtube ID, youtube time and so on.
  974.        :type yt_data: dict
  975.        """
  976.         user_nick = 'n/a'
  977.         if 'handle' in yt_data:
  978.             if yt_data['handle'] != self.client_id:
  979.                 _user = self.users.search(yt_data['handle'])
  980.                 user_nick = _user.nick
  981.  
  982.         if self.playlist.has_active_track:
  983.             self.cancel_timer()
  984.  
  985.         if yt_data['item']['offset'] == 0:
  986.             _youtube = youtube.video_details(yt_data['item']['id'], False)
  987.             self.playlist.start(user_nick, _youtube)
  988.             self.timer(self.playlist.track.time)
  989.             self.console_write(pinylib.COLOR['bright_magenta'], '[Media] %s started youtube video (%s)' %
  990.                                (user_nick, yt_data['item']['id']))
  991.         elif yt_data['item']['offset'] > 0:
  992.             if user_nick == 'n/a':
  993.                 _youtube = youtube.video_details(yt_data['item']['id'], False)
  994.                 self.playlist.start(user_nick, _youtube)
  995.                 offset = self.playlist.play(yt_data['item']['offset'])
  996.                 self.timer(offset)
  997.             else:
  998.                 offset = self.playlist.play(yt_data['item']['offset'])
  999.                 self.timer(offset)
  1000.                 self.console_write(pinylib.COLOR['bright_magenta'], '[Media] %s searched the youtube video to: %s' %
  1001.                                    (user_nick, int(round(yt_data['item']['offset']))))
  1002.  
  1003.     def on_yut_pause(self, yt_data):
  1004.         """
  1005.        Received when a youtube gets paused or searched while paused.
  1006.  
  1007.        This also gets received when the client pauses or searches while paused, the information is
  1008.        however ignored in that case.
  1009.  
  1010.        :param yt_data: The event information contains info such as the ID (handle) of the user
  1011.        pausing/searching the youtube, the youtube ID, youtube time and so on.
  1012.        :type yt_data: dict
  1013.        """
  1014.         if 'handle' in yt_data:
  1015.             if yt_data['handle'] != self.client_id:
  1016.                 _user = self.users.search(yt_data['handle'])
  1017.                 if self.playlist.has_active_track:
  1018.                     self.cancel_timer()
  1019.                 self.playlist.pause()
  1020.                 self.console_write(pinylib.COLOR['bright_magenta'], '[Media] %s paused the video at %s' %
  1021.                                    (_user.nick, int(round(yt_data['item']['offset']))))
  1022.  
  1023.     def do_youtube_playlist_search(self, search_str):
  1024.         """
  1025.        Search youtube for a playlist.
  1026.  
  1027.        :param search_str: The search term to search for.
  1028.        :type search_str: str
  1029.        """
  1030.         if self.is_client_mod:
  1031.             if len(search_str) == 0:
  1032.                 self.send_chat_msg('Missing search string.')
  1033.             else:
  1034.                 self.search_list = youtube.playlist_search(search_str)
  1035.                 if len(self.search_list) > 0:
  1036.                     self.is_search_list_yt_playlist = True
  1037.                     _ = '\n'.join('(%s) %s' % (
  1038.                         i, d['playlist_title']) for i, d in enumerate(self.search_list))
  1039.                     self.send_chat_msg(_)
  1040.                 else:
  1041.                     self.send_chat_msg(
  1042.                         'Failed to find playlist matching search term: %s' % search_str)
  1043.  
  1044.     def do_play_youtube_playlist(self, int_choice):
  1045.         """
  1046.        Play a previous searched playlist.
  1047.  
  1048.        :param int_choice: The index of the playlist.
  1049.        :type int_choice: str | int
  1050.        """
  1051.         if self.is_client_mod:
  1052.             if self.is_search_list_yt_playlist:
  1053.                 try:
  1054.                     int_choice = int(int_choice)
  1055.                 except ValueError:
  1056.                     self.send_chat_msg('Only numbers allowed.')
  1057.                 else:
  1058.                     if 0 <= int_choice <= len(self.search_list) - 1:
  1059.                         self.send_chat_msg(
  1060.                             'Please wait while creating playlist..')
  1061.                         tracks = youtube.playlist_videos(
  1062.                             self.search_list[int_choice])
  1063.                         if len(tracks) > 0:
  1064.                             self.playlist.add_list(
  1065.                                 self.active_user.nick, tracks)
  1066.                             self.send_chat_msg(
  1067.                                 '🎶 Added %s tracks from youtube playlist.' % len(tracks))
  1068.                             if not self.playlist.has_active_track:
  1069.                                 track = self.playlist.next_track
  1070.                                 self.send_yut_play(
  1071.                                     track.id, track.time, track.title)
  1072.                                 self.timer(track.time)
  1073.                         else:
  1074.                             self.send_chat_msg(
  1075.                                 'Failed to retrieve videos from youtube playlist.')
  1076.                     else:
  1077.                         self.send_chat_msg(
  1078.                             'Please make a choice between 0-%s' % str(len(self.search_list) - 1))
  1079.             else:
  1080.                 self.send_chat_msg(
  1081.                     'The search list does not contain any youtube playlist id\'s.')
  1082.  
  1083.     def do_show_search_list(self):
  1084.         """ Show what the search list contains. """
  1085.         if self.is_client_mod:
  1086.             if len(self.search_list) == 0:
  1087.                 self.send_chat_msg('The search list is empty.')
  1088.             elif self.is_search_list_yt_playlist:
  1089.                 _ = '\n'.join('(%s) - %s' % (i, d['playlist_title'])
  1090.                               for i, d in enumerate(self.search_list))
  1091.                 self.send_chat_msg('Youtube Playlist\'s\n' + _)
  1092.             else:
  1093.                 _ = '\n'.join('(%s) %s %s' % (i, d['video_title'], self.format_time(d['video_time']))
  1094.                               for i, d in enumerate(self.search_list))
  1095.                 self.send_chat_msg('🎶 Youtube Tracks\n' + _)
  1096.  
  1097.     def do_skip(self):
  1098.         """ Skip to the next item in the playlist. """
  1099.         if self.is_client_mod:
  1100.             if self.playlist.is_last_track is None:
  1101.                 self.send_chat_msg('No tunes to skip. The playlist is empty.')
  1102.             elif self.playlist.is_last_track:
  1103.                 self.send_chat_msg('This is the last track in the playlist.')
  1104.             else:
  1105.                 self.cancel_timer()
  1106.                 next_track = self.playlist.next_track
  1107.                 self.send_yut_play(
  1108.                     next_track.id, next_track.time, next_track.title)
  1109.                 self.timer(next_track.time)
  1110.  
  1111.     # TODO: Make sure this is working.
  1112.     def do_delete_playlist_item(self, to_delete):
  1113.         """
  1114.        Delete items from the playlist.
  1115.  
  1116.        :param to_delete: Item indexes to delete.
  1117.        :type to_delete: str
  1118.        """
  1119.         if self.is_client_mod:
  1120.             if len(self.playlist.track_list) == 0:
  1121.                 self.send_chat_msg('The playlist is empty.')
  1122.             elif len(to_delete) == 0:
  1123.                 self.send_chat_msg('No indexes provided.')
  1124.             else:
  1125.                 indexes = None
  1126.                 by_range = False
  1127.  
  1128.                 try:
  1129.                     if ':' in to_delete:
  1130.                         range_indexes = map(int, to_delete.split(':'))
  1131.                         temp_indexes = range(
  1132.                             range_indexes[0], range_indexes[1] + 1)
  1133.                         if len(temp_indexes) > 1:
  1134.                             by_range = True
  1135.                     else:
  1136.                         temp_indexes = map(int, to_delete.split(','))
  1137.                 except ValueError as ve:
  1138.                     log.error('wrong format: %s' % ve)
  1139.                 else:
  1140.                     indexes = []
  1141.                     for i in temp_indexes:
  1142.                         if i < len(self.playlist.track_list) and i not in indexes:
  1143.                             indexes.append(i)
  1144.  
  1145.                 if indexes is not None and len(indexes) > 0:
  1146.                     result = self.playlist.delete(indexes, by_range)
  1147.                     if result is not None:
  1148.                         if by_range:
  1149.                             self.send_chat_msg('Deleted from index: %s to index: %s' %
  1150.                                                (result['from'], result['to']))
  1151.                         elif result['deleted_indexes_len'] is 1:
  1152.                             self.send_chat_msg('Deleted %s' %
  1153.                                                result['track_title'])
  1154.                         else:
  1155.                             self.send_chat_msg('Deleted tracks at index: %s' %
  1156.                                                ', '.join(result['deleted_indexes']))
  1157.                     else:
  1158.  
  1159.                         self.send_chat_msg('Nothing was deleted.')
  1160.  
  1161.     def do_media_info(self):
  1162.         """ Show information about the currently playing youtube. """
  1163.         if self.is_client_mod and self.playlist.has_active_track:
  1164.             self.send_chat_msg(
  1165.                 'Playlist Tracks: ' + str(len(self.playlist.track_list)) + '\n' +
  1166.                 'Track Title: ' + self.playlist.track.title + '\n' +
  1167.                 'Track Index: ' + str(self.playlist.track_index) + '\n' +
  1168.                 'Elapsed Track Time: ' + self.format_time(self.playlist.elapsed) + '\n' +
  1169.                 'Remaining Track Time: ' +
  1170.                 self.format_time(self.playlist.remaining)
  1171.             )
  1172.  
  1173.     # == Tinychat Owner / Utils ==
  1174.  
  1175.     def do_make_mod(self, account):
  1176.         """
  1177.        Make a tinychat account a room moderator.
  1178.  
  1179.        :param account: The account to make a moderator.
  1180.        :type account: str
  1181.        """
  1182.         if self.is_client_owner:
  1183.             if len(account) is 0:
  1184.                 self.send_private_msg(self.active_user.id, 'Missing account name.')
  1185.             else:
  1186.                 tc_user = self.privacy_.make_moderator(account)
  1187.                 if tc_user is None:
  1188.                     self.send_private_msg(self.active_user.id, 'The account is invalid.')
  1189.                 elif not tc_user:
  1190.                     self.send_private_msg(self.active_user.id, '%s is already a moderator.' % account)
  1191.                 elif tc_user:
  1192.                     self.send_private_msg(self.active_user.id, '%s was made a room moderator.' % account)
  1193.  
  1194.     def do_remove_mod(self, account):
  1195.         """
  1196.        Removes a tinychat account from the moderator list.
  1197.  
  1198.        :param account: The account to remove from the moderator list.
  1199.        :type account: str
  1200.        """
  1201.         if self.is_client_owner:
  1202.             if len(account) is 0:
  1203.                 self.send_private_msg(self.active_user.id, 'Missing account name.')
  1204.             else:
  1205.                 tc_user = self.privacy_.remove_moderator(account)
  1206.                 if tc_user:
  1207.                     self.send_private_msg(self.active_user.id, '%s is no longer a room moderator.' % account)
  1208.                 elif not tc_user:
  1209.                     self.send_private_msg(self.active_user.id, '%s is not a room moderator.' % account)
  1210.  
  1211.     def do_directory(self):
  1212.         """ Toggles if the room should be shown on the directory. """
  1213.         if self.is_client_owner:
  1214.             if self.privacy_.show_on_directory():
  1215.                 self.send_private_msg(self.active_user.id, 'Room IS shown on the directory.')
  1216.             else:
  1217.                 self.send_private_msg(self.active_user.id, 'Room is NOT shown on the directory.')
  1218.  
  1219.     def do_push2talk(self):
  1220.         """ Toggles if the room should be in push2talk mode. """
  1221.         if self.is_client_owner:
  1222.             if self.privacy_.set_push2talk():
  1223.                 self.send_private_msg(self.active_user.id, 'Push2Talk is enabled.')
  1224.             else:
  1225.                 self.send_private_msg(self.active_user.id, 'Push2Talk is disabled.')
  1226.  
  1227.     def do_green_room(self):
  1228.         """ Toggles if the room should be in greenroom mode. """
  1229.         if self.is_client_owner:
  1230.             if self.privacy_.set_greenroom():
  1231.                 self.send_private_msg(self.active_user.id, 'Green room is enabled.')
  1232.             else:
  1233.                 self.send_private_msg(self.active_user.id, 'Green room is disabled.')
  1234.  
  1235.     def do_clear_room_bans(self):
  1236.         """ Clear all room bans. """
  1237.         if self.is_client_owner:
  1238.             if self.privacy_.clear_bans():
  1239.                 self.send_private_msg(self.active_user.id, 'All room bans was cleared.')
  1240.  
  1241.     def do_kill(self):
  1242.         """ Kills the bot. """
  1243.         self.disconnect()
  1244.  
  1245.     def do_reboot(self):
  1246.         """ Reboots the bot. """
  1247.         self.reconnect()
  1248.  
  1249.     def options(self):
  1250.         """ Load/set special options. """
  1251.  
  1252.         log.info('options: is_client_owner: %s, is_client_mod: %s' %
  1253.                  (self.is_client_owner, self.is_client_mod))
  1254.  
  1255.         if self.is_client_owner:
  1256.             self.get_privacy_settings()
  1257.  
  1258.         if self.is_client_mod:
  1259.             self.send_banlist_msg()
  1260.  
  1261.     def get_privacy_settings(self):
  1262.         """ Parse the privacy settings page. """
  1263.         log.info('Parsing %s\'s privacy page.' % self.account)
  1264.         self.privacy_ = privacy.Privacy(proxy=None)
  1265.         self.privacy_.parse_privacy_settings()
  1266.  
  1267.     def do_guests(self):
  1268.         """ Toggles if guests are allowed to join the room or not. """
  1269.         pinylib.CONFIG.B_ALLOW_GUESTS = not pinylib.CONFIG.B_ALLOW_GUESTS
  1270.         #self.send_chat_msg('Allow Guests: %s' % pinylib.CONFIG.B_ALLOW_GUESTS)
  1271.         pass
  1272.  
  1273.     def do_lurkers(self):
  1274.         """ Toggles if lurkers are allowed or not. """
  1275.         pinylib.CONFIG.B_ALLOW_LURKERS = not pinylib.CONFIG.B_ALLOW_LURKERS
  1276.         #self.send_chat_msg('Allow Lurkers: %s' % pinylib.CONFIG.B_ALLOW_LURKERS)
  1277.         pass
  1278.  
  1279.     def do_greet(self):
  1280.         """ Toggles if users should be greeted on entry. """
  1281.         pinylib.CONFIG.B_GREET = not pinylib.CONFIG.B_GREET
  1282.         self.send_private_msg(self.active_user.id, 'Greet Users: %s' % pinylib.CONFIG.B_GREET)
  1283.  
  1284.     def do_kick_as_ban(self):
  1285.         """ Toggles if kick should be used instead of ban for auto bans . """
  1286.         pinylib.CONFIG.B_USE_KICK_AS_AUTOBAN = not pinylib.CONFIG.B_USE_KICK_AS_AUTOBAN
  1287.         #self.send_chat_msg('Use Kick As Auto Ban: %s' % pinylib.CONFIG.B_USE_KICK_AS_AUTOBAN)
  1288.         pass
  1289.  
  1290.     # == Python Timer Functions  ==
  1291.  
  1292.     def timer_event(self):
  1293.         """ This gets called when the timer has reached the time. """
  1294.         if len(self.playlist.track_list) > 0:
  1295.             if self.playlist.is_last_track:
  1296.                 if self.is_connected:
  1297.                     self.send_chat_msg('Resetting playlist.')
  1298.                 self.playlist.clear()
  1299.             else:
  1300.                 track = self.playlist.next_track
  1301.                 if track is not None and self.is_connected:
  1302.                     self.send_yut_play(track.id, track.time, track.title)
  1303.                 self.timer(track.time)
  1304.  
  1305.     def timer(self, event_time):
  1306.         """
  1307.        Track event timer.
  1308.  
  1309.        This will cause an event to occur once the time is done.
  1310.  
  1311.        :param event_time: The time in seconds for when an event should occur.
  1312.        :type event_time: int | float
  1313.        """
  1314.         self.timer_thread = threading.Timer(event_time, self.timer_event)
  1315.         self.timer_thread.start()
  1316.  
  1317.     def cancel_timer(self):
  1318.         """ Cancel the track timer. """
  1319.         if self.timer_thread is not None:
  1320.             if self.timer_thread.is_alive():
  1321.                 self.timer_thread.cancel()
  1322.                 self.timer_thread = None
  1323.                 return True
  1324.             return False
  1325.         return False
  1326.  
  1327.     @staticmethod
  1328.     def format_time(time_stamp, is_milli=False):
  1329.         """
  1330.        Converts a time stamp as seconds or milliseconds to (day(s)) hours minutes seconds.
  1331.  
  1332.        :param time_stamp: Seconds or milliseconds to convert.
  1333.        :param is_milli: The time stamp to format is in milliseconds.
  1334.        :return: A string in the format (days) hh:mm:ss
  1335.        :rtype: str
  1336.        """
  1337.         if is_milli:
  1338.             m, s = divmod(time_stamp / 1000, 60)
  1339.         else:
  1340.             m, s = divmod(time_stamp, 60)
  1341.         h, m = divmod(m, 60)
  1342.         d, h = divmod(h, 24)
  1343.  
  1344.         if d == 0 and h == 0:
  1345.             human_time = '%02d:%02d' % (m, s)
  1346.         elif d == 0:
  1347.             human_time = '%d:%02d:%02d' % (h, m, s)
  1348.         else:
  1349.             human_time = '%d Day(s) %d:%02d:%02d' % (d, h, m, s)
  1350.         return human_time
  1351.  
  1352.     # == BuddyBot Additions ==
  1353.     # odsum.2018
  1354.     # User Management On_Join Registration
  1355.     # On-Join Flood Lockdown
  1356.     # Spam Protection in messaging
  1357.     # DJ Mode
  1358.     # Kick/Ban Pooling
  1359.     # Room Announcement
  1360.  
  1361.     # playing with ideas of handling spam bots
  1362.  
  1363.     def worker_kicks(self):
  1364.         limit = 0
  1365.         for k in self.kick_pool:
  1366.             if limit > 3:
  1367.                 pass
  1368.             else:
  1369.                 time.sleep(1.5)
  1370.                 self.kick_pool.remove(k)
  1371.                 self.send_kick_msg(k)
  1372.                 limit += 1
  1373.         threading.Timer(15.0, self.worker_kicks).start()
  1374.  
  1375.     def worker_bans(self):
  1376.         limit = 0
  1377.         for b in self.ban_pool:
  1378.             if limit > 3:
  1379.                 pass
  1380.             else:
  1381.                 time.sleep(2.0)
  1382.                 self.ban_pool.remove(b)
  1383.                 self.send_ban_msg(b)
  1384.                 limit += 1
  1385.         threading.Timer(30.0, self.worker_bans).start()
  1386.  
  1387.     def on_quit(self, uid):
  1388.         if uid in self.kick_pool:
  1389.             self.kick_pool.remove(uid)
  1390.  
  1391.         if uid in self.ban_pool:
  1392.             self.ban_pool.remove(uid)
  1393.  
  1394.     def process_kick(self, id):
  1395.         if id not in self.kick_pool:
  1396.             self.kick_pool.append(id)
  1397.  
  1398.     def process_ban(self, id):
  1399.         if id not in self.ban_pool:
  1400.             self.ban_pool.append(id)
  1401.  
  1402.     def user_register(self, _user):
  1403.  
  1404.         if _user.account:
  1405.  
  1406.             buddyusr = self.buddy_db.find_db_user(_user.account)
  1407.             tc_info = pinylib.apis.tinychat.user_info(_user.account)
  1408.  
  1409.             if tc_info is not None:
  1410.                 _user.tinychat_id = tc_info['tinychat_id']
  1411.                 _user.last_login = tc_info['last_active']
  1412.  
  1413.             if _user.is_owner:
  1414.                 _user.user_level = 2  # account owner
  1415.                 self.console_write(pinylib.COLOR['cyan'], '[User] Room Owner %s:%d:%s' %
  1416.                                    (_user.nick, _user.id, _user.account))
  1417.             elif _user.is_mod:
  1418.                 _user.user_level = 3  # mod
  1419.                 self.console_write(pinylib.COLOR['cyan'], '[User] Moderator %s:%d:%s' %
  1420.                                    (_user.nick, _user.id, _user.account))
  1421.             if buddyusr:
  1422.                 _level = buddyusr['level']
  1423.  
  1424.                 if _level == 4 and not _user.is_mod:
  1425.                     _user.user_level = _level  # chatmod
  1426.  
  1427.                 if _level == 5 and not _user.is_mod:
  1428.                     _user.user_level = _level  # whitelist
  1429.  
  1430.                 if _level == 2:  # overwrite mod to chatadmin
  1431.                     _user.user_level = _level
  1432.  
  1433.                 self.console_write(pinylib.COLOR['cyan'], '[User] Found, level(%s)  %s:%d:%s' % (
  1434.                     _user.user_level, _user.nick, _user.id, _user.account))
  1435.  
  1436.             if _user.user_level is None:
  1437.                 _user.user_level = 6  # account not verified
  1438.                 self.console_write(pinylib.COLOR['cyan'],
  1439.                                    '[User] Not verified %s:%d:%s' % (_user.nick, _user.id, _user.account))
  1440.  
  1441.             if self.buddy_db.find_db_account_bans(_user.account) and self.is_client_mod:
  1442.                 if self.lockdown:
  1443.                     self.process_ban(_user.id)
  1444.                 else:
  1445.                     self.process_ban(_user.id)
  1446.                 self.console_write(pinylib.COLOR['red'], '[Security] Banned: Account %s' % _user.account)
  1447.         else:
  1448.             _user.user_level = 7  # guest
  1449.             self.console_write(pinylib.COLOR['cyan'], '[User] Guest %s:%d' % (_user.nick, _user.id))
  1450.  
  1451.             if not pinylib.CONFIG.B_ALLOW_GUESTS:
  1452.                 if _user.user_level == 7:
  1453.                     if self.lockdown:
  1454.                         self.process_ban(_user.id)
  1455.                     else:
  1456.                         self.send_ban_msg(_user.id)
  1457.                     self.console_write(pinylib.COLOR['red'], '[Security] %s was banned on no guest mode' % _user.nick)
  1458.  
  1459.             if _user.is_lurker and not pinylib.CONFIG.B_ALLOW_LURKERS:
  1460.                 if _user.user_level > 5:
  1461.                     if self.lockdown:
  1462.                         self.process_ban(_user.id)
  1463.                     else:
  1464.                         self.send_ban_msg(_user.id)
  1465.                     self.console_write(pinylib.COLOR['red'], '[Security] %s was banned on no lurkers mode' % _user.nick)
  1466.  
  1467.         # Lockdown
  1468.         # odsum
  1469.  
  1470.         maxtime = 10  # Reset check in X seconds
  1471.         maxjoins = 5  # maxjoins in maxtime
  1472.  
  1473.         if self.joind_time == 0:
  1474.             self.joind_time = time.time()
  1475.             self.joind_count += 1
  1476.  
  1477.         elif self.time_join - self.joind_time > maxtime:
  1478.             self.joind_count = 0
  1479.             self.joind_time = 0
  1480.             self.bad_nick = 0
  1481.  
  1482.         elif self.joind_count > maxjoins:
  1483.  
  1484.             soft = 0
  1485.             self.do_lockdown(soft)
  1486.             self.autoban_time = self.time_join
  1487.             self.console_write(
  1488.                 pinylib.COLOR['red'], '[Security] Lockdown started')
  1489.         else:
  1490.             self.joind_count += 1
  1491.  
  1492.             if not self.isWord(_user.nick):
  1493.                 self.bad_nick += 1
  1494.  
  1495.         if self.bad_nick > 1:
  1496.             time.sleep(1.2)
  1497.             if self.lockdown:
  1498.                 self.process_ban(_user.id)
  1499.             else:
  1500.                 self.send_ban_msg(_user.id)
  1501.             self.console_write(pinylib.COLOR['red'], '[Security] Randomized Nick Banned: Nicks %s' % _user.nick)
  1502.  
  1503.         self.console_write(pinylib.COLOR['cyan'], '[User] %s:%d joined the room. (%s)' % (
  1504.             _user.nick, _user.id, self.joind_count))
  1505.  
  1506.         # TC allows X msg per owner and mod account
  1507.         if self.joind_count < 3:
  1508.             threading.Thread(target=self.welcome, args=(_user.id,)).start()
  1509.  
  1510.     def check_lockdown(self):
  1511.         # time_join being latest one? not sure
  1512.         if self.lockdown:
  1513.             if self.time_join - 240 > self.autoban_time:  # reset after X seconds locakdown
  1514.                 self.do_lockdown(1)
  1515.                 self.autoban_time = 0
  1516.                 self.bad_nick = 0
  1517.                 self.console_write(
  1518.                     pinylib.COLOR['red'], '[Security] Lockdown Mode Reset')
  1519.  
  1520.     @staticmethod
  1521.     def _removeNonAscii(s):
  1522.         return "".join(i for i in s if ord(i) < 128)
  1523.  
  1524.     def check_msg(self, msg):
  1525.  
  1526.         # Spam 2.3 Protection ting
  1527.         # odsum(lucy) //shit hasn't been the same as it was before...
  1528.         # 02.24.18
  1529.  
  1530.         ban = False
  1531.         spammer = False
  1532.         kick = False
  1533.  
  1534.         msg = self._removeNonAscii(msg)
  1535.         chat_words = msg.split(' ')
  1536.         total = sum(char.isspace() or char == "0" for char in msg)
  1537.         chatr_user = self.active_user.nick
  1538.         chatr_account = self.active_user.account
  1539.         msg_time = int(time.time())
  1540.         totalcopies = 0
  1541.         reason = ''
  1542.         spamlevel = 0
  1543.  
  1544.         # each word reviewed and scored
  1545.  
  1546.         for word in chat_words:
  1547.             if word in self.general:
  1548.                 pass
  1549.             else:
  1550.                 if not self.isWord(word):
  1551.                     spamlevel += 0.25  # for everyword that isn't english word
  1552.  
  1553.                 if not self.isWord(chatr_user):
  1554.                     spamlevel += 0.25  # wack nick
  1555.  
  1556.                 if word.isupper():
  1557.                     spamlevel += 0.125  # Uppercase word
  1558.  
  1559.                 lword = word.lower()
  1560.                 if self.buddy_db.find_db_word_bans(lword):
  1561.                     ban = True
  1562.                     spammer = True
  1563.                     spamlevel += 2
  1564.                     reason = 'Word ban: ' + lword
  1565.                     self.console_write(pinylib.COLOR['bright_magenta'], '[Spam] Banned word')
  1566.  
  1567.         if total > 140:  # if message is larger than 100 characters
  1568.             spamlevel += 0.5
  1569.  
  1570.         # knownnick = self.buddy_db.find_db_ticket(chatr_user)
  1571.         #
  1572.         # # known spammer from our database.
  1573.         #
  1574.         # if knownnick:
  1575.         #     spamlevel += 0.25
  1576.         #     spammer = True
  1577.         #
  1578.         #     if knownnick['account']:
  1579.         #         spamlevel += 0.25
  1580.  
  1581.         for m in self.msgs:
  1582.             if msg == m and m not in self.general:
  1583.                 totalcopies += 1
  1584.                 oldmsg = self.msgs[msg]
  1585.  
  1586.                 msgdiff = oldmsg['ts'] - msg_time
  1587.  
  1588.                 if totalcopies > 0:
  1589.                     spamlevel += 0.25
  1590.  
  1591.                 if oldmsg['nick'] == chatr_user:
  1592.                     spamlevel += 0.5
  1593.                     spammer = True
  1594.                     kick = True
  1595.  
  1596.                 if msgdiff < 2:
  1597.                     spamlevel += 0.25
  1598.  
  1599.                 spamlevel += 0.5
  1600.         #        reason = 'Spam repeat.'
  1601.  
  1602.         mpkg = {'score': spamlevel, 'account': chatr_account, 'nick': chatr_user, 'ts': msg_time}
  1603.  
  1604.         # if spamlevel >= 2:
  1605.         #     self.buddy_db.add_ticket(chatr_account, spamlevel, chatr_user, reason)
  1606.         #     self.console_write(pinylib.COLOR['bright_magenta'], '[Spam] Ticket submitted: Nick: %s Score: %s' %
  1607.         #                        (chatr_user, spamlevel))
  1608.  
  1609.         self.msgs.update({'%s' % msg: mpkg})
  1610.  
  1611.         if len(self.msgs) > 4:  # store last 4 messages
  1612.             self.msgs.clear()
  1613.  
  1614.         if self.active_user.user_level > 5:
  1615.             if spamlevel > 3:
  1616.                 ban = True
  1617.         if ban:
  1618.             time.sleep(0.7)
  1619.             if self.active_user.user_level == 6:
  1620.                 if spammer:
  1621.                     self.buddy_db.add_bad_account(self.active_user.account)
  1622.                     if self.lockdown:
  1623.                         self.process_ban(self.active_user.id)
  1624.                     else:
  1625.                         self.send_ban_msg(self.active_user.id)
  1626.             elif len(self.active_user.account) is 0:
  1627.                 if spammer:
  1628.                     if self.lockdown:
  1629.                         self.process_ban(self.active_user.id)
  1630.                     else:
  1631.                         self.send_ban_msg(self.active_user.id)
  1632.         if kick:
  1633.             if self.lockdown:
  1634.                 self.process_ban(self.active_user.id)
  1635.             else:
  1636.                 self.send_kick_msg(self.active_user.id)
  1637.  
  1638.  
  1639.     @staticmethod
  1640.     def isWord(word):
  1641.  
  1642.         VOWELS = "aeiou"
  1643.         PHONES = ['sh', 'ch', 'ph', 'sz', 'cz', 'sch', 'rz', 'dz']
  1644.         prevVowel = False
  1645.  
  1646.         if word:
  1647.             consecutiveVowels = 0
  1648.             consecutiveConsonents = 0
  1649.             for idx, letter in enumerate(word.lower()):
  1650.                 vowel = True if letter in VOWELS else False
  1651.  
  1652.                 if idx:
  1653.                     prev = word[idx - 1]
  1654.                     if prev in VOWELS:
  1655.                         prevVowel = True
  1656.                     if not vowel and letter == 'y' and not prevVowel:
  1657.                         vowel = True
  1658.  
  1659.                 if prevVowel != vowel:
  1660.                     consecutiveVowels = 0
  1661.                     consecutiveConsonents = 0
  1662.  
  1663.                 if vowel:
  1664.                     consecutiveVowels += 1
  1665.                 else:
  1666.                     consecutiveConsonents += 1
  1667.  
  1668.                 if consecutiveVowels >= 3 or consecutiveConsonents > 3:
  1669.                     return False
  1670.  
  1671.                 if consecutiveConsonents == 3:
  1672.                     subStr = word[idx - 2:idx + 1]
  1673.                     if any(phone in subStr for phone in PHONES):
  1674.                         consecutiveConsonents -= 1
  1675.                         continue
  1676.                     return False
  1677.         return True
  1678.  
  1679.     def do_lockdown(self, soft):
  1680.  
  1681.         if self.is_client_owner:
  1682.             if soft:
  1683.                 password = None
  1684.             else:
  1685.                 password = pinylib.string_util.create_random_string(5, 8)
  1686.  
  1687.             if not self.privacy_.set_guest_mode():
  1688.                 self.privacy_.set_room_password(password)
  1689.                 self.lockdown = True
  1690.  
  1691.                 if soft:
  1692.                     time.sleep(2.0)
  1693.                     self.send_chat_msg('Lockdown - no guests allowed.')
  1694.                 else:
  1695.                     self.send_chat_msg(
  1696.                         'Lockdown - tmp password is: %s' % password)
  1697.             else:
  1698.                 password = None
  1699.                 self.privacy_.set_room_password(password)
  1700.                 self.lockdown = False
  1701.  
  1702.                 self.kick_pool[:] = []
  1703.                 self.ban_pool[:] = []
  1704.  
  1705.                 time.sleep(2.0)
  1706.                 self.send_chat_msg(
  1707.                     '%s is open to the public again.' % self.room_name)
  1708.         else:
  1709.             if self.lockdown:
  1710.                 self.lockdown = False
  1711.  
  1712.                 if not pinylib.CONFIG.B_ALLOW_GUESTS:
  1713.                     self.do_guests()
  1714.                     self.do_kick_as_ban()
  1715.  
  1716.                 self.kick_pool[:] = []
  1717.                 self.ban_pool[:] = []
  1718.  
  1719.                 time.sleep(2.0)
  1720.                 self.send_chat_msg(
  1721.                     '%s is open to the public again.' % self.room_name)
  1722.             else:
  1723.  
  1724.                 if pinylib.CONFIG.B_ALLOW_GUESTS:
  1725.                     self.do_guests()
  1726.                     self.do_kick_as_ban()
  1727.                     self.lockdown = True
  1728.                     time.sleep(2.0)
  1729.                     self.send_chat_msg('Lockdown - no guests allowed.')
  1730.  
  1731.         threading.Timer(240.0, self.check_lockdown).start()
  1732.  
  1733.     def do_djmsg(self):
  1734.         deejays = ",".join(self.djs)
  1735.         self.send_chat_msg('%s, %s is in DJ mode, current djs: %s' % (self.active_user.nick, self.room_name, deejays))
  1736.  
  1737.     def do_dj(self, account):
  1738.         _user = self.users.search_by_nick(account)
  1739.  
  1740.         if _user is None:
  1741.             self.send_chat_msg('%s has no account.' % account)
  1742.         else:
  1743.             if _user.account in self.djs:
  1744.                 self.djs.remove(_user.account)
  1745.                 self.send_chat_msg('%s is not longer a dj.' % _user.account)
  1746.             else:
  1747.                 self.djs.append(_user.account)
  1748.                 self.send_chat_msg('%s is now in the DJ crew.' % _user.account)
  1749.  
  1750.     def do_dj_mode(self):
  1751.         if self.dj_mode == 0:
  1752.             self.dj_mode = 1
  1753.             self.send_chat_msg('Room is now in DJ mode!')
  1754.  
  1755.         else:
  1756.             self.dj_mode = 0
  1757.             self.send_chat_msg(
  1758.                 'DJ mode is off, you can add to the youtube playlist now.')
  1759.  
  1760.     def do_announcement(self, announcement):
  1761.         self.tmp_announcement = announcement
  1762.         self.send_private_msg(self.active_user.id,
  1763.                               'Room annoucement set to: %s' % announcement)
  1764.  
  1765.     def announcement(self):
  1766.         announcement = pinylib.CONFIG.B_ANNOUNCEMENT
  1767.         if self.tmp_announcement is not None:
  1768.             announcement = self.tmp_announcement
  1769.         return announcement
  1770.  
  1771.     def do_help(self):
  1772.         """ Posts a link to github readme/wiki or other page about the bot commands. """
  1773.  
  1774.         ownr_cmds = ["reboot","kb","p2t", "dir"]
  1775.         admin_cmds = ["chatadmin", "rmchatadmin", "addmod", "rmmod"]
  1776.         mod_cmds = ["announcement", "lockdown", "lockup", "chatmod", "dechatmod"]
  1777.         cmod_cmds = ["clr","kick", "ban", "unb", "sbl", "fg", "cam", "close", "bada", "banw", "rmw", "rmbad", "badn", "rmv", "v", "noguest", "greet", 'lurkers']
  1778.         media_cmds = ["yt", "close", "seek", "reset", "spl", "del", "skip", "yts", "rpl", "pause", "play", "pyst"]
  1779.         public_cmds = ["urb","wea","ip","cn","8ball","roll","flip"]
  1780.  
  1781.         prefix = pinylib.CONFIG.B_PREFIX
  1782.  
  1783.         cmds_av = public_cmds
  1784.  
  1785.         if self.active_user.user_level < 3:
  1786.             cmds_av = cmds_av + admin_cmds
  1787.             if self.is_client_owner:
  1788.                 cmds_av = cmds_av + ownr_cmds
  1789.         if self.active_user.user_level == 3:
  1790.             cmds_av = cmds_av + mod_cmds
  1791.         if self.active_user.user_level >= 3 and self.active_user.user_level > 5:
  1792.             cmds_av = cmds_av + cmod_cmds
  1793.         if self.active_user.user_level < 6:
  1794.             cmds_av = cmds_av + media_cmds
  1795.  
  1796.         cmds_av.sort()
  1797.         cmds_dump = [prefix + cmd for cmd in cmds_av]
  1798.         sets = zip(*[iter(cmds_dump)] * 8)
  1799.         self.send_private_msg(self.active_user.id, 'Available Commands:')
  1800.  
  1801.         for set in sets:
  1802.             cmds = ", ".join(set)
  1803.             time.sleep(1.5)
  1804.             self.send_private_msg(self.active_user.id, '%s' % (cmds))
  1805.  
  1806.  
  1807.     def welcome(self, uid):
  1808.  
  1809.         greetings = ["hi", "sup", "yo", "hey", "eh", ]
  1810.         prefix = pinylib.CONFIG.B_PREFIX
  1811.  
  1812.         time.sleep(5)
  1813.         _user = self.users.search(uid)
  1814.  
  1815.         if _user is not None:
  1816.  
  1817.             if pinylib.CONFIG.B_ALLOW_GUESTS:
  1818.                 if pinylib.CONFIG.B_GREET and _user is not None:
  1819.  
  1820.                     if not _user.nick.startswith('guest-'):
  1821.  
  1822.                         if _user.user_level < 4:
  1823.                             self.send_private_msg(_user.id, 'You are Mod  - %shelp for cmds' % prefix)
  1824.                             self.send_private_msg(_user.id,
  1825.                                                   '%s' % (self.announcement()))
  1826.                         elif _user.user_level == 5:
  1827.                             self.send_private_msg(_user.id,
  1828.                                                   '%s %s, wb - You have access to the bot here, %shelp for cmds' % (
  1829.                                                       random.choice(greetings), _user.nick, prefix))
  1830.                             self.send_private_msg(_user.id,
  1831.                                                   '%s' % (self.announcement()))
  1832.                         elif _user.user_level == 6:
  1833.                             self.send_chat_msg('%s %s, welcome to %s - %s' % (
  1834.                                 random.choice(greetings), _user.nick, self.room_name, self.announcement()))
  1835.                         elif _user.user_level == 7:
  1836.                             self.send_chat_msg('%s %s, welcome to %s' % (
  1837.                                 random.choice(greetings), _user.nick, self.room_name))
  1838.  
  1839.     # == Tinychat API Command Methods. ==
  1840.  
  1841.     def do_account_spy(self, account):
  1842.         """
  1843.        Shows info about a tinychat account.
  1844.        :param account: tinychat account.
  1845.        :type account: str
  1846.        """
  1847.         if self.is_client_mod:
  1848.             if len(account) is 0:
  1849.                 self.send_private_msg(self.active_user.id, 'Missing username to search for.')
  1850.             else:
  1851.                 tc_usr = pinylib.apis.tinychat.user_info(account)
  1852.                 if tc_usr is None:
  1853.                     self.send_private_msg(self.active_user.id, 'Could not find tinychat info for: %s' % account)
  1854.                 else:
  1855.                     self.send_private_msg(self.active_user.id, 'ID: %s, \nLast Login: %s' %
  1856.                                           (tc_usr['tinychat_id'], tc_usr['last_active']))
  1857.  
  1858.     # == Other API Command Methods. ==
  1859.  
  1860.     def do_search_urban_dictionary(self, search_str):
  1861.         """
  1862.        Shows urbandictionary definition of search string.
  1863.        :param search_str: The search string to look up a definition for.
  1864.        :type search_str: str
  1865.        """
  1866.         if self.is_client_mod:
  1867.             if len(search_str) is 0:
  1868.                 self.send_chat_msg('Please specify something to look up.')
  1869.             else:
  1870.                 urban = other.urbandictionary_search(search_str)
  1871.                 if urban is None:
  1872.                     self.send_chat_msg('Could not find a definition for: %s' % search_str)
  1873.                 else:
  1874.                     if len(urban) > 70:
  1875.                         chunks = pinylib.string_util.chunk_string(urban, 70)
  1876.                         for i in range(0, 2):
  1877.                             self.send_chat_msg(chunks[i])
  1878.                     else:
  1879.                         self.send_chat_msg(urban)
  1880.  
  1881.     def do_weather_search(self, search_str):
  1882.         """
  1883.        Shows weather info for a given search string.
  1884.        :param search_str: The search string to find weather data for.
  1885.        :type search_str: str
  1886.        """
  1887.         if len(search_str) is 0:
  1888.             self.send_chat_msg('Please specify a city to search for.')
  1889.         else:
  1890.             weather = other.weather_search(search_str)
  1891.             if weather is None:
  1892.                 self.send_chat_msg('Could not find weather data for: %s' % search_str)
  1893.             else:
  1894.                 self.send_chat_msg(weather)
  1895.  
  1896.     def do_whois_ip(self, ip_str):
  1897.         """
  1898.        Shows whois info for a given ip address or domain.
  1899.        :param ip_str: The ip address or domain to find info for.
  1900.        :type ip_str: str
  1901.        """
  1902.         if len(ip_str) is 0:
  1903.             self.send_chat_msg('Please provide an IP address or domain.')
  1904.         else:
  1905.             whois = other.whois(ip_str)
  1906.             if whois is None:
  1907.                 self.send_chat_msg('No info found for: %s' % ip_str)
  1908.             else:
  1909.                 self.send_chat_msg(whois)
  1910.  
  1911.     # == Just For Fun Command Methods. ==
  1912.  
  1913.  
  1914.     def do_chuck_noris(self):
  1915.         """ Shows a chuck norris joke/quote. """
  1916.         chuck = other.chuck_norris()
  1917.         if chuck is not None:
  1918.             self.send_chat_msg(chuck)
  1919.  
  1920.     def do_8ball(self, question):
  1921.         """
  1922.        Shows magic eight ball answer to a yes/no question.
  1923.        :param question: The yes/no question.
  1924.        :type question: str
  1925.        """
  1926.         if len(question) is 0:
  1927.             self.send_chat_msg('Question.')
  1928.         else:
  1929.             self.send_chat_msg('8Ball %s' % locals_.eight_ball())
  1930.  
  1931.     def do_dice(self):
  1932.         """ roll the dice. """
  1933.         self.send_chat_msg('The dice rolled: %s' % locals_.roll_dice())
  1934.  
  1935.     def do_flip_coin(self):
  1936.         """ Flip a coin. """
  1937.         self.send_chat_msg('The coin was: %s' % locals_.flip_coin())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement