Adding GetReportedSkill API on SUSI.AI Server

The GetReportedSkill API was implemented for Admins to view the reported feedback given by users, admin can then monitor skills, which are working fine and in which users are having problems. This can help in deleting buggy/erroneous skills directly from the reported skills tab in the admin panel.

The endpoint is of GET type, and accept 2 parameters: 

  • access_token(compulsory): It is the access token of the logged-in user. It is of a string data type.
  • search: It is a string param that helps us to fetch a list of feedback related to the search term

The minimal role is set to OPERATOR as Admin section access is required for reported skill list.

API Development

Here is a sample response from api:

{
  “session”: {“identity”: {
    “type”: “host”,
    “name”: “0:0:0:0:0:0:0:1_d9aaded8”,
    “anonymous”: true
  }},
  “accepted”: true,
  “list”: [
    {
      “feedback”: “test”,
      “skill_name”: “GSOC”,
      “email”: “[email protected]”,
      “timestamp”: “2019-06-15 03:25:29.425”
    },
    {
      “feedback”: “test101”,
      “skill_name”: “GSOC”,
      “email”: “[email protected]”,
      “timestamp”: “2019-06-15 12:18:33.641”
    }
  ],
  “message”: “Success: Fetched all Reported Skills”
}

The reported skills are stored in DAO under reportedSkills, for fetching the list we need to traverse it’s JSONObject.

JsonTray reportedSkills = DAO.reportedSkills;
JSONObject reportedSkillsListObj = reportedSkills.toJSON();

api/cms/GetReportSkillService.java

Code

For creating a list we need to access each property of JSONObject of reportedSkill, in the following order:

Model → Group → Language → Skill Name → Reported feedback list

