niho #2
					 3 changed files with 96 additions and 160 deletions
				
			
		
							
								
								
									
										24
									
								
								bot.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								bot.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| #!/usr/bin/python3 | ||||
| import logging as log | ||||
| import requests | ||||
| import json  | ||||
| import msk | ||||
| 
 | ||||
| def json_read(file): | ||||
|     print("Reading config file: {}".format(file)) | ||||
|     with open(file) as f: | ||||
|         config = json.load(f) | ||||
|     return config | ||||
| 
 | ||||
| config = json_read('config.json') | ||||
| 
 | ||||
| if config['verbosity'].upper() == 'DEBUG':  | ||||
|     log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG) | ||||
|     log.info("Verbose output") | ||||
| 
 | ||||
| msk = msk.Misskey(i=config['token'], url=config['url']) | ||||
| 
 | ||||
| 
 | ||||
| fid = msk.drive_files_create("yaoshi-jun-Toosaka-Rin-Fate-(series)-Anime-3306019.jpeg", isSensitive=True)['id'] | ||||
| msk.notes_create(text="Wannya see my picture?", cw="Nya?", fileIds=[fid]) | ||||
| 
 | ||||
							
								
								
									
										160
									
								
								main.py
									
										
									
									
									
								
							
							
						
						
									
										160
									
								
								main.py
									
										
									
									
									
								
							|  | @ -1,160 +0,0 @@ | |||
| #!/usr/bin/python3 | ||||
| 
 | ||||
| import requests # Для отправки http-запросов | ||||
| import json  | ||||
| import time | ||||
| import argparse | ||||
| import logging as log | ||||
| import pprint | ||||
| 
 | ||||
| p = argparse.ArgumentParser() | ||||
| p.add_argument('--verbose', '-v', action='count', default=0) | ||||
| 
 | ||||
| args = p.parse_args() | ||||
| if args.verbose: | ||||
|     log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG) | ||||
|     log.info("Verbose output.") | ||||
| else: | ||||
|     log.basicConfig(format="%(levelname)s: %(message)s") | ||||
| 
 | ||||
| #log.info("This should be verbose.") | ||||
| #log.warning("This is a warning.") | ||||
| #log.error("This is an error.") | ||||
| 
 | ||||
| # Функция для чтения JSON-файла (например, конфига), аргумент - адрес файла в ФС | ||||
| # Возвращает словарь | ||||
| def json_read(file): | ||||
|     # Создается локальное окружение (или как эта хуйня зовется), где присутствует дескриптор для нашего файла | ||||
|     log.info("Reading config file: %s", file) | ||||
|     with open(file) as f: | ||||
|         config = json.load(f) | ||||
|     return config | ||||
| 
 | ||||
| config = json_read('config.json') | ||||
| 
 | ||||
