Posted By

andrewkolesnikov on 03/02/10


Tagged

python bot comments livejournal


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

andrewkolesnikov


LiveJournal auto post comments


 / Published in: Python
 

This code allows automatically posting comments to LiveJournal to be the first commenter.

Usage: $ python auto-post-comment.py

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # code by andrewkolesnikov.com
  4. import re
  5. import sys
  6. import time
  7. import random
  8. import feedparser
  9. import logging
  10. from datetime import datetime
  11. from mechanize import Browser
  12.  
  13. class LJAutoComment:
  14. def __init__(self, url = 'http://tema.livejournal.com/data/rss', username = '', password = '', comments = [], age_threshold = 0.5, interval= 5, logLevel = logging.DEBUG):
  15. self.__dry = False
  16. self.__url = url
  17. self.__comments = comments
  18. self.__username = username
  19. self.__password = password
  20. self.__age_threshold = age_threshold
  21. self.__log_filename = '/tmp/posts_' + self.__slugify(url)
  22. self.__interval = interval
  23. logging.basicConfig(level=logLevel)
  24.  
  25. def generate_comment(self, entry):
  26. comment = random.choice(self.__comments);
  27. theID = re.match(r"\D*(\d*).*", entry.link).group(1);
  28. return comment + (' <img src="http://andrewkolesnikov.com/img/%s.jpg" >' % int(theID))
  29.  
  30. def __call__(self, dry = False):
  31. self.__dry = dry
  32. if self.__dry:
  33. logging.info('Dry-run. Comments will not be posted.')
  34.  
  35. logging.info('Fetching RSS feed: ' + self.__url);
  36. while True:
  37. self.__feed = feedparser.parse(self.__url)
  38. entry = self.__feed.entries[0]
  39. if not entry:
  40. logging.error('Couldn\'t fetch the RSS feed from %s', self.__url)
  41.  
  42. logging.info('Latest entry is: ' + entry['title']);
  43.  
  44. if self.is_commentable(entry):
  45. logging.info('Entry is commentable.');
  46. self.post_comment(entry, self.generate_comment(entry))
  47. self.log_write(entry.link)
  48. else:
  49. logging.info('Entry isn\'t commentable. Skipping..');
  50.  
  51. logging.info('Sleeping for %d seconds.', self.__interval);
  52. time.sleep(self.__interval)
  53. logging.info('Done.');
  54.  
  55. def is_commentable(self, entry):
  56. postedHoursAgo = (time.mktime(time.gmtime()) - time.mktime(entry.updated_parsed)) / 3600
  57.  
  58. logging.info('Entry posted %f hours ago, threshold is %1.2f hours', postedHoursAgo, self.__age_threshold);
  59.  
  60. alreadyCommented = self.log_check(entry.link);
  61. if alreadyCommented:
  62. logging.info('Already commented on this entry.');
  63.  
  64. if (postedHoursAgo < self.__age_threshold) and not alreadyCommented:
  65. return True
  66. return False
  67.  
  68. def post_comment(self, entry, comment):
  69. br = Browser()
  70. br.open(entry.link + '?mode=reply')
  71. br.select_form(nr=0)
  72. br['usertype'] = ['user']
  73. br['userpost'] = self.__username
  74. br['password'] = self.__password
  75. br['body'] = comment.encode('utf8');
  76.  
  77. if not self.__dry:
  78. logging.info('Posting the comment..')
  79. br.submit()
  80. print br.response()
  81. else:
  82. logging.info('Pretending to be posting the comment.. (dry run)')
  83.  
  84. def log_check(self, link):
  85. """docstring for log_check"""
  86. try:
  87. log = open(self.__log_filename, 'r+')
  88. line = 1
  89. while line:
  90. line = log.readline()
  91. logging.debug('Checking link: %s against %s', link, line);
  92. if line.find(link) >= 0:
  93. log.close()
  94. return True;
  95. log.close()
  96. except Exception, e:
  97. pass
  98. return False
  99.  
  100. def log_write(self, link):
  101. """docstring for log_write"""
  102. logging.debug('Writing link: %s to %s', link, self.__log_filename);
  103. log = open(self.__log_filename, 'w+')
  104. log.write(link + "
  105. ")
  106. log.close()
  107.  
  108. def __slugify(self, inStr):
  109. 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"];
  110. for a in removelist:
  111. aslug = re.sub(r'\b'+a+r'\b','',inStr)
  112. aslug = re.sub('[^\w\s-]', '', aslug).strip().lower()
  113. aslug = re.sub('\s+', '-', aslug)
  114. return aslug
  115.  
  116. if __name__ == '__main__':
  117. comments = [u'я подумал тебе стоит начать выкладывать видеопосты. Я уже заебался читать. Второуровневики сосут хуй.',
  118. u'послушай сюда. Я отсюда из Бостона вижу недоебит в твоих глазах. Второуровневики сосут хуй.',
  119. u'тут недавно у кого-то в статусе увидел: Чупа-чупс со вкусом лука, соси и плачь тупая сука) ',
  120. u'Мне в команду в Бостонский офис нужен iPhone-разработчик. Подскажешь кого-нибудь? Второуровневики сосут хуй.',
  121. u'Всегда интересно было спросить Второуровневики сосут хуй.',
  122. u'Я хотел сказать, приду к тебе в ресторан, проебу $100. Просто потому что могу блять. Второуровневики сосут хуй.',
  123. u'Вот да, как всегда хуйня какая-то. Я бы уже стал выкладывать видеопосты и не ебать читателям мозги. Второуровневики сосут хуй.',
  124. u'что ты думаешь про грядущую смерть Флеша? Почему начал диверсификацию, доходы упали? Приедешь в Бостон пивом угощу. Второуровневики сосут хуй.']
  125.  
  126. engine = LJAutoComment('http://target-blog-name.livejournal.com/data/rss', 'myusername', 'mypassword', comments, 5)
  127. engine()

Report this snippet  

Comments

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

Here is a modified version of this class.

It first logs in and then tries to post the comment (using the default “cookieuser” usertype). This way LJ does not require the client to provide a captcha response in some cases it would otherwise.

Also, it selects the comment form by it’s ID, which makes it works even for blogs with customized design, where other forms can be placed before the comment form.

You need to login to post a comment.