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…
Reference in a new issue