From c92b8f84705be8296018a744ba6a67994dae477b Mon Sep 17 00:00:00 2001 From: "Bohye.Woo" Date: Wed, 10 Jul 2019 13:59:34 +0200 Subject: [PATCH 1/2] Upload files to '08/Research-BohyeWoo' --- 08/Research-BohyeWoo/README.md | Bin 0 -> 1024 bytes 08/Research-BohyeWoo/annotated-reader.py | 294 ++++++++++++++++++ .../dependencies-in-a-network.html | 182 +++++++++++ 08/Research-BohyeWoo/dependency-of-network.py | 294 ++++++++++++++++++ 08/Research-BohyeWoo/nickname_color.pkl | Bin 0 -> 172 bytes 5 files changed, 770 insertions(+) create mode 100644 08/Research-BohyeWoo/README.md create mode 100644 08/Research-BohyeWoo/annotated-reader.py create mode 100644 08/Research-BohyeWoo/dependencies-in-a-network.html create mode 100644 08/Research-BohyeWoo/dependency-of-network.py create mode 100644 08/Research-BohyeWoo/nickname_color.pkl diff --git a/08/Research-BohyeWoo/README.md b/08/Research-BohyeWoo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..06d7405020018ddf3cacee90fd4af10487da3d20 GIT binary patch literal 1024 ScmZQz7zLvtFd70QH3R?z00031 literal 0 HcmV?d00001 diff --git a/08/Research-BohyeWoo/annotated-reader.py b/08/Research-BohyeWoo/annotated-reader.py new file mode 100644 index 0000000..c6dedf6 --- /dev/null +++ b/08/Research-BohyeWoo/annotated-reader.py @@ -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('') + for line in lines: # for each line in the list of lines + new_html.write( + '
{}
{}
'.format( + x, x, x, line)) + x = x + 1 + new_html.write('') + 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 + new_comment = html.new_tag("div") # make + 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 + comment = comment.split(' ',2)[2] + + comment_text.string = nickname + ': ' + comment + ' (' + time + ') ' # make comment (the parameter variable) + 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 ".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 ".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 ...".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) diff --git a/08/Research-BohyeWoo/dependencies-in-a-network.html b/08/Research-BohyeWoo/dependencies-in-a-network.html new file mode 100644 index 0000000..8488639 --- /dev/null +++ b/08/Research-BohyeWoo/dependencies-in-a-network.html @@ -0,0 +1,182 @@ + + + +
1
DEPENDENCIES IN A NETWORK +
2
HOW IS OUR NETWORK DEPENDING ON OTHERS? +
3
By Bo Woo +
4
+
5
CATEGORIES +
6
# NETWORK(ED) PUBLISHING +
7
# AUTONOMY AND ITS CONTINGENCIES +
8
# MAPPING NETWORKS
+
9
+
10
+
11
+
+
+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) +
+
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)
+
+
+
+
+
12
+INTRODUCTION +
+
+
+
+
+
+
+
13
+
+
+
+
+
+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) +
+
+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) +
+
+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) +
+
+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) +
+
+bootje:
Guest account: guest@please.undo.undo.it
+Password: guestpassword
+ (11:17PM on April 01, 2019)
+
+ + +
+
14
ANNOTATED GLOSSARY +
15
ANNOTAION BOT +
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.
(09:57PM on April 02, 2019)
16
DEPENDENCIES + +
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)
17
OUR NETWORK +
bootje: 'b-e-e-t.r-o-o-t.net' (09:59PM on April 02, 2019)
bootje: ' ciao.urca.tv' (10:00PM on April 02, 2019)
bootje: 'richfolks.club' (10:00PM on April 02, 2019)
bootje: 'nothat.bad.mn' (10:00PM on April 02, 2019)
bootje: ' p.lions.es' (10:00PM on April 02, 2019)
bootje: 'foshan-1992.pw' (10:01PM on April 02, 2019)
bootje: 'please.undo.undo.it'(10:01PM on April 02, 2019)
bootje: 'sweetandsour.chickenkiller.com' (10:01PM on April 02, 2019)
18
TCP/IP +
bootje: They are two protocols (TCP & 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)
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)
19
DNS +
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)
20
HTTP +
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)
21
SSH +
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)
22
XMPP +
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)
23
ROUTER +
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)
24
+
25
SERVER — A HOSTING INFRASTRUCTURE +
+
+
+
26
The Dependency Map
+
+
+
bootje: An explanation of the dependency map
(11:03PM on April 01, 2019)
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)
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.
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)
+ +
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)
bootje: 2.2 Apache is a web/ HTTP Server, a free and open-source cross-platform web server. (11:11PM on April 01, 2019)
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)
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)
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)
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)
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)
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)
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)
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)
+
+
27
Why couldn't I host my server at home? +
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)
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)
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)
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)
28
What solution I found around? +
bootje: What kinds of unexpected situation occured?
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)
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)
29
Layers of Parasitism +
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)
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)
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)
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)
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)
bootje: many 'sorry' and 'thank you' from my side.. (04:35PM on April 02, 2019)
30
+
31
— TRACEROUTE +
32
What is Traceroute? +
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)
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)
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)
bootje: A hop is a journey from one source(server) to destination(server). (02:46PM on April 02, 2019)
bootje: Milliseconds is the amount of time it takes to make a hop + (02:47PM on April 02, 2019)
bootje: A packet is the information that travels along the traceroute + (03:35PM on April 02, 2019)
33
What do you see from Traceroute? +
bootje: The output explains how the server at home traveled to the final destination: sweetandsour.chickenkiller.com (10:55AM on April 02, 2019)
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)
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)
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)
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)
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)
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)
34
How does my server travel to others? +
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)
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)
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)
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)
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)
bootje: Tracing the routers between 'sweetandsour.chickenkiller.com' and 'ciao.urca.tv' + (09:01PM on April 02, 2019)
+
bootje: Tracing the routers between 'nothat.bad.mn' and 'foshan-1992.pw' (09:02PM on April 02, 2019)
+
bootje: Tracing the routers between 'richfolks.club' and 'please.undo.undo.it' (09:03PM on April 02, 2019)
+ +
bootje: Tracing the routers between 'b-e-e-t.r-o-o-t.net' and 'foshan-1992.pw' (09:25PM on April 02, 2019)
+
bootje: Tracing the routers between 'ciao.urca.tv' and 'foshan-1992.pw' (09:28PM on April 02, 2019)
bootje: Tracing the routers between 'nothat.bad.mn' and 'foshan-1992.pw' (09:32PM on April 02, 2019)
bootje: Tracing the routers between 'please.undo.undo.it' and 'foshan-1992.pw' (09:33PM on April 02, 2019)
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)
+
35
What are the traceroute results?
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)
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)
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)
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)
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)
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)
36
Does telecommunication companies own power? +
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)
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)
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)
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)
bootje: I am guessing the final parasitic structure is: Swipnet < Tele2 < T-Mobile, Tele2 < KPN (02:59PM on April 02, 2019)
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)
37
+
38
XMPP — A CHATTING INFRASTRUCTURE +
39
What is XMPP? +
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)
40
How does XMPP work? +
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)
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)
41
How was I dependent on? +
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)
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)
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)
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)
42
+
43
ANNOTATION BOT — A PUBLISHING INFRASTRUCTURE +
44
What is Annotation Bot? +
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)
bootje: Annotation Bot can be used for the following purposes: + (03:26PM on April 02, 2019)
bootje: — To add comments with multiple users at the same time remotely + (03:27PM on April 02, 2019)
bootje: — To overview the transparency of ownership on commenting + (03:27PM on April 02, 2019)
bootje: — As a collaborative publishing tool to discuss the contents + (03:27PM on April 02, 2019)
45
How was Annotation Bot installed? +
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)
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)
bootje: As for creating an account, you need a server that allows you to create an account. (03:49PM on April 02, 2019)
bootje: An XMPP client can be selected depending on the user's preference. + (03:49PM on April 02, 2019)
bootje: A Channel is a platform in XMPP client to upload comments and image references. + (03:51PM on April 02, 2019)
bootje: A TXT file is to store the original text you will annotate. + (03:59PM on April 02, 2019)
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)
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)
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)
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)
46
How does Annotation Bot work? +
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)
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)
47
What was happening when using it? +
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)
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)
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)
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)
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)
48
What if? +
bootje: If there is no Python language, I can't design the Annotation Bot. + (03:42PM on April 02, 2019)
bootje: If I miss one library to download, I can't use my Annotation Bot. + (03:51PM on April 02, 2019)
bootje: If I don't have my account, I can't use my Annotation Bot. + (04:02PM on April 02, 2019)
bootje: If I don't have Artemis' server, I can't have my account. + (04:09PM on April 02, 2019)
bootje: If I don't have Artemis' server, I can't have my account. + (04:10PM on April 02, 2019)
bootje: If Artemis lose her WIFI connection, she can't have her server. + (04:14PM on April 02, 2019)
bootje: If she stop subscripting Telfort, she will lose her WIFI connection. + (04:15PM on April 02, 2019)
bootje: If Telfort will be takenover by T-Mobile, she will have to stop the Internet subscription. (04:16PM on April 02, 2019)
49
How does it dependent on others? +
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)
50
+
51
SCREEN +
52
What is Screen? +
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)
53
How to use it? +
bootje: Screen has to be installed where you save your Annotation Bot. + (03:52PM on April 02, 2019)
bootje: How to install: $ sudo apt install screen + (04:12PM on April 02, 2019)
bootje: To open a new terminal session: $ screen + (04:13PM on April 02, 2019)
bootje: To show all the active screen sessions: $ screen -ls + (04:14PM on April 02, 2019)
bootje: To Kill a screen session : $ screen -x -s 'screenname' kill + (04:17PM on April 02, 2019)
54
Why do I need it? +
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)
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)
55
+
56
Acknowledgement
bootje: The Network We (de)Served — +XPUB Special Issue #08 (08:11PM on April 02, 2019)
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)
+
bootje: . (11:31AM on April 08, 2019)
+ + + + diff --git a/08/Research-BohyeWoo/dependency-of-network.py b/08/Research-BohyeWoo/dependency-of-network.py new file mode 100644 index 0000000..4f7400e --- /dev/null +++ b/08/Research-BohyeWoo/dependency-of-network.py @@ -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('') + for line in lines: # for each line in the list of lines + new_html.write( + '
{}
{}
'.format( + x, x, x, line)) + x = x + 1 + new_html.write('') + 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 + new_comment = html.new_tag("div") # make + 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 + comment = comment.split(' ',2)[2] + + comment_text.string = nickname + ': ' + comment + ' (' + time + ') ' # make comment (the parameter variable) + 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 ".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 ".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 ...".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) diff --git a/08/Research-BohyeWoo/nickname_color.pkl b/08/Research-BohyeWoo/nickname_color.pkl new file mode 100644 index 0000000000000000000000000000000000000000..e96cef0b1a14e3337fe195ce710227b8fc4ecc4c GIT binary patch literal 172 zcmZo*nYxex0&1u9uqEZ^mt>_*iJhX+Bbry5TTrQ&oL`ixms^@sl9^aklvoK=Q=FWb zlUOum@{}G{uo57hQc_uv3KC(;w3y<};LX@RC1{F Date: Wed, 10 Jul 2019 14:00:41 +0200 Subject: [PATCH 2/2] Update '08/Research-BohyeWoo/index.html' --- .../{dependencies-in-a-network.html => index.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 08/Research-BohyeWoo/{dependencies-in-a-network.html => index.html} (100%) diff --git a/08/Research-BohyeWoo/dependencies-in-a-network.html b/08/Research-BohyeWoo/index.html similarity index 100% rename from 08/Research-BohyeWoo/dependencies-in-a-network.html rename to 08/Research-BohyeWoo/index.html