Upload files to '08/Research-BohyeWoo'

master
Bohye.Woo 6 years ago
parent bd61565343
commit c92b8f8470

Binary file not shown.

@ -0,0 +1,294 @@
#!/usr/bin/env python3
import logging
from getpass import getpass
from argparse import ArgumentParser
import datetime
import pickle
import numpy as np
import slixmpp
import ssl, os, requests, urllib
from bs4 import BeautifulSoup
from urllib.parse import quote as urlquote, unquote as urlunquote
nickname_color = {}
# import the pickled object, serializing and de-serializing a Python object)
def save_obj(obj, name):
with open(name + '.pkl', 'wb') as f:
pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)
def load_obj(name):
with open(name + '.pkl', 'rb') as f:
return pickle.load(f)
# make a numbered text
def make_numbered_text(input_text, output_html):
if not os.path.exists(output_html): # if output_html path does not exist
text = open(input_text, 'r') # open the txt file
lines = text.readlines() # to divide the text into lines in the form {{"This is line 1"},{"This is line 2"},...}
x = 1
with open(output_html, 'w') as new_html: # open the output_html with writing only as new_html
new_html.write('<html><head><link rel="stylesheet" href="style.css" type="text/css"/><meta '
'charset="utf-8"/></head><body>')
for line in lines: # for each line in the list of lines
new_html.write(
'<div class="linenum" id="linenum-{}"><div class="leftcolumn" id="leftcolumn-{}"><div class="linenumber">{}</div><div class="sentence">{}</div></div></div>'.format(
x, x, x, line))
x = x + 1
new_html.write('</body></html>')
print('I wrote a file', output_html)
# Get color from nickname_color dictionary. If it does not exist, create a color and save it
def get_nickname_color(nickname):
if nickname not in nickname_color: # If nickname is not in dict
color = list(np.random.choice(range(256), size=3)) # Generate random new color
nickname_color[nickname] = color # Save new color in dict
save_obj(nickname_color, 'nickname_color')
return nickname_color[nickname]
# (parameter variable,parameter variable,parameter variable)
def insert_comment_at_line(output_html, comment, line_number, nickname):
with open(output_html, 'r') as f:
text = f.read()
html = BeautifulSoup(text, 'html.parser')
div_id = 'linenum-{}'.format(line_number) # out comes linenum-line_number
line = html.find('div', {'id': div_id}) # find the div that has the id div_id (has the id linenum-line_number)
if not html.find('div', {
'id': 'rightcolumn-{}'.format(line_number)}): # if there is no div with id rightcolumn-line_number
# then make a new div with rightcolumn-line_number and class rightcolumn. Then, append it to the line variable.
right_column = html.new_tag("div")
right_column['id'] = 'rightcolumn-{}'.format(line_number)
right_column['class'] = 'rightcolumn'
line.append(right_column)
else:
right_column = html.find('div', {'id': 'rightcolumn-{}'.format(line_number)})
time = datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")
color = get_nickname_color(nickname)
print(color)
# new_comment = html.new_tag("comment") # make <comment></comment>
new_comment = html.new_tag("div") # make <comment></comment>
new_comment['id'] = 'comment-{}'.format(line_number)
new_comment['class'] = 'comment'
# new_comment['style'] = 'text-decoration: underline; -webkit-text-decoration-color: rgb(' + str(color[0]) + ',' + str(color[1]) + ',' + str(color[2])+');'
comment_text = html.new_tag("span")
comment_text['style'] = 'border-bottom: 2px solid rgb(' + str(color[0]) + ',' + str(color[1]) + ',' + str(color[2])+');'
#remove #comment <number>
comment = comment.split(' ',2)[2]
comment_text.string = nickname + ': ' + comment + ' (' + time + ') ' # make <comment>comment (the parameter variable)</comment>
comment_text['class'] = 'comment-text'
new_comment.append(comment_text)
right_column.append(new_comment)
print(line, comment, '#' + str(line_number) + '#')
print(div_id)
if line:
with open(output_html, 'w') as f:
right_column.append(new_comment)
f.write(html.decode())
def insert_media_at_line(output_html, mediafile, line_number):
with open(output_html, 'r') as f:
text = f.read()
html = BeautifulSoup(text, 'html.parser')
div_id = 'linenum-{}'.format(line_number)
line = html.find('div', {'id': div_id})
if not html.find('div', {'id': 'rightcolumn-{}'.format(line_number)}):
right_column = html.new_tag("div")
right_column['id'] = 'rightcolumn-{}'.format(line_number)
right_column['class'] = 'rightcolumn'
line.append(right_column)
else:
right_column = html.find('div', {'id': 'rightcolumn-{}'.format(line_number)})
print(line, mediafile, '#' + str(line_number) + '#')
print(div_id)
if line:
# notes to self write function to the detect media type
with open(output_html, 'w') as f:
new_image = html.new_tag("img", src=mediafile)
right_column.append(new_image)
f.write(html.decode())
class MUCBot(slixmpp.ClientXMPP):
def __init__(self, jid, password, room, nick, output):
slixmpp.ClientXMPP.__init__(self, jid, password)
self.room = room
self.nick = nick
self.output = output
self.current_line = 0
self.add_event_handler("session_start", self.start) # moment that it logs on
self.add_event_handler("groupchat_message", self.muc_message) # moment that someone start speaking someone
output = self.output
if not os.path.exists(output):
os.mkdir(output)
make_numbered_text('text.txt', 'dependency-of-network.html')
def start(self, event):
self.get_roster()
self.send_presence()
# https://xmpp.org/extensions/xep-0045.html
self.plugin['xep_0045'].join_muc(self.room,
self.nick,
# If a room password is needed, use:
# password=the_room_password,
wait=True)
def muc_message(self, msg):
# Always check that a message is not the bot itself, otherwise you will create an infinite loop responding to your own messages.
if msg['mucnick'] != self.nick:
# Check if an OOB URL is included in the stanza (which is how an image is sent)
# (OOB object - https://xmpp.org/extensions/xep-0066.html#x-oob)
if len(msg['oob']['url']) > 0:
# UPLOADED IMAGE
# Send a reply
self.send_message(mto=msg['from'].bare,
mbody="Really? Oke. I'll add your photo for you, {}.".format(msg['mucnick']),
mtype='groupchat')
# Save the image to the output folder
url = msg['oob']['url'] # grep the url in the message
# urlunquote is like url to filename
filename = os.path.basename(urlunquote(url)) # grep the filename in the url
output = self.output
# if not os.path.exists(output):
# os.mkdir(output)
output_path = os.path.join(output, filename)
u = urllib.request.urlopen(url) # read the image data
new_html = open(output_path, 'wb') # open the output file
new_html.write(u.read()) # write image to file
new_html.close() # close the output file
# If we haven't set current line yet, prompt the user to do so
if self.current_line < 0:
self.send_message(mto=msg['from'].bare,
mbody="{}, before uploading an image, please use the following syntax: #image <line number>".format(
msg['mucnick']),
mtype='groupchat')
# Add image to stream
img = output_path
insert_media_at_line('dependency-of-network.html', img, self.current_line)
else:
# TEXT MESSAGE
words = msg['body'].split()
linenum = words[1]
if msg['body'].startswith("#image"):
if (linenum.isdigit()):
self.current_line = int(words[1])
self.send_message(mto=msg['from'].bare,
mbody="Please now upload the image to be inserted on line {}.".format(
self.current_line),
mtype='groupchat')
else:
self.current_line = -1
self.send_message(mto=msg['from'].bare,
mbody="{}, please use the following syntax: #image <line number>".format(
msg['mucnick']),
mtype='groupchat')
if msg['body'].startswith("#comment"):
print(linenum)
if (linenum.isdigit()):
self.send_message(mto=msg['from'].bare,
mbody="Really? Oke. I'll add your comment that for you, {}.".format(
msg['mucnick']),
mtype='groupchat')
# output_html,comment,line_number,username
insert_comment_at_line('dependency-of-network.html', msg['body'], linenum, msg['mucnick'])
else:
self.send_message(mto=msg['from'].bare,
mbody="{}, please use the following syntax: #comment <line number> <message>...".format(
msg['mucnick']),
mtype='groupchat')
if __name__ == '__main__':
# Setup the command line arguments.
parser = ArgumentParser() # making your own command line - ArgumentParser.
# output verbosity options.
parser.add_argument("-q", "--quiet", help="set logging to ERROR",
action="store_const", dest="loglevel",
const=logging.ERROR, default=logging.INFO)
parser.add_argument("-d", "--debug", help="set logging to DEBUG",
action="store_const", dest="loglevel",
const=logging.DEBUG, default=logging.INFO)
# JID and password options.
parser.add_argument("-j", "--jid", dest="jid", # jid = user
help="JID to use")
parser.add_argument("-p", "--password", dest="password",
help="password to use")
parser.add_argument("-r", "--room", dest="room",
help="MUC room to join")
parser.add_argument("-n", "--nick", dest="nick",
help="MUC nickname") # MUC = multi user chat
# output folder for images
parser.add_argument("-o", "--output", dest="output",
help="output folder, this is where the files are stored",
default="./output/", type=str)
args = parser.parse_args()
# Setup logging.
logging.basicConfig(level=args.loglevel,
format='%(levelname)-8s %(message)s')
if args.jid is None:
args.jid = input("User: ")
if args.password is None:
args.password = getpass("Password: ")
if args.room is None:
args.room = input("MUC room: ")
if args.nick is None:
args.nick = input("MUC nickname: ")
if args.output is None:
args.output = input("Output folder: ")
# Setup the MUCBot and register plugins. Note that while plugins may
# have interdependencies, the order in which you register them does
# not matter.
xmpp = MUCBot(args.jid, args.password, args.room, args.nick, args.output)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0045') # Multi-User Chat
xmpp.register_plugin('xep_0199') # XMPP Ping
xmpp.register_plugin('xep_0066') # Process URI's (files, images)
# Connect to the XMPP server and start processing XMPP stanzas.
xmpp.connect()
xmpp.process()
# Load color data
if os.path.exists("nickname_color.pkl"):
nickname_color = load_obj("nickname_color") # Load dictionary from file into variable (nickname_color)

