This article is a continuation of the concept edition, so it is easy to understand if you also read it. [Concept] bot that posts the start notification of Nico Nico Live Broadcasting to Discord on discord.py
--You need to create a DB in PostgreSQL and have data in it ――If you have the setting value in the DB, isn't it necessary to rewrite the code and restart Heroku? ――I want to support not only community broadcasting but also channel broadcasting
--token: DiscordBot token --channel_id: The ID of the channel on which the bot posts notifications
token | channel_id |
---|---|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX | 0000000000000000 |
--community: The community number you want to monitor --comment: For memo (not used on the system)
id | community | comment |
---|---|---|
1 | co1520016 | BotTV |
2 | co117683 | myCommunity |
--live: Broadcast ID notified
id | live |
---|---|
1 | lv0000000 |
2 | lv2222222 |
discordbot.py
import requests
import os.path
import re
import discord
import asyncio
import os, psycopg2
import json
from bs4 import BeautifulSoup
path = "PATH"
port = "5432"
dbname = "DB_NAME"
user = "USER"
password = "PASSWORD"
conText = "host={} port={} dbname={} user={} password={}"
conText = conText.format(path,port,dbname,user,password)
connection = psycopg2.connect(conText)
cur = connection.cursor()
sql = "select token,channel_id from settings"
cur.execute(sql)
result = cur.fetchone()
#Get token
TOKEN = result[0]
#Get channel ID
CHANNEL_ID = result[1]
#Get the community you want to check from the target table
def getTarget():
targetCommunitys = []
sql = "select community from target"
cur.execute(sql)
for row in cur:
targetCommunitys.append(row[0])
return targetCommunitys
#Broadcast ID from the broadcast URL(lvXXXXXXX)Extraction
def liveIdExtraction(liveURL):
repatter = re.compile('lv[0-9]+')
return repatter.search(liveURL).group()
#Get broadcast title from broadcast URL
def getLiveTitle(liveURL):
r = requests.get(liveURL)
soup = BeautifulSoup(r.content, "html.parser")
for meta_tag in soup.find_all('meta', attrs={'property': 'og:title'}):
return meta_tag.get('content')
#Obtaining the broadcaster name from the broadcast URL
def getLiveName(liveURL):
r = requests.get(liveURL)
soup = BeautifulSoup(r.content, "html.parser")
return soup.find("span",{"class":"name"}).text
#logs Returns False if there is no search in the table True
def searchList(liveURL):
liveLV = liveIdExtraction(liveURL)
cur = connection.cursor()
sql = "SELECT count(*) FROM logs WHERE live = '" + liveLV + "'"
cur.execute(sql)
result = cur.fetchone()
if int(result[0]) > 0:
return True
else:
return False
#Broadcast ID added to logs table
def addList(liveURL):
liveLV = liveIdExtraction(liveURL)
cur = connection.cursor()
sql = "insert into logs(live) values('"+ liveLV + "');"
cur.execute(sql)
connection.commit()
#Generate the objects needed for the connection
client = discord.Client()
#Processing that operates at startup
@client.event
async def on_ready():
while(True):
#Repeat for the number of target communities
targetCommunitys = getTarget()
for targetCommunity in targetCommunitys:
#Set URL
r = requests.get("https://live.nicovideo.jp/watch/" + targetCommunity)
#Check the community TOP page
soup = BeautifulSoup(r.content, "html.parser")
result = soup.find('meta', attrs={'property': 'og:url', 'content': True})
#Broadcast URL acquisition
liveURL = result['content']
#Search in the list and do not process if the broadcast ID has already been processed
if searchList(liveURL) is False:
#Broadcast title acquisition
liveTitle = getLiveTitle(liveURL)
#Broadcaster name acquisition
liveName = getLiveName(liveURL)
#Send to Discord
channel = client.get_channel(int(CHANNEL_ID))
await channel.send(liveName + 'Has started delivery\n\n' + liveTitle + '\n' + liveURL)
#Broadcast ID postscript
addList(liveURL)
#Channel search
url = 'https://api.search.nicovideo.jp/api/v2/live/contents/search'
ua = 'Twitter @fctokyo1016'
headers = {'User-Agent': ua}
params = {
'q': 'BoxTV',
'targets': 'title,description,tags',
'_sort': '-openTime',
'_context': ua,
'fields': 'contentId,channelId,liveStatus,title',
'filters[channelId][0]': '2640777',
'filters[liveStatus][0]': 'onair'
}
#request
res = requests.get(url, headers=headers, params=params)
#Store the acquired json in the lists variable
lists = json.loads(res.text)
if lists['meta']['totalCount'] > 0:
for data in lists['data']:
if searchList(data['contentId']) is False:
#Send to Discord
channel = client.get_channel(int(CHANNEL_ID))
await channel.send('Started distribution on the channel\n\n' + data['title'] + '\nhttps://nico.ms/' + data['contentId'])
#Broadcast ID postscript
addList(data['contentId'])
#Wait 1 minute
await asyncio.sleep(60)
#Connect to Discord
client.run(TOKEN)
--Get the target community and other settings from the DB --Scraping the community page of Nico Nico Live Broadcasting to get the broadcasting URL ――In addition, hit the API of the live channel broadcast to search if the broadcast has started. --Notify Discord --Leave the notified broadcast in the DB so that it will not be notified again
Various setting values for connecting to DB
discordbot.py
path = "PATH"
port = "5432"
dbname = "DB_NAME"
user = "USER"
password = "PASSWORD"
conText = "host={} port={} dbname={} user={} password={}"
conText = conText.format(path,port,dbname,user,password)
connection = psycopg2.connect(conText)
Get the token and Discord channel ID from the settings table
discordbot.py
cur = connection.cursor()
sql = "select token,channel_id from settings"
cur.execute(sql)
result = cur.fetchone()
#Get token
TOKEN = result[0]
#Get channel ID
CHANNEL_ID = result[1]
Get the community you want to check from the target table and return it as an array
discordbot.py
#Get the community you want to check from the target table
def getTarget():
targetCommunitys = []
sql = "select community from target"
cur.execute(sql)
for row in cur:
targetCommunitys.append(row[0])
return targetCommunitys
Various data are obtained by scraping from the broadcast URL
discordbot.py
#Broadcast ID from the broadcast URL(lvXXXXXXX)Extraction
def liveIdExtraction(liveURL):
repatter = re.compile('lv[0-9]+')
return repatter.search(liveURL).group()
#Get broadcast title from broadcast URL
def getLiveTitle(liveURL):
r = requests.get(liveURL)
soup = BeautifulSoup(r.content, "html.parser")
for meta_tag in soup.find_all('meta', attrs={'property': 'og:title'}):
return meta_tag.get('content')
#Obtaining the broadcaster name from the broadcast URL
def getLiveName(liveURL):
r = requests.get(liveURL)
soup = BeautifulSoup(r.content, "html.parser")
return soup.find("span",{"class":"name"}).text
Check the logs table to see if Discord has already been notified
discordbot.py
#logs Returns False if there is no search in the table True
def searchList(liveURL):
liveLV = liveIdExtraction(liveURL)
cur = connection.cursor()
sql = "SELECT count(*) FROM logs WHERE live = '" + liveLV + "'"
cur.execute(sql)
result = cur.fetchone()
if int(result[0]) > 0:
return True
else:
return False
Log the notification in the logs table
discordbot.py
#Broadcast ID added to logs table
def addList(liveURL):
liveLV = liveIdExtraction(liveURL)
cur = connection.cursor()
sql = "insert into logs(live) values('"+ liveLV + "');"
cur.execute(sql)
connection.commit()
It is a confirmation of the channel live broadcast that was not the concept edition. I am using the API of Nico Nico Live Broadcasting niconico Content Search API Guide
discordbot.py
#Channel search
url = 'https://api.search.nicovideo.jp/api/v2/live/contents/search'
ua = 'Twitter @fctokyo1016'
headers = {'User-Agent': ua}
params = {
'q': 'BoxTV',
'targets': 'title,description,tags',
'_sort': '-openTime',
'_context': ua,
'fields': 'contentId,channelId,liveStatus,title',
'filters[channelId][0]': '2640777',
'filters[liveStatus][0]': 'onair'
}
#request
res = requests.get(url, headers=headers, params=params)
#Store the acquired json in the lists variable
lists = json.loads(res.text)
if lists['meta']['totalCount'] > 0:
for data in lists['data']:
if searchList(data['contentId']) is False:
#Send to Discord
channel = client.get_channel(int(CHANNEL_ID))
await channel.send('Started distribution on the channel\n\n' + data['title'] + '\nhttps://nico.ms/' + data['contentId'])
#Broadcast ID postscript
addList(data['contentId'])
Recommended Posts