Guest User

Untitled

a guest
Mar 16th, 2023
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.71 KB | None | 0 0
  1. # COPYRIGHT (C) 2020-2022 Nicotine+ Contributors
  2. # COPYRIGHT (C) 2011 quinox <[email protected]>
  3. #
  4. # GNU GENERAL PUBLIC LICENSE
  5. # Version 3, 29 June 2007
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19.  
  20. from pynicotine import slskmessages
  21. from pynicotine.pluginsystem import BasePlugin
  22.  
  23.  
  24. class Plugin(BasePlugin):
  25.  
  26. PLACEHOLDERS = {
  27. "%files%": "num_files",
  28. "%folders%": "num_folders"
  29. }
  30.  
  31. def __init__(self, *args, **kwargs):
  32.  
  33. super().__init__(*args, **kwargs)
  34.  
  35. self.settings = {
  36. "message": "Please consider sharing more files if you would like to download from me again. Thanks :)",
  37. "messageban": "It looks like you're not sharing anything, so you've been automatically banned. The leech detector plugin sometime gives false positives, if this is an error don't panic, leave a message and we'll sort it out!",
  38. "num_files": 1,
  39. "num_folders": 1,
  40. "open_private_chat": True,
  41. "ban_zero_files": True
  42. }
  43. self.metasettings = {
  44. "message": {
  45. "description": ("Private chat message to send to leechers. Each line is sent as a separate message, "
  46. "too many message lines may get you temporarily banned for spam!"),
  47. "type": "textview"
  48. },
  49. "messageban": {
  50. "description": ("If enabled, this message will be sent to users that share zero files."),
  51. "type": "textview"
  52. },
  53. "num_files": {
  54. "description": "Require users to have a minimum number of shared files:",
  55. "type": "int", "minimum": 0
  56. },
  57. "num_folders": {
  58. "description": "Require users to have a minimum number of shared folders:",
  59. "type": "int", "minimum": 1
  60. },
  61. "open_private_chat": {
  62. "description": "Open chat tabs when sending private messages to leechers",
  63. "type": "bool"
  64. },
  65. "ban_zero_files": {
  66. "description": "Ban users that share zero files",
  67. "type": "bool"
  68. }
  69. }
  70.  
  71. self.probed = {}
  72. self.str_action = ""
  73.  
  74. def loaded_notification(self):
  75.  
  76. min_num_files = self.metasettings["num_files"]["minimum"]
  77. min_num_folders = self.metasettings["num_folders"]["minimum"]
  78.  
  79. if self.settings["num_files"] < min_num_files:
  80. self.settings["num_files"] = min_num_files
  81.  
  82. if self.settings["num_folders"] < min_num_folders:
  83. self.settings["num_folders"] = min_num_folders
  84.  
  85. if self.settings["message"]:
  86. self.str_action = "message leecher"
  87. else:
  88. self.str_action = "log leecher"
  89.  
  90. self.log(
  91. "Ready to %ss, require users have a minimum of %d files in %d shared public folders.",
  92. (self.str_action, self.settings["num_files"], self.settings["num_folders"])
  93. )
  94.  
  95. def upload_queued_notification(self, user, virtual_path, real_path):
  96.  
  97. if user in self.probed:
  98. # We already have stats for this user.
  99. return
  100.  
  101. self.probed[user] = "requesting"
  102. self.core.queue.append(slskmessages.GetUserStats(user))
  103. # self.log("Getting statistics from the server for new user %s...", user)
  104.  
  105. def user_stats_notification(self, user, stats):
  106.  
  107. if user not in self.probed:
  108. # We did not trigger this notification
  109. return
  110.  
  111. if self.probed[user] != "requesting":
  112. # We already dealt with this user.
  113. return
  114.  
  115. if stats["files"] >= self.settings["num_files"] and stats["dirs"] >= self.settings["num_folders"]:
  116. self.log("User %s is okay, sharing %s files in %s folders.", (user, stats["files"], stats["dirs"]))
  117. self.probed[user] = "okay"
  118. return
  119.  
  120. if user in self.core.userlist.buddies:
  121. self.log("Buddy %s is only sharing %s files in %s folders. Not complaining.",
  122. (user, stats["files"], stats["dirs"]))
  123. self.probed[user] = "buddy"
  124. return
  125.  
  126. if stats["files"] == 0 and stats["dirs"] >= self.settings["num_folders"]:
  127. # SoulseekQt seems to only send the number of folders to the server in at least some cases
  128. self.log(
  129. "User %s seems to have zero files but does have %s shared folders, the remote client could be wrong.",
  130. (user, stats["dirs"])
  131. )
  132. # TODO: Implement alternative fallback method (num_files | num_folders) from a Browse Shares request
  133.  
  134. if stats["files"] == 0 and stats["dirs"] == 0:
  135. # SoulseekQt only sends the number of shared files/folders to the server once on startup (see Issue #1565)
  136. self.log("User %s seems to have zero files and no public shared folder, the server could be wrong.", user)
  137.  
  138. self.log("Leecher detected, %s is only sharing %s files in %s folders. "
  139. + "Going to " + self.str_action + " after transfer...", (user, stats["files"], stats["dirs"]))
  140. self.probed[user] = "leecher"
  141.  
  142. def upload_finished_notification(self, user, *_):
  143.  
  144. if user not in self.probed:
  145. return
  146.  
  147. if self.probed[user] != "leecher":
  148. return
  149.  
  150. self.probed[user] = "processed"
  151.  
  152. if not self.settings["message"]:
  153. self.log("Leecher %s doesn't share enough files. No message is specified in plugin settings.", user)
  154. return
  155.  
  156. for line in self.settings["message"].splitlines():
  157. for placeholder, option_key in self.PLACEHOLDERS.items():
  158. # Replace message placeholders with actual values specified in the plugin settings
  159. line = line.replace(placeholder, str(self.settings[option_key]))
  160.  
  161. self.send_private(user, line, show_ui=self.settings["open_private_chat"], switch_page=False)
  162.  
  163. self.log("Leecher %s doesn't share enough files. Message sent.", user)
Advertisement
Add Comment
Please, Sign In to add comment