Justabot est un Bot écrit en python, il permet une présence sur les salons Jabber. https://www.devosi.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

344 lines
11KB

  1. # -*- coding: utf-8 -*-
  2. # Copyright Crestetto Kévin, (Mai 2012)
  3. # checkpoint [at] singularity (dot) fr
  4. # Ce logiciel est un programme informatique
  5. # servant à discuter et executer des commandes sur un salon jabber/XMPP.
  6. # Ce logiciel est régi par la licence CeCILL soumise au droit français et
  7. # respectant les principes de diffusion des logiciels libres. Vous pouvez
  8. # utiliser, modifier et/ou redistribuer ce programme sous les conditions
  9. # de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
  10. # sur le site "http://www.cecill.info".
  11. # En contrepartie de l'accessibilité au code source et des droits de copie,
  12. # de modification et de redistribution accordés par cette licence, il n'est
  13. # offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
  14. # seule une responsabilité restreinte pèse sur l'auteur du programme, le
  15. # titulaire des droits patrimoniaux et les concédants successifs.
  16. # A cet égard l'attention de l'utilisateur est attirée sur les risques
  17. # associés au chargement, à l'utilisation, à la modification et/ou au
  18. # développement et à la reproduction du logiciel par l'utilisateur étant
  19. # donné sa spécificité de logiciel libre, qui peut le rendre complexe à
  20. # manipuler et qui le réserve donc à des développeurs et des professionnels
  21. # avertis possédant des connaissances informatiques approfondies. Les
  22. # utilisateurs sont donc invités à charger et tester l'adéquation du
  23. # logiciel à leurs besoins dans des conditions permettant d'assurer la
  24. # sécurité de leurs systèmes et ou de leurs données et, plus généralement,
  25. # à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
  26. # Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
  27. # pris connaissance de la licence CeCILL, et que vous en avez accepté les
  28. # termes.
  29. from tools import ManagePres, hashname
  30. import OBC
  31. from re import search
  32. from config.configopt import CFG
  33. from config.configtra import tra_help
  34. from config.config import ADMINS
  35. import os
  36. import time, _thread
  37. # import plugings files
  38. for p in os.listdir('plugins'):
  39. if not (os.path.isfile('plugins/' + p) and p.endswith('.py')):
  40. continue
  41. count = 0
  42. with open('plugins/' + p, 'rb') as f:
  43. lines = f.readlines()
  44. for line in lines:
  45. count += 1
  46. if count < 200:
  47. if line.startswith(b'###Iamplugin###'):
  48. exec('from plugins import ' + p[:-3])
  49. else:
  50. break
  51. class Plugs:
  52. """ Manage load, unload and list plugins """
  53. def __init__(self):
  54. """ list the plugins
  55. self.it must be init """
  56. self.MYPLUGLABEL={'emergency': 10,
  57. 'first': 30,
  58. 'before': 50,
  59. 'simple': 70,
  60. 'after': 90,
  61. 'last': 110,
  62. }
  63. self.it = None
  64. self.available_plugs = {}
  65. for p in os.listdir('plugins'):
  66. plug = 'plugins/' + p
  67. if not os.path.isfile(plug) or not p.endswith('.py'):
  68. continue
  69. count = 0
  70. with open(plug, 'rb') as f:
  71. lines = f.readlines()
  72. for line in lines:
  73. count += 1
  74. if count < 200:
  75. if line.startswith(b'###Iamplugin###'):
  76. infos = eval(p[:-3] + '.run()')
  77. for info in infos:
  78. self.available_plugs[info['Cfg']] = {
  79. 'Torun': p[:-3] + '.' + info['Torun'],
  80. 'Obj': False, 'where': info['where']}
  81. break
  82. else:
  83. break
  84. self.orderplug = {'flood': [], 'end': [], 'before': [], 'pres': []}
  85. self.thread_timecall = _thread.start_new_thread(self.timecall, ())
  86. def plug_quit(self):
  87. """ reset all plugins list """
  88. self.orderplug = {'flood': [], 'end': [], 'before': [], 'pres': []}
  89. for plug in list(self.available_plugs.keys()):
  90. self.available_plugs[plug]['Obj'] = False
  91. def allplugload(self):
  92. """ load all plugins which is True in CFG """
  93. copy = self.available_plugs
  94. for plug in list(copy.keys()):
  95. if plug in list(CFG.keys()):
  96. if CFG[plug] == True:
  97. self.plugload(plug)
  98. def plugload(self, name):
  99. """ load and sort one plugin """
  100. fun = self.available_plugs[name]
  101. if fun['Obj'] == False:
  102. Obje = fun['Torun'] + '(self.it)'
  103. Obj = eval(Obje)
  104. self.available_plugs[name]['Obj'] = Obj
  105. Obj = self.available_plugs[name]['Obj']
  106. for key in list(Obj.STEPS().keys()):
  107. for plugstep in Obj.STEPS()[key]:
  108. result = []
  109. end = False
  110. for step, n in self.orderplug[key]:
  111. if self.MYPLUGLABEL[step] >= self.MYPLUGLABEL[plugstep] and not end:
  112. end = True
  113. result.append([plugstep, name])
  114. result.append([step, n])
  115. if not end:
  116. result.append([plugstep, name])
  117. self.orderplug[key] = result
  118. def plugunload(self, name):
  119. """ unload one plugin """
  120. if self.available_plugs[name]['Obj'] != False:
  121. self.available_plugs[name]['Obj'] = False
  122. for key in list(self.orderplug.keys()):
  123. result = []
  124. for step, n in self.orderplug[key]:
  125. if n != name:
  126. result.append([step, n])
  127. self.orderplug[key] = result
  128. def timecall(self):
  129. time.sleep(3)
  130. while self.thread_timecall:
  131. for value in [10, 20, 30, 40, 50, 60]:
  132. time.sleep(10)
  133. for key in list(self.available_plugs.keys()):
  134. try:
  135. _thread.start_new_thread(
  136. self.available_plugs[key]['Obj'].newcall, (value,))
  137. except AttributeError:
  138. pass
  139. PLUGINS = Plugs()
  140. class Com(ManagePres):
  141. """manage the receive lines and switch it on anothers class
  142. inherit from tools.py, the presence and role managment
  143. """
  144. def __init__(self, it, chan):
  145. """load the class"""
  146. self.it = it
  147. self.nick = it.NICKNAME
  148. self.name = chan
  149. self.OBC = OBC.onebychan()
  150. self.mypres = ('unavailable', 'none')
  151. self.connected = {}
  152. self.hash = hashname(chan)
  153. self.admins = ['owner', 'admin']
  154. def plugcall(self, Amsg, key, where):
  155. """ call all avalables plugins and if one answer, break """
  156. order = PLUGINS.orderplug[key]
  157. onwait = None
  158. for num in range(len(order)):
  159. onstep, n = order[0]
  160. if n:
  161. plug = PLUGINS.available_plugs[n]
  162. if onwait == '' or not onwait:
  163. if where in plug['where']:
  164. onwait = plug['Obj'](Amsg, onstep, key)
  165. order = order[1:]
  166. else:
  167. break
  168. return onwait
  169. def __call__(self, mess, text, nick, typ):
  170. """ switch under all class and return the answer string "onwait" """
  171. if not nick in list(self.connected.keys()):
  172. if self.name != '@':
  173. return ''
  174. isadmin = False
  175. if self.name != '@':
  176. jid = self.connected[nick]['rname']
  177. if self.connected[nick]['aff'] in self.admins:
  178. isadmin = True
  179. if typ == 'groupchat':
  180. where = 'G'
  181. isfrom = self.name
  182. else:
  183. where = 'Q'
  184. isfrom = self.name + '/' + nick
  185. else:
  186. where = '@'
  187. if nick in ADMINS:
  188. isadmin = True
  189. jid = nick
  190. isfrom = nick
  191. arg = ' '.join(text.split(' ')[1:])
  192. isforme = False
  193. if search(r'.*[^\w]' + self.nick +
  194. r'[^\w].*', ' ' + text + ' '):
  195. isforme = True
  196. first = text.split(' ')[0]
  197. Amsg = {'text': text, 'typ': typ, 'nick': nick,
  198. 'jid': jid, 'pres': self.mypres,
  199. 'mynick': self.nick, 'arg': arg, 'isforme': isforme,
  200. 'first': first, 'chan': self.name, 'chanhash': self.hash,
  201. 'from': isfrom, 'conn': self.connected, 'isadmin': isadmin}
  202. self.plugcall(Amsg, 'before', where)
  203. if not self.OBC.isnotflood() and self.name != '@':
  204. if self.OBC.nobad:
  205. self.plugcall(Amsg, 'flood', where)
  206. return ''
  207. self.OBC.setflood()
  208. onwait = self.plugcall(Amsg, 'end', where)
  209. if not onwait:
  210. onwait = ''
  211. elif onwait == True:
  212. onwait = ''
  213. if Amsg['first'] == '!help':
  214. onwait = ''
  215. if Amsg['typ'] == 'groupchat':
  216. onwait = tra_help['groupchat']
  217. else:
  218. for typ in ['public']:
  219. onwait += tra_help[typ]['default'] + "\n"
  220. for key in list(tra_help[typ].keys()):
  221. if key not in PLUGINS.available_plugs:
  222. continue
  223. if PLUGINS.available_plugs[key]['Obj'] != False:
  224. onwait += tra_help[typ][key] + "\n"
  225. elif Amsg['first'] == '!h':
  226. onwait = ''
  227. if not Amsg['arg']:
  228. for typ in ['public']:
  229. for key in list(tra_help[typ].keys()):
  230. if key not in PLUGINS.available_plugs:
  231. continue
  232. if PLUGINS.available_plugs[key]['Obj'] != False:
  233. onwait += key + " "
  234. elif Amsg['arg'] in PLUGINS.available_plugs:
  235. if PLUGINS.available_plugs[Amsg['arg']]['Obj'] != False:
  236. for typ in ['public']:
  237. if Amsg['arg'] in tra_help[typ].keys():
  238. onwait += tra_help[typ][Amsg['arg']] + "\n"
  239. break
  240. return onwait
  241. def achange(self, nick, event):
  242. """ overwrite classManagePres,
  243. is call when a presence change """
  244. Amsg = {'text': None, 'typ': event, 'nick': nick,
  245. 'jid': None, 'pres': self.mypres,
  246. 'mynick': self.nick, 'arg': None, 'isforme': None,
  247. 'first': None, 'chan': self.name, 'chanhash': self.hash,
  248. 'from': None, 'conn': self.connected}
  249. self.plugcall(Amsg, 'pres', 'G')
  250. def unjoin(self):
  251. """ clean when going out """
  252. for plugue in list(PLUGINS.available_plugs.keys()):
  253. plug = PLUGINS.available_plugs[plugue]
  254. if plug['Obj'] != False:
  255. try:
  256. plug['Obj'].unjoin(self.name)
  257. except:
  258. print('fail unload ' + plugue)
  259. pass
  260. del self
  261. def start(self):
  262. """ start on join """
  263. self.OBC.start()