# 10/17 Discord Bot 開發(四)
:::info
時間:2023/10/17 22:20~23:30
地點:線上會議(Discord)
參與:xiaojie4082

:::
## 本次討論事項
- 講解選課相關指令
- ~~公車資訊~~ (延至下次討論)
- 機器人短時間內重複發布2000則以上訊息事件
## 講解選課相關指令
### /搜尋課程 [老師/課程] [關鍵字]
```python!
def search(course_teacher:str,keyword: str):
try:
if(course_teacher == "課程"):
# 課程名稱
url = "https://alcat.pu.edu.tw/2011courseAbstract/main.php?" + "ls_yearsem=1121&selectno=&weekday=§ion=&cus_select=&classattri=1&subjname=" + keyword + "&teaname=&opunit=&opclass=&lessonlang=&search=%E6%90%9C%E5%B0%8B&click_ok=Y"
else:
# 教師姓名
url = "https://alcat.pu.edu.tw/2011courseAbstract/main.php?" + "ls_yearsem=1121&selectno=&weekday=§ion=&cus_select=&classattri=1&subjname=&teaname=" + keyword + "&opunit=&opclass=&lessonlang=&search=%E6%90%9C%E5%B0%8B&click_ok=Y"
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
table = soup.find('table', class_='table_info')
rows = table.find_all('tr')
course_data = []
for row in rows:
cells = row.find_all('td')
if len(cells) >= 8:
course_code = cells[0].text.strip()
class_name = cells[1].text.strip()
course_type = cells[2].text.strip()
course_name = cells[3].text.strip()
credit = cells[5].text.strip()
teacher = cells[6].text.strip()
schedule = cells[7].text.strip()
course_info = {
'選課代號': course_code,
'上課班級': class_name,
'修別': course_type,
'科目名稱': course_name,
'學分數': credit,
'授課老師': teacher,
'上課時間地點': schedule
}
course_data.append(course_info)
return course_data
else:
course_info = {
'選課代號': "",
'上課班級': "",
'修別': "",
'科目名稱': "",
'學分數': "",
'授課老師': "",
'上課時間地點': ""
}
return course_data
except Exception as e:
print(e)
course_info = {
'選課代號': "",
'上課班級': "",
'修別': "",
'科目名稱': "",
'學分數': "",
'授課老師': "",
'上課時間地點': ""
}
return course_data
```
### /課程綱要 [課程代號]
```python!
def syllabus(selectno: str):
try:
url = 'https://alcat.pu.edu.tw/2011courseAbstract/main.php?ls_yearsem=1121&selectno=' + selectno + '&weekday=§ion=&cus_select=&classattri=1&subjname=&teaname=&opunit=&opclass=&lessonlang=&search=%E6%90%9C%E5%B0%8B&click_ok=Y'
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
all_a_elements = soup.find_all('a', href=True)
for a_element in all_a_elements:
href = a_element['href']
if "list_abstract_content_100.php?pkey=" in href:
new_href = href.replace("..", "https://alcat.pu.edu.tw/")
response = requests.get(new_href)
soup = BeautifulSoup(response.text, 'html.parser')
# 課程名稱
course_name_element = soup.find(text="課程名稱")
if course_name_element:
course_name = course_name_element.find_next('td').get_text(strip=True)
else:
course_name = "未找到課程名稱"
# 授課教師
instructor_element = soup.find(text="授課教師")
if instructor_element:
instructor = instructor_element.find_next('td').get_text(strip=True)
else:
instructor = "未找到授課教師"
# 上課時段
class_time_element = soup.find(text="上課時段")
if class_time_element:
class_time = class_time_element.find_next('td').get_text(strip=True)
else:
class_time = "未找到上課時段"
# 中文版課程簡介
course_description = soup.find('th', string='中文版課程簡介Course Description(Chinese Version)').find_next('td').text.strip()
if len(course_description) > 500:
course_description = course_description[:500] + "\n\n...略"
# 評分方式及比重
grading_content = soup.find('th', string="評分方式及比重Grading Methods and Ratio ").find_next('td').text.strip()
# 提取各科授課進度與內容Course Syllabus and Teaching Content
syllabus_and_content = soup.find('th', string='各科授課進度與內容Course Syllabus and Teaching Content').find_next('td').text.strip()
syllabus_and_content = syllabus_and_content.replace("週次", "").replace("Week(Time)", "").replace("主題內容/章節/或活動", "").replace("Topic/Chapter/Classroom Activities", "").replace("備註", "").replace("Remark(s)", "")
lines = syllabus_and_content.strip().split('\n\n')
weekly_contents = [line.strip() for line in lines if line.strip()]
syllabus_and_content = ""
for week, content in enumerate(weekly_contents, start=1):
syllabus_and_content = syllabus_and_content + content + "\n\n"
# PUHub 課程評論
url = "https://puhub.org/api/course_evaluation.php?course=" + course_name + "&teacher=" + instructor
response = requests.get(url)
datas = response.json()
evaluation = ""
temp = 0
for data in datas:
temp = temp + 1
evaluation = evaluation + "```" + data[6] + "``` "
if temp == 0:
evaluation = "```目前沒有任何評論```"
# AI 分析
# info = "## 課程名稱:" + course_name + "\t授課教師:" + instructor + "\t上課時段:" + class_time + "\n### 課程簡介:\n```" + course_description + "```\n### 評分方式:\n```" + grading_content + "```"
# messages = [{'role': 'user','content': "我是個大學生,正在尋找適合自己的課程,請透過下面的資訊向我提供選課分析。(200字以內)\n" + info + syllabus_and_content}]
# gpt_35_api_stream(messages)
# content = messages[1]['content']
content = ""
return course_name, instructor, class_time, course_description, grading_content, evaluation, content, new_href, url
except Exception as e:
print(e)
return "", "", "", "", "", "", "", "", ""
```
### /課程餘額 [課程代號]
```python!
def person(selectno: int):
try:
url = 'https://alcat.pu.edu.tw/choice/q_person.html'
data = {
'selectno': selectno
}
response = requests.post(url, data=data)
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
course_name = soup.find('h2', string=lambda text: text and '科目名稱:' in text).text
course_name = course_name.replace('科目名稱:', '')
rows = soup.find_all('tr')
limit = None
enrollment = None
remaining = None
for row in rows:
cells = row.find_all('td')
if len(cells) == 2:
key = cells[0].text.strip()
value = cells[1].text.strip()
if key == '人數上限':
limit = value
elif key == '修課人數':
enrollment = value
# elif key == '人數餘額':
# remaining = value
remaining = int(limit) - int(enrollment)
return course_name,enrollment,remaining
else:
return "輸入的資料有誤","輸入的資料有誤","輸入的資料有誤"
except Exception as e:
print(e)
return "輸入的資料有誤","輸入的資料有誤","輸入的資料有誤"
```
## 機器人短時間內重複發布2000則以上訊息事件
- 事件名稱:Discord Bot 持續發送訊息
- 事件時間:2023-10-16 早上 6. ~ 7.30
- 事件緣起:因 API 資料錯誤(缺漏),導致機器人持續發送訊息(陷入無限迴圈直至API資料恢復),造成所有成員困擾。
- 事件經過:
1. 2023-10-16 上午 6 點,成員反應 Discord Bot 持續發送訊息。
2. 管理團隊調查後發現,是 Bot 的 API 資料錯誤,導致 Bot 陷入無限迴圈,不斷發送訊息。
3. 管理團隊已將頻道暫時關閉,並對 Bot 添加 API 資料偵測,以防止此類事件再次發生。
4. 目前,已對機器人添加例外處理,避免發生相同狀況陷入無限迴圈。
- 事件分析:此次事件的原因是 中央氣象署 的 API 資料錯誤 以及 程式碼缺陷。造成此錯誤的原因可能是:
- 程式碼有 bug。
- API 資料有問題。
- 事件後續:
- 服務頻道改為選擇制
- 程式碼添加例外處理
## 下次會議討論事項
- 10/21 Discord Bot 開發(五)
- 公車資訊
- 添加按鈕