Posted By

aruseni on 05/03/13


Tagged

python bot comments livejournal feedparser mechanize


Versions (?)

LJAutoComment


 / Published in: Python
 

This class is used to automatically update a LiveJournal blog’s RSS feed, detect new entries and post a comment if the entry is new enough (i.e. is posted in a given period of time from now, for example not older than 1 hour)

Example:

comment = u"Первый комментарий."

engine = LJAutoComment('http://asena.livejournal.com/data/rss', 'user', 'password', comment, 1)
engine()
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # code by andrewkolesnikov.com
  4. # edited by aruseni.alwaysdata.net
  5.  
  6. import re
  7. import sys
  8. import time
  9. import feedparser
  10. import logging
  11. from datetime import datetime
  12. from mechanize import Browser
  13.  
  14. class LJAutoComment:
  15. def __init__(self, url = '', username = '', password = '', comment = '', age_threshold = 0.5, interval= 5, logLevel = logging.DEBUG):
  16. self.__dry = False
  17. self.__url = url
  18. self.__comment = comment
  19. self.__username = username
  20. self.__password = password
  21. self.__age_threshold = age_threshold
  22. self.__log_filename = '/tmp/posts_' + self.__slugify(url)
  23. self.__interval = interval
  24. logging.basicConfig(level=logLevel)
  25.  
  26. def __call__(self, dry = False):
  27. self.__dry = dry
  28. if self.__dry:
  29. logging.info('Dry-run. Comments will not be posted.')
  30.  
  31. logging.info('Fetching RSS feed: ' + self.__url);
  32. while True:
  33. self.__feed = feedparser.parse(self.__url)
  34. if not self.__feed.entries:
  35. logging.error('Couldn’t fetch the RSS feed from %s', self.__url)
  36. entry = self.__feed.entries[0]
  37.  
  38. logging.info('Latest entry is: ' + entry.get('title', "(Untitled)"));
  39.  
  40. if self.is_commentable(entry):
  41. logging.info('Entry is commentable.');
  42. self.post_comment(entry, self.__comment)
  43. self.log_write(entry.link)
  44. else:
  45. logging.info('Entry isn’t commentable. Skipping…');
  46.  
  47. logging.info('Sleeping for %d seconds.', self.__interval);
  48. time.sleep(self.__interval)
  49. logging.info('Done.');
  50.  
  51. def is_commentable(self, entry):
  52. postedHoursAgo = (time.mktime(time.gmtime()) - time.mktime(entry.updated_parsed)) / 3600
  53.  
  54. logging.info('Entry posted %f hours ago, threshold is %1.2f hours', postedHoursAgo, self.__age_threshold);
  55.  
  56. alreadyCommented = self.log_check(entry.link);
  57. if alreadyCommented:
  58. logging.info('Already commented on this entry.');
  59.  
  60. if (postedHoursAgo < self.__age_threshold) and not alreadyCommented:
  61. return True
  62. return False
  63.  
  64. def post_comment(self, entry, comment):
  65. br = Browser()
  66.  
  67. br.addheaders = [
  68. ('User-agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0'),
  69. ]
  70.  
  71. logging.info('Logging in…')
  72.  
  73. br.open("https://www.livejournal.com/login.bml")
  74.  
  75. br.select_form(nr=0)
  76. br['user'] = self.__username
  77. br['password'] = self.__password
  78.  
  79. br.submit()
  80.  
  81. br.open('%s?mode=reply' % entry.link)
  82.  
  83. formcount=0
  84. for frm in br.forms():
  85. if str(frm.attrs.get("id", "")) == "postform":
  86. break
  87. formcount=formcount+1
  88. br.select_form(nr=formcount)
  89.  
  90. br['body'] = comment.encode('utf8')
  91.  
  92. if not self.__dry:
  93. logging.info('Posting the comment…')
  94. br.submit()
  95. else:
  96. logging.info('Pretending to be posting the comment… (dry run)')
  97.  
  98. def log_check(self, link):
  99. """docstring for log_check"""
  100. try:
  101. log = open(self.__log_filename, 'r+')
  102. line = 1
  103. while line:
  104. line = log.readline()
  105. logging.debug('Checking link: %s against %s', link, line);
  106. if line.find(link) >= 0:
  107. log.close()
  108. return True;
  109. log.close()
  110. except Exception, e:
  111. pass
  112. return False
  113.  
  114. def log_write(self, link):
  115. """docstring for log_write"""
  116. logging.debug('Writing link: %s to %s', link, self.__log_filename);
  117. log = open(self.__log_filename, 'w+')
  118. log.write(link)
  119. log.close()
  120.  
  121. def __slugify(self, inStr):
  122. removelist = ["a", "an", "as", "at", "before", "but", "by", "for","from","is", "in", "into", "like", "of", "off", "on", "onto","per","since", "than", "the", "this", "that", "to", "up", "via","with"];
  123. for a in removelist:
  124. aslug = re.sub(r'\b'+a+r'\b','',inStr)
  125. aslug = re.sub('[^\w\s-]', '', aslug).strip().lower()
  126. aslug = re.sub('\s+', '-', aslug)
  127. return aslug

Report this snippet  

Comments

RSS Icon Subscribe to comments
Posted By: aruseni on May 3, 2013

Based on this snippet.

You need to login to post a comment.