Pella86

Untitled

Aug 2nd, 2017
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.78 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2.  
  3. import time
  4. import telepot
  5. from telepot.loop import MessageLoop
  6. from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
  7.  
  8. from os.path import isfile, join, split, splitext
  9. from os import listdir
  10. import random
  11.  
  12. import pickle
  13.  
  14.  
  15.  
  16. bot_id = "BOT_TOKEN"
  17. bot_tag = "YOUR_@TAG"
  18. bot_help = "This bot is useless.\n I'm testing it and for now has:\n\n - /booty : booty pictures\n\n - /booty_rate : rate the pictures\n\n - /help : this message"
  19.  
  20. #==============================================================================
  21. # # Helper functions
  22. #==============================================================================
  23.  
  24. def get_pathname(path):
  25.     ''' Little function to split the path in path, name, extension'''
  26.     path, nameext = split(path)
  27.     name, ext = splitext(nameext)
  28.     return path, name, ext
  29.  
  30. def cut_path(path):
  31.     ''' This function takes a path and outputs the path cut with the ... after the
  32.     the first folder after the first character and completes the name with the filename or the last folder
  33.     '''      
  34.     endidx = 5
  35.     char = path[endidx]    
  36.     while char != '/' and endidx < len(path):
  37.         endidx += 1
  38.         char = path[endidx]
  39.        
  40.     inpath = path[:endidx + 1 ]
  41.    
  42.     rpath = path[::-1]    
  43.     idx = 1  
  44.     char = rpath[idx]    
  45.     while char != "/" and idx < len(rpath):
  46.         idx += 1
  47.         char = rpath[idx]
  48.  
  49.     endpath = path[len(path) - idx - 1 : ]
  50.    
  51.     outpath = inpath + "..." + endpath
  52.     return outpath
  53.  
  54.  
  55. #==============================================================================
  56. # # Messages classes
  57. #==============================================================================
  58.  
  59. class PersonName:
  60.    
  61.     def __init__(self, msg):
  62.         self.id = msg['id']
  63.         self.first_name = msg["first_name"]
  64.         self.username = None
  65.         self.language_code = None
  66.        
  67.         # optional arguments
  68.         try:
  69.             self.username = msg["username"]
  70.         except KeyError:
  71.             pass
  72.        
  73.         try:
  74.             self.language_code =  msg["language_code"]
  75.         except KeyError:
  76.             pass
  77.        
  78.     def info(self):
  79.         if len(self.first_name) > 13:
  80.             sname = self.first_name[:10] + "..."
  81.         else:
  82.             sname = self.first_name
  83.        
  84.         return "{0}(@{1})".format(sname, self.username)
  85.  
  86. class Chat:
  87.    
  88.     def __init__(self, chat):
  89.        
  90.         self.id = chat["id"]
  91.         self.type = chat["type"]
  92.        
  93.         if self.type == "private":
  94.             self.person = PersonName(chat)
  95.  
  96.         if self.type == "supergroup":
  97.             self.title = chat["title"]
  98.    
  99.     def info(self):
  100.         description = ""
  101.         if self.type == "supergroup":
  102.             description += self.title
  103.        
  104.         if self.type == "private":
  105.             description += self.person.info()
  106.            
  107.         return "{0} | {1}".format(self.type, description)
  108.  
  109.  
  110. class Photo:
  111.    
  112.     def __init__(self, photo):
  113.        
  114.         self.file_id = photo["file_id"]
  115.         self.file_size = photo.get("file_size")
  116.         self.width = photo["width"]
  117.         self.height = photo["height"]
  118.        
  119.         self.file_path = None
  120.        
  121.         try:
  122.             self.file_path = photo["file_path"]
  123.         except KeyError:
  124.             pass
  125.        
  126.  
  127. class Message:
  128.    
  129.     def __init__(self, msg):
  130.        
  131.         content_type, chat_type, chat_id = telepot.glance(msg)
  132.        
  133.         self.original = msg
  134.        
  135.         self.message_id = msg["message_id"]
  136.         self.mfrom = PersonName(msg["from"])
  137.         self.chat = Chat(msg["chat"])
  138.         self.date = msg["date"]
  139.         self.content_type = content_type
  140.        
  141.         self.text = None
  142.         self.photo = None
  143.         self.reply = None
  144.        
  145.         if self.content_type == "text":
  146.             self.text = msg["text"]
  147.         if self.content_type == "photo":
  148.             self.photo = [ Photo(pic) for pic in msg["photo"] ]
  149.            
  150.         try:
  151.            self.reply = Message(msg["reply_to_message"])
  152.         except KeyError:
  153.             pass
  154.    
  155.     def info(self):
  156.         return "Message ({0}) from: {1}\nin chat: {2}".format(
  157.                 self.content_type,
  158.                 self.mfrom.info(),
  159.                 self.chat.info()
  160.                 )
  161.    
  162.     def print_message(self):
  163.         if self.content_type == "text":
  164.             print(self.text)
  165.         else:
  166.             print("message content not supported")
  167.  
  168. #==============================================================================
  169. # Define the databases
  170. #==============================================================================
  171.    
  172. class ChatDatabase:
  173.    
  174.     filepath = "./data/chatdb.txt"
  175.    
  176.     def __init__(self):
  177.         # create a database for the chat ids
  178.         self.db = []
  179.         self.previous_db = []
  180.  
  181.         # create a file where to store the chat ids
  182.         self.loadChats()
  183.    
  184.     def addChat(self, chatid):
  185.         self.db.append(chatid)
  186.    
  187.     def isNew(self, chatid):
  188.         if chatid not in self.db:
  189.             return True
  190.         else:
  191.             return False
  192.    
  193.     def getChat(self, chatid):
  194.         for chat in self.db:
  195.             if chat == chatid:
  196.                 return chat
  197.    
  198.     def loadChats(self):
  199.         try:
  200.             with open(self.filepath, "r") as f:
  201.                 s = f.readlines()
  202.            
  203.             self.db = []
  204.             for line in s:
  205.                 if line != '\n':
  206.                     self.db.append(int(line[:-1]))
  207.                     self.previous_db.append(int(line[:-1]))
  208.             print("Successfully imported: ", len(self.previous_db), "chats id")
  209.         except IOError:
  210.             print("Chat Database file not available")
  211.             pass
  212.         except Exception as e:
  213.             print(e)
  214.             raise e
  215.        
  216.     def writeChats(self):
  217.         for chat in self.db:
  218.             if chat not in self.previous_db:
  219.                 with open(self.filepath, "a") as f:
  220.                     f.write(str(chat) + "\n")
  221.                     self.previous_db.append(chat)
  222.  
  223.  
  224. class UsersDb:
  225.    
  226.     def __init__(self):      
  227.         pass
  228.        
  229.  
  230. class ImagesDB:
  231.    
  232.     filepath = "./data/images_db.txt"
  233.    
  234.     def __init__(self):
  235.         # create a database for the chat ids
  236.         self.db = {}
  237.         self.previous_db = []
  238.  
  239.         # create a file where to store the chat ids
  240.         self.loadPics()
  241.    
  242.     def addPathPic(self, path, picid):
  243.         self.db[path] = picid
  244.    
  245.     def isNew(self, path):
  246.        
  247.         if path not in self.db.keys():
  248.             print("New Path found:", path)
  249.             return True
  250.         else:
  251.             print(path, "already in database")
  252.             return False
  253.    
  254.     def getPicId(self, path):
  255.         return self.db[path]
  256.    
  257.     def loadPics(self):
  258.         try:
  259.             with open(self.filepath, "r") as f:
  260.                 s = f.readlines()
  261.            
  262.             self.db = {}
  263.             for line in s:
  264.                 if line != '\n':
  265.                     sp = line[:-1].split("-:-")
  266.                     path = sp[0]
  267.                     picid = sp[1]
  268.                    
  269.                     self.db[path] = picid
  270.                     self.previous_db.append(path)
  271.             print("Successfully imported: ", len(self.previous_db), "images id or path")
  272.         except IOError:
  273.             print("Images database not yet available")
  274.             pass
  275.         except Exception as e:
  276.             print(e)
  277.             raise e
  278.        
  279.     def writePics(self):
  280.         for path, picid in self.db.items():
  281.             if path not in self.previous_db:
  282.                 with open(self.filepath, "a") as f:
  283.                     f.write(path + "-:-" + picid + "\n")  
  284.                     self.previous_db.append(path)
  285.  
  286.  
  287.  
  288. class ImageFolder:
  289.    
  290.     def __init__(self, path):
  291.        
  292.         self.path = path
  293.         self.pictures = []
  294.         self.gatherPictures()
  295.    
  296.     def gatherPictures(self):
  297.         # for now gather all the files, next check for picture extensions
  298.         p = self.path
  299.         names = [f for f in listdir(p) if isfile(join(p, f))]
  300.            
  301.         for imgname in names:
  302.             path, name, ext = get_pathname(imgname)
  303.             if ext in ['.jpg', '.png']:
  304.                 imagepath = join(self.path, imgname)
  305.                 self.pictures.append(imagepath)
  306.    
  307.     def getPicture(self, idx):
  308.         return self.pictures[idx]
  309.    
  310.     def getSize(self):
  311.         return len(self.pictures)
  312.  
  313. class InlineDatabase:
  314.    
  315.     def __init__(self):
  316.         self.db = []
  317.    
  318.     def isNew(self, message):
  319.         if (message.chat.id, message.message_id) in self.db:
  320.             return False
  321.         else:
  322.             return True
  323.    
  324.     def add(self, message):
  325.         self.db.append((message.chat.id, message.message_id))
  326.    
  327. indb = InlineDatabase()
  328.  
  329. class VotePicture:
  330.     def __init__(self, path):
  331.         #path of pic
  332.         self.path = path
  333.         self.id = None
  334.        
  335.         # list of who voted
  336.         self.voterids = []
  337.        
  338.         # count
  339.         self.upvote = 0
  340.         self.downvote = 0
  341.        
  342.         # message ids
  343.         self.creation_message_ids = []
  344.        
  345.        
  346.    
  347.     def addVoterId(self, voterid):
  348.         print("Adding:", voterid)
  349.         self.voterids.append(voterid)
  350.    
  351.     def addCreationMessage(self, msg):
  352.         self.creation_message_ids.append((msg.chat.id, msg.message_id))
  353.    
  354.     def hasVoted(self, voterid):
  355.         if voterid in self.voterids:
  356.             return True
  357.         return False
  358.    
  359.     def upCountUp(self):
  360.         self.count += 1
  361.    
  362.     def downCountUp(self):
  363.         self.downvote += 1
  364.    
  365.     def getScore(self):
  366.         return "u {0}|{1} d".format(self.upvote, self.downvote)
  367.    
  368.     def getScoreEmoji(self):
  369.         return "👍 {0} | {1} 👎 ".format(self.upvote, self.downvote)
  370.        
  371.        
  372. class VoteDB:
  373.  
  374.     def __init__(self):
  375.         self.dbfolder = "./data/votepics/"
  376.         self.votepicturesdb = []
  377.         self.imgcount = 0
  378.        
  379.         self.load_database()
  380.    
  381.     def add(self, votepicture):
  382.        
  383.         self.imgcount += 1
  384.         votepicture.id = self.imgcount
  385.         self.votepicturesdb.append(votepicture)
  386.         self.update_database()
  387.    
  388.    
  389.     def isNew(self, votepicture):
  390.         if type(votepicture) is VotePicture:
  391.             if votepicture.id in [pic.id for pic in self.votepicturesdb]:
  392.                 return False
  393.             return True
  394.        
  395.         if type(votepicture) is str:
  396.             if votepicture in [pic.path for pic in self.votepicturesdb]:
  397.                 return False
  398.             return True
  399.    
  400.     def get_id_to_picvote(self, picvoteid):
  401.         for picvote in self.votepicturesdb:
  402.             if picvote.id == picvoteid:
  403.                 return picvote
  404.         print("id not found")
  405.    
  406.     def get_file_to_picture(self, file):
  407.        
  408.         for pic in self.votepicturesdb:
  409.             if pic.path == file:
  410.                 return pic
  411.         print("path not found")
  412.  
  413.     def dump_picture(self, picture):
  414.         path, name, ext = get_pathname(picture.path)
  415.         filename = self.dbfolder + name + ".pickle"
  416.         with open(filename, 'wb') as f:
  417.             pickle.dump(picture, f)
  418.    
  419.     def load_picture(self, filename):
  420.         path, name, ext = get_pathname(filename)
  421.         if isfile(filename) and ext == ".pickle":
  422.             with open(filename, 'rb') as f:
  423.                 data = pickle.load(f)
  424.             return data
  425.         return None
  426.            
  427.     def update_database(self):
  428.         for picture in self.votepicturesdb:
  429.             self.dump_picture(picture)
  430.    
  431.     def load_database(self):
  432.         names = [join(self.dbfolder, f) for f in listdir(self.dbfolder)]
  433.        
  434.         tmp_db = []
  435.         c = 0
  436.         for name in names:
  437.             pic = self.load_picture(name)
  438.             if pic is not None:
  439.                 tmp_db.append(pic)
  440.                 c += 1
  441.            
  442.         print("Loaded", c, "votepictures")
  443.        
  444.         print("clear previous database and Assign new stuff")
  445.         self.votepicturesdb = tmp_db
  446.    
  447.     def showScores(self):
  448.         for image in self.votepicturesdb:
  449.             _, name, ext = get_pathname(image.path)
  450.             print("{0}: {1}".format(name+ext, image.getScore()))
  451.  
  452.  
  453. def handle(msg):
  454.  
  455.     print("-------------------\n NEW MESSAGE \n-------------------")
  456.     m = Message(msg)
  457.    
  458.     print(m.info())
  459.    
  460.     if cdb.isNew(m.chat.id):
  461.         print("New chat", m.chat.id)
  462.         cdb.addChat(m.chat.id)
  463.         bot.sendMessage(m.chat.id, "HELLO I'm a goddamn fucking bot")
  464.         bot.sendMessage(m.chat.id, bot_help)
  465.         cdb.writeChats()
  466.        
  467.     if m.reply is not None:
  468.         print("found a reply")
  469.         if m.reply.mfrom.id == bot_id:
  470.             if m.reply.content_type == "text":
  471.                 bot.editMessageText((m.reply.chat.id, m.reply.message_id), m.reply.text + " PROOOT!")
  472.        
  473.     if m.content_type == "text":
  474.         print("text message detected")
  475.         print("'{0}'".format(str(m.text)))
  476.        
  477.  
  478.         # commands
  479.         if m.text == "/booty" or m.text == "/booty" + bot_tag:  
  480.            
  481.             # chose a picture from the folder random from it
  482.             file_idx = int(random.uniform(0, imgbooty.getSize()))
  483.             file = imgbooty.getPicture(file_idx)
  484.            
  485.             if idb.isNew(file):
  486.                
  487.                 bot.sendMessage(m.chat.id, "loading...")
  488.                
  489.                 # read from folder
  490.                 f = open(file, 'rb')
  491.                 r = bot.sendPhoto(m.chat.id, f)
  492.                
  493.                 # store the picture id and hashmap to file
  494.                 rm = Message(r)
  495.                 idb.addPathPic(file, rm.photo[0].file_id)
  496.                
  497.                 #update database
  498.                 idb.writePics()
  499.                
  500.            
  501.            
  502.             picmessage = "Image {0} of {1}".format(file_idx + 1, imgbooty.getSize())
  503.            
  504.             print(picmessage)
  505.            
  506.             pic = vdb.get_file_to_picture(file)
  507.             if pic is not None:
  508.                 caption = picmessage + "\nScore: " + pic.getScoreEmoji() + "\nTo vote use /booty_rate"
  509.             else:
  510.                 caption = picmessage + "\nNobody voted yet "
  511.                
  512.             bot.sendPhoto(m.chat.id, idb.getPicId(file), caption = caption)
  513.            
  514.             # add in description?
  515.                
  516.            
  517.            
  518.         elif m.text == "/inline":
  519.             # inline test
  520.             keyboard = InlineKeyboardMarkup(inline_keyboard=[
  521.                     [InlineKeyboardButton(text='Press me', callback_data='press')],
  522.                     [InlineKeyboardButton(text='like me', callback_data='like')]
  523.                     ])
  524.            
  525.             c_m = bot.sendMessage(m.chat.id, 'Use inline keyboard', reply_markup=keyboard)
  526.            
  527.             creation_m = Message(c_m)
  528.            
  529.             if indb.isNew(creation_m):
  530.                 indb.add(creation_m)
  531.                 print(len(indb.db))
  532.  
  533.         elif m.text == "/booty_rate" or m.text == "/booty_rate" + bot_tag:
  534.             # get the picture
  535.             image_voted_already = True
  536.             trials = 0
  537.             while image_voted_already and trials <= len(vdb.votepicturesdb):
  538.                 file_idx = int(random.uniform(0, imgbooty.getSize()))
  539.                 file = imgbooty.getPicture(file_idx)
  540.    
  541.                 if idb.isNew(file):
  542.                     bot.sendMessage(m.chat.id, "loading...")
  543.                     f = open(file, 'rb')
  544.                     r = bot.sendPhoto(m.chat.id, f)
  545.                     rm = Message(r)
  546.                     idb.addPathPic(file, rm.photo[0].file_id)
  547.                     idb.writePics()
  548.                
  549.                 if vdb.isNew(file):
  550.                     picture = VotePicture(file)
  551.                     vdb.add(picture)
  552.                 else:
  553.                     picture = vdb.get_file_to_picture(file)
  554.                
  555.                 # check if the person requesting the command has already voted
  556.                 if m.mfrom.id in picture.voterids:
  557.                     image_voted_already = True
  558.                     trials += 1
  559.                     print(trials)
  560.                 else:
  561.                     image_voted_already = False
  562.                    
  563.            
  564.             if image_voted_already == True and m.chat.type == "private":
  565.                 bot.sendMessage(m.chat.id, "You voted all the pictueres.\nNew one will come in the next updates\nUse /booty for results")
  566.             else:
  567.                 keyboard = InlineKeyboardMarkup(inline_keyboard=[
  568.                         [InlineKeyboardButton(text='like 👍 - ' + str(picture.upvote),
  569.                                               callback_data='brlike_' + str(picture.id))],
  570.                         [InlineKeyboardButton(text='dislike 👎 - '+ str(picture.downvote),
  571.                                               callback_data='brdislike_' + str(picture.id))]
  572.                         ])
  573.                
  574.                 if idb.isNew(file):
  575.                     bot.sendMessage(m.chat.id, "loading...")
  576.                     f = open(file, 'rb')
  577.                     c_m = bot.sendPhoto(m.chat.id, f, reply_markup=keyboard)
  578.                    
  579.                     idb.addPathPic(file, c_m.photo[0].file_id)
  580.                     idb.writePics()
  581.                
  582.                 else:
  583.                     c_m = bot.sendPhoto(m.chat.id, idb.getPicId(picture.path), reply_markup=keyboard)
  584.                    
  585.                 creation_m = Message(c_m)
  586.                 picture.addCreationMessage(creation_m)  
  587.                
  588.         elif m.text == "/help" or m.text == "/help" + bot_tag:
  589.             bot.sendMessage(m.chat.id, bot_help)
  590.         else:
  591.             if m.chat.type == "private":
  592.                 bot.sendMessage(m.chat.id, m.text + " prot!")
  593.     else:
  594.         print("message content not supported")
  595.  
  596. def query(msg):
  597.     print("-------------------\n NEW QUERY \n-------------------")
  598.    
  599.     query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
  600.     print('Callback Query:', query_id, from_id, query_data)
  601.    
  602.     if query_data == "press":
  603.         keyboard = InlineKeyboardMarkup(inline_keyboard=[
  604.                 [InlineKeyboardButton(text='Press me - edited', callback_data='press')],
  605.                 [InlineKeyboardButton(text='like me - edided', callback_data='like')]
  606.                 ])        
  607.         for cmid in indb.db:
  608.             bot.editMessageReplyMarkup(cmid, keyboard)
  609.        
  610.         bot.answerCallbackQuery(query_id, text='Got it')
  611.     if query_data == "like":
  612.         bot.answerCallbackQuery(query_id, text='Liked it')
  613.    
  614.     if query_data == "bootyrate_like":
  615.         print("Like")
  616.     elif query_data == "bootyrate_dislike":
  617.         print("Dislike")
  618.    
  619.     if query_data.startswith("br"):
  620.         s = query_data.split('_')
  621.         picid = int(s[1])
  622.        
  623.         pic = vdb.get_id_to_picvote(picid)
  624.        
  625.         print(pic.voterids)
  626.        
  627.         if pic.hasVoted(from_id):
  628.             print("Already voted")
  629.             return None
  630.         else:
  631.             pic.addVoterId(from_id)
  632.            
  633.         if query_data.startswith("brlike"):
  634.             pic.upvote += 1
  635.        
  636.             #the picture
  637.             print("The picture:", pic.path, "has received an upvote")
  638.             print("total count:", pic.upvote)
  639.        
  640.         if query_data.startswith("brdislike"):
  641.             pic.downvote += 1
  642.        
  643.             #the picture
  644.             print("The picture:", pic.path, "has received a downvote")
  645.             print("total count:", pic.downvote)
  646.        
  647.         # rested the inline keyboard
  648.         keyboard = InlineKeyboardMarkup(inline_keyboard=[
  649.                     [InlineKeyboardButton(text='like 👍 - ' + str(pic.upvote),
  650.                                           callback_data='brlike_' + str(pic.id))],
  651.                     [InlineKeyboardButton(text='dislike 👎 - '+ str(pic.downvote),
  652.                                           callback_data='brdislike_' + str(pic.id))]
  653.                     ])
  654.         print("Updating database...")
  655.         vdb.update_database()
  656.        
  657.         for cmid in pic.creation_message_ids:
  658.             bot.editMessageReplyMarkup(cmid, keyboard)  
  659.    
  660.  
  661.  
  662. idb = ImagesDB()
  663.  
  664. imgbooty = ImageFolder("./data/booty/pic/")
  665.  
  666. cdb = ChatDatabase()
  667. vdb = VoteDB()        
  668.  
  669.  
  670. MessageLoop(bot,{'chat': handle,
  671.                  'callback_query': query}).run_as_thread()
  672. print ('Listening ...')
  673.  
  674. # Keep the program running.
  675. while 1:
  676.     time.sleep(10)
Advertisement
Add Comment
Please, Sign In to add comment