for (String key:JSONObject.getNames(reportedSkillsListObj)) {
  modelName = reportedSkillsListObj.getJSONObject(key);
      if (reportedSkillsListObj.has(key)) {
        for (String group_name : JSONObject.getNames(modelName)) {
          groupName = modelName.getJSONObject(group_name);
          if (modelName.has(group_name)) {
            for (String language_name : JSONObject.getNames(groupName)) {
              languageName = groupName.getJSONObject(language_name);
              if (groupName.has(language_name)) {

api/cms/GetReportSkillService.java

If search parameter is passed, check if skillName matches with search parameter, if both strings are equal, create a new reportedObject and append it to reportList, which is a list of reported skills

if (call.get(“search”, null) != null) {
  String skill_name = call.get(“search”, null);
    if (languageName.has(skill_name)) {
      skillName = languageName.getJSONObject(skill_name);
      reports = skillName.getJSONArray(“reports”);
      for (int i = 0; i < reports.length(); i++) {
        JSONObject reportObject = new JSONObject();
        reportObject = reports.getJSONObject(i);
        reportObject.put(“skill_name”, skill_name);
        reportList.add(reportObject);

api/cms/GetReportSkillService.java

If search parameter is not passed, traversed all reported skills and append it to array(reportList).

getNames returns an array of keys as string stored in JSONObject, we traverse the array and put all the reported skill name, feedback, email and timestamp in reportObject and add it to reportList

} else {
   for (String skill_name : JSONObject.getNames(languageName)) {
      skillName = languageName.getJSONObject(skill_name);
      if (languageName.has(skill_name)) {
        reports = skillName.getJSONArray(“reports”);
           for (int i = 0; i < reports.length(); i++) {
             JSONObject reportObject = new JSONObject();
   reportObject = reports.getJSONObject(i);
   reportObject.put(“skill_name”, skill_name);    reportList.add(reportObject);
                 }
            }
       }
  }

api/cms/GetReportSkillService.java

Once we have the list of reported skills reportList return the service response

try {
   result.put(“list”, reportList);
   result.put(“accepted”, true);
   result.put(“message”, “Success: Fetched all Reported  Skills”);
   return new ServiceResponse(result);
  } catch (Exception e) {
       throw new APIException(500, “Failed to fetch the requested list!”);}

api/cms/GetReportSkillService.java

To conclude, the Admin’s now can take decisions based on reports submitted by the user to delete a skill or ignore the feedback.

Link to PR: https://github.com/fossasia/susi_server/pull/1274

Resources

Tags

SUSI.AI, FOSSASIA, GSoC`19, API Development, SUSI Server, SUSI Skills

Continue Reading

Add PayPal Payment integration in Eventyay attendee application

The eventyay attendee is an android app which allows users to discover events happening around the world using the Open Event Platform. It consumes the APIs of the open event server to get a list of available events and can get detailed information about them.

PayPal is a very common method to pay for anything throughout the world. It is a highly popular platform and it’s only right that there should be an option to pay through PayPal on Eventyay attendee for tickets. This blog will explain how and why I added PayPal payment feature in the application with a sandbox account.

  • Why PayPal?
  • Get API key for a sandbox account
  • Integration with Android Studio
  • Conclusion
  • Resources

Let’s analyze every step in detail.

Advantages of using PayPal Payment integration

  1. Provide UI to gather payment information from the user
  2. Get your credentials, which identify your PayPal account as the payment receiver. Specifically, obtain a client ID and secret.
  3. Returns a proof of payment to your app.
  4. Provides the user their goods or services.

Setup Sandbox account and get the API key

Go to https://developer.paypal.com/ and sign up for a developer account:

After Sign up, go to the dashboard and create an app: 

Now in app credentials go to sandbox accounts. Here you can find your API key.

Now, Create a new sandbox account with entering some amount of money for testing purposes:

PayPal SDK integration in the application

Add PayPal SDK in build.gradle dependencies:

//PayPal
compile ‘com.paypal.sdk:paypal-android-sdk:2.16.0’

Store the API key in the android manifest file:

<meta-data
            android:name=”com.paypal.android.API_KEY”
            android:value=”${PAYPAL_CLIENT_ID}”/>

Get the API key in the fragment where PayPal payment is required:

private lateinit var PAYPAL_API_KEY: String
PAYPAL_API_KEY = activity?.packageManager?.getApplicationInfo(activity?.packageName, PackageManager.GET_META_DATA)
            ?.metaData?.getString(PAYPAL_KEY).toString()

Start PayPal services on create view:

val payPalConfiguration = PayPalConfiguration()
            .environment(PayPalConfiguration.ENVIRONMENT_SANDBOX)
            .clientId(PAYPAL_API_KEY)val intent = Intent(context, PaymentActivity::class.java)intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, payPalConfiguration)activity?.startService(intent)

Now start the Payment conditionally with same intent: 

val payment = PayPalPayment(BigDecimal(amount.toString()), “USD”, “Pay for tickets”, PayPalPayment.PAYMENT_INTENT_SALE)
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment)
startActivityForResult(intent, PAYPAL_REQUEST_CODE)

Handle the result after payment is done:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == PAYPAL_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                val paymentConfirmation = data?.getParcelableExtra<PaymentConfirmation>(PaymentActivity.EXTRA_RESULT_CONFIRMATION)
                if (paymentConfirmation != null) {
                    val paymentInfo = paymentConfirmation.toJSONObject()
                    val tokenId = paymentInfo.getJSONObject(“response”).getString(“id”)
                    Timber.d(paymentInfo.toString(4))
                    // Send the token to server
                    val charge = Charge(attendeeViewModel.getId().toInt(), tokenId, null)
                    attendeeViewModel.completeOrder(charge)
                }
            } else if (resultCode == Activity.RESULT_CANCELED)
                Toast.makeText(context, “Payment canceled!”, Toast.LENGTH_SHORT).show()
            else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID)
                Toast.makeText(context, “Invalid Payment Configuration”, Toast.LENGTH_SHORT).show()
        }
    }

GIF

In a nutshell

With almost 250 million users worldwide, PayPal is an extremely popular platform for monetary transactions and it’s quite essential that every application an option to use it. Given the nature of Eventyay attendee and its pan-world appeal, I have added PayPal as a payment system for tickets to any event.

Resources

  1. PayPal Android SDK guide: PayPal Android SDK
  2. PayPal SDK repo: PayPal-Android-SDK

Tags

PayPal, Android, Payments, FOSSASIA, GSoC, AndroidPayments, Kotlin

Continue Reading

Allow organizers to lock/unlock a session in Open Event Frontend

This blog post will showcase an option which can be used by organizers to lock/unlock a session in Open Event Frontend. Let’s start by understanding what this feature means and why is it important for organizers. If a session is locked by an organizer, it cannot be edited by the session creator. 

Suppose an event organizer wants final session submission by a particular date so that he/she can shortlist the sessions based on final submission, but the user goes on editing the session event after final date of submission. This is a situation where this feature will help the organizer to prohibit the user from further modification of session.

If a session is unlocked, then unlock icon is shown:

Unlocked Session

However, if a session is locked, lock icon is shown:

Locked Session
{{#if record.isLocked}}
  {{#ui-popup content=(t 'Unlock Session') class='ui

basic Button' click=(action unlockSession record)
  position='left center'}}
    <i class="lock icon"></i>   
  {{/ui-popup}}
{{else}}
  {{#ui-popup content=(t 'Lock Session') class='ui basic
  Button' click=(action lockSession record) position='

left center'}}
    <i class="unlock icon"></i>   
  {{/ui-popup}}
{{/if}}

Snippet to toggle locked/unlocked icon

On clicking these icon buttons, corresponding action is triggered which updates the status of is-locked attribute of the session. When an organizer clicks on lock icon button, unlockSession action is triggered which sets is-locked property of session to false. However if unlock icon button is clicked, lockSession action is triggered which sets the is-locked property of session to true.

Snippet to lock a session:

   lockSession(session) {
     session.set('isLocked', true);
     this.set('isLoading', true);
     session.save()
       .then(() => {
         this.notify.success(this.l10n.t('Session has

been locked successfully.'));
         this.send('refreshRoute');
       })
       .catch(() => {
         this.notify.error(this.l10n.t('An unexpected

error has occurred.'));
       })
       .finally(() => {
         this.set('isLoading', false);
       });
   }

Snippet to unlock a session:

  unlockSession(session) {
     session.set('isLocked', false);
     this.set('isLoading', true);
     session.save()
       .then(() => {
         this.notify.success(this.l10n.t('Session has

been unlocked successfully.'));
         this.send('refreshRoute');
       })
       .catch(() => {
         this.notify.error(this.l10n.t('An unexpected

error has occurred.'));
       })
       .finally(() => {
         this.set('isLoading', false);
       });
   }

These changes required few server checks so that only a person with admin or organizer access can update the value of is-locked attribute of session. Also, any try to edit a locked session via API call must be rejected.

Server checks related to locking/unlocking a session:

def before_update_object(self, session, data, view_kwargs):
       """
       before update method to verify if session is

locked before updating
       session object
       :param event:
       :param data:
       :param view_kwargs:
       :return:
       """
       if data.get('is_locked') != session.is_locked:
           if not (has_access('is_admin') or
           has_access('is_organizer')):
               raise ForbiddenException({'source':
                     '/data/attributes/is-locked'}, "You
                     don't have enough permissions to ch

ange this property")

       if session.is_locked and data.get('is_locked') ==
       session.is_locked:
           raise ForbiddenException({'source':
                 '/data/attributes/is-locked'}, "Locked

sessions cannot be edited")

Resources:

Related work and code repo:

Tags:

Eventyay, FOSSASIA, Flask, Ember.js, Open Event

Continue Reading

Omise Integration in Open Event Frontend

This blog post will elaborate on how omise has been integrated into the Open Event Frontend project. Omise is Thailand’s leading online payment gateway offering a wide range of processing solutions for this project and integrating it as a payment option widens the possibilities for user base and ease of payment workflow.

Similar to Paypal, Omise offers two alternatives for using their gateway, Test mode and Live mode, where the former is generally favoured for usage in Development and Testing phase while the latter is used in actual production for capturing live payments. Both these modes require a Public key and Secret key each and are only update-able on the admin route.

This was implemented by introducing appropriate fields in the settings model.

// app/models/setting.js
omiseMode            : attr('string'),
omiseTestPublic      : attr('string'),
omiseTestSecret      : attr('string'),
omiseLivePublic      : attr('string'),
omiseLiveSecret      : attr('string')

Once your Omise credentials are configured, you can go ahead and include the options in your event creation form. You will see an option to include Omise in your payment options if you have configured your keys correctly and if the gateway supports the currency your event is dealing with, for example, even if your keys are correctly configured, you will not get the option to use omise gateway for money collection if the currency is INR.

For showing omise option in the template, a simple computed property did the trick canAcceptOmise  in the form’s component file and the template as follows:

// app/components/forms/wizard/basic-details-step.js
canAcceptOmise: computed('data.event.paymentCurrency', 'settings.isOmiseActivated', function() {
  return this.get('settings.isOmiseActivated') && find(paymentCurrencies, ['code', this.get('data.event.paymentCurrency')]).omise;
})
// app/templates/components/forms/wizard/basic-details-step.js
{{#
if canAcceptOmise}}
      <
label>{{t 'Payment with Omise'}}</label>
      <
div class="field payments">
        <
div class="ui checkbox">
          {{input type='checkbox' id='payment_by_omise' checked=data.event.canPayByOmise}}
          <
label for="payment_by_omise">
            {{t 'Yes, accept payment through Omise Gateway'}}
            <
div class="ui hidden divider"></div>
            <
span class="text muted">
              {{t 'Omise can accept Credit and Debit Cards , Net-Banking and AliPay. Find more details '}}
              <
a href="https://www.omise.co/payment-methods" target="_blank" rel="noopener noreferrer">{{t 'here'}}</a>.
            </
span>
          </
label>
        </
div>
      </
div>
      {{#
if data.event.canPayByOmise}}
        <
label>{{t 'Omise Gateway has been successfully activated'}}</label>
      {{/
if}}
    {{/
if}}

Once the event has the payment option enabled, an attendee has chosen the option to pay up using omise, they will encounter this screen on their pending order page 

On entering the credentials correctly, they will be forwarded to order completion page. On clicking the “Pay” button, the omise cdn used hits the server with a POST request to the order endpoint  and is implemented as follows :

//controllers/orders/pending.js
isOmise: computed('model.order.paymentMode', function() {
  return this.get('model.order.paymentMode') === 'omise';
}),

publicKeyOmise: computed('settings.omiseLivePublic', 'settings.omiseLivePublic', function() {
  return this.get('settings.omiseLivePublic') || this.get('settings.omiseTestPublic');
}),

omiseFormAction: computed('model.order.identifier', function() {
  let identifier = this.get('model.order.identifier');
  return `${ENV.APP.apiHost}/v1/orders/${identifier}/omise-checkout`;
})
// app/templates/orders/pending.hbs
    {{#
if isOmise}}
      <
div>
        <
form class="checkout-form" name="checkoutForm" method='POST' action={{omiseFormAction}}>
          <
script type="text/javascript" src="https://cdn.omise.co/omise.js"
                  data-key="{{publicKeyOmise}}"
                  data-amount="{{paymentAmount}}"
                  data-currency="{{model.order.event.paymentCurrency}}"
                  data-default-payment-method="credit_card">
          </
script>
        </
form>
      </
div>
    {{/
if}}

Thus primarily using Omise.js CDN and introducing the omise workflow, the project now has accessibility to Omise payment gateway service and the organiser can see his successful charge.

Resources

Related Work and Code Repository

Continue Reading

Implementing a Splash Screen, the wiser way

Implementing a Splash Screen, the wiser way

What is a Splash Screen?

A Splash Screen is basically a nice intro-screen that mobile applications have on startup of the app on a device. The splash screen can be customized according to the app’s UX need-animations, sound effects, etc. are some common tweaks to a simple splash screen.

I have been working with FOSSASIA on the Neurolab Android App where we made a splash screen for the same. Our implemented splash screen is below:

                                                     Neurolab Splash Screen

While developing this, we followed Google Material Design guidelines and the pattern it suggests is termed as ‘Launch Screen’. Displaying a launch screen can decrease the sense of long load time, and has the potential to add delight to the user experience. Launch screen implementation is considered as one of the best-practised development skills for a proper splash screen for an app.

Implementation 

Now, it is not a good idea to use a splash screen that wastes a user’s time. This should be strictly avoided. The right way of implementing a splash screen is a little different. In the new approach specify your splash screen’s background as the activity’s theme background. This way, we can effectively and efficiently use the time gap between the startup of the app and the onCreate() method.

In the Neurolab app, we use the splash screen as a bridge for the time gap between the app startup when we click the app icon and the onCreate method of the Neurolab Activity (Main/Launcher Screen) of the app, wherein the various UI components are laid out on the screen and the functionalities, navigations, listeners are linked to those components.

So, here we won’t be creating a new layout for the Splash screen as a separate activity. Rather we would specify the theme of the landing activity as the splash screen.

We create a drawable named splash_screen.xml in our project and give a parent tag of layer-list. Here is the code for our drawable file:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">
    <item android:drawable="@android:color/white" />
    <item>
        <bitmap
            android:gravity="center_horizontal"
            android:src="@drawable/splash_image" />
    </item>
</layer-list>

Next, we are going to create a new theme in the styles resource file. This theme is going to be used as the base theme for the main activity screen of the app. In this style, we specify our created drawable file to the property name windowBackground.

<style name="AppTheme.Launcher">
        <item name="android:windowBackground">@drawable/splash_screen</item>
</style>

Then, update this style in the project manifest file to set the theme of the main activity

android:theme="@style/AppTheme.Launcher"

Having done the steps so far, we create a simple class extending the AppCompatActivity. Note- This may seem like another Activity screen, but it is not. We don’t specify the setContentView() here. Instead of this class just directs to the main/home activity using an Intent. Finally, be sure to finish() the SplashActivity activity (class) to remove prevailing unused/idle activities from back stack.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Start landing activity screen
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}

We are done!!

Launch your app, and observe your Launch screen. I can promise you that your “time won’t be wasted”(pun intended).

Thanks for reading. Hope this adds value to your Android application development skills. 

References:

Tags: FOSSASIA. Neurolab, GSOC19, Open-source, splash-screen, Android

Continue Reading

Integration of AliPay Payment Gateway using Stripe Sources

Image result for alipay logo svg

Integration of AliPay Payment Gateway using Stripe Sources

This blog post explains the process of how Stripe Sources has been leveraged to integrate AliPay to extend the payment options in China.

Stripe provides a plethora of payment options configurable with Sources

Source objects allow you to accept a variety of payment methods with a single API. A source represents a customer’s payment instrument, and can be used with the Stripe API to create payments. Sources can be charged directly, or attached to customers for later reuse.

Alipay is a push-based, single-use and synchronous method of payment. This means that your customer takes action to authorize the push of funds through a redirect. There is immediate confirmation about the success or failure of a payment.

   Workflow of Alipay on the backend

During the payment process, a Source API object is created and your customer is redirected to AliPay for authorization.

Payment Flow

  1. Create a Source Object with the parameters currency, redirect_url and amount.
  2. Create a page for completion of customer authorization by specifying the redirect_url.
  3. Change the source status from pending to chargeable.
  4. Confirm the payment by redirecting to the confirmation page and process the refund for any unsuccessful payments(if deducted)

Configuration Manager

Initially, we define a class named as AliPayPaymentsManager which handles the configuration of API keys and has methods to create source objects and make them chargeable.

class AliPayPaymentsManager(object):
    """
    Class to manage AliPay Payments
    """

    @staticmethod
    def create_source(amount, currency, redirect_return_uri):
        stripe.api_key = get_settings()['alipay_publishable_key']
        response = stripe.Source.create(type='alipay',
                                        currency=currency,
                                        amount=amount,
                                        redirect={
                                            'return_url': redirect_return_uri
                                        }
                                        )
        return response

    @staticmethod
    def charge_source(order_identifier):
        order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
        stripe.api_key = get_settings()['alipay_secret_key']
        charge = stripe.Charge.create(
                 amount=int(order.amount),
                 currency=order.event.payment_currency,
                 source=order.order_notes,
                 )
        return charge

                Methods to create & charge the source

The challenge of charging the source & redirection

After creating the source object, we need to make the source object chargeable. For this purpose, the user must be redirected to the external AliPay payment gateway page where the source object is authorized and its status is changed to chargeable. The main challenge to overcome here was the method in which the redirect link was attached to the object. The parameter _external is really crucial for this process as Flask would only recognize the url as an external url if this parameter is passed to url_for.

@alipay_blueprint.route('/create_source/<string:order_identifier>', methods=['GET', 'POST'])
def create_source(order_identifier):
    """
    Create a source object for alipay payments.
    :param order_identifier:
    :return: The alipay redirection link.
    """
    try:
        order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
        source_object = AliPayPaymentsManager.create_source(amount=int(order.amount), currency='usd',
                                                            redirect_return_uri=url_for('alipay_blueprint.alipay_return_uri',
                                                            order_identifier=order.identifier, _external=True))
        order.order_notes = source_object.id
        save_to_db(order)
        return jsonify(link=source_object.redirect['url'])
    except TypeError:
        return BadRequestError({'source': ''}, 'Source creation error').respond()

Route which creates the source and returns external redirection url

After the source object is created, the status changes to pending. To charge the user, the source object must become chargeable. For this, we need to redirect the user to an external page where the payment can be authorized and the source object can become chargeable.

External Authorization Page for AliPay

After authorizing the payment, we redirect to the url given in return_redirect_uri which is configured with the source object which tries to charge the source object as it is now chargeable. After this, a POST request is sent to the return_redirect_uri route which handles success and failure cases

@alipay_blueprint.route('/alipay_return_uri/', methods=['GET', 'POST'])
def alipay_return_uri(order_identifier):
    """
    Charge Object creation & Order finalization for Alipay payments.
    :param order_identifier:
    :return: JSON response of the payment status.
    """
    try:
        charge_response = AliPayPaymentsManager.charge_source(order_identifier)
        if charge_response.status == 'succeeded':
            order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
            order.status = 'completed'
            save_to_db(order)
            return redirect(make_frontend_url('/orders/{}/view'.format(order_identifier)))
        else:
            return jsonify(status=False, error='Charge object failure')
    except TypeError:
        return jsonify(status=False, error='Source object status error')

After AliPay authorization, the order is saved and payment is completed

Resources:

Related work and code repo:

Tags:

Eventyay, FOSSASIA, Flask, Ember.js, Open Event, Python, AliPay, Stripe

Continue Reading

UNESCO Hackathon at FOSSASIA Summit 2019

As part of the celebration of the International Year of Indigenous Languages, the UNESCO and FOSSASIA once again joined hands in organizing a hackathon titled “Hack the Future”, aiming to preserve indigenous languages through free and open source software. The event took place from Mar 15 to Mar 17, during the FOSSASIA Summit 2019 at Lifelong Learning Institute, Singapore. The competition recorded a number of 193 registered participants from across Asia and neighboring regions. 15 projected ideas were submitted and 13 of them were pitched for 5 winning prizes.

The winning projects

For the expected outcome of the hack, the applications or games shall help to provide greater access to multilingual information and knowledge and enable knowledge-sharing and dissemination of good practices, specifically with regard to indigenous languages. All work shall be FOSS/Open Source and use or connect to FOSSASIA projects (APIs) and technologies to improve people’s lives and tackle indigenous languages and culture protection challenges.

The teams that met requirements and produced convincing solutions were:

  • Open Science Prize: Gadon
  • AI Dev Prize: Crowd-sourced Corpus Generation
  • Cloud Prize: Guageland
  • Indigenous Prize: Thazin
  • Audience Prize: Crowd-sourced Corpus Generation

Crowd Sourced Corpus Generation: the 5-member Indian hack team has built a crowd-sourced corpus generator that provides reliable crowd translations using AI matrix. The app contains of 2 major parts: (1) users’ translations input and (2) a platform where researchers and/or indigenous language experts can verify and give feedback on crowd translations.

Crowd-sourced Corpus Generation project team

Thazin is a mobile game project whose inspirations derived from flappy bird and Google Chrome’s “not connected” dinosaur game. In this game, a player needs to use particular indigenous languages to speak into the built-in microphone in order to get the bird to overcome obstacles of each level. The dataset is also generated from indigenous people themselves when they record their voices for players’ references.

Thazin project team

Gadong is another mobile game application designed to tackle the inadequacy of online resources for indigenous languages by providing a crowd-source dictionary for Khmu language. Gadon project not only aims to promote Khmu language to the public but also helps the Khmu people to learn English as a global language.

Gadong project team

GuageLand game application allows players to level up by learning and solving problems related to indigenous languages. The project is fully open source featuring technologies such as: SUSI.AI, react.js, node.js, Amazon-DynamoDB, html5, css3, javascript, NoSQL Database, PWA, and open data.

GuageLand project team

Participants, mentors and judges

The UNESCO Hackathon at FOSSASIA Summit 2019 received the participation of 193 candidates from 21 countries all over the world. Indians accounted for the largest number of participants (82), followed by Indians (62). And more than 20% of the participants were females.

Mentors

Seventeen open source advocates from Singapore, India, Vietnam, Sri Lanka, Germany, and indigenous experts from the Mekong region were invited to become mentors of the two-day hackathon. Mentors dedicatedly worked alongside with participants, giving them constructive feedback on the groups’ projects as well as showing them how to turn their ideas into feasible mobile app solutions. Some indigenous experts also joined the hacking projects as participants resulted in great diverse backgrounds of team members for each team.

Judges

The Hackathon jury consisted of UNESCO delegates, indegious languages experts and representatives from FOSSASIA, Microsoft, IBM, SUSI.AI and OpnTech. Some members from the jury board were mentors themselves. Thus, they not only provided support, made final evaluations on submitted projects but also encouraged participants to carry on their research after the  completion so that they can implement the applications into real life situations to empower the indeginous languages and culture through FOSS.

Conclusion

The event was another great achievement for both partners based on the quality of projects’ outcomes and the awareness of the concepts raised before, during and after the competition. With the support from UNESCO nominated indigenous experts, the young developers successfully developed innovative open source applications that support the dissemination of good practices with regard to indigenous languages and increase access to multilingual information and knowledge by leveraging open data and knowledge-sharing.

Links

Hackathon sessions at FOSSASIA Summit 2019: https://youtu.be/J53lT5IhkjY

FOSSASIA Summit 2019 Photos: https://photos.app.goo.gl/zrJnma6s1a1xPCu89

FOSSASIA on Twitter: https://twitter.com/fossasia

FOSSASIA Videos: https://www.youtube.com/fossasiaorg

FOSSASIA Calendar: https://calendar.fossasia.org



Continue Reading

Open is Becoming the New Common Foundation across Business, Government, Science, and Industry

Interview with Shanker V Selvadurai, Vice President & Chief Technology Officer of Cloud and Cognitive Software for IBM Asia Pacific

Could you briefly introduce yourself?

I am Shanker Selvadurai and currently the Vice President & Chief Technology Officer of Cloud and Cognitive Software for IBM Asia Pacific. I am based in Singapore and lead the technical organization that helps clients across Asia Pacific to explore and co-create cloud-based solutions that leverage data, analytics and artificial intelligence (AI) capabilities to deliver better decisions and outcomes.

I joined IBM in 2006.  Prior to IBM, I held key leadership positions in areas of research, development, consulting, sales and marketing with technology companies like AT&T, NCR and Fujitsu as well as start-up BlueGill Technologies. During this period I lead teams varying in size from 6 to over 1,000 while being based in North America, Europe and Asia.

I have a Bachelor of Science degree and a Master of Business Administration. I am also an Open Group Certified Distinguished Architect. Besides having published international patents/papers, I have actively contributed to international technology standards committees that include the IFX Forum, OFX Consortium and the Microsoft Advisory Council. I was also an adjunct lecturer at the Singapore Management University, teaching courses related to Services Science and Advanced Business Technology.

Tell us about your session at the FOSSASIA Summit, what will you cover?

At the FOSSASIA Summit, I am participating in a panel on “Business, Government, Science – What Opportunities Does “Open” Bring to Society”.  I hope to share IBM’s involvement in the open source movement, how businesses like IBM benefit from open source, as well as share thoughts about approaching open contribution and open governance in the future.

Shanker V Selvadurai handing over IBM Cloud Prize for Hackathon Winners

Business, Government, Science – What Opportunities Does “Open” Bring to Society from your point of view?

Open is becoming the new common foundation across business, government, science, and industry today.  For example, companies that still compete head-to-head in the marketplace are coming together to collaborate in open source communities.  They contribute to open source software and use it in their own IT systems and applications. They gain a competitive advantage — even though they may be helping their competitors in the short run.  The data demonstrates that companies with open source programs see more benefits from open source code and community participation.

IBM Connecting with Open Source Community at FOSSASIA Summit
International IBM Team Participating in FOSSASIA Summit

What is the role of Free Open Source Software in cloud and AI solutions in IBM?

Our offering portfolio, especially for our growth initiatives such as cloud and AI, is based on a solid foundation of open technologies.  Most of our strategic initiatives are founded on open source projects or communities, and we work across a wide variety of internal stakeholders to ensure that that the contributions we make to the community also provide greater value to our clients.

IBM Training on Open Source Cloud and AI Technologies at FOSSASIA OpenTechSummit
Many Open Source Developers Connect with IBM At the Booth

What was your motivation to work for IBM and to participate in the FOSSASIA Summit?

IBM has a long history as a leader in, and supporter of open source communities, most notably in the Apache, Linux, and Eclipse Foundations.  I joined IBM to help continue this tradition and I am looking forward to discussing new ideas to help build the future of open source at FOSSASIA Summit.

Which FOSS projects in the area of cloud and AI can interested developers contribute in IBM? In which domains could you use some help?

IBM believes that communities with open governance and an inclusive philosophy will attract the largest ecosystems and markets.  For a listing of some of the top open source projects that IBM believes represent significant opportunity areas, I would like to share with information how IBM supports high-impact open source projects here.

Participants from Around the World Following IBM Keynote on FOSS Collaboration

Which new features can we expect in IBM cloud and AI this year? Do you plan to release any new projects as FOSS?

Most of our strategic initiatives today are founded on open source projects or communities (Cloud Native Computing, Hyperledger, CD Foundation, etc.), and we work across a wide variety of internal stakeholders to ensure that that the contributions we make to the community also provide greater value to our clients. For a specific example of open source innovation from IBM, please check out the Egeria Project, which was founded in part by IBM.

Shanker V Selvadurai with Panelists and FOSSASIA Founder Ms. Hong Phuc Dang at the Singapore Summit 2019

As well, at the FOSSASIA Summit in Singapore, IBM shares the “Call for Code Global Challenge, which IBM is the Founding Partner.  

This multi-year global initiative rallies developers to create practical, effective, and high-quality applications based on cloud, data, and artificial intelligence that can have an immediate and lasting impact on humanitarian issues.  Call for Code brings startup, academic, and enterprise developers together and inspires them to solve the most pressing societal issues of our time. Building on the success of the 2018 competition, the 2019 Call for Code Global Challenge again asks developers to create solutions that significantly improve preparedness for natural disasters and accelerate relief when they hit. This year’s challenge introduces an emphasis on individual health and community wellbeing. This includes solutions that can reduce the risk of disease, improve access to data and the availability of resources, and address the mental health needs of those impacted before, during, and after disasters.

Hands-on Training with IBM Cloud and AI Experts at FOSSASIA Summit
Hands-on Training with IBM Cloud and AI Experts at FOSSASIA Summit
Continue Reading

10 Years FOSSASIA Anniversary OpenTechSummit 2019 Taking Place in Singapore

We are thrilled to update you with the amazing line-up at the 10 Years Anniversary Summit. The event is co-organized by the Lifelong Learning Institute and SkillsFuture under the theme “The Future is FOSS”.

Highlights of the FOSSASIA Anniversary Summit 2019 include:

  • Thu Mar 14 12:30 – Sun Mar 17 16:00 Exhibition: Showcases and job opportunities with tech companies and FOSS projects: Overview
  • Fri Mar 15 9:00 Cloud and AI Workshops: Join us for two intensive workshops with IBM experts from around the world on the latest technologies, development and deployment covering ‘Cloud, Containers and DevOps’ and developing ‘Machine Learning and Artificial Intelligence’ applications at the FOSSASIA Summit. Seats are limited. Sign up here.
  • Fri March 15 16:30 SUSI.AI – Create Skills for Your AI Solution: Sign up
  • Fri Mar 15 / Sat Mar 16 19:00 FOSSASIA Academy: Learn new tech skills in free introductory level technology workshops conducted with BuildingBloCS Computing students from Singapore. Topics include Introduction to Python, ML with Python, SQLite, MongoDB,  Vue.js, SUSI.AI Sign up to reserve.
  • Fri Mar 15 – Sun Mar 17 OpenTech Hackathon with UNESCO: Build open source apps and win prizes. Join Friday or Saturday.
  • Sat Mar 16 12:00 Capture the Community: Singapore Open Source Picture Taking and Birthday Cake. Join us
  • Sat Mar 16 13:30 Azure Kubernetes Service (AKS): Learn how to setup Kubernetes on Azure. Sign up here.
  • 12 Conference Tracks: Join talks by industry experts from IBM, Google, Oracle, Microsoft, Flowchain, Red Hat, Alibaba, Sysdig, Pivotal, Elastic, Codethink, Gitcoin and open source projects like VLC, Linux, CentOS, SELinux, Debian, Kubernetes, Lionsforge, Tensorflow, PostgreSQL, MySQL, FreeBSD, ReactJS, the Blockchain community as well as hardware experts from the Raspberry Pi Foundation, ARM, Bunnie Huang from Chibitronics, Mitch Altman and many more. We will be covering Conference Tracks such as AI, Blockchain and Cybersecurity: Schedule
  • Daily: Social Events: Pub crawls and city tours along with other techies from around the world! Sign up.

Meet companies, FOSS projects and communities and do hands-on workshops in the Exhibition:

  • Participate in workshops like doing experiments with Pocket Science Lab or Learn Soldering with Mitch Altman (Thu Mar 14 14:00, Fri Mar 15 14:00, Sat Mar 16, 14:00)
  • Get together with community developers and reps from Fosdem, CCC, Openfest, Linux Foundation, OSI and many companies and projects in the Hackers Lounge on Floor 1.
  • Exhibition Booths and Job Board: See showcases and find out about job opportunities from industry-leading companies and sponsors like IBM, UNESCO, Google, Indeed, Microsoft, Facebook, Flowchain, MySQL/Oracle, Singapore companies like Singapore Press Holdings and more: Overview 

Don’t miss out on our Social Events:

  • Sat Mar 16 19:00 10 Years FOSSASIA Party with Buffet, Live Music, Indian Dance, Chinese Performance & Cultural Program** : Celebrate FOSSASIA 10th Anniversary Party with us! Featuring Live Music, Cultural Highlights and Good Food! Indian dance, magic, music, Karaoke and so much more! (Social Event Tickets Required) : Tickets 
  • Wed Mar 13 15:00 FOSSASIA Meet & Greet: Join the FOSSASIA Speakers and Attendees Meet & Greet, meet the local tech scene, explore Singapore in a Culture and Exploration Wednesday Afternoon, and enjoy the taste of Asia at a local dinner: Attendance
  • Thu Mar 14 19:00 Welcome Dinner: With FOSSASIA Summit Speakers and Exhibitors: Attendence
  • Fri Mar 15 7:00 Cultural Morning Tour to Merlion Statue and View of Marina Bay: Attendence
  • Fri Mar 15 19:00 Chinatown & Clarke Quay Snacks and Pub Crawl: Network with speakers and participants of the FOSSASIA OpenTech Summit for a Chinatown and Clarke Quay Snacks an Pub Crawl on Friday Evening: Attendance
  • Sun Mar 17 20:30 Dim Sum and Midnight Hacks: Didn’t get enough of techie stuff? Want to work on this awesome project you found at FOSSASIA? Met some amazing developers at the weekend? Join us for the FOSSASIA After-Event hacking, coding, relaxing at Hackerspace.sg on Sunday evening: Attendance
  • Mon Mar 18 12:00 Community Lunch: Gather with us on Monday Noon for yummy local Singapore food: Attendance

FOSSASIA Summit – Schedule Roster


Featured Speakers and Sessions

We have more than 180 speakers and close to 200 sessions where participants can learn how to work with Cloud solutions, train their personal AI, create voice interfaces, build their own Operating Systems, create AR and VR apps for the web, learn about databases or prepare for Linux certification. Find out more about the speakers.


FOSSASIA Summit Theme: The Future is FOSS

Today we see that Free and Open Source is mainstream. The large online providers are offereing their services mainly based on FOSS solutions. FOSSASIA is part of a movement advancing FOSS to the next level developing not just software, but also Open Hardware like the Pocket Science Lab. The FOSS model provides us with a way to collaborate easily, freely and efficiently and it can help us to solve the problems of this planet together. Let’s do it at the FOSSASIA OpenTechSummit! The theme of the event is “The Future is FOSS”.


Thank you for sponsoring!

Thank you to our sponsors IBM, Google Open Source, Microsoft, Indeed.com, Flowchain, Facebook, MySQL/Oracle, SPH and partners for supporting the event!


Thank you for celebrating FOSSASIA’s 10th Anniversary with us.

Do follow us on our Social Media accounts to get the latest updates on the Summit and other Open Tech stuff.

We can’t wait to see you to share and gain techie knowledge with and from you!

Continue Reading

Reducing the YouTube response time by 90%

In this blog post, we are going to cover how the audio from Youtube is being used in SUSI Smart Speaker and how we reduced the response time from ~40 seconds to ~4 seconds for an average music video length.

First Approach

Earlier, we were using MPV player’s inbuilt feature to fetch the YouTube music. However, MPV player was a bulky option and the music server had to be started every time before initiating a music video.

video_process = subprocess.Popen([‘mpv’, ‘–no-video’, ‘https://www.youtube.com/watch?v=’ + video_url[4:], ‘–really-quiet’]) # nosec #pylint-disable type: ignore requests.get(‘http://localhost:7070/song/’ + video_url) self.video_process = video_process stopAction.run() stopAction.detector.terminate()

Making it Efficient

To reduce the response time, we created a custom Music Server based on Flask,python-vlc and python-pafy which accepts requests from the main client and instructs the System to play the music with just 90% more efficiency.

app = Flask(__name__)

Instance = vlc.Instance(‘–no-video’)

player = Instance.media_player_new()

url = @app.route(‘/song’, methods=[‘GET’])

def youtube():

    vid = request.args.get(‘vid’)

    url = ‘https://www.youtube.com/watch?v=’ + vid

    video = pafy.new(url)
    streams = video.audiostreams 

    best = streams[3]

    playurl = best.url

    Media = Instance.media_new(playurl)

    Media.get_mrl()

    player.set_media(Media)

    player.play()

    display_message = {“song”:“started”}

    resp = jsonify(display_message)

    resp.status_code = 200

    return resp

However, shifting to this Server removed the ability to process multiple queries and hence we were unable to pause/play/stop the music until it completed the time duration. We wanted to retain the ability to have ‘play/pause/stop’ actions without implementing multiprocessing or multithreading as it would’ve required extensive testing to successfully implement them without creating deadlocks and would’ve been overkill for a simple feature.

Bringing Back the Lost Functionalities

The first Step we took was to remove the vlc-python module and implement a way to obtain an URL that we use in another asynchronous music player.

@app.route(‘/song’, methods=[‘GET’])
def youtube():

    vid = request.args.get(‘vid’)

    streams = video.audiostreams

    best = streams[3]

    playurl = best.url 

    display_message = {“song”: “started”, “url”: playurl}

    resp = jsonify(display_message)

    resp.status_code = 200

    return resp

The next issue was to actually find a way to run the Music Player asynchronously. We used the `subprocess. Popen` method and cvlc to play the songs asynchronously.

try:

    x = requests.get(‘http://localhost:7070/song?vid=’ + video_url[4:])

    data = x.json()

    url = data[‘url’]

    video_process = subprocess.Popen([‘cvlc’, ‘http’ + url[5:], ‘–no-video’])

    self.video_process = video_process

except Exception as e:

    logger.error(e);

And this is how we were able to increase the efficiency of the music player while maintaining the functionalities.

References

Continue Reading
Close Menu