Skip to content

Commit 00c1b53

Browse files
committed
feat: add lab9
1 parent 67a82b3 commit 00c1b53

File tree

7 files changed

+386
-0
lines changed

7 files changed

+386
-0
lines changed

.github/workflows/lab9.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This workflow will build a golang project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3+
4+
name: lab9
5+
6+
on:
7+
push:
8+
paths:
9+
- 'lab9/**'
10+
11+
jobs:
12+
13+
build:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: actions/setup-go@v4
20+
with:
21+
go-version-file: 'lab9/go.mod'
22+
cache: false
23+
24+
- name: Build
25+
working-directory: 'lab9'
26+
run: pip install -r requirements.txt
27+
28+
- name: Run
29+
working-directory: 'lab9'
30+
run: |
31+
go run lab9.go &
32+
python3 validate.py

lab9/lab9.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"log"
6+
"net/http"
7+
"os"
8+
9+
"github.com/gorilla/websocket"
10+
"github.com/reactivex/rxgo/v2"
11+
)
12+
13+
type client chan<- string // an outgoing message channel
14+
15+
var (
16+
entering = make(chan client)
17+
leaving = make(chan client)
18+
messages = make(chan rxgo.Item) // all incoming client messages
19+
ObservableMsg = rxgo.FromChannel(messages)
20+
)
21+
22+
func broadcaster() {
23+
clients := make(map[client]bool) // all connected clients
24+
MessageBroadcast := ObservableMsg.Observe()
25+
for {
26+
select {
27+
case msg := <-MessageBroadcast:
28+
// Broadcast incoming message to all
29+
// clients' outgoing message channels.
30+
for cli := range clients {
31+
cli <- msg.V.(string)
32+
}
33+
34+
case cli := <-entering:
35+
clients[cli] = true
36+
37+
case cli := <-leaving:
38+
delete(clients, cli)
39+
close(cli)
40+
}
41+
}
42+
}
43+
44+
func clientWriter(conn *websocket.Conn, ch <-chan string) {
45+
for msg := range ch {
46+
conn.WriteMessage(1, []byte(msg))
47+
}
48+
}
49+
50+
func wshandle(w http.ResponseWriter, r *http.Request) {
51+
upgrader := &websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
52+
conn, err := upgrader.Upgrade(w, r, nil)
53+
if err != nil {
54+
log.Println("upgrade:", err)
55+
return
56+
}
57+
58+
ch := make(chan string) // outgoing client messages
59+
go clientWriter(conn, ch)
60+
61+
who := conn.RemoteAddr().String()
62+
ch <- "你是 " + who + "\n"
63+
messages <- rxgo.Of(who + " 來到了現場" + "\n")
64+
entering <- ch
65+
66+
defer func() {
67+
log.Println("disconnect !!")
68+
leaving <- ch
69+
messages <- rxgo.Of(who + " 離開了" + "\n")
70+
conn.Close()
71+
}()
72+
73+
for {
74+
_, msg, err := conn.ReadMessage()
75+
if err != nil {
76+
log.Println("read:", err)
77+
break
78+
}
79+
messages <- rxgo.Of(who + " 表示: " + string(msg))
80+
}
81+
}
82+
83+
func InitObservable() {
84+
// TODO: Please create an Observable to handle the messages
85+
/*
86+
ObservableMsg = ObservableMsg.Filter(...) ... {
87+
}).Map(...) {
88+
...
89+
})
90+
*/
91+
}
92+
93+
func main() {
94+
InitObservable()
95+
go broadcaster()
96+
http.HandleFunc("/wschatroom", wshandle)
97+
98+
http.Handle("/", http.FileServer(http.Dir("./static")))
99+
100+
log.Println("server start at :8090")
101+
log.Fatal(http.ListenAndServe(":8090", nil))
102+
}

lab9/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
selenium==4.15.2

lab9/sensitive_name.txt

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
侯友宜
2+
侯漢廷
3+
傅雲欽
4+
劉兆玄
5+
史明
6+
吳伯雄
7+
吳成典
8+
吳敦義
9+
吳萬固
10+
呂秀蓮
11+
夏立言
12+
姚人多
13+
姚文智
14+
張景森
15+
張燦鍙
16+
徐欣瑩
17+
施明德
18+
朱立倫
19+
李來希
20+
李國鼎
21+
李敖
22+
李登輝
23+
杜正勝
24+
林山田
25+
林益世
26+
林祖嘉
27+
林義雄
28+
柯建銘
29+
柯文哲
30+
楊志良
31+
楊時睿
32+
段宜康
33+
沈富雄
34+
洪秀柱
35+
涂醒哲
36+
游錫堃
37+
潘世偉
38+
王世堅
39+
王定宇
40+
王建煊
41+
王效蘭
42+
王淑慧
43+
王炳忠
44+
王金平
45+
莊國榮
46+
蔡啟芳
47+
蔡英文
48+
蔣孝嚴
49+
蔣經國
50+
蔣緯國
51+
蕭秋華
52+
蘇煥智
53+
吳欣盈
54+
蘇貞昌
55+
許榮淑
56+
許毓仁
57+
許水德
58+
謝志偉
59+
謝欣霓
60+
謝長廷
61+
賴清德
62+
趙少康
63+
辜寬敏
64+
連勝文
65+
連戰
66+
連根藤
67+
邱連輝
68+
郝柏村
69+
鄭南榕
70+
鄭麗君
71+
陳其邁
72+
陳唐山
73+
陳定南
74+
蕭美琴
75+
陳文茜
76+
陳柏惟
77+
陳水扁
78+
陳菊
79+
韓國瑜
80+
馬英九
81+
馬鶴凌
82+
高志鵬
83+
黃偉哲
84+
黃國昌
85+
龍應台