@ -0,0 +1,182 @@
<html><head><link href="style.css" rel="stylesheet" type="text/css"/><link href="print.css" media="print" rel="stylesheet"/><meta charset="utf-8"/> <!-- <meta http-equiv="refresh" content="3"> -->
<link href="https://cdn.conversejs.org/4.2.0/css/converse.min.css" media="screen" rel="stylesheet" type="text/css"/>
<script charset="utf-8" src="https://cdn.conversejs.org/4.2.0/dist/converse.min.js"></script>
</head><body><div class="linenum" id="linenum-1"><div class="leftcolumn" id="leftcolumn-1"><div class="linenumber">1</div><div class="sentence"><b>DEPENDENCIES IN A NETWORK</b>
</div></div></div><div class="linenum" id="linenum-2"><div class="leftcolumn" id="leftcolumn-2"><div class="linenumber">2</div><div class="sentence">HOW IS OUR NETWORK DEPENDING ON OTHERS?
</div></div><div class="rightcolumn" id="rightcolumn-2"></div></div><div class="linenum" id="linenum-3"><div class="leftcolumn" id="leftcolumn-3"><div class="linenumber">3</div><div class="sentence"><i>By Bo Woo</i>
</div></div></div><div class="linenum" id="linenum-4"><div class="leftcolumn" id="leftcolumn-4"><div class="linenumber">4</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-4"></div></div><div class="linenum" id="linenum-5"><div class="leftcolumn" id="leftcolumn-5"><div class="linenumber">5</div><div class="sentence"><b>CATEGORIES</b>
</div></div></div><div class="linenum" id="linenum-6"><div class="leftcolumn" id="leftcolumn-6"><div class="linenumber">6</div><div class="sentence"># NETWORK(ED) PUBLISHING
</div></div></div><div class="linenum" id="linenum-7"><div class="leftcolumn" id="leftcolumn-7"><div class="linenumber">7</div><div class="sentence"># AUTONOMY AND ITS CONTINGENCIES
</div></div></div><div class="linenum" id="linenum-8"><div class="leftcolumn" id="leftcolumn-8"><div class="linenumber">8</div><div class="sentence"># MAPPING NETWORKS</div></div></div>
<div class="linenum" id="linenum-9"><div class="leftcolumn" id="leftcolumn-9"><div class="linenumber">9</div><div class="sentence">
</div></div></div><div class="linenum" id="linenum-10"><div class="leftcolumn" id="leftcolumn-10"><div class="linenumber">10</div><div class="sentence">
</div></div></div><div class="linenum" id="linenum-11"><div class="leftcolumn" id="leftcolumn-11"><div class="linenumber">11</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-11">
<div class="comment" id="comment-11">
<span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: Within the context about the Special Issue, dependency in my case is very much about technical question, specifically about the structure of internet protocols. It's about the structure of how my server has been built that my annotation bot has installed in. I am very much looking at this technical dependency of the protocol here.
(11:15PM on April 01, 2019) </span>
</div>
<div class="comment" id="comment-11"><span class="comment-text" style="border-bottom: 2px solid rgb(100,216,184);">bootje: It all came from the first day of our Insfrastructour, where we visited each home to host our server. There were many frustrations whilst installing servers. During the setting up our networks, I started to be interested in dependency.
(12:31AM on April 02, 2019) </span></div><img src="./output/infratour.png"/>
</div>
</div>
<div class="linenum" id="linenum-12">
<div class="leftcolumn" id="leftcolumn-12">
<div class="linenumber">12</div><div class="sentence">
<b>INTRODUCTION</b>
</div>
</div>
<div class="rightcolumn" id="rightcolumn-12">
</div>
</div>
<div class="linenum" id="linenum-13">
<div class="leftcolumn" id="leftcolumn-13">
<div class="linenumber">13</div>
<div class="sentence">
</div>
</div>
<div class="rightcolumn" id="rightcolumn-13">
<div class="comment" id="comment-13">
<span class="comment-text" style="border-bottom: 2px solid rgb(70,73,196);">bootje: This is an annotated reader, an XMPP based publishing tool, that I developed as a way to comment my thoughts on the subject of dependencies in our network. (11:06PM on April 01, 2019) </span>
</div>
<div class="comment" id="comment-13">
<span class="comment-text" style="border-bottom: 2px solid rgb(80,190,112);">bootje: In this reader, some of thoughts are centered around my server, whereas some others are about a new protocol that I learned, the XMPP. And the other is a publishing tool I made, the Annotation Bot.
(11:12PM on April 01, 2019) </span>
</div>
<div class="comment" id="comment-13">
<span class="comment-text" style="border-bottom: 2px solid rgb(20,102,98);">bootje: These three layers are the infrastructures I made to host, to chat, and to publish. The first infrastructure is: My server — A hosting infrastructure where I talk about a dependency map, a web tool for tracing the routers, and some situations I went through whilst installing the server. Secondly, an XMPP(Extensible Messaging and Presence Protocol) that is a chatting infrastructure which I eventually made my own tool with. Last but not least, an Annotation Bot as a media tool — A publishing infrastructure that I had been developing as a way to annotate some thoughts. (11:16PM on April 01, 2019) </span>
</div>
<div class="comment" id="comment-13">
<span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: This reader is an ongoing project, sometimes I leave the questions or don't answer myself yet. Please feel free to annotate here with the guest account I provide for you. Enjoy your annotating experience.
(11:17PM on April 01, 2019) </span>
</div>
<div class="comment" id="comment-13">
<span class="comment-text" style="border-bottom: 2px solid rgb(240,150,100);">bootje: <br/>Guest account: guest@please.undo.undo.it<br/>
Password: guestpassword<br/>
(11:17PM on April 01, 2019) </span>
</div>
<img src="./output/Screenshot 2019-04-01 at 23.22.07.png"/>
<img src="./output/Screenshot 2019-04-01 at 22.58.44.png"/>
</div></div>
<div class="linenum" id="linenum-14"><div class="leftcolumn" id="leftcolumn-14"><div class="linenumber">14</div><div class="sentence"><b>ANNOTATED GLOSSARY</b>
</div></div></div><div class="linenum" id="linenum-15"><div class="leftcolumn" id="leftcolumn-15"><div class="linenumber">15</div><div class="sentence"> ANNOTAION BOT
</div></div><div class="rightcolumn" id="rightcolumn-15"><div class="comment" id="comment-15"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: Annotation Bot is an XMPP based web-publishing tool to annotate texts associated with thoughts, images, and sources. With this tool, a user can add comments or image references from any XMPP client via several digital devices.<br/>(09:57PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-16"><div class="leftcolumn" id="leftcolumn-16"><div class="linenumber">16</div><div class="sentence"> DEPENDENCIES
</div></div><div class="rightcolumn" id="rightcolumn-16"><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(35,45,107);">guest: The term "dependencies" incorporates not only technical factors such as physical access to a router, but also social dependencies, such as whether or not we had to ask anyone for permission to use the network. (11:55AM on April 12, 2019) </span></div></div></div><div class="linenum" id="linenum-17"><div class="leftcolumn" id="leftcolumn-17"><div class="linenumber">17</div><div class="sentence"> OUR NETWORK
</div></div><div class="rightcolumn" id="rightcolumn-17"><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'b-e-e-t.r-o-o-t.net' (09:59PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: ' ciao.urca.tv' (10:00PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'richfolks.club' (10:00PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'nothat.bad.mn' (10:00PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: ' p.lions.es' (10:00PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'foshan-1992.pw' (10:01PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'please.undo.undo.it'(10:01PM on April 02, 2019) </span></div><div class="comment" id="comment-17"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: 'sweetandsour.chickenkiller.com' (10:01PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-18"><div class="leftcolumn" id="leftcolumn-18"><div class="linenumber">18</div><div class="sentence"> TCP/IP
</div></div><div class="rightcolumn" id="rightcolumn-18"><div class="comment" id="comment-18"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: They are two protocols (TCP &amp; IP) that allows to establish communication between computers. Now widely adopted as a network standard, its archetype is the Defense Data Network, developed as part of Department of Defense.
(11:12PM on April 01, 2019) </span></div><div class="comment" id="comment-18"><span class="comment-text" style="border-bottom: 2px solid rgb(100,216,184);">bootje: I use two computer network protocols: TCP/IP(Transmission control protocol/Internet protocol) that TCP divides a message or files into packets that are transmitted over the Internet and then reassembled when they reach their destination, and IP is responsible for the address of each packet so that it gets to the correct destination. It is a communication protocol for enabling smooth connunication within the local area network. I am relying on these protocol within my server. (12:29AM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-19"><div class="leftcolumn" id="leftcolumn-19"><div class="linenumber">19</div><div class="sentence"> DNS
</div></div><div class="rightcolumn" id="rightcolumn-19"><div class="comment" id="comment-19"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: The Domain Name System (DNS) is a hierarchical decentralized naming system for computers, services, or other resources connected to the Internet or a private network. DNS is in the application layer within IP Suite. (11:52PM on April 01, 2019) </span></div></div></div><div class="linenum" id="linenum-20"><div class="leftcolumn" id="leftcolumn-20"><div class="linenumber">20</div><div class="sentence"> HTTP
</div></div><div class="rightcolumn" id="rightcolumn-20"><div class="comment" id="comment-20"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: The Hypertext Transfer Protocol (HTTP) is an application protocol for distributed, collaborative, hypermediainformation systems. HTTP is the foundation of data communication for the World Wide Web, where hypertextdocuments include hyperlinks to other resources that the user can easily access, for example by a mouse click or by tapping the screen. HTTP was developed to facilitate hypertext and the World Wide Web. (03:53PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-21"><div class="leftcolumn" id="leftcolumn-21"><div class="linenumber">21</div><div class="sentence"> SSH
</div></div><div class="rightcolumn" id="rightcolumn-21"><div class="comment" id="comment-21"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network. Typical applications include remote command-line login and remote command execution, but any network service can be secured with SSH. On application layer of IP Suite. (07:19PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-22"><div class="leftcolumn" id="leftcolumn-22"><div class="linenumber">22</div><div class="sentence"> XMPP
</div></div><div class="rightcolumn" id="rightcolumn-22"><div class="comment" id="comment-22"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Extensible Messaging and Presence Protocol (XMPP) is a communication protocol for message-oriented middlewarebased on XML (Extensible Markup Language). It enables the near-real-time exchange of structured yet extensible data between any two or more network entities. Originally named Jabber, the protocol was developed by the homonym open-source community in 1999 for near real-time instant messaging (IM), presence information, and contact listmaintenance. Designed to be extensible, the protocol has been used also for publish-subscribe systems, signalling for VoIP, video, file transfer, gaming, the Internet of Things (IoT) applications such as the smart grid, and social networking services. On application layer of Internet Protocal Suite. (07:20PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-23"><div class="leftcolumn" id="leftcolumn-23"><div class="linenumber">23</div><div class="sentence"> ROUTER
</div></div><div class="rightcolumn" id="rightcolumn-23"><div class="comment" id="comment-23"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: A router is a networking device that forwards data packets between computer networks. Routers perform the traffic directing functions on the Internet. (07:21PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-24"><div class="leftcolumn" id="leftcolumn-24"><div class="linenumber">24</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-24"></div></div><div class="linenum" id="linenum-25"><div class="leftcolumn" id="leftcolumn-25"><div class="linenumber">25</div><div class="sentence"><b>SERVER — A HOSTING INFRASTRUCTURE</b>
</div></div></div>
<div class="linenum" id="linenum-26">
<div class="leftcolumn" id="leftcolumn-26">
<div class="linenumber">26</div><div class="sentence"> The Dependency Map <div><div class="map"><img src="./output/dependency-map.jpg"/></div></div></div>
</div>
<div class="rightcolumn" id="rightcolumn-26">
<div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(244,240,52);">bootje: An explanation of the dependency map<br/>(11:03PM on April 01, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(80,190,112);">bootje: 1. Technically to be able to host your own server, you need a physical home where you can connect the ethernet cable with your router that is joined to Internet provided by Internet service provider(ISP). In my case, Artemis' house is a place we have the main router, with the Internet provider 'Telfort', that allows her to host the server, 77.172.158.66 with a domain name 'please.undo.undo.it'. (11:03PM on April 01, 2019) </span></div><img src="./output/02 Artemis - 77.172.158.66.png"/><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(184,220,204);">bootje: 2.
The main local area network brunched out to give permission to create another severs which are: 'sweetandsour.chickenkiller.com', and 'nothat.bad.mn'. Seemingly both local area network(LAN) looks fully independent on each other from their domain name.<br/>In actuality, 'sweetandsour.chickenkiller.com' and 'nothat.bad.mn' are living off in the 'please.undo.undo.it' with extra public port numbers of '4444' and '3333' which was created with the lan port 80. Therefore 'sweetandsour.chickenkiller.com' has an IP address of '77.172.158.66:4444' and '77.172.158.66:3333' is the IP address of 'nothat.bad.mn'.
(11:05PM on April 01, 2019) </span></div>
<!-- <img src="./output/myweb.png"/><img src="./output/myweb1.png"/>
--><img src="./output/rita.png"/><img src="./output/rita2.png"/>
<div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: 2.1 Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network.
(11:09PM on April 01, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: 2.2 Apache is a web/ HTTP Server, a free and open-source cross-platform web server. (11:11PM on April 01, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: 3. This is an account for logging into an XMPP client. As you can see after the username, we're sharing the host's domain name again. This has to do with the fact of using one local area network. If someone else would like to join to make an account for an XMPP client, the person needs to ask to receive one from the host. (11:34PM on April 01, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: 3. This is an account for logging into an XMPP client. As you can see after the username, we're sharing the host's domain name again. This has to do with the fact of using one local area network. If someone else would like to join to make an account for an XMPP client,the person needs to ask to receive one from the host. (12:13AM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: 3-1. Once you have account, it is possible to log in via any digital devices such as phone, laptop, desktop, Ipad and so on.
(12:13AM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(100,216,184);">bootje: 4. This is an XMPP client where we can log in to create channels from an account we created from the local area network of the host. After logged into an XMPP client(server), it's possible to create any channel, meaning that you can be a host of channel or join the existed channel based upon the server of your account. (12:29AM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(109,158,146);">bootje: 5. This is an annotation bot channel in which you annotate your comments in. In order to activate the channel, you need to stay inside the server where the Python script is located in, in this case, 'sweetandsour.chickenkiller.com'. The Python script can be run by entering an XMPP account with the channel name in Terminal, an interface in which you can type and execute text based commands. (10:53AM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(116,39,140);">bootje: 6. Python script is built upon an XMPP library called Slixmpp, Argparse (A parser for command-line), Beautiful Soup (A Python library for pulling data out of HTML and XML files), Pickle/.PKL file (A Python library for serializing and de-serializing an object structure in Python), Urllib (A Python package that collects several modules for working with URLs.), and using TXT file (An unformatted generic text content file) and a stylesheet file. (02:15PM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(116,39,140);">bootje: 7. An HTML file will be generated inside the server 'sweetandsour.chickenkiller.com' when running the Python script in Terminal.
(02:39PM on April 02, 2019) </span></div><div class="comment" id="comment-16"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: 8. Screen is a command line that offers you to remotely run the Python script persistently. This means you can have your annotation bot run all all times in your server as long as the server is online.
(03:29PM on April 02, 2019) </span></div>
</div></div>
<div class="linenum" id="linenum-27"><div class="leftcolumn" id="leftcolumn-27"><div class="linenumber">27</div><div class="sentence"> Why couldn't I host my server at home?
</div></div><div class="rightcolumn" id="rightcolumn-27"><div class="comment" id="comment-27"><span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: Sharing on my own experience living in Holland as an international student, I had humongous amount of belongings in my previous place in Den Haag, it was such a big problem to move out with all the furnitures and the home appliances, so I sold everything of what I bought, and moved into the new place.
(11:16PM on April 01, 2019) </span></div><div class="comment" id="comment-27"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: Currently I'm living in the apartment owned by a housing company called Holland2Stay, mostly international expats and students stay, where everything, including a bed, a table, a sofa, drawers, dish plates, cups, wineglasses, even an iron, mini spoons are all included as a full package. Obviously Internet service was included too, and you only needed to purchase a router. It seems very convinient, however, when I tried hosting my server in the router, it never made me pleasent. The central network system where they control all the routers connected to, is prohibited me from hosting my server because I couldn't have access to the router. Eventually I can't install any other server under this network that's highly secured. The housing company(Holland2Stay) has a bigger power on the network that I can't do anything with my Internet which I pay for my own service. (12:15AM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 00.18.31.png"/><img src="./output/My internet router webpage.png"/><div class="comment" id="comment-27"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: As a student in Holland, you live in housing where everything is provided for you. Everything is included even Internet. So I didn't need to apply for the Internet company, but just needed to plug in my router at home. Once I had Internet connection problem, which have come from the main server of my apartment, everyone in this apartment couldn't use Internet for some periods.
(03:33PM on April 02, 2019) </span></div><div class="comment" id="comment-28"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Although I'm hosting my server, I feel that I have a sense of distance from my server that I don't tend to use it often for such a long time. While my classmates made use of it for saving files and images, I left my server empty for quite long time. Because I am not physically possess my sever at home nor I didn't want to bother her for asking to visit her checking my device, I tend to forget using it nor thinking of it. Moreover if she doesn't allow me to either visit her to fix my device that is connected to my server or if there is a disconnection from ethernet cable, her network will disjoin from me. (12:25AM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-28"><div class="leftcolumn" id="leftcolumn-28"><div class="linenumber">28</div><div class="sentence"> What solution I found around?
</div></div><div class="rightcolumn" id="rightcolumn-28"><div class="comment" id="comment-28"><span class="comment-text" style="border-bottom: 2px solid rgb(232,57,52);">bootje: What kinds of unexpected situation occured?<br/>A contingency plan: I became technically dependent on someone: hosting my server at Artemis' place where her server also stays in. Partly my server is separated from hers because I'm not sharing server with her, but with her router(machine). Being hosted on own server at someone else's place doesn't feel that I am fully dependent on my server. I am dependent on someone's physical space, router, Internet provider, electricity, time, even financially... If any of them changes by her own freedom of choice, I will forcefully have to change my situation that is caused by the host's selection. (12:22AM on April 02, 2019) </span></div><div class="comment" id="comment-28"><span class="comment-text" style="border-bottom: 2px solid rgb(100,216,184);">bootje: For the second best plan to connect with my server, not physically but in a network way: I became technically dependent on another protocol called SSH(Secure Shell) that is a cryptographic network protocol for operating network services securely over an unsecured network. Being dependent on SSH protocol, I am virtually able to be connected to my server. Again, my ssh connection will be broken down if one of those factors I mentioned above has become a problem. (12:26AM on April 02, 2019) </span></div><img src="./output/ssh.png"/></div></div><div class="linenum" id="linenum-29"><div class="leftcolumn" id="leftcolumn-29"><div class="linenumber">29</div><div class="sentence"> Layers of Parasitism
</div></div><div class="rightcolumn" id="rightcolumn-29"><div class="comment" id="comment-29"><span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: One form of my parasitism is a social parasitism that is when an species relies on another species to raise its young. In my case, in order to raise my own network, I become a parasite who stays in Artemis' router to host my server. When I succeeded becoming a technical parasite, I got my Internet Protocol address (IP address): 77.172.158.66:4444. Here I can see my success on becoming a technical parasite with the port number :4444. I am officially part of the host 77.172.158.66 being an semi-dependent as '4444'. By having the port number '4444', I claim my own independent space, however I am technically leaving off inside Artemis' local area network(LAN). Therefore I have to rely on good will because she is in more powerful position than me. (11:38PM on April 01, 2019) </span></div><img src="./output/my IP address.png"/><div class="comment" id="comment-29"><span class="comment-text" style="border-bottom: 2px solid rgb(232,57,52);">bootje: Dependency is where there is a power dynamic, some sort of giving permission to someone else to do something. One person being more powerful than others because one has something that the others doesn't have. Therefore the weak need to be parasitic to the host.
(12:23AM on April 02, 2019) </span></div><div class="comment" id="comment-30"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Is then Artemis independent? She is reliant on her router in order to give me permission to host my server and hers. Her router is connected to the Eternet cable that is one of the most common forms of network cable used on wired networks. And if she disconnects the Ethernet cable from her router, she and I will be disconnected from the server too. Likewise, if she doesn't pay the Internet fee or her contract is finished, then she'll lose her network too. (02:41PM on April 02, 2019) </span></div><img src="./output/router artemis.png"/><div class="comment" id="comment-29"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: Relying on someone else's network to host my own server means that it's the beginning of an endless parasitic situation. Being a bloodsucker feels much more pressures than being a host because you have many technical, physical and practical concerns come along while being dependent on the host. Even if I have my own server hosted, that doesn't mean that I have full control over it. Over the few months, my server has been staying at my host's server trying to be dependent on its own situation. Living off at someone else's bring you a mixture feeling of being useless sometimes.. (03:01PM on April 02, 2019) </span></div><div class="comment" id="comment-29"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: I'm parasitic on someone to be able to live my own. I am parasitic in Artemis' server, meaning that my sever will be dependent on her decision. How ironic it is to be autonomous by parasiting on someone else. (03:30PM on April 02, 2019) </span></div><img src="./output/artemis1.png"/><img src="./output/artemis3.png"/><div class="comment" id="comment-29"><span class="comment-text" style="border-bottom: 2px solid rgb(94,26,236);">bootje: many 'sorry' and 'thank you' from my side.. (04:35PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-30"><div class="leftcolumn" id="leftcolumn-30"><div class="linenumber">30</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-30"></div></div><div class="linenum" id="linenum-31"><div class="leftcolumn" id="leftcolumn-31"><div class="linenumber">31</div><div class="sentence"> <b>— TRACEROUTE</b>
</div></div></div><div class="linenum" id="linenum-32"><div class="leftcolumn" id="leftcolumn-32"><div class="linenumber">32</div><div class="sentence"> What is Traceroute?
</div></div><div class="rightcolumn" id="rightcolumn-32"><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(184,220,204);">bootje: Traceroute is a network diagnostic tool to map the journey that a packet of IP network undertakes from its source(website) to its destination(website). In simple language, it traces the exact route taken to reach the website from your IP address. (11:08PM on April 01, 2019) </span></div><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(109,158,146);">bootje: When we try reaching to one website, information or requests went from your computer don't reach the final destination(website) in a single jump because there are many networks(Telecommunication companies) involved in between. (10:53AM on April 02, 2019) </span></div><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(116,39,140);">bootje: So when tracing the router to a random website, there are some hops that show telecommunication companies with IP addresses including a speed it has taken during the journey. (02:45PM on April 02, 2019) </span></div><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(116,39,140);">bootje: A hop is a journey from one source(server) to destination(server). (02:46PM on April 02, 2019) </span></div><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(176,45,254);">bootje: Milliseconds is the amount of time it takes to make a hop
(02:47PM on April 02, 2019) </span></div><div class="comment" id="comment-32"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: A packet is the information that travels along the traceroute
(03:35PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-33"><div class="leftcolumn" id="leftcolumn-33"><div class="linenumber">33</div><div class="sentence"> What do you see from Traceroute?
</div></div><div class="rightcolumn" id="rightcolumn-33"><img src="./output/01 traceroute explanation.png"/><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(109,158,146);">bootje: The output explains how the server at home traveled to the final destination: sweetandsour.chickenkiller.com (10:55AM on April 02, 2019) </span></div><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(116,39,140);">bootje: The first line shows when I Iogged in Terminal, and next line gives what command I used for tracing the router. And there is a third line that shows the Domain Name of my server with the IP address of '77.172.158.66', which, technically, is not mine. (02:48PM on April 02, 2019) </span></div><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: My address would be '77.172.158.66:4444' that has an extra port number because she was willing to share her local are network with another port number. Therefore this address without the port number is technically belongs to Artemis. This means that the IP address shown in Terminal won't lead me to 'sweetandsour.chickenkiller.com' but to to Artemis': 'please.undo.undo.it'.
(02:48PM on April 02, 2019) </span></div><img src="./output/port number.png"/><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: I can have a detailed look into each hop between the servers. The first hop is the Internet gateway on the network. It is a private IP address that always starts with '192.168...' A private IP address is just for my router, my network and me. In other words, it is reserved for internal use behind a router apart from the public. (02:56PM on April 02, 2019) </span></div><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: Next, there is 'prioritytelecom.net' with the IP address '80.113.23.145' on the second hop which is a static IP address of Ziggo, an Internet service provider(ISP). (03:36PM on April 02, 2019) </span></div><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Likewise, the third hop is a router on the network 'Ziggo Services B.V.', where they use different IP address '213.126.178.209', is hosted on. I assumed Ziggo has several routers in different locations.(03:44PM on April 02, 2019) </span></div><img src="./output/ziggo.png"/><div class="comment" id="comment-33"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: The Fourth hop shows another Internet service provider called Liberty Global, originally an American international telecommunication company that has a brunch in the Netherlands. The 4th, 5th and 6th are the routers on the Liberty Global telecommunication company because of its IP address that starts with '84.116.' In conclusion, there were 6 hops that was needed to go to my server.
(03:54PM on April 02, 2019) </span></div><img src="./output/liberty BV.png"/><img src="./output/Liberty global.png"/></div></div><div class="linenum" id="linenum-34"><div class="leftcolumn" id="leftcolumn-34"><div class="linenumber">34</div><div class="sentence"> How does my server travel to others?
</div></div><div class="rightcolumn" id="rightcolumn-34"><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: Based on my experience on tracing the router from A to B, I was wondering how my server is relating to others. Will my server be depending on anything when it travels to another server? If so, what does my server depends on? (11:39PM on April 01, 2019) </span></div><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: When visiting another website from my home server, what route will I reach to the destination? What can I see when we visit each other's servers?
(02:57PM on April 02, 2019) </span></div><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: I started mapping who I am dependent onto make a connection by tracing the router from each other's server. So I SSH-ed to my server with the username 'bootje', and entered into my server in order to install it: sudo apt-get install traceroute. (02:57PM on April 02, 2019) </span></div><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(141,13,10);">bootje: After finished installing it, I started tracing the router to 'b-e-e-t.r-o-o-t.net', ' ciao.urca.tv', 'richfolks.club', 'nothat.bad.mn', ' p.lions.es ', 'foshan-1992.pw', 'please.undo.undo.it', and to my own server 'sweetandsour.chickenkiller.com'. (03:37PM on April 02, 2019) </span></div><img src="./output/trace-beetroot.png"/><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: Next I asked my fellows to do the same thing: So they traced the router from their server to others including mine. (03:54PM on April 02, 2019) </span></div><img src="./output/traceroute_eachother.jpg"/><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Tracing the routers between 'sweetandsour.chickenkiller.com' and 'ciao.urca.tv'
(09:01PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 20.55.15.png"/><img src="./output/Screenshot 2019-04-02 at 20.55.26.png"/>
<div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Tracing the routers between 'nothat.bad.mn' and 'foshan-1992.pw' (09:02PM on April 02, 2019)</span></div><img src="./output/Screenshot 2019-04-02 at 20.55.00.png"/><img src="./output/Screenshot 2019-04-02 at 20.54.52.png"/>
<div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Tracing the routers between 'richfolks.club' and 'please.undo.undo.it' (09:03PM on April 02, 2019) </span></div>
<img src="./output/Screenshot 2019-04-02 at 20.54.30.png"/><img src="./output/Screenshot 2019-04-02 at 20.54.21.png"/>
<div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: Tracing the routers between 'b-e-e-t.r-o-o-t.net' and 'foshan-1992.pw' (09:25PM on April 02, 2019) </span></div>
<img src="./output/Screenshot 2019-04-02 at 21.19.43.png"/><img src="./output/Screenshot 2019-04-02 at 21.19.30.png"/><div class="comment" id="comment-24"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: Tracing the routers between 'ciao.urca.tv' and 'foshan-1992.pw' (09:28PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 21.19.18.png"/><img src="./output/Screenshot 2019-04-02 at 21.19.06.png"/><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: Tracing the routers between 'nothat.bad.mn' and 'foshan-1992.pw' (09:32PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 21.18.56.png"/><img src="./output/Screenshot 2019-04-02 at 21.18.47.png"/><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(206,203,202);">bootje: Tracing the routers between 'please.undo.undo.it' and 'foshan-1992.pw' (09:33PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 21.18.38.png"/><img src="./output/Screenshot 2019-04-02 at 21.18.31.png"/><div class="comment" id="comment-34"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: This experiment showed me on how many hops we need to pass to get to each other's server. Besides that I could anticipate the predictable route that was taken during the journey by comparing the route from both sides. (03:55PM on April 02, 2019) </span></div></div></div>
<div class="linenum" id="linenum-35"><div class="leftcolumn" id="leftcolumn-35"><div class="linenumber">35</div><div class="sentence"> What are the traceroute results?</div></div><div class="rightcolumn" id="rightcolumn-35"><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: When I tracerouted from my server to Biyi's: traceroute foshan-1992.pw, I could see there are three telecommunication company involved: KPN, Swipnet backbone and Tele2. When Biyi traced the router to my server (traceroute sweetandsour.chickenkiller.com), it showed same telecommunication companies: Tele2, swipnet backbone and KPN.
(11:47PM on April 01, 2019) </span></div><img src="./output/bo to biyi.png"/><img src="./output/biyi to bo.png"/><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: The result shows me whenever I or Biyi would visit each other's website, we will have to pass by the three routers from the aforementioned company. (11:49PM on April 01, 2019) </span></div><img src="./output/bo-to-biyi.jpg"/><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: What if the Traceroute cannot find the routers from three companies? The solution would be: My server will find another way to get to the destination, so does hers.
(02:58PM on April 02, 2019) </span></div><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: From this research, I convey the Traceroute is not showing us how the server is relying on something because it doesn't show the hierarchy of our network. But it gives the information such as how my server travels through the routers provided by telecommunication company.
(02:59PM on April 02, 2019) </span></div><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(111,131,118);">bootje: What if one of those telecommunication companies stop their business and remove the router? Then my server can't approach to the destination unless there are still some routers provided by another company.
(03:45PM on April 02, 2019) </span></div><div class="comment" id="comment-35"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: For me dependency is about who owns the power, and to whom it has more power to control the situation. I see the relation of a power ownership here: When visiting someone else's server, I should have some routers that is a part of a journey to the destination. Moreover I need telecommunication company, who owns the router, to make connections too. If there would be no companies, there will be routers, which means there will be no hops at all: Eventually my server wouldn't be able to travel to the destination. Each hop is a bridge between two server in our network we made, and if the bridge broke, you can't reach to the final destination unless there is an alternative bridge instead. (03:45PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-36"><div class="leftcolumn" id="leftcolumn-36"><div class="linenumber">36</div><div class="sentence"> Does telecommunication companies own power?
</div></div><div class="rightcolumn" id="rightcolumn-36"><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(240,32,143);">bootje: Traceroute research shows me a journey to the destination. In this journey, there are at least 1 to 30 hops that shows a router with its IP address of telecomunication company. While tracing the route from 'sweetandsour.chickenkiller.com' to 'foshan-1992.pw', I got to know there are three company involved in several routers. With a small research on the companies, I have found out that Swipnet is Sweden's one of the first commercial Internet service provider in the early 1990s. (11:42PM on April 01, 2019) </span></div><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: And the service is now closed down by Tele2 Sweden, which owned Swipnet since 1994. This means that Swipnet will be disappeared by Tele2 who owns the power. If Tele2 fully takes over the Swipnet, the route of the journey from the servers will be totally different. (11:53PM on April 01, 2019) </span></div><img src="./output/swipnet to tele2.png"/><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: About owning the power between the telecommunication company, there is another taking over situation between Tele2 and T-Mobile. According to the government agency, T-Mobile will takeover Tele2 officially, and Tele2 customers will probably be transferred to a comparable or better T-Mobile subscription. (11:54PM on April 01, 2019) </span></div><img src="./output/Screenshot 2019-03-31 at 17.37.50.png"/><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: There is another small anecdote: When Biyi tried installing a new Internet from Tele2, KPN was taking part of the system for Tele2. Apparently Tele2 and KPN cohabitates each other for their own convenience.
(11:57PM on April 01, 2019) </span></div><img src="./output/kpn.png"/><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: I am guessing the final parasitic structure is: Swipnet &lt; Tele2 &lt; T-Mobile, Tele2 &lt; KPN (02:59PM on April 02, 2019) </span></div><div class="comment" id="comment-36"><span class="comment-text" style="border-bottom: 2px solid rgb(141,13,10);">bootje: The situation of being eaten by another and cohabitation gives me a thought of how the telecommunication companies are hierarchically related each other. Through the Traceroute exercise, I found there is the power constrcution in the concept of Traceroute.
(03:40PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-37"><div class="leftcolumn" id="leftcolumn-37"><div class="linenumber">37</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-37"></div></div><div class="linenum" id="linenum-38"><div class="leftcolumn" id="leftcolumn-38"><div class="linenumber">38</div><div class="sentence"><b>XMPP — A CHATTING INFRASTRUCTURE</b>
</div></div></div><div class="linenum" id="linenum-39"><div class="leftcolumn" id="leftcolumn-39"><div class="linenumber">39</div><div class="sentence"> What is XMPP?
</div></div><div class="rightcolumn" id="rightcolumn-39"><div class="comment" id="comment-39"><span class="comment-text" style="border-bottom: 2px solid rgb(51,1,137);">bootje: XMPP(Extensible Messaging and Presence Protocol) is a communication protocol that allows systems to talk to each other. An XMPP server provides basic messaging features, and you can use to run your own XMPP service over the Internet or on a local area network.
(11:58PM on April 01, 2019) </span></div></div></div><div class="linenum" id="linenum-40"><div class="leftcolumn" id="leftcolumn-40"><div class="linenumber">40</div><div class="sentence"> How does XMPP work?
</div></div><div class="rightcolumn" id="rightcolumn-40"><div class="comment" id="comment-40"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: There are bunch of XMPP clients that are available. An XMPP clients is any software or application that enables you to connect for instant messaging with other people over the Internet. Basically it's like a platform where you open your chatting room. There are many free clients you can use to open the chatting, for many different devices and operating systems. In my case, I used an XMPP client called 'Converse'. (11:58PM on April 01, 2019) </span></div><img src="./output/Screenshot 2019-04-01 at 17.09.06.png"/><img src="./output/Screenshot 2019-04-01 at 17.09.38.png"/><img src="./output/xmpp.png"/><div class="comment" id="comment-40"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: In order to use an XMPP protocol, first, you need an account to log in via client. Having your own domain name system on your server, you can create unlimited amount of account for users who shares your local area network. Or you can log in to different devices such as phone, laptop, desktop, ipad with one account. Once you're logged in, you can start creating any of channel you'd like to make, and start chatting!
(03:40PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-41"><div class="leftcolumn" id="leftcolumn-41"><div class="linenumber">41</div><div class="sentence"> How was I dependent on?
</div></div><div class="rightcolumn" id="rightcolumn-41"><div class="comment" id="comment-41"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: Since I am a parasite on Artemis' local area network(LAN), I had no choice but to create my account from her network. Although I have my own server with the port number '4444' provided by the host, yet I am residing in her local are network. Eventually I couldn't create my own account. Again this idea of parasitization is coming back: I don't have the right to change neither my account name nor create another account.
(03:01PM on April 02, 2019) </span></div><div class="comment" id="comment-41"><span class="comment-text" style="border-bottom: 2px solid rgb(247,92,86);">bootje: Therefore when creating an XMPP account, I had to ask her permission again. whereas, she never asked me to get permission to do something because she didn't need to.
(03:46PM on April 02, 2019) </span></div><div class="comment" id="comment-41"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: After receiving an account, finally creating a channel is possible. In any channel I created, I can be a host myself. However, in order to make the channel, an address of groupchat is required. For that I need an local area network address, in my case, of course: Artemis' address: please.undo.undo.it. Every step of creating my own server to XMPP account to a channel: I needed her permission.
(03:56PM on April 02, 2019) </span></div><img src="./output/artemis2.png"/><div class="comment" id="comment-42"><span class="comment-text" style="border-bottom: 2px solid rgb(247,92,86);">bootje: Although an XMPP protocol is meant to be a free and open-source chat client, I can't be fully independent as a user in this protocol. From A to Z, I am fully relying on her. (03:46PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-42"><div class="leftcolumn" id="leftcolumn-42"><div class="linenumber">42</div><div class="sentence">
</div></div><div class="rightcolumn" id="rightcolumn-42"></div></div><div class="linenum" id="linenum-43"><div class="leftcolumn" id="leftcolumn-43"><div class="linenumber">43</div><div class="sentence"><b>ANNOTATION BOT — A PUBLISHING INFRASTRUCTURE</b>
</div></div></div><div class="linenum" id="linenum-44"><div class="leftcolumn" id="leftcolumn-44"><div class="linenumber">44</div><div class="sentence"> What is Annotation Bot?
</div></div><div class="rightcolumn" id="rightcolumn-44"><div class="comment" id="comment-44"><span class="comment-text" style="border-bottom: 2px solid rgb(183,225,197);">bootje: Annotation Bot is an XMPP based web-publishing tool to annotate texts associated with thoughts, images, and sources. With this tool, a user can add comments or image references from any XMPP client via several digital devices. (03:26PM on April 02, 2019) </span></div><div class="comment" id="comment-44"><span class="comment-text" style="border-bottom: 2px solid rgb(93,202,162);">bootje: Annotation Bot can be used for the following purposes:
(03:26PM on April 02, 2019) </span></div><div class="comment" id="comment-44"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: — To add comments with multiple users at the same time remotely
(03:27PM on April 02, 2019) </span></div><div class="comment" id="comment-44"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: — To overview the transparency of ownership on commenting
(03:27PM on April 02, 2019) </span></div><div class="comment" id="comment-44"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: — As a collaborative publishing tool to discuss the contents
(03:27PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-45"><div class="leftcolumn" id="leftcolumn-45"><div class="linenumber">45</div><div class="sentence"> How was Annotation Bot installed?
</div></div><div class="rightcolumn" id="rightcolumn-45"><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(229,58,246);">bootje: To install the Annotation Bot, you need the following structures: a home server/an account/an XMPP client/ a channel/a TXT file. (03:28PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(141,13,10);">bootje: A home server means a place you store the HTML in which the file was created from a Python script runned by Terminal. (03:41PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(247,92,86);">bootje: As for creating an account, you need a server that allows you to create an account. (03:49PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(247,92,86);">bootje: An XMPP client can be selected depending on the user's preference.
(03:49PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: A Channel is a platform in XMPP client to upload comments and image references.
(03:51PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(13,1,192);">bootje: A TXT file is to store the original text you will annotate.
(03:59PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: The Annotation Bot is written in a Python language that requires some libraries and basic HTML/CSS structure. Before running the Python script inside your server, you need another software to install in order to use this software: Slixmpp, Argparse, Beautiful Soup, Pickle/.PKL file, Urllib. (03:59PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 19.29.34.png"/><img src="./output/Screenshot 2019-04-02 at 19.30.54.png"/><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(2,1,92);">bootje: Once you have all the libraries installed in the server and the original text is saved as TXT tile, you can go to an XMPP client you selected, in my case 'Converse'. After logging in with your account, A channel can be created. The channel will need an address that will be using when running the code. In my case: dependency-of-network@groups.please.undo.undo.it. (04:07PM on April 02, 2019) </span></div><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(87,179,40);">bootje: Finally you need the following command to run the Bot: python3 FileName.py --jid username@yourserver --room Achannelname@groups.yourserver --nick assign a name for your bot (04:08PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 18.40.27.png"/><div class="comment" id="comment-45"><span class="comment-text" style="border-bottom: 2px solid rgb(94,26,236);">bootje: After executing the code, a HTML is automatically generated at which you runs the Python script. And it's time to annotate!
(04:23PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-46"><div class="leftcolumn" id="leftcolumn-46"><div class="linenumber">46</div><div class="sentence"> How does Annotation Bot work?
</div></div><div class="rightcolumn" id="rightcolumn-46"><div class="comment" id="comment-46"><span class="comment-text" style="border-bottom: 2px solid rgb(141,13,10);">bootje: Once you have your TXT file ready, it will be used to create a HTML website automatically by Python script. It also generates line numbers which will guide you to annotate. (03:41PM on April 02, 2019) </span></div><div class="comment" id="comment-46"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: Next, you can start commenting by using'#comment linenumber yourcomment'. In case of inserting a photo, you could type '#image linenumber', then the Bot will guide you to upload a photo.
(03:50PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 19.48.45.png"/></div></div><div class="linenum" id="linenum-47"><div class="leftcolumn" id="leftcolumn-47"><div class="linenumber">47</div><div class="sentence"> What was happening when using it?
</div></div><div class="rightcolumn" id="rightcolumn-47"><div class="comment" id="comment-47"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: While using the Annotation Bot as a publishing tool, I have bumped with some unexpected situation that limited me to use because of some technical issues.
(03:50PM on April 02, 2019) </span></div><div class="comment" id="comment-47"><span class="comment-text" style="border-bottom: 2px solid rgb(200,130,92);">bootje: When using the Annotation Bot, the XMPP client kept logging out automatically, that I had to log in several times to connect to the client. Whenever I lose the connection from the client, I can't annotate anything.
(04:00PM on April 02, 2019) </span></div><div class="comment" id="comment-47"><span class="comment-text" style="border-bottom: 2px solid rgb(87,179,40);">bootje: Even though I was connected to the XMPP clients, I lost my annotation channel quite often for some reason. So I had to set a persistent configuration to my channel in order for the channel(room) should remain when it's empty. (04:08PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-01 at 17.13.52.png"/><div class="comment" id="comment-47"><span class="comment-text" style="border-bottom: 2px solid rgb(69,16,58);">bootje: In order to use the Bot, you need to be able to log in via an XMPP client, and for that you need to have your account. To be able to get an account, owning your own server is required. Or you can also ask others to make one account for you unless you want an account with your server. (04:09PM on April 02, 2019) </span></div><div class="comment" id="comment-47"><span class="comment-text" style="border-bottom: 2px solid rgb(94,26,236);">bootje: In my case, although I have self-hosted server, I couldn't manage to get my own account as I was a parasite on Artemis' local area network. So I asked her to create an account for me. (04:23PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-48"><div class="leftcolumn" id="leftcolumn-48"><div class="linenumber">48</div><div class="sentence"> What if?
</div></div><div class="rightcolumn" id="rightcolumn-48"><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(141,13,10);">bootje: If there is no Python language, I can't design the Annotation Bot.
(03:42PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: If I miss one library to download, I can't use my Annotation Bot.
(03:51PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(200,0,10);">bootje: If I don't have my account, I can't use my Annotation Bot.
(04:02PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(69,16,58);">bootje: If I don't have Artemis' server, I can't have my account.
(04:09PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(241,57,219);">bootje: If I don't have Artemis' server, I can't have my account.
(04:10PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(188,40,234);">bootje: If Artemis lose her WIFI connection, she can't have her server.
(04:14PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(188,40,234);">bootje: If she stop subscripting Telfort, she will lose her WIFI connection.
(04:15PM on April 02, 2019) </span></div><div class="comment" id="comment-48"><span class="comment-text" style="border-bottom: 2px solid rgb(49,125,74);">bootje: If Telfort will be takenover by T-Mobile, she will have to stop the Internet subscription. (04:16PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-49"><div class="leftcolumn" id="leftcolumn-49"><div class="linenumber">49</div><div class="sentence"> How does it dependent on others?
</div></div><div class="rightcolumn" id="rightcolumn-49"><div class="comment" id="comment-49"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: Setting up a server at home has an implicit level of autonomy, yet we're dependent on many levels in our network. One example could be: When using an XMPP, using the protocol already means that you're relying on a certain level. However, there is no such thing as a complete autonomy/dependency. (04:04PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-50"><div class="leftcolumn" id="leftcolumn-50"><div class="linenumber">50</div><div class="sentence">
</div></div></div><div class="linenum" id="linenum-51"><div class="leftcolumn" id="leftcolumn-51"><div class="linenumber">51</div><div class="sentence"><b>SCREEN</b>
</div></div></div><div class="linenum" id="linenum-52"><div class="leftcolumn" id="leftcolumn-52"><div class="linenumber">52</div><div class="sentence"> What is Screen?
</div></div><div class="rightcolumn" id="rightcolumn-52"><div class="comment" id="comment-52"><span class="comment-text" style="border-bottom: 2px solid rgb(201,253,110);">bootje: Screen is a command line that offers you to remotely run the Python script persistently. This means you can have your Annotation Bot run all the times in the server as long as the server is online.
(11:13PM on April 01, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 20.23.54.png"/></div></div><div class="linenum" id="linenum-53"><div class="leftcolumn" id="leftcolumn-53"><div class="linenumber">53</div><div class="sentence"> How to use it?
</div></div><div class="rightcolumn" id="rightcolumn-53"><div class="comment" id="comment-53"><span class="comment-text" style="border-bottom: 2px solid rgb(13,200,192);">bootje: Screen has to be installed where you save your Annotation Bot.
(03:52PM on April 02, 2019) </span></div><div class="comment" id="comment-53"><span class="comment-text" style="border-bottom: 2px solid rgb(241,57,219);">bootje: How to install: $ sudo apt install screen
(04:12PM on April 02, 2019) </span></div><div class="comment" id="comment-53"><span class="comment-text" style="border-bottom: 2px solid rgb(73,247,217);">bootje: To open a new terminal session: $ screen
(04:13PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 20.29.53.png"/><div class="comment" id="comment-53"><span class="comment-text" style="border-bottom: 2px solid rgb(188,40,234);">bootje: To show all the active screen sessions: $ screen -ls
(04:14PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 19.51.16.png"/><div class="comment" id="comment-53"><span class="comment-text" style="border-bottom: 2px solid rgb(49,125,74);">bootje: To Kill a screen session : $ screen -x -s 'screenname' kill
(04:17PM on April 02, 2019) </span></div><img src="./output/Screenshot 2019-04-02 at 20.28.31.png"/></div></div><div class="linenum" id="linenum-54"><div class="leftcolumn" id="leftcolumn-54"><div class="linenumber">54</div><div class="sentence"> Why do I need it?
</div></div><div class="rightcolumn" id="rightcolumn-54"><div class="comment" id="comment-54"><span class="comment-text" style="border-bottom: 2px solid rgb(241,57,219);">bootje: I started thinking about why I couldn't have my Annotation Bot on my laptop all the time. It is because I need to use my computer for other things, I can't have it run 24/7. (04:12PM on April 02, 2019) </span></div><div class="comment" id="comment-54"><span class="comment-text" style="border-bottom: 2px solid rgb(73,247,217);">bootje: Moreover when the Annotation Bot is running, I need a space in my network where I store the HTML generated by Annotation Bot. Because of its live collaborationism in network, I need to have it somewhere in online remotely running. (04:13PM on April 02, 2019) </span></div></div></div><div class="linenum" id="linenum-55"><div class="leftcolumn" id="leftcolumn-55"><div class="linenumber">55</div><div class="sentence">
</div></div></div><div class="linenum" id="linenum-56"><div class="leftcolumn" id="leftcolumn-56"><div class="linenumber">56</div><div class="sentence">Acknowledgement</div></div><div class="rightcolumn" id="rightcolumn-56"><div class="comment" id="comment-56"><span class="comment-text" style="border-bottom: 2px solid rgb(127,205,255);">bootje: The Network We (de)Served —
XPUB Special Issue #08 (08:11PM on April 02, 2019) </span></div><div class="comment" id="comment-56"><span class="comment-text" style="border-bottom: 2px solid rgb(100,216,184);">bootje: Brought to you by the Master of Arts in Fine Art and Design: Experimental Publishing (XPUB) of the Piet Zwart Institute, and Varia, Centre for Everyday Technology, Rotterdam, April 2019. (08:16PM on April 02, 2019)</span></div>
<div class="comment" id="comment-56"><span class="comment-text" style="border-bottom: 2px solid rgb(3,140,5);">bootje: . (11:31AM on April 08, 2019) </span></div></div></div>
</body>
<script src="https://issue.xpub.nl/08/cnn/cnn.js" type="text/javascript"></script>
<script>
converse.initialize({
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
show_controlbox_by_default: true
});
</script>
</html>

@ -0,0 +1,294 @@
#!/usr/bin/env python3
import logging
from getpass import getpass
from argparse import ArgumentParser
import datetime
import pickle
import numpy as np
import slixmpp
import ssl, os, requests, urllib
from bs4 import BeautifulSoup
from urllib.parse import quote as urlquote, unquote as urlunquote
nickname_color = {}
# import the pickled object, serializing and de-serializing a Python object)
def save_obj(obj, name):
with open(name + '.pkl', 'wb') as f:
pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)
def load_obj(name):
with open(name + '.pkl', 'rb') as f:
return pickle.load(f)
# make a numbered text
def make_numbered_text(input_text, output_html):
if not os.path.exists(output_html): # if output_html path does not exist
text = open(input_text, 'r') # open the txt file
lines = text.readlines() # to divide the text into lines in the form {{"This is line 1"},{"This is line 2"},...}
x = 1
with open(output_html, 'w') as new_html: # open the output_html with writing only as new_html
new_html.write('<html><head><link rel="stylesheet" href="style.css" type="text/css"/><meta '
'charset="utf-8"/></head><body>')
for line in lines: # for each line in the list of lines
new_html.write(
'<div class="linenum" id="linenum-{}"><div class="leftcolumn" id="leftcolumn-{}"><div class="linenumber">{}</div><div class="sentence">{}</div></div></div>'.format(
x, x, x, line))
x = x + 1
new_html.write('</body></html>')
print('I wrote a file', output_html)
# Get color from nickname_color dictionary. If it does not exist, create a color and save it
def get_nickname_color(nickname):
if nickname not in nickname_color: # If nickname is not in dict
color = list(np.random.choice(range(256), size=3)) # Generate random new color
nickname_color[nickname] = color # Save new color in dict
save_obj(nickname_color, 'nickname_color')
return nickname_color[nickname]
# (parameter variable,parameter variable,parameter variable)
def insert_comment_at_line(output_html, comment, line_number, nickname):
with open(output_html, 'r') as f:
text = f.read()
html = BeautifulSoup(text, 'html.parser')
div_id = 'linenum-{}'.format(line_number) # out comes linenum-line_number
line = html.find('div', {'id': div_id}) # find the div that has the id div_id (has the id linenum-line_number)
if not html.find('div', {
'id': 'rightcolumn-{}'.format(line_number)}): # if there is no div with id rightcolumn-line_number
# then make a new div with rightcolumn-line_number and class rightcolumn. Then, append it to the line variable.
right_column = html.new_tag("div")
right_column['id'] = 'rightcolumn-{}'.format(line_number)
right_column['class'] = 'rightcolumn'
line.append(right_column)
else:
right_column = html.find('div', {'id': 'rightcolumn-{}'.format(line_number)})
time = datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")
color = get_nickname_color(nickname)
print(color)
# new_comment = html.new_tag("comment") # make <comment></comment>
new_comment = html.new_tag("div") # make <comment></comment>
new_comment['id'] = 'comment-{}'.format(line_number)
new_comment['class'] = 'comment'
# new_comment['style'] = 'text-decoration: underline; -webkit-text-decoration-color: rgb(' + str(color[0]) + ',' + str(color[1]) + ',' + str(color[2])+');'
comment_text = html.new_tag("span")
comment_text['style'] = 'border-bottom: 2px solid rgb(' + str(color[0]) + ',' + str(color[1]) + ',' + str(color[2])+');'
#remove #comment <number>
comment = comment.split(' ',2)[2]
comment_text.string = nickname + ': ' + comment + ' (' + time + ') ' # make <comment>comment (the parameter variable)</comment>
comment_text['class'] = 'comment-text'
new_comment.append(comment_text)
right_column.append(new_comment)
print(line, comment, '#' + str(line_number) + '#')
print(div_id)
if line:
with open(output_html, 'w') as f:
right_column.append(new_comment)
f.write(html.decode())
def insert_media_at_line(output_html, mediafile, line_number):
with open(output_html, 'r') as f:
text = f.read()
html = BeautifulSoup(text, 'html.parser')
div_id = 'linenum-{}'.format(line_number)
line = html.find('div', {'id': div_id})
if not html.find('div', {'id': 'rightcolumn-{}'.format(line_number)}):
right_column = html.new_tag("div")
right_column['id'] = 'rightcolumn-{}'.format(line_number)
right_column['class'] = 'rightcolumn'
line.append(right_column)
else:
right_column = html.find('div', {'id': 'rightcolumn-{}'.format(line_number)})
print(line, mediafile, '#' + str(line_number) + '#')
print(div_id)
if line:
# notes to self write function to the detect media type
with open(output_html, 'w') as f:
new_image = html.new_tag("img", src=mediafile)
right_column.append(new_image)
f.write(html.decode())
class MUCBot(slixmpp.ClientXMPP):
def __init__(self, jid, password, room, nick, output):
slixmpp.ClientXMPP.__init__(self, jid, password)
self.room = room
self.nick = nick
self.output = output
self.current_line = 0
self.add_event_handler("session_start", self.start) # moment that it logs on
self.add_event_handler("groupchat_message", self.muc_message) # moment that someone start speaking someone
output = self.output
if not os.path.exists(output):
os.mkdir(output)
make_numbered_text('text.txt', 'dependencies-in-a-network.html')
def start(self, event):
self.get_roster()
self.send_presence()
# https://xmpp.org/extensions/xep-0045.html
self.plugin['xep_0045'].join_muc(self.room,
self.nick,
# If a room password is needed, use:
# password=the_room_password,
wait=True)
def muc_message(self, msg):
# Always check that a message is not the bot itself, otherwise you will create an infinite loop responding to your own messages.
if msg['mucnick'] != self.nick:
# Check if an OOB URL is included in the stanza (which is how an image is sent)
# (OOB object - https://xmpp.org/extensions/xep-0066.html#x-oob)
if len(msg['oob']['url']) > 0:
# UPLOADED IMAGE
# Send a reply
self.send_message(mto=msg['from'].bare,
mbody="Really? Oke. I'll add your photo for you, {}.".format(msg['mucnick']),
mtype='groupchat')
# Save the image to the output folder
url = msg['oob']['url'] # grep the url in the message
# urlunquote is like url to filename
filename = os.path.basename(urlunquote(url)) # grep the filename in the url
output = self.output
# if not os.path.exists(output):
# os.mkdir(output)
output_path = os.path.join(output, filename)
u = urllib.request.urlopen(url) # read the image data
new_html = open(output_path, 'wb') # open the output file
new_html.write(u.read()) # write image to file
new_html.close() # close the output file
# If we haven't set current line yet, prompt the user to do so
if self.current_line < 0:
self.send_message(mto=msg['from'].bare,
mbody="{}, before uploading an image, please use the following syntax: #image <line number>".format(
msg['mucnick']),
mtype='groupchat')
# Add image to stream
img = output_path
insert_media_at_line('dependencies-in-a-network.html', img, self.current_line)
else:
# TEXT MESSAGE
words = msg['body'].split()
linenum = words[1]
if msg['body'].startswith("#image"):
if (linenum.isdigit()):
self.current_line = int(words[1])
self.send_message(mto=msg['from'].bare,
mbody="Please now upload the image to be inserted on line {}.".format(
self.current_line),
mtype='groupchat')
else:
self.current_line = -1
self.send_message(mto=msg['from'].bare,
mbody="{}, please use the following syntax: #image <line number>".format(
msg['mucnick']),
mtype='groupchat')
if msg['body'].startswith("#comment"):
print(linenum)
if (linenum.isdigit()):
self.send_message(mto=msg['from'].bare,
mbody="Really? Oke. I'll add your comment that for you, {}.".format(
msg['mucnick']),
mtype='groupchat')
# output_html,comment,line_number,username
insert_comment_at_line('dependencies-in-a-network.html', msg['body'], linenum, msg['mucnick'])
else:
self.send_message(mto=msg['from'].bare,
mbody="{}, please use the following syntax: #comment <line number> <message>...".format(
msg['mucnick']),
mtype='groupchat')
if __name__ == '__main__':
# Setup the command line arguments.
parser = ArgumentParser() # making your own command line - ArgumentParser.
# output verbosity options.
parser.add_argument("-q", "--quiet", help="set logging to ERROR",
action="store_const", dest="loglevel",
const=logging.ERROR, default=logging.INFO)
parser.add_argument("-d", "--debug", help="set logging to DEBUG",
action="store_const", dest="loglevel",
const=logging.DEBUG, default=logging.INFO)
# JID and password options.
parser.add_argument("-j", "--jid", dest="jid", # jid = user
help="JID to use")
parser.add_argument("-p", "--password", dest="password",
help="password to use")
parser.add_argument("-r", "--room", dest="room",
help="MUC room to join")
parser.add_argument("-n", "--nick", dest="nick",
help="MUC nickname") # MUC = multi user chat
# output folder for images
parser.add_argument("-o", "--output", dest="output",
help="output folder, this is where the files are stored",
default="./output/", type=str)
args = parser.parse_args()
# Setup logging.
logging.basicConfig(level=args.loglevel,
format='%(levelname)-8s %(message)s')
if args.jid is None:
args.jid = input("User: ")
if args.password is None:
args.password = getpass("Password: ")
if args.room is None:
args.room = input("MUC room: ")
if args.nick is None:
args.nick = input("MUC nickname: ")
if args.output is None:
args.output = input("Output folder: ")
# Setup the MUCBot and register plugins. Note that while plugins may
# have interdependencies, the order in which you register them does
# not matter.
xmpp = MUCBot(args.jid, args.password, args.room, args.nick, args.output)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0045') # Multi-User Chat
xmpp.register_plugin('xep_0199') # XMPP Ping
xmpp.register_plugin('xep_0066') # Process URI's (files, images)
# Connect to the XMPP server and start processing XMPP stanzas.
xmpp.connect()
xmpp.process()
# Load color data
if os.path.exists("nickname_color.pkl"):
nickname_color = load_obj("nickname_color") # Load dictionary from file into variable (nickname_color)
Loading…
Cancel
Save