| # Функция для получения уведомлений пользователя из Misskey | ||||
| # Возвращает список словарей | ||||
| def get_notifications(url, i, includeTypes=["follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "receiveFollowRequest", "followRequestAccepted", "groupInvited","app"], markAsRead=True, unreadOnly=True, following=True, limit=5): | ||||
|     log.info("Getting notifications from %s", url) | ||||
|     # Формируем URL для доступа к конкретной функции API | ||||
|     req_url = url + "/api/i/notifications" | ||||
|     body = { | ||||
|             "i": i, | ||||
|             # Можно включить лишь определенные уведомления, всю эту залупу следует вынести также в аргументы функции, чтоб реагировать на конкретные события, типа подписки или упоминания, по-разному | ||||
|             "includeTypes": includeTypes, | ||||
|             # Количество уведомлений, которые вытянем | ||||
|             "limit": 3, | ||||
|             "unreadOnly": False, | ||||
|             "markAsRead": markAsRead, | ||||
|             "unreadOnly": unreadOnly, | ||||
|             "following": following, | ||||
|             "limit": limit, | ||||
|     } | ||||
|     # Отправляем запрос, в тело запроса суем словарь-JSON, которые объявили выше | ||||
|     r = requests.post(req_url, json=body) | ||||
|     # Если все прошло збс, код HTTP 200, то отдаем получанный список уведомлений | ||||
|     if r.status_code == 200: | ||||
|         # Можешь раскомментить, глянуть, что это за черт | ||||
|         return r.json() | ||||
|     # Иначе, если не збс, то ругаемся | ||||
|     else: | ||||
|         log.error("Fuck you, leatherman") | ||||
| # Функция, создающая пост | ||||
| # 2do: посты с картинками, ... | ||||
| def create_note(url=config['url'], i=config['token'], content="", visibility="public", channel="", fileIds=[], renote=False, renoteId=None): | ||||
|     log.info("Creating note to %s", url) | ||||
|     # Аналогично, адрес нужной функции API | ||||
|     req_url = url + "/api/notes/create" | ||||
|     if renote: | ||||
|         body = { | ||||
|                 "renoteId": renoteId, | ||||
|                 "i": i | ||||
|                 } | ||||
|     else: | ||||
|         body = { | ||||
|             # Не ебу, что за noExtract*, надо полуркать, но работает и збс пока что | ||||
|             "noExtractMentions": True, | ||||
|             "noExtractHashtags": True, | ||||
|             "noExtractEmojis": True, | ||||
|             "visibility": visibility, | ||||
|             "text": content, | ||||
|             #"fileIds": fileIds, | ||||
|             # Если поставлен канал, то пост только локальный для инстанса | ||||
|             "localOnly": channel != "", | ||||
|             "i": i, | ||||
|         } | ||||
|         if channel != "": | ||||
|             body["channelId"] = channel | ||||
|     # Отправляем запрос | ||||
|     r = requests.post(req_url, json=body) | ||||
|     # Аналогично, проверка на 200, в случае успеха 1 | ||||
|     if r.status_code == 200: | ||||
|         return 0 | ||||
|     else: | ||||
|         log.error("Failed to post: %s", r.text) | ||||
|         return 1 | ||||
| 
 | ||||
| # Пока что можешь не пытаться разобраться, я сам отчасти хз, как это работает, лол | ||||
| def file_upload(file, url, i, isSensitive=False): | ||||
|     print("Uploading file to", url)  | ||||
|     req_url = url + "/api/drive/files/create" | ||||
|     with open(file, "rb") as f: | ||||
|         fileo = f.read() | ||||
|     body = { | ||||
|             "isSensitive": False,  | ||||
|             "force": True, | ||||
|             "i":i | ||||
|             } | ||||
|     body = json.dumps(body) | ||||
| 
 | ||||
|     payload = {'json_payload': body, 'i': i } | ||||
|      | ||||
|     files = {"file": (file, fileo)} | ||||
|     r = requests.post(req_url, data=payload, files=files) | ||||
|     if r.status_code == 200: | ||||
|         return r.json() | ||||
|     else: | ||||
|         print("Upload failed with code", r.status_code) | ||||
|         print(r.text) | ||||
| 
 | ||||
| def get_file_list(url, i): | ||||
|     req_url = url + "/api/drive/files" | ||||
|     r = requests.post(req_url, json={"i":i}) | ||||
|     print(r.json()) | ||||
| 
 | ||||
| ### Сюда надо захуярить еще 100500 функций### | ||||
| def follow_user(userId, url=config['url'], i=config['token']): | ||||
|     req_url = url + "/api/following/create" | ||||
|     r = requests.post(req_url, json={"i":i, "userId": userId}) | ||||
|     #print(r.json())    | ||||
|     if r.status_code == 200: | ||||
|         return r.json() | ||||
|     else: | ||||
|         print("Upload failed with code", r.status_code) | ||||
|         print(r.text) | ||||
| # Собсна, содержательная часть программы начинается тут | ||||
| 
 | ||||
| # Читаем конфиг, получаем словарь | ||||
| 
 | ||||
| 
 | ||||
| #create_note(config['url'], config['token'], renote=True, renoteId="8vxo3hpsdm") | ||||
| 
 | ||||
| while True: | ||||
|     notif_list = get_notifications(config['url'], config['token'], includeTypes=["mention"], markAsRead=False, unreadOnly=True, limit=2, following=True) | ||||
|     follow_notif_list = get_notifications(config['url'], config['token'], includeTypes=["follow"], markAsRead=False, unreadOnly=True, limit=2, following=False) | ||||
|     #pprint.pprint(notif_list) | ||||
|     pprint.pprint(follow_notif_list) | ||||
|     notes_to_repost=list() | ||||
|     users_to_follow=list() | ||||
|     for i in range(len(notif_list)): | ||||
|         #pprint.pprint(notif_list[i]['note']['id']) | ||||
|         notes_to_repost.append(notif_list[i]['note']['id']) | ||||
|     for i in range(len(follow_notif_list)): | ||||
|         #pprint.pprint(notif_list[i]['note']['id']) | ||||
|         users_to_follow.append(follow_notif_list[i]['user']['id']) | ||||
|     print(users_to_follow) | ||||
|     #for i in range(len(notes_to_repost)): | ||||
|     #    create_note(renote=True, renoteId=notes_to_repost.pop()) | ||||
|     for i in range(len(users_to_follow)): | ||||
|         follow_user(users_to_follow.pop()) | ||||
|     time.sleep(2) | ||||
							
								
								
									
										72
									
								
								msk.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								msk.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| import requests | ||||
| import logging as log | ||||
| 
 | ||||
| class Misskey: | ||||
|     '''  | ||||
|         Class for interaction with Misskey instance  | ||||
|         Currently, this class ignores most of the Misskey specific shit like channels =3 | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self, url: str, i: str): | ||||
|         self.url = url | ||||
|         self.i = i | ||||
| 
 | ||||
|     def notes_create(self, text=None, visibility = "public", cw = None, fileIds = list(), replyId = None, renoteId = None): | ||||
|         req_url = self.url + "/api/notes/create" | ||||
|          | ||||
|         if renoteId: | ||||
|             body = { | ||||
|                     "renoteId": renoteId, | ||||
|                     } | ||||
|         else: | ||||
|             body = { | ||||
|                     "text": text, | ||||
|                     "visibility": visibility, | ||||
|                     } | ||||
|             for item in [(cw, "cw"), (fileIds,"fileIds"), (replyId,"replyId")]: | ||||
|                 if item[0]: | ||||
|                     body[item[1]] = item[0] | ||||
| 
 | ||||
|         body['i'] = self.i | ||||
| 
 | ||||
|         log.info("Trying to post note to {}".format(self.url)) | ||||
|         r = requests.post(req_url, json=body) | ||||
|         print(body) | ||||
|         if r.status_code == 200: | ||||
|             log.info("Successfully posted") | ||||
|         else: | ||||
|             log.error("Posting failed with {} error!".format(r.status_code)) | ||||
|          | ||||
|         return r.json() | ||||
| 
 | ||||
|     def following_create(self, userId: str): | ||||
|         req_url = self.url + "/api/following/create" | ||||
|         r = requests.post(req_url, json={"i":self.i, "userId": userId}) | ||||
|         if r.status_code == 200: | ||||
|             res = r.json() | ||||
|             log.info("Successfully followed user {}@{}[{}]".format(res['username'],res['host'] ,userId)) | ||||
|         else: | ||||
|             log.error("Failed to follow user [{}] with {} error!".format(userId, r.status_code)) | ||||
|          | ||||
|         return r.json() | ||||
| 
 | ||||
|     def drive_files_create(self, file, isSensitive=False): | ||||
|         req_url = self.url + "/api/drive/files/create" | ||||
|          | ||||
|         with open(file, "rb") as f: | ||||
|             files = {"file": (file, f)} | ||||
|             body = { | ||||
|                    "isSensitive": isSensitive,  | ||||
|                     "i":self.i | ||||
|                     } | ||||
|             payload = {'json_payload': body, 'i': self.i } | ||||
| 
 | ||||
|             r = requests.post(req_url, data=payload, files=files) | ||||
|   | ||||
|         if r.status_code == 200: | ||||
|             res = r.json() | ||||
|             log.info("Successfully uploaded file {}[{}]".format(res['name'], res['id'])) | ||||
|         else: | ||||
|             log.error("Failed to upload file {}  with {} error!".format(file, r.status_code)) | ||||
|          | ||||
|         return r.json() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue