· 6 years ago · Mar 26, 2019, 02:36 AM
1#! /usr/bin/python3
2
3#modules i'm using
4import praw #python wrapper for the reddit api, lets you connect to the site
5import obot #keeps authorization keys in a separate file for privacy
6import sqlite3 #database
7import random #does math stuff
8
9#variables to use below that i might want to change
10USER = 'ladymouth'
11DATABASE = 'ladymouth.db' #do i need to make this a fixed path so that the files match up?
12SUBREDDIT = 'Masculism' #'MensRights+TheRedPill+Masculism' +etc
13# NEW PROBLEM: Many terms will be subreddit specific, how to target the database repeatedly VS more random?
14WAIT = 600
15LIMIT = 200
16KEYWORD = ''
17
18# authentication
19r = obot.login()
20
21class SQLmanager():
22 def __init__(self, db):
23 self.conn = sqlite3.connect(db)
24 self.cur = self.conn.cursor()
25
26 def query(self, *args):
27 self.cur.execute(*args)
28 self.conn.commit()
29 return self.cur
30
31 def close(self): #where to close / __exit__ __del__ (with statement?)
32 self.conn.close()
33
34
35class Quote():
36 def __init__(self, quoteID, author, body, tag):
37 self.qid = quoteID
38 self.author = author
39 self.body = body
40 self.tag = tag
41
42 @staticmethod
43 def pick_random():
44 global q
45 query = "SELECT * FROM quotations ORDER BY RANDOM() LIMIT 1"
46 for row in sql.query(query):
47 quoteID, author, body, tag = row #assigns sql output to the variables to pass to the class
48 q = Quote(quoteID, author, body, tag) #sends variables to create object from class
49 #should all these be separated into their own method?
50 return q
51
52 @staticmethod
53 def pick_tag(tag):
54 global q
55 query = "SELECT * from quotations WHERE tag=?"
56 for row in sql.query(query, (tag,)):
57 quoteID, author, body, tag = row #replace with ??? Quote.map_variables()
58 q = Quote(quoteID, author, body, tag) #sends variables to create object from class
59 return q
60
61 @staticmethod
62 def pick_ID(quoteID):
63 global q
64 query = "SELECT * FROM quotations WHERE quoteID=?"
65 for row in sql.query(query, (quoteID,)):
66 quoteID, author, body, tag = row
67 q = Quote(quoteID, author, body, tag)
68 return q
69
70 #create a method that finds the last posted reply, pulls the next quoteID from it.
71 @staticmethod
72 def findlastused():
73 query = "SELECT quoteID FROM replied ORDER BY quoteID DESC LIMIT 1;"
74 for row in sql.query(query):
75 lastID = row #NEED TO REMOVE FROM TUPLE HERE
76 quoteID = int(lastID) + 1
77 Quote.pickID(quoteID)
78
79 def display(self):
80 print(self.body + ' (' + self.tag + ')')
81
82''' @staticmethod
83 def map_variables():
84 global q
85 row = pick_tag
86 #should all these be separated into their own method?
87 quoteID, author, body, tag = row #assigns sql output to the variables to pass to the class
88 q = Quote(quoteID, author, body, tag) #sends variables to create object from class
89 return q'''
90
91
92class Post():
93 def __init__(self, pid, author, body, q):
94 self.pid = pid
95 self.author = author
96 self.body = body
97 self.q = q #binds the quote object to the post
98 self.reply = self.q.body + ' -' + self.q.author
99
100 def display(self):
101 print(self.author + ' says: ' + self.body)
102 print('Would reply: ' + self.reply)
103
104 @staticmethod
105 def get():
106 #make posts global to save the string and not have to redo the search?
107 posts = r.get_subreddit(SUBREDDIT).get_comments(limit = LIMIT)
108 posts = praw.helpers.flatten_tree(posts)
109 return posts
110
111 # HOW TO RETURN MORE THAN ONE MATCH??????
112 @staticmethod
113 def match_random(q):
114 global match
115 posts = Post.get()
116 tag = q.tag
117 matches = [post for post in posts if tag.lower() in post.body.lower()]
118 if matches: #to make multiple: for match in matches, try reply_with
119 match = random.choice(matches)
120 Post.create(match)
121 return match
122 else:
123 print('No matches found. Try again.')
124 exit() #kill program here or try again?
125 # would this be in a while loop? ADD A HANDLER
126 #Quote.pick_random()
127 #Post.match_random(q)
128
129 #trying a new version that breaks up the steps into separate functions, tries returning multiple matches
130 @staticmethod
131 def match(q):
132 posts = Post.get()
133 tag = q.tag
134 matches = [post for post in posts if tag.lower() in post.body.lower()]
135 return matches
136
137 @staticmethod
138 def try_all():
139 matches = Post.match(q)
140 matchlist = list()
141 if matches:
142 for match in matches: #try reply with and log
143 item = Post.create(match) #won't this just write over each version?, make a list of variables here to assign to each, or dispense with objects altogether
144 matchlist.append(item) #how to assign different names to each
145 return False
146 else: #how to rerun, put in while loop instead?
147 '''Quote.pick_random()
148 q.display()
149 Post.try_all()'''
150 return True
151
152 @staticmethod
153 def create(m):
154 global p
155 pid = str(m.id)
156 author = str(m.author)
157 body = str(m.body)
158 p = Post(pid, author, body, q)
159 return p
160
161 def check(self):
162 sql.query("CREATE TABLE IF NOT EXISTS replied(pid TEXT, author TEXT, body TEXT, quoteID INTEGER)")
163 query = "SELECT * FROM replied WHERE pid=?"
164 sql.query(query, (self.pid,))
165 already = sql.cur.fetchone()
166 if already:
167 print('Already replied to this post.')
168 return True
169 else:
170 #print('Could reply.')
171 return False
172
173 def reply_with(self):
174 if (self.check() is False) and (self.author != USER): #checks that author is not bot--does this work?
175 try:
176 #UNCOMMENT TO GO LIVE
177 #match.reply(self.reply)
178 print('REPLIED: ' + self.reply)
179 print('TO THIS POST: ' + str(match.body)) #check
180 #log post -- UNCOMMENT TO GO LIVE
181 #try:
182 #self.log()
183 #except:
184 #print('Replied but could not log.')
185 except:
186 print('Could not reply.')
187 else:
188 print('Already replied or self-reply')
189
190 def log(self):
191 try:
192 ins = "INSERT INTO replied (pid, author, body, quoteID) VALUES(?, ?, ?, ?)"
193 sql.query(ins, (self.pid, self.author, self.body, self.q.qid))
194 print('Logged post in "replied"')
195 except:
196 print('Something went wrong. Post not logged.')
197
198
199'''class Submission(Post):
200 @staticmethod
201 def get():
202 posts = r.get_subreddit(SUBREDDIT).get_new(limit = LIMIT)
203 return posts
204 @staticmethod
205 def search(tag): #tag, how to get this worked in? what's being passed into it?
206 # how to call in the inherited class rather than override it. super().__init__(self)
207 posts = r.search(tag, subreddit=SUBREDDIT, sort=u'new', limit=LIMIT)
208 return posts
209 def read():
210 print([post.selftext for post in posts])
211 def __eq__(self, tag):
212 return self.body.lower() == tag.lower()
213'''
214
215class Response(Post):
216 def __init__(self, pid, author, body, botid):
217 self.pid = pid
218 self.author = author
219 self.body = body
220 self.botid = botid #binds the response to the bot's post
221
222 @staticmethod
223 def get_bot_posts():
224 global responses
225 posts = r.get_redditor(USER).get_comments(sort=u'new')
226 refreshed = [post.refresh() for post in posts]
227 return refreshed
228
229 @staticmethod
230 def get_replies():
231 resps = []
232 refreshed = Response.get_bot_posts()
233 for post in refreshed:
234 #print(str(post.replies)) #THIS WORKED because it was trying to read blanks before
235 resps += post.replies
236 return resps
237
238 @staticmethod
239 def create(resp):
240 global b
241 pid = str(resp.id)
242 author = str(resp.author)
243 body = str(resp.body)
244 botid = str(resp.parent_id)
245 b = Response(pid, author, body, botid)
246 return b
247
248 @staticmethod
249 def check(rid):
250 sql.query("CREATE TABLE IF NOT EXISTS responses(pid TEXT, author TEXT, body TEXT, botid TEXT)") #responseto = pid/ botID from replied table
251 query = "SELECT * FROM responses WHERE pid=?"
252 #sql.query(query, (self.pid,))
253 sql.query(query, (rid,)) #can i do this check before making an object?
254 already = sql.cur.fetchone()
255 if already:
256 print('Already logged.')
257 return True
258 else:
259 print('New response to be logged.')
260 return False
261
262 #WORKS NOW comments in response to bot's posts, logs bot's comment id and pulls all responses to that id <<see comment.refresh() before comment.replies()>>
263 @staticmethod
264 def log():
265 resps = Response.get_replies()
266 for resp in resps:
267 if Response.check(str(resp.id)) == True:
268 continue
269 else:
270 #print(str(resp.id)) #bugcheck
271 #print(str(resp.author)) #bugcheck
272 #print(str(resp.parent_id)) #bugcheck
273 pid = str(resp.id)
274 author = str(resp.author)
275 body = str(resp.body)
276 botid = str(resp.parent_id)
277 ins = "INSERT INTO responses (pid, author, body, botid) VALUES(?, ?, ?, ?)"
278 sql.query(ins, (pid, author, body, botid))
279 print('Logged response')
280
281# PROGRAM RUNS HERE
282
283sql = SQLmanager(DATABASE) #needs close statement or with?
284
285#Quote.pick_random() #yields a random quote (q) // #Quote.pick_tag(KEYWORD) #yields a specific quote (q)
286#q.display() #bugcheck
287#Post.match_random(q) #yields a matching post (p)
288#p.reply_with()
289
290Quote.findlastused()
291
292#Response.log() #checks for new responses to bot
293
294sql.close()