<div dir="ltr">Hi Tony,<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-size:12.8px">When the activity maintainer and the developer agree that a new version of an activity is ready for release, all that is needed is for the activity maintainer to build the bundle and store it in the appropriate add-on directory. ASLO. </span><br style="font-size:12.8px"><br style="font-size:12.8px"><span style="font-size:12.8px">ASLO does not need any notification since each time a user clicks on an activity, ASLO finds the latest version and extracts the </span><a href="http://activity.info/" target="_blank" style="font-size:12.8px">activity.info</a><span style="font-size:12.8px"> to prepare the detail page. If the user clicks on download, the bundle is downloaded by its url. </span><br style="font-size:12.8px"><br style="font-size:12.8px"><span style="font-size:12.8px">Note: this model makes ASLO essentially bullet-proof since the only actions available are to browse activities and select one for download. The access is read-only. At the same time ASLO does not need a backend requiring adminstration.</span></blockquote><div><br></div><div>This significantly reduces the development effort. So, does that mean the developer have to specify download url in the <a href="http://activity.info">activity.info</a> ?</div><div>What do you think about the rest of process. Is it the best practice to use background worker to fetch <a href="http://activity.info">activity.info</a> ?</div><div><br></div><div>Thanks,</div><div>Jatin Dhankhar  </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 29, 2017 at 6:21 PM, Tony Anderson <span dir="ltr"><<a href="mailto:tony_anderson@usa.net" target="_blank">tony_anderson@usa.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div text="#000000" bgcolor="#FFFFFF">
    <div class="m_4767995965331274873moz-cite-prefix">Hi Jatin,<span class=""><br>
      <br>
      <br>
      <br>
       Release is made into repo -> Webhook is triggered ->
      Response is parsed -> A worker is spawned to handle building
      (inside docker or in a worker thread) -> <br>
      Once bundle is available, <a href="http://activity.info" target="_blank">activity.info</a> is parsed ->
      Parsed activity is pushed to message queue -> Message queue is
      used to update index of available activities <br>
      <br></span>
      When the activity maintainer and the developer agree that a new
      version of an activity is ready for release, all that is needed is
      for the activity maintainer to build the bundle and store it in
      the appropriate add-on directory. ASLO. <br>
      <br>
      ASLO does not need any notification since each time a user clicks
      on an activity, ASLO finds the latest version and extracts the
      <a href="http://activity.info" target="_blank">activity.info</a> to prepare the detail page. If the user clicks on
      download, the bundle is downloaded by its url. <br>
      <br>
      Note: this model makes ASLO essentially bullet-proof since the
      only actions available are to browse activities and select one for
      download. The access is read-only. At the same time ASLO does not
      need a backend requiring adminstration.<span class="HOEnZb"><font color="#888888"><br>
      <br>
      Tony</font></span><div><div class="h5"><br>
      <br>
      On 05/28/2017 06:43 PM, Jatin Dhankhar wrote:<br>
    </div></div></div><div><div class="h5">
    <blockquote type="cite">
      <div dir="ltr">Hi,
        <div><br>
        </div>
        <div>I am using webhooks for notifying the server (for release
          events only). At first I was thinking to clone the whole repo
          but it is possible to access a single file via Github API [1]
          which ultimately hands you a json including raw url to
          download from.</div>
        <div>After which it can be parsed to download the file but only
          limitation is we cannot fetch a file greater than 1 MB.</div>
        <div>Also it may take a long time to download/parse and
          optionally generate bundle, such tasks can be handled via a
          job management system like celery and when bundle is ready,
          push the name of activity to pub/sub queue system (Is it an
          effective approach ?), we can build them inside docker
          containers as suggested by Samuel. </div>
        <div>I have tested the hook and fetching, yet to test building
          inside Container and setting up Background workers. I aslo
          used <a href="https://www.iron.io/" target="_blank">https://www.iron.io/</a> at
          a previous project for background workers and it was good but
          it is expensive and may cause vendor lock-in. </div>
        <div><br>
        </div>
        <div>It would be cool to use a CDN (either in-house or third
          party like SourceForge or Bintray) to distribute the built
          activities or we can push to <a href="http://activities.sugarlabs.org" target="_blank">activities.sugarlabs.org</a>. </div>
        <div><br>
        </div>
        <div>So process so far would be </div>
        <div><br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Release
          is made into repo -> Webhook is triggered -> Response is
          parsed -> A worker is spawned to handle building (inside
          docker or in a worker thread) -> Once bundle is available,
          <a href="http://activity.info" target="_blank">activity.info</a>
          is parsed -> Parsed activity is pushed to message queue
          -> Message queue is used to update index of available
          activities </blockquote>
        <div> </div>
        <div>If something is missing/wrong, kindly guide me in the right
          direction. </div>
        <div>I have not configured the server properly yet, but it will
          be accessible at <a href="http://aslo-dev.jatindhankhar.in" target="_blank">aslo-dev.jatindhankhar.in</a>,
          right now serving on port 5000.</div>
        <div>Thanks,</div>
        <div><br>
        </div>
        <div>Jatin Dhankhar</div>
        <div><br>
        </div>
        <div> </div>
        <div> </div>
        <div><br>
        </div>
        <div><br>
        </div>
        <div>[1] <a href="https://developer.github.com/v3/repos/contents/" target="_blank">https://developer.github.<wbr>com/v3/repos/contents/</a></div>
      </div>
      <div class="gmail_extra"><br>
        <div class="gmail_quote">On Sat, May 27, 2017 at 9:32 PM, Jatin
          Dhankhar <span dir="ltr"><<a href="mailto:dhankhar.jatin@gmail.com" target="_blank">dhankhar.jatin@gmail.com</a>></span>
          wrote:<br>
          <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
            <div dir="ltr"><span>
                <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                  <div style="font-size:12.8px">would suggest, if Walter
                    and Tony are agree, to start preparing a proof of
                    concept. Basically do the following:</div>
                  <div style="font-size:12.8px">(1) Clone some sugar
                    activity to your GH account like TurtleArt. Enable
                    webhooks for this repo and send events to your
                    server at some URL (like <a href="http://aslo.jatindhankhar.in/hook" target="_blank">http://aslo.jatindhankha<wbr>r.in/hook</a>)
                    when a new release has been done.</div>
                  <div style="font-size:12.8px">(2) Parse this payload
                    and get all the information from the <a href="http://activity.info/" target="_blank">activity.info</a> file
                    (you might look SamP's code). Please tell us what
                    might be missing for the site (comparing current
                    ASLO and ASLOv2) so we can think how to fill those
                    missing info. Please check this carefully.</div>
                  <div style="font-size:12.8px">(3) Build the bundle
                    inside a Docker container (no need for hacks). Just
                    simple docker container and no docker inside docker.
                    Probably bundles will be store at <a href="http://download.sugarlabs.org/activitities3/" target="_blank">download.sugarlabs.org/acti<wbr>vitities3/</a>.
                    But for now, just put in same server and some URL
                    like <a href="http://aslo.jatindhankhar.in/download/" target="_blank">http://aslo.jatindhankhar<wbr>.in/download/</a><path_to_app>. <wbr>Then
                    we will think how to sync this.</div>
                  <div style="font-size:12.8px">(4) Show a web page with
                    the listed app we can download this new generated
                    bundle.</div>
                  <div><br>
                  </div>
                </blockquote>
                <div><br>
                </div>
              </span>
              <div>Okay, Will start work on this tomorrow. I was looking
                at some Flask tutorials. Is it okay if I use Flask ?</div>
              <div>Also wrote the weekly blog #3.</div>
              <div><br>
              </div>
              <div>Thanks,</div>
              <div>Jatin Dhankhar </div>
            </div>
            <div class="m_4767995965331274873HOEnZb">
              <div class="m_4767995965331274873h5">
                <div class="gmail_extra"><br>
                  <div class="gmail_quote">On Sat, May 27, 2017 at 7:48
                    PM, Samuel Cantero <span dir="ltr"><<a href="mailto:scanterog@gmail.com" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-abbreviated" href="mailto:scanterog@gmail.com" target="_blank">scanterog@gmail.com</a>></span>
                    wrote:<br>
                    <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
                      <div dir="ltr">
                        <div class="gmail_extra">
                          <div class="gmail_quote"><span>On Fri, May 26,
                              2017 at 5:57 AM, Jatin Dhankhar <span dir="ltr"><<a href="mailto:dhankhar.jatin@gmail.com" target="_blank">dhankhar.jatin@gmail.com</a>></span>
                              wrote:<br>
                              <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                                <div dir="ltr">Hi Sam,
                                  <div><br>
                                  </div>
                                  <div>Thank you for very much for the
                                    detailed explanation. Apart from
                                    what you have already mentioned. I
                                    checked the socialhelp module and it
                                    fails to build since the package<i> python-cairosvg</i> is
                                    not available in the Ubuntu repos
                                    anymore[1].<br>
                                  </div>
                                  <div><br>
                                  </div>
                                </div>
                              </blockquote>
                              <div><br>
                              </div>
                            </span>
                            <div>I think we don't have to worry about
                              integration with socialhelp.</div>
                            <span>
                              <div> </div>
                              <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                                <div dir="ltr">
                                  <div>I also agree that new proposal[2]
                                    has sane architecture and use of
                                    Gtihub API over raw calls is
                                    beneficial. </div>
                                </div>
                              </blockquote>
                              <div><br>
                              </div>
                            </span>
                            <div>I would suggest, if Walter and Tony are
                              agree, to start preparing a proof of
                              concept. Basically do the following:</div>
                            <div>(1) Clone some sugar activity to your
                              GH account like TurtleArt. Enable webhooks
                              for this repo and send events to your
                              server at some URL (like <a href="http://aslo.jatindhankhar.in/hook" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="http://aslo.jatindhankha" target="_blank">http://aslo.jatindhankha</a><wbr><a href="http://r.in/hook">r.in/hook</a>)
                              when a new release has been done.</div>
                            <div>(2) Parse this payload and get all the
                              information from the <a href="http://activity.info" target="_blank">activity.info</a> file
                              (you might look SamP's code). Please tell
                              us what might be missing for the site
                              (comparing current ASLO and ASLOv2) so we
                              can think how to fill those missing info.
                              Please check this carefully.</div>
                            <div>(3) Build the bundle inside a Docker
                              container (no need for hacks). Just simple
                              docker container and no docker inside
                              docker. Probably bundles will be store at
                              <a href="http://download.sugarlabs.org/activitities3/" target="_blank">download.sugarlabs.org/activit<wbr>ities3/</a>.
                              But for now, just put in same server and
                              some URL like <a href="http://aslo.jatindhankhar.in/download/" target="_blank">http://aslo.jatindhankhar.in/d<wbr>ownload/</a><path_to_app>. Then
                              we will think how to sync this.</div>
                            <div>(4) Show a web page with the listed app
                              we can download this new generated bundle.</div>
                            <div><br>
                            </div>
                            <div>If you need more info, just let us
                              know.</div>
                            <div><br>
                            </div>
                            <div>Best,</div>
                            <div><br>
                            </div>
                            <div>Sam C.</div>
                            <div>
                              <div class="m_4767995965331274873m_-8009501003666624965h5">
                                <div><br>
                                </div>
                                <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                                  <div dir="ltr">
                                    <div><br>
                                    </div>
                                    <div><br>
                                    </div>
                                    <div>Thanks, </div>
                                    <div>Jatin Dhankhar</div>
                                    <div><br>
                                    </div>
                                    <div>[1] <a href="https://github.com/samdroid-apps/aslo/blob/master/socialhelp/Dockerfile#L20" target="_blank">https://github.com/samdroi<wbr>d-apps/aslo/blob/master/social<wbr>help/Dockerfile#L20</a></div>
                                    <div>[2] <a href="https://goo.gl/VEIzCr" target="_blank">https://goo.gl/VEIzCr</a></div>
                                    <div>
                                      <div class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-h5">
                                        <div class="gmail_extra"><br>
                                          <div class="gmail_quote">On
                                            Fri, May 26, 2017 at 6:33
                                            AM, Tony Anderson <span dir="ltr"><<a href="mailto:tony@olenepal.org" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-abbreviated" href="mailto:tony@olenepal.org" target="_blank">tony@olenepal.org</a>></span>
                                            wrote:<br>
                                            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
                                              <div bgcolor="#FFFFFF">
                                                <div class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188m_3776250212530713294moz-cite-prefix">Hi
                                                  Sam<br>
                                                  <br>
                                                  Great work! I agree
                                                  with you completely. <br>
                                                  <span class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188HOEnZb"><font color="#888888"> <br>
                                                      Tony</font></span>
                                                  <div>
                                                    <div class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188h5"><br>
                                                      <br>
                                                      On 05/26/2017
                                                      03:02 AM, Samuel
                                                      Cantero wrote:<br>
                                                    </div>
                                                  </div>
                                                </div>
                                                <div>
                                                  <div class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188h5">
                                                    <blockquote type="cite">
                                                      <div dir="ltr">
                                                        <div>Hi guys!</div>
                                                        <div><br>
                                                        </div>
                                                        I have review
                                                        Sam's code and
                                                        this is what
                                                        I've found so
                                                        far:
                                                        <div><br>
                                                        </div>
                                                        <div>1.
                                                          Initially, all
                                                          activities
                                                          shown in the
                                                          web interface
                                                          are read/parse
                                                          from the JSON
                                                          files [1][2]
                                                          uploaded to: <a class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188m_3776250212530713294moz-txt-link-freetext" href="https://github.com/samdroid-apps/sugar-activities" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/sugar-activities.
                                                          Using a repo
                                                          as a
                                                          activities
                                                          registry has
                                                          advantages and
                                                          disadvantages.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>2. The main
                                                          web app spawns
                                                          a thread [3]
                                                          which polls a
                                                          kafka message
                                                          queue
                                                          (consumer) in
                                                          order to get
                                                          the new
                                                          messages
                                                          (GitHub
                                                          payloads) [4]
                                                          inserted into
                                                          the message
                                                          queue by
                                                          events sent to
                                                          <a href="https://hook.sugarlabs.org/hook" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://hook.sugarlabs.org/hoo" target="_blank">https://hook.sugarlabs.org/hoo</a><wbr>k.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>BUT this
                                                          only looks for
                                                          changes (GH
                                                          push events)
                                                          to
                                                          sugar-activities
                                                          repo. This
                                                          allows to
                                                          update the
                                                          activity
                                                          information in
                                                          the web
                                                          interface
                                                          (version,
                                                          download link,
                                                          etc) as well
                                                          as to
                                                          introduce new
                                                          activities
                                                          [5].</div>
                                                        <div><br>
                                                        </div>
                                                        <div>You can
                                                          check how the
                                                          GH payload is
                                                          processed
                                                          here: [6]. In
                                                          short, it
                                                          parses the GH
                                                          payload, gets
                                                          the repo URL
                                                          and publishes
                                                          some "message"
                                                          to the kafka
                                                          queue (or
                                                          bus), i.e act
                                                          as a kafka
                                                          producer so it
                                                          can be read
                                                          later by [4]. </div>
                                                        <div><br>
                                                        </div>
                                                        <div>This
                                                          "message"
                                                          generated at
                                                          [7] is just a
                                                          simple dict
                                                          (json) with
                                                          two data:
                                                          github repo
                                                          URL and
                                                          bundle_id. The
                                                          activity <i>bundle_id</i> is
                                                          gotten from
                                                          the <i><a href="http://activity.info" target="_blank">activity.info</a></i> file
                                                          (it doesn't
                                                          use GH API,
                                                          just use raw
                                                          access and
                                                          always master
                                                          branch).</div>
                                                        <div><br>
                                                        </div>
                                                        <div>3. Let's
                                                          review now the
                                                          bot's part so
                                                          we can
                                                          understand the
                                                          whole
                                                          workflow.
                                                          Inside repo we
                                                          can find two
                                                          folders: bot
                                                          and
                                                          bot-master. </div>
                                                        <div><br>
                                                        </div>
                                                        <div><i>Bot-master</i> is
                                                          a kafka
                                                          consumer for
                                                          the topic
                                                          "org.sugarlabs.aslo-changes"
                                                          [8]. This
                                                          topic is
                                                          different for
                                                          the one used
                                                          at [4]
                                                          (org.sugarlabs.hook).
                                                          Simplifying,
                                                          every new
                                                          topic is a new
                                                          message bus.
                                                          As a consumer,
                                                          it needs to
                                                          receive some
                                                          message to
                                                          process first.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>This is
                                                          where <i>bot</i>
                                                          comes in. <i>Bot</i>
                                                          is the
                                                          producer for
                                                          the topic
                                                          "org.sugarlabs.aslo-changes"
                                                          (as expected)
                                                          [9] but also
                                                          it is a
                                                          consumer for
                                                          the topic
                                                          "org.sugarlabs.hook"
                                                          [10]. This
                                                          means that
                                                          when a new
                                                          payload is
                                                          sent to <a href="http://hook.sugarlabs.org/hook" target="_blank">hook.sugarlabs.org/hook</a>,
                                                          <i>bot</i>
                                                          also gets the
                                                          message
                                                          "produced" at
                                                          [7] (repo URL,
                                                          bundle_id) and
                                                          based on that
                                                          message does
                                                          the following:</div>
                                                        <div>(a) clone
                                                          the repo
                                                          (master
                                                          branch) [11];
                                                           - this is of
                                                          course the
                                                          activity repo
                                                          from some GH
                                                          account - no
                                                          centralized
                                                          repositories
                                                          because devs
                                                          registers the
                                                          webhooks as
                                                          explains
                                                          here: <a href="https://github.com/samdroid-apps/sugar-activities/blob/master/README.md" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdr" target="_blank">https://github.com/samdr</a><wbr>oid-apps/sugar-activities/blob<wbr>/master/README.md.</div>
                                                        <div>(b) get the
                                                          json file
                                                          using the
                                                          bundle_id
                                                          from <a class="m_4767995965331274873m_-8009501003666624965m_-6349898199447121431gmail-m_7882053398874099122m_-687307678483002188m_3776250212530713294moz-txt-link-freetext" href="http://raw.githubusercontent.com/SAMdroid-apps/sugar-activities/master/" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="http://raw.githubusercont" target="_blank">http://raw.githubusercont</a><wbr><a href="http://ent.com/SAMdroid-apps/sugar-ac">ent.com/SAMdroid-apps/sugar-ac</a><wbr>tivities/master/{bundle_id}.js<wbr>on.

                                                          Again, no GH
                                                          API [12];</div>
                                                        <div>(c) Parse <a href="http://activity.info" target="_blank">activity.info</a>
                                                          from cloned
                                                          repo. There
                                                          are many
                                                          useful things
                                                          here like:
                                                          check if
                                                          activity is
                                                          GTK3, if has
                                                          old toolbars
                                                          and check
                                                          minimal sugar
                                                          version
                                                          supported
                                                          [13];</div>
                                                        <div>(d) Get the
                                                          images from
                                                          cloned repo:
                                                          screenshots
                                                          and icons
                                                          [14];</div>
                                                        <div>(e)
                                                          generates
                                                          bundle
                                                          filename (xo
                                                          name) and set
                                                          some extra
                                                          data in <a href="http://activity.info" target="_blank">activity.info</a>; </div>
                                                        <div>(f)
                                                          generate
                                                          (compile) the
                                                          bundle (xo
                                                          file) [15]. As
                                                          you can see
                                                          [16], this
                                                          code calls the
                                                          docker
                                                          container
                                                          "samdroid/activity-build".
                                                          I suppose this
                                                          has been
                                                          generated
                                                          previously
                                                          using [17].
                                                          Because SamP
                                                          was running
                                                          this bot
                                                          inside Docker
                                                          and was
                                                          building the
                                                          image using
                                                          docker again,
                                                          he needed the
                                                          wrapdocker
                                                          file [18].</div>
                                                        <div><br>
                                                        </div>
                                                        <div>Once the
                                                          bundle has
                                                          been
                                                          generated, it
                                                          produces the
                                                          following
                                                          message [19]
                                                          for
                                                          bot-master,
                                                          which in turns
                                                          save the
                                                          bundle [20]
                                                          and update
                                                          sugar-activities
                                                          repo with the
                                                          new
                                                          releases/version
                                                          and other
                                                          needed
                                                          information
                                                          (as new
                                                          translations)
                                                          - example at
                                                          [21]. Yes,
                                                          this process
                                                          also manages
                                                          i18n.</div>
                                                        <div><br>
                                                        </div>
                                                        <div><b>My
                                                          conclusion</b></div>
                                                        <div><b><br>
                                                          </b></div>
                                                        <div>After
                                                          reviewing
                                                          code, I still
                                                          believe the
                                                          proposal I've
                                                          sent before
                                                          [22] is the
                                                          simplest way
                                                          to manage
                                                          this. Of
                                                          course, maybe
                                                          we can
                                                          optimize some
                                                          stuff along
                                                          the way. Maybe
                                                          we can add the
                                                          chance to
                                                          upload bundles
                                                          file (XOs)
                                                          manually as
                                                          well, so we
                                                          don't "remove"
                                                          devs the
                                                          chance to
                                                          upload theirs
                                                          XOs.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>Reading
                                                          SamP who wrote
                                                          ASLO2, I'm
                                                          still even
                                                          more convinced
                                                          [22] is the
                                                          right way. He
                                                          basically
                                                          described this
                                                          proposed
                                                          solution in
                                                          previous
                                                          email: <a href="http://lists.sugarlabs.org/archive/iaep/2017-May/019761.html" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="http://lists.sugarlabs" target="_blank">http://lists.sugarlabs</a>.<wbr>org/archive/iaep/2017-May/0197<wbr>61.html.
                                                          Of course,
                                                          ASLO2 gives us
                                                          a lot of code
                                                          we can reuse
                                                          for ASLO3.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>Best,</div>
                                                        <div><br>
                                                        </div>
                                                        <div>SamC.</div>
                                                        <div><br>
                                                        </div>
                                                        <div>[1] <a href="https://github.com/samdroid-apps/aslo/blob/master/web/main.py#L112" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/web/ma<wbr>in.py#L112</div>
                                                        <div>[2] <a href="https://github.com/samdroid-apps/aslo/blob/master/web/backend.py#L32" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/web/ba<wbr>ckend.py#L32</div>
                                                        <div>[3] <a href="https://github.com/samdroid-apps/aslo/blob/master/web/main.py#L114" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/web/ma<wbr>in.py#L114</div>
                                                        <div>[4] <a href="https://github.com/samdroid-apps/aslo/blob/master/web/main.py#L92" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/web/ma<wbr>in.py#L92</div>
                                                        <div>[5] <a href="https://github.com/samdroid-apps/aslo/blob/master/web/main.py#L107" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/web/ma<wbr>in.py#L107</div>
                                                        <div>[6] <a href="https://github.com/samdroid-apps/aslo/blob/master/hookin/main.py#L12" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/hookin<wbr>/main.py#L12</div>
                                                        <div>[7] <a href="https://github.com/samdroid-apps/aslo/blob/master/hookin/backend.py#L82" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/hookin<wbr>/backend.py#L82</div>
                                                        <div>[8] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot-master/main.py#L77" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/bot-ma<wbr>ster/main.py#L77</div>
                                                        <div>[9] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/main.py#L40" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdroi" target="_blank">https://github.com/samdroi</a><wbr>d-apps/aslo/blob/master/bot/ma<wbr>in.py#L40</div>
                                                        <div>[10] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/main.py#L36" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/m<wbr>ain.py#L36</div>
                                                        <div>[11] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/main.py#L64" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/m<wbr>ain.py#L64</div>
                                                        <div>[12] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/img.py#L31" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/i<wbr>mg.py#L31</div>
                                                        <div>[13] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/props.py#L117" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/p<wbr>rops.py#L117</div>
                                                        <div>[14] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/img.py#L55" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/i<wbr>mg.py#L55</div>
                                                        <div>[15] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/build.py#L74" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/b<wbr>uild.py#L74</div>
                                                        <div>[16] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/build.py#L84" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/b<wbr>uild.py#L84</div>
                                                        <div>[17] <a href="https://github.com/samdroid-apps/aslo/blob/master/activity-build-docker/Dockerfile" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/activ<wbr>ity-build-docker/Dockerfile</div>
                                                        <div>[18] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/wrapdocker" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/w<wbr>rapdocker</div>
                                                        <div>[19] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot/main.py#L100" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot/m<wbr>ain.py#L100</div>
                                                        <div>[20] <a href="https://github.com/samdroid-apps/aslo/blob/master/bot-master/main.py#L47" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/aslo/blob/master/bot-m<wbr>aster/main.py#L47</div>
                                                        <div>[21] <a href="https://github.com/samdroid-apps/sugar-activities/commit/8de09150934502a845b5f33e6031e5ebd60e4d94" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://github.com/samdro" target="_blank">https://github.com/samdro</a><wbr>id-apps/sugar-activities/commi<wbr>t/8de09150934502a845b5f33e6031<wbr>e5ebd60e4d94</div>
                                                        <div>[22] <a href="https://goo.gl/VEIzCr" target="_blank"></a><a class="m_4767995965331274873moz-txt-link-freetext" href="https://goo.gl/VEIzCr" target="_blank">https://goo.gl/VEIzCr</a></div>
                                                      </div>
                                                    </blockquote>
                                                    <br>
                                                  </div>
                                                </div>
                                              </div>
                                            </blockquote>
                                          </div>
                                          <br>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </blockquote>
                              </div>
                            </div>
                          </div>
                          <br>
                        </div>
                      </div>
                    </blockquote>
                  </div>
                  <br>
                </div>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </div></div></div>

</blockquote></div><br></div>