Init
This commit is contained in:
commit
d78900d076
|
@ -0,0 +1 @@
|
||||||
|
config.json
|
|
@ -0,0 +1,191 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import asyncio
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import nextcord
|
||||||
|
from nextcord.ext import tasks, commands
|
||||||
|
|
||||||
|
def load_config(config_name):
|
||||||
|
if not os.path.exists(config_name):
|
||||||
|
return None
|
||||||
|
with open(config_name, "rt", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def save_config(config_name, config):
|
||||||
|
with open(config_name, 'wt', encoding="utf-8") as f:
|
||||||
|
json.dump(config, f, indent=1, ensure_ascii=False)
|
||||||
|
|
||||||
|
# dictionary of urls and time they were added
|
||||||
|
processed_urls = {}
|
||||||
|
|
||||||
|
config = load_config("config.json")
|
||||||
|
if config is None:
|
||||||
|
config = {"deepl_key": "", "discord_bot_token": "", "ping_terms": {}}
|
||||||
|
save_config("config.json", config)
|
||||||
|
|
||||||
|
if not config.get("deepl_key") or not config.get("discord_bot_token"):
|
||||||
|
raise Exception("Config file is missing some values")
|
||||||
|
|
||||||
|
intents = nextcord.Intents.default()
|
||||||
|
bot = commands.Bot(command_prefix=".", intents=intents)
|
||||||
|
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
|
||||||
|
deepl_headers = {'Authorization': f'DeepL-Auth-Key {config["deepl_key"]}', 'User-Agent': 'YahooScraper/1.0.0'}
|
||||||
|
search_term = 'けものフレンズ'
|
||||||
|
ping_terms : dict = config["ping_terms"]
|
||||||
|
|
||||||
|
def add_ping(term, user_id):
|
||||||
|
if term not in ping_terms:
|
||||||
|
ping_terms[term] = [user_id]
|
||||||
|
elif user_id not in ping_terms[term]:
|
||||||
|
ping_terms[term].append(user_id)
|
||||||
|
else:
|
||||||
|
print(f"{user_id} is already being pinged for {term}")
|
||||||
|
return
|
||||||
|
|
||||||
|
config["ping_terms"] = ping_terms
|
||||||
|
save_config("config.json", config)
|
||||||
|
|
||||||
|
async def ping_users(auction_name):
|
||||||
|
"""If the name of the listing is particularly interesting, ping some people
|
||||||
|
- HAV0X"""
|
||||||
|
users_to_ping = []
|
||||||
|
for term in ping_terms.keys():
|
||||||
|
if term in auction_name:
|
||||||
|
for user in ping_terms[term]:
|
||||||
|
if user not in users_to_ping:
|
||||||
|
users_to_ping.append(user)
|
||||||
|
|
||||||
|
if len(users_to_ping) > 0:
|
||||||
|
ping_message = "Interesting listing, pinging: " + ", ".join([f"<@{user}>" for user in users_to_ping])
|
||||||
|
await send_message_text("Japari Modding", "yahoo-auctions", ping_message)
|
||||||
|
|
||||||
|
def translate(text: str):
|
||||||
|
text = requests.post("https://api-free.deepl.com/v2/translate",
|
||||||
|
json={"text": [text], "target_lang": "EN", 'source_lang': 'JA'}, headers=deepl_headers).json()[
|
||||||
|
'translations'][0]['text']
|
||||||
|
return text.replace("Beast Friends", "Kemono Friends")
|
||||||
|
|
||||||
|
def embed_auction(service: str, url: str, name: str, name_en: str, thumbnail: str, price=None):
|
||||||
|
desc = name
|
||||||
|
if price is not None:
|
||||||
|
desc += '\nPrice: ' + price
|
||||||
|
embed = nextcord.Embed(title=name_en, url=url, description=desc)
|
||||||
|
embed.set_author(name=service)
|
||||||
|
embed.set_image(url=thumbnail)
|
||||||
|
return embed
|
||||||
|
|
||||||
|
async def send_message(server_name: str, channel_name: str, embed: nextcord.Embed):
|
||||||
|
for guild in bot.guilds:
|
||||||
|
if guild.name == server_name:
|
||||||
|
for channel in guild.channels:
|
||||||
|
if channel.name == channel_name and isinstance(channel, nextcord.TextChannel):
|
||||||
|
await channel.send(embed=embed)
|
||||||
|
break
|
||||||
|
|
||||||
|
async def send_message_text(server_name: str, channel_name: str, text: str):
|
||||||
|
for guild in bot.guilds:
|
||||||
|
if guild.name == server_name:
|
||||||
|
for channel in guild.channels:
|
||||||
|
if channel.name == channel_name and isinstance(channel, nextcord.TextChannel):
|
||||||
|
await channel.send(content=text)
|
||||||
|
break
|
||||||
|
|
||||||
|
async def check_yahoo_fleamarket(search_term: str, page: int, notify: bool):
|
||||||
|
url = f'https://buyee.jp/paypayfleamarket/search?keyword={search_term}&order-sort=created_time&page={page}'
|
||||||
|
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
|
||||||
|
# Find all item listings on the page
|
||||||
|
item_listings = soup.find('ul', {'class': 'item-lists'}).find_all('li', {'class': 'list'})
|
||||||
|
date = datetime.now().date()
|
||||||
|
|
||||||
|
for item in item_listings:
|
||||||
|
url = 'https://buyee.jp' + item.find('a').get('href')
|
||||||
|
|
||||||
|
if url in processed_urls:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name = item.find('h2', {'class': 'name'}).text
|
||||||
|
price = item.find('p', {'class': 'price'}).text
|
||||||
|
thumbnail_data = item.find('img', {'class': "thumbnail"}).get("data-bind")
|
||||||
|
thumbnail_start = thumbnail_data.find('imagePath: \'') + len('imagePath: \'')
|
||||||
|
thumbnail_end = thumbnail_data.find('\'', thumbnail_start)
|
||||||
|
thumbnail = "https:" + thumbnail_data[thumbnail_start:thumbnail_end]
|
||||||
|
|
||||||
|
if notify:
|
||||||
|
name_en = translate(name)
|
||||||
|
embed = embed_auction("Yahoo! Flea market", url, name, name_en, thumbnail, price)
|
||||||
|
await send_message("Japari Modding", "yahoo-auctions", embed)
|
||||||
|
await ping_users(name)
|
||||||
|
|
||||||
|
print('New item added:', url)
|
||||||
|
processed_urls[url] = date
|
||||||
|
except Exception as e:
|
||||||
|
print(url, e)
|
||||||
|
|
||||||
|
async def check_yahoo_auction(search_term: str, page: int, notify: bool):
|
||||||
|
url = f'https://buyee.jp/item/search/query/{search_term}?sort=end&order=d&page={page}'
|
||||||
|
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
|
||||||
|
# Find all item listings on the page
|
||||||
|
item_listings = soup.find('ul', {'class': 'auctionSearchResult'}).find_all('li', {'class': 'itemCard'})
|
||||||
|
date = datetime.now().date()
|
||||||
|
|
||||||
|
for item in item_listings:
|
||||||
|
url = 'https://buyee.jp' + item.find('a').get('href')
|
||||||
|
|
||||||
|
if url in processed_urls:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
name = item.find('div', {'class': 'itemCard__itemName'}).find('a').text
|
||||||
|
price = item.find('div', {'class': 'g-price__outer'}).find('span').text
|
||||||
|
thumbnail = item.find('img', {'class': 'g-thumbnail__image'}).get('data-src').split(';')[0]
|
||||||
|
|
||||||
|
if notify:
|
||||||
|
name_en = translate(name)
|
||||||
|
embed = embed_auction("Yahoo! JAPAN Auction", url, name, name_en, thumbnail, price)
|
||||||
|
await send_message("Japari Modding", "yahoo-auctions", embed)
|
||||||
|
await ping_users(name)
|
||||||
|
|
||||||
|
print('New item added:', url)
|
||||||
|
processed_urls[url] = date
|
||||||
|
except Exception as e:
|
||||||
|
print(url, e)
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_ready():
|
||||||
|
for i in range(1, 4):
|
||||||
|
await check_yahoo_auction(search_term, i, False)
|
||||||
|
await check_yahoo_fleamarket(search_term, i, False)
|
||||||
|
await asyncio.sleep(10)
|
||||||
|
myLoop.start()
|
||||||
|
|
||||||
|
@tasks.loop(minutes=30)
|
||||||
|
async def myLoop():
|
||||||
|
fulldate = datetime.now()
|
||||||
|
|
||||||
|
print(f'Last check: {fulldate.strftime("%d/%m/%Y %H:%M:%S")}\nCache count: {len(processed_urls)}')
|
||||||
|
|
||||||
|
try:
|
||||||
|
await check_yahoo_auction(search_term, 1, True)
|
||||||
|
except Exception as e:
|
||||||
|
print("Yahoo auction check failed:", e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await check_yahoo_fleamarket(search_term, 1, True)
|
||||||
|
except Exception as e:
|
||||||
|
print("Yahoo flea market check failed:", e)
|
||||||
|
|
||||||
|
onlydate = fulldate.date()
|
||||||
|
for key in list(processed_urls.keys()):
|
||||||
|
if onlydate - processed_urls[key] > timedelta(weeks=3):
|
||||||
|
del processed_urls[key]
|
||||||
|
|
||||||
|
bot.run(config["discord_bot_token"], reconnect=True)
|
Loading…
Reference in New Issue