lab9/static/index.html

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Chatroom</title>
7+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
8+
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous" />
9+
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" />
10+
<link rel="icon" type="image/png"
11+
href="https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678068-terminal-512.png" />
12+
<style>
13+
* {
14+
font-family: 'Source Code Pro', monospace;
15+
font-size: 1rem !important;
16+
}
17+
18+
body {
19+
background-color: #212529;
20+
}
21+
22+
pre {
23+
color: #cccccc;
24+
}
25+
26+
b {
27+
color: #01b468;
28+
}
29+
</style>
30+
</head>
31+
32+
<body>
33+
<table class="table table-dark table-bordered">
34+
<thead>
35+
<tr>
36+
<th scope="col">chatroom</th>
37+
</tr>
38+
</thead>
39+
<tbody>
40+
<tr>
41+
<td>
42+
<pre id="chatbox" class="mb-0"></pre>
43+
</td>
44+
</tr>
45+
</tbody>
46+
</table>
47+
</body>
48+
49+
</html>
50+
51+
<script>
52+
let ws = new WebSocket('ws://' + location.host + '/wschatroom');
53+
54+
function sendchat(ele) {
55+
if (event.key === 'Enter') {
56+
ws.send(ele.value + '\n');
57+
ele.value = "";
58+
}
59+
}
60+
61+
ws.onopen = () => {
62+
console.log('open connection');
63+
var chat_input = document.createElement("input");
64+
chat_input.type = 'text';
65+
chat_input.id = 'chat_input';
66+
chat_input.onkeydown = function () { sendchat(this); };
67+
document.body.appendChild(chat_input);
68+
}
69+
70+
ws.onclose = () => {
71+
console.log('close connection');
72+
}
73+
74+
//接收 Server 發送的訊息
75+
ws.onmessage = event => {
76+
console.log(event);
77+
var newB = document.createElement("b");
78+
newB.innerText = event.data;
79+
document.getElementById("chatbox").appendChild(newB);
80+
}
81+
82+
</script>

lab9/swear_word.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
白痴
2+
窩囊廢
3+
智障
4+
三小
5+
胖呆
6+
唬爛

lab9/validate.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import re
2+
from time import sleep
3+
from selenium import webdriver
4+
from selenium.webdriver.common.by import By
5+
from selenium.webdriver.common.keys import Keys
6+
from selenium.webdriver.chrome.service import Service
7+
import urllib.request
8+
9+
10+
def get_msg(text: str):
11+
pattern = r'表示: (.*)'
12+
match = re.search(pattern, text)
13+
if match:
14+
return match.group(1)
15+
else:
16+
return None
17+
18+
19+
def main():
20+
try:
21+
service = Service()
22+
options = webdriver.ChromeOptions()
23+
options.add_argument("--headless=new")
24+
driver = webdriver.Chrome(service=service, options=options)
25+
url = "http://localhost:8090"
26+
27+
for _ in range(30):
28+
try:
29+
code = urllib.request.urlopen(url).getcode()
30+
if code < 400:
31+
break
32+
except Exception as e:
33+
print(
34+
"\033[1;36m[INFO]\033[0m Unable to connect to Go server, try again...")
35+
sleep(2)
36+
else:
37+
print("\033[1;31m[ERROR]\033[0m Unable to connect to Go server!")
38+
return 1
39+
40+
test_cases = [
41+
("你好", "你好"),
42+
("我是賴清德", "我是賴*德"),
43+
("哈哈騙你的啦", "哈哈騙你的啦"),
44+
("其實我是陳菊", "其實我是陳*"),
45+
("好啦,朱立倫才是我的真實身份", "好啦,朱*倫才是我的真實身份"),
46+
("沒啦", "沒啦"),
47+
("其實我都在唬爛", "沒啦"),
48+
("呵呵", "呵呵"),
49+
("我是白痴", "呵呵"),
50+
]
51+
52+
driver.get(url)
53+
for tc in test_cases:
54+
driver.find_element(By.ID, "chat_input").send_keys(tc[0])
55+
driver.find_element(By.ID, "chat_input").send_keys(Keys.ENTER)
56+
sleep(0.5)
57+
58+
chatbox = driver.find_element(By.ID, "chatbox")
59+
last_full_msg = chatbox.find_elements(By.TAG_NAME, "b")[-1].text
60+
msg = get_msg(last_full_msg)
61+
if msg != tc[1]:
62+
print("\033[1;31m[ERROR]\033[0m", end=" ")
63+
print("Expected: %s, got: %s" % (tc[1], msg))
64+
return 1
65+
return 0
66+
except Exception as e:
67+
print("\033[1;31m[ERROR]\033[0m")
68+
print(e)
69+
return 1
70+
finally:
71+
driver.quit()
72+
73+
74+
if __name__ == "__main__":
75+
status = main()
76+
if status == 0:
77+
print("\033[1;32m[PASS]\033[0m")
78+
exit(status)

0 commit comments

Comments
 (0)